summaryrefslogtreecommitdiffstats
path: root/contrib/llvm/tools/clang/include
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/llvm/tools/clang/include')
-rw-r--r--contrib/llvm/tools/clang/include/clang-c/BuildSystem.h156
-rw-r--r--contrib/llvm/tools/clang/include/clang-c/CXCompilationDatabase.h176
-rw-r--r--contrib/llvm/tools/clang/include/clang-c/CXErrorCode.h64
-rw-r--r--contrib/llvm/tools/clang/include/clang-c/CXString.h71
-rw-r--r--contrib/llvm/tools/clang/include/clang-c/Documentation.h554
-rw-r--r--contrib/llvm/tools/clang/include/clang-c/Index.h5835
-rw-r--r--contrib/llvm/tools/clang/include/clang-c/Platform.h45
-rw-r--r--contrib/llvm/tools/clang/include/clang-c/module.modulemap4
-rw-r--r--contrib/llvm/tools/clang/include/clang/ARCMigrate/ARCMT.h131
-rw-r--r--contrib/llvm/tools/clang/include/clang/ARCMigrate/ARCMTActions.h76
-rw-r--r--contrib/llvm/tools/clang/include/clang/ARCMigrate/FileRemapper.h77
-rw-r--r--contrib/llvm/tools/clang/include/clang/AST/APValue.h452
-rw-r--r--contrib/llvm/tools/clang/include/clang/AST/AST.h28
-rw-r--r--contrib/llvm/tools/clang/include/clang/AST/ASTConsumer.h159
-rw-r--r--contrib/llvm/tools/clang/include/clang/AST/ASTContext.h2672
-rw-r--r--contrib/llvm/tools/clang/include/clang/AST/ASTDiagnostic.h47
-rw-r--r--contrib/llvm/tools/clang/include/clang/AST/ASTFwd.h33
-rw-r--r--contrib/llvm/tools/clang/include/clang/AST/ASTImporter.h295
-rw-r--r--contrib/llvm/tools/clang/include/clang/AST/ASTLambda.h80
-rw-r--r--contrib/llvm/tools/clang/include/clang/AST/ASTMutationListener.h127
-rw-r--r--contrib/llvm/tools/clang/include/clang/AST/ASTTypeTraits.h509
-rw-r--r--contrib/llvm/tools/clang/include/clang/AST/ASTUnresolvedSet.h110
-rw-r--r--contrib/llvm/tools/clang/include/clang/AST/ASTVector.h405
-rw-r--r--contrib/llvm/tools/clang/include/clang/AST/Attr.h169
-rw-r--r--contrib/llvm/tools/clang/include/clang/AST/AttrIterator.h142
-rw-r--r--contrib/llvm/tools/clang/include/clang/AST/BaseSubobject.h87
-rw-r--r--contrib/llvm/tools/clang/include/clang/AST/BuiltinTypes.def261
-rw-r--r--contrib/llvm/tools/clang/include/clang/AST/CXXInheritance.h365
-rw-r--r--contrib/llvm/tools/clang/include/clang/AST/CanonicalType.h665
-rw-r--r--contrib/llvm/tools/clang/include/clang/AST/CharUnits.h240
-rw-r--r--contrib/llvm/tools/clang/include/clang/AST/Comment.h1142
-rw-r--r--contrib/llvm/tools/clang/include/clang/AST/CommentBriefParser.h55
-rw-r--r--contrib/llvm/tools/clang/include/clang/AST/CommentCommandTraits.h189
-rw-r--r--contrib/llvm/tools/clang/include/clang/AST/CommentCommands.td241
-rw-r--r--contrib/llvm/tools/clang/include/clang/AST/CommentDiagnostic.h29
-rw-r--r--contrib/llvm/tools/clang/include/clang/AST/CommentHTMLNamedCharacterReferences.td177
-rw-r--r--contrib/llvm/tools/clang/include/clang/AST/CommentHTMLTags.td67
-rw-r--r--contrib/llvm/tools/clang/include/clang/AST/CommentLexer.h362
-rw-r--r--contrib/llvm/tools/clang/include/clang/AST/CommentParser.h123
-rw-r--r--contrib/llvm/tools/clang/include/clang/AST/CommentSema.h254
-rw-r--r--contrib/llvm/tools/clang/include/clang/AST/CommentVisitor.h70
-rw-r--r--contrib/llvm/tools/clang/include/clang/AST/Decl.h3801
-rw-r--r--contrib/llvm/tools/clang/include/clang/AST/DeclAccessPair.h72
-rw-r--r--contrib/llvm/tools/clang/include/clang/AST/DeclBase.h1904
-rw-r--r--contrib/llvm/tools/clang/include/clang/AST/DeclCXX.h3249
-rw-r--r--contrib/llvm/tools/clang/include/clang/AST/DeclContextInternals.h264
-rw-r--r--contrib/llvm/tools/clang/include/clang/AST/DeclFriend.h243
-rw-r--r--contrib/llvm/tools/clang/include/clang/AST/DeclGroup.h154
-rw-r--r--contrib/llvm/tools/clang/include/clang/AST/DeclLookups.h115
-rw-r--r--contrib/llvm/tools/clang/include/clang/AST/DeclObjC.h2742
-rw-r--r--contrib/llvm/tools/clang/include/clang/AST/DeclOpenMP.h91
-rw-r--r--contrib/llvm/tools/clang/include/clang/AST/DeclTemplate.h2927
-rw-r--r--contrib/llvm/tools/clang/include/clang/AST/DeclVisitor.h79
-rw-r--r--contrib/llvm/tools/clang/include/clang/AST/DeclarationName.h598
-rw-r--r--contrib/llvm/tools/clang/include/clang/AST/DependentDiagnostic.h189
-rw-r--r--contrib/llvm/tools/clang/include/clang/AST/EvaluatedExprVisitor.h129
-rw-r--r--contrib/llvm/tools/clang/include/clang/AST/Expr.h4941
-rw-r--r--contrib/llvm/tools/clang/include/clang/AST/ExprCXX.h4179
-rw-r--r--contrib/llvm/tools/clang/include/clang/AST/ExprObjC.h1568
-rw-r--r--contrib/llvm/tools/clang/include/clang/AST/ExprOpenMP.h129
-rw-r--r--contrib/llvm/tools/clang/include/clang/AST/ExternalASTSource.h578
-rw-r--r--contrib/llvm/tools/clang/include/clang/AST/GlobalDecl.h125
-rw-r--r--contrib/llvm/tools/clang/include/clang/AST/LambdaCapture.h128
-rw-r--r--contrib/llvm/tools/clang/include/clang/AST/Mangle.h243
-rw-r--r--contrib/llvm/tools/clang/include/clang/AST/MangleNumberingContext.h60
-rw-r--r--contrib/llvm/tools/clang/include/clang/AST/NSAPI.h262
-rw-r--r--contrib/llvm/tools/clang/include/clang/AST/NestedNameSpecifier.h516
-rw-r--r--contrib/llvm/tools/clang/include/clang/AST/OpenMPClause.h3198
-rw-r--r--contrib/llvm/tools/clang/include/clang/AST/OperationKinds.h356
-rw-r--r--contrib/llvm/tools/clang/include/clang/AST/ParentMap.h67
-rw-r--r--contrib/llvm/tools/clang/include/clang/AST/PrettyPrinter.h175
-rw-r--r--contrib/llvm/tools/clang/include/clang/AST/RawCommentList.h203
-rw-r--r--contrib/llvm/tools/clang/include/clang/AST/RecordLayout.h315
-rw-r--r--contrib/llvm/tools/clang/include/clang/AST/RecursiveASTVisitor.h2805
-rw-r--r--contrib/llvm/tools/clang/include/clang/AST/Redeclarable.h285
-rw-r--r--contrib/llvm/tools/clang/include/clang/AST/SelectorLocationsKind.h83
-rw-r--r--contrib/llvm/tools/clang/include/clang/AST/Stmt.h2196
-rw-r--r--contrib/llvm/tools/clang/include/clang/AST/StmtCXX.h417
-rw-r--r--contrib/llvm/tools/clang/include/clang/AST/StmtGraphTraits.h83
-rw-r--r--contrib/llvm/tools/clang/include/clang/AST/StmtIterator.h144
-rw-r--r--contrib/llvm/tools/clang/include/clang/AST/StmtObjC.h375
-rw-r--r--contrib/llvm/tools/clang/include/clang/AST/StmtOpenMP.h2422
-rw-r--r--contrib/llvm/tools/clang/include/clang/AST/StmtVisitor.h227
-rw-r--r--contrib/llvm/tools/clang/include/clang/AST/TemplateBase.h661
-rw-r--r--contrib/llvm/tools/clang/include/clang/AST/TemplateName.h533
-rw-r--r--contrib/llvm/tools/clang/include/clang/AST/Type.h5683
-rw-r--r--contrib/llvm/tools/clang/include/clang/AST/TypeLoc.h2039
-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.def129
-rw-r--r--contrib/llvm/tools/clang/include/clang/AST/TypeOrdering.h79
-rw-r--r--contrib/llvm/tools/clang/include/clang/AST/TypeVisitor.h95
-rw-r--r--contrib/llvm/tools/clang/include/clang/AST/UnresolvedSet.h140
-rw-r--r--contrib/llvm/tools/clang/include/clang/AST/VTTBuilder.h162
-rw-r--r--contrib/llvm/tools/clang/include/clang/AST/VTableBuilder.h566
-rw-r--r--contrib/llvm/tools/clang/include/clang/ASTMatchers/ASTMatchFinder.h294
-rw-r--r--contrib/llvm/tools/clang/include/clang/ASTMatchers/ASTMatchers.h4671
-rw-r--r--contrib/llvm/tools/clang/include/clang/ASTMatchers/ASTMatchersInternal.h1591
-rw-r--r--contrib/llvm/tools/clang/include/clang/ASTMatchers/ASTMatchersMacros.h404
-rw-r--r--contrib/llvm/tools/clang/include/clang/ASTMatchers/Dynamic/Diagnostics.h185
-rw-r--r--contrib/llvm/tools/clang/include/clang/ASTMatchers/Dynamic/Parser.h257
-rw-r--r--contrib/llvm/tools/clang/include/clang/ASTMatchers/Dynamic/Registry.h133
-rw-r--r--contrib/llvm/tools/clang/include/clang/ASTMatchers/Dynamic/VariantValue.h326
-rw-r--r--contrib/llvm/tools/clang/include/clang/Analysis/Analyses/CFGReachabilityAnalysis.h49
-rw-r--r--contrib/llvm/tools/clang/include/clang/Analysis/Analyses/Consumed.h269
-rw-r--r--contrib/llvm/tools/clang/include/clang/Analysis/Analyses/Dominators.h210
-rw-r--r--contrib/llvm/tools/clang/include/clang/Analysis/Analyses/FormatString.h679
-rw-r--r--contrib/llvm/tools/clang/include/clang/Analysis/Analyses/LiveVariables.h117
-rw-r--r--contrib/llvm/tools/clang/include/clang/Analysis/Analyses/PostOrderCFGView.h115
-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.h69
-rw-r--r--contrib/llvm/tools/clang/include/clang/Analysis/Analyses/ThreadSafety.h226
-rw-r--r--contrib/llvm/tools/clang/include/clang/Analysis/Analyses/ThreadSafetyCommon.h505
-rw-r--r--contrib/llvm/tools/clang/include/clang/Analysis/Analyses/ThreadSafetyLogical.h108
-rw-r--r--contrib/llvm/tools/clang/include/clang/Analysis/Analyses/ThreadSafetyOps.def57
-rw-r--r--contrib/llvm/tools/clang/include/clang/Analysis/Analyses/ThreadSafetyTIL.h1918
-rw-r--r--contrib/llvm/tools/clang/include/clang/Analysis/Analyses/ThreadSafetyTraverse.h902
-rw-r--r--contrib/llvm/tools/clang/include/clang/Analysis/Analyses/ThreadSafetyUtil.h358
-rw-r--r--contrib/llvm/tools/clang/include/clang/Analysis/Analyses/UninitializedValues.h126
-rw-r--r--contrib/llvm/tools/clang/include/clang/Analysis/AnalysisContext.h480
-rw-r--r--contrib/llvm/tools/clang/include/clang/Analysis/AnalysisDiagnostic.h28
-rw-r--r--contrib/llvm/tools/clang/include/clang/Analysis/CFG.h1113
-rw-r--r--contrib/llvm/tools/clang/include/clang/Analysis/CFGStmtMap.h52
-rw-r--r--contrib/llvm/tools/clang/include/clang/Analysis/CallGraph.h253
-rw-r--r--contrib/llvm/tools/clang/include/clang/Analysis/CodeInjector.h46
-rw-r--r--contrib/llvm/tools/clang/include/clang/Analysis/DomainSpecific/CocoaConventions.h42
-rw-r--r--contrib/llvm/tools/clang/include/clang/Analysis/DomainSpecific/ObjCNoReturn.h46
-rw-r--r--contrib/llvm/tools/clang/include/clang/Analysis/FlowSensitive/DataflowValues.h172
-rw-r--r--contrib/llvm/tools/clang/include/clang/Analysis/ProgramPoint.h704
-rw-r--r--contrib/llvm/tools/clang/include/clang/Analysis/Support/BumpVector.h250
-rw-r--r--contrib/llvm/tools/clang/include/clang/Basic/ABI.h211
-rw-r--r--contrib/llvm/tools/clang/include/clang/Basic/AddressSpaces.h51
-rw-r--r--contrib/llvm/tools/clang/include/clang/Basic/AllDiagnostics.h40
-rw-r--r--contrib/llvm/tools/clang/include/clang/Basic/Attr.td2172
-rw-r--r--contrib/llvm/tools/clang/include/clang/Basic/AttrDocs.td1861
-rw-r--r--contrib/llvm/tools/clang/include/clang/Basic/AttrKinds.h34
-rw-r--r--contrib/llvm/tools/clang/include/clang/Basic/Attributes.h39
-rw-r--r--contrib/llvm/tools/clang/include/clang/Basic/Builtins.def1257
-rw-r--r--contrib/llvm/tools/clang/include/clang/Basic/Builtins.h220
-rw-r--r--contrib/llvm/tools/clang/include/clang/Basic/BuiltinsAArch64.def65
-rw-r--r--contrib/llvm/tools/clang/include/clang/Basic/BuiltinsAMDGPU.def36
-rw-r--r--contrib/llvm/tools/clang/include/clang/Basic/BuiltinsARM.def114
-rw-r--r--contrib/llvm/tools/clang/include/clang/Basic/BuiltinsHexagon.def878
-rw-r--r--contrib/llvm/tools/clang/include/clang/Basic/BuiltinsLe64.def19
-rw-r--r--contrib/llvm/tools/clang/include/clang/Basic/BuiltinsMips.def900
-rw-r--r--contrib/llvm/tools/clang/include/clang/Basic/BuiltinsNEON.def21
-rw-r--r--contrib/llvm/tools/clang/include/clang/Basic/BuiltinsNVPTX.def569
-rw-r--r--contrib/llvm/tools/clang/include/clang/Basic/BuiltinsPPC.def379
-rw-r--r--contrib/llvm/tools/clang/include/clang/Basic/BuiltinsSystemZ.def252
-rw-r--r--contrib/llvm/tools/clang/include/clang/Basic/BuiltinsWebAssembly.def24
-rw-r--r--contrib/llvm/tools/clang/include/clang/Basic/BuiltinsX86.def1577
-rw-r--r--contrib/llvm/tools/clang/include/clang/Basic/BuiltinsXCore.def22
-rw-r--r--contrib/llvm/tools/clang/include/clang/Basic/CapturedStmt.h24
-rw-r--r--contrib/llvm/tools/clang/include/clang/Basic/CharInfo.h198
-rw-r--r--contrib/llvm/tools/clang/include/clang/Basic/CommentNodes.td27
-rw-r--r--contrib/llvm/tools/clang/include/clang/Basic/CommentOptions.h39
-rw-r--r--contrib/llvm/tools/clang/include/clang/Basic/DeclNodes.td88
-rw-r--r--contrib/llvm/tools/clang/include/clang/Basic/Diagnostic.h1414
-rw-r--r--contrib/llvm/tools/clang/include/clang/Basic/Diagnostic.td127
-rw-r--r--contrib/llvm/tools/clang/include/clang/Basic/DiagnosticASTKinds.td266
-rw-r--r--contrib/llvm/tools/clang/include/clang/Basic/DiagnosticAnalysisKinds.td12
-rw-r--r--contrib/llvm/tools/clang/include/clang/Basic/DiagnosticCategories.h26
-rw-r--r--contrib/llvm/tools/clang/include/clang/Basic/DiagnosticCategories.td11
-rw-r--r--contrib/llvm/tools/clang/include/clang/Basic/DiagnosticCommentKinds.td172
-rw-r--r--contrib/llvm/tools/clang/include/clang/Basic/DiagnosticCommonKinds.td217
-rw-r--r--contrib/llvm/tools/clang/include/clang/Basic/DiagnosticDriverKinds.td226
-rw-r--r--contrib/llvm/tools/clang/include/clang/Basic/DiagnosticFrontendKinds.td219
-rw-r--r--contrib/llvm/tools/clang/include/clang/Basic/DiagnosticGroups.td848
-rw-r--r--contrib/llvm/tools/clang/include/clang/Basic/DiagnosticIDs.h287
-rw-r--r--contrib/llvm/tools/clang/include/clang/Basic/DiagnosticLexKinds.td673
-rw-r--r--contrib/llvm/tools/clang/include/clang/Basic/DiagnosticOptions.def99
-rw-r--r--contrib/llvm/tools/clang/include/clang/Basic/DiagnosticOptions.h118
-rw-r--r--contrib/llvm/tools/clang/include/clang/Basic/DiagnosticParseKinds.td985
-rw-r--r--contrib/llvm/tools/clang/include/clang/Basic/DiagnosticSemaKinds.td8221
-rw-r--r--contrib/llvm/tools/clang/include/clang/Basic/DiagnosticSerializationKinds.td124
-rw-r--r--contrib/llvm/tools/clang/include/clang/Basic/ExceptionSpecificationType.h60
-rw-r--r--contrib/llvm/tools/clang/include/clang/Basic/ExpressionTraits.h26
-rw-r--r--contrib/llvm/tools/clang/include/clang/Basic/FileManager.h288
-rw-r--r--contrib/llvm/tools/clang/include/clang/Basic/FileSystemOptions.h32
-rw-r--r--contrib/llvm/tools/clang/include/clang/Basic/FileSystemStatCache.h131
-rw-r--r--contrib/llvm/tools/clang/include/clang/Basic/IdentifierTable.h876
-rw-r--r--contrib/llvm/tools/clang/include/clang/Basic/LLVM.h83
-rw-r--r--contrib/llvm/tools/clang/include/clang/Basic/Lambda.h43
-rw-r--r--contrib/llvm/tools/clang/include/clang/Basic/LangOptions.def246
-rw-r--r--contrib/llvm/tools/clang/include/clang/Basic/LangOptions.h190
-rw-r--r--contrib/llvm/tools/clang/include/clang/Basic/Linkage.h110
-rw-r--r--contrib/llvm/tools/clang/include/clang/Basic/MacroBuilder.h48
-rw-r--r--contrib/llvm/tools/clang/include/clang/Basic/Module.h569
-rw-r--r--contrib/llvm/tools/clang/include/clang/Basic/ObjCRuntime.h333
-rw-r--r--contrib/llvm/tools/clang/include/clang/Basic/OpenCLExtensions.def35
-rw-r--r--contrib/llvm/tools/clang/include/clang/Basic/OpenMPKinds.def451
-rw-r--r--contrib/llvm/tools/clang/include/clang/Basic/OpenMPKinds.h175
-rw-r--r--contrib/llvm/tools/clang/include/clang/Basic/OperatorKinds.def107
-rw-r--r--contrib/llvm/tools/clang/include/clang/Basic/OperatorKinds.h36
-rw-r--r--contrib/llvm/tools/clang/include/clang/Basic/OperatorPrecedence.h52
-rw-r--r--contrib/llvm/tools/clang/include/clang/Basic/PartialDiagnostic.h410
-rw-r--r--contrib/llvm/tools/clang/include/clang/Basic/PlistSupport.h119
-rw-r--r--contrib/llvm/tools/clang/include/clang/Basic/PrettyStackTrace.h38
-rw-r--r--contrib/llvm/tools/clang/include/clang/Basic/SanitizerBlacklist.h46
-rw-r--r--contrib/llvm/tools/clang/include/clang/Basic/Sanitizers.def122
-rw-r--r--contrib/llvm/tools/clang/include/clang/Basic/Sanitizers.h86
-rw-r--r--contrib/llvm/tools/clang/include/clang/Basic/SourceLocation.h438
-rw-r--r--contrib/llvm/tools/clang/include/clang/Basic/SourceManager.h1711
-rw-r--r--contrib/llvm/tools/clang/include/clang/Basic/SourceManagerInternals.h128
-rw-r--r--contrib/llvm/tools/clang/include/clang/Basic/Specifiers.h283
-rw-r--r--contrib/llvm/tools/clang/include/clang/Basic/StmtNodes.td224
-rw-r--r--contrib/llvm/tools/clang/include/clang/Basic/TargetBuiltins.h201
-rw-r--r--contrib/llvm/tools/clang/include/clang/Basic/TargetCXXABI.h354
-rw-r--r--contrib/llvm/tools/clang/include/clang/Basic/TargetInfo.h953
-rw-r--r--contrib/llvm/tools/clang/include/clang/Basic/TargetOptions.h54
-rw-r--r--contrib/llvm/tools/clang/include/clang/Basic/TemplateKinds.h44
-rw-r--r--contrib/llvm/tools/clang/include/clang/Basic/TokenKinds.def781
-rw-r--r--contrib/llvm/tools/clang/include/clang/Basic/TokenKinds.h106
-rw-r--r--contrib/llvm/tools/clang/include/clang/Basic/TypeTraits.h100
-rw-r--r--contrib/llvm/tools/clang/include/clang/Basic/Version.h82
-rw-r--r--contrib/llvm/tools/clang/include/clang/Basic/VersionTuple.h163
-rw-r--r--contrib/llvm/tools/clang/include/clang/Basic/VirtualFileSystem.h341
-rw-r--r--contrib/llvm/tools/clang/include/clang/Basic/Visibility.h141
-rw-r--r--contrib/llvm/tools/clang/include/clang/Basic/arm_neon.td1657
-rw-r--r--contrib/llvm/tools/clang/include/clang/CodeGen/BackendUtil.h44
-rw-r--r--contrib/llvm/tools/clang/include/clang/CodeGen/CGFunctionInfo.h538
-rw-r--r--contrib/llvm/tools/clang/include/clang/CodeGen/CodeGenABITypes.h91
-rw-r--r--contrib/llvm/tools/clang/include/clang/CodeGen/CodeGenAction.h107
-rw-r--r--contrib/llvm/tools/clang/include/clang/CodeGen/ModuleBuilder.h54
-rw-r--r--contrib/llvm/tools/clang/include/clang/CodeGen/ObjectFilePCHContainerOperations.h43
-rw-r--r--contrib/llvm/tools/clang/include/clang/Driver/Action.h317
-rw-r--r--contrib/llvm/tools/clang/include/clang/Driver/CC1Options.td718
-rw-r--r--contrib/llvm/tools/clang/include/clang/Driver/CLCompatOptions.td342
-rw-r--r--contrib/llvm/tools/clang/include/clang/Driver/Compilation.h202
-rw-r--r--contrib/llvm/tools/clang/include/clang/Driver/Driver.h468
-rw-r--r--contrib/llvm/tools/clang/include/clang/Driver/DriverDiagnostic.h28
-rw-r--r--contrib/llvm/tools/clang/include/clang/Driver/Job.h174
-rw-r--r--contrib/llvm/tools/clang/include/clang/Driver/Multilib.h175
-rw-r--r--contrib/llvm/tools/clang/include/clang/Driver/Options.h51
-rw-r--r--contrib/llvm/tools/clang/include/clang/Driver/Options.td2133
-rw-r--r--contrib/llvm/tools/clang/include/clang/Driver/Phases.h37
-rw-r--r--contrib/llvm/tools/clang/include/clang/Driver/SanitizerArgs.h73
-rw-r--r--contrib/llvm/tools/clang/include/clang/Driver/Tool.h137
-rw-r--r--contrib/llvm/tools/clang/include/clang/Driver/ToolChain.h418
-rw-r--r--contrib/llvm/tools/clang/include/clang/Driver/Types.def96
-rw-r--r--contrib/llvm/tools/clang/include/clang/Driver/Types.h97
-rw-r--r--contrib/llvm/tools/clang/include/clang/Driver/Util.h32
-rw-r--r--contrib/llvm/tools/clang/include/clang/Edit/Commit.h143
-rw-r--r--contrib/llvm/tools/clang/include/clang/Edit/EditedSource.h97
-rw-r--r--contrib/llvm/tools/clang/include/clang/Edit/EditsReceiver.h35
-rw-r--r--contrib/llvm/tools/clang/include/clang/Edit/FileOffset.h61
-rw-r--r--contrib/llvm/tools/clang/include/clang/Edit/Rewriters.h41
-rw-r--r--contrib/llvm/tools/clang/include/clang/Format/Format.h792
-rw-r--r--contrib/llvm/tools/clang/include/clang/Frontend/ASTConsumers.h58
-rw-r--r--contrib/llvm/tools/clang/include/clang/Frontend/ASTUnit.h924
-rw-r--r--contrib/llvm/tools/clang/include/clang/Frontend/ChainedDiagnosticConsumer.h72
-rw-r--r--contrib/llvm/tools/clang/include/clang/Frontend/CodeGenOptions.def212
-rw-r--r--contrib/llvm/tools/clang/include/clang/Frontend/CodeGenOptions.h245
-rw-r--r--contrib/llvm/tools/clang/include/clang/Frontend/CommandLineSourceLoc.h87
-rw-r--r--contrib/llvm/tools/clang/include/clang/Frontend/CompilerInstance.h785
-rw-r--r--contrib/llvm/tools/clang/include/clang/Frontend/CompilerInvocation.h219
-rw-r--r--contrib/llvm/tools/clang/include/clang/Frontend/DependencyOutputOptions.h73
-rw-r--r--contrib/llvm/tools/clang/include/clang/Frontend/DiagnosticRenderer.h178
-rw-r--r--contrib/llvm/tools/clang/include/clang/Frontend/FrontendAction.h298
-rw-r--r--contrib/llvm/tools/clang/include/clang/Frontend/FrontendActions.h241
-rw-r--r--contrib/llvm/tools/clang/include/clang/Frontend/FrontendDiagnostic.h28
-rw-r--r--contrib/llvm/tools/clang/include/clang/Frontend/FrontendOptions.h292
-rw-r--r--contrib/llvm/tools/clang/include/clang/Frontend/FrontendPluginRegistry.h26
-rw-r--r--contrib/llvm/tools/clang/include/clang/Frontend/LangStandard.h100
-rw-r--r--contrib/llvm/tools/clang/include/clang/Frontend/LangStandards.def153
-rw-r--r--contrib/llvm/tools/clang/include/clang/Frontend/LayoutOverrideSource.h63
-rw-r--r--contrib/llvm/tools/clang/include/clang/Frontend/LogDiagnosticPrinter.h85
-rw-r--r--contrib/llvm/tools/clang/include/clang/Frontend/MigratorOptions.h31
-rw-r--r--contrib/llvm/tools/clang/include/clang/Frontend/MultiplexConsumer.h69
-rw-r--r--contrib/llvm/tools/clang/include/clang/Frontend/PCHContainerOperations.h118
-rw-r--r--contrib/llvm/tools/clang/include/clang/Frontend/PreprocessorOutputOptions.h41
-rw-r--r--contrib/llvm/tools/clang/include/clang/Frontend/SerializedDiagnosticPrinter.h43
-rw-r--r--contrib/llvm/tools/clang/include/clang/Frontend/SerializedDiagnosticReader.h131
-rw-r--r--contrib/llvm/tools/clang/include/clang/Frontend/SerializedDiagnostics.h59
-rw-r--r--contrib/llvm/tools/clang/include/clang/Frontend/TextDiagnostic.h122
-rw-r--r--contrib/llvm/tools/clang/include/clang/Frontend/TextDiagnosticBuffer.h55
-rw-r--r--contrib/llvm/tools/clang/include/clang/Frontend/TextDiagnosticPrinter.h58
-rw-r--r--contrib/llvm/tools/clang/include/clang/Frontend/Utils.h220
-rw-r--r--contrib/llvm/tools/clang/include/clang/Frontend/VerifyDiagnosticConsumer.h278
-rw-r--r--contrib/llvm/tools/clang/include/clang/FrontendTool/Utils.h30
-rw-r--r--contrib/llvm/tools/clang/include/clang/Index/CommentToXML.h52
-rw-r--r--contrib/llvm/tools/clang/include/clang/Index/USRGeneration.h62
-rw-r--r--contrib/llvm/tools/clang/include/clang/Lex/CodeCompletionHandler.h71
-rw-r--r--contrib/llvm/tools/clang/include/clang/Lex/DirectoryLookup.h196
-rw-r--r--contrib/llvm/tools/clang/include/clang/Lex/ExternalPreprocessorSource.h48
-rw-r--r--contrib/llvm/tools/clang/include/clang/Lex/HeaderMap.h76
-rw-r--r--contrib/llvm/tools/clang/include/clang/Lex/HeaderSearch.h688
-rw-r--r--contrib/llvm/tools/clang/include/clang/Lex/HeaderSearchOptions.h206
-rw-r--r--contrib/llvm/tools/clang/include/clang/Lex/LexDiagnostic.h28
-rw-r--r--contrib/llvm/tools/clang/include/clang/Lex/Lexer.h665
-rw-r--r--contrib/llvm/tools/clang/include/clang/Lex/LiteralSupport.h260
-rw-r--r--contrib/llvm/tools/clang/include/clang/Lex/MacroArgs.h127
-rw-r--r--contrib/llvm/tools/clang/include/clang/Lex/MacroInfo.h609
-rw-r--r--contrib/llvm/tools/clang/include/clang/Lex/ModuleLoader.h129
-rw-r--r--contrib/llvm/tools/clang/include/clang/Lex/ModuleMap.h514
-rw-r--r--contrib/llvm/tools/clang/include/clang/Lex/MultipleIncludeOpt.h181
-rw-r--r--contrib/llvm/tools/clang/include/clang/Lex/PPCallbacks.h509
-rw-r--r--contrib/llvm/tools/clang/include/clang/Lex/PPConditionalDirectiveRecord.h103
-rw-r--r--contrib/llvm/tools/clang/include/clang/Lex/PTHLexer.h104
-rw-r--r--contrib/llvm/tools/clang/include/clang/Lex/PTHManager.h150
-rw-r--r--contrib/llvm/tools/clang/include/clang/Lex/Pragma.h126
-rw-r--r--contrib/llvm/tools/clang/include/clang/Lex/PreprocessingRecord.h536
-rw-r--r--contrib/llvm/tools/clang/include/clang/Lex/Preprocessor.h1911
-rw-r--r--contrib/llvm/tools/clang/include/clang/Lex/PreprocessorLexer.h183
-rw-r--r--contrib/llvm/tools/clang/include/clang/Lex/PreprocessorOptions.h185
-rw-r--r--contrib/llvm/tools/clang/include/clang/Lex/ScratchBuffer.h45
-rw-r--r--contrib/llvm/tools/clang/include/clang/Lex/Token.h328
-rw-r--r--contrib/llvm/tools/clang/include/clang/Lex/TokenConcatenation.h72
-rw-r--r--contrib/llvm/tools/clang/include/clang/Lex/TokenLexer.h205
-rw-r--r--contrib/llvm/tools/clang/include/clang/Parse/ParseAST.h49
-rw-r--r--contrib/llvm/tools/clang/include/clang/Parse/ParseDiagnostic.h28
-rw-r--r--contrib/llvm/tools/clang/include/clang/Parse/Parser.h2593
-rw-r--r--contrib/llvm/tools/clang/include/clang/Rewrite/Core/DeltaTree.h50
-rw-r--r--contrib/llvm/tools/clang/include/clang/Rewrite/Core/HTMLRewrite.h81
-rw-r--r--contrib/llvm/tools/clang/include/clang/Rewrite/Core/RewriteBuffer.h117
-rw-r--r--contrib/llvm/tools/clang/include/clang/Rewrite/Core/RewriteRope.h214
-rw-r--r--contrib/llvm/tools/clang/include/clang/Rewrite/Core/Rewriter.h195
-rw-r--r--contrib/llvm/tools/clang/include/clang/Rewrite/Core/TokenRewriter.h79
-rw-r--r--contrib/llvm/tools/clang/include/clang/Rewrite/Frontend/ASTConsumers.h48
-rw-r--r--contrib/llvm/tools/clang/include/clang/Rewrite/Frontend/FixItRewriter.h132
-rw-r--r--contrib/llvm/tools/clang/include/clang/Rewrite/Frontend/FrontendActions.h83
-rw-r--r--contrib/llvm/tools/clang/include/clang/Rewrite/Frontend/Rewriters.h35
-rw-r--r--contrib/llvm/tools/clang/include/clang/Sema/AnalysisBasedWarnings.h103
-rw-r--r--contrib/llvm/tools/clang/include/clang/Sema/AttributeList.h863
-rw-r--r--contrib/llvm/tools/clang/include/clang/Sema/CXXFieldCollector.h80
-rw-r--r--contrib/llvm/tools/clang/include/clang/Sema/CodeCompleteConsumer.h976
-rw-r--r--contrib/llvm/tools/clang/include/clang/Sema/CodeCompleteOptions.h41
-rw-r--r--contrib/llvm/tools/clang/include/clang/Sema/DeclSpec.h2313
-rw-r--r--contrib/llvm/tools/clang/include/clang/Sema/DelayedDiagnostic.h305
-rw-r--r--contrib/llvm/tools/clang/include/clang/Sema/Designator.h210
-rw-r--r--contrib/llvm/tools/clang/include/clang/Sema/ExternalSemaSource.h229
-rw-r--r--contrib/llvm/tools/clang/include/clang/Sema/IdentifierResolver.h213
-rw-r--r--contrib/llvm/tools/clang/include/clang/Sema/Initialization.h1145
-rw-r--r--contrib/llvm/tools/clang/include/clang/Sema/LocInfoType.h62
-rw-r--r--contrib/llvm/tools/clang/include/clang/Sema/Lookup.h760
-rw-r--r--contrib/llvm/tools/clang/include/clang/Sema/LoopHint.h45
-rw-r--r--contrib/llvm/tools/clang/include/clang/Sema/MultiplexExternalSemaSource.h353
-rw-r--r--contrib/llvm/tools/clang/include/clang/Sema/ObjCMethodList.h58
-rw-r--r--contrib/llvm/tools/clang/include/clang/Sema/Overload.h799
-rw-r--r--contrib/llvm/tools/clang/include/clang/Sema/Ownership.h287
-rw-r--r--contrib/llvm/tools/clang/include/clang/Sema/ParsedTemplate.h214
-rw-r--r--contrib/llvm/tools/clang/include/clang/Sema/PrettyDeclStackTrace.h47
-rw-r--r--contrib/llvm/tools/clang/include/clang/Sema/Scope.h484
-rw-r--r--contrib/llvm/tools/clang/include/clang/Sema/ScopeInfo.h858
-rw-r--r--contrib/llvm/tools/clang/include/clang/Sema/Sema.h9265
-rw-r--r--contrib/llvm/tools/clang/include/clang/Sema/SemaConsumer.h48
-rw-r--r--contrib/llvm/tools/clang/include/clang/Sema/SemaDiagnostic.h28
-rw-r--r--contrib/llvm/tools/clang/include/clang/Sema/SemaFixItUtils.h91
-rw-r--r--contrib/llvm/tools/clang/include/clang/Sema/SemaInternal.h346
-rw-r--r--contrib/llvm/tools/clang/include/clang/Sema/SemaLambda.h36
-rw-r--r--contrib/llvm/tools/clang/include/clang/Sema/Template.h519
-rw-r--r--contrib/llvm/tools/clang/include/clang/Sema/TemplateDeduction.h315
-rw-r--r--contrib/llvm/tools/clang/include/clang/Sema/TypoCorrection.h366
-rw-r--r--contrib/llvm/tools/clang/include/clang/Sema/Weak.h46
-rw-r--r--contrib/llvm/tools/clang/include/clang/Serialization/ASTBitCodes.h1605
-rw-r--r--contrib/llvm/tools/clang/include/clang/Serialization/ASTDeserializationListener.h58
-rw-r--r--contrib/llvm/tools/clang/include/clang/Serialization/ASTReader.h2141
-rw-r--r--contrib/llvm/tools/clang/include/clang/Serialization/ASTWriter.h920
-rw-r--r--contrib/llvm/tools/clang/include/clang/Serialization/ContinuousRangeMap.h139
-rw-r--r--contrib/llvm/tools/clang/include/clang/Serialization/GlobalModuleIndex.h207
-rw-r--r--contrib/llvm/tools/clang/include/clang/Serialization/Module.h475
-rw-r--r--contrib/llvm/tools/clang/include/clang/Serialization/ModuleFileExtension.h149
-rw-r--r--contrib/llvm/tools/clang/include/clang/Serialization/ModuleManager.h289
-rw-r--r--contrib/llvm/tools/clang/include/clang/Serialization/SerializationDiagnostic.h28
-rw-r--r--contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Checkers/CheckerBase.td39
-rw-r--r--contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Checkers/ClangCheckers.h22
-rw-r--r--contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Checkers/LocalCheckers.h28
-rw-r--r--contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Checkers/ObjCRetainCount.h234
-rw-r--r--contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/Analyses.def57
-rw-r--r--contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/AnalyzerOptions.h567
-rw-r--r--contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/BugReporter/BugReporter.h561
-rw-r--r--contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/BugReporter/BugReporterVisitor.h366
-rw-r--r--contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/BugReporter/BugType.h81
-rw-r--r--contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/BugReporter/CommonBugCategories.h25
-rw-r--r--contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h848
-rw-r--r--contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/Checker.h554
-rw-r--r--contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/CheckerManager.h632
-rw-r--r--contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/CheckerOptInfo.h44
-rw-r--r--contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/CheckerRegistry.h140
-rw-r--r--contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/IssueHash.h51
-rw-r--r--contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathDiagnosticConsumers.h40
-rw-r--r--contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/APSIntType.h109
-rw-r--r--contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h135
-rw-r--r--contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/BasicValueFactory.h200
-rw-r--r--contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/BlockCounter.h60
-rw-r--r--contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h1091
-rw-r--r--contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h349
-rw-r--r--contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/CheckerHelpers.h49
-rw-r--r--contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ConstraintManager.h188
-rw-r--r--contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/CoreEngine.h547
-rw-r--r--contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/DynamicTypeInfo.h52
-rw-r--r--contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/DynamicTypeMap.h57
-rw-r--r--contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/Environment.h127
-rw-r--r--contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ExplodedGraph.h497
-rw-r--r--contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h646
-rw-r--r--contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/FunctionSummary.h140
-rw-r--r--contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/LoopWidening.h36
-rw-r--r--contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h1370
-rw-r--r--contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h854
-rw-r--r--contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ProgramStateTrait.h245
-rw-r--r--contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ProgramState_Fwd.h43
-rw-r--r--contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/SValBuilder.h333
-rw-r--r--contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/SVals.h574
-rw-r--r--contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/Store.h288
-rw-r--r--contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/StoreRef.h51
-rw-r--r--contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/SubEngine.h162
-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.h681
-rw-r--r--contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/TaintManager.h46
-rw-r--r--contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/TaintTag.h27
-rw-r--r--contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/WorkList.h100
-rw-r--r--contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Frontend/AnalysisConsumer.h49
-rw-r--r--contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Frontend/CheckerRegistration.h33
-rw-r--r--contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Frontend/FrontendActions.h60
-rw-r--r--contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Frontend/ModelConsumer.h44
-rw-r--r--contrib/llvm/tools/clang/include/clang/Tooling/ArgumentsAdjusters.h69
-rw-r--r--contrib/llvm/tools/clang/include/clang/Tooling/CommonOptionsParser.h117
-rw-r--r--contrib/llvm/tools/clang/include/clang/Tooling/CompilationDatabase.h222
-rw-r--r--contrib/llvm/tools/clang/include/clang/Tooling/CompilationDatabasePluginRegistry.h27
-rw-r--r--contrib/llvm/tools/clang/include/clang/Tooling/Core/Lookup.h48
-rw-r--r--contrib/llvm/tools/clang/include/clang/Tooling/Core/Replacement.h241
-rw-r--r--contrib/llvm/tools/clang/include/clang/Tooling/FileMatchTrie.h89
-rw-r--r--contrib/llvm/tools/clang/include/clang/Tooling/JSONCompilationDatabase.h133
-rw-r--r--contrib/llvm/tools/clang/include/clang/Tooling/Refactoring.h74
-rw-r--r--contrib/llvm/tools/clang/include/clang/Tooling/RefactoringCallbacks.h90
-rw-r--r--contrib/llvm/tools/clang/include/clang/Tooling/ReplacementsYaml.h76
-rw-r--r--contrib/llvm/tools/clang/include/clang/Tooling/Tooling.h455
-rw-r--r--contrib/llvm/tools/clang/include/clang/module.modulemap134
428 files changed, 191901 insertions, 0 deletions
diff --git a/contrib/llvm/tools/clang/include/clang-c/BuildSystem.h b/contrib/llvm/tools/clang/include/clang-c/BuildSystem.h
new file mode 100644
index 0000000..8d323a4
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang-c/BuildSystem.h
@@ -0,0 +1,156 @@
+/*==-- clang-c/BuildSystem.h - Utilities for use by build systems -*- 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 various utilities for use by build systems. *|
+|* *|
+\*===----------------------------------------------------------------------===*/
+
+#ifndef LLVM_CLANG_C_BUILDSYSTEM_H
+#define LLVM_CLANG_C_BUILDSYSTEM_H
+
+#include "clang-c/Platform.h"
+#include "clang-c/CXErrorCode.h"
+#include "clang-c/CXString.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * \defgroup BUILD_SYSTEM Build system utilities
+ * @{
+ */
+
+/**
+ * \brief Return the timestamp for use with Clang's
+ * \c -fbuild-session-timestamp= option.
+ */
+CINDEX_LINKAGE unsigned long long clang_getBuildSessionTimestamp(void);
+
+/**
+ * \brief Object encapsulating information about overlaying virtual
+ * file/directories over the real file system.
+ */
+typedef struct CXVirtualFileOverlayImpl *CXVirtualFileOverlay;
+
+/**
+ * \brief Create a \c CXVirtualFileOverlay object.
+ * Must be disposed with \c clang_VirtualFileOverlay_dispose().
+ *
+ * \param options is reserved, always pass 0.
+ */
+CINDEX_LINKAGE CXVirtualFileOverlay
+clang_VirtualFileOverlay_create(unsigned options);
+
+/**
+ * \brief Map an absolute virtual file path to an absolute real one.
+ * The virtual path must be canonicalized (not contain "."/"..").
+ * \returns 0 for success, non-zero to indicate an error.
+ */
+CINDEX_LINKAGE enum CXErrorCode
+clang_VirtualFileOverlay_addFileMapping(CXVirtualFileOverlay,
+ const char *virtualPath,
+ const char *realPath);
+
+/**
+ * \brief Set the case sensitivity for the \c CXVirtualFileOverlay object.
+ * The \c CXVirtualFileOverlay object is case-sensitive by default, this
+ * option can be used to override the default.
+ * \returns 0 for success, non-zero to indicate an error.
+ */
+CINDEX_LINKAGE enum CXErrorCode
+clang_VirtualFileOverlay_setCaseSensitivity(CXVirtualFileOverlay,
+ int caseSensitive);
+
+/**
+ * \brief Write out the \c CXVirtualFileOverlay object to a char buffer.
+ *
+ * \param options is reserved, always pass 0.
+ * \param out_buffer_ptr pointer to receive the buffer pointer, which should be
+ * disposed using \c clang_free().
+ * \param out_buffer_size pointer to receive the buffer size.
+ * \returns 0 for success, non-zero to indicate an error.
+ */
+CINDEX_LINKAGE enum CXErrorCode
+clang_VirtualFileOverlay_writeToBuffer(CXVirtualFileOverlay, unsigned options,
+ char **out_buffer_ptr,
+ unsigned *out_buffer_size);
+
+/**
+ * \brief free memory allocated by libclang, such as the buffer returned by
+ * \c CXVirtualFileOverlay() or \c clang_ModuleMapDescriptor_writeToBuffer().
+ *
+ * \param buffer memory pointer to free.
+ */
+CINDEX_LINKAGE void clang_free(void *buffer);
+
+/**
+ * \brief Dispose a \c CXVirtualFileOverlay object.
+ */
+CINDEX_LINKAGE void clang_VirtualFileOverlay_dispose(CXVirtualFileOverlay);
+
+/**
+ * \brief Object encapsulating information about a module.map file.
+ */
+typedef struct CXModuleMapDescriptorImpl *CXModuleMapDescriptor;
+
+/**
+ * \brief Create a \c CXModuleMapDescriptor object.
+ * Must be disposed with \c clang_ModuleMapDescriptor_dispose().
+ *
+ * \param options is reserved, always pass 0.
+ */
+CINDEX_LINKAGE CXModuleMapDescriptor
+clang_ModuleMapDescriptor_create(unsigned options);
+
+/**
+ * \brief Sets the framework module name that the module.map describes.
+ * \returns 0 for success, non-zero to indicate an error.
+ */
+CINDEX_LINKAGE enum CXErrorCode
+clang_ModuleMapDescriptor_setFrameworkModuleName(CXModuleMapDescriptor,
+ const char *name);
+
+/**
+ * \brief Sets the umbrealla header name that the module.map describes.
+ * \returns 0 for success, non-zero to indicate an error.
+ */
+CINDEX_LINKAGE enum CXErrorCode
+clang_ModuleMapDescriptor_setUmbrellaHeader(CXModuleMapDescriptor,
+ const char *name);
+
+/**
+ * \brief Write out the \c CXModuleMapDescriptor object to a char buffer.
+ *
+ * \param options is reserved, always pass 0.
+ * \param out_buffer_ptr pointer to receive the buffer pointer, which should be
+ * disposed using \c clang_free().
+ * \param out_buffer_size pointer to receive the buffer size.
+ * \returns 0 for success, non-zero to indicate an error.
+ */
+CINDEX_LINKAGE enum CXErrorCode
+clang_ModuleMapDescriptor_writeToBuffer(CXModuleMapDescriptor, unsigned options,
+ char **out_buffer_ptr,
+ unsigned *out_buffer_size);
+
+/**
+ * \brief Dispose a \c CXModuleMapDescriptor object.
+ */
+CINDEX_LINKAGE void clang_ModuleMapDescriptor_dispose(CXModuleMapDescriptor);
+
+/**
+ * @}
+ */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* CLANG_C_BUILD_SYSTEM_H */
+
diff --git a/contrib/llvm/tools/clang/include/clang-c/CXCompilationDatabase.h b/contrib/llvm/tools/clang/include/clang-c/CXCompilationDatabase.h
new file mode 100644
index 0000000..9359abf
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang-c/CXCompilationDatabase.h
@@ -0,0 +1,176 @@
+/*===-- clang-c/CXCompilationDatabase.h - Compilation database ---*- 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 use CompilationDatabase without *|
+|* the full Clang C++ API. *|
+|* *|
+\*===----------------------------------------------------------------------===*/
+
+#ifndef LLVM_CLANG_C_CXCOMPILATIONDATABASE_H
+#define LLVM_CLANG_C_CXCOMPILATIONDATABASE_H
+
+#include "clang-c/Platform.h"
+#include "clang-c/CXString.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/** \defgroup COMPILATIONDB CompilationDatabase functions
+ * \ingroup CINDEX
+ *
+ * @{
+ */
+
+/**
+ * A compilation database holds all information used to compile files in a
+ * project. For each file in the database, it can be queried for the working
+ * directory or the command line used for the compiler invocation.
+ *
+ * Must be freed by \c clang_CompilationDatabase_dispose
+ */
+typedef void * CXCompilationDatabase;
+
+/**
+ * \brief Contains the results of a search in the compilation database
+ *
+ * When searching for the compile command for a file, the compilation db can
+ * return several commands, as the file may have been compiled with
+ * different options in different places of the project. This choice of compile
+ * commands is wrapped in this opaque data structure. It must be freed by
+ * \c clang_CompileCommands_dispose.
+ */
+typedef void * CXCompileCommands;
+
+/**
+ * \brief Represents the command line invocation to compile a specific file.
+ */
+typedef void * CXCompileCommand;
+
+/**
+ * \brief Error codes for Compilation Database
+ */
+typedef enum {
+ /*
+ * \brief No error occurred
+ */
+ CXCompilationDatabase_NoError = 0,
+
+ /*
+ * \brief Database can not be loaded
+ */
+ CXCompilationDatabase_CanNotLoadDatabase = 1
+
+} CXCompilationDatabase_Error;
+
+/**
+ * \brief Creates a compilation database from the database found in directory
+ * buildDir. For example, CMake can output a compile_commands.json which can
+ * be used to build the database.
+ *
+ * It must be freed by \c clang_CompilationDatabase_dispose.
+ */
+CINDEX_LINKAGE CXCompilationDatabase
+clang_CompilationDatabase_fromDirectory(const char *BuildDir,
+ CXCompilationDatabase_Error *ErrorCode);
+
+/**
+ * \brief Free the given compilation database
+ */
+CINDEX_LINKAGE void
+clang_CompilationDatabase_dispose(CXCompilationDatabase);
+
+/**
+ * \brief Find the compile commands used for a file. The compile commands
+ * must be freed by \c clang_CompileCommands_dispose.
+ */
+CINDEX_LINKAGE CXCompileCommands
+clang_CompilationDatabase_getCompileCommands(CXCompilationDatabase,
+ const char *CompleteFileName);
+
+/**
+ * \brief Get all the compile commands in the given compilation database.
+ */
+CINDEX_LINKAGE CXCompileCommands
+clang_CompilationDatabase_getAllCompileCommands(CXCompilationDatabase);
+
+/**
+ * \brief Free the given CompileCommands
+ */
+CINDEX_LINKAGE void clang_CompileCommands_dispose(CXCompileCommands);
+
+/**
+ * \brief Get the number of CompileCommand we have for a file
+ */
+CINDEX_LINKAGE unsigned
+clang_CompileCommands_getSize(CXCompileCommands);
+
+/**
+ * \brief Get the I'th CompileCommand for a file
+ *
+ * Note : 0 <= i < clang_CompileCommands_getSize(CXCompileCommands)
+ */
+CINDEX_LINKAGE CXCompileCommand
+clang_CompileCommands_getCommand(CXCompileCommands, unsigned I);
+
+/**
+ * \brief Get the working directory where the CompileCommand was executed from
+ */
+CINDEX_LINKAGE CXString
+clang_CompileCommand_getDirectory(CXCompileCommand);
+
+/**
+ * \brief Get the filename associated with the CompileCommand.
+ */
+CINDEX_LINKAGE CXString
+clang_CompileCommand_getFilename(CXCompileCommand);
+
+/**
+ * \brief Get the number of arguments in the compiler invocation.
+ *
+ */
+CINDEX_LINKAGE unsigned
+clang_CompileCommand_getNumArgs(CXCompileCommand);
+
+/**
+ * \brief Get the I'th argument value in the compiler invocations
+ *
+ * Invariant :
+ * - argument 0 is the compiler executable
+ */
+CINDEX_LINKAGE CXString
+clang_CompileCommand_getArg(CXCompileCommand, unsigned I);
+
+/**
+ * \brief Get the number of source mappings for the compiler invocation.
+ */
+CINDEX_LINKAGE unsigned
+clang_CompileCommand_getNumMappedSources(CXCompileCommand);
+
+/**
+ * \brief Get the I'th mapped source path for the compiler invocation.
+ */
+CINDEX_LINKAGE CXString
+clang_CompileCommand_getMappedSourcePath(CXCompileCommand, unsigned I);
+
+/**
+ * \brief Get the I'th mapped source content for the compiler invocation.
+ */
+CINDEX_LINKAGE CXString
+clang_CompileCommand_getMappedSourceContent(CXCompileCommand, unsigned I);
+
+/**
+ * @}
+ */
+
+#ifdef __cplusplus
+}
+#endif
+#endif
+
diff --git a/contrib/llvm/tools/clang/include/clang-c/CXErrorCode.h b/contrib/llvm/tools/clang/include/clang-c/CXErrorCode.h
new file mode 100644
index 0000000..aff73b7
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang-c/CXErrorCode.h
@@ -0,0 +1,64 @@
+/*===-- clang-c/CXErrorCode.h - C Index Error Codes --------------*- 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 the CXErrorCode enumerators. *|
+|* *|
+\*===----------------------------------------------------------------------===*/
+
+#ifndef LLVM_CLANG_C_CXERRORCODE_H
+#define LLVM_CLANG_C_CXERRORCODE_H
+
+#include "clang-c/Platform.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * \brief Error codes returned by libclang routines.
+ *
+ * Zero (\c CXError_Success) is the only error code indicating success. Other
+ * error codes, including not yet assigned non-zero values, indicate errors.
+ */
+enum CXErrorCode {
+ /**
+ * \brief No error.
+ */
+ CXError_Success = 0,
+
+ /**
+ * \brief A generic error code, no further details are available.
+ *
+ * Errors of this kind can get their own specific error codes in future
+ * libclang versions.
+ */
+ CXError_Failure = 1,
+
+ /**
+ * \brief libclang crashed while performing the requested operation.
+ */
+ CXError_Crashed = 2,
+
+ /**
+ * \brief The function detected that the arguments violate the function
+ * contract.
+ */
+ CXError_InvalidArguments = 3,
+
+ /**
+ * \brief An AST deserialization error has occurred.
+ */
+ CXError_ASTReadError = 4
+};
+
+#ifdef __cplusplus
+}
+#endif
+#endif
+
diff --git a/contrib/llvm/tools/clang/include/clang-c/CXString.h b/contrib/llvm/tools/clang/include/clang-c/CXString.h
new file mode 100644
index 0000000..68ab7bc
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang-c/CXString.h
@@ -0,0 +1,71 @@
+/*===-- clang-c/CXString.h - C Index strings --------------------*- 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 the interface to C Index strings. *|
+|* *|
+\*===----------------------------------------------------------------------===*/
+
+#ifndef LLVM_CLANG_C_CXSTRING_H
+#define LLVM_CLANG_C_CXSTRING_H
+
+#include "clang-c/Platform.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * \defgroup CINDEX_STRING String manipulation routines
+ * \ingroup CINDEX
+ *
+ * @{
+ */
+
+/**
+ * \brief A character string.
+ *
+ * The \c CXString type is used to return strings from the interface when
+ * the ownership of that string might differ 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 {
+ const void *data;
+ unsigned private_flags;
+} CXString;
+
+typedef struct {
+ CXString *Strings;
+ unsigned Count;
+} CXStringSet;
+
+/**
+ * \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 Free the given string set.
+ */
+CINDEX_LINKAGE void clang_disposeStringSet(CXStringSet *set);
+
+/**
+ * @}
+ */
+
+#ifdef __cplusplus
+}
+#endif
+#endif
+
diff --git a/contrib/llvm/tools/clang/include/clang-c/Documentation.h b/contrib/llvm/tools/clang/include/clang-c/Documentation.h
new file mode 100644
index 0000000..89373b1
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang-c/Documentation.h
@@ -0,0 +1,554 @@
+/*==-- clang-c/Documentation.h - Utilities for comment processing -*- 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 supplementary interface for inspecting *|
+|* documentation comments. *|
+|* *|
+\*===----------------------------------------------------------------------===*/
+
+#ifndef LLVM_CLANG_C_DOCUMENTATION_H
+#define LLVM_CLANG_C_DOCUMENTATION_H
+
+#include "clang-c/Index.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * \defgroup CINDEX_COMMENT Comment introspection
+ *
+ * The routines in this group provide access to information in documentation
+ * comments. These facilities are distinct from the core and may be subject to
+ * their own schedule of stability and deprecation.
+ *
+ * @{
+ */
+
+/**
+ * \brief A parsed comment.
+ */
+typedef struct {
+ const void *ASTNode;
+ CXTranslationUnit TranslationUnit;
+} CXComment;
+
+/**
+ * \brief Given a cursor that represents a documentable entity (e.g.,
+ * declaration), return the associated parsed comment as a
+ * \c CXComment_FullComment AST node.
+ */
+CINDEX_LINKAGE CXComment clang_Cursor_getParsedComment(CXCursor C);
+
+/**
+ * \brief Describes the type of the comment AST node (\c CXComment). A comment
+ * node can be considered block content (e. g., paragraph), inline content
+ * (plain text) or neither (the root AST node).
+ */
+enum CXCommentKind {
+ /**
+ * \brief Null comment. No AST node is constructed at the requested location
+ * because there is no text or a syntax error.
+ */
+ CXComment_Null = 0,
+
+ /**
+ * \brief Plain text. Inline content.
+ */
+ CXComment_Text = 1,
+
+ /**
+ * \brief A command with word-like arguments that is considered inline content.
+ *
+ * For example: \\c command.
+ */
+ CXComment_InlineCommand = 2,
+
+ /**
+ * \brief HTML start tag with attributes (name-value pairs). Considered
+ * inline content.
+ *
+ * For example:
+ * \verbatim
+ * <br> <br /> <a href="http://example.org/">
+ * \endverbatim
+ */
+ CXComment_HTMLStartTag = 3,
+
+ /**
+ * \brief HTML end tag. Considered inline content.
+ *
+ * For example:
+ * \verbatim
+ * </a>
+ * \endverbatim
+ */
+ CXComment_HTMLEndTag = 4,
+
+ /**
+ * \brief A paragraph, contains inline comment. The paragraph itself is
+ * block content.
+ */
+ CXComment_Paragraph = 5,
+
+ /**
+ * \brief A command that has zero or more word-like arguments (number of
+ * word-like arguments depends on command name) and a paragraph as an
+ * argument. Block command is block content.
+ *
+ * Paragraph argument is also a child of the block command.
+ *
+ * For example: \\brief has 0 word-like arguments and a paragraph argument.
+ *
+ * AST nodes of special kinds that parser knows about (e. g., \\param
+ * command) have their own node kinds.
+ */
+ CXComment_BlockCommand = 6,
+
+ /**
+ * \brief A \\param or \\arg command that describes the function parameter
+ * (name, passing direction, description).
+ *
+ * For example: \\param [in] ParamName description.
+ */
+ CXComment_ParamCommand = 7,
+
+ /**
+ * \brief A \\tparam command that describes a template parameter (name and
+ * description).
+ *
+ * For example: \\tparam T description.
+ */
+ CXComment_TParamCommand = 8,
+
+ /**
+ * \brief A verbatim block command (e. g., preformatted code). Verbatim
+ * block has an opening and a closing command and contains multiple lines of
+ * text (\c CXComment_VerbatimBlockLine child nodes).
+ *
+ * For example:
+ * \\verbatim
+ * aaa
+ * \\endverbatim
+ */
+ CXComment_VerbatimBlockCommand = 9,
+
+ /**
+ * \brief A line of text that is contained within a
+ * CXComment_VerbatimBlockCommand node.
+ */
+ CXComment_VerbatimBlockLine = 10,
+
+ /**
+ * \brief A verbatim line command. Verbatim line has an opening command,
+ * a single line of text (up to the newline after the opening command) and
+ * has no closing command.
+ */
+ CXComment_VerbatimLine = 11,
+
+ /**
+ * \brief A full comment attached to a declaration, contains block content.
+ */
+ CXComment_FullComment = 12
+};
+
+/**
+ * \brief The most appropriate rendering mode for an inline command, chosen on
+ * command semantics in Doxygen.
+ */
+enum CXCommentInlineCommandRenderKind {
+ /**
+ * \brief Command argument should be rendered in a normal font.
+ */
+ CXCommentInlineCommandRenderKind_Normal,
+
+ /**
+ * \brief Command argument should be rendered in a bold font.
+ */
+ CXCommentInlineCommandRenderKind_Bold,
+
+ /**
+ * \brief Command argument should be rendered in a monospaced font.
+ */
+ CXCommentInlineCommandRenderKind_Monospaced,
+
+ /**
+ * \brief Command argument should be rendered emphasized (typically italic
+ * font).
+ */
+ CXCommentInlineCommandRenderKind_Emphasized
+};
+
+/**
+ * \brief Describes parameter passing direction for \\param or \\arg command.
+ */
+enum CXCommentParamPassDirection {
+ /**
+ * \brief The parameter is an input parameter.
+ */
+ CXCommentParamPassDirection_In,
+
+ /**
+ * \brief The parameter is an output parameter.
+ */
+ CXCommentParamPassDirection_Out,
+
+ /**
+ * \brief The parameter is an input and output parameter.
+ */
+ CXCommentParamPassDirection_InOut
+};
+
+/**
+ * \param Comment AST node of any kind.
+ *
+ * \returns the type of the AST node.
+ */
+CINDEX_LINKAGE enum CXCommentKind clang_Comment_getKind(CXComment Comment);
+
+/**
+ * \param Comment AST node of any kind.
+ *
+ * \returns number of children of the AST node.
+ */
+CINDEX_LINKAGE unsigned clang_Comment_getNumChildren(CXComment Comment);
+
+/**
+ * \param Comment AST node of any kind.
+ *
+ * \param ChildIdx child index (zero-based).
+ *
+ * \returns the specified child of the AST node.
+ */
+CINDEX_LINKAGE
+CXComment clang_Comment_getChild(CXComment Comment, unsigned ChildIdx);
+
+/**
+ * \brief A \c CXComment_Paragraph node is considered whitespace if it contains
+ * only \c CXComment_Text nodes that are empty or whitespace.
+ *
+ * Other AST nodes (except \c CXComment_Paragraph and \c CXComment_Text) are
+ * never considered whitespace.
+ *
+ * \returns non-zero if \c Comment is whitespace.
+ */
+CINDEX_LINKAGE unsigned clang_Comment_isWhitespace(CXComment Comment);
+
+/**
+ * \returns non-zero if \c Comment is inline content and has a newline
+ * immediately following it in the comment text. Newlines between paragraphs
+ * do not count.
+ */
+CINDEX_LINKAGE
+unsigned clang_InlineContentComment_hasTrailingNewline(CXComment Comment);
+
+/**
+ * \param Comment a \c CXComment_Text AST node.
+ *
+ * \returns text contained in the AST node.
+ */
+CINDEX_LINKAGE CXString clang_TextComment_getText(CXComment Comment);
+
+/**
+ * \param Comment a \c CXComment_InlineCommand AST node.
+ *
+ * \returns name of the inline command.
+ */
+CINDEX_LINKAGE
+CXString clang_InlineCommandComment_getCommandName(CXComment Comment);
+
+/**
+ * \param Comment a \c CXComment_InlineCommand AST node.
+ *
+ * \returns the most appropriate rendering mode, chosen on command
+ * semantics in Doxygen.
+ */
+CINDEX_LINKAGE enum CXCommentInlineCommandRenderKind
+clang_InlineCommandComment_getRenderKind(CXComment Comment);
+
+/**
+ * \param Comment a \c CXComment_InlineCommand AST node.
+ *
+ * \returns number of command arguments.
+ */
+CINDEX_LINKAGE
+unsigned clang_InlineCommandComment_getNumArgs(CXComment Comment);
+
+/**
+ * \param Comment a \c CXComment_InlineCommand AST node.
+ *
+ * \param ArgIdx argument index (zero-based).
+ *
+ * \returns text of the specified argument.
+ */
+CINDEX_LINKAGE
+CXString clang_InlineCommandComment_getArgText(CXComment Comment,
+ unsigned ArgIdx);
+
+/**
+ * \param Comment a \c CXComment_HTMLStartTag or \c CXComment_HTMLEndTag AST
+ * node.
+ *
+ * \returns HTML tag name.
+ */
+CINDEX_LINKAGE CXString clang_HTMLTagComment_getTagName(CXComment Comment);
+
+/**
+ * \param Comment a \c CXComment_HTMLStartTag AST node.
+ *
+ * \returns non-zero if tag is self-closing (for example, &lt;br /&gt;).
+ */
+CINDEX_LINKAGE
+unsigned clang_HTMLStartTagComment_isSelfClosing(CXComment Comment);
+
+/**
+ * \param Comment a \c CXComment_HTMLStartTag AST node.
+ *
+ * \returns number of attributes (name-value pairs) attached to the start tag.
+ */
+CINDEX_LINKAGE unsigned clang_HTMLStartTag_getNumAttrs(CXComment Comment);
+
+/**
+ * \param Comment a \c CXComment_HTMLStartTag AST node.
+ *
+ * \param AttrIdx attribute index (zero-based).
+ *
+ * \returns name of the specified attribute.
+ */
+CINDEX_LINKAGE
+CXString clang_HTMLStartTag_getAttrName(CXComment Comment, unsigned AttrIdx);
+
+/**
+ * \param Comment a \c CXComment_HTMLStartTag AST node.
+ *
+ * \param AttrIdx attribute index (zero-based).
+ *
+ * \returns value of the specified attribute.
+ */
+CINDEX_LINKAGE
+CXString clang_HTMLStartTag_getAttrValue(CXComment Comment, unsigned AttrIdx);
+
+/**
+ * \param Comment a \c CXComment_BlockCommand AST node.
+ *
+ * \returns name of the block command.
+ */
+CINDEX_LINKAGE
+CXString clang_BlockCommandComment_getCommandName(CXComment Comment);
+
+/**
+ * \param Comment a \c CXComment_BlockCommand AST node.
+ *
+ * \returns number of word-like arguments.
+ */
+CINDEX_LINKAGE
+unsigned clang_BlockCommandComment_getNumArgs(CXComment Comment);
+
+/**
+ * \param Comment a \c CXComment_BlockCommand AST node.
+ *
+ * \param ArgIdx argument index (zero-based).
+ *
+ * \returns text of the specified word-like argument.
+ */
+CINDEX_LINKAGE
+CXString clang_BlockCommandComment_getArgText(CXComment Comment,
+ unsigned ArgIdx);
+
+/**
+ * \param Comment a \c CXComment_BlockCommand or
+ * \c CXComment_VerbatimBlockCommand AST node.
+ *
+ * \returns paragraph argument of the block command.
+ */
+CINDEX_LINKAGE
+CXComment clang_BlockCommandComment_getParagraph(CXComment Comment);
+
+/**
+ * \param Comment a \c CXComment_ParamCommand AST node.
+ *
+ * \returns parameter name.
+ */
+CINDEX_LINKAGE
+CXString clang_ParamCommandComment_getParamName(CXComment Comment);
+
+/**
+ * \param Comment a \c CXComment_ParamCommand AST node.
+ *
+ * \returns non-zero if the parameter that this AST node represents was found
+ * in the function prototype and \c clang_ParamCommandComment_getParamIndex
+ * function will return a meaningful value.
+ */
+CINDEX_LINKAGE
+unsigned clang_ParamCommandComment_isParamIndexValid(CXComment Comment);
+
+/**
+ * \param Comment a \c CXComment_ParamCommand AST node.
+ *
+ * \returns zero-based parameter index in function prototype.
+ */
+CINDEX_LINKAGE
+unsigned clang_ParamCommandComment_getParamIndex(CXComment Comment);
+
+/**
+ * \param Comment a \c CXComment_ParamCommand AST node.
+ *
+ * \returns non-zero if parameter passing direction was specified explicitly in
+ * the comment.
+ */
+CINDEX_LINKAGE
+unsigned clang_ParamCommandComment_isDirectionExplicit(CXComment Comment);
+
+/**
+ * \param Comment a \c CXComment_ParamCommand AST node.
+ *
+ * \returns parameter passing direction.
+ */
+CINDEX_LINKAGE
+enum CXCommentParamPassDirection clang_ParamCommandComment_getDirection(
+ CXComment Comment);
+
+/**
+ * \param Comment a \c CXComment_TParamCommand AST node.
+ *
+ * \returns template parameter name.
+ */
+CINDEX_LINKAGE
+CXString clang_TParamCommandComment_getParamName(CXComment Comment);
+
+/**
+ * \param Comment a \c CXComment_TParamCommand AST node.
+ *
+ * \returns non-zero if the parameter that this AST node represents was found
+ * in the template parameter list and
+ * \c clang_TParamCommandComment_getDepth and
+ * \c clang_TParamCommandComment_getIndex functions will return a meaningful
+ * value.
+ */
+CINDEX_LINKAGE
+unsigned clang_TParamCommandComment_isParamPositionValid(CXComment Comment);
+
+/**
+ * \param Comment a \c CXComment_TParamCommand AST node.
+ *
+ * \returns zero-based nesting depth of this parameter in the template parameter list.
+ *
+ * For example,
+ * \verbatim
+ * template<typename C, template<typename T> class TT>
+ * void test(TT<int> aaa);
+ * \endverbatim
+ * for C and TT nesting depth is 0,
+ * for T nesting depth is 1.
+ */
+CINDEX_LINKAGE
+unsigned clang_TParamCommandComment_getDepth(CXComment Comment);
+
+/**
+ * \param Comment a \c CXComment_TParamCommand AST node.
+ *
+ * \returns zero-based parameter index in the template parameter list at a
+ * given nesting depth.
+ *
+ * For example,
+ * \verbatim
+ * template<typename C, template<typename T> class TT>
+ * void test(TT<int> aaa);
+ * \endverbatim
+ * for C and TT nesting depth is 0, so we can ask for index at depth 0:
+ * at depth 0 C's index is 0, TT's index is 1.
+ *
+ * For T nesting depth is 1, so we can ask for index at depth 0 and 1:
+ * at depth 0 T's index is 1 (same as TT's),
+ * at depth 1 T's index is 0.
+ */
+CINDEX_LINKAGE
+unsigned clang_TParamCommandComment_getIndex(CXComment Comment, unsigned Depth);
+
+/**
+ * \param Comment a \c CXComment_VerbatimBlockLine AST node.
+ *
+ * \returns text contained in the AST node.
+ */
+CINDEX_LINKAGE
+CXString clang_VerbatimBlockLineComment_getText(CXComment Comment);
+
+/**
+ * \param Comment a \c CXComment_VerbatimLine AST node.
+ *
+ * \returns text contained in the AST node.
+ */
+CINDEX_LINKAGE CXString clang_VerbatimLineComment_getText(CXComment Comment);
+
+/**
+ * \brief Convert an HTML tag AST node to string.
+ *
+ * \param Comment a \c CXComment_HTMLStartTag or \c CXComment_HTMLEndTag AST
+ * node.
+ *
+ * \returns string containing an HTML tag.
+ */
+CINDEX_LINKAGE CXString clang_HTMLTagComment_getAsString(CXComment Comment);
+
+/**
+ * \brief Convert a given full parsed comment to an HTML fragment.
+ *
+ * Specific details of HTML layout are subject to change. Don't try to parse
+ * this HTML back into an AST, use other APIs instead.
+ *
+ * Currently the following CSS classes are used:
+ * \li "para-brief" for \\brief paragraph and equivalent commands;
+ * \li "para-returns" for \\returns paragraph and equivalent commands;
+ * \li "word-returns" for the "Returns" word in \\returns paragraph.
+ *
+ * Function argument documentation is rendered as a \<dl\> list with arguments
+ * sorted in function prototype order. CSS classes used:
+ * \li "param-name-index-NUMBER" for parameter name (\<dt\>);
+ * \li "param-descr-index-NUMBER" for parameter description (\<dd\>);
+ * \li "param-name-index-invalid" and "param-descr-index-invalid" are used if
+ * parameter index is invalid.
+ *
+ * Template parameter documentation is rendered as a \<dl\> list with
+ * parameters sorted in template parameter list order. CSS classes used:
+ * \li "tparam-name-index-NUMBER" for parameter name (\<dt\>);
+ * \li "tparam-descr-index-NUMBER" for parameter description (\<dd\>);
+ * \li "tparam-name-index-other" and "tparam-descr-index-other" are used for
+ * names inside template template parameters;
+ * \li "tparam-name-index-invalid" and "tparam-descr-index-invalid" are used if
+ * parameter position is invalid.
+ *
+ * \param Comment a \c CXComment_FullComment AST node.
+ *
+ * \returns string containing an HTML fragment.
+ */
+CINDEX_LINKAGE CXString clang_FullComment_getAsHTML(CXComment Comment);
+
+/**
+ * \brief Convert a given full parsed comment to an XML document.
+ *
+ * A Relax NG schema for the XML can be found in comment-xml-schema.rng file
+ * inside clang source tree.
+ *
+ * \param Comment a \c CXComment_FullComment AST node.
+ *
+ * \returns string containing an XML document.
+ */
+CINDEX_LINKAGE CXString clang_FullComment_getAsXML(CXComment Comment);
+
+/**
+ * @}
+ */
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* CLANG_C_DOCUMENTATION_H */
+
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..09e2160
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang-c/Index.h
@@ -0,0 +1,5835 @@
+/*===-- 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 LLVM_CLANG_C_INDEX_H
+#define LLVM_CLANG_C_INDEX_H
+
+#include <time.h>
+
+#include "clang-c/Platform.h"
+#include "clang-c/CXErrorCode.h"
+#include "clang-c/CXString.h"
+#include "clang-c/BuildSystem.h"
+
+/**
+ * \brief The version constants for the libclang API.
+ * CINDEX_VERSION_MINOR should increase when there are API additions.
+ * CINDEX_VERSION_MAJOR is intended for "major" source/ABI breaking changes.
+ *
+ * The policy about the libclang API was always to keep it source and ABI
+ * compatible, thus CINDEX_VERSION_MAJOR is expected to remain stable.
+ */
+#define CINDEX_VERSION_MAJOR 0
+#define CINDEX_VERSION_MINOR 32
+
+#define CINDEX_VERSION_ENCODE(major, minor) ( \
+ ((major) * 10000) \
+ + ((minor) * 1))
+
+#define CINDEX_VERSION CINDEX_VERSION_ENCODE( \
+ CINDEX_VERSION_MAJOR, \
+ CINDEX_VERSION_MINOR )
+
+#define CINDEX_VERSION_STRINGIZE_(major, minor) \
+ #major"."#minor
+#define CINDEX_VERSION_STRINGIZE(major, minor) \
+ CINDEX_VERSION_STRINGIZE_(major, minor)
+
+#define CINDEX_VERSION_STRING CINDEX_VERSION_STRINGIZE( \
+ CINDEX_VERSION_MAJOR, \
+ CINDEX_VERSION_MINOR)
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/** \defgroup CINDEX libclang: 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,
+ /**
+ * \brief The entity is available, but not accessible; any use of it will be
+ * an error.
+ */
+ CXAvailability_NotAccessible
+};
+
+/**
+ * \brief Describes a version number of the form major.minor.subminor.
+ */
+typedef struct CXVersion {
+ /**
+ * \brief The major version number, e.g., the '10' in '10.7.3'. A negative
+ * value indicates that there is no version number at all.
+ */
+ int Major;
+ /**
+ * \brief The minor version number, e.g., the '7' in '10.7.3'. This value
+ * will be negative if no minor version number was provided, e.g., for
+ * version '10'.
+ */
+ int Minor;
+ /**
+ * \brief The subminor version number, e.g., the '3' in '10.7.3'. This value
+ * will be negative if no minor or subminor version number was provided,
+ * e.g., in version '10' or '10.7'.
+ */
+ int Subminor;
+} CXVersion;
+
+/**
+ * \brief 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:
+ *
+ * \code
+ * // 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);
+ * \endcode
+ *
+ * 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);
+
+typedef enum {
+ /**
+ * \brief Used to indicate that no special CXIndex options are needed.
+ */
+ CXGlobalOpt_None = 0x0,
+
+ /**
+ * \brief Used to indicate that threads that libclang creates for indexing
+ * purposes should use background priority.
+ *
+ * Affects #clang_indexSourceFile, #clang_indexTranslationUnit,
+ * #clang_parseTranslationUnit, #clang_saveTranslationUnit.
+ */
+ CXGlobalOpt_ThreadBackgroundPriorityForIndexing = 0x1,
+
+ /**
+ * \brief Used to indicate that threads that libclang creates for editing
+ * purposes should use background priority.
+ *
+ * Affects #clang_reparseTranslationUnit, #clang_codeCompleteAt,
+ * #clang_annotateTokens
+ */
+ CXGlobalOpt_ThreadBackgroundPriorityForEditing = 0x2,
+
+ /**
+ * \brief Used to indicate that all threads that libclang creates should use
+ * background priority.
+ */
+ CXGlobalOpt_ThreadBackgroundPriorityForAll =
+ CXGlobalOpt_ThreadBackgroundPriorityForIndexing |
+ CXGlobalOpt_ThreadBackgroundPriorityForEditing
+
+} CXGlobalOptFlags;
+
+/**
+ * \brief Sets general options associated with a CXIndex.
+ *
+ * For example:
+ * \code
+ * CXIndex idx = ...;
+ * clang_CXIndex_setGlobalOptions(idx,
+ * clang_CXIndex_getGlobalOptions(idx) |
+ * CXGlobalOpt_ThreadBackgroundPriorityForIndexing);
+ * \endcode
+ *
+ * \param options A bitmask of options, a bitwise OR of CXGlobalOpt_XXX flags.
+ */
+CINDEX_LINKAGE void clang_CXIndex_setGlobalOptions(CXIndex, unsigned options);
+
+/**
+ * \brief Gets the general options associated with a CXIndex.
+ *
+ * \returns A bitmask of options, a bitwise OR of CXGlobalOpt_XXX flags that
+ * are associated with the given CXIndex object.
+ */
+CINDEX_LINKAGE unsigned clang_CXIndex_getGlobalOptions(CXIndex);
+
+/**
+ * \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 Uniquely identifies a CXFile, that refers to the same underlying file,
+ * across an indexing session.
+ */
+typedef struct {
+ unsigned long long data[3];
+} CXFileUniqueID;
+
+/**
+ * \brief Retrieve the unique ID for the given \c file.
+ *
+ * \param file the file to get the ID for.
+ * \param outID stores the returned CXFileUniqueID.
+ * \returns If there was a failure getting the unique ID, returns non-zero,
+ * otherwise returns 0.
+*/
+CINDEX_LINKAGE int clang_getFileUniqueID(CXFile file, CXFileUniqueID *outID);
+
+/**
+ * \brief Determine whether the given header is guarded against
+ * multiple inclusions, either with the conventional
+ * \#ifndef/\#define/\#endif macro guards or with \#pragma once.
+ */
+CINDEX_LINKAGE unsigned
+clang_isFileMultipleIncludeGuarded(CXTranslationUnit tu, CXFile file);
+
+/**
+ * \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);
+
+/**
+ * \brief Returns non-zero if the \c file1 and \c file2 point to the same file,
+ * or they are both NULL.
+ */
+CINDEX_LINKAGE int clang_File_isEqual(CXFile file1, CXFile file2);
+
+/**
+ * @}
+ */
+
+/**
+ * \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_getExpansionLocation() or clang_getSpellingLocation()
+ * to map a source location to a particular file, line, and column.
+ */
+typedef struct {
+ const 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 {
+ const 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(void);
+
+/**
+ * \brief 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 Returns non-zero if the given source location is in a system header.
+ */
+CINDEX_LINKAGE int clang_Location_isInSystemHeader(CXSourceLocation location);
+
+/**
+ * \brief Returns non-zero if the given source location is in the main file of
+ * the corresponding translation unit.
+ */
+CINDEX_LINKAGE int clang_Location_isFromMainFile(CXSourceLocation location);
+
+/**
+ * \brief Retrieve a NULL (invalid) source range.
+ */
+CINDEX_LINKAGE CXSourceRange clang_getNullRange(void);
+
+/**
+ * \brief Retrieve a source range given the beginning and ending source
+ * locations.
+ */
+CINDEX_LINKAGE CXSourceRange clang_getRange(CXSourceLocation begin,
+ CXSourceLocation end);
+
+/**
+ * \brief Determine whether two ranges are equivalent.
+ *
+ * \returns non-zero if the ranges are the same, zero if they differ.
+ */
+CINDEX_LINKAGE unsigned clang_equalRanges(CXSourceRange range1,
+ CXSourceRange range2);
+
+/**
+ * \brief Returns non-zero if \p range is null.
+ */
+CINDEX_LINKAGE int clang_Range_isNull(CXSourceRange range);
+
+/**
+ * \brief Retrieve the file, line, column, and offset represented by
+ * the given source location.
+ *
+ * If the location refers into a macro expansion, retrieves the
+ * location of the macro expansion.
+ *
+ * \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_getExpansionLocation(CXSourceLocation location,
+ CXFile *file,
+ unsigned *line,
+ unsigned *column,
+ unsigned *offset);
+
+/**
+ * \brief Retrieve the file, line, column, and offset represented by
+ * the given source location, as specified in a # line directive.
+ *
+ * Example: given the following source code in a file somefile.c
+ *
+ * \code
+ * #123 "dummy.c" 1
+ *
+ * static int func(void)
+ * {
+ * return 0;
+ * }
+ * \endcode
+ *
+ * the location information returned by this function would be
+ *
+ * File: dummy.c Line: 124 Column: 12
+ *
+ * whereas clang_getExpansionLocation would have returned
+ *
+ * File: somefile.c Line: 3 Column: 12
+ *
+ * \param location the location within a source file that will be decomposed
+ * into its parts.
+ *
+ * \param filename [out] if non-NULL, will be set to the filename of the
+ * source location. Note that filenames returned will be for "virtual" files,
+ * which don't necessarily exist on the machine running clang - e.g. when
+ * parsing preprocessed output obtained from a different environment. If
+ * a non-NULL value is passed in, remember to dispose of the returned value
+ * using \c clang_disposeString() once you've finished with it. For an invalid
+ * source location, an empty string is returned.
+ *
+ * \param line [out] if non-NULL, will be set to the line number of the
+ * source location. For an invalid source location, zero is returned.
+ *
+ * \param column [out] if non-NULL, will be set to the column number of the
+ * source location. For an invalid source location, zero is returned.
+ */
+CINDEX_LINKAGE void clang_getPresumedLocation(CXSourceLocation location,
+ CXString *filename,
+ unsigned *line,
+ unsigned *column);
+
+/**
+ * \brief Legacy API to retrieve the file, line, column, and offset represented
+ * by the given source location.
+ *
+ * This interface has been replaced by the newer interface
+ * #clang_getExpansionLocation(). See that interface's documentation for
+ * details.
+ */
+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 the file, line, column, and offset represented by
+ * the given source location.
+ *
+ * If the location refers into a macro expansion, return where the macro was
+ * expanded or where the macro argument was written, if the location points at
+ * a macro argument.
+ *
+ * \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_getFileLocation(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);
+
+/**
+ * \brief Identifies an array of ranges.
+ */
+typedef struct {
+ /** \brief The number of ranges in the \c ranges array. */
+ unsigned count;
+ /**
+ * \brief An array of \c CXSourceRanges.
+ */
+ CXSourceRange *ranges;
+} CXSourceRangeList;
+
+/**
+ * \brief Retrieve all ranges that were skipped by the preprocessor.
+ *
+ * The preprocessor will skip lines when they are surrounded by an
+ * if/ifdef/ifndef directive whose condition does not evaluate to true.
+ */
+CINDEX_LINKAGE CXSourceRangeList *clang_getSkippedRanges(CXTranslationUnit tu,
+ CXFile file);
+
+/**
+ * \brief Destroy the given \c CXSourceRangeList.
+ */
+CINDEX_LINKAGE void clang_disposeSourceRangeList(CXSourceRangeList *ranges);
+
+/**
+ * @}
+ */
+
+/**
+ * \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 A group of CXDiagnostics.
+ */
+typedef void *CXDiagnosticSet;
+
+/**
+ * \brief Determine the number of diagnostics in a CXDiagnosticSet.
+ */
+CINDEX_LINKAGE unsigned clang_getNumDiagnosticsInSet(CXDiagnosticSet Diags);
+
+/**
+ * \brief Retrieve a diagnostic associated with the given CXDiagnosticSet.
+ *
+ * \param Diags the CXDiagnosticSet 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_getDiagnosticInSet(CXDiagnosticSet Diags,
+ unsigned Index);
+
+/**
+ * \brief Describes the kind of error that occurred (if any) in a call to
+ * \c clang_loadDiagnostics.
+ */
+enum CXLoadDiag_Error {
+ /**
+ * \brief Indicates that no error occurred.
+ */
+ CXLoadDiag_None = 0,
+
+ /**
+ * \brief Indicates that an unknown error occurred while attempting to
+ * deserialize diagnostics.
+ */
+ CXLoadDiag_Unknown = 1,
+
+ /**
+ * \brief Indicates that the file containing the serialized diagnostics
+ * could not be opened.
+ */
+ CXLoadDiag_CannotLoad = 2,
+
+ /**
+ * \brief Indicates that the serialized diagnostics file is invalid or
+ * corrupt.
+ */
+ CXLoadDiag_InvalidFile = 3
+};
+
+/**
+ * \brief Deserialize a set of diagnostics from a Clang diagnostics bitcode
+ * file.
+ *
+ * \param file The name of the file to deserialize.
+ * \param error A pointer to a enum value recording if there was a problem
+ * deserializing the diagnostics.
+ * \param errorString A pointer to a CXString for recording the error string
+ * if the file was not successfully loaded.
+ *
+ * \returns A loaded CXDiagnosticSet if successful, and NULL otherwise. These
+ * diagnostics should be released using clang_disposeDiagnosticSet().
+ */
+CINDEX_LINKAGE CXDiagnosticSet clang_loadDiagnostics(const char *file,
+ enum CXLoadDiag_Error *error,
+ CXString *errorString);
+
+/**
+ * \brief Release a CXDiagnosticSet and all of its contained diagnostics.
+ */
+CINDEX_LINKAGE void clang_disposeDiagnosticSet(CXDiagnosticSet Diags);
+
+/**
+ * \brief Retrieve the child diagnostics of a CXDiagnostic.
+ *
+ * This CXDiagnosticSet does not need to be released by
+ * clang_disposeDiagnosticSet.
+ */
+CINDEX_LINKAGE CXDiagnosticSet clang_getChildDiagnostics(CXDiagnostic D);
+
+/**
+ * \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 Retrieve the complete set of diagnostics associated with a
+ * translation unit.
+ *
+ * \param Unit the translation unit to query.
+ */
+CINDEX_LINKAGE CXDiagnosticSet
+ clang_getDiagnosticSetFromTU(CXTranslationUnit Unit);
+
+/**
+ * \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_formatDiagnostic().
+ */
+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_formatDiagnostic().
+ */
+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. This
+ * is now deprecated. Use clang_getDiagnosticCategoryText()
+ * instead.
+ *
+ * \param Category A diagnostic category number, as returned by
+ * \c clang_getDiagnosticCategory().
+ *
+ * \returns The name of the given diagnostic category.
+ */
+CINDEX_DEPRECATED CINDEX_LINKAGE
+CXString clang_getDiagnosticCategoryName(unsigned Category);
+
+/**
+ * \brief Retrieve the diagnostic category text for a given diagnostic.
+ *
+ * \returns The text of the given diagnostic category.
+ */
+CINDEX_LINKAGE CXString clang_getDiagnosticCategoryText(CXDiagnostic);
+
+/**
+ * \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', '-fsyntax-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 Same as \c clang_createTranslationUnit2, but returns
+ * the \c CXTranslationUnit instead of an error code. In case of an error this
+ * routine returns a \c NULL \c CXTranslationUnit, without further detailed
+ * error codes.
+ */
+CINDEX_LINKAGE CXTranslationUnit clang_createTranslationUnit(
+ CXIndex CIdx,
+ const char *ast_filename);
+
+/**
+ * \brief Create a translation unit from an AST file (\c -emit-ast).
+ *
+ * \param[out] out_TU A non-NULL pointer to store the created
+ * \c CXTranslationUnit.
+ *
+ * \returns Zero on success, otherwise returns an error code.
+ */
+CINDEX_LINKAGE enum CXErrorCode clang_createTranslationUnit2(
+ CXIndex CIdx,
+ const char *ast_filename,
+ CXTranslationUnit *out_TU);
+
+/**
+ * \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 Used to indicate that the translation unit will be serialized with
+ * \c clang_saveTranslationUnit.
+ *
+ * This option is typically used when parsing a header with the intent of
+ * producing a precompiled header.
+ */
+ CXTranslationUnit_ForSerialization = 0x10,
+
+ /**
+ * \brief DEPRECATED: Enabled chained precompiled preambles in C++.
+ *
+ * Note: this is a *temporary* option that is available only while
+ * we are testing C++ precompiled preamble support. It is deprecated.
+ */
+ CXTranslationUnit_CXXChainedPCH = 0x20,
+
+ /**
+ * \brief Used to indicate that function/method bodies should be skipped while
+ * parsing.
+ *
+ * This option can be used to search for declarations/definitions while
+ * ignoring the usages.
+ */
+ CXTranslationUnit_SkipFunctionBodies = 0x40,
+
+ /**
+ * \brief Used to indicate that brief documentation comments should be
+ * included into the set of code completions returned from this translation
+ * unit.
+ */
+ CXTranslationUnit_IncludeBriefCommentsInCodeCompletion = 0x80,
+
+ /**
+ * \brief Used to indicate that the precompiled preamble should be created on
+ * the first parse. Otherwise it will be created on the first reparse. This
+ * trades runtime on the first parse (serializing the preamble takes time) for
+ * reduced runtime on the second parse (can now reuse the preamble).
+ */
+ CXTranslationUnit_CreatePreambleOnFirstParse = 0x100
+};
+
+/**
+ * \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 Same as \c clang_parseTranslationUnit2, but returns
+ * the \c CXTranslationUnit instead of an error code. In case of an error this
+ * routine returns a \c NULL \c CXTranslationUnit, without further detailed
+ * error codes.
+ */
+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 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 \c 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', '-fsyntax-only' (which is the default), and '-o \<output file>'.
+ *
+ * \param num_command_line_args The number of command-line arguments in
+ * \c 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.
+ *
+ * \param[out] out_TU A non-NULL pointer to store the created
+ * \c CXTranslationUnit, describing the parsed code and containing any
+ * diagnostics produced by the compiler.
+ *
+ * \returns Zero on success, otherwise returns an error code.
+ */
+CINDEX_LINKAGE enum CXErrorCode
+clang_parseTranslationUnit2(CXIndex CIdx,
+ const char *source_filename,
+ const char *const *command_line_args,
+ int num_command_line_args,
+ struct CXUnsavedFile *unsaved_files,
+ unsigned num_unsaved_files,
+ unsigned options,
+ CXTranslationUnit *out_TU);
+
+/**
+ * \brief Same as clang_parseTranslationUnit2 but requires a full command line
+ * for \c command_line_args including argv[0]. This is useful if the standard
+ * library paths are relative to the binary.
+ */
+CINDEX_LINKAGE enum CXErrorCode clang_parseTranslationUnit2FullArgv(
+ CXIndex CIdx, const char *source_filename,
+ const char *const *command_line_args, int num_command_line_args,
+ struct CXUnsavedFile *unsaved_files, unsigned num_unsaved_files,
+ unsigned options, CXTranslationUnit *out_TU);
+
+/**
+ * \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 Describes the kind of error that occurred (if any) in a call to
+ * \c clang_saveTranslationUnit().
+ */
+enum CXSaveError {
+ /**
+ * \brief Indicates that no error occurred while saving a translation unit.
+ */
+ CXSaveError_None = 0,
+
+ /**
+ * \brief Indicates that an unknown error occurred while attempting to save
+ * the file.
+ *
+ * This error typically indicates that file I/O failed when attempting to
+ * write the file.
+ */
+ CXSaveError_Unknown = 1,
+
+ /**
+ * \brief Indicates that errors during translation prevented this attempt
+ * to save the translation unit.
+ *
+ * Errors that prevent the translation unit from being saved can be
+ * extracted using \c clang_getNumDiagnostics() and \c clang_getDiagnostic().
+ */
+ CXSaveError_TranslationErrors = 2,
+
+ /**
+ * \brief Indicates that the translation unit to be saved was somehow
+ * invalid (e.g., NULL).
+ */
+ CXSaveError_InvalidTU = 3
+};
+
+/**
+ * \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 A value that will match one of the enumerators of the CXSaveError
+ * enumeration. Zero (CXSaveError_None) indicates that the translation unit was
+ * saved successfully, while a non-zero value indicates that a problem occurred.
+ */
+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 error code will be
+ * returned if reparsing was impossible, such that the translation unit is
+ * invalid. In such cases, the only valid call for \c TU is
+ * \c clang_disposeTranslationUnit(TU). The error codes returned by this
+ * routine are described by the \c CXErrorCode enum.
+ */
+CINDEX_LINKAGE int clang_reparseTranslationUnit(CXTranslationUnit TU,
+ unsigned num_unsaved_files,
+ struct CXUnsavedFile *unsaved_files,
+ unsigned options);
+
+/**
+ * \brief Categorizes how memory is being used by a translation unit.
+ */
+enum CXTUResourceUsageKind {
+ CXTUResourceUsage_AST = 1,
+ CXTUResourceUsage_Identifiers = 2,
+ CXTUResourceUsage_Selectors = 3,
+ CXTUResourceUsage_GlobalCompletionResults = 4,
+ CXTUResourceUsage_SourceManagerContentCache = 5,
+ CXTUResourceUsage_AST_SideTables = 6,
+ CXTUResourceUsage_SourceManager_Membuffer_Malloc = 7,
+ CXTUResourceUsage_SourceManager_Membuffer_MMap = 8,
+ CXTUResourceUsage_ExternalASTSource_Membuffer_Malloc = 9,
+ CXTUResourceUsage_ExternalASTSource_Membuffer_MMap = 10,
+ CXTUResourceUsage_Preprocessor = 11,
+ CXTUResourceUsage_PreprocessingRecord = 12,
+ CXTUResourceUsage_SourceManager_DataStructures = 13,
+ CXTUResourceUsage_Preprocessor_HeaderSearch = 14,
+ CXTUResourceUsage_MEMORY_IN_BYTES_BEGIN = CXTUResourceUsage_AST,
+ CXTUResourceUsage_MEMORY_IN_BYTES_END =
+ CXTUResourceUsage_Preprocessor_HeaderSearch,
+
+ CXTUResourceUsage_First = CXTUResourceUsage_AST,
+ CXTUResourceUsage_Last = CXTUResourceUsage_Preprocessor_HeaderSearch
+};
+
+/**
+ * \brief Returns the human-readable null-terminated C string that represents
+ * the name of the memory category. This string should never be freed.
+ */
+CINDEX_LINKAGE
+const char *clang_getTUResourceUsageName(enum CXTUResourceUsageKind kind);
+
+typedef struct CXTUResourceUsageEntry {
+ /* \brief The memory usage category. */
+ enum CXTUResourceUsageKind kind;
+ /* \brief Amount of resources used.
+ The units will depend on the resource kind. */
+ unsigned long amount;
+} CXTUResourceUsageEntry;
+
+/**
+ * \brief The memory usage of a CXTranslationUnit, broken into categories.
+ */
+typedef struct CXTUResourceUsage {
+ /* \brief Private data member, used for queries. */
+ void *data;
+
+ /* \brief The number of entries in the 'entries' array. */
+ unsigned numEntries;
+
+ /* \brief An array of key-value pairs, representing the breakdown of memory
+ usage. */
+ CXTUResourceUsageEntry *entries;
+
+} CXTUResourceUsage;
+
+/**
+ * \brief Return the memory usage of a translation unit. This object
+ * should be released with clang_disposeCXTUResourceUsage().
+ */
+CINDEX_LINKAGE CXTUResourceUsage clang_getCXTUResourceUsage(CXTranslationUnit TU);
+
+CINDEX_LINKAGE void clang_disposeCXTUResourceUsage(CXTUResourceUsage usage);
+
+/**
+ * @}
+ */
+
+/**
+ * \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 C++ using declaration. */
+ CXCursor_UsingDeclaration = 35,
+ /** \brief A C++ alias declaration */
+ CXCursor_TypeAliasDecl = 36,
+ /** \brief An Objective-C \@synthesize definition. */
+ CXCursor_ObjCSynthesizeDecl = 37,
+ /** \brief An Objective-C \@dynamic definition. */
+ CXCursor_ObjCDynamicDecl = 38,
+ /** \brief An access specifier. */
+ CXCursor_CXXAccessSpecifier = 39,
+
+ CXCursor_FirstDecl = CXCursor_UnexposedDecl,
+ CXCursor_LastDecl = CXCursor_CXXAccessSpecifier,
+
+ /* 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,
+
+ /**
+ * \brief A reference to a variable that occurs in some non-expression
+ * context, e.g., a C++ lambda capture list.
+ */
+ CXCursor_VariableRef = 50,
+
+ CXCursor_LastRef = CXCursor_VariableRef,
+
+ /* 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, variable, 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,
+
+ /** \brief An integer literal.
+ */
+ CXCursor_IntegerLiteral = 106,
+
+ /** \brief A floating point number literal.
+ */
+ CXCursor_FloatingLiteral = 107,
+
+ /** \brief An imaginary number literal.
+ */
+ CXCursor_ImaginaryLiteral = 108,
+
+ /** \brief A string literal.
+ */
+ CXCursor_StringLiteral = 109,
+
+ /** \brief A character literal.
+ */
+ CXCursor_CharacterLiteral = 110,
+
+ /** \brief A parenthesized expression, e.g. "(1)".
+ *
+ * This AST node is only formed if full location information is requested.
+ */
+ CXCursor_ParenExpr = 111,
+
+ /** \brief This represents the unary-expression's (except sizeof and
+ * alignof).
+ */
+ CXCursor_UnaryOperator = 112,
+
+ /** \brief [C99 6.5.2.1] Array Subscripting.
+ */
+ CXCursor_ArraySubscriptExpr = 113,
+
+ /** \brief A builtin binary operation expression such as "x + y" or
+ * "x <= y".
+ */
+ CXCursor_BinaryOperator = 114,
+
+ /** \brief Compound assignment such as "+=".
+ */
+ CXCursor_CompoundAssignOperator = 115,
+
+ /** \brief The ?: ternary operator.
+ */
+ CXCursor_ConditionalOperator = 116,
+
+ /** \brief 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: (int)f.
+ */
+ CXCursor_CStyleCastExpr = 117,
+
+ /** \brief [C99 6.5.2.5]
+ */
+ CXCursor_CompoundLiteralExpr = 118,
+
+ /** \brief Describes an C or C++ initializer list.
+ */
+ CXCursor_InitListExpr = 119,
+
+ /** \brief The GNU address of label extension, representing &&label.
+ */
+ CXCursor_AddrLabelExpr = 120,
+
+ /** \brief This is the GNU Statement Expression extension: ({int X=4; X;})
+ */
+ CXCursor_StmtExpr = 121,
+
+ /** \brief Represents a C11 generic selection.
+ */
+ CXCursor_GenericSelectionExpr = 122,
+
+ /** \brief 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).
+ */
+ CXCursor_GNUNullExpr = 123,
+
+ /** \brief C++'s static_cast<> expression.
+ */
+ CXCursor_CXXStaticCastExpr = 124,
+
+ /** \brief C++'s dynamic_cast<> expression.
+ */
+ CXCursor_CXXDynamicCastExpr = 125,
+
+ /** \brief C++'s reinterpret_cast<> expression.
+ */
+ CXCursor_CXXReinterpretCastExpr = 126,
+
+ /** \brief C++'s const_cast<> expression.
+ */
+ CXCursor_CXXConstCastExpr = 127,
+
+ /** \brief Represents an explicit C++ type conversion that uses "functional"
+ * notion (C++ [expr.type.conv]).
+ *
+ * Example:
+ * \code
+ * x = int(0.5);
+ * \endcode
+ */
+ CXCursor_CXXFunctionalCastExpr = 128,
+
+ /** \brief A C++ typeid expression (C++ [expr.typeid]).
+ */
+ CXCursor_CXXTypeidExpr = 129,
+
+ /** \brief [C++ 2.13.5] C++ Boolean Literal.
+ */
+ CXCursor_CXXBoolLiteralExpr = 130,
+
+ /** \brief [C++0x 2.14.7] C++ Pointer Literal.
+ */
+ CXCursor_CXXNullPtrLiteralExpr = 131,
+
+ /** \brief Represents the "this" expression in C++
+ */
+ CXCursor_CXXThisExpr = 132,
+
+ /** \brief [C++ 15] C++ Throw Expression.
+ *
+ * This handles 'throw' and 'throw' assignment-expression. When
+ * assignment-expression isn't present, Op will be null.
+ */
+ CXCursor_CXXThrowExpr = 133,
+
+ /** \brief A new expression for memory allocation and constructor calls, e.g:
+ * "new CXXNewExpr(foo)".
+ */
+ CXCursor_CXXNewExpr = 134,
+
+ /** \brief A delete expression for memory deallocation and destructor calls,
+ * e.g. "delete[] pArray".
+ */
+ CXCursor_CXXDeleteExpr = 135,
+
+ /** \brief A unary expression.
+ */
+ CXCursor_UnaryExpr = 136,
+
+ /** \brief An Objective-C string literal i.e. @"foo".
+ */
+ CXCursor_ObjCStringLiteral = 137,
+
+ /** \brief An Objective-C \@encode expression.
+ */
+ CXCursor_ObjCEncodeExpr = 138,
+
+ /** \brief An Objective-C \@selector expression.
+ */
+ CXCursor_ObjCSelectorExpr = 139,
+
+ /** \brief An Objective-C \@protocol expression.
+ */
+ CXCursor_ObjCProtocolExpr = 140,
+
+ /** \brief An Objective-C "bridged" cast expression, which casts between
+ * Objective-C pointers and C pointers, transferring ownership in the process.
+ *
+ * \code
+ * NSString *str = (__bridge_transfer NSString *)CFCreateString();
+ * \endcode
+ */
+ CXCursor_ObjCBridgedCastExpr = 141,
+
+ /** \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
+ */
+ CXCursor_PackExpansionExpr = 142,
+
+ /** \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
+ */
+ CXCursor_SizeOfPackExpr = 143,
+
+ /* \brief Represents a C++ lambda expression that produces a local function
+ * object.
+ *
+ * \code
+ * void abssort(float *x, unsigned N) {
+ * std::sort(x, x + N,
+ * [](float a, float b) {
+ * return std::abs(a) < std::abs(b);
+ * });
+ * }
+ * \endcode
+ */
+ CXCursor_LambdaExpr = 144,
+
+ /** \brief Objective-c Boolean Literal.
+ */
+ CXCursor_ObjCBoolLiteralExpr = 145,
+
+ /** \brief Represents the "self" expression in an Objective-C method.
+ */
+ CXCursor_ObjCSelfExpr = 146,
+
+ /** \brief OpenMP 4.0 [2.4, Array Section].
+ */
+ CXCursor_OMPArraySectionExpr = 147,
+
+ CXCursor_LastExpr = CXCursor_OMPArraySectionExpr,
+
+ /* 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,
+
+ /** \brief A group of statements like { stmt stmt }.
+ *
+ * This cursor kind is used to describe compound statements, e.g. function
+ * bodies.
+ */
+ CXCursor_CompoundStmt = 202,
+
+ /** \brief A case statement.
+ */
+ CXCursor_CaseStmt = 203,
+
+ /** \brief A default statement.
+ */
+ CXCursor_DefaultStmt = 204,
+
+ /** \brief An if statement
+ */
+ CXCursor_IfStmt = 205,
+
+ /** \brief A switch statement.
+ */
+ CXCursor_SwitchStmt = 206,
+
+ /** \brief A while statement.
+ */
+ CXCursor_WhileStmt = 207,
+
+ /** \brief A do statement.
+ */
+ CXCursor_DoStmt = 208,
+
+ /** \brief A for statement.
+ */
+ CXCursor_ForStmt = 209,
+
+ /** \brief A goto statement.
+ */
+ CXCursor_GotoStmt = 210,
+
+ /** \brief An indirect goto statement.
+ */
+ CXCursor_IndirectGotoStmt = 211,
+
+ /** \brief A continue statement.
+ */
+ CXCursor_ContinueStmt = 212,
+
+ /** \brief A break statement.
+ */
+ CXCursor_BreakStmt = 213,
+
+ /** \brief A return statement.
+ */
+ CXCursor_ReturnStmt = 214,
+
+ /** \brief A GCC inline assembly statement extension.
+ */
+ CXCursor_GCCAsmStmt = 215,
+ CXCursor_AsmStmt = CXCursor_GCCAsmStmt,
+
+ /** \brief Objective-C's overall \@try-\@catch-\@finally statement.
+ */
+ CXCursor_ObjCAtTryStmt = 216,
+
+ /** \brief Objective-C's \@catch statement.
+ */
+ CXCursor_ObjCAtCatchStmt = 217,
+
+ /** \brief Objective-C's \@finally statement.
+ */
+ CXCursor_ObjCAtFinallyStmt = 218,
+
+ /** \brief Objective-C's \@throw statement.
+ */
+ CXCursor_ObjCAtThrowStmt = 219,
+
+ /** \brief Objective-C's \@synchronized statement.
+ */
+ CXCursor_ObjCAtSynchronizedStmt = 220,
+
+ /** \brief Objective-C's autorelease pool statement.
+ */
+ CXCursor_ObjCAutoreleasePoolStmt = 221,
+
+ /** \brief Objective-C's collection statement.
+ */
+ CXCursor_ObjCForCollectionStmt = 222,
+
+ /** \brief C++'s catch statement.
+ */
+ CXCursor_CXXCatchStmt = 223,
+
+ /** \brief C++'s try statement.
+ */
+ CXCursor_CXXTryStmt = 224,
+
+ /** \brief C++'s for (* : *) statement.
+ */
+ CXCursor_CXXForRangeStmt = 225,
+
+ /** \brief Windows Structured Exception Handling's try statement.
+ */
+ CXCursor_SEHTryStmt = 226,
+
+ /** \brief Windows Structured Exception Handling's except statement.
+ */
+ CXCursor_SEHExceptStmt = 227,
+
+ /** \brief Windows Structured Exception Handling's finally statement.
+ */
+ CXCursor_SEHFinallyStmt = 228,
+
+ /** \brief A MS inline assembly statement extension.
+ */
+ CXCursor_MSAsmStmt = 229,
+
+ /** \brief The null statement ";": C99 6.8.3p3.
+ *
+ * This cursor kind is used to describe the null statement.
+ */
+ CXCursor_NullStmt = 230,
+
+ /** \brief Adaptor class for mixing declarations with statements and
+ * expressions.
+ */
+ CXCursor_DeclStmt = 231,
+
+ /** \brief OpenMP parallel directive.
+ */
+ CXCursor_OMPParallelDirective = 232,
+
+ /** \brief OpenMP SIMD directive.
+ */
+ CXCursor_OMPSimdDirective = 233,
+
+ /** \brief OpenMP for directive.
+ */
+ CXCursor_OMPForDirective = 234,
+
+ /** \brief OpenMP sections directive.
+ */
+ CXCursor_OMPSectionsDirective = 235,
+
+ /** \brief OpenMP section directive.
+ */
+ CXCursor_OMPSectionDirective = 236,
+
+ /** \brief OpenMP single directive.
+ */
+ CXCursor_OMPSingleDirective = 237,
+
+ /** \brief OpenMP parallel for directive.
+ */
+ CXCursor_OMPParallelForDirective = 238,
+
+ /** \brief OpenMP parallel sections directive.
+ */
+ CXCursor_OMPParallelSectionsDirective = 239,
+
+ /** \brief OpenMP task directive.
+ */
+ CXCursor_OMPTaskDirective = 240,
+
+ /** \brief OpenMP master directive.
+ */
+ CXCursor_OMPMasterDirective = 241,
+
+ /** \brief OpenMP critical directive.
+ */
+ CXCursor_OMPCriticalDirective = 242,
+
+ /** \brief OpenMP taskyield directive.
+ */
+ CXCursor_OMPTaskyieldDirective = 243,
+
+ /** \brief OpenMP barrier directive.
+ */
+ CXCursor_OMPBarrierDirective = 244,
+
+ /** \brief OpenMP taskwait directive.
+ */
+ CXCursor_OMPTaskwaitDirective = 245,
+
+ /** \brief OpenMP flush directive.
+ */
+ CXCursor_OMPFlushDirective = 246,
+
+ /** \brief Windows Structured Exception Handling's leave statement.
+ */
+ CXCursor_SEHLeaveStmt = 247,
+
+ /** \brief OpenMP ordered directive.
+ */
+ CXCursor_OMPOrderedDirective = 248,
+
+ /** \brief OpenMP atomic directive.
+ */
+ CXCursor_OMPAtomicDirective = 249,
+
+ /** \brief OpenMP for SIMD directive.
+ */
+ CXCursor_OMPForSimdDirective = 250,
+
+ /** \brief OpenMP parallel for SIMD directive.
+ */
+ CXCursor_OMPParallelForSimdDirective = 251,
+
+ /** \brief OpenMP target directive.
+ */
+ CXCursor_OMPTargetDirective = 252,
+
+ /** \brief OpenMP teams directive.
+ */
+ CXCursor_OMPTeamsDirective = 253,
+
+ /** \brief OpenMP taskgroup directive.
+ */
+ CXCursor_OMPTaskgroupDirective = 254,
+
+ /** \brief OpenMP cancellation point directive.
+ */
+ CXCursor_OMPCancellationPointDirective = 255,
+
+ /** \brief OpenMP cancel directive.
+ */
+ CXCursor_OMPCancelDirective = 256,
+
+ /** \brief OpenMP target data directive.
+ */
+ CXCursor_OMPTargetDataDirective = 257,
+
+ /** \brief OpenMP taskloop directive.
+ */
+ CXCursor_OMPTaskLoopDirective = 258,
+
+ /** \brief OpenMP taskloop simd directive.
+ */
+ CXCursor_OMPTaskLoopSimdDirective = 259,
+
+ /** \brief OpenMP distribute directive.
+ */
+ CXCursor_OMPDistributeDirective = 260,
+
+ CXCursor_LastStmt = CXCursor_OMPDistributeDirective,
+
+ /**
+ * \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_CXXFinalAttr = 404,
+ CXCursor_CXXOverrideAttr = 405,
+ CXCursor_AnnotateAttr = 406,
+ CXCursor_AsmLabelAttr = 407,
+ CXCursor_PackedAttr = 408,
+ CXCursor_PureAttr = 409,
+ CXCursor_ConstAttr = 410,
+ CXCursor_NoDuplicateAttr = 411,
+ CXCursor_CUDAConstantAttr = 412,
+ CXCursor_CUDADeviceAttr = 413,
+ CXCursor_CUDAGlobalAttr = 414,
+ CXCursor_CUDAHostAttr = 415,
+ CXCursor_CUDASharedAttr = 416,
+ CXCursor_VisibilityAttr = 417,
+ CXCursor_DLLExport = 418,
+ CXCursor_DLLImport = 419,
+ CXCursor_LastAttr = CXCursor_DLLImport,
+
+ /* Preprocessing */
+ CXCursor_PreprocessingDirective = 500,
+ CXCursor_MacroDefinition = 501,
+ CXCursor_MacroExpansion = 502,
+ CXCursor_MacroInstantiation = CXCursor_MacroExpansion,
+ CXCursor_InclusionDirective = 503,
+ CXCursor_FirstPreprocessing = CXCursor_PreprocessingDirective,
+ CXCursor_LastPreprocessing = CXCursor_InclusionDirective,
+
+ /* Extra Declarations */
+ /**
+ * \brief A module import declaration.
+ */
+ CXCursor_ModuleImportDecl = 600,
+ CXCursor_TypeAliasTemplateDecl = 601,
+ CXCursor_FirstExtraDecl = CXCursor_ModuleImportDecl,
+ CXCursor_LastExtraDecl = CXCursor_TypeAliasTemplateDecl,
+
+ /**
+ * \brief A code completion overload candidate.
+ */
+ CXCursor_OverloadCandidate = 700
+};
+
+/**
+ * \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;
+ int xdata;
+ const 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 Returns non-zero if \p cursor is null.
+ */
+CINDEX_LINKAGE int clang_Cursor_isNull(CXCursor cursor);
+
+/**
+ * \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 attribute.
+ */
+CINDEX_LINKAGE unsigned clang_isAttribute(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);
+
+enum CXVisibilityKind {
+ /** \brief This value indicates that no visibility information is available
+ * for a provided CXCursor. */
+ CXVisibility_Invalid,
+
+ /** \brief Symbol not seen by the linker. */
+ CXVisibility_Hidden,
+ /** \brief Symbol seen by the linker but resolves to a symbol inside this object. */
+ CXVisibility_Protected,
+ /** \brief Symbol seen by the linker and acts like a normal symbol. */
+ CXVisibility_Default
+};
+
+/**
+ * \brief Describe the visibility of the entity referred to by a cursor.
+ *
+ * This returns the default visibility if not explicitly specified by
+ * a visibility attribute. The default visibility may be changed by
+ * commandline arguments.
+ *
+ * \param cursor The cursor to query.
+ *
+ * \returns The visibility of the cursor.
+ */
+CINDEX_LINKAGE enum CXVisibilityKind clang_getCursorVisibility(CXCursor cursor);
+
+/**
+ * \brief Determine the availability of the entity that this cursor refers to,
+ * taking the current target platform into account.
+ *
+ * \param cursor The cursor to query.
+ *
+ * \returns The availability of the cursor.
+ */
+CINDEX_LINKAGE enum CXAvailabilityKind
+clang_getCursorAvailability(CXCursor cursor);
+
+/**
+ * Describes the availability of a given entity on a particular platform, e.g.,
+ * a particular class might only be available on Mac OS 10.7 or newer.
+ */
+typedef struct CXPlatformAvailability {
+ /**
+ * \brief A string that describes the platform for which this structure
+ * provides availability information.
+ *
+ * Possible values are "ios" or "macosx".
+ */
+ CXString Platform;
+ /**
+ * \brief The version number in which this entity was introduced.
+ */
+ CXVersion Introduced;
+ /**
+ * \brief The version number in which this entity was deprecated (but is
+ * still available).
+ */
+ CXVersion Deprecated;
+ /**
+ * \brief The version number in which this entity was obsoleted, and therefore
+ * is no longer available.
+ */
+ CXVersion Obsoleted;
+ /**
+ * \brief Whether the entity is unconditionally unavailable on this platform.
+ */
+ int Unavailable;
+ /**
+ * \brief An optional message to provide to a user of this API, e.g., to
+ * suggest replacement APIs.
+ */
+ CXString Message;
+} CXPlatformAvailability;
+
+/**
+ * \brief Determine the availability of the entity that this cursor refers to
+ * on any platforms for which availability information is known.
+ *
+ * \param cursor The cursor to query.
+ *
+ * \param always_deprecated If non-NULL, will be set to indicate whether the
+ * entity is deprecated on all platforms.
+ *
+ * \param deprecated_message If non-NULL, will be set to the message text
+ * provided along with the unconditional deprecation of this entity. The client
+ * is responsible for deallocating this string.
+ *
+ * \param always_unavailable If non-NULL, will be set to indicate whether the
+ * entity is unavailable on all platforms.
+ *
+ * \param unavailable_message If non-NULL, will be set to the message text
+ * provided along with the unconditional unavailability of this entity. The
+ * client is responsible for deallocating this string.
+ *
+ * \param availability If non-NULL, an array of CXPlatformAvailability instances
+ * that will be populated with platform availability information, up to either
+ * the number of platforms for which availability information is available (as
+ * returned by this function) or \c availability_size, whichever is smaller.
+ *
+ * \param availability_size The number of elements available in the
+ * \c availability array.
+ *
+ * \returns The number of platforms (N) for which availability information is
+ * available (which is unrelated to \c availability_size).
+ *
+ * Note that the client is responsible for calling
+ * \c clang_disposeCXPlatformAvailability to free each of the
+ * platform-availability structures returned. There are
+ * \c min(N, availability_size) such structures.
+ */
+CINDEX_LINKAGE int
+clang_getCursorPlatformAvailability(CXCursor cursor,
+ int *always_deprecated,
+ CXString *deprecated_message,
+ int *always_unavailable,
+ CXString *unavailable_message,
+ CXPlatformAvailability *availability,
+ int availability_size);
+
+/**
+ * \brief Free the memory associated with a \c CXPlatformAvailability structure.
+ */
+CINDEX_LINKAGE void
+clang_disposeCXPlatformAvailability(CXPlatformAvailability *availability);
+
+/**
+ * \brief Describe the "language" of the entity referred to by a cursor.
+ */
+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 Returns the translation unit that a cursor originated from.
+ */
+CINDEX_LINKAGE CXTranslationUnit clang_Cursor_getTranslationUnit(CXCursor);
+
+/**
+ * \brief A fast container representing a set of CXCursors.
+ */
+typedef struct CXCursorSetImpl *CXCursorSet;
+
+/**
+ * \brief Creates an empty CXCursorSet.
+ */
+CINDEX_LINKAGE CXCursorSet clang_createCXCursorSet(void);
+
+/**
+ * \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 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 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
+ * base class, its protocols, or its categories' protocols, 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. A method from an Objective-C
+ * implementation is considered to override the same methods as its
+ * corresponding method in the interface.
+ *
+ * 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 within 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 Represents 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,
+ CXType_ConstantArray = 112,
+ CXType_Vector = 113,
+ CXType_IncompleteArray = 114,
+ CXType_VariableArray = 115,
+ CXType_DependentSizedArray = 116,
+ CXType_MemberPointer = 117,
+ CXType_Auto = 118
+};
+
+/**
+ * \brief Describes the calling convention of a function type
+ */
+enum CXCallingConv {
+ CXCallingConv_Default = 0,
+ CXCallingConv_C = 1,
+ CXCallingConv_X86StdCall = 2,
+ CXCallingConv_X86FastCall = 3,
+ CXCallingConv_X86ThisCall = 4,
+ CXCallingConv_X86Pascal = 5,
+ CXCallingConv_AAPCS = 6,
+ CXCallingConv_AAPCS_VFP = 7,
+ /* Value 8 was PnaclCall, but it was never used, so it could safely be re-used. */
+ CXCallingConv_IntelOclBicc = 9,
+ CXCallingConv_X86_64Win64 = 10,
+ CXCallingConv_X86_64SysV = 11,
+ CXCallingConv_X86VectorCall = 12,
+
+ CXCallingConv_Invalid = 100,
+ CXCallingConv_Unexposed = 200
+};
+
+/**
+ * \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);
+
+/**
+ * \brief Pretty-print the underlying type using the rules of the
+ * language of the translation unit from which it came.
+ *
+ * If the type is invalid, an empty string is returned.
+ */
+CINDEX_LINKAGE CXString clang_getTypeSpelling(CXType CT);
+
+/**
+ * \brief Retrieve the underlying type of a typedef declaration.
+ *
+ * If the cursor does not reference a typedef declaration, an invalid type is
+ * returned.
+ */
+CINDEX_LINKAGE CXType clang_getTypedefDeclUnderlyingType(CXCursor C);
+
+/**
+ * \brief Retrieve the integer type of an enum declaration.
+ *
+ * If the cursor does not reference an enum declaration, an invalid type is
+ * returned.
+ */
+CINDEX_LINKAGE CXType clang_getEnumDeclIntegerType(CXCursor C);
+
+/**
+ * \brief Retrieve the integer value of an enum constant declaration as a signed
+ * long long.
+ *
+ * If the cursor does not reference an enum constant declaration, LLONG_MIN is returned.
+ * Since this is also potentially a valid constant value, the kind of the cursor
+ * must be verified before calling this function.
+ */
+CINDEX_LINKAGE long long clang_getEnumConstantDeclValue(CXCursor C);
+
+/**
+ * \brief Retrieve the integer value of an enum constant declaration as an unsigned
+ * long long.
+ *
+ * If the cursor does not reference an enum constant declaration, ULLONG_MAX is returned.
+ * Since this is also potentially a valid constant value, the kind of the cursor
+ * must be verified before calling this function.
+ */
+CINDEX_LINKAGE unsigned long long clang_getEnumConstantDeclUnsignedValue(CXCursor C);
+
+/**
+ * \brief Retrieve the bit width of a bit field declaration as an integer.
+ *
+ * If a cursor that is not a bit field declaration is passed in, -1 is returned.
+ */
+CINDEX_LINKAGE int clang_getFieldDeclBitWidth(CXCursor C);
+
+/**
+ * \brief Retrieve the number of non-variadic arguments associated with a given
+ * cursor.
+ *
+ * The number of arguments can be determined for calls as well as for
+ * declarations of functions or methods. For other cursors -1 is returned.
+ */
+CINDEX_LINKAGE int clang_Cursor_getNumArguments(CXCursor C);
+
+/**
+ * \brief Retrieve the argument cursor of a function or method.
+ *
+ * The argument cursor can be determined for calls as well as for declarations
+ * of functions or methods. For other cursors and for invalid indices, an
+ * invalid cursor is returned.
+ */
+CINDEX_LINKAGE CXCursor clang_Cursor_getArgument(CXCursor C, unsigned i);
+
+/**
+ * \brief Describes the kind of a template argument.
+ *
+ * See the definition of llvm::clang::TemplateArgument::ArgKind for full
+ * element descriptions.
+ */
+enum CXTemplateArgumentKind {
+ CXTemplateArgumentKind_Null,
+ CXTemplateArgumentKind_Type,
+ CXTemplateArgumentKind_Declaration,
+ CXTemplateArgumentKind_NullPtr,
+ CXTemplateArgumentKind_Integral,
+ CXTemplateArgumentKind_Template,
+ CXTemplateArgumentKind_TemplateExpansion,
+ CXTemplateArgumentKind_Expression,
+ CXTemplateArgumentKind_Pack,
+ /* Indicates an error case, preventing the kind from being deduced. */
+ CXTemplateArgumentKind_Invalid
+};
+
+/**
+ *\brief Returns the number of template args of a function decl representing a
+ * template specialization.
+ *
+ * If the argument cursor cannot be converted into a template function
+ * declaration, -1 is returned.
+ *
+ * For example, for the following declaration and specialization:
+ * template <typename T, int kInt, bool kBool>
+ * void foo() { ... }
+ *
+ * template <>
+ * void foo<float, -7, true>();
+ *
+ * The value 3 would be returned from this call.
+ */
+CINDEX_LINKAGE int clang_Cursor_getNumTemplateArguments(CXCursor C);
+
+/**
+ * \brief Retrieve the kind of the I'th template argument of the CXCursor C.
+ *
+ * If the argument CXCursor does not represent a FunctionDecl, an invalid
+ * template argument kind is returned.
+ *
+ * For example, for the following declaration and specialization:
+ * template <typename T, int kInt, bool kBool>
+ * void foo() { ... }
+ *
+ * template <>
+ * void foo<float, -7, true>();
+ *
+ * For I = 0, 1, and 2, Type, Integral, and Integral will be returned,
+ * respectively.
+ */
+CINDEX_LINKAGE enum CXTemplateArgumentKind clang_Cursor_getTemplateArgumentKind(
+ CXCursor C, unsigned I);
+
+/**
+ * \brief Retrieve a CXType representing the type of a TemplateArgument of a
+ * function decl representing a template specialization.
+ *
+ * If the argument CXCursor does not represent a FunctionDecl whose I'th
+ * template argument has a kind of CXTemplateArgKind_Integral, an invalid type
+ * is returned.
+ *
+ * For example, for the following declaration and specialization:
+ * template <typename T, int kInt, bool kBool>
+ * void foo() { ... }
+ *
+ * template <>
+ * void foo<float, -7, true>();
+ *
+ * If called with I = 0, "float", will be returned.
+ * Invalid types will be returned for I == 1 or 2.
+ */
+CINDEX_LINKAGE CXType clang_Cursor_getTemplateArgumentType(CXCursor C,
+ unsigned I);
+
+/**
+ * \brief Retrieve the value of an Integral TemplateArgument (of a function
+ * decl representing a template specialization) as a signed long long.
+ *
+ * It is undefined to call this function on a CXCursor that does not represent a
+ * FunctionDecl or whose I'th template argument is not an integral value.
+ *
+ * For example, for the following declaration and specialization:
+ * template <typename T, int kInt, bool kBool>
+ * void foo() { ... }
+ *
+ * template <>
+ * void foo<float, -7, true>();
+ *
+ * If called with I = 1 or 2, -7 or true will be returned, respectively.
+ * For I == 0, this function's behavior is undefined.
+ */
+CINDEX_LINKAGE long long clang_Cursor_getTemplateArgumentValue(CXCursor C,
+ unsigned I);
+
+/**
+ * \brief Retrieve the value of an Integral TemplateArgument (of a function
+ * decl representing a template specialization) as an unsigned long long.
+ *
+ * It is undefined to call this function on a CXCursor that does not represent a
+ * FunctionDecl or whose I'th template argument is not an integral value.
+ *
+ * For example, for the following declaration and specialization:
+ * template <typename T, int kInt, bool kBool>
+ * void foo() { ... }
+ *
+ * template <>
+ * void foo<float, 2147483649, true>();
+ *
+ * If called with I = 1 or 2, 2147483649 or true will be returned, respectively.
+ * For I == 0, this function's behavior is undefined.
+ */
+CINDEX_LINKAGE unsigned long long clang_Cursor_getTemplateArgumentUnsignedValue(
+ CXCursor C, unsigned I);
+
+/**
+ * \brief 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);
+
+/**
+ * \brief 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);
+
+/**
+ * \brief 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);
+
+/**
+ * \brief 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 calling convention associated with a function type.
+ *
+ * If a non-function type is passed in, CXCallingConv_Invalid is returned.
+ */
+CINDEX_LINKAGE enum CXCallingConv clang_getFunctionTypeCallingConv(CXType T);
+
+/**
+ * \brief Retrieve the return type associated with a function type.
+ *
+ * If a non-function type is passed in, an invalid type is returned.
+ */
+CINDEX_LINKAGE CXType clang_getResultType(CXType T);
+
+/**
+ * \brief Retrieve the number of non-variadic parameters associated with a
+ * function type.
+ *
+ * If a non-function type is passed in, -1 is returned.
+ */
+CINDEX_LINKAGE int clang_getNumArgTypes(CXType T);
+
+/**
+ * \brief Retrieve the type of a parameter of a function type.
+ *
+ * If a non-function type is passed in or the function does not have enough
+ * parameters, an invalid type is returned.
+ */
+CINDEX_LINKAGE CXType clang_getArgType(CXType T, unsigned i);
+
+/**
+ * \brief Return 1 if the CXType is a variadic function type, and 0 otherwise.
+ */
+CINDEX_LINKAGE unsigned clang_isFunctionTypeVariadic(CXType T);
+
+/**
+ * \brief Retrieve the return type associated with a given cursor.
+ *
+ * This only returns a valid type if 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 Return the element type of an array, complex, or vector type.
+ *
+ * If a type is passed in that is not an array, complex, or vector type,
+ * an invalid type is returned.
+ */
+CINDEX_LINKAGE CXType clang_getElementType(CXType T);
+
+/**
+ * \brief Return the number of elements of an array or vector type.
+ *
+ * If a type is passed in that is not an array or vector type,
+ * -1 is returned.
+ */
+CINDEX_LINKAGE long long clang_getNumElements(CXType T);
+
+/**
+ * \brief Return the element type of an array type.
+ *
+ * If a non-array type is passed in, an invalid type is returned.
+ */
+CINDEX_LINKAGE CXType clang_getArrayElementType(CXType T);
+
+/**
+ * \brief Return the array size of a constant array.
+ *
+ * If a non-array type is passed in, -1 is returned.
+ */
+CINDEX_LINKAGE long long clang_getArraySize(CXType T);
+
+/**
+ * \brief List the possible error codes for \c clang_Type_getSizeOf,
+ * \c clang_Type_getAlignOf, \c clang_Type_getOffsetOf and
+ * \c clang_Cursor_getOffsetOf.
+ *
+ * A value of this enumeration type can be returned if the target type is not
+ * a valid argument to sizeof, alignof or offsetof.
+ */
+enum CXTypeLayoutError {
+ /**
+ * \brief Type is of kind CXType_Invalid.
+ */
+ CXTypeLayoutError_Invalid = -1,
+ /**
+ * \brief The type is an incomplete Type.
+ */
+ CXTypeLayoutError_Incomplete = -2,
+ /**
+ * \brief The type is a dependent Type.
+ */
+ CXTypeLayoutError_Dependent = -3,
+ /**
+ * \brief The type is not a constant size type.
+ */
+ CXTypeLayoutError_NotConstantSize = -4,
+ /**
+ * \brief The Field name is not valid for this record.
+ */
+ CXTypeLayoutError_InvalidFieldName = -5
+};
+
+/**
+ * \brief Return the alignment of a type in bytes as per C++[expr.alignof]
+ * standard.
+ *
+ * If the type declaration is invalid, CXTypeLayoutError_Invalid is returned.
+ * If the type declaration is an incomplete type, CXTypeLayoutError_Incomplete
+ * is returned.
+ * If the type declaration is a dependent type, CXTypeLayoutError_Dependent is
+ * returned.
+ * If the type declaration is not a constant size type,
+ * CXTypeLayoutError_NotConstantSize is returned.
+ */
+CINDEX_LINKAGE long long clang_Type_getAlignOf(CXType T);
+
+/**
+ * \brief Return the class type of an member pointer type.
+ *
+ * If a non-member-pointer type is passed in, an invalid type is returned.
+ */
+CINDEX_LINKAGE CXType clang_Type_getClassType(CXType T);
+
+/**
+ * \brief Return the size of a type in bytes as per C++[expr.sizeof] standard.
+ *
+ * If the type declaration is invalid, CXTypeLayoutError_Invalid is returned.
+ * If the type declaration is an incomplete type, CXTypeLayoutError_Incomplete
+ * is returned.
+ * If the type declaration is a dependent type, CXTypeLayoutError_Dependent is
+ * returned.
+ */
+CINDEX_LINKAGE long long clang_Type_getSizeOf(CXType T);
+
+/**
+ * \brief Return the offset of a field named S in a record of type T in bits
+ * as it would be returned by __offsetof__ as per C++11[18.2p4]
+ *
+ * If the cursor is not a record field declaration, CXTypeLayoutError_Invalid
+ * is returned.
+ * If the field's type declaration is an incomplete type,
+ * CXTypeLayoutError_Incomplete is returned.
+ * If the field's type declaration is a dependent type,
+ * CXTypeLayoutError_Dependent is returned.
+ * If the field's name S is not found,
+ * CXTypeLayoutError_InvalidFieldName is returned.
+ */
+CINDEX_LINKAGE long long clang_Type_getOffsetOf(CXType T, const char *S);
+
+/**
+ * \brief Return the offset of the field represented by the Cursor.
+ *
+ * If the cursor is not a field declaration, -1 is returned.
+ * If the cursor semantic parent is not a record field declaration,
+ * CXTypeLayoutError_Invalid is returned.
+ * If the field's type declaration is an incomplete type,
+ * CXTypeLayoutError_Incomplete is returned.
+ * If the field's type declaration is a dependent type,
+ * CXTypeLayoutError_Dependent is returned.
+ * If the field's name S is not found,
+ * CXTypeLayoutError_InvalidFieldName is returned.
+ */
+CINDEX_LINKAGE long long clang_Cursor_getOffsetOfField(CXCursor C);
+
+/**
+ * \brief Determine whether the given cursor represents an anonymous record
+ * declaration.
+ */
+CINDEX_LINKAGE unsigned clang_Cursor_isAnonymous(CXCursor C);
+
+enum CXRefQualifierKind {
+ /** \brief No ref-qualifier was provided. */
+ CXRefQualifier_None = 0,
+ /** \brief An lvalue ref-qualifier was provided (\c &). */
+ CXRefQualifier_LValue,
+ /** \brief An rvalue ref-qualifier was provided (\c &&). */
+ CXRefQualifier_RValue
+};
+
+/**
+ * \brief Returns the number of template arguments for given class template
+ * specialization, or -1 if type \c T is not a class template specialization.
+ *
+ * Variadic argument packs count as only one argument, and can not be inspected
+ * further.
+ */
+CINDEX_LINKAGE int clang_Type_getNumTemplateArguments(CXType T);
+
+/**
+ * \brief Returns the type template argument of a template class specialization
+ * at given index.
+ *
+ * This function only returns template type arguments and does not handle
+ * template template arguments or variadic packs.
+ */
+CINDEX_LINKAGE CXType clang_Type_getTemplateArgumentAsType(CXType T, unsigned i);
+
+/**
+ * \brief Retrieve the ref-qualifier kind of a function or method.
+ *
+ * The ref-qualifier is returned for C++ functions or methods. For other types
+ * or non-C++ declarations, CXRefQualifier_None is returned.
+ */
+CINDEX_LINKAGE enum CXRefQualifierKind clang_Type_getCXXRefQualifier(CXType T);
+
+/**
+ * \brief Returns non-zero if the cursor specifies a Record member that is a
+ * bitfield.
+ */
+CINDEX_LINKAGE unsigned clang_Cursor_isBitField(CXCursor C);
+
+/**
+ * \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 referenced object.
+ *
+ * If the cursor refers to a C++ declaration, its access control level within its
+ * parent scope is returned. Otherwise, if the cursor refers to a base specifier or
+ * access specifier, the specifier itself is returned.
+ */
+CINDEX_LINKAGE enum CX_CXXAccessSpecifier clang_getCXXAccessSpecifier(CXCursor);
+
+/**
+ * \brief Represents the storage classes as declared in the source. CX_SC_Invalid
+ * was added for the case that the passed cursor in not a declaration.
+ */
+enum CX_StorageClass {
+ CX_SC_Invalid,
+ CX_SC_None,
+ CX_SC_Extern,
+ CX_SC_Static,
+ CX_SC_PrivateExtern,
+ CX_SC_OpenCLWorkGroupLocal,
+ CX_SC_Auto,
+ CX_SC_Register
+};
+
+/**
+ * \brief Returns the storage class for a function or variable declaration.
+ *
+ * If the passed in Cursor is not a function or variable declaration,
+ * CX_SC_Invalid is returned else the storage class.
+ */
+CINDEX_LINKAGE enum CX_StorageClass clang_Cursor_getStorageClass(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 a range for a piece that forms the cursors spelling name.
+ * Most of the times there is only one range for the complete spelling but for
+ * Objective-C methods and Objective-C message expressions, there are multiple
+ * pieces for each selector identifier.
+ *
+ * \param pieceIndex the index of the spelling name piece. If this is greater
+ * than the actual number of pieces, it will return a NULL (invalid) range.
+ *
+ * \param options Reserved.
+ */
+CINDEX_LINKAGE CXSourceRange clang_Cursor_getSpellingNameRange(CXCursor,
+ unsigned pieceIndex,
+ unsigned options);
+
+/**
+ * \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);
+
+/**
+ * \brief If the cursor points to a selector identifier in an Objective-C
+ * method or message expression, this returns the selector index.
+ *
+ * After getting a cursor with #clang_getCursor, this can be called to
+ * determine if the location points to a selector identifier.
+ *
+ * \returns The selector index if the cursor is an Objective-C method or message
+ * expression and the cursor is pointing to a selector identifier, or -1
+ * otherwise.
+ */
+CINDEX_LINKAGE int clang_Cursor_getObjCSelectorIndex(CXCursor);
+
+/**
+ * \brief Given a cursor pointing to a C++ method call or an Objective-C
+ * message, returns non-zero if the method/message is "dynamic", meaning:
+ *
+ * For a C++ method: the call is virtual.
+ * For an Objective-C message: the receiver is an object instance, not 'super'
+ * or a specific class.
+ *
+ * If the method/message is "static" or the cursor does not point to a
+ * method/message, it will return zero.
+ */
+CINDEX_LINKAGE int clang_Cursor_isDynamicCall(CXCursor C);
+
+/**
+ * \brief Given a cursor pointing to an Objective-C message, returns the CXType
+ * of the receiver.
+ */
+CINDEX_LINKAGE CXType clang_Cursor_getReceiverType(CXCursor C);
+
+/**
+ * \brief Property attributes for a \c CXCursor_ObjCPropertyDecl.
+ */
+typedef enum {
+ CXObjCPropertyAttr_noattr = 0x00,
+ CXObjCPropertyAttr_readonly = 0x01,
+ CXObjCPropertyAttr_getter = 0x02,
+ CXObjCPropertyAttr_assign = 0x04,
+ CXObjCPropertyAttr_readwrite = 0x08,
+ CXObjCPropertyAttr_retain = 0x10,
+ CXObjCPropertyAttr_copy = 0x20,
+ CXObjCPropertyAttr_nonatomic = 0x40,
+ CXObjCPropertyAttr_setter = 0x80,
+ CXObjCPropertyAttr_atomic = 0x100,
+ CXObjCPropertyAttr_weak = 0x200,
+ CXObjCPropertyAttr_strong = 0x400,
+ CXObjCPropertyAttr_unsafe_unretained = 0x800
+} CXObjCPropertyAttrKind;
+
+/**
+ * \brief Given a cursor that represents a property declaration, return the
+ * associated property attributes. The bits are formed from
+ * \c CXObjCPropertyAttrKind.
+ *
+ * \param reserved Reserved for future use, pass 0.
+ */
+CINDEX_LINKAGE unsigned clang_Cursor_getObjCPropertyAttributes(CXCursor C,
+ unsigned reserved);
+
+/**
+ * \brief 'Qualifiers' written next to the return and parameter types in
+ * Objective-C method declarations.
+ */
+typedef enum {
+ CXObjCDeclQualifier_None = 0x0,
+ CXObjCDeclQualifier_In = 0x1,
+ CXObjCDeclQualifier_Inout = 0x2,
+ CXObjCDeclQualifier_Out = 0x4,
+ CXObjCDeclQualifier_Bycopy = 0x8,
+ CXObjCDeclQualifier_Byref = 0x10,
+ CXObjCDeclQualifier_Oneway = 0x20
+} CXObjCDeclQualifierKind;
+
+/**
+ * \brief Given a cursor that represents an Objective-C method or parameter
+ * declaration, return the associated Objective-C qualifiers for the return
+ * type or the parameter respectively. The bits are formed from
+ * CXObjCDeclQualifierKind.
+ */
+CINDEX_LINKAGE unsigned clang_Cursor_getObjCDeclQualifiers(CXCursor C);
+
+/**
+ * \brief Given a cursor that represents an Objective-C method or property
+ * declaration, return non-zero if the declaration was affected by "@optional".
+ * Returns zero if the cursor is not such a declaration or it is "@required".
+ */
+CINDEX_LINKAGE unsigned clang_Cursor_isObjCOptional(CXCursor C);
+
+/**
+ * \brief Returns non-zero if the given cursor is a variadic function or method.
+ */
+CINDEX_LINKAGE unsigned clang_Cursor_isVariadic(CXCursor C);
+
+/**
+ * \brief Given a cursor that represents a declaration, return the associated
+ * comment's source range. The range may include multiple consecutive comments
+ * with whitespace in between.
+ */
+CINDEX_LINKAGE CXSourceRange clang_Cursor_getCommentRange(CXCursor C);
+
+/**
+ * \brief Given a cursor that represents a declaration, return the associated
+ * comment text, including comment markers.
+ */
+CINDEX_LINKAGE CXString clang_Cursor_getRawCommentText(CXCursor C);
+
+/**
+ * \brief Given a cursor that represents a documentable entity (e.g.,
+ * declaration), return the associated \\brief paragraph; otherwise return the
+ * first paragraph.
+ */
+CINDEX_LINKAGE CXString clang_Cursor_getBriefCommentText(CXCursor C);
+
+/**
+ * @}
+ */
+
+/** \defgroup CINDEX_MANGLE Name Mangling API Functions
+ *
+ * @{
+ */
+
+/**
+ * \brief Retrieve the CXString representing the mangled name of the cursor.
+ */
+CINDEX_LINKAGE CXString clang_Cursor_getMangling(CXCursor);
+
+/**
+ * \brief Retrieve the CXStrings representing the mangled symbols of the C++
+ * constructor or destructor at the cursor.
+ */
+CINDEX_LINKAGE CXStringSet *clang_Cursor_getCXXManglings(CXCursor);
+
+/**
+ * @}
+ */
+
+/**
+ * \defgroup CINDEX_MODULE Module introspection
+ *
+ * The functions in this group provide access to information about modules.
+ *
+ * @{
+ */
+
+typedef void *CXModule;
+
+/**
+ * \brief Given a CXCursor_ModuleImportDecl cursor, return the associated module.
+ */
+CINDEX_LINKAGE CXModule clang_Cursor_getModule(CXCursor C);
+
+/**
+ * \brief Given a CXFile header file, return the module that contains it, if one
+ * exists.
+ */
+CINDEX_LINKAGE CXModule clang_getModuleForFile(CXTranslationUnit, CXFile);
+
+/**
+ * \param Module a module object.
+ *
+ * \returns the module file where the provided module object came from.
+ */
+CINDEX_LINKAGE CXFile clang_Module_getASTFile(CXModule Module);
+
+/**
+ * \param Module a module object.
+ *
+ * \returns the parent of a sub-module or NULL if the given module is top-level,
+ * e.g. for 'std.vector' it will return the 'std' module.
+ */
+CINDEX_LINKAGE CXModule clang_Module_getParent(CXModule Module);
+
+/**
+ * \param Module a module object.
+ *
+ * \returns the name of the module, e.g. for the 'std.vector' sub-module it
+ * will return "vector".
+ */
+CINDEX_LINKAGE CXString clang_Module_getName(CXModule Module);
+
+/**
+ * \param Module a module object.
+ *
+ * \returns the full name of the module, e.g. "std.vector".
+ */
+CINDEX_LINKAGE CXString clang_Module_getFullName(CXModule Module);
+
+/**
+ * \param Module a module object.
+ *
+ * \returns non-zero if the module is a system one.
+ */
+CINDEX_LINKAGE int clang_Module_isSystem(CXModule Module);
+
+/**
+ * \param Module a module object.
+ *
+ * \returns the number of top level headers associated with this module.
+ */
+CINDEX_LINKAGE unsigned clang_Module_getNumTopLevelHeaders(CXTranslationUnit,
+ CXModule Module);
+
+/**
+ * \param Module a module object.
+ *
+ * \param Index top level header index (zero-based).
+ *
+ * \returns the specified top level header associated with the module.
+ */
+CINDEX_LINKAGE
+CXFile clang_Module_getTopLevelHeader(CXTranslationUnit,
+ CXModule Module, unsigned Index);
+
+/**
+ * @}
+ */
+
+/**
+ * \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++ field is declared 'mutable'.
+ */
+CINDEX_LINKAGE unsigned clang_CXXField_isMutable(CXCursor C);
+
+/**
+ * \brief Determine if a C++ member function or member function template is
+ * pure virtual.
+ */
+CINDEX_LINKAGE unsigned clang_CXXMethod_isPureVirtual(CXCursor C);
+
+/**
+ * \brief Determine if a C++ member function or member function template is
+ * declared 'static'.
+ */
+CINDEX_LINKAGE unsigned clang_CXXMethod_isStatic(CXCursor C);
+
+/**
+ * \brief Determine if a C++ member function or member function template is
+ * explicitly declared 'virtual' or if it overrides a virtual method from
+ * one of the base classes.
+ */
+CINDEX_LINKAGE unsigned clang_CXXMethod_isVirtual(CXCursor C);
+
+/**
+ * \brief Determine if a C++ member function or member function template is
+ * declared 'const'.
+ */
+CINDEX_LINKAGE unsigned clang_CXXMethod_isConst(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);
+
+/**
+ * \brief Given a cursor that references something else, return the source range
+ * covering that reference.
+ *
+ * \param C A cursor pointing to a member reference, a declaration reference, or
+ * an operator call.
+ * \param NameFlags A bitset with three independent flags:
+ * CXNameRange_WantQualifier, CXNameRange_WantTemplateArgs, and
+ * CXNameRange_WantSinglePiece.
+ * \param PieceIndex For contiguous names or when passing the flag
+ * CXNameRange_WantSinglePiece, only one piece with index 0 is
+ * available. When the CXNameRange_WantSinglePiece flag is not passed for a
+ * non-contiguous names, this index can be used to retrieve the individual
+ * pieces of the name. See also CXNameRange_WantSinglePiece.
+ *
+ * \returns The piece of the name pointed to by the given cursor. If there is no
+ * name, or if the PieceIndex is out-of-range, a null-cursor will be returned.
+ */
+CINDEX_LINKAGE CXSourceRange clang_getCursorReferenceNameRange(CXCursor C,
+ unsigned NameFlags,
+ unsigned PieceIndex);
+
+enum CXNameRefFlags {
+ /**
+ * \brief Include the nested-name-specifier, e.g. Foo:: in x.Foo::y, in the
+ * range.
+ */
+ CXNameRange_WantQualifier = 0x1,
+
+ /**
+ * \brief Include the explicit template arguments, e.g. \<int> in x.f<int>,
+ * in the range.
+ */
+ CXNameRange_WantTemplateArgs = 0x2,
+
+ /**
+ * \brief If the name is non-contiguous, return the full spanning range.
+ *
+ * Non-contiguous names occur in Objective-C when a selector with two or more
+ * parameters is used, or in C++ when using an operator:
+ * \code
+ * [object doSomething:here withValue:there]; // Objective-C
+ * return some_vector[1]; // C++
+ * \endcode
+ */
+ CXNameRange_WantSinglePiece = 0x4
+};
+
+/**
+ * @}
+ */
+
+/**
+ * \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.
+ */
+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 Retrieve the number of annotations associated with the given
+ * completion string.
+ *
+ * \param completion_string the completion string to query.
+ *
+ * \returns the number of annotations associated with the given completion
+ * string.
+ */
+CINDEX_LINKAGE unsigned
+clang_getCompletionNumAnnotations(CXCompletionString completion_string);
+
+/**
+ * \brief Retrieve the annotation associated with the given completion string.
+ *
+ * \param completion_string the completion string to query.
+ *
+ * \param annotation_number the 0-based index of the annotation of the
+ * completion string.
+ *
+ * \returns annotation string associated with the completion at index
+ * \c annotation_number, or a NULL string if that annotation is not available.
+ */
+CINDEX_LINKAGE CXString
+clang_getCompletionAnnotation(CXCompletionString completion_string,
+ unsigned annotation_number);
+
+/**
+ * \brief Retrieve the parent context of the given completion string.
+ *
+ * The parent context of a completion string is the semantic parent of
+ * the declaration (if any) that the code completion represents. For example,
+ * a code completion for an Objective-C method would have the method's class
+ * or protocol as its context.
+ *
+ * \param completion_string The code completion string whose parent is
+ * being queried.
+ *
+ * \param kind DEPRECATED: always set to CXCursor_NotImplemented if non-NULL.
+ *
+ * \returns The name of the completion parent, e.g., "NSObject" if
+ * the completion string represents a method in the NSObject class.
+ */
+CINDEX_LINKAGE CXString
+clang_getCompletionParent(CXCompletionString completion_string,
+ enum CXCursorKind *kind);
+
+/**
+ * \brief Retrieve the brief documentation comment attached to the declaration
+ * that corresponds to the given completion string.
+ */
+CINDEX_LINKAGE CXString
+clang_getCompletionBriefComment(CXCompletionString completion_string);
+
+/**
+ * \brief Retrieve a completion string for an arbitrary declaration or macro
+ * definition cursor.
+ *
+ * \param cursor The cursor to query.
+ *
+ * \returns A non-context-sensitive completion string for declaration and macro
+ * definition cursors, or NULL for other kinds of cursors.
+ */
+CINDEX_LINKAGE CXCompletionString
+clang_getCursorCompletionString(CXCursor cursor);
+
+/**
+ * \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 Whether to include brief documentation within the set of code
+ * completions returned.
+ */
+ CXCodeComplete_IncludeBriefComments = 0x04
+};
+
+/**
+ * \brief Bits that represent the context under which completion is occurring.
+ *
+ * The enumerators in this enumeration may be bitwise-OR'd together if multiple
+ * contexts are occurring simultaneously.
+ */
+enum CXCompletionContext {
+ /**
+ * \brief The context for completions is unexposed, as only Clang results
+ * should be included. (This is equivalent to having no context bits set.)
+ */
+ CXCompletionContext_Unexposed = 0,
+
+ /**
+ * \brief Completions for any possible type should be included in the results.
+ */
+ CXCompletionContext_AnyType = 1 << 0,
+
+ /**
+ * \brief Completions for any possible value (variables, function calls, etc.)
+ * should be included in the results.
+ */
+ CXCompletionContext_AnyValue = 1 << 1,
+ /**
+ * \brief Completions for values that resolve to an Objective-C object should
+ * be included in the results.
+ */
+ CXCompletionContext_ObjCObjectValue = 1 << 2,
+ /**
+ * \brief Completions for values that resolve to an Objective-C selector
+ * should be included in the results.
+ */
+ CXCompletionContext_ObjCSelectorValue = 1 << 3,
+ /**
+ * \brief Completions for values that resolve to a C++ class type should be
+ * included in the results.
+ */
+ CXCompletionContext_CXXClassTypeValue = 1 << 4,
+
+ /**
+ * \brief Completions for fields of the member being accessed using the dot
+ * operator should be included in the results.
+ */
+ CXCompletionContext_DotMemberAccess = 1 << 5,
+ /**
+ * \brief Completions for fields of the member being accessed using the arrow
+ * operator should be included in the results.
+ */
+ CXCompletionContext_ArrowMemberAccess = 1 << 6,
+ /**
+ * \brief Completions for properties of the Objective-C object being accessed
+ * using the dot operator should be included in the results.
+ */
+ CXCompletionContext_ObjCPropertyAccess = 1 << 7,
+
+ /**
+ * \brief Completions for enum tags should be included in the results.
+ */
+ CXCompletionContext_EnumTag = 1 << 8,
+ /**
+ * \brief Completions for union tags should be included in the results.
+ */
+ CXCompletionContext_UnionTag = 1 << 9,
+ /**
+ * \brief Completions for struct tags should be included in the results.
+ */
+ CXCompletionContext_StructTag = 1 << 10,
+
+ /**
+ * \brief Completions for C++ class names should be included in the results.
+ */
+ CXCompletionContext_ClassTag = 1 << 11,
+ /**
+ * \brief Completions for C++ namespaces and namespace aliases should be
+ * included in the results.
+ */
+ CXCompletionContext_Namespace = 1 << 12,
+ /**
+ * \brief Completions for C++ nested name specifiers should be included in
+ * the results.
+ */
+ CXCompletionContext_NestedNameSpecifier = 1 << 13,
+
+ /**
+ * \brief Completions for Objective-C interfaces (classes) should be included
+ * in the results.
+ */
+ CXCompletionContext_ObjCInterface = 1 << 14,
+ /**
+ * \brief Completions for Objective-C protocols should be included in
+ * the results.
+ */
+ CXCompletionContext_ObjCProtocol = 1 << 15,
+ /**
+ * \brief Completions for Objective-C categories should be included in
+ * the results.
+ */
+ CXCompletionContext_ObjCCategory = 1 << 16,
+ /**
+ * \brief Completions for Objective-C instance messages should be included
+ * in the results.
+ */
+ CXCompletionContext_ObjCInstanceMessage = 1 << 17,
+ /**
+ * \brief Completions for Objective-C class messages should be included in
+ * the results.
+ */
+ CXCompletionContext_ObjCClassMessage = 1 << 18,
+ /**
+ * \brief Completions for Objective-C selector names should be included in
+ * the results.
+ */
+ CXCompletionContext_ObjCSelectorName = 1 << 19,
+
+ /**
+ * \brief Completions for preprocessor macro names should be included in
+ * the results.
+ */
+ CXCompletionContext_MacroName = 1 << 20,
+
+ /**
+ * \brief Natural language completions should be included in the results.
+ */
+ CXCompletionContext_NaturalLanguage = 1 << 21,
+
+ /**
+ * \brief The current context is unknown, so set all contexts.
+ */
+ CXCompletionContext_Unknown = ((1 << 22) - 1)
+};
+
+/**
+ * \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 Results 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);
+
+/**
+ * \brief Determines what completions are appropriate for the context
+ * the given code completion.
+ *
+ * \param Results the code completion results to query
+ *
+ * \returns the kinds of completions that are appropriate for use
+ * along with the given code completion results.
+ */
+CINDEX_LINKAGE
+unsigned long long clang_codeCompleteGetContexts(
+ CXCodeCompleteResults *Results);
+
+/**
+ * \brief Returns the cursor kind for the container for the current code
+ * completion context. The container is only guaranteed to be set for
+ * contexts where a container exists (i.e. member accesses or Objective-C
+ * message sends); if there is not a container, this function will return
+ * CXCursor_InvalidCode.
+ *
+ * \param Results the code completion results to query
+ *
+ * \param IsIncomplete on return, this value will be false if Clang has complete
+ * information about the container. If Clang does not have complete
+ * information, this value will be true.
+ *
+ * \returns the container kind, or CXCursor_InvalidCode if there is not a
+ * container
+ */
+CINDEX_LINKAGE
+enum CXCursorKind clang_codeCompleteGetContainerKind(
+ CXCodeCompleteResults *Results,
+ unsigned *IsIncomplete);
+
+/**
+ * \brief Returns the USR for the container for the current code completion
+ * context. If there is not a container for the current context, this
+ * function will return the empty string.
+ *
+ * \param Results the code completion results to query
+ *
+ * \returns the USR for the container
+ */
+CINDEX_LINKAGE
+CXString clang_codeCompleteGetContainerUSR(CXCodeCompleteResults *Results);
+
+/**
+ * \brief Returns the currently-entered selector for an Objective-C message
+ * send, formatted like "initWithFoo:bar:". Only guaranteed to return a
+ * non-empty string for CXCompletionContext_ObjCInstanceMessage and
+ * CXCompletionContext_ObjCClassMessage.
+ *
+ * \param Results the code completion results to query
+ *
+ * \returns the selector (or partial selector) that has been entered thus far
+ * for an Objective-C message send.
+ */
+CINDEX_LINKAGE
+CXString clang_codeCompleteGetObjCSelector(CXCodeCompleteResults *Results);
+
+/**
+ * @}
+ */
+
+/**
+ * \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(void);
+
+/**
+ * \brief Enable/disable crash recovery.
+ *
+ * \param isEnabled Flag to indicate if crash recovery is enabled. A non-zero
+ * value enables crash recovery, while 0 disables it.
+ */
+CINDEX_LINKAGE void clang_toggleCrashRecovery(unsigned isEnabled);
+
+ /**
+ * \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);
+
+/**
+ * @}
+ */
+
+/** \defgroup CINDEX_REMAPPING Remapping functions
+ *
+ * @{
+ */
+
+/**
+ * \brief A remapping of original source files and their translated files.
+ */
+typedef void *CXRemapping;
+
+/**
+ * \brief Retrieve a remapping.
+ *
+ * \param path the path that contains metadata about remappings.
+ *
+ * \returns the requested remapping. This remapping must be freed
+ * via a call to \c clang_remap_dispose(). Can return NULL if an error occurred.
+ */
+CINDEX_LINKAGE CXRemapping clang_getRemappings(const char *path);
+
+/**
+ * \brief Retrieve a remapping.
+ *
+ * \param filePaths pointer to an array of file paths containing remapping info.
+ *
+ * \param numFiles number of file paths.
+ *
+ * \returns the requested remapping. This remapping must be freed
+ * via a call to \c clang_remap_dispose(). Can return NULL if an error occurred.
+ */
+CINDEX_LINKAGE
+CXRemapping clang_getRemappingsFromFileList(const char **filePaths,
+ unsigned numFiles);
+
+/**
+ * \brief Determine the number of remappings.
+ */
+CINDEX_LINKAGE unsigned clang_remap_getNumFiles(CXRemapping);
+
+/**
+ * \brief Get the original and the associated filename from the remapping.
+ *
+ * \param original If non-NULL, will be set to the original filename.
+ *
+ * \param transformed If non-NULL, will be set to the filename that the original
+ * is associated with.
+ */
+CINDEX_LINKAGE void clang_remap_getFilenames(CXRemapping, unsigned index,
+ CXString *original, CXString *transformed);
+
+/**
+ * \brief Dispose the remapping.
+ */
+CINDEX_LINKAGE void clang_remap_dispose(CXRemapping);
+
+/**
+ * @}
+ */
+
+/** \defgroup CINDEX_HIGH Higher level API functions
+ *
+ * @{
+ */
+
+enum CXVisitorResult {
+ CXVisit_Break,
+ CXVisit_Continue
+};
+
+typedef struct {
+ void *context;
+ enum CXVisitorResult (*visit)(void *context, CXCursor, CXSourceRange);
+} CXCursorAndRangeVisitor;
+
+typedef enum {
+ /**
+ * \brief Function returned successfully.
+ */
+ CXResult_Success = 0,
+ /**
+ * \brief One of the parameters was invalid for the function.
+ */
+ CXResult_Invalid = 1,
+ /**
+ * \brief The function was terminated by a callback (e.g. it returned
+ * CXVisit_Break)
+ */
+ CXResult_VisitBreak = 2
+
+} CXResult;
+
+/**
+ * \brief Find references of a declaration in a specific file.
+ *
+ * \param cursor pointing to a declaration or a reference of one.
+ *
+ * \param file to search for references.
+ *
+ * \param visitor callback that will receive pairs of CXCursor/CXSourceRange for
+ * each reference found.
+ * The CXSourceRange will point inside the file; if the reference is inside
+ * a macro (and not a macro argument) the CXSourceRange will be invalid.
+ *
+ * \returns one of the CXResult enumerators.
+ */
+CINDEX_LINKAGE CXResult clang_findReferencesInFile(CXCursor cursor, CXFile file,
+ CXCursorAndRangeVisitor visitor);
+
+/**
+ * \brief Find #import/#include directives in a specific file.
+ *
+ * \param TU translation unit containing the file to query.
+ *
+ * \param file to search for #import/#include directives.
+ *
+ * \param visitor callback that will receive pairs of CXCursor/CXSourceRange for
+ * each directive found.
+ *
+ * \returns one of the CXResult enumerators.
+ */
+CINDEX_LINKAGE CXResult clang_findIncludesInFile(CXTranslationUnit TU,
+ CXFile file,
+ CXCursorAndRangeVisitor visitor);
+
+#ifdef __has_feature
+# if __has_feature(blocks)
+
+typedef enum CXVisitorResult
+ (^CXCursorAndRangeVisitorBlock)(CXCursor, CXSourceRange);
+
+CINDEX_LINKAGE
+CXResult clang_findReferencesInFileWithBlock(CXCursor, CXFile,
+ CXCursorAndRangeVisitorBlock);
+
+CINDEX_LINKAGE
+CXResult clang_findIncludesInFileWithBlock(CXTranslationUnit, CXFile,
+ CXCursorAndRangeVisitorBlock);
+
+# endif
+#endif
+
+/**
+ * \brief The client's data object that is associated with a CXFile.
+ */
+typedef void *CXIdxClientFile;
+
+/**
+ * \brief The client's data object that is associated with a semantic entity.
+ */
+typedef void *CXIdxClientEntity;
+
+/**
+ * \brief The client's data object that is associated with a semantic container
+ * of entities.
+ */
+typedef void *CXIdxClientContainer;
+
+/**
+ * \brief The client's data object that is associated with an AST file (PCH
+ * or module).
+ */
+typedef void *CXIdxClientASTFile;
+
+/**
+ * \brief Source location passed to index callbacks.
+ */
+typedef struct {
+ void *ptr_data[2];
+ unsigned int_data;
+} CXIdxLoc;
+
+/**
+ * \brief Data for ppIncludedFile callback.
+ */
+typedef struct {
+ /**
+ * \brief Location of '#' in the \#include/\#import directive.
+ */
+ CXIdxLoc hashLoc;
+ /**
+ * \brief Filename as written in the \#include/\#import directive.
+ */
+ const char *filename;
+ /**
+ * \brief The actual file that the \#include/\#import directive resolved to.
+ */
+ CXFile file;
+ int isImport;
+ int isAngled;
+ /**
+ * \brief Non-zero if the directive was automatically turned into a module
+ * import.
+ */
+ int isModuleImport;
+} CXIdxIncludedFileInfo;
+
+/**
+ * \brief Data for IndexerCallbacks#importedASTFile.
+ */
+typedef struct {
+ /**
+ * \brief Top level AST file containing the imported PCH, module or submodule.
+ */
+ CXFile file;
+ /**
+ * \brief The imported module or NULL if the AST file is a PCH.
+ */
+ CXModule module;
+ /**
+ * \brief Location where the file is imported. Applicable only for modules.
+ */
+ CXIdxLoc loc;
+ /**
+ * \brief Non-zero if an inclusion directive was automatically turned into
+ * a module import. Applicable only for modules.
+ */
+ int isImplicit;
+
+} CXIdxImportedASTFileInfo;
+
+typedef enum {
+ CXIdxEntity_Unexposed = 0,
+ CXIdxEntity_Typedef = 1,
+ CXIdxEntity_Function = 2,
+ CXIdxEntity_Variable = 3,
+ CXIdxEntity_Field = 4,
+ CXIdxEntity_EnumConstant = 5,
+
+ CXIdxEntity_ObjCClass = 6,
+ CXIdxEntity_ObjCProtocol = 7,
+ CXIdxEntity_ObjCCategory = 8,
+
+ CXIdxEntity_ObjCInstanceMethod = 9,
+ CXIdxEntity_ObjCClassMethod = 10,
+ CXIdxEntity_ObjCProperty = 11,
+ CXIdxEntity_ObjCIvar = 12,
+
+ CXIdxEntity_Enum = 13,
+ CXIdxEntity_Struct = 14,
+ CXIdxEntity_Union = 15,
+
+ CXIdxEntity_CXXClass = 16,
+ CXIdxEntity_CXXNamespace = 17,
+ CXIdxEntity_CXXNamespaceAlias = 18,
+ CXIdxEntity_CXXStaticVariable = 19,
+ CXIdxEntity_CXXStaticMethod = 20,
+ CXIdxEntity_CXXInstanceMethod = 21,
+ CXIdxEntity_CXXConstructor = 22,
+ CXIdxEntity_CXXDestructor = 23,
+ CXIdxEntity_CXXConversionFunction = 24,
+ CXIdxEntity_CXXTypeAlias = 25,
+ CXIdxEntity_CXXInterface = 26
+
+} CXIdxEntityKind;
+
+typedef enum {
+ CXIdxEntityLang_None = 0,
+ CXIdxEntityLang_C = 1,
+ CXIdxEntityLang_ObjC = 2,
+ CXIdxEntityLang_CXX = 3
+} CXIdxEntityLanguage;
+
+/**
+ * \brief Extra C++ template information for an entity. This can apply to:
+ * CXIdxEntity_Function
+ * CXIdxEntity_CXXClass
+ * CXIdxEntity_CXXStaticMethod
+ * CXIdxEntity_CXXInstanceMethod
+ * CXIdxEntity_CXXConstructor
+ * CXIdxEntity_CXXConversionFunction
+ * CXIdxEntity_CXXTypeAlias
+ */
+typedef enum {
+ CXIdxEntity_NonTemplate = 0,
+ CXIdxEntity_Template = 1,
+ CXIdxEntity_TemplatePartialSpecialization = 2,
+ CXIdxEntity_TemplateSpecialization = 3
+} CXIdxEntityCXXTemplateKind;
+
+typedef enum {
+ CXIdxAttr_Unexposed = 0,
+ CXIdxAttr_IBAction = 1,
+ CXIdxAttr_IBOutlet = 2,
+ CXIdxAttr_IBOutletCollection = 3
+} CXIdxAttrKind;
+
+typedef struct {
+ CXIdxAttrKind kind;
+ CXCursor cursor;
+ CXIdxLoc loc;
+} CXIdxAttrInfo;
+
+typedef struct {
+ CXIdxEntityKind kind;
+ CXIdxEntityCXXTemplateKind templateKind;
+ CXIdxEntityLanguage lang;
+ const char *name;
+ const char *USR;
+ CXCursor cursor;
+ const CXIdxAttrInfo *const *attributes;
+ unsigned numAttributes;
+} CXIdxEntityInfo;
+
+typedef struct {
+ CXCursor cursor;
+} CXIdxContainerInfo;
+
+typedef struct {
+ const CXIdxAttrInfo *attrInfo;
+ const CXIdxEntityInfo *objcClass;
+ CXCursor classCursor;
+ CXIdxLoc classLoc;
+} CXIdxIBOutletCollectionAttrInfo;
+
+typedef enum {
+ CXIdxDeclFlag_Skipped = 0x1
+} CXIdxDeclInfoFlags;
+
+typedef struct {
+ const CXIdxEntityInfo *entityInfo;
+ CXCursor cursor;
+ CXIdxLoc loc;
+ const CXIdxContainerInfo *semanticContainer;
+ /**
+ * \brief Generally same as #semanticContainer but can be different in
+ * cases like out-of-line C++ member functions.
+ */
+ const CXIdxContainerInfo *lexicalContainer;
+ int isRedeclaration;
+ int isDefinition;
+ int isContainer;
+ const CXIdxContainerInfo *declAsContainer;
+ /**
+ * \brief Whether the declaration exists in code or was created implicitly
+ * by the compiler, e.g. implicit Objective-C methods for properties.
+ */
+ int isImplicit;
+ const CXIdxAttrInfo *const *attributes;
+ unsigned numAttributes;
+
+ unsigned flags;
+
+} CXIdxDeclInfo;
+
+typedef enum {
+ CXIdxObjCContainer_ForwardRef = 0,
+ CXIdxObjCContainer_Interface = 1,
+ CXIdxObjCContainer_Implementation = 2
+} CXIdxObjCContainerKind;
+
+typedef struct {
+ const CXIdxDeclInfo *declInfo;
+ CXIdxObjCContainerKind kind;
+} CXIdxObjCContainerDeclInfo;
+
+typedef struct {
+ const CXIdxEntityInfo *base;
+ CXCursor cursor;
+ CXIdxLoc loc;
+} CXIdxBaseClassInfo;
+
+typedef struct {
+ const CXIdxEntityInfo *protocol;
+ CXCursor cursor;
+ CXIdxLoc loc;
+} CXIdxObjCProtocolRefInfo;
+
+typedef struct {
+ const CXIdxObjCProtocolRefInfo *const *protocols;
+ unsigned numProtocols;
+} CXIdxObjCProtocolRefListInfo;
+
+typedef struct {
+ const CXIdxObjCContainerDeclInfo *containerInfo;
+ const CXIdxBaseClassInfo *superInfo;
+ const CXIdxObjCProtocolRefListInfo *protocols;
+} CXIdxObjCInterfaceDeclInfo;
+
+typedef struct {
+ const CXIdxObjCContainerDeclInfo *containerInfo;
+ const CXIdxEntityInfo *objcClass;
+ CXCursor classCursor;
+ CXIdxLoc classLoc;
+ const CXIdxObjCProtocolRefListInfo *protocols;
+} CXIdxObjCCategoryDeclInfo;
+
+typedef struct {
+ const CXIdxDeclInfo *declInfo;
+ const CXIdxEntityInfo *getter;
+ const CXIdxEntityInfo *setter;
+} CXIdxObjCPropertyDeclInfo;
+
+typedef struct {
+ const CXIdxDeclInfo *declInfo;
+ const CXIdxBaseClassInfo *const *bases;
+ unsigned numBases;
+} CXIdxCXXClassDeclInfo;
+
+/**
+ * \brief Data for IndexerCallbacks#indexEntityReference.
+ */
+typedef enum {
+ /**
+ * \brief The entity is referenced directly in user's code.
+ */
+ CXIdxEntityRef_Direct = 1,
+ /**
+ * \brief An implicit reference, e.g. a reference of an Objective-C method
+ * via the dot syntax.
+ */
+ CXIdxEntityRef_Implicit = 2
+} CXIdxEntityRefKind;
+
+/**
+ * \brief Data for IndexerCallbacks#indexEntityReference.
+ */
+typedef struct {
+ CXIdxEntityRefKind kind;
+ /**
+ * \brief Reference cursor.
+ */
+ CXCursor cursor;
+ CXIdxLoc loc;
+ /**
+ * \brief The entity that gets referenced.
+ */
+ const CXIdxEntityInfo *referencedEntity;
+ /**
+ * \brief Immediate "parent" of the reference. For example:
+ *
+ * \code
+ * Foo *var;
+ * \endcode
+ *
+ * The parent of reference of type 'Foo' is the variable 'var'.
+ * For references inside statement bodies of functions/methods,
+ * the parentEntity will be the function/method.
+ */
+ const CXIdxEntityInfo *parentEntity;
+ /**
+ * \brief Lexical container context of the reference.
+ */
+ const CXIdxContainerInfo *container;
+} CXIdxEntityRefInfo;
+
+/**
+ * \brief A group of callbacks used by #clang_indexSourceFile and
+ * #clang_indexTranslationUnit.
+ */
+typedef struct {
+ /**
+ * \brief Called periodically to check whether indexing should be aborted.
+ * Should return 0 to continue, and non-zero to abort.
+ */
+ int (*abortQuery)(CXClientData client_data, void *reserved);
+
+ /**
+ * \brief Called at the end of indexing; passes the complete diagnostic set.
+ */
+ void (*diagnostic)(CXClientData client_data,
+ CXDiagnosticSet, void *reserved);
+
+ CXIdxClientFile (*enteredMainFile)(CXClientData client_data,
+ CXFile mainFile, void *reserved);
+
+ /**
+ * \brief Called when a file gets \#included/\#imported.
+ */
+ CXIdxClientFile (*ppIncludedFile)(CXClientData client_data,
+ const CXIdxIncludedFileInfo *);
+
+ /**
+ * \brief Called when a AST file (PCH or module) gets imported.
+ *
+ * AST files will not get indexed (there will not be callbacks to index all
+ * the entities in an AST file). The recommended action is that, if the AST
+ * file is not already indexed, to initiate a new indexing job specific to
+ * the AST file.
+ */
+ CXIdxClientASTFile (*importedASTFile)(CXClientData client_data,
+ const CXIdxImportedASTFileInfo *);
+
+ /**
+ * \brief Called at the beginning of indexing a translation unit.
+ */
+ CXIdxClientContainer (*startedTranslationUnit)(CXClientData client_data,
+ void *reserved);
+
+ void (*indexDeclaration)(CXClientData client_data,
+ const CXIdxDeclInfo *);
+
+ /**
+ * \brief Called to index a reference of an entity.
+ */
+ void (*indexEntityReference)(CXClientData client_data,
+ const CXIdxEntityRefInfo *);
+
+} IndexerCallbacks;
+
+CINDEX_LINKAGE int clang_index_isEntityObjCContainerKind(CXIdxEntityKind);
+CINDEX_LINKAGE const CXIdxObjCContainerDeclInfo *
+clang_index_getObjCContainerDeclInfo(const CXIdxDeclInfo *);
+
+CINDEX_LINKAGE const CXIdxObjCInterfaceDeclInfo *
+clang_index_getObjCInterfaceDeclInfo(const CXIdxDeclInfo *);
+
+CINDEX_LINKAGE
+const CXIdxObjCCategoryDeclInfo *
+clang_index_getObjCCategoryDeclInfo(const CXIdxDeclInfo *);
+
+CINDEX_LINKAGE const CXIdxObjCProtocolRefListInfo *
+clang_index_getObjCProtocolRefListInfo(const CXIdxDeclInfo *);
+
+CINDEX_LINKAGE const CXIdxObjCPropertyDeclInfo *
+clang_index_getObjCPropertyDeclInfo(const CXIdxDeclInfo *);
+
+CINDEX_LINKAGE const CXIdxIBOutletCollectionAttrInfo *
+clang_index_getIBOutletCollectionAttrInfo(const CXIdxAttrInfo *);
+
+CINDEX_LINKAGE const CXIdxCXXClassDeclInfo *
+clang_index_getCXXClassDeclInfo(const CXIdxDeclInfo *);
+
+/**
+ * \brief For retrieving a custom CXIdxClientContainer attached to a
+ * container.
+ */
+CINDEX_LINKAGE CXIdxClientContainer
+clang_index_getClientContainer(const CXIdxContainerInfo *);
+
+/**
+ * \brief For setting a custom CXIdxClientContainer attached to a
+ * container.
+ */
+CINDEX_LINKAGE void
+clang_index_setClientContainer(const CXIdxContainerInfo *,CXIdxClientContainer);
+
+/**
+ * \brief For retrieving a custom CXIdxClientEntity attached to an entity.
+ */
+CINDEX_LINKAGE CXIdxClientEntity
+clang_index_getClientEntity(const CXIdxEntityInfo *);
+
+/**
+ * \brief For setting a custom CXIdxClientEntity attached to an entity.
+ */
+CINDEX_LINKAGE void
+clang_index_setClientEntity(const CXIdxEntityInfo *, CXIdxClientEntity);
+
+/**
+ * \brief An indexing action/session, to be applied to one or multiple
+ * translation units.
+ */
+typedef void *CXIndexAction;
+
+/**
+ * \brief An indexing action/session, to be applied to one or multiple
+ * translation units.
+ *
+ * \param CIdx The index object with which the index action will be associated.
+ */
+CINDEX_LINKAGE CXIndexAction clang_IndexAction_create(CXIndex CIdx);
+
+/**
+ * \brief Destroy the given index action.
+ *
+ * The index action must not be destroyed until all of the translation units
+ * created within that index action have been destroyed.
+ */
+CINDEX_LINKAGE void clang_IndexAction_dispose(CXIndexAction);
+
+typedef enum {
+ /**
+ * \brief Used to indicate that no special indexing options are needed.
+ */
+ CXIndexOpt_None = 0x0,
+
+ /**
+ * \brief Used to indicate that IndexerCallbacks#indexEntityReference should
+ * be invoked for only one reference of an entity per source file that does
+ * not also include a declaration/definition of the entity.
+ */
+ CXIndexOpt_SuppressRedundantRefs = 0x1,
+
+ /**
+ * \brief Function-local symbols should be indexed. If this is not set
+ * function-local symbols will be ignored.
+ */
+ CXIndexOpt_IndexFunctionLocalSymbols = 0x2,
+
+ /**
+ * \brief Implicit function/class template instantiations should be indexed.
+ * If this is not set, implicit instantiations will be ignored.
+ */
+ CXIndexOpt_IndexImplicitTemplateInstantiations = 0x4,
+
+ /**
+ * \brief Suppress all compiler warnings when parsing for indexing.
+ */
+ CXIndexOpt_SuppressWarnings = 0x8,
+
+ /**
+ * \brief Skip a function/method body that was already parsed during an
+ * indexing session associated with a \c CXIndexAction object.
+ * Bodies in system headers are always skipped.
+ */
+ CXIndexOpt_SkipParsedBodiesInSession = 0x10
+
+} CXIndexOptFlags;
+
+/**
+ * \brief Index the given source file and the translation unit corresponding
+ * to that file via callbacks implemented through #IndexerCallbacks.
+ *
+ * \param client_data pointer data supplied by the client, which will
+ * be passed to the invoked callbacks.
+ *
+ * \param index_callbacks Pointer to indexing callbacks that the client
+ * implements.
+ *
+ * \param index_callbacks_size Size of #IndexerCallbacks structure that gets
+ * passed in index_callbacks.
+ *
+ * \param index_options A bitmask of options that affects how indexing is
+ * performed. This should be a bitwise OR of the CXIndexOpt_XXX flags.
+ *
+ * \param[out] out_TU pointer to store a \c CXTranslationUnit that can be
+ * reused after indexing is finished. Set to \c NULL if you do not require it.
+ *
+ * \returns 0 on success or if there were errors from which the compiler could
+ * recover. If there is a failure from which there is no recovery, returns
+ * a non-zero \c CXErrorCode.
+ *
+ * The rest of the parameters are the same as #clang_parseTranslationUnit.
+ */
+CINDEX_LINKAGE int clang_indexSourceFile(CXIndexAction,
+ CXClientData client_data,
+ IndexerCallbacks *index_callbacks,
+ unsigned index_callbacks_size,
+ unsigned index_options,
+ const char *source_filename,
+ const char * const *command_line_args,
+ int num_command_line_args,
+ struct CXUnsavedFile *unsaved_files,
+ unsigned num_unsaved_files,
+ CXTranslationUnit *out_TU,
+ unsigned TU_options);
+
+/**
+ * \brief Same as clang_indexSourceFile but requires a full command line
+ * for \c command_line_args including argv[0]. This is useful if the standard
+ * library paths are relative to the binary.
+ */
+CINDEX_LINKAGE int clang_indexSourceFileFullArgv(
+ CXIndexAction, CXClientData client_data, IndexerCallbacks *index_callbacks,
+ unsigned index_callbacks_size, unsigned index_options,
+ const char *source_filename, const char *const *command_line_args,
+ int num_command_line_args, struct CXUnsavedFile *unsaved_files,
+ unsigned num_unsaved_files, CXTranslationUnit *out_TU, unsigned TU_options);
+
+/**
+ * \brief Index the given translation unit via callbacks implemented through
+ * #IndexerCallbacks.
+ *
+ * The order of callback invocations is not guaranteed to be the same as
+ * when indexing a source file. The high level order will be:
+ *
+ * -Preprocessor callbacks invocations
+ * -Declaration/reference callbacks invocations
+ * -Diagnostic callback invocations
+ *
+ * The parameters are the same as #clang_indexSourceFile.
+ *
+ * \returns If there is a failure from which there is no recovery, returns
+ * non-zero, otherwise returns 0.
+ */
+CINDEX_LINKAGE int clang_indexTranslationUnit(CXIndexAction,
+ CXClientData client_data,
+ IndexerCallbacks *index_callbacks,
+ unsigned index_callbacks_size,
+ unsigned index_options,
+ CXTranslationUnit);
+
+/**
+ * \brief Retrieve the CXIdxFile, file, line, column, and offset represented by
+ * the given CXIdxLoc.
+ *
+ * If the location refers into a macro expansion, retrieves the
+ * location of the macro expansion and if it refers into a macro argument
+ * retrieves the location of the argument.
+ */
+CINDEX_LINKAGE void clang_indexLoc_getFileLocation(CXIdxLoc loc,
+ CXIdxClientFile *indexFile,
+ CXFile *file,
+ unsigned *line,
+ unsigned *column,
+ unsigned *offset);
+
+/**
+ * \brief Retrieve the CXSourceLocation represented by the given CXIdxLoc.
+ */
+CINDEX_LINKAGE
+CXSourceLocation clang_indexLoc_getCXSourceLocation(CXIdxLoc loc);
+
+/**
+ * \brief Visitor invoked for each field found by a traversal.
+ *
+ * This visitor function will be invoked for each field found by
+ * \c clang_Type_visitFields. Its first argument is the cursor being
+ * visited, its second argument is the client data provided to
+ * \c clang_Type_visitFields.
+ *
+ * The visitor should return one of the \c CXVisitorResult values
+ * to direct \c clang_Type_visitFields.
+ */
+typedef enum CXVisitorResult (*CXFieldVisitor)(CXCursor C,
+ CXClientData client_data);
+
+/**
+ * \brief Visit the fields of a particular type.
+ *
+ * This function visits all the direct fields of the given cursor,
+ * invoking the given \p visitor function with the cursors of each
+ * visited field. The traversal may be ended prematurely, if
+ * the visitor returns \c CXFieldVisit_Break.
+ *
+ * \param T the record type whose field may be visited.
+ *
+ * \param visitor the visitor function that will be invoked for each
+ * field of \p T.
+ *
+ * \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 CXFieldVisit_Break.
+ */
+CINDEX_LINKAGE unsigned clang_Type_visitFields(CXType T,
+ CXFieldVisitor visitor,
+ CXClientData client_data);
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+#ifdef __cplusplus
+}
+#endif
+#endif
diff --git a/contrib/llvm/tools/clang/include/clang-c/Platform.h b/contrib/llvm/tools/clang/include/clang-c/Platform.h
new file mode 100644
index 0000000..e2a4dcc
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang-c/Platform.h
@@ -0,0 +1,45 @@
+/*===-- clang-c/Platform.h - C Index platform decls -------------*- 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 platform specific macros (dllimport, deprecated, ...) *|
+|* *|
+\*===----------------------------------------------------------------------===*/
+
+#ifndef LLVM_CLANG_C_PLATFORM_H
+#define LLVM_CLANG_C_PLATFORM_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
+
+#ifdef __GNUC__
+ #define CINDEX_DEPRECATED __attribute__((deprecated))
+#else
+ #ifdef _MSC_VER
+ #define CINDEX_DEPRECATED __declspec(deprecated)
+ #else
+ #define CINDEX_DEPRECATED
+ #endif
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+#endif
diff --git a/contrib/llvm/tools/clang/include/clang-c/module.modulemap b/contrib/llvm/tools/clang/include/clang-c/module.modulemap
new file mode 100644
index 0000000..95a59d6
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang-c/module.modulemap
@@ -0,0 +1,4 @@
+module Clang_C {
+ umbrella "."
+ module * { export * }
+}
diff --git a/contrib/llvm/tools/clang/include/clang/ARCMigrate/ARCMT.h b/contrib/llvm/tools/clang/include/clang/ARCMigrate/ARCMT.h
new file mode 100644
index 0000000..7408186
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/ARCMigrate/ARCMT.h
@@ -0,0 +1,131 @@
+//===-- ARCMT.h - ARC Migration Rewriter ------------------------*- 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_ARCMIGRATE_ARCMT_H
+#define LLVM_CLANG_ARCMIGRATE_ARCMT_H
+
+#include "clang/ARCMigrate/FileRemapper.h"
+#include "clang/Basic/SourceLocation.h"
+#include "clang/Frontend/CompilerInvocation.h"
+
+namespace clang {
+ class ASTContext;
+ class DiagnosticConsumer;
+ class PCHContainerOperations;
+
+namespace arcmt {
+ class MigrationPass;
+
+/// \brief Creates an AST with the provided CompilerInvocation but with these
+/// changes:
+/// -if a PCH/PTH is set, the original header is used instead
+/// -Automatic Reference Counting mode is enabled
+///
+/// It then checks the AST and produces errors/warning for ARC migration issues
+/// that the user needs to handle manually.
+///
+/// \param emitPremigrationARCErrors if true all ARC errors will get emitted
+/// even if the migrator can fix them, but the function will still return false
+/// if all ARC errors can be fixed.
+///
+/// \param plistOut if non-empty, it is the file path to store the plist with
+/// the pre-migration ARC diagnostics.
+///
+/// \returns false if no error is produced, true otherwise.
+bool
+checkForManualIssues(CompilerInvocation &CI, const FrontendInputFile &Input,
+ std::shared_ptr<PCHContainerOperations> PCHContainerOps,
+ DiagnosticConsumer *DiagClient,
+ bool emitPremigrationARCErrors = false,
+ StringRef plistOut = StringRef());
+
+/// \brief Works similar to checkForManualIssues but instead of checking, it
+/// applies automatic modifications to source files to conform to ARC.
+///
+/// \returns false if no error is produced, true otherwise.
+bool
+applyTransformations(CompilerInvocation &origCI,
+ const FrontendInputFile &Input,
+ std::shared_ptr<PCHContainerOperations> PCHContainerOps,
+ DiagnosticConsumer *DiagClient);
+
+/// \brief Applies automatic modifications and produces temporary files
+/// and metadata into the \p outputDir path.
+///
+/// \param emitPremigrationARCErrors if true all ARC errors will get emitted
+/// even if the migrator can fix them, but the function will still return false
+/// if all ARC errors can be fixed.
+///
+/// \param plistOut if non-empty, it is the file path to store the plist with
+/// the pre-migration ARC diagnostics.
+///
+/// \returns false if no error is produced, true otherwise.
+bool migrateWithTemporaryFiles(
+ CompilerInvocation &origCI, const FrontendInputFile &Input,
+ std::shared_ptr<PCHContainerOperations> PCHContainerOps,
+ DiagnosticConsumer *DiagClient, StringRef outputDir,
+ bool emitPremigrationARCErrors, StringRef plistOut);
+
+/// \brief Get the set of file remappings from the \p outputDir path that
+/// migrateWithTemporaryFiles produced.
+///
+/// \returns false if no error is produced, true otherwise.
+bool getFileRemappings(std::vector<std::pair<std::string,std::string> > &remap,
+ StringRef outputDir,
+ DiagnosticConsumer *DiagClient);
+
+/// \brief Get the set of file remappings from a list of files with remapping
+/// info.
+///
+/// \returns false if no error is produced, true otherwise.
+bool getFileRemappingsFromFileList(
+ std::vector<std::pair<std::string,std::string> > &remap,
+ ArrayRef<StringRef> remapFiles,
+ DiagnosticConsumer *DiagClient);
+
+typedef void (*TransformFn)(MigrationPass &pass);
+
+std::vector<TransformFn> getAllTransformations(LangOptions::GCMode OrigGCMode,
+ bool NoFinalizeRemoval);
+
+class MigrationProcess {
+ CompilerInvocation OrigCI;
+ std::shared_ptr<PCHContainerOperations> PCHContainerOps;
+ DiagnosticConsumer *DiagClient;
+ FileRemapper Remapper;
+
+public:
+ bool HadARCErrors;
+
+ MigrationProcess(const CompilerInvocation &CI,
+ std::shared_ptr<PCHContainerOperations> PCHContainerOps,
+ DiagnosticConsumer *diagClient,
+ StringRef outputDir = StringRef());
+
+ class RewriteListener {
+ public:
+ virtual ~RewriteListener();
+
+ virtual void start(ASTContext &Ctx) { }
+ virtual void finish() { }
+
+ virtual void insert(SourceLocation loc, StringRef text) { }
+ virtual void remove(CharSourceRange range) { }
+ };
+
+ bool applyTransform(TransformFn trans, RewriteListener *listener = nullptr);
+
+ FileRemapper &getRemapper() { return Remapper; }
+};
+
+} // end namespace arcmt
+
+} // end namespace clang
+
+#endif
diff --git a/contrib/llvm/tools/clang/include/clang/ARCMigrate/ARCMTActions.h b/contrib/llvm/tools/clang/include/clang/ARCMigrate/ARCMTActions.h
new file mode 100644
index 0000000..c830aa3
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/ARCMigrate/ARCMTActions.h
@@ -0,0 +1,76 @@
+//===--- ARCMTActions.h - ARC Migrate Tool 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_ARCMIGRATE_ARCMTACTIONS_H
+#define LLVM_CLANG_ARCMIGRATE_ARCMTACTIONS_H
+
+#include "clang/ARCMigrate/FileRemapper.h"
+#include "clang/Frontend/FrontendAction.h"
+#include <memory>
+
+namespace clang {
+namespace arcmt {
+
+class CheckAction : public WrapperFrontendAction {
+protected:
+ bool BeginInvocation(CompilerInstance &CI) override;
+
+public:
+ CheckAction(FrontendAction *WrappedAction);
+};
+
+class ModifyAction : public WrapperFrontendAction {
+protected:
+ bool BeginInvocation(CompilerInstance &CI) override;
+
+public:
+ ModifyAction(FrontendAction *WrappedAction);
+};
+
+class MigrateSourceAction : public ASTFrontendAction {
+ FileRemapper Remapper;
+protected:
+ bool BeginInvocation(CompilerInstance &CI) override;
+ std::unique_ptr<ASTConsumer> CreateASTConsumer(CompilerInstance &CI,
+ StringRef InFile) override;
+};
+
+class MigrateAction : public WrapperFrontendAction {
+ std::string MigrateDir;
+ std::string PlistOut;
+ bool EmitPremigrationARCErros;
+protected:
+ bool BeginInvocation(CompilerInstance &CI) override;
+
+public:
+ MigrateAction(FrontendAction *WrappedAction, StringRef migrateDir,
+ StringRef plistOut,
+ bool emitPremigrationARCErrors);
+};
+
+/// \brief Migrates to modern ObjC syntax.
+class ObjCMigrateAction : public WrapperFrontendAction {
+ std::string MigrateDir;
+ unsigned ObjCMigAction;
+ FileRemapper Remapper;
+ CompilerInstance *CompInst;
+public:
+ ObjCMigrateAction(FrontendAction *WrappedAction, StringRef migrateDir,
+ unsigned migrateAction);
+
+protected:
+ std::unique_ptr<ASTConsumer> CreateASTConsumer(CompilerInstance &CI,
+ StringRef InFile) override;
+ bool BeginInvocation(CompilerInstance &CI) override;
+};
+
+}
+}
+
+#endif
diff --git a/contrib/llvm/tools/clang/include/clang/ARCMigrate/FileRemapper.h b/contrib/llvm/tools/clang/include/clang/ARCMigrate/FileRemapper.h
new file mode 100644
index 0000000..53b88e9
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/ARCMigrate/FileRemapper.h
@@ -0,0 +1,77 @@
+//===-- FileRemapper.h - File Remapping Helper ------------------*- 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_ARCMIGRATE_FILEREMAPPER_H
+#define LLVM_CLANG_ARCMIGRATE_FILEREMAPPER_H
+
+#include "clang/Basic/LLVM.h"
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/PointerUnion.h"
+#include "llvm/ADT/StringRef.h"
+#include <memory>
+
+namespace llvm {
+ class MemoryBuffer;
+}
+
+namespace clang {
+ class FileManager;
+ class FileEntry;
+ class DiagnosticsEngine;
+ class PreprocessorOptions;
+
+namespace arcmt {
+
+class FileRemapper {
+ // FIXME: Reuse the same FileManager for multiple ASTContexts.
+ std::unique_ptr<FileManager> FileMgr;
+
+ typedef llvm::PointerUnion<const FileEntry *, llvm::MemoryBuffer *> Target;
+ typedef llvm::DenseMap<const FileEntry *, Target> MappingsTy;
+ MappingsTy FromToMappings;
+
+ llvm::DenseMap<const FileEntry *, const FileEntry *> ToFromMappings;
+
+public:
+ FileRemapper();
+ ~FileRemapper();
+
+ bool initFromDisk(StringRef outputDir, DiagnosticsEngine &Diag,
+ bool ignoreIfFilesChanged);
+ bool initFromFile(StringRef filePath, DiagnosticsEngine &Diag,
+ bool ignoreIfFilesChanged);
+ bool flushToDisk(StringRef outputDir, DiagnosticsEngine &Diag);
+ bool flushToFile(StringRef outputPath, DiagnosticsEngine &Diag);
+
+ bool overwriteOriginal(DiagnosticsEngine &Diag,
+ StringRef outputDir = StringRef());
+
+ void remap(StringRef filePath, std::unique_ptr<llvm::MemoryBuffer> memBuf);
+
+ void applyMappings(PreprocessorOptions &PPOpts) const;
+
+ void clear(StringRef outputDir = StringRef());
+
+private:
+ void remap(const FileEntry *file, std::unique_ptr<llvm::MemoryBuffer> memBuf);
+ void remap(const FileEntry *file, const FileEntry *newfile);
+
+ const FileEntry *getOriginalFile(StringRef filePath);
+ void resetTarget(Target &targ);
+
+ bool report(const Twine &err, DiagnosticsEngine &Diag);
+
+ std::string getRemapInfoFile(StringRef outputDir);
+};
+
+} // end namespace arcmt
+
+} // end namespace clang
+
+#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..e58c219
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/AST/APValue.h
@@ -0,0 +1,452 @@
+//===--- 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 "clang/Basic/LLVM.h"
+#include "llvm/ADT/APFloat.h"
+#include "llvm/ADT/APSInt.h"
+#include "llvm/ADT/PointerIntPair.h"
+#include "llvm/ADT/PointerUnion.h"
+
+namespace clang {
+ class AddrLabelExpr;
+ class ASTContext;
+ class CharUnits;
+ class DiagnosticBuilder;
+ class Expr;
+ class FieldDecl;
+ class Decl;
+ class ValueDecl;
+ class CXXRecordDecl;
+ class QualType;
+
+/// APValue - This class implements a discriminated union of [uninitialized]
+/// [APSInt] [APFloat], [Complex APSInt] [Complex APFloat], [Expr + Offset],
+/// [Vector: N * APValue], [Array: N * APValue]
+class APValue {
+ typedef llvm::APSInt APSInt;
+ typedef llvm::APFloat APFloat;
+public:
+ enum ValueKind {
+ Uninitialized,
+ Int,
+ Float,
+ ComplexInt,
+ ComplexFloat,
+ LValue,
+ Vector,
+ Array,
+ Struct,
+ Union,
+ MemberPointer,
+ AddrLabelDiff
+ };
+ typedef llvm::PointerUnion<const ValueDecl *, const Expr *> LValueBase;
+ typedef llvm::PointerIntPair<const Decl *, 1, bool> BaseOrMemberType;
+ union LValuePathEntry {
+ /// BaseOrMember - The FieldDecl or CXXRecordDecl indicating the next item
+ /// in the path. An opaque value of type BaseOrMemberType.
+ void *BaseOrMember;
+ /// ArrayIndex - The array index of the next item in the path.
+ uint64_t ArrayIndex;
+ };
+ struct NoLValuePath {};
+ struct UninitArray {};
+ struct UninitStruct {};
+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 LV;
+ struct Vec {
+ APValue *Elts;
+ unsigned NumElts;
+ Vec() : Elts(nullptr), NumElts(0) {}
+ ~Vec() { delete[] Elts; }
+ };
+ struct Arr {
+ APValue *Elts;
+ unsigned NumElts, ArrSize;
+ Arr(unsigned NumElts, unsigned ArrSize);
+ ~Arr();
+ };
+ struct StructData {
+ APValue *Elts;
+ unsigned NumBases;
+ unsigned NumFields;
+ StructData(unsigned NumBases, unsigned NumFields);
+ ~StructData();
+ };
+ struct UnionData {
+ const FieldDecl *Field;
+ APValue *Value;
+ UnionData();
+ ~UnionData();
+ };
+ struct AddrLabelDiffData {
+ const AddrLabelExpr* LHSExpr;
+ const AddrLabelExpr* RHSExpr;
+ };
+ struct MemberPointerData;
+
+ // We ensure elsewhere that Data is big enough for LV and MemberPointerData.
+ typedef llvm::AlignedCharArrayUnion<void *, APSInt, APFloat, ComplexAPSInt,
+ ComplexAPFloat, Vec, Arr, StructData,
+ UnionData, AddrLabelDiffData> DataType;
+ static const size_t DataSize = sizeof(DataType);
+
+ DataType Data;
+
+public:
+ APValue() : Kind(Uninitialized) {}
+ explicit APValue(APSInt I) : Kind(Uninitialized) {
+ MakeInt(); setInt(std::move(I));
+ }
+ explicit APValue(APFloat F) : Kind(Uninitialized) {
+ MakeFloat(); setFloat(std::move(F));
+ }
+ explicit APValue(const APValue *E, unsigned N) : Kind(Uninitialized) {
+ MakeVector(); setVector(E, N);
+ }
+ APValue(APSInt R, APSInt I) : Kind(Uninitialized) {
+ MakeComplexInt(); setComplexInt(std::move(R), std::move(I));
+ }
+ APValue(APFloat R, APFloat I) : Kind(Uninitialized) {
+ MakeComplexFloat(); setComplexFloat(std::move(R), std::move(I));
+ }
+ APValue(const APValue &RHS);
+ APValue(APValue &&RHS) : Kind(Uninitialized) { swap(RHS); }
+ APValue(LValueBase B, const CharUnits &O, NoLValuePath N, unsigned CallIndex)
+ : Kind(Uninitialized) {
+ MakeLValue(); setLValue(B, O, N, CallIndex);
+ }
+ APValue(LValueBase B, const CharUnits &O, ArrayRef<LValuePathEntry> Path,
+ bool OnePastTheEnd, unsigned CallIndex)
+ : Kind(Uninitialized) {
+ MakeLValue(); setLValue(B, O, Path, OnePastTheEnd, CallIndex);
+ }
+ APValue(UninitArray, unsigned InitElts, unsigned Size) : Kind(Uninitialized) {
+ MakeArray(InitElts, Size);
+ }
+ APValue(UninitStruct, unsigned B, unsigned M) : Kind(Uninitialized) {
+ MakeStruct(B, M);
+ }
+ explicit APValue(const FieldDecl *D, const APValue &V = APValue())
+ : Kind(Uninitialized) {
+ MakeUnion(); setUnion(D, V);
+ }
+ APValue(const ValueDecl *Member, bool IsDerivedMember,
+ ArrayRef<const CXXRecordDecl*> Path) : Kind(Uninitialized) {
+ MakeMemberPointer(Member, IsDerivedMember, Path);
+ }
+ APValue(const AddrLabelExpr* LHSExpr, const AddrLabelExpr* RHSExpr)
+ : Kind(Uninitialized) {
+ MakeAddrLabelDiff(); setAddrLabelDiff(LHSExpr, RHSExpr);
+ }
+
+ ~APValue() {
+ MakeUninit();
+ }
+
+ /// \brief Returns whether the object performed allocations.
+ ///
+ /// If APValues are constructed via placement new, \c needsCleanup()
+ /// indicates whether the destructor must be called in order to correctly
+ /// free all allocated memory.
+ bool needsCleanup() const;
+
+ /// \brief Swaps the contents of this and the given APValue.
+ void swap(APValue &RHS);
+
+ 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; }
+ bool isArray() const { return Kind == Array; }
+ bool isStruct() const { return Kind == Struct; }
+ bool isUnion() const { return Kind == Union; }
+ bool isMemberPointer() const { return Kind == MemberPointer; }
+ bool isAddrLabelDiff() const { return Kind == AddrLabelDiff; }
+
+ void dump() const;
+ void dump(raw_ostream &OS) const;
+
+ void printPretty(raw_ostream &OS, ASTContext &Ctx, QualType Ty) const;
+ std::string getAsString(ASTContext &Ctx, QualType Ty) const;
+
+ APSInt &getInt() {
+ assert(isInt() && "Invalid accessor");
+ return *(APSInt*)(char*)Data.buffer;
+ }
+ const APSInt &getInt() const {
+ return const_cast<APValue*>(this)->getInt();
+ }
+
+ APFloat &getFloat() {
+ assert(isFloat() && "Invalid accessor");
+ return *(APFloat*)(char*)Data.buffer;
+ }
+ const APFloat &getFloat() const {
+ return const_cast<APValue*>(this)->getFloat();
+ }
+
+ APSInt &getComplexIntReal() {
+ assert(isComplexInt() && "Invalid accessor");
+ return ((ComplexAPSInt*)(char*)Data.buffer)->Real;
+ }
+ const APSInt &getComplexIntReal() const {
+ return const_cast<APValue*>(this)->getComplexIntReal();
+ }
+
+ APSInt &getComplexIntImag() {
+ assert(isComplexInt() && "Invalid accessor");
+ return ((ComplexAPSInt*)(char*)Data.buffer)->Imag;
+ }
+ const APSInt &getComplexIntImag() const {
+ return const_cast<APValue*>(this)->getComplexIntImag();
+ }
+
+ APFloat &getComplexFloatReal() {
+ assert(isComplexFloat() && "Invalid accessor");
+ return ((ComplexAPFloat*)(char*)Data.buffer)->Real;
+ }
+ const APFloat &getComplexFloatReal() const {
+ return const_cast<APValue*>(this)->getComplexFloatReal();
+ }
+
+ APFloat &getComplexFloatImag() {
+ assert(isComplexFloat() && "Invalid accessor");
+ return ((ComplexAPFloat*)(char*)Data.buffer)->Imag;
+ }
+ const APFloat &getComplexFloatImag() const {
+ return const_cast<APValue*>(this)->getComplexFloatImag();
+ }
+
+ const LValueBase getLValueBase() const;
+ CharUnits &getLValueOffset();
+ const CharUnits &getLValueOffset() const {
+ return const_cast<APValue*>(this)->getLValueOffset();
+ }
+ bool isLValueOnePastTheEnd() const;
+ bool hasLValuePath() const;
+ ArrayRef<LValuePathEntry> getLValuePath() const;
+ unsigned getLValueCallIndex() const;
+
+ APValue &getVectorElt(unsigned I) {
+ assert(isVector() && "Invalid accessor");
+ assert(I < getVectorLength() && "Index out of range");
+ return ((Vec*)(char*)Data.buffer)->Elts[I];
+ }
+ const APValue &getVectorElt(unsigned I) const {
+ return const_cast<APValue*>(this)->getVectorElt(I);
+ }
+ unsigned getVectorLength() const {
+ assert(isVector() && "Invalid accessor");
+ return ((const Vec*)(const void *)Data.buffer)->NumElts;
+ }
+
+ APValue &getArrayInitializedElt(unsigned I) {
+ assert(isArray() && "Invalid accessor");
+ assert(I < getArrayInitializedElts() && "Index out of range");
+ return ((Arr*)(char*)Data.buffer)->Elts[I];
+ }
+ const APValue &getArrayInitializedElt(unsigned I) const {
+ return const_cast<APValue*>(this)->getArrayInitializedElt(I);
+ }
+ bool hasArrayFiller() const {
+ return getArrayInitializedElts() != getArraySize();
+ }
+ APValue &getArrayFiller() {
+ assert(isArray() && "Invalid accessor");
+ assert(hasArrayFiller() && "No array filler");
+ return ((Arr*)(char*)Data.buffer)->Elts[getArrayInitializedElts()];
+ }
+ const APValue &getArrayFiller() const {
+ return const_cast<APValue*>(this)->getArrayFiller();
+ }
+ unsigned getArrayInitializedElts() const {
+ assert(isArray() && "Invalid accessor");
+ return ((const Arr*)(const void *)Data.buffer)->NumElts;
+ }
+ unsigned getArraySize() const {
+ assert(isArray() && "Invalid accessor");
+ return ((const Arr*)(const void *)Data.buffer)->ArrSize;
+ }
+
+ unsigned getStructNumBases() const {
+ assert(isStruct() && "Invalid accessor");
+ return ((const StructData*)(const char*)Data.buffer)->NumBases;
+ }
+ unsigned getStructNumFields() const {
+ assert(isStruct() && "Invalid accessor");
+ return ((const StructData*)(const char*)Data.buffer)->NumFields;
+ }
+ APValue &getStructBase(unsigned i) {
+ assert(isStruct() && "Invalid accessor");
+ return ((StructData*)(char*)Data.buffer)->Elts[i];
+ }
+ APValue &getStructField(unsigned i) {
+ assert(isStruct() && "Invalid accessor");
+ return ((StructData*)(char*)Data.buffer)->Elts[getStructNumBases() + i];
+ }
+ const APValue &getStructBase(unsigned i) const {
+ return const_cast<APValue*>(this)->getStructBase(i);
+ }
+ const APValue &getStructField(unsigned i) const {
+ return const_cast<APValue*>(this)->getStructField(i);
+ }
+
+ const FieldDecl *getUnionField() const {
+ assert(isUnion() && "Invalid accessor");
+ return ((const UnionData*)(const char*)Data.buffer)->Field;
+ }
+ APValue &getUnionValue() {
+ assert(isUnion() && "Invalid accessor");
+ return *((UnionData*)(char*)Data.buffer)->Value;
+ }
+ const APValue &getUnionValue() const {
+ return const_cast<APValue*>(this)->getUnionValue();
+ }
+
+ const ValueDecl *getMemberPointerDecl() const;
+ bool isMemberPointerToDerivedMember() const;
+ ArrayRef<const CXXRecordDecl*> getMemberPointerPath() const;
+
+ const AddrLabelExpr* getAddrLabelDiffLHS() const {
+ assert(isAddrLabelDiff() && "Invalid accessor");
+ return ((const AddrLabelDiffData*)(const char*)Data.buffer)->LHSExpr;
+ }
+ const AddrLabelExpr* getAddrLabelDiffRHS() const {
+ assert(isAddrLabelDiff() && "Invalid accessor");
+ return ((const AddrLabelDiffData*)(const char*)Data.buffer)->RHSExpr;
+ }
+
+ void setInt(APSInt I) {
+ assert(isInt() && "Invalid accessor");
+ *(APSInt *)(char *)Data.buffer = std::move(I);
+ }
+ void setFloat(APFloat F) {
+ assert(isFloat() && "Invalid accessor");
+ *(APFloat *)(char *)Data.buffer = std::move(F);
+ }
+ void setVector(const APValue *E, unsigned N) {
+ assert(isVector() && "Invalid accessor");
+ ((Vec*)(char*)Data.buffer)->Elts = new APValue[N];
+ ((Vec*)(char*)Data.buffer)->NumElts = N;
+ for (unsigned i = 0; i != N; ++i)
+ ((Vec*)(char*)Data.buffer)->Elts[i] = E[i];
+ }
+ void setComplexInt(APSInt R, APSInt I) {
+ assert(R.getBitWidth() == I.getBitWidth() &&
+ "Invalid complex int (type mismatch).");
+ assert(isComplexInt() && "Invalid accessor");
+ ((ComplexAPSInt *)(char *)Data.buffer)->Real = std::move(R);
+ ((ComplexAPSInt *)(char *)Data.buffer)->Imag = std::move(I);
+ }
+ void setComplexFloat(APFloat R, APFloat I) {
+ assert(&R.getSemantics() == &I.getSemantics() &&
+ "Invalid complex float (type mismatch).");
+ assert(isComplexFloat() && "Invalid accessor");
+ ((ComplexAPFloat *)(char *)Data.buffer)->Real = std::move(R);
+ ((ComplexAPFloat *)(char *)Data.buffer)->Imag = std::move(I);
+ }
+ void setLValue(LValueBase B, const CharUnits &O, NoLValuePath,
+ unsigned CallIndex);
+ void setLValue(LValueBase B, const CharUnits &O,
+ ArrayRef<LValuePathEntry> Path, bool OnePastTheEnd,
+ unsigned CallIndex);
+ void setUnion(const FieldDecl *Field, const APValue &Value) {
+ assert(isUnion() && "Invalid accessor");
+ ((UnionData*)(char*)Data.buffer)->Field = Field;
+ *((UnionData*)(char*)Data.buffer)->Value = Value;
+ }
+ void setAddrLabelDiff(const AddrLabelExpr* LHSExpr,
+ const AddrLabelExpr* RHSExpr) {
+ ((AddrLabelDiffData*)(char*)Data.buffer)->LHSExpr = LHSExpr;
+ ((AddrLabelDiffData*)(char*)Data.buffer)->RHSExpr = RHSExpr;
+ }
+
+ /// Assign by swapping from a copy of the RHS.
+ APValue &operator=(APValue RHS) {
+ swap(RHS);
+ return *this;
+ }
+
+private:
+ void DestroyDataAndMakeUninit();
+ void MakeUninit() {
+ if (Kind != Uninitialized)
+ DestroyDataAndMakeUninit();
+ }
+ void MakeInt() {
+ assert(isUninit() && "Bad state change");
+ new ((void*)Data.buffer) APSInt(1);
+ Kind = Int;
+ }
+ void MakeFloat() {
+ assert(isUninit() && "Bad state change");
+ new ((void*)(char*)Data.buffer) APFloat(0.0);
+ Kind = Float;
+ }
+ void MakeVector() {
+ assert(isUninit() && "Bad state change");
+ new ((void*)(char*)Data.buffer) Vec();
+ Kind = Vector;
+ }
+ void MakeComplexInt() {
+ assert(isUninit() && "Bad state change");
+ new ((void*)(char*)Data.buffer) ComplexAPSInt();
+ Kind = ComplexInt;
+ }
+ void MakeComplexFloat() {
+ assert(isUninit() && "Bad state change");
+ new ((void*)(char*)Data.buffer) ComplexAPFloat();
+ Kind = ComplexFloat;
+ }
+ void MakeLValue();
+ void MakeArray(unsigned InitElts, unsigned Size);
+ void MakeStruct(unsigned B, unsigned M) {
+ assert(isUninit() && "Bad state change");
+ new ((void*)(char*)Data.buffer) StructData(B, M);
+ Kind = Struct;
+ }
+ void MakeUnion() {
+ assert(isUninit() && "Bad state change");
+ new ((void*)(char*)Data.buffer) UnionData();
+ Kind = Union;
+ }
+ void MakeMemberPointer(const ValueDecl *Member, bool IsDerivedMember,
+ ArrayRef<const CXXRecordDecl*> Path);
+ void MakeAddrLabelDiff() {
+ assert(isUninit() && "Bad state change");
+ new ((void*)(char*)Data.buffer) AddrLabelDiffData();
+ Kind = AddrLabelDiff;
+ }
+};
+
+} // 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..6db351d
--- /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/StmtVisitor.h"
+#include "clang/AST/Type.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..b2730e4
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/AST/ASTConsumer.h
@@ -0,0 +1,159 @@
+//===--- 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
+
+#include "llvm/ADT/StringRef.h"
+
+namespace clang {
+ class ASTContext;
+ class CXXMethodDecl;
+ class CXXRecordDecl;
+ class Decl;
+ class DeclGroupRef;
+ class ASTMutationListener;
+ class ASTDeserializationListener; // layering violation because void* is ugly
+ class SemaConsumer; // layering violation required for safe SemaConsumer
+ class TagDecl;
+ class VarDecl;
+ class FunctionDecl;
+ class ImportDecl;
+
+/// 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*.
+ ///
+ /// \returns true to continue parsing, or false to abort parsing.
+ virtual bool HandleTopLevelDecl(DeclGroupRef D);
+
+ /// \brief This callback is invoked each time an inline method definition is
+ /// completed.
+ virtual void HandleInlineMethodDefinition(CXXMethodDecl *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) {}
+
+ /// \brief This callback is invoked the first time each TagDecl is required to
+ /// be complete.
+ virtual void HandleTagDeclRequiredDefinition(const TagDecl *D) {}
+
+ /// \brief Invoked when a function is implicitly instantiated.
+ /// Note that at this point point it does not have a body, its body is
+ /// instantiated at the end of the translation unit and passed to
+ /// HandleTopLevelDecl.
+ virtual void HandleCXXImplicitFunctionInstantiation(FunctionDecl *D) {}
+
+ /// \brief Handle the specified top-level declaration that occurred inside
+ /// and ObjC container.
+ /// The default implementation ignored them.
+ virtual void HandleTopLevelDeclInObjCContainer(DeclGroupRef D);
+
+ /// \brief Handle an ImportDecl that was implicitly created due to an
+ /// inclusion directive.
+ /// The default implementation passes it to HandleTopLevelDecl.
+ virtual void HandleImplicitImportDecl(ImportDecl *D);
+
+ /// \brief Handle a pragma that appends to Linker Options. Currently this
+ /// only exists to support Microsoft's #pragma comment(linker, "/foo").
+ virtual void HandleLinkerOptionPragma(llvm::StringRef Opts) {}
+
+ /// \brief Handle a pragma that emits a mismatch identifier and value to the
+ /// object file for the linker to work with. Currently, this only exists to
+ /// support Microsoft's #pragma detect_mismatch.
+ virtual void HandleDetectMismatch(llvm::StringRef Name,
+ llvm::StringRef Value) {}
+
+ /// \brief Handle a dependent library created by a pragma in the source.
+ /// Currently this only exists to support Microsoft's
+ /// #pragma comment(lib, "/foo").
+ virtual void HandleDependentLibrary(llvm::StringRef Lib) {}
+
+ /// 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) {}
+
+ /// HandleCXXStaticMemberVarInstantiation - Tell the consumer that this
+ // variable has been instantiated.
+ virtual void HandleCXXStaticMemberVarInstantiation(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.
+ virtual void HandleVTable(CXXRecordDecl *RD) {}
+
+ /// \brief If the consumer is interested in entities getting modified after
+ /// their initial creation, it should return a pointer to
+ /// an ASTMutationListener here.
+ virtual ASTMutationListener *GetASTMutationListener() { return nullptr; }
+
+ /// \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 nullptr;
+ }
+
+ /// PrintStats - If desired, print any statistics.
+ virtual void PrintStats() {}
+
+ /// \brief This callback is called for each function if the Parser was
+ /// initialized with \c SkipFunctionBodies set to \c true.
+ ///
+ /// \return \c true if the function's body should be skipped. The function
+ /// body may be parsed anyway if it is needed (for instance, if it contains
+ /// the code completion point or is constexpr).
+ virtual bool shouldSkipFunctionBody(Decl *D) { 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..b66009e
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/AST/ASTContext.h
@@ -0,0 +1,2672 @@
+//===--- 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.
+//
+//===----------------------------------------------------------------------===//
+///
+/// \file
+/// \brief Defines the clang::ASTContext interface.
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_AST_ASTCONTEXT_H
+#define LLVM_CLANG_AST_ASTCONTEXT_H
+
+#include "clang/AST/ASTTypeTraits.h"
+#include "clang/AST/CanonicalType.h"
+#include "clang/AST/CommentCommandTraits.h"
+#include "clang/AST/Decl.h"
+#include "clang/AST/ExternalASTSource.h"
+#include "clang/AST/NestedNameSpecifier.h"
+#include "clang/AST/PrettyPrinter.h"
+#include "clang/AST/RawCommentList.h"
+#include "clang/AST/TemplateName.h"
+#include "clang/AST/Type.h"
+#include "clang/Basic/AddressSpaces.h"
+#include "clang/Basic/IdentifierTable.h"
+#include "clang/Basic/LangOptions.h"
+#include "clang/Basic/Module.h"
+#include "clang/Basic/OperatorKinds.h"
+#include "clang/Basic/PartialDiagnostic.h"
+#include "clang/Basic/SanitizerBlacklist.h"
+#include "clang/Basic/VersionTuple.h"
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/FoldingSet.h"
+#include "llvm/ADT/IntrusiveRefCntPtr.h"
+#include "llvm/ADT/SmallPtrSet.h"
+#include "llvm/ADT/TinyPtrVector.h"
+#include "llvm/Support/Allocator.h"
+#include <memory>
+#include <vector>
+
+namespace llvm {
+ struct fltSemantics;
+}
+
+namespace clang {
+ class FileManager;
+ class AtomicExpr;
+ class ASTRecordLayout;
+ class BlockExpr;
+ class CharUnits;
+ class DiagnosticsEngine;
+ class Expr;
+ class ASTMutationListener;
+ class IdentifierTable;
+ class MaterializeTemporaryExpr;
+ class SelectorTable;
+ class TargetInfo;
+ class CXXABI;
+ class MangleNumberingContext;
+ // Decls
+ class MangleContext;
+ class ObjCIvarDecl;
+ class ObjCPropertyDecl;
+ class UnresolvedSetIterator;
+ class UsingDecl;
+ class UsingShadowDecl;
+ class VTableContextBase;
+
+ namespace Builtin { class Context; }
+ enum BuiltinTemplateKind : int;
+
+ namespace comments {
+ class FullComment;
+ }
+
+ struct TypeInfo {
+ uint64_t Width;
+ unsigned Align;
+ bool AlignIsRequired : 1;
+ TypeInfo() : Width(0), Align(0), AlignIsRequired(false) {}
+ TypeInfo(uint64_t Width, unsigned Align, bool AlignIsRequired)
+ : Width(Width), Align(Align), AlignIsRequired(AlignIsRequired) {}
+ };
+
+/// \brief Holds long-lived AST nodes (such as types and decls) that can be
+/// referred to throughout the semantic analysis of a file.
+class ASTContext : public RefCountedBase<ASTContext> {
+ ASTContext &this_() { return *this; }
+
+ mutable SmallVector<Type *, 0> Types;
+ mutable llvm::FoldingSet<ExtQuals> ExtQualNodes;
+ mutable llvm::FoldingSet<ComplexType> ComplexTypes;
+ mutable llvm::FoldingSet<PointerType> PointerTypes;
+ mutable llvm::FoldingSet<AdjustedType> AdjustedTypes;
+ 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::ContextualFoldingSet<FunctionProtoType, ASTContext&>
+ 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;
+ mutable llvm::FoldingSet<AutoType> AutoTypes;
+ mutable llvm::FoldingSet<AtomicType> AtomicTypes;
+ llvm::FoldingSet<AttributedType> AttributedTypes;
+
+ mutable llvm::FoldingSet<QualifiedTemplateName> QualifiedTemplateNames;
+ mutable llvm::FoldingSet<DependentTemplateName> DependentTemplateNames;
+ mutable llvm::FoldingSet<SubstTemplateTemplateParmStorage>
+ SubstTemplateTemplateParms;
+ mutable llvm::ContextualFoldingSet<SubstTemplateTemplateParmPackStorage,
+ ASTContext&>
+ 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;
+
+ /// \brief 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;
+
+ /// \brief A cache from types to size and alignment information.
+ typedef llvm::DenseMap<const Type *, struct TypeInfo> TypeInfoMap;
+ mutable TypeInfoMap MemoizedTypeInfo;
+
+ /// \brief A cache mapping from CXXRecordDecls to key functions.
+ llvm::DenseMap<const CXXRecordDecl*, LazyDeclPtr> KeyFunctions;
+
+ /// \brief Mapping from ObjCContainers to their ObjCImplementations.
+ llvm::DenseMap<ObjCContainerDecl*, ObjCImplDecl*> ObjCImpls;
+
+ /// \brief Mapping from ObjCMethod to its duplicate declaration in the same
+ /// interface.
+ llvm::DenseMap<const ObjCMethodDecl*,const ObjCMethodDecl*> ObjCMethodRedecls;
+
+ /// \brief Mapping from __block VarDecls to their copy initialization expr.
+ llvm::DenseMap<const VarDecl*, Expr*> BlockVarCopyInits;
+
+ /// \brief Mapping from class scope functions specialization to their
+ /// template patterns.
+ llvm::DenseMap<const FunctionDecl*, FunctionDecl*>
+ ClassScopeSpecializationPattern;
+
+ /// \brief Mapping from materialized temporaries with static storage duration
+ /// that appear in constant initializers to their evaluated values. These are
+ /// allocated in a std::map because their address must be stable.
+ llvm::DenseMap<const MaterializeTemporaryExpr *, APValue *>
+ MaterializedTemporaryValues;
+
+ /// \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 The typedef for the __int128_t type.
+ mutable TypedefDecl *Int128Decl;
+
+ /// \brief The typedef for the __uint128_t type.
+ mutable TypedefDecl *UInt128Decl;
+
+ /// \brief The typedef for the __float128 stub type.
+ mutable TypeDecl *Float128StubDecl;
+
+ /// \brief The typedef for the target specific predefined
+ /// __builtin_va_list type.
+ mutable TypedefDecl *BuiltinVaListDecl;
+
+ /// The typedef for the predefined \c __builtin_ms_va_list type.
+ mutable TypedefDecl *BuiltinMSVaListDecl;
+
+ /// \brief The typedef for the predefined \c id type.
+ mutable TypedefDecl *ObjCIdDecl;
+
+ /// \brief The typedef for the predefined \c SEL type.
+ mutable TypedefDecl *ObjCSelDecl;
+
+ /// \brief The typedef for the predefined \c Class type.
+ mutable TypedefDecl *ObjCClassDecl;
+
+ /// \brief The typedef for the predefined \c Protocol class in Objective-C.
+ mutable ObjCInterfaceDecl *ObjCProtocolClassDecl;
+
+ /// \brief The typedef for the predefined 'BOOL' type.
+ mutable TypedefDecl *BOOLDecl;
+
+ // Typedefs which may be provided defining the structure of Objective-C
+ // pseudo-builtins
+ QualType ObjCIdRedefinitionType;
+ QualType ObjCClassRedefinitionType;
+ QualType ObjCSelRedefinitionType;
+
+ /// The identifier 'NSObject'.
+ IdentifierInfo *NSObjectName = nullptr;
+
+ /// The identifier 'NSCopying'.
+ IdentifierInfo *NSCopyingName = nullptr;
+
+ /// The identifier '__make_integer_seq'.
+ mutable IdentifierInfo *MakeIntegerSeqName = nullptr;
+
+ QualType ObjCConstantStringType;
+ mutable RecordDecl *CFConstantStringTypeDecl;
+
+ mutable QualType ObjCSuperType;
+
+ QualType ObjCNSStringType;
+
+ /// \brief The typedef declaration for the Objective-C "instancetype" type.
+ TypedefDecl *ObjCInstanceTypeDecl;
+
+ /// \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 The type for the C ucontext_t type.
+ TypeDecl *ucontext_tDecl;
+
+ /// \brief Type for the Block descriptor for Blocks CodeGen.
+ ///
+ /// Since this is only used for generation of debug info, it is not
+ /// serialized.
+ mutable RecordDecl *BlockDescriptorType;
+
+ /// \brief Type for the Block descriptor for Blocks CodeGen.
+ ///
+ /// Since this is only used for generation of debug info, it is not
+ /// serialized.
+ mutable RecordDecl *BlockDescriptorExtendedType;
+
+ /// \brief Declaration for the CUDA cudaConfigureCall function.
+ FunctionDecl *cudaConfigureCallDecl;
+
+ /// \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 A mapping from non-redeclarable declarations in modules that were
+ /// merged with other declarations to the canonical declaration that they were
+ /// merged into.
+ llvm::DenseMap<Decl*, Decl*> MergedDecls;
+
+ /// \brief A mapping from a defining declaration to a list of modules (other
+ /// than the owning module of the declaration) that contain merged
+ /// definitions of that entity.
+ llvm::DenseMap<NamedDecl*, llvm::TinyPtrVector<Module*>> MergedDefModules;
+
+public:
+ /// \brief A type synonym for the TemplateOrInstantiation mapping.
+ typedef llvm::PointerUnion<VarTemplateDecl *, MemberSpecializationInfo *>
+ TemplateOrSpecializationInfo;
+
+private:
+
+ /// \brief A mapping to contain the template or declaration that
+ /// a variable declaration describes or was instantiated from,
+ /// respectively.
+ ///
+ /// For non-templates, this value will be NULL. For variable
+ /// declarations that describe a variable template, this will be a
+ /// pointer to a VarTemplateDecl. For static data members
+ /// of class template specializations, this will be the
+ /// MemberSpecializationInfo referring to the member variable that was
+ /// instantiated or specialized. Thus, the mapping will keep track of
+ /// the static data member templates from which static data members of
+ /// class template specializations were instantiated.
+ ///
+ /// 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 *, TemplateOrSpecializationInfo>
+ TemplateOrInstantiation;
+
+ /// \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 llvm::TinyPtrVector<const CXXMethodDecl*> CXXMethodVector;
+ llvm::DenseMap<const CXXMethodDecl *, CXXMethodVector> OverriddenMethods;
+
+ /// \brief Mapping from each declaration context to its corresponding
+ /// mangling numbering context (used for constructs like lambdas which
+ /// need to be consistently numbered for the mangler).
+ llvm::DenseMap<const DeclContext *, MangleNumberingContext *>
+ MangleNumberingContexts;
+
+ /// \brief Side-table of mangling numbers for declarations which rarely
+ /// need them (like static local vars).
+ llvm::DenseMap<const NamedDecl *, unsigned> MangleNumbers;
+ llvm::DenseMap<const VarDecl *, unsigned> StaticLocalNumbers;
+
+ /// \brief Mapping that stores parameterIndex values for ParmVarDecls when
+ /// that value exceeds the bitfield size of ParmVarDeclBits.ParameterIndex.
+ typedef llvm::DenseMap<const VarDecl *, unsigned> ParameterIndexTable;
+ ParameterIndexTable ParamIndices;
+
+ ImportDecl *FirstLocalImport;
+ ImportDecl *LastLocalImport;
+
+ TranslationUnitDecl *TUDecl;
+ mutable ExternCContextDecl *ExternCContext;
+ mutable BuiltinTemplateDecl *MakeIntegerSeqDecl;
+
+ /// \brief The associated SourceManager object.a
+ SourceManager &SourceMgr;
+
+ /// \brief The language options used to create the AST associated with
+ /// this ASTContext object.
+ LangOptions &LangOpts;
+
+ /// \brief Blacklist object that is used by sanitizers to decide which
+ /// entities should not be instrumented.
+ std::unique_ptr<SanitizerBlacklist> SanitizerBL;
+
+ /// \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.
+ std::unique_ptr<CXXABI> ABI;
+ CXXABI *createCXXABI(const TargetInfo &T);
+
+ /// \brief The logical -> physical address space map.
+ const LangAS::Map *AddrSpaceMap;
+
+ /// \brief Address space map mangling must be used with language specific
+ /// address spaces (e.g. OpenCL/CUDA)
+ bool AddrSpaceMapMangling;
+
+ friend class ASTDeclReader;
+ friend class ASTReader;
+ friend class ASTWriter;
+ friend class CXXRecordDecl;
+
+ const TargetInfo *Target;
+ const TargetInfo *AuxTarget;
+ clang::PrintingPolicy PrintingPolicy;
+
+public:
+ IdentifierTable &Idents;
+ SelectorTable &Selectors;
+ Builtin::Context &BuiltinInfo;
+ mutable DeclarationNameTable DeclarationNames;
+ IntrusiveRefCntPtr<ExternalASTSource> ExternalSource;
+ ASTMutationListener *Listener;
+
+ /// \brief Contains parents of a node.
+ typedef llvm::SmallVector<ast_type_traits::DynTypedNode, 2> ParentVector;
+
+ /// \brief Maps from a node to its parents. This is used for nodes that have
+ /// pointer identity only, which are more common and we can save space by
+ /// only storing a unique pointer to them.
+ typedef llvm::DenseMap<const void *,
+ llvm::PointerUnion4<const Decl *, const Stmt *,
+ ast_type_traits::DynTypedNode *,
+ ParentVector *>> ParentMapPointers;
+
+ /// Parent map for nodes without pointer identity. We store a full
+ /// DynTypedNode for all keys.
+ typedef llvm::DenseMap<
+ ast_type_traits::DynTypedNode,
+ llvm::PointerUnion4<const Decl *, const Stmt *,
+ ast_type_traits::DynTypedNode *, ParentVector *>>
+ ParentMapOtherNodes;
+
+ /// Container for either a single DynTypedNode or for an ArrayRef to
+ /// DynTypedNode. For use with ParentMap.
+ class DynTypedNodeList {
+ typedef ast_type_traits::DynTypedNode DynTypedNode;
+ llvm::AlignedCharArrayUnion<ast_type_traits::DynTypedNode,
+ ArrayRef<DynTypedNode>> Storage;
+ bool IsSingleNode;
+
+ public:
+ DynTypedNodeList(const DynTypedNode &N) : IsSingleNode(true) {
+ new (Storage.buffer) DynTypedNode(N);
+ }
+ DynTypedNodeList(ArrayRef<DynTypedNode> A) : IsSingleNode(false) {
+ new (Storage.buffer) ArrayRef<DynTypedNode>(A);
+ }
+
+ const ast_type_traits::DynTypedNode *begin() const {
+ if (!IsSingleNode)
+ return reinterpret_cast<const ArrayRef<DynTypedNode> *>(Storage.buffer)
+ ->begin();
+ return reinterpret_cast<const DynTypedNode *>(Storage.buffer);
+ }
+
+ const ast_type_traits::DynTypedNode *end() const {
+ if (!IsSingleNode)
+ return reinterpret_cast<const ArrayRef<DynTypedNode> *>(Storage.buffer)
+ ->end();
+ return reinterpret_cast<const DynTypedNode *>(Storage.buffer) + 1;
+ }
+
+ size_t size() const { return end() - begin(); }
+ bool empty() const { return begin() == end(); }
+ const DynTypedNode &operator[](size_t N) const {
+ assert(N < size() && "Out of bounds!");
+ return *(begin() + N);
+ }
+ };
+
+ /// \brief Returns the parents of the given node.
+ ///
+ /// Note that this will lazily compute the parents of all nodes
+ /// and store them for later retrieval. Thus, the first call is O(n)
+ /// in the number of AST nodes.
+ ///
+ /// Caveats and FIXMEs:
+ /// Calculating the parent map over all AST nodes will need to load the
+ /// full AST. This can be undesirable in the case where the full AST is
+ /// expensive to create (for example, when using precompiled header
+ /// preambles). Thus, there are good opportunities for optimization here.
+ /// One idea is to walk the given node downwards, looking for references
+ /// to declaration contexts - once a declaration context is found, compute
+ /// the parent map for the declaration context; if that can satisfy the
+ /// request, loading the whole AST can be avoided. Note that this is made
+ /// more complex by statements in templates having multiple parents - those
+ /// problems can be solved by building closure over the templated parts of
+ /// the AST, which also avoids touching large parts of the AST.
+ /// Additionally, we will want to add an interface to already give a hint
+ /// where to search for the parents, for example when looking at a statement
+ /// inside a certain function.
+ ///
+ /// 'NodeT' can be one of Decl, Stmt, Type, TypeLoc,
+ /// NestedNameSpecifier or NestedNameSpecifierLoc.
+ template <typename NodeT> DynTypedNodeList getParents(const NodeT &Node) {
+ return getParents(ast_type_traits::DynTypedNode::create(Node));
+ }
+
+ DynTypedNodeList getParents(const ast_type_traits::DynTypedNode &Node);
+
+ const clang::PrintingPolicy &getPrintingPolicy() const {
+ return PrintingPolicy;
+ }
+
+ void setPrintingPolicy(const clang::PrintingPolicy &Policy) {
+ PrintingPolicy = Policy;
+ }
+
+ SourceManager& getSourceManager() { return SourceMgr; }
+ const SourceManager& getSourceManager() const { return SourceMgr; }
+
+ llvm::BumpPtrAllocator &getAllocator() const {
+ return BumpAlloc;
+ }
+
+ void *Allocate(size_t Size, unsigned Align = 8) const {
+ return BumpAlloc.Allocate(Size, Align);
+ }
+ template <typename T> T *Allocate(size_t Num = 1) const {
+ return static_cast<T *>(Allocate(Num * sizeof(T), llvm::alignOf<T>()));
+ }
+ void Deallocate(void *Ptr) const { }
+
+ /// Return the total amount of physical memory allocated for representing
+ /// AST nodes and type information.
+ size_t getASTAllocatedMemory() const {
+ return BumpAlloc.getTotalMemory();
+ }
+ /// Return the total memory used for various side tables.
+ size_t getSideTableAllocatedMemory() const;
+
+ PartialDiagnostic::StorageAllocator &getDiagAllocator() {
+ return DiagAllocator;
+ }
+
+ const TargetInfo &getTargetInfo() const { return *Target; }
+ const TargetInfo *getAuxTargetInfo() const { return AuxTarget; }
+
+ /// getIntTypeForBitwidth -
+ /// sets integer QualTy according to specified details:
+ /// bitwidth, signed/unsigned.
+ /// Returns empty type if there is no appropriate target types.
+ QualType getIntTypeForBitwidth(unsigned DestWidth,
+ unsigned Signed) const;
+ /// getRealTypeForBitwidth -
+ /// sets floating point QualTy according to specified bitwidth.
+ /// Returns empty type if there is no appropriate target types.
+ QualType getRealTypeForBitwidth(unsigned DestWidth) const;
+
+ bool AtomicUsesUnsupportedLibcall(const AtomicExpr *E) const;
+
+ const LangOptions& getLangOpts() const { return LangOpts; }
+
+ const SanitizerBlacklist &getSanitizerBlacklist() const {
+ return *SanitizerBL;
+ }
+
+ DiagnosticsEngine &getDiagnostics() const;
+
+ FullSourceLoc getFullLoc(SourceLocation Loc) const {
+ return FullSourceLoc(Loc,SourceMgr);
+ }
+
+ /// \brief All comments in this translation unit.
+ RawCommentList Comments;
+
+ /// \brief True if comments are already loaded from ExternalASTSource.
+ mutable bool CommentsLoaded;
+
+ class RawCommentAndCacheFlags {
+ public:
+ enum Kind {
+ /// We searched for a comment attached to the particular declaration, but
+ /// didn't find any.
+ ///
+ /// getRaw() == 0.
+ NoCommentInDecl = 0,
+
+ /// We have found a comment attached to this particular declaration.
+ ///
+ /// getRaw() != 0.
+ FromDecl,
+
+ /// This declaration does not have an attached comment, and we have
+ /// searched the redeclaration chain.
+ ///
+ /// If getRaw() == 0, the whole redeclaration chain does not have any
+ /// comments.
+ ///
+ /// If getRaw() != 0, it is a comment propagated from other
+ /// redeclaration.
+ FromRedecl
+ };
+
+ Kind getKind() const LLVM_READONLY {
+ return Data.getInt();
+ }
+
+ void setKind(Kind K) {
+ Data.setInt(K);
+ }
+
+ const RawComment *getRaw() const LLVM_READONLY {
+ return Data.getPointer();
+ }
+
+ void setRaw(const RawComment *RC) {
+ Data.setPointer(RC);
+ }
+
+ const Decl *getOriginalDecl() const LLVM_READONLY {
+ return OriginalDecl;
+ }
+
+ void setOriginalDecl(const Decl *Orig) {
+ OriginalDecl = Orig;
+ }
+
+ private:
+ llvm::PointerIntPair<const RawComment *, 2, Kind> Data;
+ const Decl *OriginalDecl;
+ };
+
+ /// \brief Mapping from declarations to comments attached to any
+ /// redeclaration.
+ ///
+ /// Raw comments are owned by Comments list. This mapping is populated
+ /// lazily.
+ mutable llvm::DenseMap<const Decl *, RawCommentAndCacheFlags> RedeclComments;
+
+ /// \brief Mapping from declarations to parsed comments attached to any
+ /// redeclaration.
+ mutable llvm::DenseMap<const Decl *, comments::FullComment *> ParsedComments;
+
+ /// \brief Return the documentation comment attached to a given declaration,
+ /// without looking into cache.
+ RawComment *getRawCommentForDeclNoCache(const Decl *D) const;
+
+public:
+ RawCommentList &getRawCommentList() {
+ return Comments;
+ }
+
+ void addComment(const RawComment &RC) {
+ assert(LangOpts.RetainCommentsFromSystemHeaders ||
+ !SourceMgr.isInSystemHeader(RC.getSourceRange().getBegin()));
+ Comments.addComment(RC, BumpAlloc);
+ }
+
+ /// \brief Return the documentation comment attached to a given declaration.
+ /// Returns NULL if no comment is attached.
+ ///
+ /// \param OriginalDecl if not NULL, is set to declaration AST node that had
+ /// the comment, if the comment we found comes from a redeclaration.
+ const RawComment *
+ getRawCommentForAnyRedecl(const Decl *D,
+ const Decl **OriginalDecl = nullptr) const;
+
+ /// Return parsed documentation comment attached to a given declaration.
+ /// Returns NULL if no comment is attached.
+ ///
+ /// \param PP the Preprocessor used with this TU. Could be NULL if
+ /// preprocessor is not available.
+ comments::FullComment *getCommentForDecl(const Decl *D,
+ const Preprocessor *PP) const;
+
+ /// Return parsed documentation comment attached to a given declaration.
+ /// Returns NULL if no comment is attached. Does not look at any
+ /// redeclarations of the declaration.
+ comments::FullComment *getLocalCommentForDeclUncached(const Decl *D) const;
+
+ comments::FullComment *cloneFullComment(comments::FullComment *FC,
+ const Decl *D) const;
+
+private:
+ mutable comments::CommandTraits CommentCommandTraits;
+
+ /// \brief Iterator that visits import declarations.
+ class import_iterator {
+ ImportDecl *Import;
+
+ public:
+ typedef ImportDecl *value_type;
+ typedef ImportDecl *reference;
+ typedef ImportDecl *pointer;
+ typedef int difference_type;
+ typedef std::forward_iterator_tag iterator_category;
+
+ import_iterator() : Import() {}
+ explicit import_iterator(ImportDecl *Import) : Import(Import) {}
+
+ reference operator*() const { return Import; }
+ pointer operator->() const { return Import; }
+
+ import_iterator &operator++() {
+ Import = ASTContext::getNextLocalImport(Import);
+ return *this;
+ }
+
+ import_iterator operator++(int) {
+ import_iterator Other(*this);
+ ++(*this);
+ return Other;
+ }
+
+ friend bool operator==(import_iterator X, import_iterator Y) {
+ return X.Import == Y.Import;
+ }
+
+ friend bool operator!=(import_iterator X, import_iterator Y) {
+ return X.Import != Y.Import;
+ }
+ };
+
+public:
+ comments::CommandTraits &getCommentCommandTraits() const {
+ return CommentCommandTraits;
+ }
+
+ /// \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.
+ // FIXME: Remove ?
+ MemberSpecializationInfo *getInstantiatedFromStaticDataMember(
+ const VarDecl *Var);
+
+ TemplateOrSpecializationInfo
+ getTemplateOrSpecializationInfo(const VarDecl *Var);
+
+ FunctionDecl *getClassScopeSpecializationPattern(const FunctionDecl *FD);
+
+ void setClassScopeSpecializationPattern(FunctionDecl *FD,
+ FunctionDecl *Pattern);
+
+ /// \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());
+
+ void setTemplateOrSpecializationInfo(VarDecl *Inst,
+ TemplateOrSpecializationInfo TSI);
+
+ /// \brief If the given using decl \p Inst 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::const_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);
+
+ /// \brief Return C++ or ObjC overridden methods for the given \p Method.
+ ///
+ /// An ObjC method is considered to override any method in the class's
+ /// base classes, its protocols, or its categories' protocols, that has
+ /// the same selector and is of the same kind (class or instance).
+ /// A method in an implementation is not considered as overriding the same
+ /// method in the interface or its categories.
+ void getOverriddenMethods(
+ const NamedDecl *Method,
+ SmallVectorImpl<const NamedDecl *> &Overridden) const;
+
+ /// \brief Notify the AST context that a new import declaration has been
+ /// parsed or implicitly created within this translation unit.
+ void addedLocalImportDecl(ImportDecl *Import);
+
+ static ImportDecl *getNextLocalImport(ImportDecl *Import) {
+ return Import->NextLocalImport;
+ }
+
+ typedef llvm::iterator_range<import_iterator> import_range;
+ import_range local_imports() const {
+ return import_range(import_iterator(FirstLocalImport), import_iterator());
+ }
+
+ Decl *getPrimaryMergedDecl(Decl *D) {
+ Decl *Result = MergedDecls.lookup(D);
+ return Result ? Result : D;
+ }
+ void setPrimaryMergedDecl(Decl *D, Decl *Primary) {
+ MergedDecls[D] = Primary;
+ }
+
+ /// \brief Note that the definition \p ND has been merged into module \p M,
+ /// and should be visible whenever \p M is visible.
+ void mergeDefinitionIntoModule(NamedDecl *ND, Module *M,
+ bool NotifyListeners = true);
+ /// \brief Clean up the merged definition list. Call this if you might have
+ /// added duplicates into the list.
+ void deduplicateMergedDefinitonsFor(NamedDecl *ND);
+
+ /// \brief Get the additional modules in which the definition \p Def has
+ /// been merged.
+ ArrayRef<Module*> getModulesWithMergedDefinition(NamedDecl *Def) {
+ auto MergedIt = MergedDefModules.find(Def);
+ if (MergedIt == MergedDefModules.end())
+ return None;
+ return MergedIt->second;
+ }
+
+ TranslationUnitDecl *getTranslationUnitDecl() const { return TUDecl; }
+
+ ExternCContextDecl *getExternCContextDecl() const;
+ BuiltinTemplateDecl *getMakeIntegerSeqDecl() const;
+
+ // Builtin Types.
+ CanQualType VoidTy;
+ CanQualType BoolTy;
+ CanQualType CharTy;
+ CanQualType WCharTy; // [C++ 3.9.1p5].
+ CanQualType WideCharTy; // Same as WCharTy in C++, integer type in C99.
+ CanQualType WIntTy; // [C99 7.24.1], integer type unchanged by default promotions.
+ 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 HalfTy; // [OpenCL 6.1.1.1], ARM NEON
+ CanQualType FloatComplexTy, DoubleComplexTy, LongDoubleComplexTy;
+ CanQualType VoidPtrTy, NullPtrTy;
+ CanQualType DependentTy, OverloadTy, BoundMemberTy, UnknownAnyTy;
+ CanQualType BuiltinFnTy;
+ CanQualType PseudoObjectTy, ARCUnbridgedCastTy;
+ CanQualType ObjCBuiltinIdTy, ObjCBuiltinClassTy, ObjCBuiltinSelTy;
+ CanQualType ObjCBuiltinBoolTy;
+ CanQualType OCLImage1dTy, OCLImage1dArrayTy, OCLImage1dBufferTy;
+ CanQualType OCLImage2dTy, OCLImage2dArrayTy, OCLImage2dDepthTy;
+ CanQualType OCLImage2dArrayDepthTy, OCLImage2dMSAATy, OCLImage2dArrayMSAATy;
+ CanQualType OCLImage2dMSAADepthTy, OCLImage2dArrayMSAADepthTy;
+ CanQualType OCLImage3dTy;
+ CanQualType OCLSamplerTy, OCLEventTy, OCLClkEventTy;
+ CanQualType OCLQueueTy, OCLNDRangeTy, OCLReserveIDTy;
+ CanQualType OMPArraySectionTy;
+
+ // Types for deductions in C++0x [stmt.ranged]'s desugaring. Built on demand.
+ mutable QualType AutoDeductTy; // Deduction against 'auto'.
+ mutable QualType AutoRRefDeductTy; // Deduction against 'auto &&'.
+
+ // Decl used to help define __builtin_va_list for some targets.
+ // The decl is built when constructing 'BuiltinVaListDecl'.
+ mutable Decl *VaListTagDecl;
+
+ ASTContext(LangOptions &LOpts, SourceManager &SM, IdentifierTable &idents,
+ SelectorTable &sels, Builtin::Context &builtins);
+
+ ~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(IntrusiveRefCntPtr<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 SmallVectorImpl<Type *>& getTypes() const { return Types; }
+
+ BuiltinTemplateDecl *buildBuiltinTemplateDecl(BuiltinTemplateKind BTK,
+ const IdentifierInfo *II) const;
+
+ /// \brief Create a new implicit TU-level CXXRecordDecl or RecordDecl
+ /// declaration.
+ RecordDecl *buildImplicitRecord(StringRef Name,
+ RecordDecl::TagKind TK = TTK_Struct) const;
+
+ /// \brief Create a new implicit TU-level typedef declaration.
+ TypedefDecl *buildImplicitTypedef(QualType T, StringRef Name) const;
+
+ /// \brief Retrieve the declaration for the 128-bit signed integer type.
+ TypedefDecl *getInt128Decl() const;
+
+ /// \brief Retrieve the declaration for the 128-bit unsigned integer type.
+ TypedefDecl *getUInt128Decl() const;
+
+ /// \brief Retrieve the declaration for a 128-bit float stub type.
+ TypeDecl *getFloat128StubType() const;
+
+ //===--------------------------------------------------------------------===//
+ // Type Constructors
+ //===--------------------------------------------------------------------===//
+
+private:
+ /// \brief Return a type with extended qualifiers.
+ QualType getExtQualType(const Type *Base, Qualifiers Quals) const;
+
+ QualType getTypeDeclTypeSlow(const TypeDecl *Decl) const;
+
+public:
+ /// \brief 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;
+
+ /// \brief Return the uniqued reference to the type for an Objective-C
+ /// 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;
+
+ /// \brief Return the uniqued reference to the type for a \c restrict
+ /// qualified type.
+ ///
+ /// The resulting type has a union of the qualifiers from \p T and
+ /// \c restrict.
+ QualType getRestrictType(QualType T) const {
+ return T.withFastQualifiers(Qualifiers::Restrict);
+ }
+
+ /// \brief Return the uniqued reference to the type for a \c volatile
+ /// qualified type.
+ ///
+ /// The resulting type has a union of the qualifiers from \p T and
+ /// \c volatile.
+ QualType getVolatileType(QualType T) const {
+ return T.withFastQualifiers(Qualifiers::Volatile);
+ }
+
+ /// \brief Return the uniqued reference to the type for a \c const
+ /// qualified type.
+ ///
+ /// The resulting type has a union of the qualifiers from \p T and \c const.
+ ///
+ /// It can be reasonably expected that this will always be equivalent to
+ /// calling T.withConst().
+ QualType getConstType(QualType T) const { return T.withConst(); }
+
+ /// \brief Change the ExtInfo on a function type.
+ const FunctionType *adjustFunctionType(const FunctionType *Fn,
+ FunctionType::ExtInfo EInfo);
+
+ /// Adjust the given function result type.
+ CanQualType getCanonicalFunctionResultType(QualType ResultType) const;
+
+ /// \brief Change the result type of a function type once it is deduced.
+ void adjustDeducedFunctionResultType(FunctionDecl *FD, QualType ResultType);
+
+ /// \brief Change the exception specification on a function once it is
+ /// delay-parsed, instantiated, or computed.
+ void adjustExceptionSpec(FunctionDecl *FD,
+ const FunctionProtoType::ExceptionSpecInfo &ESI,
+ bool AsWritten = false);
+
+ /// \brief 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));
+ }
+
+ /// \brief 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));
+ }
+
+ /// \brief Return the uniqued reference to a type adjusted from the original
+ /// type to a new type.
+ QualType getAdjustedType(QualType Orig, QualType New) const;
+ CanQualType getAdjustedType(CanQualType Orig, CanQualType New) const {
+ return CanQualType::CreateUnsafe(
+ getAdjustedType((QualType)Orig, (QualType)New));
+ }
+
+ /// \brief Return the uniqued reference to the decayed version of the given
+ /// type. Can only be called on array and function types which decay to
+ /// pointer types.
+ QualType getDecayedType(QualType T) const;
+ CanQualType getDecayedType(CanQualType T) const {
+ return CanQualType::CreateUnsafe(getDecayedType((QualType) T));
+ }
+
+ /// \brief Return the uniqued reference to the atomic type for the specified
+ /// type.
+ QualType getAtomicType(QualType T) const;
+
+ /// \brief Return the uniqued reference to the type for a block of the
+ /// specified type.
+ QualType getBlockPointerType(QualType T) const;
+
+ /// Gets the struct used to keep track of the descriptor for pointer to
+ /// blocks.
+ QualType getBlockDescriptorType() const;
+
+ /// Gets the struct used to keep track of the extended descriptor for
+ /// pointer to blocks.
+ QualType getBlockDescriptorExtendedType() const;
+
+ void setcudaConfigureCallDecl(FunctionDecl *FD) {
+ cudaConfigureCallDecl = FD;
+ }
+ FunctionDecl *getcudaConfigureCallDecl() {
+ return cudaConfigureCallDecl;
+ }
+
+ /// Returns true iff we need copy/dispose helpers for the given type.
+ bool BlockRequiresCopying(QualType Ty, const VarDecl *D);
+
+
+ /// Returns true, if given type has a known lifetime. HasByrefExtendedLayout is set
+ /// to false in this case. If HasByrefExtendedLayout returns true, byref variable
+ /// has extended lifetime.
+ bool getByrefLifetime(QualType Ty,
+ Qualifiers::ObjCLifetime &Lifetime,
+ bool &HasByrefExtendedLayout) const;
+
+ /// \brief Return the uniqued reference to the type for an lvalue reference
+ /// to the specified type.
+ QualType getLValueReferenceType(QualType T, bool SpelledAsLValue = true)
+ const;
+
+ /// \brief Return the uniqued reference to the type for an rvalue reference
+ /// to the specified type.
+ QualType getRValueReferenceType(QualType T) const;
+
+ /// \brief Return the uniqued reference to the type for a member pointer to
+ /// the specified type in the specified class.
+ ///
+ /// The class \p Cls is a \c Type because it could be a dependent name.
+ QualType getMemberPointerType(QualType T, const Type *Cls) const;
+
+ /// \brief Return 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;
+
+ /// \brief Return 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;
+
+ /// \brief Return a unique reference to the type for an incomplete array of
+ /// the specified element type.
+ QualType getIncompleteArrayType(QualType EltTy,
+ ArrayType::ArraySizeModifier ASM,
+ unsigned IndexTypeQuals) const;
+
+ /// \brief 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;
+
+ /// \brief Returns a vla type where known sizes are replaced with [*].
+ QualType getVariableArrayDecayedType(QualType Ty) const;
+
+ /// \brief Return the unique reference to a vector type of the specified
+ /// element type and size.
+ ///
+ /// \pre \p VectorType must be a built-in type.
+ QualType getVectorType(QualType VectorType, unsigned NumElts,
+ VectorType::VectorKind VecKind) const;
+
+ /// \brief Return the unique reference to an extended vector type
+ /// of the specified element type and size.
+ ///
+ /// \pre \p VectorType must be a built-in type.
+ QualType getExtVectorType(QualType VectorType, unsigned NumElts) const;
+
+ /// \pre Return 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;
+
+ /// \brief 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());
+ }
+
+ /// \brief Return a normal function type with a typed argument list.
+ QualType getFunctionType(QualType ResultTy, ArrayRef<QualType> Args,
+ const FunctionProtoType::ExtProtoInfo &EPI) const;
+
+ /// \brief Return the unique reference to the type for the specified type
+ /// declaration.
+ QualType getTypeDeclType(const TypeDecl *Decl,
+ const TypeDecl *PrevDecl = nullptr) 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);
+ }
+
+ /// \brief Return the unique reference to the type for the specified
+ /// typedef-name decl.
+ QualType getTypedefType(const TypedefNameDecl *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,
+ TemplateTypeParmDecl *ParmDecl = nullptr) 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,
+ Optional<unsigned> NumExpansions);
+
+ QualType getObjCInterfaceType(const ObjCInterfaceDecl *Decl,
+ ObjCInterfaceDecl *PrevDecl = nullptr) const;
+
+ /// Legacy interface: cannot provide type arguments or __kindof.
+ QualType getObjCObjectType(QualType Base,
+ ObjCProtocolDecl * const *Protocols,
+ unsigned NumProtocols) const;
+
+ QualType getObjCObjectType(QualType Base,
+ ArrayRef<QualType> typeArgs,
+ ArrayRef<ObjCProtocolDecl *> protocols,
+ bool isKindOf) const;
+
+ bool ObjCObjectAdoptsQTypeProtocols(QualType QT, ObjCInterfaceDecl *Decl);
+ /// QIdProtocolsAdoptObjCObjectProtocols - Checks that protocols in
+ /// QT's qualified-id protocol list adopt all protocols in IDecl's list
+ /// of protocols.
+ bool QIdProtocolsAdoptObjCObjectProtocols(QualType QT,
+ ObjCInterfaceDecl *IDecl);
+
+ /// \brief Return a ObjCObjectPointerType type for the given ObjCObjectType.
+ QualType getObjCObjectPointerType(QualType OIT) const;
+
+ /// \brief GCC extension.
+ QualType getTypeOfExprType(Expr *e) const;
+ QualType getTypeOfType(QualType t) const;
+
+ /// \brief C++11 decltype.
+ QualType getDecltypeType(Expr *e, QualType UnderlyingType) const;
+
+ /// \brief Unary type transforms
+ QualType getUnaryTransformType(QualType BaseType, QualType UnderlyingType,
+ UnaryTransformType::UTTKind UKind) const;
+
+ /// \brief C++11 deduced auto type.
+ QualType getAutoType(QualType DeducedType, AutoTypeKeyword Keyword,
+ bool IsDependent) const;
+
+ /// \brief C++11 deduction pattern for 'auto' type.
+ QualType getAutoDeductType() const;
+
+ /// \brief C++11 deduction pattern for 'auto &&' type.
+ QualType getAutoRRefDeductType() const;
+
+ /// \brief Return the unique reference to the type for the specified TagDecl
+ /// (struct/union/class/enum) decl.
+ QualType getTagDeclType(const TagDecl *Decl) const;
+
+ /// \brief 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;
+
+ /// \brief Return the unique type for "intmax_t" (C99 7.18.1.5), defined in
+ /// <stdint.h>.
+ CanQualType getIntMaxType() const;
+
+ /// \brief Return the unique type for "uintmax_t" (C99 7.18.1.5), defined in
+ /// <stdint.h>.
+ CanQualType getUIntMaxType() const;
+
+ /// \brief Return the unique wchar_t type available in C++ (and available as
+ /// __wchar_t as a Microsoft extension).
+ QualType getWCharType() const { return WCharTy; }
+
+ /// \brief Return the type of wide characters. 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 getWideCharType() const { return WideCharTy; }
+
+ /// \brief Return the type of "signed wchar_t".
+ ///
+ /// Used when in C++, as a GCC extension.
+ QualType getSignedWCharType() const;
+
+ /// \brief Return the type of "unsigned wchar_t".
+ ///
+ /// Used when in C++, as a GCC extension.
+ QualType getUnsignedWCharType() const;
+
+ /// \brief In C99, this returns a type compatible with the type
+ /// defined in <stddef.h> as defined by the target.
+ QualType getWIntType() const { return WIntTy; }
+
+ /// \brief Return a type compatible with "intptr_t" (C99 7.18.1.4),
+ /// as defined by the target.
+ QualType getIntPtrType() const;
+
+ /// \brief Return a type compatible with "uintptr_t" (C99 7.18.1.4),
+ /// as defined by the target.
+ QualType getUIntPtrType() const;
+
+ /// \brief Return the unique type for "ptrdiff_t" (C99 7.17) defined in
+ /// <stddef.h>. Pointer - pointer requires this (C99 6.5.6p9).
+ QualType getPointerDiffType() const;
+
+ /// \brief Return the unique type for "pid_t" defined in
+ /// <sys/types.h>. We need this to compute the correct type for vfork().
+ QualType getProcessIDType() const;
+
+ /// \brief Return the C structure type used to represent constant CFStrings.
+ QualType getCFConstantStringType() const;
+
+ /// \brief Returns the C struct type for objc_super
+ QualType getObjCSuperType() const;
+ void setObjCSuperType(QualType ST) { ObjCSuperType = ST; }
+
+ /// 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;
+ }
+
+ QualType getObjCNSStringType() const {
+ return ObjCNSStringType;
+ }
+
+ void setObjCNSStringType(QualType T) {
+ ObjCNSStringType = T;
+ }
+
+ /// \brief Retrieve the type that \c id has been defined to, which may be
+ /// different from the built-in \c id if \c id has been typedef'd.
+ QualType getObjCIdRedefinitionType() const {
+ if (ObjCIdRedefinitionType.isNull())
+ return getObjCIdType();
+ return ObjCIdRedefinitionType;
+ }
+
+ /// \brief Set the user-written type that redefines \c id.
+ void setObjCIdRedefinitionType(QualType RedefType) {
+ ObjCIdRedefinitionType = RedefType;
+ }
+
+ /// \brief Retrieve the type that \c Class has been defined to, which may be
+ /// different from the built-in \c Class if \c Class has been typedef'd.
+ QualType getObjCClassRedefinitionType() const {
+ if (ObjCClassRedefinitionType.isNull())
+ return getObjCClassType();
+ return ObjCClassRedefinitionType;
+ }
+
+ /// \brief Set the user-written type that redefines 'SEL'.
+ void setObjCClassRedefinitionType(QualType RedefType) {
+ ObjCClassRedefinitionType = RedefType;
+ }
+
+ /// \brief Retrieve the type that 'SEL' has been defined to, which may be
+ /// different from the built-in 'SEL' if 'SEL' has been typedef'd.
+ QualType getObjCSelRedefinitionType() const {
+ if (ObjCSelRedefinitionType.isNull())
+ return getObjCSelType();
+ return ObjCSelRedefinitionType;
+ }
+
+
+ /// \brief Set the user-written type that redefines 'SEL'.
+ void setObjCSelRedefinitionType(QualType RedefType) {
+ ObjCSelRedefinitionType = RedefType;
+ }
+
+ /// Retrieve the identifier 'NSObject'.
+ IdentifierInfo *getNSObjectName() {
+ if (!NSObjectName) {
+ NSObjectName = &Idents.get("NSObject");
+ }
+
+ return NSObjectName;
+ }
+
+ /// Retrieve the identifier 'NSCopying'.
+ IdentifierInfo *getNSCopyingName() {
+ if (!NSCopyingName) {
+ NSCopyingName = &Idents.get("NSCopying");
+ }
+
+ return NSCopyingName;
+ }
+
+ IdentifierInfo *getMakeIntegerSeqName() const {
+ if (!MakeIntegerSeqName)
+ MakeIntegerSeqName = &Idents.get("__make_integer_seq");
+ return MakeIntegerSeqName;
+ }
+
+ /// \brief Retrieve the Objective-C "instancetype" type, if already known;
+ /// otherwise, returns a NULL type;
+ QualType getObjCInstanceType() {
+ return getTypeDeclType(getObjCInstanceTypeDecl());
+ }
+
+ /// \brief Retrieve the typedef declaration corresponding to the Objective-C
+ /// "instancetype" type.
+ TypedefDecl *getObjCInstanceTypeDecl();
+
+ /// \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 Set the type for the C ucontext_t type.
+ void setucontext_tDecl(TypeDecl *ucontext_tDecl) {
+ this->ucontext_tDecl = ucontext_tDecl;
+ }
+
+ /// \brief Retrieve the C ucontext_t type.
+ QualType getucontext_tType() const {
+ if (ucontext_tDecl)
+ return getTypeDeclType(ucontext_tDecl);
+ return QualType();
+ }
+
+ /// \brief The result type of logical operations, '<', '>', '!=', etc.
+ QualType getLogicalOperationType() const {
+ return getLangOpts().CPlusPlus ? BoolTy : IntTy;
+ }
+
+ /// \brief Emit the Objective-CC type encoding for the given type \p T into
+ /// \p S.
+ ///
+ /// If \p Field is specified then record field names are also encoded.
+ void getObjCEncodingForType(QualType T, std::string &S,
+ const FieldDecl *Field=nullptr,
+ QualType *NotEncodedT=nullptr) const;
+
+ /// \brief Emit the Objective-C property type encoding for the given
+ /// type \p T into \p S.
+ void getObjCEncodingForPropertyType(QualType T, std::string &S) const;
+
+ void getLegacyIntegralTypeEncoding(QualType &t) const;
+
+ /// \brief Put the string version of the type qualifiers \p QT into \p S.
+ void getObjCEncodingForTypeQualifier(Decl::ObjCDeclQualifier QT,
+ std::string &S) const;
+
+ /// \brief Emit the encoded type for the function \p Decl into \p S.
+ ///
+ /// This is in the same format as Objective-C method encodings.
+ ///
+ /// \returns true if an error occurred (e.g., because one of the parameter
+ /// types is incomplete), false otherwise.
+ bool getObjCEncodingForFunctionDecl(const FunctionDecl *Decl, std::string& S);
+
+ /// \brief Emit the encoded type for the method declaration \p Decl into
+ /// \p S.
+ ///
+ /// \returns true if an error occurred (e.g., because one of the parameter
+ /// types is incomplete), false otherwise.
+ bool getObjCEncodingForMethodDecl(const ObjCMethodDecl *Decl, std::string &S,
+ bool Extended = false)
+ const;
+
+ /// \brief 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;
+
+ ObjCPropertyImplDecl *getObjCPropertyImplDeclForPropertyDecl(
+ const ObjCPropertyDecl *PD,
+ const Decl *Container) const;
+
+ /// \brief Return the size of type \p T for Objective-C encoding purpose,
+ /// in characters.
+ CharUnits getObjCEncodingTypeSize(QualType T) const;
+
+ /// \brief Retrieve the typedef corresponding to the predefined \c id type
+ /// in Objective-C.
+ TypedefDecl *getObjCIdDecl() const;
+
+ /// \brief Represents the Objective-CC \c id type.
+ ///
+ /// This is set up lazily, by Sema. \c id is always a (typedef for a)
+ /// pointer type, a pointer to a struct.
+ QualType getObjCIdType() const {
+ return getTypeDeclType(getObjCIdDecl());
+ }
+
+ /// \brief Retrieve the typedef corresponding to the predefined 'SEL' type
+ /// in Objective-C.
+ TypedefDecl *getObjCSelDecl() const;
+
+ /// \brief Retrieve the type that corresponds to the predefined Objective-C
+ /// 'SEL' type.
+ QualType getObjCSelType() const {
+ return getTypeDeclType(getObjCSelDecl());
+ }
+
+ /// \brief Retrieve the typedef declaration corresponding to the predefined
+ /// Objective-C 'Class' type.
+ TypedefDecl *getObjCClassDecl() const;
+
+ /// \brief Represents the Objective-C \c Class type.
+ ///
+ /// This is set up lazily, by Sema. \c Class is always a (typedef for a)
+ /// pointer type, a pointer to a struct.
+ QualType getObjCClassType() const {
+ return getTypeDeclType(getObjCClassDecl());
+ }
+
+ /// \brief Retrieve the Objective-C class declaration corresponding to
+ /// the predefined \c Protocol class.
+ ObjCInterfaceDecl *getObjCProtocolDecl() const;
+
+ /// \brief Retrieve declaration of 'BOOL' typedef
+ TypedefDecl *getBOOLDecl() const {
+ return BOOLDecl;
+ }
+
+ /// \brief Save declaration of 'BOOL' typedef
+ void setBOOLDecl(TypedefDecl *TD) {
+ BOOLDecl = TD;
+ }
+
+ /// \brief type of 'BOOL' type.
+ QualType getBOOLType() const {
+ return getTypeDeclType(getBOOLDecl());
+ }
+
+ /// \brief Retrieve the type of the Objective-C \c Protocol class.
+ QualType getObjCProtoType() const {
+ return getObjCInterfaceType(getObjCProtocolDecl());
+ }
+
+ /// \brief Retrieve the C type declaration corresponding to the predefined
+ /// \c __builtin_va_list type.
+ TypedefDecl *getBuiltinVaListDecl() const;
+
+ /// \brief Retrieve the type of the \c __builtin_va_list type.
+ QualType getBuiltinVaListType() const {
+ return getTypeDeclType(getBuiltinVaListDecl());
+ }
+
+ /// \brief Retrieve the C type declaration corresponding to the predefined
+ /// \c __va_list_tag type used to help define the \c __builtin_va_list type
+ /// for some targets.
+ Decl *getVaListTagDecl() const;
+
+ /// Retrieve the C type declaration corresponding to the predefined
+ /// \c __builtin_ms_va_list type.
+ TypedefDecl *getBuiltinMSVaListDecl() const;
+
+ /// Retrieve the type of the \c __builtin_ms_va_list type.
+ QualType getBuiltinMSVaListType() const {
+ return getTypeDeclType(getBuiltinMSVaListDecl());
+ }
+
+ /// \brief Return a type with additional \c const, \c volatile, or
+ /// \c restrict qualifiers.
+ QualType getCVRQualifiedType(QualType T, unsigned CVR) const {
+ return getQualifiedType(T, Qualifiers::fromCVRMask(CVR));
+ }
+
+ /// \brief Un-split a SplitQualType.
+ QualType getQualifiedType(SplitQualType split) const {
+ return getQualifiedType(split.Ty, split.Quals);
+ }
+
+ /// \brief Return 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);
+ }
+
+ /// \brief Return 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);
+ }
+
+ /// \brief Return a type with the given lifetime qualifier.
+ ///
+ /// \pre Neither type.ObjCLifetime() nor \p lifetime may be \c OCL_None.
+ QualType getLifetimeQualifiedType(QualType type,
+ Qualifiers::ObjCLifetime lifetime) {
+ assert(type.getObjCLifetime() == Qualifiers::OCL_None);
+ assert(lifetime != Qualifiers::OCL_None);
+
+ Qualifiers qs;
+ qs.addObjCLifetime(lifetime);
+ return getQualifiedType(type, qs);
+ }
+
+ /// getUnqualifiedObjCPointerType - Returns version of
+ /// Objective-C pointer type with lifetime qualifier removed.
+ QualType getUnqualifiedObjCPointerType(QualType type) const {
+ if (!type.getTypePtr()->isObjCObjectPointerType() ||
+ !type.getQualifiers().hasObjCLifetime())
+ return type;
+ Qualifiers Qs = type.getQualifiers();
+ Qs.removeObjCLifetime();
+ return getQualifiedType(type.getUnqualifiedType(), 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 getSubstTemplateTemplateParm(TemplateTemplateParmDecl *param,
+ TemplateName replacement) 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>
+ GE_Missing_ucontext ///< Missing a type from <ucontext.h>
+ };
+
+ /// \brief Return the type for the specified builtin.
+ ///
+ /// If \p 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 = nullptr) const;
+
+private:
+ CanQualType getFromTargetType(unsigned Type) const;
+ TypeInfo getTypeInfoImpl(const Type *T) const;
+
+ //===--------------------------------------------------------------------===//
+ // Type Predicates.
+ //===--------------------------------------------------------------------===//
+
+public:
+ /// \brief Return one of the GCNone, Weak or Strong Objective-C garbage
+ /// collection attributes.
+ Qualifiers::GC getObjCGCAttrKind(QualType Ty) const;
+
+ /// \brief Return true if the given vector types are of the same unqualified
+ /// type or if they are equivalent to the same GCC vector type.
+ ///
+ /// \note This ignores whether they are target-specific (AltiVec or Neon)
+ /// types.
+ bool areCompatibleVectorTypes(QualType FirstVec, QualType SecondVec);
+
+ /// \brief Return true if this is an \c NSObject object with its \c NSObject
+ /// attribute set.
+ static bool isObjCNSObjectType(QualType Ty) {
+ return Ty->isObjCNSObjectType();
+ }
+
+ //===--------------------------------------------------------------------===//
+ // Type Sizing and Analysis
+ //===--------------------------------------------------------------------===//
+
+ /// \brief Return the APFloat 'semantics' for the specified scalar floating
+ /// point type.
+ const llvm::fltSemantics &getFloatTypeSemantics(QualType T) const;
+
+ /// \brief Get the size and alignment of the specified complete type in bits.
+ TypeInfo getTypeInfo(const Type *T) const;
+ TypeInfo getTypeInfo(QualType T) const { return getTypeInfo(T.getTypePtr()); }
+
+ /// \brief Get default simd alignment of the specified complete type in bits.
+ unsigned getOpenMPDefaultSimdAlign(QualType T) const;
+
+ /// \brief Return the size of the specified (complete) type \p T, in bits.
+ uint64_t getTypeSize(QualType T) const { return getTypeInfo(T).Width; }
+ uint64_t getTypeSize(const Type *T) const { return getTypeInfo(T).Width; }
+
+ /// \brief Return the size of the character type, in bits.
+ uint64_t getCharWidth() const {
+ return getTypeSize(CharTy);
+ }
+
+ /// \brief Convert a size in bits to a size in characters.
+ CharUnits toCharUnitsFromBits(int64_t BitSize) const;
+
+ /// \brief Convert a size in characters to a size in bits.
+ int64_t toBits(CharUnits CharSize) const;
+
+ /// \brief Return the size of the specified (complete) type \p T, in
+ /// characters.
+ CharUnits getTypeSizeInChars(QualType T) const;
+ CharUnits getTypeSizeInChars(const Type *T) const;
+
+ /// \brief Return the ABI-specified alignment of a (complete) type \p T, in
+ /// bits.
+ unsigned getTypeAlign(QualType T) const { return getTypeInfo(T).Align; }
+ unsigned getTypeAlign(const Type *T) const { return getTypeInfo(T).Align; }
+
+ /// \brief Return the ABI-specified alignment of a (complete) type \p T, in
+ /// characters.
+ CharUnits getTypeAlignInChars(QualType T) const;
+ CharUnits getTypeAlignInChars(const Type *T) const;
+
+ // getTypeInfoDataSizeInChars - Return the size of a type, in chars. If the
+ // type is a record, its data size is returned.
+ std::pair<CharUnits, CharUnits> getTypeInfoDataSizeInChars(QualType T) const;
+
+ std::pair<CharUnits, CharUnits> getTypeInfoInChars(const Type *T) const;
+ std::pair<CharUnits, CharUnits> getTypeInfoInChars(QualType T) const;
+
+ /// \brief Determine if the alignment the type has was required using an
+ /// alignment attribute.
+ bool isAlignmentRequired(const Type *T) const;
+ bool isAlignmentRequired(QualType T) const;
+
+ /// \brief Return the "preferred" alignment of the specified type \p T 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;
+
+ /// \brief Return the default alignment for __attribute__((aligned)) on
+ /// this target, to be used if no alignment value is specified.
+ unsigned getTargetDefaultAlignForAttributeAligned(void) const;
+
+ /// \brief Return the alignment in bits that should be given to a
+ /// global variable with type \p T.
+ unsigned getAlignOfGlobalVar(QualType T) const;
+
+ /// \brief Return the alignment in characters that should be given to a
+ /// global variable with type \p T.
+ CharUnits getAlignOfGlobalVarInChars(QualType T) const;
+
+ /// \brief Return a conservative estimate of the alignment of the specified
+ /// decl \p D.
+ ///
+ /// \pre \p D must not be a bitfield type, as bitfields do not have a valid
+ /// alignment.
+ ///
+ /// If \p ForAlignof, references are treated like their underlying type
+ /// and large arrays don't get any special treatment. If not \p ForAlignof
+ /// it computes the value expected by CodeGen: references are treated like
+ /// pointers and large arrays get extra alignment.
+ CharUnits getDeclAlign(const Decl *D, bool ForAlignof = false) const;
+
+ /// \brief Get or compute information about the layout of the specified
+ /// record (struct/union/class) \p D, which indicates its size and field
+ /// position information.
+ const ASTRecordLayout &getASTRecordLayout(const RecordDecl *D) const;
+
+ /// \brief 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, raw_ostream &OS,
+ bool Simple = false) const;
+
+ /// \brief 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;
+
+ /// \brief Get our current best idea for the key function of 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.
+ ///
+ /// Other ABIs use the same idea. However, the ARM C++ ABI ignores
+ /// virtual functions that are defined 'inline', which means that
+ /// the result of this computation can change.
+ const CXXMethodDecl *getCurrentKeyFunction(const CXXRecordDecl *RD);
+
+ /// \brief Observe that the given method cannot be a key function.
+ /// Checks the key-function cache for the method's class and clears it
+ /// if matches the given declaration.
+ ///
+ /// This is used in ABIs where out-of-line definitions marked
+ /// inline are not considered to be key functions.
+ ///
+ /// \param method should be the declaration from the class definition
+ void setNonKeyFunction(const CXXMethodDecl *method);
+
+ /// Loading virtual member pointers using the virtual inheritance model
+ /// always results in an adjustment using the vbtable even if the index is
+ /// zero.
+ ///
+ /// This is usually OK because the first slot in the vbtable points
+ /// backwards to the top of the MDC. However, the MDC might be reusing a
+ /// vbptr from an nv-base. In this case, the first slot in the vbtable
+ /// points to the start of the nv-base which introduced the vbptr and *not*
+ /// the MDC. Modify the NonVirtualBaseAdjustment to account for this.
+ CharUnits getOffsetOfBaseWithVBPtr(const CXXRecordDecl *RD) const;
+
+ /// Get the offset of a FieldDecl or IndirectFieldDecl, in bits.
+ uint64_t getFieldOffset(const ValueDecl *FD) const;
+
+ bool isNearlyEmpty(const CXXRecordDecl *RD) const;
+
+ VTableContextBase *getVTableContext();
+
+ MangleContext *createMangleContext();
+
+ void DeepCollectObjCIvars(const ObjCInterfaceDecl *OI, bool leafClass,
+ SmallVectorImpl<const ObjCIvarDecl*> &Ivars) const;
+
+ unsigned CountNonClassIvars(const ObjCInterfaceDecl *OI) const;
+ void CollectInheritedProtocols(const Decl *CDecl,
+ llvm::SmallPtrSet<ObjCProtocolDecl*, 8> &Protocols);
+
+ //===--------------------------------------------------------------------===//
+ // Type Operators
+ //===--------------------------------------------------------------------===//
+
+ /// \brief Return the canonical (structural) type corresponding to the
+ /// specified potentially non-canonical type \p T.
+ ///
+ /// 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();
+ }
+
+ /// \brief 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 \p T1 and \p T2 are equivalent.
+ bool hasSameType(QualType T1, QualType T2) const {
+ return getCanonicalType(T1) == getCanonicalType(T2);
+ }
+
+ bool hasSameType(const Type *T1, const Type *T2) const {
+ return getCanonicalType(T1) == getCanonicalType(T2);
+ }
+
+ /// \brief Return this type as a completely-unqualified array type,
+ /// capturing the qualifiers in \p 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) const {
+ return getCanonicalType(T1).getTypePtr() ==
+ getCanonicalType(T2).getTypePtr();
+ }
+
+ bool hasSameNullabilityTypeQualifier(QualType SubT, QualType SuperT,
+ bool IsParam) const {
+ auto SubTnullability = SubT->getNullability(*this);
+ auto SuperTnullability = SuperT->getNullability(*this);
+ if (SubTnullability.hasValue() == SuperTnullability.hasValue()) {
+ // Neither has nullability; return true
+ if (!SubTnullability)
+ return true;
+ // Both have nullability qualifier.
+ if (*SubTnullability == *SuperTnullability ||
+ *SubTnullability == NullabilityKind::Unspecified ||
+ *SuperTnullability == NullabilityKind::Unspecified)
+ return true;
+
+ if (IsParam) {
+ // Ok for the superclass method parameter to be "nonnull" and the subclass
+ // method parameter to be "nullable"
+ return (*SuperTnullability == NullabilityKind::NonNull &&
+ *SubTnullability == NullabilityKind::Nullable);
+ }
+ else {
+ // For the return type, it's okay for the superclass method to specify
+ // "nullable" and the subclass method specify "nonnull"
+ return (*SuperTnullability == NullabilityKind::Nullable &&
+ *SubTnullability == NullabilityKind::NonNull);
+ }
+ }
+ return true;
+ }
+
+ bool ObjCMethodsAreEqual(const ObjCMethodDecl *MethodDecl,
+ const ObjCMethodDecl *MethodImp);
+
+ 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 for the current target.
+ CallingConv getDefaultCallingConvention(bool isVariadic,
+ bool IsCXXMethod) const;
+
+ /// \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));
+ }
+
+ /// \brief Return the innermost element type of an array type.
+ ///
+ /// For example, will return "int" for int[m][n]
+ QualType getBaseElementType(const ArrayType *VAT) const;
+
+ /// \brief Return the innermost element type of a type (which needn't
+ /// actually be an array type).
+ QualType getBaseElementType(QualType QT) const;
+
+ /// \brief Return number of constant array elements.
+ uint64_t getConstantArrayElementCount(const ConstantArrayType *CA) const;
+
+ /// \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 getAdjustedParameterType(QualType T) const;
+
+ /// \brief Retrieve the parameter type as adjusted for use in the signature
+ /// of a function, decaying array and function types and removing top-level
+ /// cv-qualifiers.
+ QualType getSignatureParameterType(QualType T) const;
+
+ QualType getExceptionObjectType(QualType T) const;
+
+ /// \brief 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 \p 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;
+
+ /// \brief Return the type that \p PromotableType will promote to: C99
+ /// 6.3.1.1p2, assuming that \p PromotableType is a promotable integer type.
+ QualType getPromotedIntegerType(QualType PromotableType) const;
+
+ /// \brief Recurses in pointer/array types until it finds an Objective-C
+ /// retainable type and returns its ownership.
+ Qualifiers::ObjCLifetime getInnerObjCOwnership(QualType T) 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;
+
+ /// \brief Return the highest ranked integer type, see C99 6.3.1.8p1.
+ ///
+ /// If \p LHS > \p RHS, returns 1. If \p LHS == \p RHS, returns 0. If
+ /// \p LHS < \p RHS, return -1.
+ int getIntegerTypeOrder(QualType LHS, QualType RHS) const;
+
+ /// \brief Compare the rank of the two specified floating point types,
+ /// ignoring the domain of the type (i.e. 'double' == '_Complex double').
+ ///
+ /// If \p LHS > \p RHS, returns 1. If \p LHS == \p RHS, returns 0. If
+ /// \p LHS < \p RHS, return -1.
+ int getFloatingTypeOrder(QualType LHS, QualType RHS) const;
+
+ /// \brief Return a real floating point or a complex type (based on
+ /// \p typeDomain/\p typeSize).
+ ///
+ /// \param typeDomain a real floating point or complex type.
+ /// \param typeSize a real floating point or complex type.
+ QualType getFloatingTypeOfSizeWithinDomain(QualType typeSize,
+ QualType typeDomain) const;
+
+ unsigned getTargetAddressSpace(QualType T) const {
+ return getTargetAddressSpace(T.getQualifiers());
+ }
+
+ unsigned getTargetAddressSpace(Qualifiers Q) const {
+ return getTargetAddressSpace(Q.getAddressSpace());
+ }
+
+ unsigned getTargetAddressSpace(unsigned AS) const {
+ if (AS < LangAS::Offset || AS >= LangAS::Offset + LangAS::Count)
+ return AS;
+ else
+ return (*AddrSpaceMap)[AS - LangAS::Offset];
+ }
+
+ bool addressSpaceMapManglingFor(unsigned AS) const {
+ return AddrSpaceMapMangling ||
+ AS < LangAS::Offset ||
+ AS >= LangAS::Offset + LangAS::Count;
+ }
+
+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 propertyTypesAreCompatible(QualType, QualType);
+ bool typesAreBlockPointerCompatible(QualType, QualType);
+
+ bool isObjCIdType(QualType T) const {
+ return T == getObjCIdType();
+ }
+ bool isObjCClassType(QualType T) const {
+ return T == getObjCClassType();
+ }
+ bool isObjCSelType(QualType T) const {
+ return T == getObjCSelType();
+ }
+ 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 BlockReturnType);
+ 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, bool BlockReturnType = false);
+ QualType mergeFunctionTypes(QualType, QualType, bool OfBlockPointer=false,
+ bool Unqualified = false);
+ QualType mergeFunctionParameterTypes(QualType, QualType,
+ bool OfBlockPointer = false,
+ bool Unqualified = false);
+ QualType mergeTransparentUnionType(QualType, QualType,
+ bool OfBlockPointer=false,
+ bool Unqualified = false);
+
+ QualType mergeObjCGCQualifiers(QualType, QualType);
+
+ bool FunctionTypesMatchOnNSConsumedAttrs(
+ const FunctionProtoType *FromFunctionType,
+ const FunctionProtoType *ToFunctionType);
+
+ void ResetObjCLayout(const ObjCContainerDecl *CD);
+
+ //===--------------------------------------------------------------------===//
+ // 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) const;
+
+ //===--------------------------------------------------------------------===//
+ // Integer Values
+ //===--------------------------------------------------------------------===//
+
+ /// \brief Make an APSInt of the appropriate width and signedness for the
+ /// given \p Value and integer \p Type.
+ llvm::APSInt MakeIntValue(uint64_t Value, QualType Type) const {
+ llvm::APSInt Res(getIntWidth(Type),
+ !Type->isSignedIntegerOrEnumerationType());
+ Res = Value;
+ return Res;
+ }
+
+ bool isSentinelNullExpr(const Expr *E);
+
+ /// \brief Get the implementation of the ObjCInterfaceDecl \p D, or NULL if
+ /// none exists.
+ ObjCImplementationDecl *getObjCImplementation(ObjCInterfaceDecl *D);
+ /// \brief Get the implementation of the ObjCCategoryDecl \p D, or NULL if
+ /// none exists.
+ ObjCCategoryImplDecl *getObjCImplementation(ObjCCategoryDecl *D);
+
+ /// \brief Return true if there is at least one \@implementation in the 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 Get the duplicate declaration of a ObjCMethod in the same
+ /// interface, or null if none exists.
+ const ObjCMethodDecl *
+ getObjCMethodRedeclaration(const ObjCMethodDecl *MD) const;
+
+ void setObjCMethodRedeclaration(const ObjCMethodDecl *MD,
+ const ObjCMethodDecl *Redecl);
+
+ /// \brief Returns the Objective-C interface that \p ND belongs to if it is
+ /// an Objective-C method/property/ivar etc. that is part of an interface,
+ /// otherwise returns null.
+ const ObjCInterfaceDecl *getObjContainingInterface(const NamedDecl *ND) const;
+
+ /// \brief Set the copy inialization expression of a block var decl.
+ void setBlockVarCopyInits(VarDecl*VD, Expr* Init);
+ /// \brief Get the copy initialization expression of the VarDecl \p VD, 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;
+
+ /// \brief Add a deallocation callback that will be invoked when the
+ /// ASTContext is destroyed.
+ ///
+ /// \param Callback A callback function that will be invoked on destruction.
+ ///
+ /// \param 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) const;
+ 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);
+
+ const CXXConstructorDecl *
+ getCopyConstructorForExceptionObject(CXXRecordDecl *RD);
+
+ void addCopyConstructorForExceptionObject(CXXRecordDecl *RD,
+ CXXConstructorDecl *CD);
+
+ void addDefaultArgExprForConstructor(const CXXConstructorDecl *CD,
+ unsigned ParmIdx, Expr *DAE);
+
+ Expr *getDefaultArgExprForConstructor(const CXXConstructorDecl *CD,
+ unsigned ParmIdx);
+
+ void addTypedefNameForUnnamedTagDecl(TagDecl *TD, TypedefNameDecl *TND);
+
+ TypedefNameDecl *getTypedefNameForUnnamedTagDecl(const TagDecl *TD);
+
+ void addDeclaratorForUnnamedTagDecl(TagDecl *TD, DeclaratorDecl *DD);
+
+ DeclaratorDecl *getDeclaratorForUnnamedTagDecl(const TagDecl *TD);
+
+ void setManglingNumber(const NamedDecl *ND, unsigned Number);
+ unsigned getManglingNumber(const NamedDecl *ND) const;
+
+ void setStaticLocalNumber(const VarDecl *VD, unsigned Number);
+ unsigned getStaticLocalNumber(const VarDecl *VD) const;
+
+ /// \brief Retrieve the context for computing mangling numbers in the given
+ /// DeclContext.
+ MangleNumberingContext &getManglingNumberContext(const DeclContext *DC);
+
+ MangleNumberingContext *createMangleNumberingContext() const;
+
+ /// \brief Used by ParmVarDecl to store on the side the
+ /// index of the parameter when it exceeds the size of the normal bitfield.
+ void setParameterIndex(const ParmVarDecl *D, unsigned index);
+
+ /// \brief Used by ParmVarDecl to retrieve on the side the
+ /// index of the parameter when it exceeds the size of the normal bitfield.
+ unsigned getParameterIndex(const ParmVarDecl *D) const;
+
+ /// \brief Get the storage for the constant value of a materialized temporary
+ /// of static storage duration.
+ APValue *getMaterializedTemporaryValue(const MaterializeTemporaryExpr *E,
+ bool MayCreate);
+
+ //===--------------------------------------------------------------------===//
+ // 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 move constructors.
+ static unsigned NumImplicitMoveConstructors;
+
+ /// \brief The number of implicitly-declared move constructors for
+ /// which declarations were built.
+ static unsigned NumImplicitMoveConstructorsDeclared;
+
+ /// \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 move assignment operators.
+ static unsigned NumImplicitMoveAssignmentOperators;
+
+ /// \brief The number of implicitly-declared move assignment operators for
+ /// which declarations were built.
+ static unsigned NumImplicitMoveAssignmentOperatorsDeclared;
+
+ /// \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 &) = delete;
+ void operator=(const ASTContext &) = delete;
+
+public:
+ /// \brief Initialize built-in types.
+ ///
+ /// This routine may only be invoked once for a given ASTContext object.
+ /// It is normally invoked after ASTContext construction.
+ ///
+ /// \param Target The target
+ void InitBuiltinTypes(const TargetInfo &Target,
+ const TargetInfo *AuxTarget = nullptr);
+
+private:
+ void InitBuiltinType(CanQualType &R, BuiltinType::Kind K);
+
+ // Return the Objective-C 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,
+ bool StructField = false,
+ bool EncodeBlockParameters = false,
+ bool EncodeClassNames = false,
+ bool EncodePointerToObjCTypedef = false,
+ QualType *NotEncodedT=nullptr) const;
+
+ // Adds the encoding of the structure's members.
+ void getObjCEncodingForStructureImpl(RecordDecl *RD, std::string &S,
+ const FieldDecl *Field,
+ bool includeVBases = true,
+ QualType *NotEncodedT=nullptr) const;
+public:
+ // Adds the encoding of a method parameter or return type.
+ void getObjCEncodingForMethodParameter(Decl::ObjCDeclQualifier QT,
+ QualType T, std::string& S,
+ bool Extended) const;
+
+ /// \brief Returns true if this is an inline-initialized static data member
+ /// which is treated as a definition for MSVC compatibility.
+ bool isMSStaticDataMemberInlineDefinition(const VarDecl *VD) const;
+
+private:
+ const ASTRecordLayout &
+ getObjCLayout(const ObjCInterfaceDecl *D,
+ const ObjCImplementationDecl *Impl) const;
+
+ /// \brief A set of deallocations that should be performed when the
+ /// ASTContext is destroyed.
+ // FIXME: We really should have a better mechanism in the ASTContext to
+ // manage running destructors for types which do variable sized allocation
+ // within the AST. In some places we thread the AST bump pointer allocator
+ // into the datastructures which avoids this mess during deallocation but is
+ // wasteful of memory, and here we require a lot of error prone book keeping
+ // in order to track and run destructors while we're tearing things down.
+ typedef llvm::SmallVector<std::pair<void (*)(void *), void *>, 16>
+ DeallocationFunctionsAndArguments;
+ DeallocationFunctionsAndArguments 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;
+
+ friend class DeclContext;
+ friend class DeclarationNameTable;
+ void ReleaseDeclContextMaps();
+ void ReleaseParentMapEntries();
+
+ std::unique_ptr<ParentMapPointers> PointerParents;
+ std::unique_ptr<ParentMapOtherNodes> OtherParents;
+
+ std::unique_ptr<VTableContextBase> VTContext;
+
+public:
+ enum PragmaSectionFlag : unsigned {
+ PSF_None = 0,
+ PSF_Read = 0x1,
+ PSF_Write = 0x2,
+ PSF_Execute = 0x4,
+ PSF_Implicit = 0x8,
+ PSF_Invalid = 0x80000000U,
+ };
+
+ struct SectionInfo {
+ DeclaratorDecl *Decl;
+ SourceLocation PragmaSectionLocation;
+ int SectionFlags;
+ SectionInfo() {}
+ SectionInfo(DeclaratorDecl *Decl,
+ SourceLocation PragmaSectionLocation,
+ int SectionFlags)
+ : Decl(Decl),
+ PragmaSectionLocation(PragmaSectionLocation),
+ SectionFlags(SectionFlags) {}
+ };
+
+ llvm::StringMap<SectionInfo> SectionInfos;
+};
+
+/// \brief Utility function for constructing a nullary selector.
+static inline Selector GetNullarySelector(StringRef 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(StringRef 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.
+
+/// @brief Placement new for using the ASTContext's allocator.
+///
+/// This placement form of operator new uses the ASTContext's allocator for
+/// obtaining memory.
+///
+/// IMPORTANT: These are also declared in clang/AST/AttrIterator.h! Any changes
+/// here need to also be made there.
+///
+/// We intentionally avoid using a nothrow specification here so that the calls
+/// to this operator will not perform a null check on the result -- the
+/// underlying allocator never returns null pointers.
+///
+/// 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
+/// Memory allocated through this placement new operator does not need to be
+/// explicitly freed, as ASTContext will free all of this memory when it gets
+/// destroyed. Please note that you cannot use delete on the pointer.
+///
+/// @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) {
+ 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) {
+ C.Deallocate(Ptr);
+}
+
+/// This placement form of operator new[] uses the ASTContext's allocator for
+/// obtaining memory.
+///
+/// We intentionally avoid using a nothrow specification here so that the calls
+/// to this operator will not perform a null check on the result -- the
+/// underlying allocator never returns null pointers.
+///
+/// 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
+/// Memory allocated through this placement new[] operator does not need to be
+/// explicitly freed, as ASTContext will free all of this memory when it gets
+/// destroyed. Please note that you cannot use delete on the pointer.
+///
+/// @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) {
+ 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) {
+ C.Deallocate(Ptr);
+}
+
+/// \brief Create the representation of a LazyGenerationalUpdatePtr.
+template <typename Owner, typename T,
+ void (clang::ExternalASTSource::*Update)(Owner)>
+typename clang::LazyGenerationalUpdatePtr<Owner, T, Update>::ValueType
+ clang::LazyGenerationalUpdatePtr<Owner, T, Update>::makeValue(
+ const clang::ASTContext &Ctx, T Value) {
+ // Note, this is implemented here so that ExternalASTSource.h doesn't need to
+ // include ASTContext.h. We explicitly instantiate it for all relevant types
+ // in ASTContext.cpp.
+ if (auto *Source = Ctx.getExternalSource())
+ return new (Ctx) LazyData(Source, Value);
+ return Value;
+}
+
+#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..27c85e6
--- /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_AST_ASTDIAGNOSTIC_H
+#define LLVM_CLANG_AST_ASTDIAGNOSTIC_H
+
+#include "clang/Basic/Diagnostic.h"
+
+namespace clang {
+ namespace diag {
+ enum {
+#define DIAG(ENUM,FLAGS,DEFAULT_MAPPING,DESC,GROUP,\
+ SFINAE,NOWERROR,SHOWINSYSHEADER,CATEGORY) ENUM,
+#define ASTSTART
+#include "clang/Basic/DiagnosticASTKinds.inc"
+#undef DIAG
+ NUM_BUILTIN_AST_DIAGNOSTICS
+ };
+ } // end namespace diag
+
+ /// \brief DiagnosticsEngine 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 DiagnosticsEngine::SetArgToStringFn(), where the cookie is an \c
+ /// ASTContext pointer.
+ void FormatASTNodeDiagnosticArgument(
+ DiagnosticsEngine::ArgumentKind Kind,
+ intptr_t Val,
+ StringRef Modifier,
+ StringRef Argument,
+ ArrayRef<DiagnosticsEngine::ArgumentValue> PrevArgs,
+ SmallVectorImpl<char> &Output,
+ void *Cookie,
+ ArrayRef<intptr_t> QualTypeVals);
+} // end namespace clang
+
+#endif
diff --git a/contrib/llvm/tools/clang/include/clang/AST/ASTFwd.h b/contrib/llvm/tools/clang/include/clang/AST/ASTFwd.h
new file mode 100644
index 0000000..003d489
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/AST/ASTFwd.h
@@ -0,0 +1,33 @@
+//===--- ASTFwd.h ----------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===--------------------------------------------------------------===//
+///
+/// \file
+/// \brief Forward declaration of all AST node types.
+///
+//===-------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_AST_ASTFWD_H
+#define LLVM_CLANG_AST_ASTFWD_H
+
+namespace clang {
+
+class Decl;
+#define DECL(DERIVED, BASE) class DERIVED##Decl;
+#include "clang/AST/DeclNodes.inc"
+class Stmt;
+#define STMT(DERIVED, BASE) class DERIVED;
+#include "clang/AST/StmtNodes.inc"
+class Type;
+#define TYPE(DERIVED, BASE) class DERIVED##Type;
+#include "clang/AST/TypeNodes.def"
+class CXXCtorInitializer;
+
+} // 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..ee48955
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/AST/ASTImporter.h
@@ -0,0 +1,295 @@
+//===--- 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 DiagnosticsEngine;
+ 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 Whether the last diagnostic came from the "from" context.
+ bool LastDiagFromFrom;
+
+ /// \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.
+ 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 Return the copy of the given declaration in the "to" context if
+ /// it has already been imported from the "from" context. Otherwise return
+ /// NULL.
+ Decl *GetAlreadyImportedOrNull(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 given nested-name-specifier from the "from"
+ /// context into the "to" context.
+ ///
+ /// \returns the equivalent nested-name-specifier in the "to"
+ /// context.
+ NestedNameSpecifierLoc Import(NestedNameSpecifierLoc 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 Called for ObjCInterfaceDecl, ObjCProtocolDecl, and TagDecl.
+ /// Mark the Decl as complete, filling it in as much as possible.
+ ///
+ /// \param D A declaration in the "to" context.
+ virtual void CompleteDecl(Decl* D);
+
+ /// \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 Called by StructuralEquivalenceContext. If a RecordDecl is
+ /// being compared to another RecordDecl as part of import, completing the
+ /// other RecordDecl may trigger importation of the first RecordDecl. This
+ /// happens especially for anonymous structs. If the original of the second
+ /// RecordDecl can be found, we can complete it without the need for
+ /// importation, eliminating this loop.
+ virtual Decl *GetOriginalDecl(Decl *To) { return nullptr; }
+
+ /// \brief Determine whether the given types are structurally
+ /// equivalent.
+ bool IsStructurallyEquivalent(QualType From, QualType To,
+ bool Complain = true);
+ };
+}
+
+#endif // LLVM_CLANG_AST_ASTIMPORTER_H
diff --git a/contrib/llvm/tools/clang/include/clang/AST/ASTLambda.h b/contrib/llvm/tools/clang/include/clang/AST/ASTLambda.h
new file mode 100644
index 0000000..69df2d8
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/AST/ASTLambda.h
@@ -0,0 +1,80 @@
+//===--- ASTLambda.h - Lambda Helper Functions --------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+///
+/// \file
+/// \brief This file provides some common utility functions for processing
+/// Lambda related AST Constructs.
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_AST_ASTLAMBDA_H
+#define LLVM_CLANG_AST_ASTLAMBDA_H
+
+#include "clang/AST/DeclCXX.h"
+#include "clang/AST/DeclTemplate.h"
+
+namespace clang {
+inline StringRef getLambdaStaticInvokerName() {
+ return "__invoke";
+}
+// This function returns true if M is a specialization, a template,
+// or a non-generic lambda call operator.
+inline bool isLambdaCallOperator(const CXXMethodDecl *MD) {
+ const CXXRecordDecl *LambdaClass = MD->getParent();
+ if (!LambdaClass || !LambdaClass->isLambda()) return false;
+ return MD->getOverloadedOperator() == OO_Call;
+}
+
+inline bool isLambdaCallOperator(const DeclContext *DC) {
+ if (!DC || !isa<CXXMethodDecl>(DC)) return false;
+ return isLambdaCallOperator(cast<CXXMethodDecl>(DC));
+}
+
+inline bool isGenericLambdaCallOperatorSpecialization(const CXXMethodDecl *MD) {
+ if (!MD) return false;
+ const CXXRecordDecl *LambdaClass = MD->getParent();
+ if (LambdaClass && LambdaClass->isGenericLambda())
+ return isLambdaCallOperator(MD) &&
+ MD->isFunctionTemplateSpecialization();
+ return false;
+}
+
+inline bool isLambdaConversionOperator(CXXConversionDecl *C) {
+ return C ? C->getParent()->isLambda() : false;
+}
+
+inline bool isLambdaConversionOperator(Decl *D) {
+ if (!D) return false;
+ if (CXXConversionDecl *Conv = dyn_cast<CXXConversionDecl>(D))
+ return isLambdaConversionOperator(Conv);
+ if (FunctionTemplateDecl *F = dyn_cast<FunctionTemplateDecl>(D))
+ if (CXXConversionDecl *Conv =
+ dyn_cast_or_null<CXXConversionDecl>(F->getTemplatedDecl()))
+ return isLambdaConversionOperator(Conv);
+ return false;
+}
+
+inline bool isGenericLambdaCallOperatorSpecialization(DeclContext *DC) {
+ return isGenericLambdaCallOperatorSpecialization(
+ dyn_cast<CXXMethodDecl>(DC));
+}
+
+
+// This returns the parent DeclContext ensuring that the correct
+// parent DeclContext is returned for Lambdas
+inline DeclContext *getLambdaAwareParentOfDeclContext(DeclContext *DC) {
+ if (isLambdaCallOperator(DC))
+ return DC->getParent()->getParent();
+ else
+ return DC->getParent();
+}
+
+} // clang
+
+#endif
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..3ff392d
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/AST/ASTMutationListener.h
@@ -0,0 +1,127 @@
+//===--- 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 Attr;
+ class ClassTemplateDecl;
+ class ClassTemplateSpecializationDecl;
+ class CXXDestructorDecl;
+ class CXXRecordDecl;
+ class Decl;
+ class DeclContext;
+ class FunctionDecl;
+ class FunctionTemplateDecl;
+ class Module;
+ class NamedDecl;
+ class ObjCCategoryDecl;
+ class ObjCContainerDecl;
+ class ObjCInterfaceDecl;
+ class ObjCPropertyDecl;
+ class QualType;
+ class RecordDecl;
+ class TagDecl;
+ class VarDecl;
+ class VarTemplateDecl;
+ class VarTemplateSpecializationDecl;
+
+/// \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) {}
+
+ /// \brief A template specialization (or partial one) was added to the
+ /// template declaration.
+ virtual void
+ AddedCXXTemplateSpecialization(const VarTemplateDecl *TD,
+ const VarTemplateSpecializationDecl *D) {}
+
+ /// \brief A template specialization (or partial one) was added to the
+ /// template declaration.
+ virtual void AddedCXXTemplateSpecialization(const FunctionTemplateDecl *TD,
+ const FunctionDecl *D) {}
+
+ /// \brief A function's exception specification has been evaluated or
+ /// instantiated.
+ virtual void ResolvedExceptionSpec(const FunctionDecl *FD) {}
+
+ /// \brief A function's return type has been deduced.
+ virtual void DeducedReturnType(const FunctionDecl *FD, QualType ReturnType);
+
+ /// \brief A virtual destructor's operator delete has been resolved.
+ virtual void ResolvedOperatorDelete(const CXXDestructorDecl *DD,
+ const FunctionDecl *Delete) {}
+
+ /// \brief An implicit member got a definition.
+ virtual void CompletedImplicitDefinition(const FunctionDecl *D) {}
+
+ /// \brief A static data member was implicitly instantiated.
+ virtual void StaticDataMemberInstantiated(const VarDecl *D) {}
+
+ /// \brief A function template's definition was instantiated.
+ virtual void FunctionDefinitionInstantiated(const FunctionDecl *D) {}
+
+ /// \brief A new objc category class was added for an interface.
+ virtual void AddedObjCCategoryToInterface(const ObjCCategoryDecl *CatD,
+ const ObjCInterfaceDecl *IFD) {}
+
+ /// \brief A declaration is marked used which was not previously marked used.
+ ///
+ /// \param D the declaration marked used
+ virtual void DeclarationMarkedUsed(const Decl *D) {}
+
+ /// \brief A declaration is marked as OpenMP threadprivate which was not
+ /// previously marked as threadprivate.
+ ///
+ /// \param D the declaration marked OpenMP threadprivate.
+ virtual void DeclarationMarkedOpenMPThreadPrivate(const Decl *D) {}
+
+ /// \brief A definition has been made visible by being redefined locally.
+ ///
+ /// \param D The definition that was previously not visible.
+ /// \param M The containing module in which the definition was made visible,
+ /// if any.
+ virtual void RedefinedHiddenDefinition(const NamedDecl *D, Module *M) {}
+
+ /// \brief An attribute was added to a RecordDecl
+ ///
+ /// \param Attr The attribute that was added to the Record
+ ///
+ /// \param Record The RecordDecl that got a new attribute
+ virtual void AddedAttributeToRecord(const Attr *Attr,
+ const RecordDecl *Record) {}
+
+ // NOTE: If new methods are added they should also be added to
+ // MultiplexASTMutationListener.
+};
+
+} // end namespace clang
+
+#endif
diff --git a/contrib/llvm/tools/clang/include/clang/AST/ASTTypeTraits.h b/contrib/llvm/tools/clang/include/clang/AST/ASTTypeTraits.h
new file mode 100644
index 0000000..dcaac80
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/AST/ASTTypeTraits.h
@@ -0,0 +1,509 @@
+//===--- ASTTypeTraits.h ----------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// Provides a dynamic type identifier and a dynamically typed node container
+// that can be used to store an AST base node at runtime in the same storage in
+// a type safe way.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_AST_ASTTYPETRAITS_H
+#define LLVM_CLANG_AST_ASTTYPETRAITS_H
+
+#include "clang/AST/ASTFwd.h"
+#include "clang/AST/Decl.h"
+#include "clang/AST/NestedNameSpecifier.h"
+#include "clang/AST/Stmt.h"
+#include "clang/AST/TemplateBase.h"
+#include "clang/AST/TypeLoc.h"
+#include "clang/Basic/LLVM.h"
+#include "llvm/ADT/DenseMapInfo.h"
+#include "llvm/Support/AlignOf.h"
+
+namespace llvm {
+
+class raw_ostream;
+
+}
+
+namespace clang {
+
+struct PrintingPolicy;
+
+namespace ast_type_traits {
+
+/// \brief Kind identifier.
+///
+/// It can be constructed from any node kind and allows for runtime type
+/// hierarchy checks.
+/// Use getFromNodeKind<T>() to construct them.
+class ASTNodeKind {
+public:
+ /// \brief Empty identifier. It matches nothing.
+ ASTNodeKind() : KindId(NKI_None) {}
+
+ /// \brief Construct an identifier for T.
+ template <class T>
+ static ASTNodeKind getFromNodeKind() {
+ return ASTNodeKind(KindToKindId<T>::Id);
+ }
+
+ /// \{
+ /// \brief Construct an identifier for the dynamic type of the node
+ static ASTNodeKind getFromNode(const Decl &D);
+ static ASTNodeKind getFromNode(const Stmt &S);
+ static ASTNodeKind getFromNode(const Type &T);
+ /// \}
+
+ /// \brief Returns \c true if \c this and \c Other represent the same kind.
+ bool isSame(ASTNodeKind Other) const;
+
+ /// \brief Returns \c true only for the default \c ASTNodeKind()
+ bool isNone() const { return KindId == NKI_None; }
+
+ /// \brief Returns \c true if \c this is a base kind of (or same as) \c Other.
+ /// \param Distance If non-null, used to return the distance between \c this
+ /// and \c Other in the class hierarchy.
+ bool isBaseOf(ASTNodeKind Other, unsigned *Distance = nullptr) const;
+
+ /// \brief String representation of the kind.
+ StringRef asStringRef() const;
+
+ /// \brief Strict weak ordering for ASTNodeKind.
+ bool operator<(const ASTNodeKind &Other) const {
+ return KindId < Other.KindId;
+ }
+
+ /// \brief Return the most derived type between \p Kind1 and \p Kind2.
+ ///
+ /// Return ASTNodeKind() if they are not related.
+ static ASTNodeKind getMostDerivedType(ASTNodeKind Kind1, ASTNodeKind Kind2);
+
+ /// \brief Return the most derived common ancestor between Kind1 and Kind2.
+ ///
+ /// Return ASTNodeKind() if they are not related.
+ static ASTNodeKind getMostDerivedCommonAncestor(ASTNodeKind Kind1,
+ ASTNodeKind Kind2);
+
+ /// \brief Hooks for using ASTNodeKind as a key in a DenseMap.
+ struct DenseMapInfo {
+ // ASTNodeKind() is a good empty key because it is represented as a 0.
+ static inline ASTNodeKind getEmptyKey() { return ASTNodeKind(); }
+ // NKI_NumberOfKinds is not a valid value, so it is good for a
+ // tombstone key.
+ static inline ASTNodeKind getTombstoneKey() {
+ return ASTNodeKind(NKI_NumberOfKinds);
+ }
+ static unsigned getHashValue(const ASTNodeKind &Val) { return Val.KindId; }
+ static bool isEqual(const ASTNodeKind &LHS, const ASTNodeKind &RHS) {
+ return LHS.KindId == RHS.KindId;
+ }
+ };
+
+ /// Check if the given ASTNodeKind identifies a type that offers pointer
+ /// identity. This is useful for the fast path in DynTypedNode.
+ bool hasPointerIdentity() const {
+ return KindId > NKI_LastKindWithoutPointerIdentity;
+ }
+
+private:
+ /// \brief Kind ids.
+ ///
+ /// Includes all possible base and derived kinds.
+ enum NodeKindId {
+ NKI_None,
+ NKI_TemplateArgument,
+ NKI_NestedNameSpecifierLoc,
+ NKI_QualType,
+ NKI_TypeLoc,
+ NKI_LastKindWithoutPointerIdentity = NKI_TypeLoc,
+ NKI_CXXCtorInitializer,
+ NKI_NestedNameSpecifier,
+ NKI_Decl,
+#define DECL(DERIVED, BASE) NKI_##DERIVED##Decl,
+#include "clang/AST/DeclNodes.inc"
+ NKI_Stmt,
+#define STMT(DERIVED, BASE) NKI_##DERIVED,
+#include "clang/AST/StmtNodes.inc"
+ NKI_Type,
+#define TYPE(DERIVED, BASE) NKI_##DERIVED##Type,
+#include "clang/AST/TypeNodes.def"
+ NKI_NumberOfKinds
+ };
+
+ /// \brief Use getFromNodeKind<T>() to construct the kind.
+ ASTNodeKind(NodeKindId KindId) : KindId(KindId) {}
+
+ /// \brief Returns \c true if \c Base is a base kind of (or same as) \c
+ /// Derived.
+ /// \param Distance If non-null, used to return the distance between \c Base
+ /// and \c Derived in the class hierarchy.
+ static bool isBaseOf(NodeKindId Base, NodeKindId Derived, unsigned *Distance);
+
+ /// \brief Helper meta-function to convert a kind T to its enum value.
+ ///
+ /// This struct is specialized below for all known kinds.
+ template <class T> struct KindToKindId {
+ static const NodeKindId Id = NKI_None;
+ };
+ template <class T>
+ struct KindToKindId<const T> : KindToKindId<T> {};
+
+ /// \brief Per kind info.
+ struct KindInfo {
+ /// \brief The id of the parent kind, or None if it has no parent.
+ NodeKindId ParentId;
+ /// \brief Name of the kind.
+ const char *Name;
+ };
+ static const KindInfo AllKindInfo[NKI_NumberOfKinds];
+
+ NodeKindId KindId;
+};
+
+#define KIND_TO_KIND_ID(Class) \
+ template <> struct ASTNodeKind::KindToKindId<Class> { \
+ static const NodeKindId Id = NKI_##Class; \
+ };
+KIND_TO_KIND_ID(CXXCtorInitializer)
+KIND_TO_KIND_ID(TemplateArgument)
+KIND_TO_KIND_ID(NestedNameSpecifier)
+KIND_TO_KIND_ID(NestedNameSpecifierLoc)
+KIND_TO_KIND_ID(QualType)
+KIND_TO_KIND_ID(TypeLoc)
+KIND_TO_KIND_ID(Decl)
+KIND_TO_KIND_ID(Stmt)
+KIND_TO_KIND_ID(Type)
+#define DECL(DERIVED, BASE) KIND_TO_KIND_ID(DERIVED##Decl)
+#include "clang/AST/DeclNodes.inc"
+#define STMT(DERIVED, BASE) KIND_TO_KIND_ID(DERIVED)
+#include "clang/AST/StmtNodes.inc"
+#define TYPE(DERIVED, BASE) KIND_TO_KIND_ID(DERIVED##Type)
+#include "clang/AST/TypeNodes.def"
+#undef KIND_TO_KIND_ID
+
+inline raw_ostream &operator<<(raw_ostream &OS, ASTNodeKind K) {
+ OS << K.asStringRef();
+ return OS;
+}
+
+/// \brief A dynamically typed AST node container.
+///
+/// Stores an AST node in a type safe way. This allows writing code that
+/// works with different kinds of AST nodes, despite the fact that they don't
+/// have a common base class.
+///
+/// Use \c create(Node) to create a \c DynTypedNode from an AST node,
+/// and \c get<T>() to retrieve the node as type T if the types match.
+///
+/// See \c ASTNodeKind for which node base types are currently supported;
+/// You can create DynTypedNodes for all nodes in the inheritance hierarchy of
+/// the supported base types.
+class DynTypedNode {
+public:
+ /// \brief Creates a \c DynTypedNode from \c Node.
+ template <typename T>
+ static DynTypedNode create(const T &Node) {
+ return BaseConverter<T>::create(Node);
+ }
+
+ /// \brief Retrieve the stored node as type \c T.
+ ///
+ /// Returns NULL if the stored node does not have a type that is
+ /// convertible to \c T.
+ ///
+ /// For types that have identity via their pointer in the AST
+ /// (like \c Stmt, \c Decl, \c Type and \c NestedNameSpecifier) the returned
+ /// pointer points to the referenced AST node.
+ /// For other types (like \c QualType) the value is stored directly
+ /// in the \c DynTypedNode, and the returned pointer points at
+ /// the storage inside DynTypedNode. For those nodes, do not
+ /// use the pointer outside the scope of the DynTypedNode.
+ template <typename T>
+ const T *get() const {
+ return BaseConverter<T>::get(NodeKind, Storage.buffer);
+ }
+
+ /// \brief Retrieve the stored node as type \c T.
+ ///
+ /// Similar to \c get(), but asserts that the type is what we are expecting.
+ template <typename T>
+ const T &getUnchecked() const {
+ return BaseConverter<T>::getUnchecked(NodeKind, Storage.buffer);
+ }
+
+ ASTNodeKind getNodeKind() const { return NodeKind; }
+
+ /// \brief Returns a pointer that identifies the stored AST node.
+ ///
+ /// Note that this is not supported by all AST nodes. For AST nodes
+ /// that don't have a pointer-defined identity inside the AST, this
+ /// method returns NULL.
+ const void *getMemoizationData() const {
+ return NodeKind.hasPointerIdentity()
+ ? *reinterpret_cast<void *const *>(Storage.buffer)
+ : nullptr;
+ }
+
+ /// \brief Prints the node to the given output stream.
+ void print(llvm::raw_ostream &OS, const PrintingPolicy &PP) const;
+
+ /// \brief Dumps the node to the given output stream.
+ void dump(llvm::raw_ostream &OS, SourceManager &SM) const;
+
+ /// \brief For nodes which represent textual entities in the source code,
+ /// return their SourceRange. For all other nodes, return SourceRange().
+ SourceRange getSourceRange() const;
+
+ /// @{
+ /// \brief Imposes an order on \c DynTypedNode.
+ ///
+ /// Supports comparison of nodes that support memoization.
+ /// FIXME: Implement comparsion for other node types (currently
+ /// only Stmt, Decl, Type and NestedNameSpecifier return memoization data).
+ bool operator<(const DynTypedNode &Other) const {
+ if (!NodeKind.isSame(Other.NodeKind))
+ return NodeKind < Other.NodeKind;
+
+ if (ASTNodeKind::getFromNodeKind<QualType>().isSame(NodeKind))
+ return getUnchecked<QualType>().getAsOpaquePtr() <
+ Other.getUnchecked<QualType>().getAsOpaquePtr();
+
+ if (ASTNodeKind::getFromNodeKind<TypeLoc>().isSame(NodeKind)) {
+ auto TLA = getUnchecked<TypeLoc>();
+ auto TLB = Other.getUnchecked<TypeLoc>();
+ return std::make_pair(TLA.getType().getAsOpaquePtr(),
+ TLA.getOpaqueData()) <
+ std::make_pair(TLB.getType().getAsOpaquePtr(),
+ TLB.getOpaqueData());
+ }
+
+ if (ASTNodeKind::getFromNodeKind<NestedNameSpecifierLoc>().isSame(
+ NodeKind)) {
+ auto NNSLA = getUnchecked<NestedNameSpecifierLoc>();
+ auto NNSLB = Other.getUnchecked<NestedNameSpecifierLoc>();
+ return std::make_pair(NNSLA.getNestedNameSpecifier(),
+ NNSLA.getOpaqueData()) <
+ std::make_pair(NNSLB.getNestedNameSpecifier(),
+ NNSLB.getOpaqueData());
+ }
+
+ assert(getMemoizationData() && Other.getMemoizationData());
+ return getMemoizationData() < Other.getMemoizationData();
+ }
+ bool operator==(const DynTypedNode &Other) const {
+ // DynTypedNode::create() stores the exact kind of the node in NodeKind.
+ // If they contain the same node, their NodeKind must be the same.
+ if (!NodeKind.isSame(Other.NodeKind))
+ return false;
+
+ // FIXME: Implement for other types.
+ if (ASTNodeKind::getFromNodeKind<QualType>().isSame(NodeKind))
+ return getUnchecked<QualType>() == Other.getUnchecked<QualType>();
+
+ if (ASTNodeKind::getFromNodeKind<TypeLoc>().isSame(NodeKind))
+ return getUnchecked<TypeLoc>() == Other.getUnchecked<TypeLoc>();
+
+ if (ASTNodeKind::getFromNodeKind<NestedNameSpecifierLoc>().isSame(NodeKind))
+ return getUnchecked<NestedNameSpecifierLoc>() ==
+ Other.getUnchecked<NestedNameSpecifierLoc>();
+
+ assert(getMemoizationData() && Other.getMemoizationData());
+ return getMemoizationData() == Other.getMemoizationData();
+ }
+ bool operator!=(const DynTypedNode &Other) const {
+ return !operator==(Other);
+ }
+ /// @}
+
+ /// \brief Hooks for using DynTypedNode as a key in a DenseMap.
+ struct DenseMapInfo {
+ static inline DynTypedNode getEmptyKey() {
+ DynTypedNode Node;
+ Node.NodeKind = ASTNodeKind::DenseMapInfo::getEmptyKey();
+ return Node;
+ }
+ static inline DynTypedNode getTombstoneKey() {
+ DynTypedNode Node;
+ Node.NodeKind = ASTNodeKind::DenseMapInfo::getTombstoneKey();
+ return Node;
+ }
+ static unsigned getHashValue(const DynTypedNode &Val) {
+ // FIXME: Add hashing support for the remaining types.
+ if (ASTNodeKind::getFromNodeKind<TypeLoc>().isSame(Val.NodeKind)) {
+ auto TL = Val.getUnchecked<TypeLoc>();
+ return llvm::hash_combine(TL.getType().getAsOpaquePtr(),
+ TL.getOpaqueData());
+ }
+
+ if (ASTNodeKind::getFromNodeKind<NestedNameSpecifierLoc>().isSame(
+ Val.NodeKind)) {
+ auto NNSL = Val.getUnchecked<NestedNameSpecifierLoc>();
+ return llvm::hash_combine(NNSL.getNestedNameSpecifier(),
+ NNSL.getOpaqueData());
+ }
+
+ assert(Val.getMemoizationData());
+ return llvm::hash_value(Val.getMemoizationData());
+ }
+ static bool isEqual(const DynTypedNode &LHS, const DynTypedNode &RHS) {
+ auto Empty = ASTNodeKind::DenseMapInfo::getEmptyKey();
+ auto TombStone = ASTNodeKind::DenseMapInfo::getTombstoneKey();
+ return (ASTNodeKind::DenseMapInfo::isEqual(LHS.NodeKind, Empty) &&
+ ASTNodeKind::DenseMapInfo::isEqual(RHS.NodeKind, Empty)) ||
+ (ASTNodeKind::DenseMapInfo::isEqual(LHS.NodeKind, TombStone) &&
+ ASTNodeKind::DenseMapInfo::isEqual(RHS.NodeKind, TombStone)) ||
+ LHS == RHS;
+ }
+ };
+
+private:
+ /// \brief Takes care of converting from and to \c T.
+ template <typename T, typename EnablerT = void> struct BaseConverter;
+
+ /// \brief Converter that uses dyn_cast<T> from a stored BaseT*.
+ template <typename T, typename BaseT> struct DynCastPtrConverter {
+ static const T *get(ASTNodeKind NodeKind, const char Storage[]) {
+ if (ASTNodeKind::getFromNodeKind<T>().isBaseOf(NodeKind))
+ return &getUnchecked(NodeKind, Storage);
+ return nullptr;
+ }
+ static const T &getUnchecked(ASTNodeKind NodeKind, const char Storage[]) {
+ assert(ASTNodeKind::getFromNodeKind<T>().isBaseOf(NodeKind));
+ return *cast<T>(static_cast<const BaseT *>(
+ *reinterpret_cast<const void *const *>(Storage)));
+ }
+ static DynTypedNode create(const BaseT &Node) {
+ DynTypedNode Result;
+ Result.NodeKind = ASTNodeKind::getFromNode(Node);
+ new (Result.Storage.buffer) const void *(&Node);
+ return Result;
+ }
+ };
+
+ /// \brief Converter that stores T* (by pointer).
+ template <typename T> struct PtrConverter {
+ static const T *get(ASTNodeKind NodeKind, const char Storage[]) {
+ if (ASTNodeKind::getFromNodeKind<T>().isSame(NodeKind))
+ return &getUnchecked(NodeKind, Storage);
+ return nullptr;
+ }
+ static const T &getUnchecked(ASTNodeKind NodeKind, const char Storage[]) {
+ assert(ASTNodeKind::getFromNodeKind<T>().isSame(NodeKind));
+ return *static_cast<const T *>(
+ *reinterpret_cast<const void *const *>(Storage));
+ }
+ static DynTypedNode create(const T &Node) {
+ DynTypedNode Result;
+ Result.NodeKind = ASTNodeKind::getFromNodeKind<T>();
+ new (Result.Storage.buffer) const void *(&Node);
+ return Result;
+ }
+ };
+
+ /// \brief Converter that stores T (by value).
+ template <typename T> struct ValueConverter {
+ static const T *get(ASTNodeKind NodeKind, const char Storage[]) {
+ if (ASTNodeKind::getFromNodeKind<T>().isSame(NodeKind))
+ return reinterpret_cast<const T *>(Storage);
+ return nullptr;
+ }
+ static const T &getUnchecked(ASTNodeKind NodeKind, const char Storage[]) {
+ assert(ASTNodeKind::getFromNodeKind<T>().isSame(NodeKind));
+ return *reinterpret_cast<const T *>(Storage);
+ }
+ static DynTypedNode create(const T &Node) {
+ DynTypedNode Result;
+ Result.NodeKind = ASTNodeKind::getFromNodeKind<T>();
+ new (Result.Storage.buffer) T(Node);
+ return Result;
+ }
+ };
+
+ ASTNodeKind NodeKind;
+
+ /// \brief Stores the data of the node.
+ ///
+ /// Note that we can store \c Decls, \c Stmts, \c Types,
+ /// \c NestedNameSpecifiers and \c CXXCtorInitializer by pointer as they are
+ /// guaranteed to be unique pointers pointing to dedicated storage in the AST.
+ /// \c QualTypes, \c NestedNameSpecifierLocs, \c TypeLocs and
+ /// \c TemplateArguments on the other hand do not have storage or unique
+ /// pointers and thus need to be stored by value.
+ llvm::AlignedCharArrayUnion<const void *, TemplateArgument,
+ NestedNameSpecifierLoc, QualType,
+ TypeLoc> Storage;
+};
+
+template <typename T>
+struct DynTypedNode::BaseConverter<
+ T, typename std::enable_if<std::is_base_of<Decl, T>::value>::type>
+ : public DynCastPtrConverter<T, Decl> {};
+
+template <typename T>
+struct DynTypedNode::BaseConverter<
+ T, typename std::enable_if<std::is_base_of<Stmt, T>::value>::type>
+ : public DynCastPtrConverter<T, Stmt> {};
+
+template <typename T>
+struct DynTypedNode::BaseConverter<
+ T, typename std::enable_if<std::is_base_of<Type, T>::value>::type>
+ : public DynCastPtrConverter<T, Type> {};
+
+template <>
+struct DynTypedNode::BaseConverter<
+ NestedNameSpecifier, void> : public PtrConverter<NestedNameSpecifier> {};
+
+template <>
+struct DynTypedNode::BaseConverter<
+ CXXCtorInitializer, void> : public PtrConverter<CXXCtorInitializer> {};
+
+template <>
+struct DynTypedNode::BaseConverter<
+ TemplateArgument, void> : public ValueConverter<TemplateArgument> {};
+
+template <>
+struct DynTypedNode::BaseConverter<
+ NestedNameSpecifierLoc,
+ void> : public ValueConverter<NestedNameSpecifierLoc> {};
+
+template <>
+struct DynTypedNode::BaseConverter<QualType,
+ void> : public ValueConverter<QualType> {};
+
+template <>
+struct DynTypedNode::BaseConverter<
+ TypeLoc, void> : public ValueConverter<TypeLoc> {};
+
+// The only operation we allow on unsupported types is \c get.
+// This allows to conveniently use \c DynTypedNode when having an arbitrary
+// AST node that is not supported, but prevents misuse - a user cannot create
+// a DynTypedNode from arbitrary types.
+template <typename T, typename EnablerT> struct DynTypedNode::BaseConverter {
+ static const T *get(ASTNodeKind NodeKind, const char Storage[]) {
+ return NULL;
+ }
+};
+
+} // end namespace ast_type_traits
+} // end namespace clang
+
+namespace llvm {
+
+template <>
+struct DenseMapInfo<clang::ast_type_traits::ASTNodeKind>
+ : clang::ast_type_traits::ASTNodeKind::DenseMapInfo {};
+
+template <>
+struct DenseMapInfo<clang::ast_type_traits::DynTypedNode>
+ : clang::ast_type_traits::DynTypedNode::DenseMapInfo {};
+
+} // end namespace llvm
+
+#endif
diff --git a/contrib/llvm/tools/clang/include/clang/AST/ASTUnresolvedSet.h b/contrib/llvm/tools/clang/include/clang/AST/ASTUnresolvedSet.h
new file mode 100644
index 0000000..9078a0e
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/AST/ASTUnresolvedSet.h
@@ -0,0 +1,110 @@
+//===-- ASTUnresolvedSet.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 provides an UnresolvedSet-like class, whose contents are
+// allocated using the allocator associated with an ASTContext.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_AST_ASTUNRESOLVEDSET_H
+#define LLVM_CLANG_AST_ASTUNRESOLVEDSET_H
+
+#include "clang/AST/ASTVector.h"
+#include "clang/AST/UnresolvedSet.h"
+
+namespace clang {
+
+/// \brief An UnresolvedSet-like class which uses the ASTContext's allocator.
+class ASTUnresolvedSet {
+ struct DeclsTy : ASTVector<DeclAccessPair> {
+ DeclsTy() {}
+ DeclsTy(ASTContext &C, unsigned N) : ASTVector<DeclAccessPair>(C, N) {}
+
+ bool isLazy() const { return getTag(); }
+ void setLazy(bool Lazy) { setTag(Lazy); }
+ };
+
+ DeclsTy Decls;
+
+ friend class LazyASTUnresolvedSet;
+
+public:
+ ASTUnresolvedSet() {}
+ ASTUnresolvedSet(ASTContext &C, unsigned N) : Decls(C, N) {}
+
+ 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(ASTContext &C, NamedDecl *D, AccessSpecifier AS) {
+ Decls.push_back(DeclAccessPair::make(D, AS), C);
+ }
+
+ /// Replaces the given declaration with the new one, once.
+ ///
+ /// \return true if the set changed
+ bool replace(const NamedDecl *Old, NamedDecl *New, AccessSpecifier AS) {
+ for (DeclsTy::iterator I = Decls.begin(), E = Decls.end(); I != E; ++I) {
+ if (I->getDecl() == Old) {
+ I->set(New, AS);
+ return true;
+ }
+ }
+ return false;
+ }
+
+ void erase(unsigned I) { Decls[I] = Decls.pop_back_val(); }
+
+ void clear() { Decls.clear(); }
+
+ bool empty() const { return Decls.empty(); }
+ unsigned size() const { return Decls.size(); }
+
+ void reserve(ASTContext &C, unsigned N) {
+ Decls.reserve(C, N);
+ }
+
+ void append(ASTContext &C, iterator I, iterator E) {
+ Decls.append(C, I.I, E.I);
+ }
+
+ DeclAccessPair &operator[](unsigned I) { return Decls[I]; }
+ const DeclAccessPair &operator[](unsigned I) const { return Decls[I]; }
+};
+
+/// \brief An UnresolvedSet-like class that might not have been loaded from the
+/// external AST source yet.
+class LazyASTUnresolvedSet {
+ mutable ASTUnresolvedSet Impl;
+
+ void getFromExternalSource(ASTContext &C) const;
+
+public:
+ ASTUnresolvedSet &get(ASTContext &C) const {
+ if (Impl.Decls.isLazy())
+ getFromExternalSource(C);
+ return Impl;
+ }
+
+ void reserve(ASTContext &C, unsigned N) { Impl.reserve(C, N); }
+ void addLazyDecl(ASTContext &C, uintptr_t ID, AccessSpecifier AS) {
+ assert(Impl.empty() || Impl.Decls.isLazy());
+ Impl.Decls.setLazy(true);
+ Impl.addDecl(C, reinterpret_cast<NamedDecl*>(ID << 2), AS);
+ }
+};
+
+} // 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..79453bf
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/AST/ASTVector.h
@@ -0,0 +1,405 @@
+//===- 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_ASTVECTOR_H
+#define LLVM_CLANG_AST_ASTVECTOR_H
+
+#include "clang/AST/AttrIterator.h"
+#include "llvm/ADT/PointerIntPair.h"
+#include "llvm/Support/Allocator.h"
+#include "llvm/Support/type_traits.h"
+#include <algorithm>
+#include <cstring>
+#include <memory>
+
+namespace clang {
+ class ASTContext;
+
+template<typename T>
+class ASTVector {
+private:
+ T *Begin, *End;
+ llvm::PointerIntPair<T*, 1, bool> Capacity;
+
+ void setEnd(T *P) { this->End = P; }
+
+protected:
+ // Make a tag bit available to users of this class.
+ // FIXME: This is a horrible hack.
+ bool getTag() const { return Capacity.getInt(); }
+ void setTag(bool B) { Capacity.setInt(B); }
+
+public:
+ // Default ctor - Initialize to empty.
+ ASTVector() : Begin(nullptr), End(nullptr), Capacity(nullptr, false) {}
+
+ ASTVector(ASTVector &&O) : Begin(O.Begin), End(O.End), Capacity(O.Capacity) {
+ O.Begin = O.End = nullptr;
+ O.Capacity.setPointer(nullptr);
+ O.Capacity.setInt(false);
+ }
+
+ ASTVector(const ASTContext &C, unsigned N)
+ : Begin(nullptr), End(nullptr), Capacity(nullptr, false) {
+ reserve(C, N);
+ }
+
+ ASTVector &operator=(ASTVector &&RHS) {
+ ASTVector O(std::move(RHS));
+ using std::swap;
+ swap(Begin, O.Begin);
+ swap(End, O.End);
+ swap(Capacity, O.Capacity);
+ return *this;
+ }
+
+ ~ASTVector() {
+ if (std::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 (std::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, const ASTContext &C) {
+ if (End < this->capacity_ptr()) {
+ Retry:
+ new (End) T(Elt);
+ ++End;
+ return;
+ }
+ grow(C);
+ goto Retry;
+ }
+
+ void reserve(const ASTContext &C, unsigned N) {
+ if (unsigned(this->capacity_ptr()-Begin) < N)
+ grow(C, N);
+ }
+
+ /// capacity - Return the total number of elements in the currently allocated
+ /// buffer.
+ size_t capacity() const { return this->capacity_ptr() - Begin; }
+
+ /// append - Add the specified range to the end of the SmallVector.
+ ///
+ template<typename in_iter>
+ void append(const 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(const 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(const ASTContext &C, iterator I, const T &Elt) {
+ if (I == this->end()) { // Important special case for empty vector.
+ push_back(Elt, C);
+ return this->end()-1;
+ }
+
+ if (this->End < this->capacity_ptr()) {
+ 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(const ASTContext &C, iterator I, size_type NumToInsert,
+ const T &Elt) {
+ // Convert iterator to elt# to avoid invalidating iterator when we reserve()
+ size_t InsertElt = I - this->begin();
+
+ if (I == this->end()) { // Important special case for empty vector.
+ append(C, NumToInsert, Elt);
+ return this->begin() + InsertElt;
+ }
+
+ // 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(const ASTContext &C, iterator I, ItTy From, ItTy To) {
+ // Convert iterator to elt# to avoid invalidating iterator when we reserve()
+ size_t InsertElt = I - this->begin();
+
+ if (I == this->end()) { // Important special case for empty vector.
+ append(C, From, To);
+ return this->begin() + InsertElt;
+ }
+
+ size_t NumToInsert = std::distance(From, To);
+
+ // 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(const 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(const 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:
+ const_iterator capacity_ptr() const {
+ return (iterator) Capacity.getPointer();
+ }
+ iterator capacity_ptr() { return (iterator)Capacity.getPointer(); }
+};
+
+// Define this out-of-line to dissuade the C++ compiler from inlining it.
+template <typename T>
+void ASTVector<T>::grow(const ASTContext &C, size_t MinSize) {
+ size_t CurCapacity = this->capacity();
+ size_t CurSize = size();
+ size_t NewCapacity = 2*CurCapacity;
+ if (NewCapacity < MinSize)
+ NewCapacity = MinSize;
+
+ // Allocate the memory from the ASTContext.
+ T *NewElts = new (C, llvm::alignOf<T>()) T[NewCapacity];
+
+ // Copy the elements over.
+ if (Begin != End) {
+ if (std::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));
+ }
+ }
+
+ // ASTContext never frees any memory.
+ Begin = NewElts;
+ End = NewElts+CurSize;
+ Capacity.setPointer(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..8b80e9f
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/AST/Attr.h
@@ -0,0 +1,169 @@
+//===--- Attr.h - 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 defines the Attr interface and subclasses.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_AST_ATTR_H
+#define LLVM_CLANG_AST_ATTR_H
+
+#include "clang/AST/AttrIterator.h"
+#include "clang/AST/Decl.h"
+#include "clang/AST/Expr.h"
+#include "clang/AST/Type.h"
+#include "clang/Basic/AttrKinds.h"
+#include "clang/Basic/LLVM.h"
+#include "clang/Basic/Sanitizers.h"
+#include "clang/Basic/SourceLocation.h"
+#include "clang/Basic/VersionTuple.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/ADT/StringSwitch.h"
+#include "llvm/Support/ErrorHandling.h"
+#include "llvm/Support/raw_ostream.h"
+#include <algorithm>
+#include <cassert>
+
+namespace clang {
+ class ASTContext;
+ class IdentifierInfo;
+ class ObjCInterfaceDecl;
+ class Expr;
+ class QualType;
+ class FunctionDecl;
+ class TypeSourceInfo;
+
+/// Attr - This represents one attribute.
+class Attr {
+private:
+ SourceRange Range;
+ unsigned AttrKind : 16;
+
+protected:
+ /// An index into the spelling list of an
+ /// attribute defined in Attr.td file.
+ unsigned SpellingListIndex : 4;
+ bool Inherited : 1;
+ bool IsPackExpansion : 1;
+ bool Implicit : 1;
+ bool IsLateParsed : 1;
+ bool DuplicatesAllowed : 1;
+
+ void *operator new(size_t bytes) LLVM_NOEXCEPT {
+ llvm_unreachable("Attrs cannot be allocated with regular 'new'.");
+ }
+ void operator delete(void *data) LLVM_NOEXCEPT {
+ llvm_unreachable("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 = 8) LLVM_NOEXCEPT {
+ return ::operator new(Bytes, C, Alignment);
+ }
+ void operator delete(void *Ptr, ASTContext &C,
+ size_t Alignment) LLVM_NOEXCEPT {
+ return ::operator delete(Ptr, C, Alignment);
+ }
+
+protected:
+ Attr(attr::Kind AK, SourceRange R, unsigned SpellingListIndex,
+ bool IsLateParsed, bool DuplicatesAllowed)
+ : Range(R), AttrKind(AK), SpellingListIndex(SpellingListIndex),
+ Inherited(false), IsPackExpansion(false), Implicit(false),
+ IsLateParsed(IsLateParsed), DuplicatesAllowed(DuplicatesAllowed) {}
+
+public:
+
+ attr::Kind getKind() const {
+ return static_cast<attr::Kind>(AttrKind);
+ }
+
+ unsigned getSpellingListIndex() const { return SpellingListIndex; }
+ const char *getSpelling() const;
+
+ SourceLocation getLocation() const { return Range.getBegin(); }
+ SourceRange getRange() const { return Range; }
+ void setRange(SourceRange R) { Range = R; }
+
+ bool isInherited() const { return Inherited; }
+
+ /// \brief Returns true if the attribute has been implicitly created instead
+ /// of explicitly written by the user.
+ bool isImplicit() const { return Implicit; }
+ void setImplicit(bool I) { Implicit = I; }
+
+ void setPackExpansion(bool PE) { IsPackExpansion = PE; }
+ bool isPackExpansion() const { return IsPackExpansion; }
+
+ // Clone this attribute.
+ Attr *clone(ASTContext &C) const;
+
+ bool isLateParsed() const { return IsLateParsed; }
+
+ // Pretty print this attribute.
+ void printPretty(raw_ostream &OS, const PrintingPolicy &Policy) const;
+
+ /// \brief By default, attributes cannot be duplicated when being merged;
+ /// however, an attribute can override this. Returns true if the attribute
+ /// can be duplicated when merging.
+ bool duplicatesAllowed() const { return DuplicatesAllowed; }
+};
+
+class InheritableAttr : public Attr {
+protected:
+ InheritableAttr(attr::Kind AK, SourceRange R, unsigned SpellingListIndex,
+ bool IsLateParsed, bool DuplicatesAllowed)
+ : Attr(AK, R, SpellingListIndex, IsLateParsed, DuplicatesAllowed) {}
+
+public:
+ void setInherited(bool I) { Inherited = I; }
+
+ // Implement isa/cast/dyncast/etc.
+ static bool classof(const Attr *A) {
+ return A->getKind() <= attr::LAST_INHERITABLE;
+ }
+};
+
+class InheritableParamAttr : public InheritableAttr {
+protected:
+ InheritableParamAttr(attr::Kind AK, SourceRange R, unsigned SpellingListIndex,
+ bool IsLateParsed, bool DuplicatesAllowed)
+ : InheritableAttr(AK, R, SpellingListIndex, IsLateParsed,
+ DuplicatesAllowed) {}
+
+public:
+ // Implement isa/cast/dyncast/etc.
+ static bool classof(const Attr *A) {
+ // Relies on relative order of enum emission with respect to MS inheritance
+ // attrs.
+ return A->getKind() <= attr::LAST_INHERITABLE_PARAM;
+ }
+};
+
+#include "clang/AST/Attrs.inc"
+
+inline const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB,
+ const Attr *At) {
+ DB.AddTaggedVal(reinterpret_cast<intptr_t>(At),
+ DiagnosticsEngine::ak_attr);
+ return DB;
+}
+
+inline const PartialDiagnostic &operator<<(const PartialDiagnostic &PD,
+ const Attr *At) {
+ PD.AddTaggedVal(reinterpret_cast<intptr_t>(At),
+ DiagnosticsEngine::ak_attr);
+ return PD;
+}
+} // end namespace clang
+
+#endif
diff --git a/contrib/llvm/tools/clang/include/clang/AST/AttrIterator.h b/contrib/llvm/tools/clang/include/clang/AST/AttrIterator.h
new file mode 100644
index 0000000..a0c8030
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/AST/AttrIterator.h
@@ -0,0 +1,142 @@
+//===--- AttrIterator.h - Classes for attribute iteration -------*- C++ -*-===//
+//
+// 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 vector and specific_attr_iterator interfaces.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_AST_ATTRITERATOR_H
+#define LLVM_CLANG_AST_ATTRITERATOR_H
+
+#include "clang/Basic/LLVM.h"
+#include <iterator>
+
+namespace clang {
+ class ASTContext;
+ class Attr;
+}
+
+// Defined in ASTContext.h
+void *operator new(size_t Bytes, const clang::ASTContext &C,
+ size_t Alignment = 8);
+// 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);
+
+// 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);
+void operator delete[](void *Ptr, const clang::ASTContext &C, size_t);
+
+namespace clang {
+
+/// AttrVec - A vector of Attr, which is how they are stored on the AST.
+typedef SmallVector<Attr*, 2> AttrVec;
+typedef SmallVector<const Attr*, 2> ConstAttrVec;
+
+/// specific_attr_iterator - Iterates over a subrange of an AttrVec, only
+/// providing attributes that are of a specific type.
+template <typename SpecificAttr, typename Container = AttrVec>
+class specific_attr_iterator {
+ typedef typename Container::const_iterator 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 dereference a
+ /// past-the-end iterator when we move to a past-the-end position.
+ mutable Iterator Current;
+
+ void AdvanceToNext() const {
+ while (!isa<SpecificAttr>(*Current))
+ ++Current;
+ }
+
+ void AdvanceToNext(Iterator I) const {
+ while (Current != I && !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(Iterator i) : Current(i) { }
+
+ reference operator*() const {
+ AdvanceToNext();
+ return cast<SpecificAttr>(*Current);
+ }
+ pointer operator->() const {
+ AdvanceToNext();
+ return 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) {
+ assert((Left.Current == nullptr) == (Right.Current == nullptr));
+ 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 SpecificAttr, typename Container>
+inline specific_attr_iterator<SpecificAttr, Container>
+ specific_attr_begin(const Container& container) {
+ return specific_attr_iterator<SpecificAttr, Container>(container.begin());
+}
+template <typename SpecificAttr, typename Container>
+inline specific_attr_iterator<SpecificAttr, Container>
+ specific_attr_end(const Container& container) {
+ return specific_attr_iterator<SpecificAttr, Container>(container.end());
+}
+
+template <typename SpecificAttr, typename Container>
+inline bool hasSpecificAttr(const Container& container) {
+ return specific_attr_begin<SpecificAttr>(container) !=
+ specific_attr_end<SpecificAttr>(container);
+}
+template <typename SpecificAttr, typename Container>
+inline SpecificAttr *getSpecificAttr(const Container& container) {
+ specific_attr_iterator<SpecificAttr, Container> i =
+ specific_attr_begin<SpecificAttr>(container);
+ if (i != specific_attr_end<SpecificAttr>(container))
+ return *i;
+ else
+ return nullptr;
+}
+
+} // end namespace clang
+
+#endif
diff --git a/contrib/llvm/tools/clang/include/clang/AST/BaseSubobject.h b/contrib/llvm/tools/clang/include/clang/AST/BaseSubobject.h
new file mode 100644
index 0000000..da538e3
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/AST/BaseSubobject.h
@@ -0,0 +1,87 @@
+//===--- BaseSubobject.h - BaseSubobject class ----------------------------===//
+//
+// 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 definition of the BaseSubobject class.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_AST_BASESUBOBJECT_H
+#define LLVM_CLANG_AST_BASESUBOBJECT_H
+
+#include "clang/AST/CharUnits.h"
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/Support/DataTypes.h"
+#include "llvm/Support/type_traits.h"
+
+namespace clang {
+ class CXXRecordDecl;
+
+// 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. Used for vtable and VTT generation.
+class BaseSubobject {
+ /// Base - The base class declaration.
+ const CXXRecordDecl *Base;
+
+ /// BaseOffset - The offset from the most derived class to the base class.
+ CharUnits BaseOffset;
+
+public:
+ BaseSubobject() { }
+ BaseSubobject(const CXXRecordDecl *Base, CharUnits BaseOffset)
+ : Base(Base), BaseOffset(BaseOffset) { }
+
+ /// getBase - Returns the base class declaration.
+ const CXXRecordDecl *getBase() const { return Base; }
+
+ /// getBaseOffset - Returns the base class offset.
+ CharUnits getBaseOffset() const { return BaseOffset; }
+
+ friend bool operator==(const BaseSubobject &LHS, const BaseSubobject &RHS) {
+ return LHS.Base == RHS.Base && LHS.BaseOffset == RHS.BaseOffset;
+ }
+};
+
+} // end namespace clang
+
+namespace llvm {
+
+template<> struct DenseMapInfo<clang::BaseSubobject> {
+ static clang::BaseSubobject getEmptyKey() {
+ return clang::BaseSubobject(
+ DenseMapInfo<const clang::CXXRecordDecl *>::getEmptyKey(),
+ clang::CharUnits::fromQuantity(DenseMapInfo<int64_t>::getEmptyKey()));
+ }
+
+ static clang::BaseSubobject getTombstoneKey() {
+ return clang::BaseSubobject(
+ DenseMapInfo<const clang::CXXRecordDecl *>::getTombstoneKey(),
+ clang::CharUnits::fromQuantity(DenseMapInfo<int64_t>::getTombstoneKey()));
+ }
+
+ static unsigned getHashValue(const clang::BaseSubobject &Base) {
+ typedef std::pair<const clang::CXXRecordDecl *, clang::CharUnits> PairTy;
+ return DenseMapInfo<PairTy>::getHashValue(PairTy(Base.getBase(),
+ Base.getBaseOffset()));
+ }
+
+ static bool isEqual(const clang::BaseSubobject &LHS,
+ const clang::BaseSubobject &RHS) {
+ return LHS == RHS;
+ }
+};
+
+// It's OK to treat BaseSubobject as a POD type.
+template <> struct isPodLike<clang::BaseSubobject> {
+ static const bool value = true;
+};
+
+}
+
+#endif
diff --git a/contrib/llvm/tools/clang/include/clang/AST/BuiltinTypes.def b/contrib/llvm/tools/clang/include/clang/AST/BuiltinTypes.def
new file mode 100644
index 0000000..85e237a
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/AST/BuiltinTypes.def
@@ -0,0 +1,261 @@
+//===-- BuiltinTypeNodes.def - Metadata about BuiltinTypes ------*- C++ -*-===//
+//
+// 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 database about various builtin singleton types.
+//
+// BuiltinType::Id is the enumerator defining the type.
+//
+// Context.SingletonId is the global singleton of this type. Some global
+// singletons are shared by multiple types.
+//
+// BUILTIN_TYPE(Id, SingletonId) - A builtin type that has not been
+// covered by any other #define. Defining this macro covers all
+// the builtins.
+//
+// SIGNED_TYPE(Id, SingletonId) - A signed integral type.
+//
+// UNSIGNED_TYPE(Id, SingletonId) - An unsigned integral type.
+//
+// FLOATING_TYPE(Id, SingletonId) - A floating-point type.
+//
+// PLACEHOLDER_TYPE(Id, SingletonId) - A placeholder type. Placeholder
+// types are used to perform context-sensitive checking of specific
+// forms of expression.
+//
+// SHARED_SINGLETON_TYPE(Expansion) - The given expansion corresponds
+// to a builtin which uses a shared singleton type.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef SIGNED_TYPE
+#define SIGNED_TYPE(Id, SingletonId) BUILTIN_TYPE(Id, SingletonId)
+#endif
+
+#ifndef UNSIGNED_TYPE
+#define UNSIGNED_TYPE(Id, SingletonId) BUILTIN_TYPE(Id, SingletonId)
+#endif
+
+#ifndef FLOATING_TYPE
+#define FLOATING_TYPE(Id, SingletonId) BUILTIN_TYPE(Id, SingletonId)
+#endif
+
+#ifndef PLACEHOLDER_TYPE
+#define PLACEHOLDER_TYPE(Id, SingletonId) BUILTIN_TYPE(Id, SingletonId)
+#endif
+
+#ifndef SHARED_SINGLETON_TYPE
+#define SHARED_SINGLETON_TYPE(Expansion) Expansion
+#endif
+
+//===- Builtin Types ------------------------------------------------------===//
+
+// void
+BUILTIN_TYPE(Void, VoidTy)
+
+//===- Unsigned Types -----------------------------------------------------===//
+
+// 'bool' in C++, '_Bool' in C99
+UNSIGNED_TYPE(Bool, BoolTy)
+
+// 'char' for targets where it's unsigned
+SHARED_SINGLETON_TYPE(UNSIGNED_TYPE(Char_U, CharTy))
+
+// 'unsigned char', explicitly qualified
+UNSIGNED_TYPE(UChar, UnsignedCharTy)
+
+// 'wchar_t' for targets where it's unsigned
+SHARED_SINGLETON_TYPE(UNSIGNED_TYPE(WChar_U, WCharTy))
+
+// 'char16_t' in C++
+UNSIGNED_TYPE(Char16, Char16Ty)
+
+// 'char32_t' in C++
+UNSIGNED_TYPE(Char32, Char32Ty)
+
+// 'unsigned short'
+UNSIGNED_TYPE(UShort, UnsignedShortTy)
+
+// 'unsigned int'
+UNSIGNED_TYPE(UInt, UnsignedIntTy)
+
+// 'unsigned long'
+UNSIGNED_TYPE(ULong, UnsignedLongTy)
+
+// 'unsigned long long'
+UNSIGNED_TYPE(ULongLong, UnsignedLongLongTy)
+
+// '__uint128_t'
+UNSIGNED_TYPE(UInt128, UnsignedInt128Ty)
+
+//===- Signed Types -------------------------------------------------------===//
+
+// 'char' for targets where it's signed
+SHARED_SINGLETON_TYPE(SIGNED_TYPE(Char_S, CharTy))
+
+// 'signed char', explicitly qualified
+SIGNED_TYPE(SChar, SignedCharTy)
+
+// 'wchar_t' for targets where it's signed
+SHARED_SINGLETON_TYPE(SIGNED_TYPE(WChar_S, WCharTy))
+
+// 'short' or 'signed short'
+SIGNED_TYPE(Short, ShortTy)
+
+// 'int' or 'signed int'
+SIGNED_TYPE(Int, IntTy)
+
+// 'long' or 'signed long'
+SIGNED_TYPE(Long, LongTy)
+
+// 'long long' or 'signed long long'
+SIGNED_TYPE(LongLong, LongLongTy)
+
+// '__int128_t'
+SIGNED_TYPE(Int128, Int128Ty)
+
+//===- Floating point types -----------------------------------------------===//
+
+// 'half' in OpenCL, '__fp16' in ARM NEON.
+FLOATING_TYPE(Half, HalfTy)
+
+// 'float'
+FLOATING_TYPE(Float, FloatTy)
+
+// 'double'
+FLOATING_TYPE(Double, DoubleTy)
+
+// 'long double'
+FLOATING_TYPE(LongDouble, LongDoubleTy)
+
+//===- Language-specific types --------------------------------------------===//
+
+// This is the type of C++0x 'nullptr'.
+BUILTIN_TYPE(NullPtr, NullPtrTy)
+
+// The primitive Objective C 'id' type. The user-visible 'id'
+// type is a typedef of an ObjCObjectPointerType to an
+// ObjCObjectType with this as its base. In fact, this only ever
+// shows up in an AST as the base type of an ObjCObjectType.
+BUILTIN_TYPE(ObjCId, ObjCBuiltinIdTy)
+
+// The primitive Objective C 'Class' type. The user-visible
+// 'Class' type is a typedef of an ObjCObjectPointerType to an
+// ObjCObjectType with this as its base. In fact, this only ever
+// shows up in an AST as the base type of an ObjCObjectType.
+BUILTIN_TYPE(ObjCClass, ObjCBuiltinClassTy)
+
+// The primitive Objective C 'SEL' type. The user-visible 'SEL'
+// type is a typedef of a PointerType to this.
+BUILTIN_TYPE(ObjCSel, ObjCBuiltinSelTy)
+
+// OpenCL image types.
+BUILTIN_TYPE(OCLImage1d, OCLImage1dTy)
+BUILTIN_TYPE(OCLImage1dArray, OCLImage1dArrayTy)
+BUILTIN_TYPE(OCLImage1dBuffer, OCLImage1dBufferTy)
+BUILTIN_TYPE(OCLImage2d, OCLImage2dTy)
+BUILTIN_TYPE(OCLImage2dArray, OCLImage2dArrayTy)
+BUILTIN_TYPE(OCLImage2dDepth, OCLImage2dDepthTy)
+BUILTIN_TYPE(OCLImage2dArrayDepth, OCLImage2dArrayDepthTy)
+BUILTIN_TYPE(OCLImage2dMSAA, OCLImage2dMSAATy)
+BUILTIN_TYPE(OCLImage2dArrayMSAA, OCLImage2dArrayMSAATy)
+BUILTIN_TYPE(OCLImage2dMSAADepth, OCLImage2dMSAADepthTy)
+BUILTIN_TYPE(OCLImage2dArrayMSAADepth, OCLImage2dArrayMSAADepthTy)
+BUILTIN_TYPE(OCLImage3d, OCLImage3dTy)
+
+// OpenCL sampler_t.
+BUILTIN_TYPE(OCLSampler, OCLSamplerTy)
+
+// OpenCL event_t.
+BUILTIN_TYPE(OCLEvent, OCLEventTy)
+
+// OpenCL clk_event_t.
+BUILTIN_TYPE(OCLClkEvent, OCLClkEventTy)
+
+// OpenCL queue_t.
+BUILTIN_TYPE(OCLQueue, OCLQueueTy)
+
+// OpenCL ndrange_t.
+BUILTIN_TYPE(OCLNDRange, OCLNDRangeTy)
+
+// OpenCL reserve_id_t.
+BUILTIN_TYPE(OCLReserveID, OCLReserveIDTy)
+
+// 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.
+BUILTIN_TYPE(Dependent, DependentTy)
+
+// The type of an unresolved overload set. A placeholder type.
+// Expressions with this type have one of the following basic
+// forms, with parentheses generally permitted:
+// foo # possibly qualified, not if an implicit access
+// foo # possibly qualified, not if an implicit access
+// &foo # possibly qualified, not if an implicit access
+// x->foo # only if might be a static member function
+// &x->foo # only if might be a static member function
+// &Class::foo # when a pointer-to-member; sub-expr also has this type
+// OverloadExpr::find can be used to analyze the expression.
+//
+// Overload should be the first placeholder type, or else change
+// BuiltinType::isNonOverloadPlaceholderType()
+PLACEHOLDER_TYPE(Overload, OverloadTy)
+
+// The type of a bound C++ non-static member function.
+// A placeholder type. Expressions with this type have one of the
+// following basic forms:
+// foo # if an implicit access
+// x->foo # if only contains non-static members
+PLACEHOLDER_TYPE(BoundMember, BoundMemberTy)
+
+// The type of an expression which refers to a pseudo-object,
+// such as those introduced by Objective C's @property or
+// VS.NET's __property declarations. A placeholder type. The
+// pseudo-object is actually accessed by emitting a call to
+// some sort of function or method; typically there is a pair
+// of a setter and a getter, with the setter used if the
+// pseudo-object reference is used syntactically as the
+// left-hand-side of an assignment operator.
+//
+// A pseudo-object reference naming an Objective-C @property is
+// always a dot access with a base of object-pointer type,
+// e.g. 'x.foo'.
+//
+// In VS.NET, a __property declaration creates an implicit
+// member with an associated name, which can then be named
+// in any of the normal ways an ordinary member could be.
+PLACEHOLDER_TYPE(PseudoObject, PseudoObjectTy)
+
+// __builtin_any_type. A placeholder type. Useful for clients
+// like debuggers that don't know what type to give something.
+// Only a small number of operations are valid on expressions of
+// unknown type, most notably explicit casts.
+PLACEHOLDER_TYPE(UnknownAny, UnknownAnyTy)
+
+PLACEHOLDER_TYPE(BuiltinFn, BuiltinFnTy)
+
+// The type of a cast which, in ARC, would normally require a
+// __bridge, but which might be okay depending on the immediate
+// context.
+PLACEHOLDER_TYPE(ARCUnbridgedCast, ARCUnbridgedCastTy)
+
+// A placeholder type for OpenMP array sections.
+PLACEHOLDER_TYPE(OMPArraySection, OMPArraySectionTy)
+
+#ifdef LAST_BUILTIN_TYPE
+LAST_BUILTIN_TYPE(OMPArraySection)
+#undef LAST_BUILTIN_TYPE
+#endif
+
+#undef SHARED_SINGLETON_TYPE
+#undef PLACEHOLDER_TYPE
+#undef FLOATING_TYPE
+#undef SIGNED_TYPE
+#undef UNSIGNED_TYPE
+#undef BUILTIN_TYPE
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..8587260
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/AST/CXXInheritance.h
@@ -0,0 +1,365 @@
+//===------ 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/DeclBase.h"
+#include "clang/AST/DeclCXX.h"
+#include "clang/AST/DeclarationName.h"
+#include "clang/AST/Type.h"
+#include "clang/AST/TypeOrdering.h"
+#include "llvm/ADT/MapVector.h"
+#include "llvm/ADT/SmallSet.h"
+#include "llvm/ADT/SmallVector.h"
+#include <cassert>
+#include <list>
+#include <map>
+
+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 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() {
+ 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 hierarchy:
+///
+/// @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.
+ llvm::SmallDenseMap<QualType, std::pair<bool, unsigned>, 8> 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.
+ std::unique_ptr<NamedDecl *[]> DeclsFound;
+ unsigned NumDeclsFound;
+
+ friend class CXXRecordDecl;
+
+ void ComputeDeclsFound();
+
+ bool lookupInBases(ASTContext &Context, const CXXRecordDecl *Record,
+ CXXRecordDecl::BaseMatchesCallback BaseMatches);
+
+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(nullptr),
+ NumDeclsFound(0) {}
+
+ 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(); }
+
+ typedef llvm::iterator_range<decl_iterator> decl_range;
+ decl_range found_decls();
+
+ /// \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(nullptr), Subobject(0), InVirtualSubobject(nullptr) { }
+
+ 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 {
+ typedef SmallVector<UniqueVirtualMethod, 4> ValuesT;
+ typedef llvm::MapVector<unsigned, ValuesT> MapType;
+ MapType Overrides;
+
+public:
+ // Iterate over the set of subobjects that have overriding methods.
+ typedef MapType::iterator iterator;
+ typedef MapType::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 SmallVectorImpl<UniqueVirtualMethod>::iterator
+ overriding_iterator;
+ typedef SmallVectorImpl<UniqueVirtualMethod>::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 contains 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 overridden 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 virtual 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::MapVector<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..b25800b
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/AST/CanonicalType.h
@@ -0,0 +1,665 @@
+//===-- 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_CANONICALTYPE_H
+#define LLVM_CLANG_AST_CANONICALTYPE_H
+
+#include "clang/AST/Type.h"
+#include "llvm/ADT/iterator.h"
+#include "llvm/Support/Casting.h"
+
+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 std::enable_if<std::is_base_of<T, U>::value, 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.
+ explicit 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;
+
+ template<typename U> CanProxy<U> castAs() 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, 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, isInterfaceType)
+ 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, isSignedIntegerOrEnumerationType)
+ LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isUnsignedIntegerOrEnumerationType)
+ LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isConstantSizeType)
+ LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isSpecifierType)
+ LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(CXXRecordDecl*, getAsCXXRecordDecl)
+
+ /// \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< ::clang::CanQual<T> > {
+ typedef const T *SimpleType;
+ static SimpleType getSimplifiedValue(::clang::CanQual<T> Val) {
+ return Val.getTypePtr();
+ }
+};
+
+// 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>
+struct CanTypeIterator
+ : llvm::iterator_adaptor_base<
+ CanTypeIterator<InputIterator>, InputIterator,
+ typename std::iterator_traits<InputIterator>::iterator_category,
+ CanQualType,
+ typename std::iterator_traits<InputIterator>::difference_type,
+ CanProxy<Type>, CanQualType> {
+ CanTypeIterator() {}
+ explicit CanTypeIterator(InputIterator Iter)
+ : CanTypeIterator::iterator_adaptor_base(std::move(Iter)) {}
+
+ CanQualType operator*() const { return CanQualType::CreateUnsafe(*this->I); }
+ CanProxy<Type> operator->() const;
+};
+
+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)
+};
+
+// CanProxyAdaptors for arrays are intentionally unimplemented because
+// they are not safe.
+template<> struct CanProxyAdaptor<ArrayType>;
+template<> struct CanProxyAdaptor<ConstantArrayType>;
+template<> struct CanProxyAdaptor<IncompleteArrayType>;
+template<> struct CanProxyAdaptor<VariableArrayType>;
+template<> struct CanProxyAdaptor<DependentSizedArrayType>;
+
+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(getReturnType)
+ LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(FunctionType::ExtInfo, getExtInfo)
+};
+
+template<>
+struct CanProxyAdaptor<FunctionNoProtoType>
+ : public CanProxyBase<FunctionNoProtoType> {
+ LLVM_CLANG_CANPROXY_TYPE_ACCESSOR(getReturnType)
+ LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(FunctionType::ExtInfo, getExtInfo)
+};
+
+template<>
+struct CanProxyAdaptor<FunctionProtoType>
+ : public CanProxyBase<FunctionProtoType> {
+ LLVM_CLANG_CANPROXY_TYPE_ACCESSOR(getReturnType)
+ LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(FunctionType::ExtInfo, getExtInfo)
+ LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(unsigned, getNumParams)
+ CanQualType getParamType(unsigned i) const {
+ return CanQualType::CreateUnsafe(this->getTypePtr()->getParamType(i));
+ }
+
+ LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isVariadic)
+ LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(unsigned, getTypeQuals)
+
+ typedef CanTypeIterator<FunctionProtoType::param_type_iterator>
+ param_type_iterator;
+
+ param_type_iterator param_type_begin() const {
+ return param_type_iterator(this->getTypePtr()->param_type_begin());
+ }
+
+ param_type_iterator param_type_end() const {
+ return param_type_iterator(this->getTypePtr()->param_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<UnaryTransformType>
+ : public CanProxyBase<UnaryTransformType> {
+ LLVM_CLANG_CANPROXY_TYPE_ACCESSOR(getBaseType)
+ LLVM_CLANG_CANPROXY_TYPE_ACCESSOR(getUnderlyingType)
+ LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(UnaryTransformType::UTTKind, getUTTKind)
+};
+
+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(TemplateTypeParmDecl *, getDecl)
+ LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(IdentifierInfo *, getIdentifier)
+};
+
+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 {
+ ArrayType_cannot_be_used_with_getAs<U> at;
+ (void)at;
+
+ if (Stored.isNull())
+ return CanProxy<U>();
+
+ if (isa<U>(Stored.getTypePtr()))
+ return CanQual<U>::CreateUnsafe(Stored);
+
+ return CanProxy<U>();
+}
+
+template<typename T>
+template<typename U>
+CanProxy<U> CanQual<T>::castAs() const {
+ ArrayType_cannot_be_used_with_getAs<U> at;
+ (void)at;
+
+ assert(!Stored.isNull() && isa<U>(Stored.getTypePtr()));
+ return CanQual<U>::CreateUnsafe(Stored);
+}
+
+template<typename T>
+CanProxy<T> CanQual<T>::operator->() const {
+ return CanProxy<T>(*this);
+}
+
+template <typename InputIterator>
+CanProxy<Type> CanTypeIterator<InputIterator>::operator->() const {
+ return CanProxy<Type>(*this);
+}
+
+}
+
+
+#endif
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..1d22bcc
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/AST/CharUnits.h
@@ -0,0 +1,240 @@
+//===--- 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.
+ ///
+ /// In both C and C++, an object of type 'char', 'signed char', or 'unsigned
+ /// char' occupies exactly one byte, so 'character unit' and 'byte' refer to
+ /// the same quantity of storage. However, we use the term 'character unit'
+ /// rather than 'byte' to avoid an implication that a character unit is
+ /// exactly 8 bits.
+ ///
+ /// For portability, never assume that a target character is 8 bits wide. Use
+ /// CharUnit values wherever 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++ () {
+ ++Quantity;
+ return *this;
+ }
+ CharUnits operator++ (int) {
+ return CharUnits(Quantity++);
+ }
+ CharUnits& operator-= (const CharUnits &Other) {
+ Quantity -= Other.Quantity;
+ return *this;
+ }
+ CharUnits& operator-- () {
+ --Quantity;
+ return *this;
+ }
+ CharUnits operator-- (int) {
+ return CharUnits(Quantity--);
+ }
+
+ // 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; }
+
+ /// isPowerOfTwo - Test whether the quantity is a power of two.
+ /// Zero is not a power of two.
+ bool isPowerOfTwo() const {
+ return (Quantity & -Quantity) == Quantity;
+ }
+
+ /// Test whether this is a multiple of the other value.
+ ///
+ /// Among other things, this promises that
+ /// self.RoundUpToAlignment(N) will just return self.
+ bool isMultipleOf(CharUnits N) const {
+ return (*this % N) == 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 \p Align.
+ /// Align must be non-zero.
+ CharUnits RoundUpToAlignment(const CharUnits &Align) const {
+ return CharUnits(llvm::RoundUpToAlignment(Quantity,
+ Align.Quantity));
+ }
+
+ /// Given that this is a non-zero alignment value, what is the
+ /// alignment at the given offset?
+ CharUnits alignmentAtOffset(CharUnits offset) const {
+ assert(Quantity != 0 && "offsetting from unknown alignment?");
+ return CharUnits(llvm::MinAlign(Quantity, offset.Quantity));
+ }
+
+ /// Given that this is the alignment of the first element of an
+ /// array, return the minimum alignment of any element in the array.
+ CharUnits alignmentOfArrayElement(CharUnits elementSize) const {
+ // Since we don't track offsetted alignments, the alignment of
+ // the second element (or any odd element) will be minimally
+ // aligned.
+ return alignmentAtOffset(elementSize);
+ }
+
+
+ }; // 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/Comment.h b/contrib/llvm/tools/clang/include/clang/AST/Comment.h
new file mode 100644
index 0000000..94470cb
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/AST/Comment.h
@@ -0,0 +1,1142 @@
+//===--- Comment.h - Comment 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 comment AST nodes.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_AST_COMMENT_H
+#define LLVM_CLANG_AST_COMMENT_H
+
+#include "clang/AST/CommentCommandTraits.h"
+#include "clang/AST/DeclObjC.h"
+#include "clang/AST/Type.h"
+#include "clang/Basic/SourceLocation.h"
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/StringRef.h"
+
+namespace clang {
+class Decl;
+class ParmVarDecl;
+class TemplateParameterList;
+
+namespace comments {
+class FullComment;
+
+/// Describes the syntax that was used in a documentation command.
+///
+/// Exact values of this enumeration are important because they used to select
+/// parts of diagnostic messages. Audit diagnostics before changing or adding
+/// a new value.
+enum CommandMarkerKind {
+ /// Command started with a backslash character:
+ /// \code
+ /// \foo
+ /// \endcode
+ CMK_Backslash = 0,
+
+ /// Command started with an 'at' character:
+ /// \code
+ /// @foo
+ /// \endcode
+ CMK_At = 1
+};
+
+/// Any part of the comment.
+/// Abstract class.
+class Comment {
+protected:
+ /// Preferred location to show caret.
+ SourceLocation Loc;
+
+ /// Source range of this AST node.
+ SourceRange Range;
+
+ class CommentBitfields {
+ friend class Comment;
+
+ /// Type of this AST node.
+ unsigned Kind : 8;
+ };
+ enum { NumCommentBits = 8 };
+
+ class InlineContentCommentBitfields {
+ friend class InlineContentComment;
+
+ unsigned : NumCommentBits;
+
+ /// True if there is a newline after this inline content node.
+ /// (There is no separate AST node for a newline.)
+ unsigned HasTrailingNewline : 1;
+ };
+ enum { NumInlineContentCommentBits = NumCommentBits + 1 };
+
+ class TextCommentBitfields {
+ friend class TextComment;
+
+ unsigned : NumInlineContentCommentBits;
+
+ /// True if \c IsWhitespace field contains a valid value.
+ mutable unsigned IsWhitespaceValid : 1;
+
+ /// True if this comment AST node contains only whitespace.
+ mutable unsigned IsWhitespace : 1;
+ };
+ enum { NumTextCommentBits = NumInlineContentCommentBits + 2 };
+
+ class InlineCommandCommentBitfields {
+ friend class InlineCommandComment;
+
+ unsigned : NumInlineContentCommentBits;
+
+ unsigned RenderKind : 2;
+ unsigned CommandID : CommandInfo::NumCommandIDBits;
+ };
+ enum { NumInlineCommandCommentBits = NumInlineContentCommentBits + 2 +
+ CommandInfo::NumCommandIDBits };
+
+ class HTMLTagCommentBitfields {
+ friend class HTMLTagComment;
+
+ unsigned : NumInlineContentCommentBits;
+
+ /// True if we found that this tag is malformed in some way.
+ unsigned IsMalformed : 1;
+ };
+ enum { NumHTMLTagCommentBits = NumInlineContentCommentBits + 1 };
+
+ class HTMLStartTagCommentBitfields {
+ friend class HTMLStartTagComment;
+
+ unsigned : NumHTMLTagCommentBits;
+
+ /// True if this tag is self-closing (e. g., <br />). This is based on tag
+ /// spelling in comment (plain <br> would not set this flag).
+ unsigned IsSelfClosing : 1;
+ };
+ enum { NumHTMLStartTagCommentBits = NumHTMLTagCommentBits + 1 };
+
+ class ParagraphCommentBitfields {
+ friend class ParagraphComment;
+
+ unsigned : NumCommentBits;
+
+ /// True if \c IsWhitespace field contains a valid value.
+ mutable unsigned IsWhitespaceValid : 1;
+
+ /// True if this comment AST node contains only whitespace.
+ mutable unsigned IsWhitespace : 1;
+ };
+ enum { NumParagraphCommentBits = NumCommentBits + 2 };
+
+ class BlockCommandCommentBitfields {
+ friend class BlockCommandComment;
+
+ unsigned : NumCommentBits;
+
+ unsigned CommandID : CommandInfo::NumCommandIDBits;
+
+ /// Describes the syntax that was used in a documentation command.
+ /// Contains values from CommandMarkerKind enum.
+ unsigned CommandMarker : 1;
+ };
+ enum { NumBlockCommandCommentBits = NumCommentBits +
+ CommandInfo::NumCommandIDBits + 1 };
+
+ class ParamCommandCommentBitfields {
+ friend class ParamCommandComment;
+
+ unsigned : NumBlockCommandCommentBits;
+
+ /// Parameter passing direction, see ParamCommandComment::PassDirection.
+ unsigned Direction : 2;
+
+ /// True if direction was specified explicitly in the comment.
+ unsigned IsDirectionExplicit : 1;
+ };
+ enum { NumParamCommandCommentBits = NumBlockCommandCommentBits + 3 };
+
+ union {
+ CommentBitfields CommentBits;
+ InlineContentCommentBitfields InlineContentCommentBits;
+ TextCommentBitfields TextCommentBits;
+ InlineCommandCommentBitfields InlineCommandCommentBits;
+ HTMLTagCommentBitfields HTMLTagCommentBits;
+ HTMLStartTagCommentBitfields HTMLStartTagCommentBits;
+ ParagraphCommentBitfields ParagraphCommentBits;
+ BlockCommandCommentBitfields BlockCommandCommentBits;
+ ParamCommandCommentBitfields ParamCommandCommentBits;
+ };
+
+ void setSourceRange(SourceRange SR) {
+ Range = SR;
+ }
+
+ void setLocation(SourceLocation L) {
+ Loc = L;
+ }
+
+public:
+ enum CommentKind {
+ NoCommentKind = 0,
+#define COMMENT(CLASS, PARENT) CLASS##Kind,
+#define COMMENT_RANGE(BASE, FIRST, LAST) \
+ First##BASE##Constant=FIRST##Kind, Last##BASE##Constant=LAST##Kind,
+#define LAST_COMMENT_RANGE(BASE, FIRST, LAST) \
+ First##BASE##Constant=FIRST##Kind, Last##BASE##Constant=LAST##Kind
+#define ABSTRACT_COMMENT(COMMENT)
+#include "clang/AST/CommentNodes.inc"
+ };
+
+ Comment(CommentKind K,
+ SourceLocation LocBegin,
+ SourceLocation LocEnd) :
+ Loc(LocBegin), Range(SourceRange(LocBegin, LocEnd)) {
+ CommentBits.Kind = K;
+ }
+
+ CommentKind getCommentKind() const {
+ return static_cast<CommentKind>(CommentBits.Kind);
+ }
+
+ const char *getCommentKindName() const;
+
+ void dump() const;
+ void dumpColor() const;
+ void dump(const ASTContext &Context) const;
+ void dump(raw_ostream &OS, const CommandTraits *Traits,
+ const SourceManager *SM) const;
+
+ SourceRange getSourceRange() const LLVM_READONLY { return Range; }
+
+ SourceLocation getLocStart() const LLVM_READONLY {
+ return Range.getBegin();
+ }
+
+ SourceLocation getLocEnd() const LLVM_READONLY {
+ return Range.getEnd();
+ }
+
+ SourceLocation getLocation() const LLVM_READONLY { return Loc; }
+
+ typedef Comment * const *child_iterator;
+
+ child_iterator child_begin() const;
+ child_iterator child_end() const;
+
+ // TODO: const child iterator
+
+ unsigned child_count() const {
+ return child_end() - child_begin();
+ }
+};
+
+/// Inline content (contained within a block).
+/// Abstract class.
+class InlineContentComment : public Comment {
+protected:
+ InlineContentComment(CommentKind K,
+ SourceLocation LocBegin,
+ SourceLocation LocEnd) :
+ Comment(K, LocBegin, LocEnd) {
+ InlineContentCommentBits.HasTrailingNewline = 0;
+ }
+
+public:
+ static bool classof(const Comment *C) {
+ return C->getCommentKind() >= FirstInlineContentCommentConstant &&
+ C->getCommentKind() <= LastInlineContentCommentConstant;
+ }
+
+ void addTrailingNewline() {
+ InlineContentCommentBits.HasTrailingNewline = 1;
+ }
+
+ bool hasTrailingNewline() const {
+ return InlineContentCommentBits.HasTrailingNewline;
+ }
+};
+
+/// Plain text.
+class TextComment : public InlineContentComment {
+ StringRef Text;
+
+public:
+ TextComment(SourceLocation LocBegin,
+ SourceLocation LocEnd,
+ StringRef Text) :
+ InlineContentComment(TextCommentKind, LocBegin, LocEnd),
+ Text(Text) {
+ TextCommentBits.IsWhitespaceValid = false;
+ }
+
+ static bool classof(const Comment *C) {
+ return C->getCommentKind() == TextCommentKind;
+ }
+
+ child_iterator child_begin() const { return nullptr; }
+
+ child_iterator child_end() const { return nullptr; }
+
+ StringRef getText() const LLVM_READONLY { return Text; }
+
+ bool isWhitespace() const {
+ if (TextCommentBits.IsWhitespaceValid)
+ return TextCommentBits.IsWhitespace;
+
+ TextCommentBits.IsWhitespace = isWhitespaceNoCache();
+ TextCommentBits.IsWhitespaceValid = true;
+ return TextCommentBits.IsWhitespace;
+ }
+
+private:
+ bool isWhitespaceNoCache() const;
+};
+
+/// A command with word-like arguments that is considered inline content.
+class InlineCommandComment : public InlineContentComment {
+public:
+ struct Argument {
+ SourceRange Range;
+ StringRef Text;
+
+ Argument(SourceRange Range, StringRef Text) : Range(Range), Text(Text) { }
+ };
+
+ /// The most appropriate rendering mode for this command, chosen on command
+ /// semantics in Doxygen.
+ enum RenderKind {
+ RenderNormal,
+ RenderBold,
+ RenderMonospaced,
+ RenderEmphasized
+ };
+
+protected:
+ /// Command arguments.
+ ArrayRef<Argument> Args;
+
+public:
+ InlineCommandComment(SourceLocation LocBegin,
+ SourceLocation LocEnd,
+ unsigned CommandID,
+ RenderKind RK,
+ ArrayRef<Argument> Args) :
+ InlineContentComment(InlineCommandCommentKind, LocBegin, LocEnd),
+ Args(Args) {
+ InlineCommandCommentBits.RenderKind = RK;
+ InlineCommandCommentBits.CommandID = CommandID;
+ }
+
+ static bool classof(const Comment *C) {
+ return C->getCommentKind() == InlineCommandCommentKind;
+ }
+
+ child_iterator child_begin() const { return nullptr; }
+
+ child_iterator child_end() const { return nullptr; }
+
+ unsigned getCommandID() const {
+ return InlineCommandCommentBits.CommandID;
+ }
+
+ StringRef getCommandName(const CommandTraits &Traits) const {
+ return Traits.getCommandInfo(getCommandID())->Name;
+ }
+
+ SourceRange getCommandNameRange() const {
+ return SourceRange(getLocStart().getLocWithOffset(-1),
+ getLocEnd());
+ }
+
+ RenderKind getRenderKind() const {
+ return static_cast<RenderKind>(InlineCommandCommentBits.RenderKind);
+ }
+
+ unsigned getNumArgs() const {
+ return Args.size();
+ }
+
+ StringRef getArgText(unsigned Idx) const {
+ return Args[Idx].Text;
+ }
+
+ SourceRange getArgRange(unsigned Idx) const {
+ return Args[Idx].Range;
+ }
+};
+
+/// Abstract class for opening and closing HTML tags. HTML tags are always
+/// treated as inline content (regardless HTML semantics).
+class HTMLTagComment : public InlineContentComment {
+protected:
+ StringRef TagName;
+ SourceRange TagNameRange;
+
+ HTMLTagComment(CommentKind K,
+ SourceLocation LocBegin,
+ SourceLocation LocEnd,
+ StringRef TagName,
+ SourceLocation TagNameBegin,
+ SourceLocation TagNameEnd) :
+ InlineContentComment(K, LocBegin, LocEnd),
+ TagName(TagName),
+ TagNameRange(TagNameBegin, TagNameEnd) {
+ setLocation(TagNameBegin);
+ HTMLTagCommentBits.IsMalformed = 0;
+ }
+
+public:
+ static bool classof(const Comment *C) {
+ return C->getCommentKind() >= FirstHTMLTagCommentConstant &&
+ C->getCommentKind() <= LastHTMLTagCommentConstant;
+ }
+
+ StringRef getTagName() const LLVM_READONLY { return TagName; }
+
+ SourceRange getTagNameSourceRange() const LLVM_READONLY {
+ SourceLocation L = getLocation();
+ return SourceRange(L.getLocWithOffset(1),
+ L.getLocWithOffset(1 + TagName.size()));
+ }
+
+ bool isMalformed() const {
+ return HTMLTagCommentBits.IsMalformed;
+ }
+
+ void setIsMalformed() {
+ HTMLTagCommentBits.IsMalformed = 1;
+ }
+};
+
+/// An opening HTML tag with attributes.
+class HTMLStartTagComment : public HTMLTagComment {
+public:
+ class Attribute {
+ public:
+ SourceLocation NameLocBegin;
+ StringRef Name;
+
+ SourceLocation EqualsLoc;
+
+ SourceRange ValueRange;
+ StringRef Value;
+
+ Attribute() { }
+
+ Attribute(SourceLocation NameLocBegin, StringRef Name) :
+ NameLocBegin(NameLocBegin), Name(Name),
+ EqualsLoc(SourceLocation()),
+ ValueRange(SourceRange()), Value(StringRef())
+ { }
+
+ Attribute(SourceLocation NameLocBegin, StringRef Name,
+ SourceLocation EqualsLoc,
+ SourceRange ValueRange, StringRef Value) :
+ NameLocBegin(NameLocBegin), Name(Name),
+ EqualsLoc(EqualsLoc),
+ ValueRange(ValueRange), Value(Value)
+ { }
+
+ SourceLocation getNameLocEnd() const {
+ return NameLocBegin.getLocWithOffset(Name.size());
+ }
+
+ SourceRange getNameRange() const {
+ return SourceRange(NameLocBegin, getNameLocEnd());
+ }
+ };
+
+private:
+ ArrayRef<Attribute> Attributes;
+
+public:
+ HTMLStartTagComment(SourceLocation LocBegin,
+ StringRef TagName) :
+ HTMLTagComment(HTMLStartTagCommentKind,
+ LocBegin, LocBegin.getLocWithOffset(1 + TagName.size()),
+ TagName,
+ LocBegin.getLocWithOffset(1),
+ LocBegin.getLocWithOffset(1 + TagName.size())) {
+ HTMLStartTagCommentBits.IsSelfClosing = false;
+ }
+
+ static bool classof(const Comment *C) {
+ return C->getCommentKind() == HTMLStartTagCommentKind;
+ }
+
+ child_iterator child_begin() const { return nullptr; }
+
+ child_iterator child_end() const { return nullptr; }
+
+ unsigned getNumAttrs() const {
+ return Attributes.size();
+ }
+
+ const Attribute &getAttr(unsigned Idx) const {
+ return Attributes[Idx];
+ }
+
+ void setAttrs(ArrayRef<Attribute> Attrs) {
+ Attributes = Attrs;
+ if (!Attrs.empty()) {
+ const Attribute &Attr = Attrs.back();
+ SourceLocation L = Attr.ValueRange.getEnd();
+ if (L.isValid())
+ Range.setEnd(L);
+ else {
+ Range.setEnd(Attr.getNameLocEnd());
+ }
+ }
+ }
+
+ void setGreaterLoc(SourceLocation GreaterLoc) {
+ Range.setEnd(GreaterLoc);
+ }
+
+ bool isSelfClosing() const {
+ return HTMLStartTagCommentBits.IsSelfClosing;
+ }
+
+ void setSelfClosing() {
+ HTMLStartTagCommentBits.IsSelfClosing = true;
+ }
+};
+
+/// A closing HTML tag.
+class HTMLEndTagComment : public HTMLTagComment {
+public:
+ HTMLEndTagComment(SourceLocation LocBegin,
+ SourceLocation LocEnd,
+ StringRef TagName) :
+ HTMLTagComment(HTMLEndTagCommentKind,
+ LocBegin, LocEnd,
+ TagName,
+ LocBegin.getLocWithOffset(2),
+ LocBegin.getLocWithOffset(2 + TagName.size()))
+ { }
+
+ static bool classof(const Comment *C) {
+ return C->getCommentKind() == HTMLEndTagCommentKind;
+ }
+
+ child_iterator child_begin() const { return nullptr; }
+
+ child_iterator child_end() const { return nullptr; }
+};
+
+/// Block content (contains inline content).
+/// Abstract class.
+class BlockContentComment : public Comment {
+protected:
+ BlockContentComment(CommentKind K,
+ SourceLocation LocBegin,
+ SourceLocation LocEnd) :
+ Comment(K, LocBegin, LocEnd)
+ { }
+
+public:
+ static bool classof(const Comment *C) {
+ return C->getCommentKind() >= FirstBlockContentCommentConstant &&
+ C->getCommentKind() <= LastBlockContentCommentConstant;
+ }
+};
+
+/// A single paragraph that contains inline content.
+class ParagraphComment : public BlockContentComment {
+ ArrayRef<InlineContentComment *> Content;
+
+public:
+ ParagraphComment(ArrayRef<InlineContentComment *> Content) :
+ BlockContentComment(ParagraphCommentKind,
+ SourceLocation(),
+ SourceLocation()),
+ Content(Content) {
+ if (Content.empty()) {
+ ParagraphCommentBits.IsWhitespace = true;
+ ParagraphCommentBits.IsWhitespaceValid = true;
+ return;
+ }
+
+ ParagraphCommentBits.IsWhitespaceValid = false;
+
+ setSourceRange(SourceRange(Content.front()->getLocStart(),
+ Content.back()->getLocEnd()));
+ setLocation(Content.front()->getLocStart());
+ }
+
+ static bool classof(const Comment *C) {
+ return C->getCommentKind() == ParagraphCommentKind;
+ }
+
+ child_iterator child_begin() const {
+ return reinterpret_cast<child_iterator>(Content.begin());
+ }
+
+ child_iterator child_end() const {
+ return reinterpret_cast<child_iterator>(Content.end());
+ }
+
+ bool isWhitespace() const {
+ if (ParagraphCommentBits.IsWhitespaceValid)
+ return ParagraphCommentBits.IsWhitespace;
+
+ ParagraphCommentBits.IsWhitespace = isWhitespaceNoCache();
+ ParagraphCommentBits.IsWhitespaceValid = true;
+ return ParagraphCommentBits.IsWhitespace;
+ }
+
+private:
+ bool isWhitespaceNoCache() const;
+};
+
+/// A command that has zero or more word-like arguments (number of word-like
+/// arguments depends on command name) and a paragraph as an argument
+/// (e. g., \\brief).
+class BlockCommandComment : public BlockContentComment {
+public:
+ struct Argument {
+ SourceRange Range;
+ StringRef Text;
+
+ Argument() { }
+ Argument(SourceRange Range, StringRef Text) : Range(Range), Text(Text) { }
+ };
+
+protected:
+ /// Word-like arguments.
+ ArrayRef<Argument> Args;
+
+ /// Paragraph argument.
+ ParagraphComment *Paragraph;
+
+ BlockCommandComment(CommentKind K,
+ SourceLocation LocBegin,
+ SourceLocation LocEnd,
+ unsigned CommandID,
+ CommandMarkerKind CommandMarker) :
+ BlockContentComment(K, LocBegin, LocEnd),
+ Paragraph(nullptr) {
+ setLocation(getCommandNameBeginLoc());
+ BlockCommandCommentBits.CommandID = CommandID;
+ BlockCommandCommentBits.CommandMarker = CommandMarker;
+ }
+
+public:
+ BlockCommandComment(SourceLocation LocBegin,
+ SourceLocation LocEnd,
+ unsigned CommandID,
+ CommandMarkerKind CommandMarker) :
+ BlockContentComment(BlockCommandCommentKind, LocBegin, LocEnd),
+ Paragraph(nullptr) {
+ setLocation(getCommandNameBeginLoc());
+ BlockCommandCommentBits.CommandID = CommandID;
+ BlockCommandCommentBits.CommandMarker = CommandMarker;
+ }
+
+ static bool classof(const Comment *C) {
+ return C->getCommentKind() >= FirstBlockCommandCommentConstant &&
+ C->getCommentKind() <= LastBlockCommandCommentConstant;
+ }
+
+ child_iterator child_begin() const {
+ return reinterpret_cast<child_iterator>(&Paragraph);
+ }
+
+ child_iterator child_end() const {
+ return reinterpret_cast<child_iterator>(&Paragraph + 1);
+ }
+
+ unsigned getCommandID() const {
+ return BlockCommandCommentBits.CommandID;
+ }
+
+ StringRef getCommandName(const CommandTraits &Traits) const {
+ return Traits.getCommandInfo(getCommandID())->Name;
+ }
+
+ SourceLocation getCommandNameBeginLoc() const {
+ return getLocStart().getLocWithOffset(1);
+ }
+
+ SourceRange getCommandNameRange(const CommandTraits &Traits) const {
+ StringRef Name = getCommandName(Traits);
+ return SourceRange(getCommandNameBeginLoc(),
+ getLocStart().getLocWithOffset(1 + Name.size()));
+ }
+
+ unsigned getNumArgs() const {
+ return Args.size();
+ }
+
+ StringRef getArgText(unsigned Idx) const {
+ return Args[Idx].Text;
+ }
+
+ SourceRange getArgRange(unsigned Idx) const {
+ return Args[Idx].Range;
+ }
+
+ void setArgs(ArrayRef<Argument> A) {
+ Args = A;
+ if (Args.size() > 0) {
+ SourceLocation NewLocEnd = Args.back().Range.getEnd();
+ if (NewLocEnd.isValid())
+ setSourceRange(SourceRange(getLocStart(), NewLocEnd));
+ }
+ }
+
+ ParagraphComment *getParagraph() const LLVM_READONLY {
+ return Paragraph;
+ }
+
+ bool hasNonWhitespaceParagraph() const {
+ return Paragraph && !Paragraph->isWhitespace();
+ }
+
+ void setParagraph(ParagraphComment *PC) {
+ Paragraph = PC;
+ SourceLocation NewLocEnd = PC->getLocEnd();
+ if (NewLocEnd.isValid())
+ setSourceRange(SourceRange(getLocStart(), NewLocEnd));
+ }
+
+ CommandMarkerKind getCommandMarker() const LLVM_READONLY {
+ return static_cast<CommandMarkerKind>(
+ BlockCommandCommentBits.CommandMarker);
+ }
+};
+
+/// Doxygen \\param command.
+class ParamCommandComment : public BlockCommandComment {
+private:
+ /// Parameter index in the function declaration.
+ unsigned ParamIndex;
+
+public:
+ enum : unsigned {
+ InvalidParamIndex = ~0U,
+ VarArgParamIndex = ~0U/*InvalidParamIndex*/ - 1U
+ };
+
+ ParamCommandComment(SourceLocation LocBegin,
+ SourceLocation LocEnd,
+ unsigned CommandID,
+ CommandMarkerKind CommandMarker) :
+ BlockCommandComment(ParamCommandCommentKind, LocBegin, LocEnd,
+ CommandID, CommandMarker),
+ ParamIndex(InvalidParamIndex) {
+ ParamCommandCommentBits.Direction = In;
+ ParamCommandCommentBits.IsDirectionExplicit = false;
+ }
+
+ static bool classof(const Comment *C) {
+ return C->getCommentKind() == ParamCommandCommentKind;
+ }
+
+ enum PassDirection {
+ In,
+ Out,
+ InOut
+ };
+
+ static const char *getDirectionAsString(PassDirection D);
+
+ PassDirection getDirection() const LLVM_READONLY {
+ return static_cast<PassDirection>(ParamCommandCommentBits.Direction);
+ }
+
+ bool isDirectionExplicit() const LLVM_READONLY {
+ return ParamCommandCommentBits.IsDirectionExplicit;
+ }
+
+ void setDirection(PassDirection Direction, bool Explicit) {
+ ParamCommandCommentBits.Direction = Direction;
+ ParamCommandCommentBits.IsDirectionExplicit = Explicit;
+ }
+
+ bool hasParamName() const {
+ return getNumArgs() > 0;
+ }
+
+ StringRef getParamName(const FullComment *FC) const;
+
+ StringRef getParamNameAsWritten() const {
+ return Args[0].Text;
+ }
+
+ SourceRange getParamNameRange() const {
+ return Args[0].Range;
+ }
+
+ bool isParamIndexValid() const LLVM_READONLY {
+ return ParamIndex != InvalidParamIndex;
+ }
+
+ bool isVarArgParam() const LLVM_READONLY {
+ return ParamIndex == VarArgParamIndex;
+ }
+
+ void setIsVarArgParam() {
+ ParamIndex = VarArgParamIndex;
+ assert(isParamIndexValid());
+ }
+
+ unsigned getParamIndex() const LLVM_READONLY {
+ assert(isParamIndexValid());
+ assert(!isVarArgParam());
+ return ParamIndex;
+ }
+
+ void setParamIndex(unsigned Index) {
+ ParamIndex = Index;
+ assert(isParamIndexValid());
+ assert(!isVarArgParam());
+ }
+};
+
+/// Doxygen \\tparam command, describes a template parameter.
+class TParamCommandComment : public BlockCommandComment {
+private:
+ /// If this template parameter name was resolved (found in template parameter
+ /// list), then this stores a list of position indexes in all template
+ /// parameter lists.
+ ///
+ /// For example:
+ /// \verbatim
+ /// template<typename C, template<typename T> class TT>
+ /// void test(TT<int> aaa);
+ /// \endverbatim
+ /// For C: Position = { 0 }
+ /// For TT: Position = { 1 }
+ /// For T: Position = { 1, 0 }
+ ArrayRef<unsigned> Position;
+
+public:
+ TParamCommandComment(SourceLocation LocBegin,
+ SourceLocation LocEnd,
+ unsigned CommandID,
+ CommandMarkerKind CommandMarker) :
+ BlockCommandComment(TParamCommandCommentKind, LocBegin, LocEnd, CommandID,
+ CommandMarker)
+ { }
+
+ static bool classof(const Comment *C) {
+ return C->getCommentKind() == TParamCommandCommentKind;
+ }
+
+ bool hasParamName() const {
+ return getNumArgs() > 0;
+ }
+
+ StringRef getParamName(const FullComment *FC) const;
+
+ StringRef getParamNameAsWritten() const {
+ return Args[0].Text;
+ }
+
+ SourceRange getParamNameRange() const {
+ return Args[0].Range;
+ }
+
+ bool isPositionValid() const LLVM_READONLY {
+ return !Position.empty();
+ }
+
+ unsigned getDepth() const {
+ assert(isPositionValid());
+ return Position.size();
+ }
+
+ unsigned getIndex(unsigned Depth) const {
+ assert(isPositionValid());
+ return Position[Depth];
+ }
+
+ void setPosition(ArrayRef<unsigned> NewPosition) {
+ Position = NewPosition;
+ assert(isPositionValid());
+ }
+};
+
+/// A line of text contained in a verbatim block.
+class VerbatimBlockLineComment : public Comment {
+ StringRef Text;
+
+public:
+ VerbatimBlockLineComment(SourceLocation LocBegin,
+ StringRef Text) :
+ Comment(VerbatimBlockLineCommentKind,
+ LocBegin,
+ LocBegin.getLocWithOffset(Text.size())),
+ Text(Text)
+ { }
+
+ static bool classof(const Comment *C) {
+ return C->getCommentKind() == VerbatimBlockLineCommentKind;
+ }
+
+ child_iterator child_begin() const { return nullptr; }
+
+ child_iterator child_end() const { return nullptr; }
+
+ StringRef getText() const LLVM_READONLY {
+ return Text;
+ }
+};
+
+/// A verbatim block command (e. g., preformatted code). Verbatim block has an
+/// opening and a closing command and contains multiple lines of text
+/// (VerbatimBlockLineComment nodes).
+class VerbatimBlockComment : public BlockCommandComment {
+protected:
+ StringRef CloseName;
+ SourceLocation CloseNameLocBegin;
+ ArrayRef<VerbatimBlockLineComment *> Lines;
+
+public:
+ VerbatimBlockComment(SourceLocation LocBegin,
+ SourceLocation LocEnd,
+ unsigned CommandID) :
+ BlockCommandComment(VerbatimBlockCommentKind,
+ LocBegin, LocEnd, CommandID,
+ CMK_At) // FIXME: improve source fidelity.
+ { }
+
+ static bool classof(const Comment *C) {
+ return C->getCommentKind() == VerbatimBlockCommentKind;
+ }
+
+ child_iterator child_begin() const {
+ return reinterpret_cast<child_iterator>(Lines.begin());
+ }
+
+ child_iterator child_end() const {
+ return reinterpret_cast<child_iterator>(Lines.end());
+ }
+
+ void setCloseName(StringRef Name, SourceLocation LocBegin) {
+ CloseName = Name;
+ CloseNameLocBegin = LocBegin;
+ }
+
+ void setLines(ArrayRef<VerbatimBlockLineComment *> L) {
+ Lines = L;
+ }
+
+ StringRef getCloseName() const {
+ return CloseName;
+ }
+
+ unsigned getNumLines() const {
+ return Lines.size();
+ }
+
+ StringRef getText(unsigned LineIdx) const {
+ return Lines[LineIdx]->getText();
+ }
+};
+
+/// A verbatim line command. Verbatim line has an opening command, a single
+/// line of text (up to the newline after the opening command) and has no
+/// closing command.
+class VerbatimLineComment : public BlockCommandComment {
+protected:
+ StringRef Text;
+ SourceLocation TextBegin;
+
+public:
+ VerbatimLineComment(SourceLocation LocBegin,
+ SourceLocation LocEnd,
+ unsigned CommandID,
+ SourceLocation TextBegin,
+ StringRef Text) :
+ BlockCommandComment(VerbatimLineCommentKind,
+ LocBegin, LocEnd,
+ CommandID,
+ CMK_At), // FIXME: improve source fidelity.
+ Text(Text),
+ TextBegin(TextBegin)
+ { }
+
+ static bool classof(const Comment *C) {
+ return C->getCommentKind() == VerbatimLineCommentKind;
+ }
+
+ child_iterator child_begin() const { return nullptr; }
+
+ child_iterator child_end() const { return nullptr; }
+
+ StringRef getText() const {
+ return Text;
+ }
+
+ SourceRange getTextRange() const {
+ return SourceRange(TextBegin, getLocEnd());
+ }
+};
+
+/// Information about the declaration, useful to clients of FullComment.
+struct DeclInfo {
+ /// Declaration the comment is actually attached to (in the source).
+ /// Should not be NULL.
+ const Decl *CommentDecl;
+
+ /// CurrentDecl is the declaration with which the FullComment is associated.
+ ///
+ /// It can be different from \c CommentDecl. It happens when we we decide
+ /// that the comment originally attached to \c CommentDecl is fine for
+ /// \c CurrentDecl too (for example, for a redeclaration or an overrider of
+ /// \c CommentDecl).
+ ///
+ /// The information in the DeclInfo corresponds to CurrentDecl.
+ const Decl *CurrentDecl;
+
+ /// Parameters that can be referenced by \\param if \c CommentDecl is something
+ /// that we consider a "function".
+ ArrayRef<const ParmVarDecl *> ParamVars;
+
+ /// Function return type if \c CommentDecl is something that we consider
+ /// a "function".
+ QualType ReturnType;
+
+ /// Template parameters that can be referenced by \\tparam if \c CommentDecl is
+ /// a template (\c IsTemplateDecl or \c IsTemplatePartialSpecialization is
+ /// true).
+ const TemplateParameterList *TemplateParameters;
+
+ /// A simplified description of \c CommentDecl kind that should be good enough
+ /// for documentation rendering purposes.
+ enum DeclKind {
+ /// Everything else not explicitly mentioned below.
+ OtherKind,
+
+ /// Something that we consider a "function":
+ /// \li function,
+ /// \li function template,
+ /// \li function template specialization,
+ /// \li member function,
+ /// \li member function template,
+ /// \li member function template specialization,
+ /// \li ObjC method,
+ /// \li a typedef for a function pointer, member function pointer,
+ /// ObjC block.
+ FunctionKind,
+
+ /// Something that we consider a "class":
+ /// \li class/struct,
+ /// \li class template,
+ /// \li class template (partial) specialization.
+ ClassKind,
+
+ /// Something that we consider a "variable":
+ /// \li namespace scope variables;
+ /// \li static and non-static class data members;
+ /// \li enumerators.
+ VariableKind,
+
+ /// A C++ namespace.
+ NamespaceKind,
+
+ /// A C++ typedef-name (a 'typedef' decl specifier or alias-declaration),
+ /// see \c TypedefNameDecl.
+ TypedefKind,
+
+ /// An enumeration or scoped enumeration.
+ EnumKind
+ };
+
+ /// What kind of template specialization \c CommentDecl is.
+ enum TemplateDeclKind {
+ NotTemplate,
+ Template,
+ TemplateSpecialization,
+ TemplatePartialSpecialization
+ };
+
+ /// If false, only \c CommentDecl is valid.
+ unsigned IsFilled : 1;
+
+ /// Simplified kind of \c CommentDecl, see \c DeclKind enum.
+ unsigned Kind : 3;
+
+ /// Is \c CommentDecl a template declaration.
+ unsigned TemplateKind : 2;
+
+ /// Is \c CommentDecl an ObjCMethodDecl.
+ unsigned IsObjCMethod : 1;
+
+ /// Is \c CommentDecl a non-static member function of C++ class or
+ /// instance method of ObjC class.
+ /// Can be true only if \c IsFunctionDecl is true.
+ unsigned IsInstanceMethod : 1;
+
+ /// Is \c CommentDecl a static member function of C++ class or
+ /// class method of ObjC class.
+ /// Can be true only if \c IsFunctionDecl is true.
+ unsigned IsClassMethod : 1;
+
+ void fill();
+
+ DeclKind getKind() const LLVM_READONLY {
+ return static_cast<DeclKind>(Kind);
+ }
+
+ TemplateDeclKind getTemplateKind() const LLVM_READONLY {
+ return static_cast<TemplateDeclKind>(TemplateKind);
+ }
+};
+
+/// A full comment attached to a declaration, contains block content.
+class FullComment : public Comment {
+ ArrayRef<BlockContentComment *> Blocks;
+ DeclInfo *ThisDeclInfo;
+
+public:
+ FullComment(ArrayRef<BlockContentComment *> Blocks, DeclInfo *D) :
+ Comment(FullCommentKind, SourceLocation(), SourceLocation()),
+ Blocks(Blocks), ThisDeclInfo(D) {
+ if (Blocks.empty())
+ return;
+
+ setSourceRange(SourceRange(Blocks.front()->getLocStart(),
+ Blocks.back()->getLocEnd()));
+ setLocation(Blocks.front()->getLocStart());
+ }
+
+ static bool classof(const Comment *C) {
+ return C->getCommentKind() == FullCommentKind;
+ }
+
+ child_iterator child_begin() const {
+ return reinterpret_cast<child_iterator>(Blocks.begin());
+ }
+
+ child_iterator child_end() const {
+ return reinterpret_cast<child_iterator>(Blocks.end());
+ }
+
+ const Decl *getDecl() const LLVM_READONLY {
+ return ThisDeclInfo->CommentDecl;
+ }
+
+ const DeclInfo *getDeclInfo() const LLVM_READONLY {
+ if (!ThisDeclInfo->IsFilled)
+ ThisDeclInfo->fill();
+ return ThisDeclInfo;
+ }
+
+ ArrayRef<BlockContentComment *> getBlocks() const { return Blocks; }
+
+};
+} // end namespace comments
+} // end namespace clang
+
+#endif
+
diff --git a/contrib/llvm/tools/clang/include/clang/AST/CommentBriefParser.h b/contrib/llvm/tools/clang/include/clang/AST/CommentBriefParser.h
new file mode 100644
index 0000000..be5b8ee
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/AST/CommentBriefParser.h
@@ -0,0 +1,55 @@
+//===--- CommentBriefParser.h - Dumb comment 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 a very simple Doxygen comment parser.
+//
+//===----------------------------------------------------------------------===//
+
+
+#ifndef LLVM_CLANG_AST_COMMENTBRIEFPARSER_H
+#define LLVM_CLANG_AST_COMMENTBRIEFPARSER_H
+
+#include "clang/AST/CommentLexer.h"
+
+namespace clang {
+namespace comments {
+
+/// A very simple comment parser that extracts "a brief description".
+///
+/// Due to a variety of comment styles, it considers the following as "a brief
+/// description", in order of priority:
+/// \li a \\brief or \\short command,
+/// \li the first paragraph,
+/// \li a \\result or \\return or \\returns paragraph.
+class BriefParser {
+ Lexer &L;
+
+ const CommandTraits &Traits;
+
+ /// Current lookahead token.
+ Token Tok;
+
+ SourceLocation ConsumeToken() {
+ SourceLocation Loc = Tok.getLocation();
+ L.lex(Tok);
+ return Loc;
+ }
+
+public:
+ BriefParser(Lexer &L, const CommandTraits &Traits);
+
+ /// Return the best "brief description" we can find.
+ std::string Parse();
+};
+
+} // end namespace comments
+} // end namespace clang
+
+#endif
+
diff --git a/contrib/llvm/tools/clang/include/clang/AST/CommentCommandTraits.h b/contrib/llvm/tools/clang/include/clang/AST/CommentCommandTraits.h
new file mode 100644
index 0000000..289f2fd
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/AST/CommentCommandTraits.h
@@ -0,0 +1,189 @@
+//===--- CommentCommandTraits.h - Comment command properties ----*- C++ -*-===//
+//
+// 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 class that provides information about comment
+// commands.
+//
+//===----------------------------------------------------------------------===//
+
+
+#ifndef LLVM_CLANG_AST_COMMENTCOMMANDTRAITS_H
+#define LLVM_CLANG_AST_COMMENTCOMMANDTRAITS_H
+
+#include "clang/Basic/CommentOptions.h"
+#include "clang/Basic/LLVM.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/Support/Allocator.h"
+#include "llvm/Support/ErrorHandling.h"
+
+namespace clang {
+namespace comments {
+
+/// \brief Information about a single command.
+///
+/// When reordering, adding or removing members please update the corresponding
+/// TableGen backend.
+struct CommandInfo {
+ unsigned getID() const {
+ return ID;
+ }
+
+ const char *Name;
+
+ /// Name of the command that ends the verbatim block.
+ const char *EndCommandName;
+
+ /// DRY definition of the number of bits used for a command ID.
+ enum { NumCommandIDBits = 20 };
+
+ /// The ID of the command.
+ unsigned ID : NumCommandIDBits;
+
+ /// Number of word-like arguments for a given block command, except for
+ /// \\param and \\tparam commands -- these have special argument parsers.
+ unsigned NumArgs : 4;
+
+ /// True if this command is a inline command (of any kind).
+ unsigned IsInlineCommand : 1;
+
+ /// True if this command is a block command (of any kind).
+ unsigned IsBlockCommand : 1;
+
+ /// True if this command is introducing a brief documentation
+ /// paragraph (\\brief or an alias).
+ unsigned IsBriefCommand : 1;
+
+ /// True if this command is \\returns or an alias.
+ unsigned IsReturnsCommand : 1;
+
+ /// True if this command is introducing documentation for a function
+ /// parameter (\\param or an alias).
+ unsigned IsParamCommand : 1;
+
+ /// True if this command is introducing documentation for
+ /// a template parameter (\\tparam or an alias).
+ unsigned IsTParamCommand : 1;
+
+ /// True if this command is \\throws or an alias.
+ unsigned IsThrowsCommand : 1;
+
+ /// True if this command is \\deprecated or an alias.
+ unsigned IsDeprecatedCommand : 1;
+
+ /// \brief True if this is a \\headerfile-like command.
+ unsigned IsHeaderfileCommand : 1;
+
+ /// True if we don't want to warn about this command being passed an empty
+ /// paragraph. Meaningful only for block commands.
+ unsigned IsEmptyParagraphAllowed : 1;
+
+ /// \brief True if this command is a verbatim-like block command.
+ ///
+ /// A verbatim-like block command eats every character (except line starting
+ /// decorations) until matching end command is seen or comment end is hit.
+ unsigned IsVerbatimBlockCommand : 1;
+
+ /// \brief True if this command is an end command for a verbatim-like block.
+ unsigned IsVerbatimBlockEndCommand : 1;
+
+ /// \brief True if this command is a verbatim line command.
+ ///
+ /// A verbatim-like line command eats everything until a newline is seen or
+ /// comment end is hit.
+ unsigned IsVerbatimLineCommand : 1;
+
+ /// \brief True if this command contains a declaration for the entity being
+ /// documented.
+ ///
+ /// For example:
+ /// \code
+ /// \fn void f(int a);
+ /// \endcode
+ unsigned IsDeclarationCommand : 1;
+
+ /// \brief True if verbatim-like line command is a function declaration.
+ unsigned IsFunctionDeclarationCommand : 1;
+
+ /// \brief True if block command is further describing a container API; such
+ /// as \@coclass, \@classdesign, etc.
+ unsigned IsRecordLikeDetailCommand : 1;
+
+ /// \brief True if block command is a container API; such as \@interface.
+ unsigned IsRecordLikeDeclarationCommand : 1;
+
+ /// \brief True if this command is unknown. This \c CommandInfo object was
+ /// created during parsing.
+ unsigned IsUnknownCommand : 1;
+};
+
+/// This class provides information about commands that can be used
+/// in comments.
+class CommandTraits {
+public:
+ enum KnownCommandIDs {
+#define COMMENT_COMMAND(NAME) KCI_##NAME,
+#include "clang/AST/CommentCommandList.inc"
+#undef COMMENT_COMMAND
+ KCI_Last
+ };
+
+ CommandTraits(llvm::BumpPtrAllocator &Allocator,
+ const CommentOptions &CommentOptions);
+
+ void registerCommentOptions(const CommentOptions &CommentOptions);
+
+ /// \returns a CommandInfo object for a given command name or
+ /// NULL if no CommandInfo object exists for this command.
+ const CommandInfo *getCommandInfoOrNULL(StringRef Name) const;
+
+ const CommandInfo *getCommandInfo(StringRef Name) const {
+ if (const CommandInfo *Info = getCommandInfoOrNULL(Name))
+ return Info;
+ llvm_unreachable("the command should be known");
+ }
+
+ const CommandInfo *getTypoCorrectCommandInfo(StringRef Typo) const;
+
+ const CommandInfo *getCommandInfo(unsigned CommandID) const;
+
+ const CommandInfo *registerUnknownCommand(StringRef CommandName);
+
+ const CommandInfo *registerBlockCommand(StringRef CommandName);
+
+ /// \returns a CommandInfo object for a given command name or
+ /// NULL if \c Name is not a builtin command.
+ static const CommandInfo *getBuiltinCommandInfo(StringRef Name);
+
+ /// \returns a CommandInfo object for a given command ID or
+ /// NULL if \c CommandID is not a builtin command.
+ static const CommandInfo *getBuiltinCommandInfo(unsigned CommandID);
+
+private:
+ CommandTraits(const CommandTraits &) = delete;
+ void operator=(const CommandTraits &) = delete;
+
+ const CommandInfo *getRegisteredCommandInfo(StringRef Name) const;
+ const CommandInfo *getRegisteredCommandInfo(unsigned CommandID) const;
+
+ CommandInfo *createCommandInfoWithName(StringRef CommandName);
+
+ unsigned NextID;
+
+ /// Allocator for CommandInfo objects.
+ llvm::BumpPtrAllocator &Allocator;
+
+ SmallVector<CommandInfo *, 4> RegisteredCommands;
+};
+
+} // end namespace comments
+} // end namespace clang
+
+#endif
+
diff --git a/contrib/llvm/tools/clang/include/clang/AST/CommentCommands.td b/contrib/llvm/tools/clang/include/clang/AST/CommentCommands.td
new file mode 100644
index 0000000..958ee03
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/AST/CommentCommands.td
@@ -0,0 +1,241 @@
+//===----------------------------------------------------------------------===//
+// Define command classes.
+//===----------------------------------------------------------------------===//
+
+class Command<string name> {
+ string Name = name;
+ string EndCommandName = "";
+
+ int NumArgs = 0;
+
+ bit IsInlineCommand = 0;
+
+ bit IsBlockCommand = 0;
+ bit IsBriefCommand = 0;
+ bit IsReturnsCommand = 0;
+ bit IsParamCommand = 0;
+ bit IsTParamCommand = 0;
+ bit IsThrowsCommand = 0;
+ bit IsDeprecatedCommand = 0;
+ bit IsHeaderfileCommand = 0;
+
+ bit IsEmptyParagraphAllowed = 0;
+
+ bit IsVerbatimBlockCommand = 0;
+ bit IsVerbatimBlockEndCommand = 0;
+ bit IsVerbatimLineCommand = 0;
+ bit IsDeclarationCommand = 0;
+ bit IsFunctionDeclarationCommand = 0;
+ bit IsRecordLikeDetailCommand = 0;
+ bit IsRecordLikeDeclarationCommand = 0;
+}
+
+class InlineCommand<string name> : Command<name> {
+ let IsInlineCommand = 1;
+}
+
+class BlockCommand<string name> : Command<name> {
+ let IsBlockCommand = 1;
+}
+
+class RecordLikeDetailCommand<string name> : BlockCommand<name> {
+ let IsRecordLikeDetailCommand = 1;
+}
+
+class VerbatimBlockCommand<string name> : Command<name> {
+ let EndCommandName = name;
+ let IsVerbatimBlockCommand = 1;
+}
+
+multiclass VerbatimBlockCommand<string name, string endCommandName> {
+ def Begin : Command<name> {
+ let EndCommandName = endCommandName;
+ let IsVerbatimBlockCommand = 1;
+ }
+
+ def End : Command<endCommandName> {
+ let IsVerbatimBlockEndCommand = 1;
+ }
+}
+
+class VerbatimLineCommand<string name> : Command<name> {
+ let IsVerbatimLineCommand = 1;
+}
+
+class DeclarationVerbatimLineCommand<string name> :
+ VerbatimLineCommand<name> {
+ let IsDeclarationCommand = 1;
+}
+
+class FunctionDeclarationVerbatimLineCommand<string name> :
+ DeclarationVerbatimLineCommand<name> {
+ let IsFunctionDeclarationCommand = 1;
+}
+
+class RecordLikeDeclarationVerbatimLineCommand<string name> :
+ DeclarationVerbatimLineCommand<name> {
+ let IsRecordLikeDeclarationCommand = 1;
+}
+
+//===----------------------------------------------------------------------===//
+// InlineCommand
+//===----------------------------------------------------------------------===//
+
+def B : InlineCommand<"b">;
+def C : InlineCommand<"c">;
+def P : InlineCommand<"p">;
+def A : InlineCommand<"a">;
+def E : InlineCommand<"e">;
+def Em : InlineCommand<"em">;
+
+//===----------------------------------------------------------------------===//
+// BlockCommand
+//===----------------------------------------------------------------------===//
+
+def Brief : BlockCommand<"brief"> { let IsBriefCommand = 1; }
+def Short : BlockCommand<"short"> { let IsBriefCommand = 1; }
+
+// Opposite of \brief, it is the default in our implementation.
+def Details : BlockCommand<"details">;
+
+def Returns : BlockCommand<"returns"> { let IsReturnsCommand = 1; }
+def Return : BlockCommand<"return"> { let IsReturnsCommand = 1; }
+def Result : BlockCommand<"result"> { let IsReturnsCommand = 1; }
+
+def Param : BlockCommand<"param"> { let IsParamCommand = 1; }
+
+// Doxygen command for template parameter documentation.
+def Tparam : BlockCommand<"tparam"> { let IsTParamCommand = 1; }
+
+// HeaderDoc command for template parameter documentation.
+def Templatefield : BlockCommand<"templatefield"> { let IsTParamCommand = 1; }
+
+def Throws : BlockCommand<"throws"> { let IsThrowsCommand = 1; }
+def Throw : BlockCommand<"throw"> { let IsThrowsCommand = 1; }
+def Exception : BlockCommand<"exception"> { let IsThrowsCommand = 1; }
+
+def Deprecated : BlockCommand<"deprecated"> {
+ let IsEmptyParagraphAllowed = 1;
+ let IsDeprecatedCommand = 1;
+}
+
+def Headerfile : BlockCommand<"headerfile"> { let IsHeaderfileCommand = 1; }
+
+// We don't do any additional semantic analysis for the following
+// BlockCommands. It might be a good idea to do something extra for them, but
+// for now we model them as plain BlockCommands.
+def Arg : BlockCommand<"arg">;
+def Attention : BlockCommand<"attention">;
+def Author : BlockCommand<"author">;
+def Authors : BlockCommand<"authors">;
+def Bug : BlockCommand<"bug">;
+def Copyright : BlockCommand<"copyright">;
+def Date : BlockCommand<"date">;
+def Invariant : BlockCommand<"invariant">;
+def Li : BlockCommand<"li">;
+def Note : BlockCommand<"note">;
+def Par : BlockCommand<"par">;
+def Post : BlockCommand<"post">;
+def Pre : BlockCommand<"pre">;
+def Remark : BlockCommand<"remark">;
+def Remarks : BlockCommand<"remarks">;
+def Sa : BlockCommand<"sa">;
+def See : BlockCommand<"see">;
+def Since : BlockCommand<"since">;
+def Todo : BlockCommand<"todo">;
+def Version : BlockCommand<"version">;
+def Warning : BlockCommand<"warning">;
+// HeaderDoc commands
+def Abstract : BlockCommand<"abstract"> { let IsBriefCommand = 1; }
+def ClassDesign : RecordLikeDetailCommand<"classdesign">;
+def CoClass : RecordLikeDetailCommand<"coclass">;
+def Dependency : RecordLikeDetailCommand<"dependency">;
+def Discussion : BlockCommand<"discussion">;
+def Helper : RecordLikeDetailCommand<"helper">;
+def HelperClass : RecordLikeDetailCommand<"helperclass">;
+def Helps : RecordLikeDetailCommand<"helps">;
+def InstanceSize : RecordLikeDetailCommand<"instancesize">;
+def Ownership : RecordLikeDetailCommand<"ownership">;
+def Performance : RecordLikeDetailCommand<"performance">;
+def Security : RecordLikeDetailCommand<"security">;
+def SeeAlso : BlockCommand<"seealso">;
+def SuperClass : RecordLikeDetailCommand<"superclass">;
+
+//===----------------------------------------------------------------------===//
+// VerbatimBlockCommand
+//===----------------------------------------------------------------------===//
+
+defm Code : VerbatimBlockCommand<"code", "endcode">;
+defm Verbatim : VerbatimBlockCommand<"verbatim", "endverbatim">;
+defm Htmlonly : VerbatimBlockCommand<"htmlonly", "endhtmlonly">;
+defm Latexonly : VerbatimBlockCommand<"latexonly", "endlatexonly">;
+defm Xmlonly : VerbatimBlockCommand<"xmlonly", "endxmlonly">;
+defm Manonly : VerbatimBlockCommand<"manonly", "endmanonly">;
+defm Rtfonly : VerbatimBlockCommand<"rtfonly", "endrtfonly">;
+
+defm Dot : VerbatimBlockCommand<"dot", "enddot">;
+defm Msc : VerbatimBlockCommand<"msc", "endmsc">;
+
+// These three commands have special support in CommentLexer to recognize their
+// names.
+def FDollar : VerbatimBlockCommand<"f$">; // Inline LaTeX formula
+defm FBracket : VerbatimBlockCommand<"f[", "f]">; // Displayed LaTeX formula
+defm FBrace : VerbatimBlockCommand<"f{", "f}">; // LaTeX environment
+
+// HeaderDoc commands
+defm Textblock : VerbatimBlockCommand<"textblock", "/textblock">;
+defm Link : VerbatimBlockCommand<"link", "/link">;
+
+//===----------------------------------------------------------------------===//
+// VerbatimLineCommand
+//===----------------------------------------------------------------------===//
+
+def Defgroup : VerbatimLineCommand<"defgroup">;
+def Ingroup : VerbatimLineCommand<"ingroup">;
+def Addtogroup : VerbatimLineCommand<"addtogroup">;
+def Weakgroup : VerbatimLineCommand<"weakgroup">;
+def Name : VerbatimLineCommand<"name">;
+
+def Section : VerbatimLineCommand<"section">;
+def Subsection : VerbatimLineCommand<"subsection">;
+def Subsubsection : VerbatimLineCommand<"subsubsection">;
+def Paragraph : VerbatimLineCommand<"paragraph">;
+
+def Mainpage : VerbatimLineCommand<"mainpage">;
+def Subpage : VerbatimLineCommand<"subpage">;
+def Ref : VerbatimLineCommand<"ref">;
+
+def Relates : VerbatimLineCommand<"relates">;
+def Related : VerbatimLineCommand<"related">;
+def RelatesAlso : VerbatimLineCommand<"relatesalso">;
+def RelatedAlso : VerbatimLineCommand<"relatedalso">;
+
+//===----------------------------------------------------------------------===//
+// DeclarationVerbatimLineCommand
+//===----------------------------------------------------------------------===//
+
+// Doxygen commands.
+def Def : DeclarationVerbatimLineCommand<"def">;
+def Fn : DeclarationVerbatimLineCommand<"fn">;
+def Namespace : DeclarationVerbatimLineCommand<"namespace">;
+def Overload : DeclarationVerbatimLineCommand<"overload">;
+def Property : DeclarationVerbatimLineCommand<"property">;
+def Typedef : DeclarationVerbatimLineCommand<"typedef">;
+def Var : DeclarationVerbatimLineCommand<"var">;
+
+// HeaderDoc commands.
+def Class : RecordLikeDeclarationVerbatimLineCommand<"class">;
+def Interface : RecordLikeDeclarationVerbatimLineCommand<"interface">;
+def Protocol : RecordLikeDeclarationVerbatimLineCommand<"protocol">;
+def Struct : RecordLikeDeclarationVerbatimLineCommand<"struct">;
+def Union : RecordLikeDeclarationVerbatimLineCommand<"union">;
+def Category : DeclarationVerbatimLineCommand<"category">;
+def Template : DeclarationVerbatimLineCommand<"template">;
+def Function : FunctionDeclarationVerbatimLineCommand<"function">;
+def FunctionGroup : FunctionDeclarationVerbatimLineCommand<"functiongroup">;
+def Method : FunctionDeclarationVerbatimLineCommand<"method">;
+def MethodGroup : FunctionDeclarationVerbatimLineCommand<"methodgroup">;
+def Callback : FunctionDeclarationVerbatimLineCommand<"callback">;
+def Const : DeclarationVerbatimLineCommand<"const">;
+def Constant : DeclarationVerbatimLineCommand<"constant">;
+def Enum : DeclarationVerbatimLineCommand<"enum">;
diff --git a/contrib/llvm/tools/clang/include/clang/AST/CommentDiagnostic.h b/contrib/llvm/tools/clang/include/clang/AST/CommentDiagnostic.h
new file mode 100644
index 0000000..f3a209b
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/AST/CommentDiagnostic.h
@@ -0,0 +1,29 @@
+//===--- CommentDiagnostic.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_AST_COMMENTDIAGNOSTIC_H
+#define LLVM_CLANG_AST_COMMENTDIAGNOSTIC_H
+
+#include "clang/Basic/Diagnostic.h"
+
+namespace clang {
+ namespace diag {
+ enum {
+#define DIAG(ENUM,FLAGS,DEFAULT_MAPPING,DESC,GROUP,\
+ SFINAE,NOWERROR,SHOWINSYSHEADER,CATEGORY) ENUM,
+#define COMMENTSTART
+#include "clang/Basic/DiagnosticCommentKinds.inc"
+#undef DIAG
+ NUM_BUILTIN_COMMENT_DIAGNOSTICS
+ };
+ } // end namespace diag
+} // end namespace clang
+
+#endif
+
diff --git a/contrib/llvm/tools/clang/include/clang/AST/CommentHTMLNamedCharacterReferences.td b/contrib/llvm/tools/clang/include/clang/AST/CommentHTMLNamedCharacterReferences.td
new file mode 100644
index 0000000..4493108
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/AST/CommentHTMLNamedCharacterReferences.td
@@ -0,0 +1,177 @@
+// HTML Named Character Reference
+class NCR<string spelling, int codePoint> {
+ string Spelling = spelling;
+ int CodePoint = codePoint;
+}
+
+// The list below includes named character references supported by Doxygen:
+// http://www.stack.nl/~dimitri/doxygen/manual/htmlcmds.html
+//
+// It does not include all HTML 5 named character references.
+//
+// Corresponding code point values can be found here:
+// http://www.w3.org/TR/2011/WD-html5-20110113/named-character-references.html
+
+def : NCR<"copy", 0x000A9>;
+def : NCR<"COPY", 0x000A9>;
+def : NCR<"trade", 0x02122>;
+def : NCR<"TRADE", 0x02122>;
+def : NCR<"reg", 0x000AE>;
+def : NCR<"REG", 0x000AE>;
+def : NCR<"lt", 0x0003C>;
+def : NCR<"Lt", 0x0003C>;
+def : NCR<"LT", 0x0003C>;
+def : NCR<"gt", 0x0003E>;
+def : NCR<"Gt", 0x0003E>;
+def : NCR<"GT", 0x0003E>;
+def : NCR<"amp", 0x00026>;
+def : NCR<"AMP", 0x00026>;
+def : NCR<"apos", 0x00027>;
+def : NCR<"quot", 0x00022>;
+def : NCR<"QUOT", 0x00022>;
+def : NCR<"lsquo", 0x02018>;
+def : NCR<"rsquo", 0x02019>;
+def : NCR<"ldquo", 0x0201C>;
+def : NCR<"rdquo", 0x0201D>;
+def : NCR<"ndash", 0x02013>;
+def : NCR<"mdash", 0x02014>;
+
+def : NCR<"Auml", 0x000C4>;
+def : NCR<"Euml", 0x000CB>;
+def : NCR<"Iuml", 0x000CF>;
+def : NCR<"Ouml", 0x000D6>;
+def : NCR<"Uuml", 0x000DC>;
+def : NCR<"Yuml", 0x00178>;
+def : NCR<"auml", 0x000E4>;
+def : NCR<"euml", 0x000EB>;
+def : NCR<"iuml", 0x000EF>;
+def : NCR<"ouml", 0x000F6>;
+def : NCR<"uuml", 0x000FC>;
+def : NCR<"yuml", 0x000FF>;
+
+def : NCR<"Aacute", 0x000C1>;
+def : NCR<"Eacute", 0x000C9>;
+def : NCR<"Iacute", 0x000CD>;
+def : NCR<"Oacute", 0x000D3>;
+def : NCR<"Uacute", 0x000DA>;
+def : NCR<"Yacute", 0x000DD>;
+def : NCR<"aacute", 0x000E1>;
+def : NCR<"eacute", 0x000E9>;
+def : NCR<"iacute", 0x000ED>;
+def : NCR<"oacute", 0x000F3>;
+def : NCR<"uacute", 0x000FA>;
+def : NCR<"yacute", 0x000FD>;
+
+def : NCR<"Agrave", 0x000C0>;
+def : NCR<"Egrave", 0x000C8>;
+def : NCR<"Igrave", 0x000CC>;
+def : NCR<"Ograve", 0x000D2>;
+def : NCR<"Ugrave", 0x000D9>;
+// def : NCR<"Ygrave", 0x01EF2>; // Defined neither in Doxygen, nor in HTML5.
+def : NCR<"agrave", 0x000E0>;
+def : NCR<"egrave", 0x000E8>;
+def : NCR<"igrave", 0x000EC>;
+def : NCR<"ograve", 0x000F2>;
+def : NCR<"ugrave", 0x000F9>;
+def : NCR<"ygrave", 0x01EF3>; // Defined in Doxygen, not defined in HTML5.
+
+def : NCR<"Acirc", 0x000C2>;
+def : NCR<"Ecirc", 0x000CA>;
+def : NCR<"Icirc", 0x000CE>;
+def : NCR<"Ocirc", 0x000D4>;
+def : NCR<"Ucirc", 0x000DB>;
+def : NCR<"Ycirc", 0x00176>; // Not defined in Doxygen, defined in HTML5.
+def : NCR<"acirc", 0x000E2>;
+def : NCR<"ecirc", 0x000EA>;
+def : NCR<"icirc", 0x000EE>;
+def : NCR<"ocirc", 0x000F4>;
+def : NCR<"ucirc", 0x000FB>;
+def : NCR<"ycirc", 0x00177>;
+
+def : NCR<"Atilde", 0x000C3>;
+def : NCR<"Ntilde", 0x000D1>;
+def : NCR<"Otilde", 0x000D5>;
+def : NCR<"atilde", 0x000E3>;
+def : NCR<"ntilde", 0x000F1>;
+def : NCR<"otilde", 0x000F5>;
+
+def : NCR<"szlig", 0x000DF>;
+
+def : NCR<"ccedil", 0x000E7>;
+def : NCR<"Ccedil", 0x000C7>;
+
+def : NCR<"aring", 0x000E5>;
+def : NCR<"Aring", 0x000C5>;
+
+def : NCR<"nbsp", 0x000A0>;
+
+def : NCR<"Gamma", 0x00393>;
+def : NCR<"Delta", 0x00394>;
+def : NCR<"Theta", 0x00398>;
+def : NCR<"Lambda", 0x0039B>;
+def : NCR<"Xi", 0x0039E>;
+def : NCR<"Pi", 0x003A0>;
+def : NCR<"Sigma", 0x003A3>;
+def : NCR<"Upsilon", 0x003A5>;
+def : NCR<"Phi", 0x003A6>;
+def : NCR<"Psi", 0x003A8>;
+def : NCR<"Omega", 0x003A9>;
+
+def : NCR<"alpha", 0x003B1>;
+def : NCR<"beta", 0x003B2>;
+def : NCR<"gamma", 0x003B3>;
+def : NCR<"delta", 0x003B4>;
+def : NCR<"epsilon", 0x003B5>;
+def : NCR<"zeta", 0x003B6>;
+def : NCR<"eta", 0x003B7>;
+def : NCR<"theta", 0x003B8>;
+def : NCR<"iota", 0x003B9>;
+def : NCR<"kappa", 0x003BA>;
+def : NCR<"lambda", 0x003BB>;
+def : NCR<"mu", 0x003BC>;
+def : NCR<"nu", 0x003BD>;
+def : NCR<"xi", 0x003BE>;
+def : NCR<"pi", 0x003C0>;
+def : NCR<"rho", 0x003C1>;
+def : NCR<"sigma", 0x003C3>;
+def : NCR<"tau", 0x003C4>;
+def : NCR<"upsilon", 0x003C5>;
+def : NCR<"phi", 0x003C6>;
+def : NCR<"chi", 0x003C7>;
+def : NCR<"psi", 0x003C8>;
+def : NCR<"omega", 0x003C9>;
+def : NCR<"sigmaf", 0x003C2>;
+
+def : NCR<"sect", 0x000A7>;
+def : NCR<"deg", 0x000B0>;
+def : NCR<"prime", 0x02032>;
+def : NCR<"Prime", 0x02033>;
+def : NCR<"infin", 0x0221E>;
+def : NCR<"empty", 0x02205>;
+def : NCR<"plusmn", 0x000B1>;
+def : NCR<"times", 0x000D7>;
+def : NCR<"minus", 0x02212>;
+def : NCR<"sdot", 0x022C5>;
+def : NCR<"part", 0x02202>;
+def : NCR<"nabla", 0x02207>;
+def : NCR<"radic", 0x0221A>;
+def : NCR<"perp", 0x022A5>;
+def : NCR<"sum", 0x02211>;
+def : NCR<"int", 0x0222B>;
+def : NCR<"prod", 0x0220F>;
+def : NCR<"sim", 0x0223C>;
+def : NCR<"asymp", 0x02248>;
+def : NCR<"ne", 0x02260>;
+def : NCR<"equiv", 0x02261>;
+def : NCR<"prop", 0x0221D>;
+def : NCR<"le", 0x02264>;
+def : NCR<"ge", 0x02265>;
+def : NCR<"larr", 0x02190>;
+def : NCR<"rarr", 0x02192>;
+def : NCR<"isin", 0x02208>;
+def : NCR<"notin", 0x02209>;
+def : NCR<"lceil", 0x02308>;
+def : NCR<"rceil", 0x02309>;
+def : NCR<"lfloor", 0x0230A>;
+def : NCR<"rfloor", 0x0230B>;
+
diff --git a/contrib/llvm/tools/clang/include/clang/AST/CommentHTMLTags.td b/contrib/llvm/tools/clang/include/clang/AST/CommentHTMLTags.td
new file mode 100644
index 0000000..2514900
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/AST/CommentHTMLTags.td
@@ -0,0 +1,67 @@
+class Tag<string spelling> {
+ string Spelling = spelling;
+ bit EndTagOptional = 0;
+ bit EndTagForbidden = 0;
+}
+
+def Em : Tag<"em">;
+def Strong : Tag<"strong">;
+def Tt : Tag<"tt">;
+def I : Tag<"i">;
+def B : Tag<"b">;
+def Big : Tag<"big">;
+def Small : Tag<"small">;
+def Strike : Tag<"strike">;
+def S : Tag<"s">;
+def U : Tag<"u">;
+def Font : Tag<"font">;
+def A : Tag<"a">;
+def Hr : Tag<"hr"> { let EndTagForbidden = 1; }
+def Div : Tag<"div">;
+def Span : Tag<"span">;
+def H1 : Tag<"h1">;
+def H2 : Tag<"h2">;
+def H3 : Tag<"h3">;
+def H4 : Tag<"h4">;
+def H5 : Tag<"h5">;
+def H6 : Tag<"h6">;
+def Code : Tag<"code">;
+def Blockquote : Tag<"blockquote">;
+def Sub : Tag<"sub">;
+def Sup : Tag<"sup">;
+def Img : Tag<"img"> { let EndTagForbidden = 1; }
+def P : Tag<"p"> { let EndTagOptional = 1; }
+def Br : Tag<"br"> { let EndTagForbidden = 1; }
+def Pre : Tag<"pre">;
+def Ins : Tag<"ins">;
+def Del : Tag<"del">;
+def Ul : Tag<"ul">;
+def Ol : Tag<"ol">;
+def Li : Tag<"li"> { let EndTagOptional = 1; }
+def Dl : Tag<"dl">;
+def Dt : Tag<"dt"> { let EndTagOptional = 1; }
+def Dd : Tag<"dd"> { let EndTagOptional = 1; }
+def Table : Tag<"table">;
+def Caption : Tag<"caption">;
+def Thead : Tag<"thead"> { let EndTagOptional = 1; }
+def Tfoot : Tag<"tfoot"> { let EndTagOptional = 1; }
+def Tbody : Tag<"tbody"> { let EndTagOptional = 1; }
+def Colgroup : Tag<"colgroup"> { let EndTagOptional = 1; }
+def Col : Tag<"col"> { let EndTagForbidden = 1; }
+def Tr : Tag<"tr"> { let EndTagOptional = 1; }
+def Th : Tag<"th"> { let EndTagOptional = 1; }
+def Td : Tag<"td"> { let EndTagOptional = 1; }
+
+// Define a blacklist of attributes that are not safe to pass through to HTML
+// output if the input is untrusted.
+//
+// FIXME: this should be a whitelist. When changing this to a whitelist, don't
+// forget to change the default in the TableGen backend.
+class Attribute<string spelling> {
+ string Spelling = spelling;
+ bit IsSafeToPassThrough = 1;
+}
+class EventHandlerContentAttribute<string spelling> : Attribute<spelling> {
+ let IsSafeToPassThrough = 0;
+}
+
diff --git a/contrib/llvm/tools/clang/include/clang/AST/CommentLexer.h b/contrib/llvm/tools/clang/include/clang/AST/CommentLexer.h
new file mode 100644
index 0000000..f190b93
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/AST/CommentLexer.h
@@ -0,0 +1,362 @@
+//===--- CommentLexer.h - Lexer for structured comments ---------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines lexer for structured comments and supporting token class.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_AST_COMMENTLEXER_H
+#define LLVM_CLANG_AST_COMMENTLEXER_H
+
+#include "clang/Basic/Diagnostic.h"
+#include "clang/Basic/SourceManager.h"
+#include "llvm/ADT/SmallString.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/Support/Allocator.h"
+#include "llvm/Support/raw_ostream.h"
+
+namespace clang {
+namespace comments {
+
+class Lexer;
+class TextTokenRetokenizer;
+struct CommandInfo;
+class CommandTraits;
+
+namespace tok {
+enum TokenKind {
+ eof,
+ newline,
+ text,
+ unknown_command, // Command that does not have an ID.
+ backslash_command, // Command with an ID, that used backslash marker.
+ at_command, // Command with an ID, that used 'at' marker.
+ verbatim_block_begin,
+ verbatim_block_line,
+ verbatim_block_end,
+ verbatim_line_name,
+ verbatim_line_text,
+ html_start_tag, // <tag
+ html_ident, // attr
+ html_equals, // =
+ html_quoted_string, // "blah\"blah" or 'blah\'blah'
+ html_greater, // >
+ html_slash_greater, // />
+ html_end_tag // </tag
+};
+} // end namespace tok
+
+/// \brief Comment token.
+class Token {
+ friend class Lexer;
+ friend class TextTokenRetokenizer;
+
+ /// The location of the token.
+ SourceLocation Loc;
+
+ /// The actual kind of the token.
+ tok::TokenKind Kind;
+
+ /// Length of the token spelling in comment. Can be 0 for synthenized
+ /// tokens.
+ unsigned Length;
+
+ /// Contains text value associated with a token.
+ const char *TextPtr;
+
+ /// Integer value associated with a token.
+ ///
+ /// If the token is a konwn command, contains command ID and TextPtr is
+ /// unused (command spelling can be found with CommandTraits). Otherwise,
+ /// contains the length of the string that starts at TextPtr.
+ unsigned IntVal;
+
+public:
+ SourceLocation getLocation() const LLVM_READONLY { return Loc; }
+ void setLocation(SourceLocation SL) { Loc = SL; }
+
+ SourceLocation getEndLocation() const LLVM_READONLY {
+ if (Length == 0 || Length == 1)
+ return Loc;
+ return Loc.getLocWithOffset(Length - 1);
+ }
+
+ tok::TokenKind getKind() const LLVM_READONLY { return Kind; }
+ void setKind(tok::TokenKind K) { Kind = K; }
+
+ bool is(tok::TokenKind K) const LLVM_READONLY { return Kind == K; }
+ bool isNot(tok::TokenKind K) const LLVM_READONLY { return Kind != K; }
+
+ unsigned getLength() const LLVM_READONLY { return Length; }
+ void setLength(unsigned L) { Length = L; }
+
+ StringRef getText() const LLVM_READONLY {
+ assert(is(tok::text));
+ return StringRef(TextPtr, IntVal);
+ }
+
+ void setText(StringRef Text) {
+ assert(is(tok::text));
+ TextPtr = Text.data();
+ IntVal = Text.size();
+ }
+
+ StringRef getUnknownCommandName() const LLVM_READONLY {
+ assert(is(tok::unknown_command));
+ return StringRef(TextPtr, IntVal);
+ }
+
+ void setUnknownCommandName(StringRef Name) {
+ assert(is(tok::unknown_command));
+ TextPtr = Name.data();
+ IntVal = Name.size();
+ }
+
+ unsigned getCommandID() const LLVM_READONLY {
+ assert(is(tok::backslash_command) || is(tok::at_command));
+ return IntVal;
+ }
+
+ void setCommandID(unsigned ID) {
+ assert(is(tok::backslash_command) || is(tok::at_command));
+ IntVal = ID;
+ }
+
+ unsigned getVerbatimBlockID() const LLVM_READONLY {
+ assert(is(tok::verbatim_block_begin) || is(tok::verbatim_block_end));
+ return IntVal;
+ }
+
+ void setVerbatimBlockID(unsigned ID) {
+ assert(is(tok::verbatim_block_begin) || is(tok::verbatim_block_end));
+ IntVal = ID;
+ }
+
+ StringRef getVerbatimBlockText() const LLVM_READONLY {
+ assert(is(tok::verbatim_block_line));
+ return StringRef(TextPtr, IntVal);
+ }
+
+ void setVerbatimBlockText(StringRef Text) {
+ assert(is(tok::verbatim_block_line));
+ TextPtr = Text.data();
+ IntVal = Text.size();
+ }
+
+ unsigned getVerbatimLineID() const LLVM_READONLY {
+ assert(is(tok::verbatim_line_name));
+ return IntVal;
+ }
+
+ void setVerbatimLineID(unsigned ID) {
+ assert(is(tok::verbatim_line_name));
+ IntVal = ID;
+ }
+
+ StringRef getVerbatimLineText() const LLVM_READONLY {
+ assert(is(tok::verbatim_line_text));
+ return StringRef(TextPtr, IntVal);
+ }
+
+ void setVerbatimLineText(StringRef Text) {
+ assert(is(tok::verbatim_line_text));
+ TextPtr = Text.data();
+ IntVal = Text.size();
+ }
+
+ StringRef getHTMLTagStartName() const LLVM_READONLY {
+ assert(is(tok::html_start_tag));
+ return StringRef(TextPtr, IntVal);
+ }
+
+ void setHTMLTagStartName(StringRef Name) {
+ assert(is(tok::html_start_tag));
+ TextPtr = Name.data();
+ IntVal = Name.size();
+ }
+
+ StringRef getHTMLIdent() const LLVM_READONLY {
+ assert(is(tok::html_ident));
+ return StringRef(TextPtr, IntVal);
+ }
+
+ void setHTMLIdent(StringRef Name) {
+ assert(is(tok::html_ident));
+ TextPtr = Name.data();
+ IntVal = Name.size();
+ }
+
+ StringRef getHTMLQuotedString() const LLVM_READONLY {
+ assert(is(tok::html_quoted_string));
+ return StringRef(TextPtr, IntVal);
+ }
+
+ void setHTMLQuotedString(StringRef Str) {
+ assert(is(tok::html_quoted_string));
+ TextPtr = Str.data();
+ IntVal = Str.size();
+ }
+
+ StringRef getHTMLTagEndName() const LLVM_READONLY {
+ assert(is(tok::html_end_tag));
+ return StringRef(TextPtr, IntVal);
+ }
+
+ void setHTMLTagEndName(StringRef Name) {
+ assert(is(tok::html_end_tag));
+ TextPtr = Name.data();
+ IntVal = Name.size();
+ }
+
+ void dump(const Lexer &L, const SourceManager &SM) const;
+};
+
+/// \brief Comment lexer.
+class Lexer {
+private:
+ Lexer(const Lexer &) = delete;
+ void operator=(const Lexer &) = delete;
+
+ /// Allocator for strings that are semantic values of tokens and have to be
+ /// computed (for example, resolved decimal character references).
+ llvm::BumpPtrAllocator &Allocator;
+
+ DiagnosticsEngine &Diags;
+
+ const CommandTraits &Traits;
+
+ const char *const BufferStart;
+ const char *const BufferEnd;
+ SourceLocation FileLoc;
+
+ const char *BufferPtr;
+
+ /// One past end pointer for the current comment. For BCPL comments points
+ /// to newline or BufferEnd, for C comments points to star in '*/'.
+ const char *CommentEnd;
+
+ enum LexerCommentState {
+ LCS_BeforeComment,
+ LCS_InsideBCPLComment,
+ LCS_InsideCComment,
+ LCS_BetweenComments
+ };
+
+ /// Low-level lexer state, track if we are inside or outside of comment.
+ LexerCommentState CommentState;
+
+ enum LexerState {
+ /// Lexing normal comment text
+ LS_Normal,
+
+ /// Finished lexing verbatim block beginning command, will lex first body
+ /// line.
+ LS_VerbatimBlockFirstLine,
+
+ /// Lexing verbatim block body line-by-line, skipping line-starting
+ /// decorations.
+ LS_VerbatimBlockBody,
+
+ /// Finished lexing verbatim line beginning command, will lex text (one
+ /// line).
+ LS_VerbatimLineText,
+
+ /// Finished lexing \verbatim <TAG \endverbatim part, lexing tag attributes.
+ LS_HTMLStartTag,
+
+ /// Finished lexing \verbatim </TAG \endverbatim part, lexing '>'.
+ LS_HTMLEndTag
+ };
+
+ /// Current lexing mode.
+ LexerState State;
+
+ /// If State is LS_VerbatimBlock, contains the name of verbatim end
+ /// command, including command marker.
+ SmallString<16> VerbatimBlockEndCommandName;
+
+ /// Given a character reference name (e.g., "lt"), return the character that
+ /// it stands for (e.g., "<").
+ StringRef resolveHTMLNamedCharacterReference(StringRef Name) const;
+
+ /// Given a Unicode codepoint as base-10 integer, return the character.
+ StringRef resolveHTMLDecimalCharacterReference(StringRef Name) const;
+
+ /// Given a Unicode codepoint as base-16 integer, return the character.
+ StringRef resolveHTMLHexCharacterReference(StringRef Name) const;
+
+ void formTokenWithChars(Token &Result, const char *TokEnd,
+ tok::TokenKind Kind);
+
+ void formTextToken(Token &Result, const char *TokEnd) {
+ StringRef Text(BufferPtr, TokEnd - BufferPtr);
+ formTokenWithChars(Result, TokEnd, tok::text);
+ Result.setText(Text);
+ }
+
+ SourceLocation getSourceLocation(const char *Loc) const {
+ assert(Loc >= BufferStart && Loc <= BufferEnd &&
+ "Location out of range for this buffer!");
+
+ const unsigned CharNo = Loc - BufferStart;
+ return FileLoc.getLocWithOffset(CharNo);
+ }
+
+ DiagnosticBuilder Diag(SourceLocation Loc, unsigned DiagID) {
+ return Diags.Report(Loc, DiagID);
+ }
+
+ /// Eat string matching regexp \code \s*\* \endcode.
+ void skipLineStartingDecorations();
+
+ /// Lex stuff inside comments. CommentEnd should be set correctly.
+ void lexCommentText(Token &T);
+
+ void setupAndLexVerbatimBlock(Token &T,
+ const char *TextBegin,
+ char Marker, const CommandInfo *Info);
+
+ void lexVerbatimBlockFirstLine(Token &T);
+
+ void lexVerbatimBlockBody(Token &T);
+
+ void setupAndLexVerbatimLine(Token &T, const char *TextBegin,
+ const CommandInfo *Info);
+
+ void lexVerbatimLineText(Token &T);
+
+ void lexHTMLCharacterReference(Token &T);
+
+ void setupAndLexHTMLStartTag(Token &T);
+
+ void lexHTMLStartTag(Token &T);
+
+ void setupAndLexHTMLEndTag(Token &T);
+
+ void lexHTMLEndTag(Token &T);
+
+public:
+ Lexer(llvm::BumpPtrAllocator &Allocator, DiagnosticsEngine &Diags,
+ const CommandTraits &Traits,
+ SourceLocation FileLoc,
+ const char *BufferStart, const char *BufferEnd);
+
+ void lex(Token &T);
+
+ StringRef getSpelling(const Token &Tok,
+ const SourceManager &SourceMgr,
+ bool *Invalid = nullptr) const;
+};
+
+} // end namespace comments
+} // end namespace clang
+
+#endif
+
diff --git a/contrib/llvm/tools/clang/include/clang/AST/CommentParser.h b/contrib/llvm/tools/clang/include/clang/AST/CommentParser.h
new file mode 100644
index 0000000..fa88628
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/AST/CommentParser.h
@@ -0,0 +1,123 @@
+//===--- CommentParser.h - Doxygen comment 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 Doxygen comment parser.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_AST_COMMENTPARSER_H
+#define LLVM_CLANG_AST_COMMENTPARSER_H
+
+#include "clang/AST/Comment.h"
+#include "clang/AST/CommentLexer.h"
+#include "clang/AST/CommentSema.h"
+#include "clang/Basic/Diagnostic.h"
+#include "llvm/Support/Allocator.h"
+
+namespace clang {
+class SourceManager;
+
+namespace comments {
+class CommandTraits;
+
+/// Doxygen comment parser.
+class Parser {
+ Parser(const Parser &) = delete;
+ void operator=(const Parser &) = delete;
+
+ friend class TextTokenRetokenizer;
+
+ Lexer &L;
+
+ Sema &S;
+
+ /// Allocator for anything that goes into AST nodes.
+ llvm::BumpPtrAllocator &Allocator;
+
+ /// Source manager for the comment being parsed.
+ const SourceManager &SourceMgr;
+
+ DiagnosticsEngine &Diags;
+
+ DiagnosticBuilder Diag(SourceLocation Loc, unsigned DiagID) {
+ return Diags.Report(Loc, DiagID);
+ }
+
+ const CommandTraits &Traits;
+
+ /// Current lookahead token. We can safely assume that all tokens are from
+ /// a single source file.
+ Token Tok;
+
+ /// A stack of additional lookahead tokens.
+ SmallVector<Token, 8> MoreLATokens;
+
+ void consumeToken() {
+ if (MoreLATokens.empty())
+ L.lex(Tok);
+ else
+ Tok = MoreLATokens.pop_back_val();
+ }
+
+ void putBack(const Token &OldTok) {
+ MoreLATokens.push_back(Tok);
+ Tok = OldTok;
+ }
+
+ void putBack(ArrayRef<Token> Toks) {
+ if (Toks.empty())
+ return;
+
+ MoreLATokens.push_back(Tok);
+ MoreLATokens.append(Toks.rbegin(), std::prev(Toks.rend()));
+
+ Tok = Toks[0];
+ }
+
+ bool isTokBlockCommand() {
+ return (Tok.is(tok::backslash_command) || Tok.is(tok::at_command)) &&
+ Traits.getCommandInfo(Tok.getCommandID())->IsBlockCommand;
+ }
+
+public:
+ Parser(Lexer &L, Sema &S, llvm::BumpPtrAllocator &Allocator,
+ const SourceManager &SourceMgr, DiagnosticsEngine &Diags,
+ const CommandTraits &Traits);
+
+ /// Parse arguments for \\param command.
+ void parseParamCommandArgs(ParamCommandComment *PC,
+ TextTokenRetokenizer &Retokenizer);
+
+ /// Parse arguments for \\tparam command.
+ void parseTParamCommandArgs(TParamCommandComment *TPC,
+ TextTokenRetokenizer &Retokenizer);
+
+ void parseBlockCommandArgs(BlockCommandComment *BC,
+ TextTokenRetokenizer &Retokenizer,
+ unsigned NumArgs);
+
+ BlockCommandComment *parseBlockCommand();
+ InlineCommandComment *parseInlineCommand();
+
+ HTMLStartTagComment *parseHTMLStartTag();
+ HTMLEndTagComment *parseHTMLEndTag();
+
+ BlockContentComment *parseParagraphOrBlockCommand();
+
+ VerbatimBlockComment *parseVerbatimBlock();
+ VerbatimLineComment *parseVerbatimLine();
+ BlockContentComment *parseBlockContent();
+ FullComment *parseFullComment();
+};
+
+} // end namespace comments
+} // end namespace clang
+
+#endif
+
diff --git a/contrib/llvm/tools/clang/include/clang/AST/CommentSema.h b/contrib/llvm/tools/clang/include/clang/AST/CommentSema.h
new file mode 100644
index 0000000..6a80383
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/AST/CommentSema.h
@@ -0,0 +1,254 @@
+//===--- CommentSema.h - Doxygen comment semantic 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 semantic analysis class for Doxygen comments.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_AST_COMMENTSEMA_H
+#define LLVM_CLANG_AST_COMMENTSEMA_H
+
+#include "clang/AST/Comment.h"
+#include "clang/Basic/Diagnostic.h"
+#include "clang/Basic/SourceLocation.h"
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/StringMap.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/Support/Allocator.h"
+
+namespace clang {
+class Decl;
+class SourceMgr;
+class Preprocessor;
+
+namespace comments {
+class CommandTraits;
+
+class Sema {
+ Sema(const Sema &) = delete;
+ void operator=(const Sema &) = delete;
+
+ /// Allocator for AST nodes.
+ llvm::BumpPtrAllocator &Allocator;
+
+ /// Source manager for the comment being parsed.
+ const SourceManager &SourceMgr;
+
+ DiagnosticsEngine &Diags;
+
+ CommandTraits &Traits;
+
+ const Preprocessor *PP;
+
+ /// Information about the declaration this comment is attached to.
+ DeclInfo *ThisDeclInfo;
+
+ /// Comment AST nodes that correspond to parameter names in
+ /// \c TemplateParameters.
+ ///
+ /// Contains a valid value if \c DeclInfo->IsFilled is true.
+ llvm::StringMap<TParamCommandComment *> TemplateParameterDocs;
+
+ /// AST node for the \\brief command and its aliases.
+ const BlockCommandComment *BriefCommand;
+
+ /// AST node for the \\headerfile command.
+ const BlockCommandComment *HeaderfileCommand;
+
+ DiagnosticBuilder Diag(SourceLocation Loc, unsigned DiagID) {
+ return Diags.Report(Loc, DiagID);
+ }
+
+ /// A stack of HTML tags that are currently open (not matched with closing
+ /// tags).
+ SmallVector<HTMLStartTagComment *, 8> HTMLOpenTags;
+
+public:
+ Sema(llvm::BumpPtrAllocator &Allocator, const SourceManager &SourceMgr,
+ DiagnosticsEngine &Diags, CommandTraits &Traits,
+ const Preprocessor *PP);
+
+ void setDecl(const Decl *D);
+
+ /// Returns a copy of array, owned by Sema's allocator.
+ template<typename T>
+ ArrayRef<T> copyArray(ArrayRef<T> Source) {
+ if (!Source.empty())
+ return Source.copy(Allocator);
+ return None;
+ }
+
+ ParagraphComment *actOnParagraphComment(
+ ArrayRef<InlineContentComment *> Content);
+
+ BlockCommandComment *actOnBlockCommandStart(SourceLocation LocBegin,
+ SourceLocation LocEnd,
+ unsigned CommandID,
+ CommandMarkerKind CommandMarker);
+
+ void actOnBlockCommandArgs(BlockCommandComment *Command,
+ ArrayRef<BlockCommandComment::Argument> Args);
+
+ void actOnBlockCommandFinish(BlockCommandComment *Command,
+ ParagraphComment *Paragraph);
+
+ ParamCommandComment *actOnParamCommandStart(SourceLocation LocBegin,
+ SourceLocation LocEnd,
+ unsigned CommandID,
+ CommandMarkerKind CommandMarker);
+
+ void actOnParamCommandDirectionArg(ParamCommandComment *Command,
+ SourceLocation ArgLocBegin,
+ SourceLocation ArgLocEnd,
+ StringRef Arg);
+
+ void actOnParamCommandParamNameArg(ParamCommandComment *Command,
+ SourceLocation ArgLocBegin,
+ SourceLocation ArgLocEnd,
+ StringRef Arg);
+
+ void actOnParamCommandFinish(ParamCommandComment *Command,
+ ParagraphComment *Paragraph);
+
+ TParamCommandComment *actOnTParamCommandStart(SourceLocation LocBegin,
+ SourceLocation LocEnd,
+ unsigned CommandID,
+ CommandMarkerKind CommandMarker);
+
+ void actOnTParamCommandParamNameArg(TParamCommandComment *Command,
+ SourceLocation ArgLocBegin,
+ SourceLocation ArgLocEnd,
+ StringRef Arg);
+
+ void actOnTParamCommandFinish(TParamCommandComment *Command,
+ ParagraphComment *Paragraph);
+
+ InlineCommandComment *actOnInlineCommand(SourceLocation CommandLocBegin,
+ SourceLocation CommandLocEnd,
+ unsigned CommandID);
+
+ InlineCommandComment *actOnInlineCommand(SourceLocation CommandLocBegin,
+ SourceLocation CommandLocEnd,
+ unsigned CommandID,
+ SourceLocation ArgLocBegin,
+ SourceLocation ArgLocEnd,
+ StringRef Arg);
+
+ InlineContentComment *actOnUnknownCommand(SourceLocation LocBegin,
+ SourceLocation LocEnd,
+ StringRef CommandName);
+
+ InlineContentComment *actOnUnknownCommand(SourceLocation LocBegin,
+ SourceLocation LocEnd,
+ unsigned CommandID);
+
+ TextComment *actOnText(SourceLocation LocBegin,
+ SourceLocation LocEnd,
+ StringRef Text);
+
+ VerbatimBlockComment *actOnVerbatimBlockStart(SourceLocation Loc,
+ unsigned CommandID);
+
+ VerbatimBlockLineComment *actOnVerbatimBlockLine(SourceLocation Loc,
+ StringRef Text);
+
+ void actOnVerbatimBlockFinish(VerbatimBlockComment *Block,
+ SourceLocation CloseNameLocBegin,
+ StringRef CloseName,
+ ArrayRef<VerbatimBlockLineComment *> Lines);
+
+ VerbatimLineComment *actOnVerbatimLine(SourceLocation LocBegin,
+ unsigned CommandID,
+ SourceLocation TextBegin,
+ StringRef Text);
+
+ HTMLStartTagComment *actOnHTMLStartTagStart(SourceLocation LocBegin,
+ StringRef TagName);
+
+ void actOnHTMLStartTagFinish(HTMLStartTagComment *Tag,
+ ArrayRef<HTMLStartTagComment::Attribute> Attrs,
+ SourceLocation GreaterLoc,
+ bool IsSelfClosing);
+
+ HTMLEndTagComment *actOnHTMLEndTag(SourceLocation LocBegin,
+ SourceLocation LocEnd,
+ StringRef TagName);
+
+ FullComment *actOnFullComment(ArrayRef<BlockContentComment *> Blocks);
+
+ void checkBlockCommandEmptyParagraph(BlockCommandComment *Command);
+
+ void checkReturnsCommand(const BlockCommandComment *Command);
+
+ /// Emit diagnostics about duplicate block commands that should be
+ /// used only once per comment, e.g., \\brief and \\returns.
+ void checkBlockCommandDuplicate(const BlockCommandComment *Command);
+
+ void checkDeprecatedCommand(const BlockCommandComment *Comment);
+
+ void checkFunctionDeclVerbatimLine(const BlockCommandComment *Comment);
+
+ void checkContainerDeclVerbatimLine(const BlockCommandComment *Comment);
+
+ void checkContainerDecl(const BlockCommandComment *Comment);
+
+ /// Resolve parameter names to parameter indexes in function declaration.
+ /// Emit diagnostics about unknown parametrs.
+ void resolveParamCommandIndexes(const FullComment *FC);
+
+ bool isFunctionDecl();
+ bool isAnyFunctionDecl();
+
+ /// \returns \c true if declaration that this comment is attached to declares
+ /// a function pointer.
+ bool isFunctionPointerVarDecl();
+ bool isFunctionOrMethodVariadic();
+ bool isObjCMethodDecl();
+ bool isObjCPropertyDecl();
+ bool isTemplateOrSpecialization();
+ bool isRecordLikeDecl();
+ bool isClassOrStructDecl();
+ bool isUnionDecl();
+ bool isObjCInterfaceDecl();
+ bool isObjCProtocolDecl();
+ bool isClassTemplateDecl();
+ bool isFunctionTemplateDecl();
+
+ ArrayRef<const ParmVarDecl *> getParamVars();
+
+ /// Extract all important semantic information from
+ /// \c ThisDeclInfo->ThisDecl into \c ThisDeclInfo members.
+ void inspectThisDecl();
+
+ /// Returns index of a function parameter with a given name.
+ unsigned resolveParmVarReference(StringRef Name,
+ ArrayRef<const ParmVarDecl *> ParamVars);
+
+ /// Returns index of a function parameter with the name closest to a given
+ /// typo.
+ unsigned correctTypoInParmVarReference(StringRef Typo,
+ ArrayRef<const ParmVarDecl *> ParamVars);
+
+ bool resolveTParamReference(StringRef Name,
+ const TemplateParameterList *TemplateParameters,
+ SmallVectorImpl<unsigned> *Position);
+
+ StringRef correctTypoInTParamReference(
+ StringRef Typo,
+ const TemplateParameterList *TemplateParameters);
+
+ InlineCommandComment::RenderKind
+ getInlineCommandRenderKind(StringRef Name) const;
+};
+
+} // end namespace comments
+} // end namespace clang
+
+#endif
+
diff --git a/contrib/llvm/tools/clang/include/clang/AST/CommentVisitor.h b/contrib/llvm/tools/clang/include/clang/AST/CommentVisitor.h
new file mode 100644
index 0000000..21641bf
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/AST/CommentVisitor.h
@@ -0,0 +1,70 @@
+//===--- CommentVisitor.h - Visitor for Comment subclasses ------*- 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_AST_COMMENTVISITOR_H
+#define LLVM_CLANG_AST_COMMENTVISITOR_H
+
+#include "clang/AST/Comment.h"
+#include "llvm/Support/ErrorHandling.h"
+
+namespace clang {
+namespace comments {
+
+template <typename T> struct make_ptr { typedef T *type; };
+template <typename T> struct make_const_ptr { typedef const T *type; };
+
+template<template <typename> class Ptr, typename ImplClass, typename RetTy=void>
+class CommentVisitorBase {
+public:
+#define PTR(CLASS) typename Ptr<CLASS>::type
+#define DISPATCH(NAME, CLASS) \
+ return static_cast<ImplClass*>(this)->visit ## NAME(static_cast<PTR(CLASS)>(C))
+
+ RetTy visit(PTR(Comment) C) {
+ if (!C)
+ return RetTy();
+
+ switch (C->getCommentKind()) {
+ default: llvm_unreachable("Unknown comment kind!");
+#define ABSTRACT_COMMENT(COMMENT)
+#define COMMENT(CLASS, PARENT) \
+ case Comment::CLASS##Kind: DISPATCH(CLASS, CLASS);
+#include "clang/AST/CommentNodes.inc"
+#undef ABSTRACT_COMMENT
+#undef COMMENT
+ }
+ }
+
+ // If the derived class does not implement a certain Visit* method, fall back
+ // on Visit* method for the superclass.
+#define ABSTRACT_COMMENT(COMMENT) COMMENT
+#define COMMENT(CLASS, PARENT) \
+ RetTy visit ## CLASS(PTR(CLASS) C) { DISPATCH(PARENT, PARENT); }
+#include "clang/AST/CommentNodes.inc"
+#undef ABSTRACT_COMMENT
+#undef COMMENT
+
+ RetTy visitComment(PTR(Comment) C) { return RetTy(); }
+
+#undef PTR
+#undef DISPATCH
+};
+
+template<typename ImplClass, typename RetTy=void>
+class CommentVisitor :
+ public CommentVisitorBase<make_ptr, ImplClass, RetTy> {};
+
+template<typename ImplClass, typename RetTy=void>
+class ConstCommentVisitor :
+ public CommentVisitorBase<make_const_ptr, ImplClass, RetTy> {};
+
+} // end namespace comments
+} // end namespace clang
+
+#endif
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..046ce70
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/AST/Decl.h
@@ -0,0 +1,3801 @@
+//===--- 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/DeclarationName.h"
+#include "clang/AST/ExternalASTSource.h"
+#include "clang/AST/Redeclarable.h"
+#include "clang/AST/Type.h"
+#include "clang/Basic/Linkage.h"
+#include "clang/Basic/Module.h"
+#include "clang/Basic/OperatorKinds.h"
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/Optional.h"
+#include "llvm/Support/Compiler.h"
+#include "llvm/Support/raw_ostream.h"
+#include "llvm/Support/TrailingObjects.h"
+
+namespace clang {
+struct ASTTemplateArgumentListInfo;
+class CXXTemporary;
+class CompoundStmt;
+class DependentFunctionTemplateSpecializationInfo;
+class Expr;
+class FunctionTemplateDecl;
+class FunctionTemplateSpecializationInfo;
+class LabelStmt;
+class MemberSpecializationInfo;
+class NestedNameSpecifier;
+class ParmVarDecl;
+class Stmt;
+class StringLiteral;
+class TemplateArgumentList;
+class TemplateParameterList;
+class TypeAliasTemplateDecl;
+class TypeLoc;
+class UnresolvedSetImpl;
+class VarTemplateDecl;
+
+/// \brief A container of type source information.
+///
+/// A client can read the relevant info using TypeLoc wrappers, e.g:
+/// @code
+/// TypeLoc TL = TypeSourceInfo->getTypeLoc();
+/// TL.getStartLoc().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
+
+ /// \brief Override the type stored in this TypeSourceInfo. Use with caution!
+ void overrideType(QualType T) { Ty = T; }
+};
+
+/// TranslationUnitDecl - The top declaration context.
+class TranslationUnitDecl : public Decl, public DeclContext {
+ virtual void anchor();
+ ASTContext &Ctx;
+
+ /// The (most recently entered) anonymous namespace for this
+ /// translation unit, if one has been created.
+ NamespaceDecl *AnonymousNamespace;
+
+ explicit TranslationUnitDecl(ASTContext &ctx);
+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 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));
+ }
+};
+
+/// \brief Declaration context for names declared as extern "C" in C++. This
+/// is neither the semantic nor lexical context for such declarations, but is
+/// used to check for conflicts with other extern "C" declarations. Example:
+///
+/// \code
+/// namespace N { extern "C" void f(); } // #1
+/// void N::f() {} // #2
+/// namespace M { extern "C" void f(); } // #3
+/// \endcode
+///
+/// The semantic context of #1 is namespace N and its lexical context is the
+/// LinkageSpecDecl; the semantic context of #2 is namespace N and its lexical
+/// context is the TU. However, both declarations are also visible in the
+/// extern "C" context.
+///
+/// The declaration at #3 finds it is a redeclaration of \c N::f through
+/// lookup in the extern "C" context.
+class ExternCContextDecl : public Decl, public DeclContext {
+ virtual void anchor();
+
+ explicit ExternCContextDecl(TranslationUnitDecl *TU)
+ : Decl(ExternCContext, TU, SourceLocation()),
+ DeclContext(ExternCContext) {}
+public:
+ static ExternCContextDecl *Create(const ASTContext &C,
+ TranslationUnitDecl *TU);
+ // Implement isa/cast/dyncast/etc.
+ static bool classof(const Decl *D) { return classofKind(D->getKind()); }
+ static bool classofKind(Kind K) { return K == ExternCContext; }
+ static DeclContext *castToDeclContext(const ExternCContextDecl *D) {
+ return static_cast<DeclContext *>(const_cast<ExternCContextDecl*>(D));
+ }
+ static ExternCContextDecl *castFromDeclContext(const DeclContext *DC) {
+ return static_cast<ExternCContextDecl *>(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 {
+ virtual void anchor();
+ /// 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;
+
+private:
+ NamedDecl *getUnderlyingDeclImpl() LLVM_READONLY;
+
+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.
+ 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(raw_ostream &os) const { os << Name; }
+
+ /// 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; }
+
+ /// printQualifiedName - 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 printName().
+ /// Creating this name is expensive, so it should be called only when
+ /// performance doesn't matter.
+ void printQualifiedName(raw_ostream &OS) const;
+ void printQualifiedName(raw_ostream &OS, const PrintingPolicy &Policy) const;
+
+ // FIXME: Remove string version.
+ std::string getQualifiedNameAsString() const;
+
+ /// getNameForDiagnostic - Appends a human-readable name for this
+ /// declaration into the given stream.
+ ///
+ /// This is the method invoked by Sema when displaying a NamedDecl
+ /// in a diagnostic. It does not necessarily produce the same
+ /// result as printName(); for example, class template
+ /// specializations are printed with their template arguments.
+ virtual void getNameForDiagnostic(raw_ostream &OS,
+ const PrintingPolicy &Policy,
+ bool Qualified) const;
+
+ /// \brief 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.
+ ///
+ /// \param IsKnownNewer \c true if this declaration is known to be newer
+ /// than \p OldD (for instance, if this declaration is newly-created).
+ bool declarationReplaces(NamedDecl *OldD, bool IsKnownNewer = true) const;
+
+ /// \brief Determine whether this declaration has linkage.
+ bool hasLinkage() const;
+
+ using Decl::isModulePrivate;
+ using Decl::setModulePrivate;
+
+ /// \brief Determine whether this declaration is hidden from name lookup.
+ bool isHidden() const { return Hidden; }
+
+ /// \brief Set whether this declaration is hidden from name lookup.
+ void setHidden(bool Hide) {
+ assert((!Hide || isFromASTFile() || hasLocalOwningModuleStorage()) &&
+ "declaration with no owning module can't be hidden");
+ Hidden = Hide;
+ }
+
+ /// \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.
+ if (isa<EnumDecl>(DC))
+ DC = DC->getRedeclContext();
+
+ return DC->isRecord();
+ }
+
+ /// \brief Determine whether the given declaration is an instance member of
+ /// a C++ class.
+ bool isCXXInstanceMember() const;
+
+ /// \brief Determine what kind of linkage this entity has.
+ /// This is not the linkage as defined by the standard or the codegen notion
+ /// of linkage. It is just an implementation detail that is used to compute
+ /// those.
+ Linkage getLinkageInternal() const;
+
+ /// \brief Get the linkage from a semantic point of view. Entities in
+ /// anonymous namespaces are external (in c++98).
+ Linkage getFormalLinkage() const {
+ return clang::getFormalLinkage(getLinkageInternal());
+ }
+
+ /// \brief True if this decl has external linkage.
+ bool hasExternalFormalLinkage() const {
+ return isExternalFormalLinkage(getLinkageInternal());
+ }
+
+ bool isExternallyVisible() const {
+ return clang::isExternallyVisible(getLinkageInternal());
+ }
+
+ /// \brief Determines the visibility of this entity.
+ Visibility getVisibility() const {
+ return getLinkageAndVisibility().getVisibility();
+ }
+
+ /// \brief Determines the linkage and visibility of this entity.
+ LinkageInfo getLinkageAndVisibility() const;
+
+ /// Kinds of explicit visibility.
+ enum ExplicitVisibilityKind {
+ VisibilityForType,
+ VisibilityForValue
+ };
+
+ /// \brief If visibility was explicitly specified for this
+ /// declaration, return that visibility.
+ Optional<Visibility>
+ getExplicitVisibility(ExplicitVisibilityKind kind) const;
+
+ /// \brief True if the computed linkage is valid. Used for consistency
+ /// checking. Should always return true.
+ bool isLinkageValid() const;
+
+ /// \brief True if something has required us to compute the linkage
+ /// of this declaration.
+ ///
+ /// Language features which can retroactively change linkage (like a
+ /// typedef name for linkage purposes) may need to consider this,
+ /// but hopefully only in transitory ways during parsing.
+ bool hasLinkageBeenComputed() const {
+ return hasCachedLinkage();
+ }
+
+ /// \brief Looks through UsingDecls and ObjCCompatibleAliasDecls for
+ /// the underlying named decl.
+ NamedDecl *getUnderlyingDecl() {
+ // Fast-path the common case.
+ if (this->getKind() != UsingShadow &&
+ this->getKind() != ObjCCompatibleAlias &&
+ this->getKind() != NamespaceAlias)
+ return this;
+
+ return getUnderlyingDeclImpl();
+ }
+ const NamedDecl *getUnderlyingDecl() const {
+ return const_cast<NamedDecl*>(this)->getUnderlyingDecl();
+ }
+
+ NamedDecl *getMostRecentDecl() {
+ return cast<NamedDecl>(static_cast<Decl *>(this)->getMostRecentDecl());
+ }
+ const NamedDecl *getMostRecentDecl() const {
+ return const_cast<NamedDecl*>(this)->getMostRecentDecl();
+ }
+
+ ObjCStringFormatFamily getObjCFStringFormattingFamily() const;
+
+ static bool classof(const Decl *D) { return classofKind(D->getKind()); }
+ static bool classofKind(Kind K) { return K >= firstNamed && K <= lastNamed; }
+};
+
+inline raw_ostream &operator<<(raw_ostream &OS, const NamedDecl &ND) {
+ ND.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 {
+ void anchor() override;
+ LabelStmt *TheStmt;
+ StringRef MSAsmName;
+ bool MSAsmNameResolved;
+ /// LocStart - For normal labels, this is the same as the main declaration
+ /// label, i.e., the location of the identifier; for GNU local labels,
+ /// this is the location of the __label__ keyword.
+ SourceLocation LocStart;
+
+ LabelDecl(DeclContext *DC, SourceLocation IdentL, IdentifierInfo *II,
+ LabelStmt *S, SourceLocation StartL)
+ : NamedDecl(Label, DC, IdentL, II),
+ TheStmt(S),
+ MSAsmNameResolved(false),
+ LocStart(StartL) {}
+
+public:
+ static LabelDecl *Create(ASTContext &C, DeclContext *DC,
+ SourceLocation IdentL, IdentifierInfo *II);
+ static LabelDecl *Create(ASTContext &C, DeclContext *DC,
+ SourceLocation IdentL, IdentifierInfo *II,
+ SourceLocation GnuLabelL);
+ static LabelDecl *CreateDeserialized(ASTContext &C, unsigned ID);
+
+ LabelStmt *getStmt() const { return TheStmt; }
+ void setStmt(LabelStmt *T) { TheStmt = T; }
+
+ bool isGnuLocal() const { return LocStart != getLocation(); }
+ void setLocStart(SourceLocation L) { LocStart = L; }
+
+ SourceRange getSourceRange() const override LLVM_READONLY {
+ return SourceRange(LocStart, getLocation());
+ }
+
+ bool isMSAsmLabel() const { return MSAsmName.size() != 0; }
+ bool isResolvedMSAsmLabel() const { return isMSAsmLabel() && MSAsmNameResolved; }
+ void setMSAsmLabel(StringRef Name);
+ StringRef getMSAsmLabel() const { return MSAsmName; }
+ void setMSAsmLabelResolved() { MSAsmNameResolved = true; }
+
+ // Implement isa/cast/dyncast/etc.
+ static bool classof(const Decl *D) { return classofKind(D->getKind()); }
+ static bool classofKind(Kind K) { return K == Label; }
+};
+
+/// NamespaceDecl - Represent a C++ namespace.
+class NamespaceDecl : public NamedDecl, public DeclContext,
+ public Redeclarable<NamespaceDecl>
+{
+ /// LocStart - The starting location of the source range, pointing
+ /// to either the namespace or the inline keyword.
+ SourceLocation LocStart;
+ /// RBraceLoc - The ending location of the source range.
+ SourceLocation RBraceLoc;
+
+ /// \brief A pointer to either the anonymous namespace that lives just inside
+ /// this namespace or to the first namespace in the chain (the latter case
+ /// only when this is not the first in the chain), along with a
+ /// boolean value indicating whether this is an inline namespace.
+ llvm::PointerIntPair<NamespaceDecl *, 1, bool> AnonOrFirstNamespaceAndInline;
+
+ NamespaceDecl(ASTContext &C, DeclContext *DC, bool Inline,
+ SourceLocation StartLoc, SourceLocation IdLoc,
+ IdentifierInfo *Id, NamespaceDecl *PrevDecl);
+
+ typedef Redeclarable<NamespaceDecl> redeclarable_base;
+ NamespaceDecl *getNextRedeclarationImpl() override;
+ NamespaceDecl *getPreviousDeclImpl() override;
+ NamespaceDecl *getMostRecentDeclImpl() override;
+
+public:
+ static NamespaceDecl *Create(ASTContext &C, DeclContext *DC,
+ bool Inline, SourceLocation StartLoc,
+ SourceLocation IdLoc, IdentifierInfo *Id,
+ NamespaceDecl *PrevDecl);
+
+ static NamespaceDecl *CreateDeserialized(ASTContext &C, unsigned ID);
+
+ typedef redeclarable_base::redecl_range redecl_range;
+ typedef redeclarable_base::redecl_iterator redecl_iterator;
+ using redeclarable_base::redecls_begin;
+ using redeclarable_base::redecls_end;
+ using redeclarable_base::redecls;
+ using redeclarable_base::getPreviousDecl;
+ using redeclarable_base::getMostRecentDecl;
+ using redeclarable_base::isFirstDecl;
+
+ /// \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 AnonOrFirstNamespaceAndInline.getInt();
+ }
+
+ /// \brief Set whether this is an inline namespace declaration.
+ void setInline(bool Inline) {
+ AnonOrFirstNamespaceAndInline.setInt(Inline);
+ }
+
+ /// \brief Get the original (first) namespace declaration.
+ NamespaceDecl *getOriginalNamespace();
+
+ /// \brief Get the original (first) namespace declaration.
+ const NamespaceDecl *getOriginalNamespace() const;
+
+ /// \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;
+
+ /// \brief Retrieve the anonymous namespace nested inside this namespace,
+ /// if any.
+ NamespaceDecl *getAnonymousNamespace() const {
+ return getOriginalNamespace()->AnonOrFirstNamespaceAndInline.getPointer();
+ }
+
+ void setAnonymousNamespace(NamespaceDecl *D) {
+ getOriginalNamespace()->AnonOrFirstNamespaceAndInline.setPointer(D);
+ }
+
+ /// Retrieves the canonical declaration of this namespace.
+ NamespaceDecl *getCanonicalDecl() override {
+ return getOriginalNamespace();
+ }
+ const NamespaceDecl *getCanonicalDecl() const {
+ return getOriginalNamespace();
+ }
+
+ SourceRange getSourceRange() const override LLVM_READONLY {
+ return SourceRange(LocStart, RBraceLoc);
+ }
+
+ SourceLocation getLocStart() const LLVM_READONLY { return LocStart; }
+ SourceLocation getRBraceLoc() const { return RBraceLoc; }
+ void setLocStart(SourceLocation L) { LocStart = L; }
+ void setRBraceLoc(SourceLocation L) { RBraceLoc = L; }
+
+ // Implement isa/cast/dyncast/etc.
+ static bool classof(const Decl *D) { return classofKind(D->getKind()); }
+ 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 {
+ void anchor() override;
+ 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; }
+
+ /// \brief Determine whether this symbol is weakly-imported,
+ /// or declared with the weak or weak-ref attr.
+ bool isWeak() const;
+
+ // Implement isa/cast/dyncast/etc.
+ static bool classof(const Decl *D) { return classofKind(D->getKind()); }
+ 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 {
+ NestedNameSpecifierLoc QualifierLoc;
+
+ /// NumTemplParamLists - The number of "outer" template parameter lists.
+ /// The count includes all of the template parameter lists that were matched
+ /// against the template-ids occurring into the NNS and possibly (in the
+ /// case of an explicit specialization) a final "template <>".
+ unsigned NumTemplParamLists;
+
+ /// TemplParamLists - A new-allocated array of size NumTemplParamLists,
+ /// containing pointers to the "outer" template parameter lists.
+ /// It includes all of the template parameter lists that were matched
+ /// against the template-ids occurring into the NNS and possibly (in the
+ /// case of an explicit specialization) a final "template <>".
+ TemplateParameterList** TemplParamLists;
+
+ /// Default constructor.
+ QualifierInfo()
+ : QualifierLoc(), NumTemplParamLists(0), TemplParamLists(nullptr) {}
+
+ /// setTemplateParameterListsInfo - Sets info about "outer" template
+ /// parameter lists.
+ void setTemplateParameterListsInfo(ASTContext &Context,
+ ArrayRef<TemplateParameterList *> TPLists);
+
+private:
+ // Copy constructor and copy assignment are disabled.
+ QualifierInfo(const QualifierInfo&) = delete;
+ QualifierInfo& operator=(const QualifierInfo&) = delete;
+};
+
+/// \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;
+
+ /// InnerLocStart - The start of the source range for this declaration,
+ /// ignoring outer template declarations.
+ SourceLocation InnerLocStart;
+
+ 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,
+ SourceLocation StartL)
+ : ValueDecl(DK, DC, L, N, T), DeclInfo(TInfo), InnerLocStart(StartL) {
+ }
+
+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.
+ SourceLocation getInnerLocStart() const { return InnerLocStart; }
+ void setInnerLocStart(SourceLocation L) { InnerLocStart = L; }
+
+ /// getOuterLocStart - Return SourceLocation representing start of source
+ /// range taking into account any outer template declarations.
+ SourceLocation getOuterLocStart() const;
+
+ SourceRange getSourceRange() const override LLVM_READONLY;
+ SourceLocation getLocStart() const LLVM_READONLY {
+ return getOuterLocStart();
+ }
+
+ /// \brief Retrieve the nested-name-specifier that qualifies the name of this
+ /// declaration, if it was present in the source.
+ NestedNameSpecifier *getQualifier() const {
+ return hasExtInfo() ? getExtInfo()->QualifierLoc.getNestedNameSpecifier()
+ : nullptr;
+ }
+
+ /// \brief Retrieve the nested-name-specifier (with source-location
+ /// information) that qualifies the name of this declaration, if it was
+ /// present in the source.
+ NestedNameSpecifierLoc getQualifierLoc() const {
+ return hasExtInfo() ? getExtInfo()->QualifierLoc
+ : NestedNameSpecifierLoc();
+ }
+
+ void setQualifierInfo(NestedNameSpecifierLoc QualifierLoc);
+
+ unsigned getNumTemplateParameterLists() const {
+ return hasExtInfo() ? getExtInfo()->NumTemplParamLists : 0;
+ }
+ TemplateParameterList *getTemplateParameterList(unsigned index) const {
+ assert(index < getNumTemplateParameterLists());
+ return getExtInfo()->TemplParamLists[index];
+ }
+ void setTemplateParameterListsInfo(ASTContext &Context,
+ ArrayRef<TemplateParameterList *> TPLists);
+
+ SourceLocation getTypeSpecStartLoc() const;
+
+ // Implement isa/cast/dyncast/etc.
+ static bool classof(const Decl *D) { return classofKind(D->getKind()); }
+ 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,
+ /// or in C++11, whether the statement is a 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:
+ /// getStorageClassSpecifierString - Return the string used to
+ /// specify the storage class \p SC.
+ ///
+ /// It is illegal to call this function with SC == None.
+ static const char *getStorageClassSpecifierString(StorageClass SC);
+
+ /// \brief Initialization styles.
+ enum InitializationStyle {
+ CInit, ///< C-style initialization with assignment
+ CallInit, ///< Call-style initialization (C++98)
+ ListInit ///< Direct list-initialization (C++11)
+ };
+
+ /// \brief Kinds of thread-local storage.
+ enum TLSKind {
+ TLS_None, ///< Not a TLS variable.
+ TLS_Static, ///< TLS with a known-constant initializer.
+ TLS_Dynamic ///< TLS with a dynamic initializer.
+ };
+
+protected:
+ // A pointer union of Stmt * and EvaluatedStmt *. When an EvaluatedStmt, we
+ // have allocated the auxilliary struct of information there.
+ //
+ // TODO: It is a bit unfortunate to use a PointerUnion inside the VarDecl for
+ // this as *many* VarDecls are ParmVarDecls that don't have default
+ // arguments. We could save some space by moving this pointer union to be
+ // allocated in trailing space when necessary.
+ typedef llvm::PointerUnion<Stmt *, EvaluatedStmt *> InitType;
+
+ /// \brief The initializer for this variable or, for a ParmVarDecl, the
+ /// C++ default argument.
+ mutable InitType Init;
+
+private:
+ class VarDeclBitfields {
+ friend class VarDecl;
+ friend class ASTDeclReader;
+
+ unsigned SClass : 3;
+ unsigned TSCSpec : 2;
+ unsigned InitStyle : 2;
+ };
+ enum { NumVarDeclBits = 7 };
+
+ friend class ASTDeclReader;
+ friend class StmtIteratorBase;
+ friend class ASTNodeImporter;
+
+protected:
+ enum { NumParameterIndexBits = 8 };
+
+ enum DefaultArgKind {
+ DAK_None,
+ DAK_Unparsed,
+ DAK_Uninstantiated,
+ DAK_Normal
+ };
+
+ class ParmVarDeclBitfields {
+ friend class ParmVarDecl;
+ friend class ASTDeclReader;
+
+ unsigned : NumVarDeclBits;
+
+ /// Whether this parameter inherits a default argument from a
+ /// prior declaration.
+ unsigned HasInheritedDefaultArg : 1;
+
+ /// Describes the kind of default argument for this parameter. By default
+ /// this is none. If this is normal, then the default argument is stored in
+ /// the \c VarDecl initalizer expression unless we were unble to parse
+ /// (even an invalid) expression for the default argument.
+ unsigned DefaultArgKind : 2;
+
+ /// Whether this parameter undergoes K&R argument promotion.
+ unsigned IsKNRPromoted : 1;
+
+ /// Whether this parameter is an ObjC method parameter or not.
+ unsigned IsObjCMethodParam : 1;
+
+ /// If IsObjCMethodParam, a Decl::ObjCDeclQualifier.
+ /// Otherwise, the number of function parameter scopes enclosing
+ /// the function parameter scope in which this parameter was
+ /// declared.
+ unsigned ScopeDepthOrObjCQuals : 7;
+
+ /// The number of parameters preceding this parameter in the
+ /// function parameter scope in which it was declared.
+ unsigned ParameterIndex : NumParameterIndexBits;
+ };
+
+ class NonParmVarDeclBitfields {
+ friend class VarDecl;
+ friend class ASTDeclReader;
+
+ unsigned : NumVarDeclBits;
+
+ /// \brief Whether this variable is the exception variable in a C++ catch
+ /// or an Objective-C @catch statement.
+ unsigned ExceptionVar : 1;
+
+ /// \brief Whether this local variable could be allocated in the return
+ /// slot of its function, enabling the named return value optimization
+ /// (NRVO).
+ unsigned NRVOVariable : 1;
+
+ /// \brief Whether this variable is the for-range-declaration in a C++0x
+ /// for-range statement.
+ unsigned CXXForRangeDecl : 1;
+
+ /// \brief Whether this variable is an ARC pseudo-__strong
+ /// variable; see isARCPseudoStrong() for details.
+ unsigned ARCPseudoStrong : 1;
+
+ /// \brief Whether this variable is (C++0x) constexpr.
+ unsigned IsConstexpr : 1;
+
+ /// \brief Whether this variable is a (C++ Concepts TS) concept.
+ unsigned IsConcept : 1;
+
+ /// \brief Whether this variable is the implicit variable for a lambda
+ /// init-capture.
+ unsigned IsInitCapture : 1;
+
+ /// \brief Whether this local extern variable's previous declaration was
+ /// declared in the same block scope. This controls whether we should merge
+ /// the type of this declaration with its previous declaration.
+ unsigned PreviousDeclInSameBlockScope : 1;
+ };
+
+ union {
+ unsigned AllBits;
+ VarDeclBitfields VarDeclBits;
+ ParmVarDeclBitfields ParmVarDeclBits;
+ NonParmVarDeclBitfields NonParmVarDeclBits;
+ };
+
+ VarDecl(Kind DK, ASTContext &C, DeclContext *DC, SourceLocation StartLoc,
+ SourceLocation IdLoc, IdentifierInfo *Id, QualType T,
+ TypeSourceInfo *TInfo, StorageClass SC);
+
+ typedef Redeclarable<VarDecl> redeclarable_base;
+ VarDecl *getNextRedeclarationImpl() override {
+ return getNextRedeclaration();
+ }
+ VarDecl *getPreviousDeclImpl() override {
+ return getPreviousDecl();
+ }
+ VarDecl *getMostRecentDeclImpl() override {
+ return getMostRecentDecl();
+ }
+
+public:
+ typedef redeclarable_base::redecl_range redecl_range;
+ typedef redeclarable_base::redecl_iterator redecl_iterator;
+ using redeclarable_base::redecls_begin;
+ using redeclarable_base::redecls_end;
+ using redeclarable_base::redecls;
+ using redeclarable_base::getPreviousDecl;
+ using redeclarable_base::getMostRecentDecl;
+ using redeclarable_base::isFirstDecl;
+
+ static VarDecl *Create(ASTContext &C, DeclContext *DC,
+ SourceLocation StartLoc, SourceLocation IdLoc,
+ IdentifierInfo *Id, QualType T, TypeSourceInfo *TInfo,
+ StorageClass S);
+
+ static VarDecl *CreateDeserialized(ASTContext &C, unsigned ID);
+
+ SourceRange getSourceRange() const override LLVM_READONLY;
+
+ /// \brief Returns the storage class as written in the source. For the
+ /// computed linkage of symbol, see getLinkage.
+ StorageClass getStorageClass() const {
+ return (StorageClass) VarDeclBits.SClass;
+ }
+ void setStorageClass(StorageClass SC);
+
+ void setTSCSpec(ThreadStorageClassSpecifier TSC) {
+ VarDeclBits.TSCSpec = TSC;
+ assert(VarDeclBits.TSCSpec == TSC && "truncation");
+ }
+ ThreadStorageClassSpecifier getTSCSpec() const {
+ return static_cast<ThreadStorageClassSpecifier>(VarDeclBits.TSCSpec);
+ }
+ TLSKind getTLSKind() const;
+
+ /// hasLocalStorage - Returns true if a variable with function scope
+ /// is a non-static local variable.
+ bool hasLocalStorage() const {
+ if (getStorageClass() == SC_None)
+ // Second check is for C++11 [dcl.stc]p4.
+ return !isFileVarDecl() && getTSCSpec() == TSCS_unspecified;
+
+ // Global Named Register (GNU extension)
+ if (getStorageClass() == SC_Register && !isLocalVarDeclOrParm())
+ return false;
+
+ // Return true for: Auto, Register.
+ // Return false for: Extern, Static, PrivateExtern, OpenCLWorkGroupLocal.
+
+ 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 ||
+ // C++11 [dcl.stc]p4
+ (getStorageClass() == SC_None && getTSCSpec() == TSCS_thread_local))
+ && !isFileVarDecl();
+ }
+
+ /// \brief Returns true if a variable has extern or __private_extern__
+ /// storage.
+ bool hasExternalStorage() const {
+ return getStorageClass() == SC_Extern ||
+ getStorageClass() == SC_PrivateExtern;
+ }
+
+ /// \brief Returns true for all variables that do not have local storage.
+ ///
+ /// This includes all global variables as well as static variables declared
+ /// within a function.
+ bool hasGlobalStorage() const { return !hasLocalStorage(); }
+
+ /// \brief Get the storage duration of this variable, per C++ [basic.stc].
+ StorageDuration getStorageDuration() const {
+ return hasLocalStorage() ? SD_Automatic :
+ getTSCSpec() ? SD_Thread : SD_Static;
+ }
+
+ /// \brief Compute the language linkage.
+ LanguageLinkage getLanguageLinkage() const;
+
+ /// \brief Determines whether this variable is a variable with
+ /// external, C linkage.
+ bool isExternC() const;
+
+ /// \brief Determines whether this variable's context is, or is nested within,
+ /// a C++ extern "C" linkage spec.
+ bool isInExternCContext() const;
+
+ /// \brief Determines whether this variable's context is, or is nested within,
+ /// a C++ extern "C++" linkage spec.
+ bool isInExternCXXContext() 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 = getLexicalDeclContext())
+ return DC->getRedeclContext()->isFunctionOrMethod();
+ return false;
+ }
+
+ /// \brief Similar to isLocalVarDecl but also includes parameters.
+ bool isLocalVarDeclOrParm() const {
+ return isLocalVarDecl() || getKind() == Decl::ParmVar;
+ }
+
+ /// isFunctionOrMethodVarDecl - Similar to isLocalVarDecl, but
+ /// excludes variables declared in blocks.
+ bool isFunctionOrMethodVarDecl() const {
+ if (getKind() != Decl::Var)
+ return false;
+ const DeclContext *DC = getLexicalDeclContext()->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();
+ }
+
+ VarDecl *getCanonicalDecl() override;
+ 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(ASTContext &) const;
+ DefinitionKind isThisDeclarationADefinition() const {
+ return isThisDeclarationADefinition(getASTContext());
+ }
+
+ /// \brief Check whether this variable is defined in this
+ /// translation unit.
+ DefinitionKind hasDefinition(ASTContext &) const;
+ DefinitionKind hasDefinition() const {
+ return hasDefinition(getASTContext());
+ }
+
+ /// \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 Get the real (not just tentative) definition for this declaration.
+ VarDecl *getDefinition(ASTContext &);
+ const VarDecl *getDefinition(ASTContext &C) const {
+ return const_cast<VarDecl*>(this)->getDefinition(C);
+ }
+ VarDecl *getDefinition() {
+ return getDefinition(getASTContext());
+ }
+ 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.
+ bool isOutOfLine() const override;
+
+ /// \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 {
+ Kind K = getKind();
+ if (K == ParmVar || K == ImplicitParam)
+ return false;
+
+ if (getLexicalDeclContext()->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;
+ const Expr *getInit() const {
+ return const_cast<VarDecl *>(this)->getInit();
+ }
+ Expr *getInit();
+
+ /// \brief Retrieve the address of the initializer expression.
+ Stmt **getInitAddress();
+
+ void setInit(Expr *I);
+
+ /// \brief Determine whether this variable's value can be used in a
+ /// constant expression, according to the relevant language standard.
+ /// This only checks properties of the declaration, and does not check
+ /// whether the initializer is in fact a constant expression.
+ bool isUsableInConstantExpressions(ASTContext &C) const;
+
+ EvaluatedStmt *ensureEvaluatedStmt() const;
+
+ /// \brief Attempt to evaluate the value of the initializer attached to this
+ /// declaration, and produce notes explaining why it cannot be evaluated or is
+ /// not a constant expression. Returns a pointer to the value if evaluation
+ /// succeeded, 0 otherwise.
+ APValue *evaluateValue() const;
+ APValue *evaluateValue(SmallVectorImpl<PartialDiagnosticAt> &Notes) const;
+
+ /// \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;
+
+ /// \brief Determines whether it is already known whether the
+ /// initializer is an integral constant expression or not.
+ bool isInitKnownICE() const;
+
+ /// \brief Determines whether the initializer is an integral constant
+ /// expression, or in C++11, whether the initializer is a constant
+ /// expression.
+ ///
+ /// \pre isInitKnownICE()
+ bool isInitICE() const;
+
+ /// \brief Determine whether the value of the initializer attached to this
+ /// declaration is an integral constant expression.
+ bool checkInitIsICE() const;
+
+ void setInitStyle(InitializationStyle Style) {
+ VarDeclBits.InitStyle = Style;
+ }
+
+ /// \brief The style of initialization for this declaration.
+ ///
+ /// C-style initialization is "int x = 1;". Call-style initialization is
+ /// a C++98 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. List-style initialization is C++11 syntax,
+ /// e.g. "int x{1};". Clients can distinguish between different forms of
+ /// initialization by checking this value. In particular, "int x = {1};" is
+ /// C-style, "int x({1})" is call-style, and "int x{1};" is list-style; the
+ /// Init expression in all three cases is an InitListExpr.
+ InitializationStyle getInitStyle() const {
+ return static_cast<InitializationStyle>(VarDeclBits.InitStyle);
+ }
+
+ /// \brief Whether the initializer is a direct-initializer (list or call).
+ bool isDirectInit() const {
+ return getInitStyle() != CInit;
+ }
+
+ /// \brief Determine whether this variable is the exception variable in a
+ /// C++ catch statememt or an Objective-C \@catch statement.
+ bool isExceptionVariable() const {
+ return isa<ParmVarDecl>(this) ? false : NonParmVarDeclBits.ExceptionVar;
+ }
+ void setExceptionVariable(bool EV) {
+ assert(!isa<ParmVarDecl>(this));
+ NonParmVarDeclBits.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 isa<ParmVarDecl>(this) ? false : NonParmVarDeclBits.NRVOVariable;
+ }
+ void setNRVOVariable(bool NRVO) {
+ assert(!isa<ParmVarDecl>(this));
+ NonParmVarDeclBits.NRVOVariable = NRVO;
+ }
+
+ /// \brief Determine whether this variable is the for-range-declaration in
+ /// a C++0x for-range statement.
+ bool isCXXForRangeDecl() const {
+ return isa<ParmVarDecl>(this) ? false : NonParmVarDeclBits.CXXForRangeDecl;
+ }
+ void setCXXForRangeDecl(bool FRD) {
+ assert(!isa<ParmVarDecl>(this));
+ NonParmVarDeclBits.CXXForRangeDecl = FRD;
+ }
+
+ /// \brief Determine whether this variable is an ARC pseudo-__strong
+ /// variable. A pseudo-__strong variable has a __strong-qualified
+ /// type but does not actually retain the object written into it.
+ /// Generally such variables are also 'const' for safety.
+ bool isARCPseudoStrong() const {
+ return isa<ParmVarDecl>(this) ? false : NonParmVarDeclBits.ARCPseudoStrong;
+ }
+ void setARCPseudoStrong(bool ps) {
+ assert(!isa<ParmVarDecl>(this));
+ NonParmVarDeclBits.ARCPseudoStrong = ps;
+ }
+
+ /// Whether this variable is (C++11) constexpr.
+ bool isConstexpr() const {
+ return isa<ParmVarDecl>(this) ? false : NonParmVarDeclBits.IsConstexpr;
+ }
+ void setConstexpr(bool IC) {
+ assert(!isa<ParmVarDecl>(this));
+ NonParmVarDeclBits.IsConstexpr = IC;
+ }
+
+ /// Whether this variable is (C++ Concepts TS) concept.
+ bool isConcept() const {
+ return isa<ParmVarDecl>(this) ? false : NonParmVarDeclBits.IsConcept;
+ }
+ void setConcept(bool IC) {
+ assert(!isa<ParmVarDecl>(this));
+ NonParmVarDeclBits.IsConcept = IC;
+ }
+
+ /// Whether this variable is the implicit variable for a lambda init-capture.
+ bool isInitCapture() const {
+ return isa<ParmVarDecl>(this) ? false : NonParmVarDeclBits.IsInitCapture;
+ }
+ void setInitCapture(bool IC) {
+ assert(!isa<ParmVarDecl>(this));
+ NonParmVarDeclBits.IsInitCapture = IC;
+ }
+
+ /// Whether this local extern variable declaration's previous declaration
+ /// was declared in the same block scope. Only correct in C++.
+ bool isPreviousDeclInSameBlockScope() const {
+ return isa<ParmVarDecl>(this)
+ ? false
+ : NonParmVarDeclBits.PreviousDeclInSameBlockScope;
+ }
+ void setPreviousDeclInSameBlockScope(bool Same) {
+ assert(!isa<ParmVarDecl>(this));
+ NonParmVarDeclBits.PreviousDeclInSameBlockScope = Same;
+ }
+
+ /// \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 an instantiation of a variable template or a
+ /// static data member of a class template, determine what kind of
+ /// template specialization or instantiation this is.
+ TemplateSpecializationKind getTemplateSpecializationKind() const;
+
+ /// \brief If this variable is an instantiation of a variable template or a
+ /// static data member of a class template, determine its point of
+ /// instantiation.
+ SourceLocation getPointOfInstantiation() 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());
+
+ /// \brief Specify that this variable is an instantiation of the
+ /// static data member VD.
+ void setInstantiationOfStaticDataMember(VarDecl *VD,
+ TemplateSpecializationKind TSK);
+
+ /// \brief Retrieves the variable template that is described by this
+ /// variable declaration.
+ ///
+ /// Every variable template is represented as a VarTemplateDecl and a
+ /// VarDecl. The former contains template properties (such as
+ /// the template parameter lists) while the latter contains the
+ /// actual description of the template's
+ /// contents. VarTemplateDecl::getTemplatedDecl() retrieves the
+ /// VarDecl that from a VarTemplateDecl, while
+ /// getDescribedVarTemplate() retrieves the VarTemplateDecl from
+ /// a VarDecl.
+ VarTemplateDecl *getDescribedVarTemplate() const;
+
+ void setDescribedVarTemplate(VarTemplateDecl *Template);
+
+ // Implement isa/cast/dyncast/etc.
+ static bool classof(const Decl *D) { return classofKind(D->getKind()); }
+ static bool classofKind(Kind K) { return K >= firstVar && K <= lastVar; }
+};
+
+class ImplicitParamDecl : public VarDecl {
+ void anchor() override;
+public:
+ static ImplicitParamDecl *Create(ASTContext &C, DeclContext *DC,
+ SourceLocation IdLoc, IdentifierInfo *Id,
+ QualType T);
+
+ static ImplicitParamDecl *CreateDeserialized(ASTContext &C, unsigned ID);
+
+ ImplicitParamDecl(ASTContext &C, DeclContext *DC, SourceLocation IdLoc,
+ IdentifierInfo *Id, QualType Type)
+ : VarDecl(ImplicitParam, C, DC, IdLoc, IdLoc, Id, Type,
+ /*tinfo*/ nullptr, SC_None) {
+ setImplicit();
+ }
+
+ // Implement isa/cast/dyncast/etc.
+ static bool classof(const Decl *D) { return classofKind(D->getKind()); }
+ static bool classofKind(Kind K) { return K == ImplicitParam; }
+};
+
+/// ParmVarDecl - Represents a parameter to a function.
+class ParmVarDecl : public VarDecl {
+public:
+ enum { MaxFunctionScopeDepth = 255 };
+ enum { MaxFunctionScopeIndex = 255 };
+
+protected:
+ ParmVarDecl(Kind DK, ASTContext &C, DeclContext *DC, SourceLocation StartLoc,
+ SourceLocation IdLoc, IdentifierInfo *Id, QualType T,
+ TypeSourceInfo *TInfo, StorageClass S, Expr *DefArg)
+ : VarDecl(DK, C, DC, StartLoc, IdLoc, Id, T, TInfo, S) {
+ assert(ParmVarDeclBits.HasInheritedDefaultArg == false);
+ assert(ParmVarDeclBits.DefaultArgKind == DAK_None);
+ assert(ParmVarDeclBits.IsKNRPromoted == false);
+ assert(ParmVarDeclBits.IsObjCMethodParam == false);
+ setDefaultArg(DefArg);
+ }
+
+public:
+ static ParmVarDecl *Create(ASTContext &C, DeclContext *DC,
+ SourceLocation StartLoc,
+ SourceLocation IdLoc, IdentifierInfo *Id,
+ QualType T, TypeSourceInfo *TInfo,
+ StorageClass S, Expr *DefArg);
+
+ static ParmVarDecl *CreateDeserialized(ASTContext &C, unsigned ID);
+
+ SourceRange getSourceRange() const override LLVM_READONLY;
+
+ void setObjCMethodScopeInfo(unsigned parameterIndex) {
+ ParmVarDeclBits.IsObjCMethodParam = true;
+ setParameterIndex(parameterIndex);
+ }
+
+ void setScopeInfo(unsigned scopeDepth, unsigned parameterIndex) {
+ assert(!ParmVarDeclBits.IsObjCMethodParam);
+
+ ParmVarDeclBits.ScopeDepthOrObjCQuals = scopeDepth;
+ assert(ParmVarDeclBits.ScopeDepthOrObjCQuals == scopeDepth
+ && "truncation!");
+
+ setParameterIndex(parameterIndex);
+ }
+
+ bool isObjCMethodParameter() const {
+ return ParmVarDeclBits.IsObjCMethodParam;
+ }
+
+ unsigned getFunctionScopeDepth() const {
+ if (ParmVarDeclBits.IsObjCMethodParam) return 0;
+ return ParmVarDeclBits.ScopeDepthOrObjCQuals;
+ }
+
+ /// Returns the index of this parameter in its prototype or method scope.
+ unsigned getFunctionScopeIndex() const {
+ return getParameterIndex();
+ }
+
+ ObjCDeclQualifier getObjCDeclQualifier() const {
+ if (!ParmVarDeclBits.IsObjCMethodParam) return OBJC_TQ_None;
+ return ObjCDeclQualifier(ParmVarDeclBits.ScopeDepthOrObjCQuals);
+ }
+ void setObjCDeclQualifier(ObjCDeclQualifier QTVal) {
+ assert(ParmVarDeclBits.IsObjCMethodParam);
+ ParmVarDeclBits.ScopeDepthOrObjCQuals = QTVal;
+ }
+
+ /// True if the value passed to this parameter must undergo
+ /// K&R-style default argument promotion:
+ ///
+ /// C99 6.5.2.2.
+ /// If the expression that denotes the called function has a type
+ /// that does not include a prototype, the integer promotions are
+ /// performed on each argument, and arguments that have type float
+ /// are promoted to double.
+ bool isKNRPromoted() const {
+ return ParmVarDeclBits.IsKNRPromoted;
+ }
+ void setKNRPromoted(bool promoted) {
+ ParmVarDeclBits.IsKNRPromoted = promoted;
+ }
+
+ Expr *getDefaultArg();
+ const Expr *getDefaultArg() const {
+ return const_cast<ParmVarDecl *>(this)->getDefaultArg();
+ }
+
+ void setDefaultArg(Expr *defarg);
+
+ /// \brief Retrieve the source range that covers the entire default
+ /// argument.
+ SourceRange getDefaultArgRange() const;
+ void setUninstantiatedDefaultArg(Expr *arg);
+ Expr *getUninstantiatedDefaultArg();
+ const Expr *getUninstantiatedDefaultArg() const {
+ return const_cast<ParmVarDecl *>(this)->getUninstantiatedDefaultArg();
+ }
+
+ /// hasDefaultArg - Determines whether this parameter has a default argument,
+ /// either parsed or not.
+ bool hasDefaultArg() const;
+
+ /// 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 ParmVarDeclBits.DefaultArgKind == DAK_Unparsed;
+ }
+
+ bool hasUninstantiatedDefaultArg() const {
+ return ParmVarDeclBits.DefaultArgKind == DAK_Uninstantiated;
+ }
+
+ /// 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() {
+ ParmVarDeclBits.DefaultArgKind = DAK_Unparsed;
+ }
+
+ bool hasInheritedDefaultArg() const {
+ return ParmVarDeclBits.HasInheritedDefaultArg;
+ }
+
+ void setHasInheritedDefaultArg(bool I = true) {
+ ParmVarDeclBits.HasInheritedDefaultArg = I;
+ }
+
+ QualType getOriginalType() const;
+
+ /// \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 classofKind(Kind K) { return K == ParmVar; }
+
+private:
+ enum { ParameterIndexSentinel = (1 << NumParameterIndexBits) - 1 };
+
+ void setParameterIndex(unsigned parameterIndex) {
+ if (parameterIndex >= ParameterIndexSentinel) {
+ setParameterIndexLarge(parameterIndex);
+ return;
+ }
+
+ ParmVarDeclBits.ParameterIndex = parameterIndex;
+ assert(ParmVarDeclBits.ParameterIndex == parameterIndex && "truncation!");
+ }
+ unsigned getParameterIndex() const {
+ unsigned d = ParmVarDeclBits.ParameterIndex;
+ return d == ParameterIndexSentinel ? getParameterIndexLarge() : d;
+ }
+
+ void setParameterIndexLarge(unsigned parameterIndex);
+ unsigned getParameterIndexLarge() const;
+};
+
+/// 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
+/// getPreviousDecl() chain.
+class FunctionDecl : public DeclaratorDecl, public DeclContext,
+ public Redeclarable<FunctionDecl> {
+public:
+ /// \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;
+
+ /// DeclsInPrototypeScope - Array of pointers to NamedDecls for
+ /// decls defined in the function prototype that are not parameters. E.g.
+ /// 'enum Y' in 'void f(enum Y {AA} x) {}'.
+ ArrayRef<NamedDecl *> DeclsInPrototypeScope;
+
+ LazyDeclStmtPtr Body;
+
+ // FIXME: This can be packed into the bitfields in DeclContext.
+ // NOTE: VC++ packs bitfields poorly if the types differ.
+ unsigned SClass : 2;
+ unsigned IsInline : 1;
+ unsigned IsInlineSpecified : 1;
+ unsigned IsVirtualAsWritten : 1;
+ unsigned IsPure : 1;
+ unsigned HasInheritedPrototype : 1;
+ unsigned HasWrittenPrototype : 1;
+ unsigned IsDeleted : 1;
+ unsigned IsTrivial : 1; // sunk from CXXMethodDecl
+ unsigned IsDefaulted : 1; // sunk from CXXMethoDecl
+ unsigned IsExplicitlyDefaulted : 1; //sunk from CXXMethodDecl
+ unsigned HasImplicitReturnZero : 1;
+ unsigned IsLateTemplateParsed : 1;
+ unsigned IsConstexpr : 1;
+
+ /// \brief Indicates if the function uses __try.
+ unsigned UsesSEHTry : 1;
+
+ /// \brief Indicates if the function was a definition but its body was
+ /// skipped.
+ unsigned HasSkippedBody : 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, ArrayRef<ParmVarDecl *> NewParamInfo);
+
+protected:
+ FunctionDecl(Kind DK, ASTContext &C, DeclContext *DC, SourceLocation StartLoc,
+ const DeclarationNameInfo &NameInfo,
+ QualType T, TypeSourceInfo *TInfo,
+ StorageClass S, bool isInlineSpecified,
+ bool isConstexprSpecified)
+ : DeclaratorDecl(DK, DC, NameInfo.getLoc(), NameInfo.getName(), T, TInfo,
+ StartLoc),
+ DeclContext(DK),
+ redeclarable_base(C),
+ ParamInfo(nullptr), Body(),
+ SClass(S),
+ IsInline(isInlineSpecified), IsInlineSpecified(isInlineSpecified),
+ IsVirtualAsWritten(false), IsPure(false), HasInheritedPrototype(false),
+ HasWrittenPrototype(true), IsDeleted(false), IsTrivial(false),
+ IsDefaulted(false), IsExplicitlyDefaulted(false),
+ HasImplicitReturnZero(false), IsLateTemplateParsed(false),
+ IsConstexpr(isConstexprSpecified), UsesSEHTry(false),
+ HasSkippedBody(false), EndRangeLoc(NameInfo.getEndLoc()),
+ TemplateOrSpecialization(),
+ DNLoc(NameInfo.getInfo()) {}
+
+ typedef Redeclarable<FunctionDecl> redeclarable_base;
+ FunctionDecl *getNextRedeclarationImpl() override {
+ return getNextRedeclaration();
+ }
+ FunctionDecl *getPreviousDeclImpl() override {
+ return getPreviousDecl();
+ }
+ FunctionDecl *getMostRecentDeclImpl() override {
+ return getMostRecentDecl();
+ }
+
+public:
+ typedef redeclarable_base::redecl_range redecl_range;
+ typedef redeclarable_base::redecl_iterator redecl_iterator;
+ using redeclarable_base::redecls_begin;
+ using redeclarable_base::redecls_end;
+ using redeclarable_base::redecls;
+ using redeclarable_base::getPreviousDecl;
+ using redeclarable_base::getMostRecentDecl;
+ using redeclarable_base::isFirstDecl;
+
+ static FunctionDecl *Create(ASTContext &C, DeclContext *DC,
+ SourceLocation StartLoc, SourceLocation NLoc,
+ DeclarationName N, QualType T,
+ TypeSourceInfo *TInfo,
+ StorageClass SC,
+ bool isInlineSpecified = false,
+ bool hasWrittenPrototype = true,
+ bool isConstexprSpecified = false) {
+ DeclarationNameInfo NameInfo(N, NLoc);
+ return FunctionDecl::Create(C, DC, StartLoc, NameInfo, T, TInfo,
+ SC,
+ isInlineSpecified, hasWrittenPrototype,
+ isConstexprSpecified);
+ }
+
+ static FunctionDecl *Create(ASTContext &C, DeclContext *DC,
+ SourceLocation StartLoc,
+ const DeclarationNameInfo &NameInfo,
+ QualType T, TypeSourceInfo *TInfo,
+ StorageClass SC,
+ bool isInlineSpecified,
+ bool hasWrittenPrototype,
+ bool isConstexprSpecified = false);
+
+ static FunctionDecl *CreateDeserialized(ASTContext &C, unsigned ID);
+
+ DeclarationNameInfo getNameInfo() const {
+ return DeclarationNameInfo(getDeclName(), getLocation(), DNLoc);
+ }
+
+ void getNameForDiagnostic(raw_ostream &OS, const PrintingPolicy &Policy,
+ bool Qualified) const override;
+
+ void setRangeEnd(SourceLocation E) { EndRangeLoc = E; }
+
+ SourceRange getSourceRange() const override LLVM_READONLY;
+
+ /// \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;
+
+ bool hasBody() const override {
+ const FunctionDecl* Definition;
+ return hasBody(Definition);
+ }
+
+ /// hasTrivialBody - Returns whether the function has a trivial body that does
+ /// not require any specific codegen.
+ bool hasTrivialBody() const;
+
+ /// isDefined - Returns true if the function is defined at all, including
+ /// a deleted definition. Except for the behavior when the function is
+ /// deleted, behaves like hasBody.
+ bool isDefined(const FunctionDecl *&Definition) const;
+
+ virtual bool isDefined() const {
+ const FunctionDecl* Definition;
+ return isDefined(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;
+
+ Stmt *getBody() const override {
+ 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 isDefined. Note
+ /// that this returns false for a defaulted function unless that function
+ /// has been implicitly defined (possibly as deleted).
+ bool isThisDeclarationADefinition() const {
+ return IsDeleted || Body || IsLateTemplateParsed;
+ }
+
+ /// doesThisDeclarationHaveABody - Returns whether this specific
+ /// declaration of the function has a body - that is, if it is a non-
+ /// deleted definition.
+ bool doesThisDeclarationHaveABody() const {
+ return Body || IsLateTemplateParsed;
+ }
+
+ 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 templated function will be late parsed.
+ bool isLateTemplateParsed() const { return IsLateTemplateParsed; }
+ void setLateTemplateParsed(bool ILT = true) { IsLateTemplateParsed = ILT; }
+
+ /// 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 this function is defaulted per C++0x. Only valid for
+ /// special member functions.
+ bool isDefaulted() const { return IsDefaulted; }
+ void setDefaulted(bool D = true) { IsDefaulted = D; }
+
+ /// Whether this function is explicitly defaulted per C++0x. Only valid
+ /// for special member functions.
+ bool isExplicitlyDefaulted() const { return IsExplicitlyDefaulted; }
+ void setExplicitlyDefaulted(bool ED = true) { IsExplicitlyDefaulted = ED; }
+
+ /// 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; }
+
+ /// Whether this is a (C++11) constexpr function or constexpr constructor.
+ bool isConstexpr() const { return IsConstexpr; }
+ void setConstexpr(bool IC) { IsConstexpr = IC; }
+
+ /// \brief Indicates the function uses __try.
+ bool usesSEHTry() const { return UsesSEHTry; }
+ void setUsesSEHTry(bool UST) { UsesSEHTry = UST; }
+
+ /// \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
+ // If a function is deleted, its first declaration must be.
+ bool isDeleted() const { return getCanonicalDecl()->IsDeleted; }
+ bool isDeletedAsWritten() const { return IsDeleted && !IsDefaulted; }
+ void setDeletedAsWritten(bool D = true) { IsDeleted = D; }
+
+ /// \brief Determines whether this function is "main", which is the
+ /// entry point into an executable program.
+ bool isMain() const;
+
+ /// \brief Determines whether this function is a MSVCRT user defined entry
+ /// point.
+ bool isMSVCRTEntryPoint() const;
+
+ /// \brief Determines whether this operator new or delete is one
+ /// of the reserved global placement operators:
+ /// void *operator new(size_t, void *);
+ /// void *operator new[](size_t, void *);
+ /// void operator delete(void *, void *);
+ /// void operator delete[](void *, void *);
+ /// These functions have special behavior under [new.delete.placement]:
+ /// These functions are reserved, a C++ program may not define
+ /// functions that displace the versions in the Standard C++ library.
+ /// The provisions of [basic.stc.dynamic] do not apply to these
+ /// reserved placement forms of operator new and operator delete.
+ ///
+ /// This function must be an allocation or deallocation function.
+ bool isReservedGlobalPlacementOperator() const;
+
+ /// \brief Determines whether this function is one of the replaceable
+ /// global allocation functions:
+ /// void *operator new(size_t);
+ /// void *operator new(size_t, const std::nothrow_t &) noexcept;
+ /// void *operator new[](size_t);
+ /// void *operator new[](size_t, const std::nothrow_t &) noexcept;
+ /// void operator delete(void *) noexcept;
+ /// void operator delete(void *, std::size_t) noexcept; [C++1y]
+ /// void operator delete(void *, const std::nothrow_t &) noexcept;
+ /// void operator delete[](void *) noexcept;
+ /// void operator delete[](void *, std::size_t) noexcept; [C++1y]
+ /// void operator delete[](void *, const std::nothrow_t &) noexcept;
+ /// These functions have special behavior under C++1y [expr.new]:
+ /// An implementation is allowed to omit a call to a replaceable global
+ /// allocation function. [...]
+ bool isReplaceableGlobalAllocationFunction() const;
+
+ /// Compute the language linkage.
+ LanguageLinkage getLanguageLinkage() const;
+
+ /// \brief Determines whether this function is a function with
+ /// external, C linkage.
+ bool isExternC() const;
+
+ /// \brief Determines whether this function's context is, or is nested within,
+ /// a C++ extern "C" linkage spec.
+ bool isInExternCContext() const;
+
+ /// \brief Determines whether this function's context is, or is nested within,
+ /// a C++ extern "C++" linkage spec.
+ bool isInExternCXXContext() const;
+
+ /// \brief Determines whether this is a global function.
+ bool isGlobal() const;
+
+ /// \brief Determines whether this function is known to be 'noreturn', through
+ /// an attribute on its declaration or its type.
+ bool isNoReturn() const;
+
+ /// \brief True if the function was a definition but its body was skipped.
+ bool hasSkippedBody() const { return HasSkippedBody; }
+ void setHasSkippedBody(bool Skipped = true) { HasSkippedBody = Skipped; }
+
+ void setPreviousDeclaration(FunctionDecl * PrevDecl);
+
+ FunctionDecl *getCanonicalDecl() override;
+ const FunctionDecl *getCanonicalDecl() const {
+ return const_cast<FunctionDecl*>(this)->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;
+ typedef llvm::iterator_range<param_iterator> param_range;
+ typedef llvm::iterator_range<param_const_iterator> param_const_range;
+
+ param_iterator param_begin() { return param_iterator(ParamInfo); }
+ param_iterator param_end() {
+ return param_iterator(ParamInfo + param_size());
+ }
+ param_range params() { return param_range(param_begin(), param_end()); }
+
+ param_const_iterator param_begin() const {
+ return param_const_iterator(ParamInfo);
+ }
+ param_const_iterator param_end() const {
+ return param_const_iterator(ParamInfo + param_size());
+ }
+ param_const_range params() const {
+ return param_const_range(param_begin(), param_end());
+ }
+
+ /// 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(ArrayRef<ParmVarDecl *> NewParamInfo) {
+ setParams(getASTContext(), NewParamInfo);
+ }
+
+ // ArrayRef iterface to parameters.
+ // FIXME: Should one day replace iterator interface.
+ ArrayRef<ParmVarDecl*> parameters() const {
+ return llvm::makeArrayRef(ParamInfo, getNumParams());
+ }
+
+ ArrayRef<NamedDecl *> getDeclsInPrototypeScope() const {
+ return DeclsInPrototypeScope;
+ }
+ void setDeclsInPrototypeScope(ArrayRef<NamedDecl *> NewDecls);
+
+ /// 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 getReturnType() const {
+ return getType()->getAs<FunctionType>()->getReturnType();
+ }
+
+ /// \brief Attempt to compute an informative source range covering the
+ /// function return type. This may omit qualifiers and other information with
+ /// limited representation in the AST.
+ SourceRange getReturnTypeSourceRange() const;
+
+ /// \brief Determine the type of an expression that calls this function.
+ QualType getCallResultType() const {
+ return getType()->getAs<FunctionType>()->getCallResultType(getASTContext());
+ }
+
+ /// \brief Returns true if this function or its return type has the
+ /// warn_unused_result attribute. If the return type has the attribute and
+ /// this function is a method of the return type's class, then false will be
+ /// returned to avoid spurious warnings on member methods such as assignment
+ /// operators.
+ bool hasUnusedResultAttr() const;
+
+ /// \brief Returns the storage class as written in the source. For the
+ /// computed linkage of symbol, see getLinkage.
+ StorageClass getStorageClass() const { return StorageClass(SClass); }
+
+ /// \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 "constexpr" or is a member function of a class
+ /// that was defined in the class body.
+ bool isInlined() const { return IsInline; }
+
+ bool isInlineDefinitionExternallyVisible() const;
+
+ bool isMSExternInline() const;
+
+ bool doesDeclarationForceExternallyVisibleDefinition() 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;
+
+ void setDescribedFunctionTemplate(FunctionTemplateDecl *Template);
+
+ /// \brief Determine whether this function is a function template
+ /// specialization.
+ bool isFunctionTemplateSpecialization() const {
+ return getPrimaryTemplate() != nullptr;
+ }
+
+ /// \brief Retrieve the class scope template pattern that this function
+ /// template specialization is instantiated from.
+ FunctionDecl *getClassScopeSpecializationPattern() const;
+
+ /// \brief If this function is actually a function template specialization,
+ /// retrieve information about this function template specialization.
+ /// Otherwise, returns NULL.
+ FunctionTemplateSpecializationInfo *getTemplateSpecializationInfo() const;
+
+ /// \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 Determines if the given function was instantiated from a
+ /// function template.
+ bool isTemplateInstantiation() 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 ASTTemplateArgumentListInfo*
+ 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 = nullptr,
+ 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;
+
+ /// \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; otherwise, 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.
+ bool isOutOfLine() const override;
+
+ /// \brief Identify a memory copying or setting function.
+ /// If the given function is a memory copy or setting function, returns
+ /// the corresponding Builtin ID. If the function is not a memory function,
+ /// returns 0.
+ unsigned getMemoryFunctionKind() const;
+
+ // Implement isa/cast/dyncast/etc.
+ static bool classof(const Decl *D) { return classofKind(D->getKind()); }
+ 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, public Mergeable<FieldDecl> {
+ // FIXME: This can be packed into the bitfields in Decl.
+ bool Mutable : 1;
+ mutable unsigned CachedFieldIndex : 31;
+
+ /// The kinds of value we can store in InitializerOrBitWidth.
+ ///
+ /// Note that this is compatible with InClassInitStyle except for
+ /// ISK_CapturedVLAType.
+ enum InitStorageKind {
+ /// If the pointer is null, there's nothing special. Otherwise,
+ /// this is a bitfield and the pointer is the Expr* storing the
+ /// bit-width.
+ ISK_BitWidthOrNothing = (unsigned) ICIS_NoInit,
+
+ /// The pointer is an (optional due to delayed parsing) Expr*
+ /// holding the copy-initializer.
+ ISK_InClassCopyInit = (unsigned) ICIS_CopyInit,
+
+ /// The pointer is an (optional due to delayed parsing) Expr*
+ /// holding the list-initializer.
+ ISK_InClassListInit = (unsigned) ICIS_ListInit,
+
+ /// The pointer is a VariableArrayType* that's been captured;
+ /// the enclosing context is a lambda or captured statement.
+ ISK_CapturedVLAType,
+ };
+
+ /// \brief Storage for either the bit-width, the in-class
+ /// initializer, or the captured variable length array bound.
+ ///
+ /// We can safely combine these because in-class initializers are
+ /// not permitted for bit-fields, and both are exclusive with VLA
+ /// captures.
+ ///
+ /// If the storage kind is ISK_InClassCopyInit or
+ /// ISK_InClassListInit, but the initializer is null, then this
+ /// field has an in-class initializer which has not yet been parsed
+ /// and attached.
+ llvm::PointerIntPair<void *, 2, InitStorageKind> InitStorage;
+protected:
+ FieldDecl(Kind DK, DeclContext *DC, SourceLocation StartLoc,
+ SourceLocation IdLoc, IdentifierInfo *Id,
+ QualType T, TypeSourceInfo *TInfo, Expr *BW, bool Mutable,
+ InClassInitStyle InitStyle)
+ : DeclaratorDecl(DK, DC, IdLoc, Id, T, TInfo, StartLoc),
+ Mutable(Mutable), CachedFieldIndex(0),
+ InitStorage(BW, (InitStorageKind) InitStyle) {
+ assert((!BW || InitStyle == ICIS_NoInit) && "got initializer for bitfield");
+ }
+
+public:
+ static FieldDecl *Create(const ASTContext &C, DeclContext *DC,
+ SourceLocation StartLoc, SourceLocation IdLoc,
+ IdentifierInfo *Id, QualType T,
+ TypeSourceInfo *TInfo, Expr *BW, bool Mutable,
+ InClassInitStyle InitStyle);
+
+ static FieldDecl *CreateDeserialized(ASTContext &C, unsigned ID);
+
+ /// 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 Determines whether this field is a bitfield.
+ bool isBitField() const {
+ return InitStorage.getInt() == ISK_BitWidthOrNothing &&
+ InitStorage.getPointer() != nullptr;
+ }
+
+ /// @brief Determines whether this is an unnamed bitfield.
+ bool isUnnamedBitfield() const { return isBitField() && !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 isBitField()
+ ? static_cast<Expr *>(InitStorage.getPointer())
+ : nullptr;
+ }
+ unsigned getBitWidthValue(const ASTContext &Ctx) const;
+
+ /// setBitWidth - Set the bit-field width for this member.
+ // Note: used by some clients (i.e., do not remove it).
+ void setBitWidth(Expr *Width) {
+ assert(InitStorage.getInt() == ISK_BitWidthOrNothing &&
+ InitStorage.getPointer() == nullptr &&
+ "bit width, initializer or captured type already set");
+ InitStorage.setPointerAndInt(Width, ISK_BitWidthOrNothing);
+ }
+
+ /// removeBitWidth - Remove the bit-field width from this member.
+ // Note: used by some clients (i.e., do not remove it).
+ void removeBitWidth() {
+ assert(isBitField() && "no bitfield width to remove");
+ InitStorage.setPointerAndInt(nullptr, ISK_BitWidthOrNothing);
+ }
+
+ /// getInClassInitStyle - Get the kind of (C++11) in-class initializer which
+ /// this field has.
+ InClassInitStyle getInClassInitStyle() const {
+ InitStorageKind storageKind = InitStorage.getInt();
+ return (storageKind == ISK_CapturedVLAType
+ ? ICIS_NoInit : (InClassInitStyle) storageKind);
+ }
+
+ /// hasInClassInitializer - Determine whether this member has a C++11 in-class
+ /// initializer.
+ bool hasInClassInitializer() const {
+ return getInClassInitStyle() != ICIS_NoInit;
+ }
+
+ /// getInClassInitializer - Get the C++11 in-class initializer for this
+ /// member, or null if one has not been set. If a valid declaration has an
+ /// in-class initializer, but this returns null, then we have not parsed and
+ /// attached it yet.
+ Expr *getInClassInitializer() const {
+ return hasInClassInitializer()
+ ? static_cast<Expr *>(InitStorage.getPointer())
+ : nullptr;
+ }
+
+ /// setInClassInitializer - Set the C++11 in-class initializer for this
+ /// member.
+ void setInClassInitializer(Expr *Init) {
+ assert(hasInClassInitializer() &&
+ InitStorage.getPointer() == nullptr &&
+ "bit width, initializer or captured type already set");
+ InitStorage.setPointer(Init);
+ }
+
+ /// removeInClassInitializer - Remove the C++11 in-class initializer from this
+ /// member.
+ void removeInClassInitializer() {
+ assert(hasInClassInitializer() && "no initializer to remove");
+ InitStorage.setPointerAndInt(nullptr, ISK_BitWidthOrNothing);
+ }
+
+ /// \brief Determine whether this member captures the variable length array
+ /// type.
+ bool hasCapturedVLAType() const {
+ return InitStorage.getInt() == ISK_CapturedVLAType;
+ }
+
+ /// \brief Get the captured variable length array type.
+ const VariableArrayType *getCapturedVLAType() const {
+ return hasCapturedVLAType() ? static_cast<const VariableArrayType *>(
+ InitStorage.getPointer())
+ : nullptr;
+ }
+ /// \brief Set the captured variable length array type for this field.
+ void setCapturedVLAType(const VariableArrayType *VLAType);
+
+ /// 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());
+ }
+
+ SourceRange getSourceRange() const override LLVM_READONLY;
+
+ /// Retrieves the canonical declaration of this field.
+ FieldDecl *getCanonicalDecl() override { return getFirstDecl(); }
+ const FieldDecl *getCanonicalDecl() const { return getFirstDecl(); }
+
+ // Implement isa/cast/dyncast/etc.
+ static bool classof(const Decl *D) { return classofKind(D->getKind()); }
+ static bool classofKind(Kind K) { return K >= firstField && K <= lastField; }
+
+ friend class ASTDeclReader;
+ friend class ASTDeclWriter;
+};
+
+/// 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, public Mergeable<EnumConstantDecl> {
+ 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);
+ static EnumConstantDecl *CreateDeserialized(ASTContext &C, unsigned ID);
+
+ 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 override LLVM_READONLY;
+
+ /// Retrieves the canonical declaration of this enumerator.
+ EnumConstantDecl *getCanonicalDecl() override { return getFirstDecl(); }
+ const EnumConstantDecl *getCanonicalDecl() const { return getFirstDecl(); }
+
+ // Implement isa/cast/dyncast/etc.
+ static bool classof(const Decl *D) { return classofKind(D->getKind()); }
+ 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,
+ public Mergeable<IndirectFieldDecl> {
+ void anchor() override;
+ 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);
+
+ static IndirectFieldDecl *CreateDeserialized(ASTContext &C, unsigned ID);
+
+ typedef NamedDecl * const *chain_iterator;
+ typedef llvm::iterator_range<chain_iterator> chain_range;
+
+ chain_range chain() const { return chain_range(chain_begin(), chain_end()); }
+ chain_iterator chain_begin() const { return chain_iterator(Chaining); }
+ chain_iterator chain_end() const {
+ return chain_iterator(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());
+ }
+
+ IndirectFieldDecl *getCanonicalDecl() override { return getFirstDecl(); }
+ const IndirectFieldDecl *getCanonicalDecl() const { return getFirstDecl(); }
+
+ // Implement isa/cast/dyncast/etc.
+ static bool classof(const Decl *D) { return classofKind(D->getKind()); }
+ static bool classofKind(Kind K) { return K == IndirectField; }
+ friend class ASTDeclReader;
+};
+
+/// TypeDecl - Represents a declaration of a type.
+///
+class TypeDecl : public NamedDecl {
+ void anchor() override;
+ /// 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;
+ /// LocStart - The start of the source range for this declaration.
+ SourceLocation LocStart;
+ friend class ASTContext;
+
+protected:
+ TypeDecl(Kind DK, DeclContext *DC, SourceLocation L, IdentifierInfo *Id,
+ SourceLocation StartL = SourceLocation())
+ : NamedDecl(DK, DC, L, Id), TypeForDecl(nullptr), LocStart(StartL) {}
+
+public:
+ // Low-level accessor. If you just want the type defined by this node,
+ // check out ASTContext::getTypeDeclType or one of
+ // ASTContext::getTypedefType, ASTContext::getRecordType, etc. if you
+ // already know the specific kind of node this is.
+ const Type *getTypeForDecl() const { return TypeForDecl; }
+ void setTypeForDecl(const Type *TD) { TypeForDecl = TD; }
+
+ SourceLocation getLocStart() const LLVM_READONLY { return LocStart; }
+ void setLocStart(SourceLocation L) { LocStart = L; }
+ SourceRange getSourceRange() const override LLVM_READONLY {
+ if (LocStart.isValid())
+ return SourceRange(LocStart, getLocation());
+ else
+ return SourceRange(getLocation());
+ }
+
+ // Implement isa/cast/dyncast/etc.
+ static bool classof(const Decl *D) { return classofKind(D->getKind()); }
+ static bool classofKind(Kind K) { return K >= firstType && K <= lastType; }
+};
+
+
+/// Base class for declarations which introduce a typedef-name.
+class TypedefNameDecl : public TypeDecl, public Redeclarable<TypedefNameDecl> {
+ void anchor() override;
+ typedef std::pair<TypeSourceInfo*, QualType> ModedTInfo;
+ llvm::PointerUnion<TypeSourceInfo*, ModedTInfo*> MaybeModedTInfo;
+
+protected:
+ TypedefNameDecl(Kind DK, ASTContext &C, DeclContext *DC,
+ SourceLocation StartLoc, SourceLocation IdLoc,
+ IdentifierInfo *Id, TypeSourceInfo *TInfo)
+ : TypeDecl(DK, DC, IdLoc, Id, StartLoc), redeclarable_base(C),
+ MaybeModedTInfo(TInfo) {}
+
+ typedef Redeclarable<TypedefNameDecl> redeclarable_base;
+ TypedefNameDecl *getNextRedeclarationImpl() override {
+ return getNextRedeclaration();
+ }
+ TypedefNameDecl *getPreviousDeclImpl() override {
+ return getPreviousDecl();
+ }
+ TypedefNameDecl *getMostRecentDeclImpl() override {
+ return getMostRecentDecl();
+ }
+
+public:
+ typedef redeclarable_base::redecl_range redecl_range;
+ typedef redeclarable_base::redecl_iterator redecl_iterator;
+ using redeclarable_base::redecls_begin;
+ using redeclarable_base::redecls_end;
+ using redeclarable_base::redecls;
+ using redeclarable_base::getPreviousDecl;
+ using redeclarable_base::getMostRecentDecl;
+ using redeclarable_base::isFirstDecl;
+
+ bool isModed() const { return MaybeModedTInfo.is<ModedTInfo*>(); }
+
+ TypeSourceInfo *getTypeSourceInfo() const {
+ return isModed()
+ ? MaybeModedTInfo.get<ModedTInfo*>()->first
+ : MaybeModedTInfo.get<TypeSourceInfo*>();
+ }
+ QualType getUnderlyingType() const {
+ return isModed()
+ ? MaybeModedTInfo.get<ModedTInfo*>()->second
+ : MaybeModedTInfo.get<TypeSourceInfo*>()->getType();
+ }
+ void setTypeSourceInfo(TypeSourceInfo *newType) {
+ MaybeModedTInfo = newType;
+ }
+ void setModedTypeSourceInfo(TypeSourceInfo *unmodedTSI, QualType modedTy) {
+ MaybeModedTInfo = new (getASTContext()) ModedTInfo(unmodedTSI, modedTy);
+ }
+
+ /// Retrieves the canonical declaration of this typedef-name.
+ TypedefNameDecl *getCanonicalDecl() override { return getFirstDecl(); }
+ const TypedefNameDecl *getCanonicalDecl() const { return getFirstDecl(); }
+
+ /// Retrieves the tag declaration for which this is the typedef name for
+ /// linkage purposes, if any.
+ ///
+ /// \param AnyRedecl Look for the tag declaration in any redeclaration of
+ /// this typedef declaration.
+ TagDecl *getAnonDeclWithTypedefName(bool AnyRedecl = false) const;
+
+ // Implement isa/cast/dyncast/etc.
+ static bool classof(const Decl *D) { return classofKind(D->getKind()); }
+ static bool classofKind(Kind K) {
+ return K >= firstTypedefName && K <= lastTypedefName;
+ }
+};
+
+/// TypedefDecl - Represents the declaration of a typedef-name via the 'typedef'
+/// type specifier.
+class TypedefDecl : public TypedefNameDecl {
+ TypedefDecl(ASTContext &C, DeclContext *DC, SourceLocation StartLoc,
+ SourceLocation IdLoc, IdentifierInfo *Id, TypeSourceInfo *TInfo)
+ : TypedefNameDecl(Typedef, C, DC, StartLoc, IdLoc, Id, TInfo) {}
+
+public:
+ static TypedefDecl *Create(ASTContext &C, DeclContext *DC,
+ SourceLocation StartLoc, SourceLocation IdLoc,
+ IdentifierInfo *Id, TypeSourceInfo *TInfo);
+ static TypedefDecl *CreateDeserialized(ASTContext &C, unsigned ID);
+
+ SourceRange getSourceRange() const override LLVM_READONLY;
+
+ // Implement isa/cast/dyncast/etc.
+ static bool classof(const Decl *D) { return classofKind(D->getKind()); }
+ static bool classofKind(Kind K) { return K == Typedef; }
+};
+
+/// TypeAliasDecl - Represents the declaration of a typedef-name via a C++0x
+/// alias-declaration.
+class TypeAliasDecl : public TypedefNameDecl {
+ /// The template for which this is the pattern, if any.
+ TypeAliasTemplateDecl *Template;
+
+ TypeAliasDecl(ASTContext &C, DeclContext *DC, SourceLocation StartLoc,
+ SourceLocation IdLoc, IdentifierInfo *Id, TypeSourceInfo *TInfo)
+ : TypedefNameDecl(TypeAlias, C, DC, StartLoc, IdLoc, Id, TInfo),
+ Template(nullptr) {}
+
+public:
+ static TypeAliasDecl *Create(ASTContext &C, DeclContext *DC,
+ SourceLocation StartLoc, SourceLocation IdLoc,
+ IdentifierInfo *Id, TypeSourceInfo *TInfo);
+ static TypeAliasDecl *CreateDeserialized(ASTContext &C, unsigned ID);
+
+ SourceRange getSourceRange() const override LLVM_READONLY;
+
+ TypeAliasTemplateDecl *getDescribedAliasTemplate() const { return Template; }
+ void setDescribedAliasTemplate(TypeAliasTemplateDecl *TAT) { Template = TAT; }
+
+ // Implement isa/cast/dyncast/etc.
+ static bool classof(const Decl *D) { return classofKind(D->getKind()); }
+ static bool classofKind(Kind K) { return K == TypeAlias; }
+};
+
+/// 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 : 3;
+
+ /// IsCompleteDefinition - True if this is a definition ("struct foo
+ /// {};"), false if it is a declaration ("struct foo;"). It is not
+ /// a definition until the definition has been fully processed.
+ bool IsCompleteDefinition : 1;
+
+protected:
+ /// IsBeingDefined - True if this is currently being defined.
+ bool IsBeingDefined : 1;
+
+private:
+ /// 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;
+
+ /// \brief True if this tag is free standing, e.g. "struct foo;".
+ bool IsFreeStanding : 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++11 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++11, Microsoft extensions, or Objective C mode.
+ bool IsFixed : 1;
+
+ /// \brief Indicates whether it is possible for declarations of this kind
+ /// to have an out-of-date definition.
+ ///
+ /// This option is only enabled when modules are enabled.
+ bool MayHaveOutOfDateDef : 1;
+
+ /// Has the full definition of this type been required by a use somewhere in
+ /// the TU.
+ bool IsCompleteDefinitionRequired : 1;
+private:
+ SourceLocation RBraceLoc;
+
+ // A struct representing syntactic qualifier info,
+ // to be used for the (uncommon) case of out-of-line declarations.
+ typedef QualifierInfo ExtInfo;
+
+ /// \brief 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 or alias, it points to the TypedefNameDecl (used for mangling);
+ /// otherwise, if the tag declaration is anonymous and it is used as a
+ /// declaration specifier for variables, it points to the first VarDecl (used
+ /// for mangling);
+ /// otherwise, it is a null (TypedefNameDecl) pointer.
+ llvm::PointerUnion<TypedefNameDecl *, ExtInfo *> TypedefNameDeclOrQualifier;
+
+ bool hasExtInfo() const { return TypedefNameDeclOrQualifier.is<ExtInfo *>(); }
+ ExtInfo *getExtInfo() { return TypedefNameDeclOrQualifier.get<ExtInfo *>(); }
+ const ExtInfo *getExtInfo() const {
+ return TypedefNameDeclOrQualifier.get<ExtInfo *>();
+ }
+
+protected:
+ TagDecl(Kind DK, TagKind TK, const ASTContext &C, DeclContext *DC,
+ SourceLocation L, IdentifierInfo *Id, TagDecl *PrevDecl,
+ SourceLocation StartL)
+ : TypeDecl(DK, DC, L, Id, StartL), DeclContext(DK), redeclarable_base(C),
+ TagDeclKind(TK), IsCompleteDefinition(false), IsBeingDefined(false),
+ IsEmbeddedInDeclarator(false), IsFreeStanding(false),
+ IsCompleteDefinitionRequired(false),
+ TypedefNameDeclOrQualifier((TypedefNameDecl *)nullptr) {
+ assert((DK != Enum || TK == TTK_Enum) &&
+ "EnumDecl not matched with TTK_Enum");
+ setPreviousDecl(PrevDecl);
+ }
+
+ typedef Redeclarable<TagDecl> redeclarable_base;
+ TagDecl *getNextRedeclarationImpl() override {
+ return getNextRedeclaration();
+ }
+ TagDecl *getPreviousDeclImpl() override {
+ return getPreviousDecl();
+ }
+ TagDecl *getMostRecentDeclImpl() override {
+ return getMostRecentDecl();
+ }
+
+ /// @brief Completes the definition of this tag declaration.
+ ///
+ /// This is a helper function for derived classes.
+ void completeDefinition();
+
+public:
+ typedef redeclarable_base::redecl_range redecl_range;
+ typedef redeclarable_base::redecl_iterator redecl_iterator;
+ using redeclarable_base::redecls_begin;
+ using redeclarable_base::redecls_end;
+ using redeclarable_base::redecls;
+ using redeclarable_base::getPreviousDecl;
+ using redeclarable_base::getMostRecentDecl;
+ using redeclarable_base::isFirstDecl;
+
+ SourceLocation getRBraceLoc() const { return RBraceLoc; }
+ void setRBraceLoc(SourceLocation L) { RBraceLoc = L; }
+
+ /// getInnerLocStart - Return SourceLocation representing start of source
+ /// range ignoring outer template declarations.
+ SourceLocation getInnerLocStart() const { return getLocStart(); }
+
+ /// getOuterLocStart - Return SourceLocation representing start of source
+ /// range taking into account any outer template declarations.
+ SourceLocation getOuterLocStart() const;
+ SourceRange getSourceRange() const override LLVM_READONLY;
+
+ TagDecl *getCanonicalDecl() override;
+ const TagDecl *getCanonicalDecl() const {
+ return const_cast<TagDecl*>(this)->getCanonicalDecl();
+ }
+
+ /// isThisDeclarationADefinition() - Return true if this declaration
+ /// is a completion definition of the type. Provided for consistency.
+ bool isThisDeclarationADefinition() const {
+ return isCompleteDefinition();
+ }
+
+ /// isCompleteDefinition - Return true if this decl has its body
+ /// fully specified.
+ bool isCompleteDefinition() const {
+ return IsCompleteDefinition;
+ }
+
+ /// \brief Return true if this complete decl is
+ /// required to be complete for some existing use.
+ bool isCompleteDefinitionRequired() const {
+ return IsCompleteDefinitionRequired;
+ }
+
+ /// 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;
+ }
+
+ bool isFreeStanding() const { return IsFreeStanding; }
+ void setFreeStanding(bool isFreeStanding = true) {
+ IsFreeStanding = isFreeStanding;
+ }
+
+ /// \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 has a definition, 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 setCompleteDefinition(bool V) { IsCompleteDefinition = V; }
+
+ void setCompleteDefinitionRequired(bool V = true) {
+ IsCompleteDefinitionRequired = V;
+ }
+
+ StringRef 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 isInterface() const { return getTagKind() == TTK_Interface; }
+ bool isClass() const { return getTagKind() == TTK_Class; }
+ bool isUnion() const { return getTagKind() == TTK_Union; }
+ bool isEnum() const { return getTagKind() == TTK_Enum; }
+
+ /// Is this tag type named, either directly or via being defined in
+ /// a typedef of this type?
+ ///
+ /// C++11 [basic.link]p8:
+ /// A type is said to have linkage if and only if:
+ /// - it is a class or enumeration type that is named (or has a
+ /// name for linkage purposes) and the name has linkage; ...
+ /// C++11 [dcl.typedef]p9:
+ /// 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.
+ ///
+ /// C does not have an analogous rule, but the same concept is
+ /// nonetheless useful in some places.
+ bool hasNameForLinkage() const {
+ return (getDeclName() || getTypedefNameForAnonDecl());
+ }
+
+ TypedefNameDecl *getTypedefNameForAnonDecl() const {
+ return hasExtInfo() ? nullptr
+ : TypedefNameDeclOrQualifier.get<TypedefNameDecl *>();
+ }
+
+ void setTypedefNameForAnonDecl(TypedefNameDecl *TDD);
+
+ /// \brief Retrieve the nested-name-specifier that qualifies the name of this
+ /// declaration, if it was present in the source.
+ NestedNameSpecifier *getQualifier() const {
+ return hasExtInfo() ? getExtInfo()->QualifierLoc.getNestedNameSpecifier()
+ : nullptr;
+ }
+
+ /// \brief Retrieve the nested-name-specifier (with source-location
+ /// information) that qualifies the name of this declaration, if it was
+ /// present in the source.
+ NestedNameSpecifierLoc getQualifierLoc() const {
+ return hasExtInfo() ? getExtInfo()->QualifierLoc
+ : NestedNameSpecifierLoc();
+ }
+
+ void setQualifierInfo(NestedNameSpecifierLoc QualifierLoc);
+
+ unsigned getNumTemplateParameterLists() const {
+ return hasExtInfo() ? getExtInfo()->NumTemplParamLists : 0;
+ }
+ TemplateParameterList *getTemplateParameterList(unsigned i) const {
+ assert(i < getNumTemplateParameterLists());
+ return getExtInfo()->TemplParamLists[i];
+ }
+ void setTemplateParameterListsInfo(ASTContext &Context,
+ ArrayRef<TemplateParameterList *> TPLists);
+
+ // Implement isa/cast/dyncast/etc.
+ static bool classof(const Decl *D) { return classofKind(D->getKind()); }
+ 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. In C++11, enums can be forward-declared
+/// with a fixed underlying type, and in C we allow them to be forward-declared
+/// with no underlying type as an extension.
+class EnumDecl : public TagDecl {
+ void anchor() override;
+ /// 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 this enumeration is an instantiation of a member enumeration
+ /// of a class template specialization, this is the member specialization
+ /// information.
+ MemberSpecializationInfo *SpecializationInfo;
+
+ EnumDecl(ASTContext &C, DeclContext *DC, SourceLocation StartLoc,
+ SourceLocation IdLoc, IdentifierInfo *Id, EnumDecl *PrevDecl,
+ bool Scoped, bool ScopedUsingClassTag, bool Fixed)
+ : TagDecl(Enum, TTK_Enum, C, DC, IdLoc, Id, PrevDecl, StartLoc),
+ SpecializationInfo(nullptr) {
+ assert(Scoped || !ScopedUsingClassTag);
+ IntegerType = (const Type *)nullptr;
+ NumNegativeBits = 0;
+ NumPositiveBits = 0;
+ IsScoped = Scoped;
+ IsScopedUsingClassTag = ScopedUsingClassTag;
+ IsFixed = Fixed;
+ }
+
+ void setInstantiationOfMemberEnum(ASTContext &C, EnumDecl *ED,
+ TemplateSpecializationKind TSK);
+public:
+ EnumDecl *getCanonicalDecl() override {
+ return cast<EnumDecl>(TagDecl::getCanonicalDecl());
+ }
+ const EnumDecl *getCanonicalDecl() const {
+ return const_cast<EnumDecl*>(this)->getCanonicalDecl();
+ }
+
+ EnumDecl *getPreviousDecl() {
+ return cast_or_null<EnumDecl>(
+ static_cast<TagDecl *>(this)->getPreviousDecl());
+ }
+ const EnumDecl *getPreviousDecl() const {
+ return const_cast<EnumDecl*>(this)->getPreviousDecl();
+ }
+
+ EnumDecl *getMostRecentDecl() {
+ return cast<EnumDecl>(static_cast<TagDecl *>(this)->getMostRecentDecl());
+ }
+ const EnumDecl *getMostRecentDecl() const {
+ return const_cast<EnumDecl*>(this)->getMostRecentDecl();
+ }
+
+ EnumDecl *getDefinition() const {
+ return cast_or_null<EnumDecl>(TagDecl::getDefinition());
+ }
+
+ static EnumDecl *Create(ASTContext &C, DeclContext *DC,
+ SourceLocation StartLoc, SourceLocation IdLoc,
+ IdentifierInfo *Id, EnumDecl *PrevDecl,
+ bool IsScoped, bool IsScopedUsingClassTag,
+ bool IsFixed);
+ static EnumDecl *CreateDeserialized(ASTContext &C, unsigned ID);
+
+ /// 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;
+ typedef llvm::iterator_range<specific_decl_iterator<EnumConstantDecl>>
+ enumerator_range;
+
+ enumerator_range enumerators() const {
+ return enumerator_range(enumerator_begin(), enumerator_end());
+ }
+
+ enumerator_iterator enumerator_begin() const {
+ const EnumDecl *E = getDefinition();
+ if (!E)
+ E = this;
+ return enumerator_iterator(E->decls_begin());
+ }
+
+ enumerator_iterator enumerator_end() const {
+ const EnumDecl *E = 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 with no fixed
+ /// underlying type.
+ 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().getUnqualifiedType();
+ }
+
+ /// \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 Retrieve the source range that covers the underlying type if
+ /// specified.
+ SourceRange getIntegerTypeRange() const LLVM_READONLY;
+
+ /// \brief Returns the width in bits required 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 required 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++11 scoped enumeration.
+ bool isScoped() const {
+ return IsScoped;
+ }
+
+ /// \brief Returns true if this is a C++11 scoped enumeration.
+ bool isScopedUsingClassTag() const {
+ return IsScopedUsingClassTag;
+ }
+
+ /// \brief Returns true if this is an Objective-C, C++11, or
+ /// Microsoft-style enumeration with a fixed underlying type.
+ bool isFixed() const {
+ return IsFixed;
+ }
+
+ /// \brief Returns true if this can be considered a complete type.
+ bool isComplete() const {
+ return isCompleteDefinition() || 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;
+
+ /// \brief If this enumeration is a member of a specialization of a
+ /// templated class, determine what kind of template specialization
+ /// or instantiation this is.
+ TemplateSpecializationKind getTemplateSpecializationKind() const;
+
+ /// \brief For an enumeration member that was instantiated from a member
+ /// enumeration of a templated class, set the template specialiation kind.
+ void setTemplateSpecializationKind(TemplateSpecializationKind TSK,
+ SourceLocation PointOfInstantiation = SourceLocation());
+
+ /// \brief If this enumeration is an instantiation of a member enumeration of
+ /// a class template specialization, retrieves the member specialization
+ /// information.
+ MemberSpecializationInfo *getMemberSpecializationInfo() const {
+ return SpecializationInfo;
+ }
+
+ /// \brief Specify that this enumeration is an instantiation of the
+ /// member enumeration ED.
+ void setInstantiationOfMemberEnum(EnumDecl *ED,
+ TemplateSpecializationKind TSK) {
+ setInstantiationOfMemberEnum(getASTContext(), ED, TSK);
+ }
+
+ static bool classof(const Decl *D) { return classofKind(D->getKind()); }
+ 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 Objective-C object pointer type.
+ bool HasObjectMember : 1;
+
+ /// HasVolatileMember - This is true if struct has at least one member of
+ /// 'volatile' type.
+ bool HasVolatileMember : 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, const ASTContext &C, DeclContext *DC,
+ SourceLocation StartLoc, SourceLocation IdLoc,
+ IdentifierInfo *Id, RecordDecl *PrevDecl);
+
+public:
+ static RecordDecl *Create(const ASTContext &C, TagKind TK, DeclContext *DC,
+ SourceLocation StartLoc, SourceLocation IdLoc,
+ IdentifierInfo *Id, RecordDecl* PrevDecl = nullptr);
+ static RecordDecl *CreateDeserialized(const ASTContext &C, unsigned ID);
+
+ RecordDecl *getPreviousDecl() {
+ return cast_or_null<RecordDecl>(
+ static_cast<TagDecl *>(this)->getPreviousDecl());
+ }
+ const RecordDecl *getPreviousDecl() const {
+ return const_cast<RecordDecl*>(this)->getPreviousDecl();
+ }
+
+ RecordDecl *getMostRecentDecl() {
+ return cast<RecordDecl>(static_cast<TagDecl *>(this)->getMostRecentDecl());
+ }
+ const RecordDecl *getMostRecentDecl() const {
+ return const_cast<RecordDecl*>(this)->getMostRecentDecl();
+ }
+
+ 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; }
+
+ bool hasVolatileMember() const { return HasVolatileMember; }
+ void setHasVolatileMember (bool val) { HasVolatileMember = val; }
+
+ bool hasLoadedFieldsFromExternalStorage() const {
+ return LoadedFieldsFromExternalStorage;
+ }
+ void setHasLoadedFieldsFromExternalStorage(bool val) {
+ LoadedFieldsFromExternalStorage = 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;
+
+ /// \brief Determine whether this record is a class describing a lambda
+ /// function object.
+ bool isLambda() const;
+
+ /// \brief Determine whether this record is a record for captured variables in
+ /// CapturedStmt construct.
+ bool isCapturedRecord() const;
+ /// \brief Mark the record as a record for captured variables in CapturedStmt
+ /// construct.
+ void setCapturedRecord();
+
+ /// 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 'isCompleteDefinition'.
+ /// 'isCompleteDefinition' indicates whether or not a specific
+ /// RecordDecl is a completed definition, 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;
+ typedef llvm::iterator_range<specific_decl_iterator<FieldDecl>> field_range;
+
+ field_range fields() const { return field_range(field_begin(), field_end()); }
+ 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 classofKind(Kind K) {
+ return K >= firstRecord && K <= lastRecord;
+ }
+
+ /// isMsStrust - Get whether or not this is an ms_struct which can
+ /// be turned on with an attribute, pragma, or -mms-bitfields
+ /// commandline option.
+ bool isMsStruct(const ASTContext &C) const;
+
+ /// \brief Whether we are allowed to insert extra padding between fields.
+ /// These padding are added to help AddressSanitizer detect
+ /// intra-object-overflow bugs.
+ bool mayInsertExtraPadding(bool EmitRemark = false) const;
+
+ /// Finds the first data member which has a name.
+ /// nullptr is returned if no named data member exists.
+ const FieldDecl *findFirstNamedDataMember() const;
+
+private:
+ /// \brief Deserialize just the fields.
+ void LoadFieldsFromExternalStorage() const;
+};
+
+class FileScopeAsmDecl : public Decl {
+ virtual void anchor();
+ StringLiteral *AsmString;
+ SourceLocation RParenLoc;
+ FileScopeAsmDecl(DeclContext *DC, StringLiteral *asmstring,
+ SourceLocation StartL, SourceLocation EndL)
+ : Decl(FileScopeAsm, DC, StartL), AsmString(asmstring), RParenLoc(EndL) {}
+public:
+ static FileScopeAsmDecl *Create(ASTContext &C, DeclContext *DC,
+ StringLiteral *Str, SourceLocation AsmLoc,
+ SourceLocation RParenLoc);
+
+ static FileScopeAsmDecl *CreateDeserialized(ASTContext &C, unsigned ID);
+
+ SourceLocation getAsmLoc() const { return getLocation(); }
+ SourceLocation getRParenLoc() const { return RParenLoc; }
+ void setRParenLoc(SourceLocation L) { RParenLoc = L; }
+ SourceRange getSourceRange() const override LLVM_READONLY {
+ return SourceRange(getAsmLoc(), getRParenLoc());
+ }
+
+ 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 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 != nullptr; }
+ 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;
+ bool BlockMissingReturnType : 1;
+ bool IsConversionFromLambda : 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;
+
+ const Capture *Captures;
+ unsigned NumCaptures;
+
+ unsigned ManglingNumber;
+ Decl *ManglingContextDecl;
+
+protected:
+ BlockDecl(DeclContext *DC, SourceLocation CaretLoc)
+ : Decl(Block, DC, CaretLoc), DeclContext(Block),
+ IsVariadic(false), CapturesCXXThis(false),
+ BlockMissingReturnType(true), IsConversionFromLambda(false),
+ ParamInfo(nullptr), NumParams(0), Body(nullptr),
+ SignatureAsWritten(nullptr), Captures(nullptr), NumCaptures(0),
+ ManglingNumber(0), ManglingContextDecl(nullptr) {}
+
+public:
+ static BlockDecl *Create(ASTContext &C, DeclContext *DC, SourceLocation L);
+ static BlockDecl *CreateDeserialized(ASTContext &C, unsigned ID);
+
+ 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 override { 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;
+ typedef llvm::iterator_range<param_iterator> param_range;
+ typedef llvm::iterator_range<param_const_iterator> param_const_range;
+
+ // ArrayRef access to formal parameters.
+ // FIXME: Should eventual replace iterator access.
+ ArrayRef<ParmVarDecl*> parameters() const {
+ return llvm::makeArrayRef(ParamInfo, param_size());
+ }
+
+ bool param_empty() const { return NumParams == 0; }
+ param_range params() { return param_range(param_begin(), param_end()); }
+ param_iterator param_begin() { return param_iterator(ParamInfo); }
+ param_iterator param_end() {
+ return param_iterator(ParamInfo + param_size());
+ }
+
+ param_const_range params() const {
+ return param_const_range(param_begin(), param_end());
+ }
+ param_const_iterator param_begin() const {
+ return param_const_iterator(ParamInfo);
+ }
+ param_const_iterator param_end() const {
+ return param_const_iterator(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(ArrayRef<ParmVarDecl *> NewParamInfo);
+
+ /// 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;
+ typedef llvm::iterator_range<capture_iterator> capture_range;
+ typedef llvm::iterator_range<capture_const_iterator> capture_const_range;
+
+ capture_range captures() {
+ return capture_range(capture_begin(), capture_end());
+ }
+ capture_const_range captures() const {
+ return capture_const_range(capture_begin(), capture_end());
+ }
+
+ 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; }
+ bool blockMissingReturnType() const { return BlockMissingReturnType; }
+ void setBlockMissingReturnType(bool val) { BlockMissingReturnType = val; }
+
+ bool isConversionFromLambda() const { return IsConversionFromLambda; }
+ void setIsConversionFromLambda(bool val) { IsConversionFromLambda = val; }
+
+ bool capturesVariable(const VarDecl *var) const;
+
+ void setCaptures(ASTContext &Context, ArrayRef<Capture> Captures,
+ bool CapturesCXXThis);
+
+ unsigned getBlockManglingNumber() const {
+ return ManglingNumber;
+ }
+ Decl *getBlockManglingContextDecl() const {
+ return ManglingContextDecl;
+ }
+
+ void setBlockMangling(unsigned Number, Decl *Ctx) {
+ ManglingNumber = Number;
+ ManglingContextDecl = Ctx;
+ }
+
+ SourceRange getSourceRange() const override LLVM_READONLY;
+
+ // Implement isa/cast/dyncast/etc.
+ static bool classof(const Decl *D) { return classofKind(D->getKind()); }
+ 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));
+ }
+};
+
+/// \brief This represents the body of a CapturedStmt, and serves as its
+/// DeclContext.
+class CapturedDecl final
+ : public Decl,
+ public DeclContext,
+ private llvm::TrailingObjects<CapturedDecl, ImplicitParamDecl *> {
+protected:
+ size_t numTrailingObjects(OverloadToken<ImplicitParamDecl>) {
+ return NumParams;
+ }
+
+private:
+ /// \brief The number of parameters to the outlined function.
+ unsigned NumParams;
+ /// \brief The position of context parameter in list of parameters.
+ unsigned ContextParam;
+ /// \brief The body of the outlined function.
+ llvm::PointerIntPair<Stmt *, 1, bool> BodyAndNothrow;
+
+ explicit CapturedDecl(DeclContext *DC, unsigned NumParams);
+
+ ImplicitParamDecl *const *getParams() const {
+ return getTrailingObjects<ImplicitParamDecl *>();
+ }
+
+ ImplicitParamDecl **getParams() {
+ return getTrailingObjects<ImplicitParamDecl *>();
+ }
+
+public:
+ static CapturedDecl *Create(ASTContext &C, DeclContext *DC,
+ unsigned NumParams);
+ static CapturedDecl *CreateDeserialized(ASTContext &C, unsigned ID,
+ unsigned NumParams);
+
+ Stmt *getBody() const override;
+ void setBody(Stmt *B);
+
+ bool isNothrow() const;
+ void setNothrow(bool Nothrow = true);
+
+ unsigned getNumParams() const { return NumParams; }
+
+ ImplicitParamDecl *getParam(unsigned i) const {
+ assert(i < NumParams);
+ return getParams()[i];
+ }
+ void setParam(unsigned i, ImplicitParamDecl *P) {
+ assert(i < NumParams);
+ getParams()[i] = P;
+ }
+
+ /// \brief Retrieve the parameter containing captured variables.
+ ImplicitParamDecl *getContextParam() const {
+ assert(ContextParam < NumParams);
+ return getParam(ContextParam);
+ }
+ void setContextParam(unsigned i, ImplicitParamDecl *P) {
+ assert(i < NumParams);
+ ContextParam = i;
+ setParam(i, P);
+ }
+ unsigned getContextParamPosition() const { return ContextParam; }
+
+ typedef ImplicitParamDecl *const *param_iterator;
+ typedef llvm::iterator_range<param_iterator> param_range;
+
+ /// \brief Retrieve an iterator pointing to the first parameter decl.
+ param_iterator param_begin() const { return getParams(); }
+ /// \brief Retrieve an iterator one past the last parameter decl.
+ param_iterator param_end() const { return getParams() + NumParams; }
+
+ /// \brief Retrieve an iterator range for the parameter declarations.
+ param_range params() const { return param_range(param_begin(), param_end()); }
+
+ // Implement isa/cast/dyncast/etc.
+ static bool classof(const Decl *D) { return classofKind(D->getKind()); }
+ static bool classofKind(Kind K) { return K == Captured; }
+ static DeclContext *castToDeclContext(const CapturedDecl *D) {
+ return static_cast<DeclContext *>(const_cast<CapturedDecl *>(D));
+ }
+ static CapturedDecl *castFromDeclContext(const DeclContext *DC) {
+ return static_cast<CapturedDecl *>(const_cast<DeclContext *>(DC));
+ }
+
+ friend class ASTDeclReader;
+ friend class ASTDeclWriter;
+ friend TrailingObjects;
+};
+
+/// \brief Describes a module import declaration, which makes the contents
+/// of the named module visible in the current translation unit.
+///
+/// An import declaration imports the named module (or submodule). For example:
+/// \code
+/// @import std.vector;
+/// \endcode
+///
+/// Import declarations can also be implicitly generated from
+/// \#include/\#import directives.
+class ImportDecl final : public Decl,
+ llvm::TrailingObjects<ImportDecl, SourceLocation> {
+ /// \brief The imported module, along with a bit that indicates whether
+ /// we have source-location information for each identifier in the module
+ /// name.
+ ///
+ /// When the bit is false, we only have a single source location for the
+ /// end of the import declaration.
+ llvm::PointerIntPair<Module *, 1, bool> ImportedAndComplete;
+
+ /// \brief The next import in the list of imports local to the translation
+ /// unit being parsed (not loaded from an AST file).
+ ImportDecl *NextLocalImport;
+
+ friend class ASTReader;
+ friend class ASTDeclReader;
+ friend class ASTContext;
+ friend TrailingObjects;
+
+ ImportDecl(DeclContext *DC, SourceLocation StartLoc, Module *Imported,
+ ArrayRef<SourceLocation> IdentifierLocs);
+
+ ImportDecl(DeclContext *DC, SourceLocation StartLoc, Module *Imported,
+ SourceLocation EndLoc);
+
+ ImportDecl(EmptyShell Empty) : Decl(Import, Empty), NextLocalImport() { }
+
+public:
+ /// \brief Create a new module import declaration.
+ static ImportDecl *Create(ASTContext &C, DeclContext *DC,
+ SourceLocation StartLoc, Module *Imported,
+ ArrayRef<SourceLocation> IdentifierLocs);
+
+ /// \brief Create a new module import declaration for an implicitly-generated
+ /// import.
+ static ImportDecl *CreateImplicit(ASTContext &C, DeclContext *DC,
+ SourceLocation StartLoc, Module *Imported,
+ SourceLocation EndLoc);
+
+ /// \brief Create a new, deserialized module import declaration.
+ static ImportDecl *CreateDeserialized(ASTContext &C, unsigned ID,
+ unsigned NumLocations);
+
+ /// \brief Retrieve the module that was imported by the import declaration.
+ Module *getImportedModule() const { return ImportedAndComplete.getPointer(); }
+
+ /// \brief Retrieves the locations of each of the identifiers that make up
+ /// the complete module name in the import declaration.
+ ///
+ /// This will return an empty array if the locations of the individual
+ /// identifiers aren't available.
+ ArrayRef<SourceLocation> getIdentifierLocs() const;
+
+ SourceRange getSourceRange() const override LLVM_READONLY;
+
+ static bool classof(const Decl *D) { return classofKind(D->getKind()); }
+ static bool classofKind(Kind K) { return K == Import; }
+};
+
+/// \brief Represents an empty-declaration.
+class EmptyDecl : public Decl {
+ virtual void anchor();
+ EmptyDecl(DeclContext *DC, SourceLocation L)
+ : Decl(Empty, DC, L) { }
+
+public:
+ static EmptyDecl *Create(ASTContext &C, DeclContext *DC,
+ SourceLocation L);
+ static EmptyDecl *CreateDeserialized(ASTContext &C, unsigned ID);
+
+ static bool classof(const Decl *D) { return classofKind(D->getKind()); }
+ static bool classofKind(Kind K) { return K == Empty; }
+};
+
+/// Insertion operator for diagnostics. This allows sending NamedDecl's
+/// into a diagnostic with <<.
+inline const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB,
+ const NamedDecl* ND) {
+ DB.AddTaggedVal(reinterpret_cast<intptr_t>(ND),
+ DiagnosticsEngine::ak_nameddecl);
+ return DB;
+}
+inline const PartialDiagnostic &operator<<(const PartialDiagnostic &PD,
+ const NamedDecl* ND) {
+ PD.AddTaggedVal(reinterpret_cast<intptr_t>(ND),
+ DiagnosticsEngine::ak_nameddecl);
+ return PD;
+}
+
+template<typename decl_type>
+void Redeclarable<decl_type>::setPreviousDecl(decl_type *PrevDecl) {
+ // Note: This routine is implemented here because we need both NamedDecl
+ // and Redeclarable to be defined.
+ assert(RedeclLink.NextIsLatest() &&
+ "setPreviousDecl on a decl already in a redeclaration chain");
+
+ 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.
+ First = PrevDecl->getFirstDecl();
+ assert(First->RedeclLink.NextIsLatest() && "Expected first");
+ decl_type *MostRecent = First->getNextRedeclaration();
+ RedeclLink = PreviousDeclLink(cast<decl_type>(MostRecent));
+
+ // If the declaration was previously visible, a redeclaration of it remains
+ // visible even if it wouldn't be visible by itself.
+ static_cast<decl_type*>(this)->IdentifierNamespace |=
+ MostRecent->getIdentifierNamespace() &
+ (Decl::IDNS_Ordinary | Decl::IDNS_Tag | Decl::IDNS_Type);
+ } else {
+ // Make this first.
+ First = static_cast<decl_type*>(this);
+ }
+
+ // First one will point to this one as latest.
+ First->RedeclLink.setLatest(static_cast<decl_type*>(this));
+
+ assert(!isa<NamedDecl>(static_cast<decl_type*>(this)) ||
+ cast<NamedDecl>(static_cast<decl_type*>(this))->isLinkageValid());
+}
+
+// Inline function definitions.
+
+/// \brief Check if the given decl is complete.
+///
+/// We use this function to break a cycle between the inline definitions in
+/// Type.h and Decl.h.
+inline bool IsEnumDeclComplete(EnumDecl *ED) {
+ return ED->isComplete();
+}
+
+/// \brief Check if the given decl is scoped.
+///
+/// We use this function to break a cycle between the inline definitions in
+/// Type.h and Decl.h.
+inline bool IsEnumDeclScoped(EnumDecl *ED) {
+ return ED->isScoped();
+}
+
+} // 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..3c5056c
--- /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"
+#include "llvm/Support/DataTypes.h"
+
+namespace clang {
+
+class NamedDecl;
+
+/// A POD class for pairing a NamedDecl* with an access specifier.
+/// Can be put into unions.
+class DeclAccessPair {
+ uintptr_t 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 reinterpret_cast<NamedDecl*>(~Mask & Ptr);
+ }
+ AccessSpecifier getAccess() const {
+ return AccessSpecifier(Mask & Ptr);
+ }
+
+ void setDecl(NamedDecl *D) {
+ set(D, getAccess());
+ }
+ void setAccess(AccessSpecifier AS) {
+ set(getDecl(), AS);
+ }
+ void set(NamedDecl *D, AccessSpecifier AS) {
+ Ptr = 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..05b2a12
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/AST/DeclBase.h
@@ -0,0 +1,1904 @@
+//===-- 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/AttrIterator.h"
+#include "clang/AST/DeclarationName.h"
+#include "clang/Basic/Specifiers.h"
+#include "llvm/ADT/PointerUnion.h"
+#include "llvm/ADT/iterator.h"
+#include "llvm/ADT/iterator_range.h"
+#include "llvm/Support/Compiler.h"
+#include "llvm/Support/PrettyStackTrace.h"
+
+namespace clang {
+class ASTMutationListener;
+class BlockDecl;
+class CXXRecordDecl;
+class CompoundStmt;
+class DeclContext;
+class DeclarationName;
+class DependentDiagnostic;
+class EnumDecl;
+class FunctionDecl;
+class FunctionType;
+enum Linkage : unsigned char;
+class LinkageComputer;
+class LinkageSpecDecl;
+class Module;
+class NamedDecl;
+class NamespaceDecl;
+class ObjCCategoryDecl;
+class ObjCCategoryImplDecl;
+class ObjCContainerDecl;
+class ObjCImplDecl;
+class ObjCImplementationDecl;
+class ObjCInterfaceDecl;
+class ObjCMethodDecl;
+class ObjCProtocolDecl;
+struct PrintingPolicy;
+class RecordDecl;
+class Stmt;
+class StoredDeclsMap;
+class TranslationUnitDecl;
+class UsingDirectiveDecl;
+}
+
+namespace clang {
+
+ /// \brief Captures the result of checking the availability of a
+ /// declaration.
+ enum AvailabilityResult {
+ AR_Available = 0,
+ AR_NotYetIntroduced,
+ AR_Deprecated,
+ AR_Unavailable
+ };
+
+/// Decl - This represents one declaration (or definition), e.g. a variable,
+/// typedef, function, struct, etc.
+///
+/// Note: There are objects tacked on before the *beginning* of Decl
+/// (and its subclasses) in its Decl::operator new(). Proper alignment
+/// of all subclasses (not requiring more than DeclObjAlignment) is
+/// asserted in DeclBase.cpp.
+class Decl {
+public:
+ /// \brief Alignment guaranteed when allocating Decl and any subtypes.
+ enum { DeclObjAlignment = llvm::AlignOf<uint64_t>::Alignment };
+
+ /// \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,
+
+ /// This declaration is a function-local extern declaration of a
+ /// variable or function. This may also be IDNS_Ordinary if it
+ /// has been declared outside any function.
+ IDNS_LocalExtern = 0x0800
+ };
+
+ /// ObjCDeclQualifier - 'Qualifiers' written next to the return and
+ /// parameter types in method declarations. Other than remembering
+ /// them and mangling them into the method's signature string, these
+ /// are ignored by the compiler; they are consumed by certain
+ /// remote-messaging frameworks.
+ ///
+ /// in, inout, and out are mutually exclusive and apply only to
+ /// method parameters. bycopy and byref are mutually exclusive and
+ /// apply only to method parameters (?). oneway applies only to
+ /// results. All of these expect their corresponding parameter to
+ /// have a particular type. None of this is currently enforced by
+ /// clang.
+ ///
+ /// This should be kept in sync with ObjCDeclSpec::ObjCDeclQualifier.
+ 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,
+
+ /// The nullability qualifier is set when the nullability of the
+ /// result or parameter was expressed via a context-sensitive
+ /// keyword.
+ OBJC_TQ_CSNullability = 0x40
+ };
+
+protected:
+ // Enumeration values used in the bits stored in NextInContextAndBits.
+ enum {
+ /// \brief Whether this declaration is a top-level declaration (function,
+ /// global variable, etc.) that is lexically inside an objc container
+ /// definition.
+ TopLevelDeclInObjCContainerFlag = 0x01,
+
+ /// \brief Whether this declaration is private to the module in which it was
+ /// defined.
+ ModulePrivateFlag = 0x02
+ };
+
+ /// \brief The next declaration within the same lexical
+ /// DeclContext. These pointers form the linked list that is
+ /// traversed via DeclContext's decls_begin()/decls_end().
+ ///
+ /// The extra two bits are used for the TopLevelDeclInObjCContainer and
+ /// ModulePrivate bits.
+ llvm::PointerIntPair<Decl *, 2, unsigned> NextInContextAndBits;
+
+private:
+ 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;
+
+ /// \brief Whether this declaration was "referenced".
+ /// The difference with 'Used' is whether the reference appears in a
+ /// evaluated context or not, e.g. functions used in uninstantiated templates
+ /// are regarded as "referenced" but not "used".
+ unsigned Referenced : 1;
+
+ /// \brief Whether statistic collection is enabled.
+ static bool StatisticsEnabled;
+
+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;
+
+ /// \brief Whether this declaration was loaded from an AST file.
+ unsigned FromASTFile : 1;
+
+ /// \brief Whether this declaration is hidden from normal name lookup, e.g.,
+ /// because it is was loaded from an AST file is either module-private or
+ /// because its submodule has not been made visible.
+ unsigned Hidden : 1;
+
+ /// IdentifierNamespace - This specifies what IDNS_* namespace this lives in.
+ unsigned IdentifierNamespace : 12;
+
+ /// \brief If 0, we have not computed the linkage of this declaration.
+ /// Otherwise, it is the linkage + 1.
+ mutable unsigned CacheValidAndLinkage : 3;
+
+ friend class ASTDeclWriter;
+ friend class ASTDeclReader;
+ friend class ASTReader;
+ friend class LinkageComputer;
+
+ template<typename decl_type> friend class Redeclarable;
+
+ /// \brief Allocate memory for a deserialized declaration.
+ ///
+ /// This routine must be used to allocate memory for any declaration that is
+ /// deserialized from a module file.
+ ///
+ /// \param Size The size of the allocated object.
+ /// \param Ctx The context in which we will allocate memory.
+ /// \param ID The global ID of the deserialized declaration.
+ /// \param Extra The amount of extra space to allocate after the object.
+ void *operator new(std::size_t Size, const ASTContext &Ctx, unsigned ID,
+ std::size_t Extra = 0);
+
+ /// \brief Allocate memory for a non-deserialized declaration.
+ void *operator new(std::size_t Size, const ASTContext &Ctx,
+ DeclContext *Parent, std::size_t Extra = 0);
+
+private:
+ bool AccessDeclContextSanity() const;
+
+protected:
+
+ Decl(Kind DK, DeclContext *DC, SourceLocation L)
+ : NextInContextAndBits(), DeclCtx(DC),
+ Loc(L), DeclKind(DK), InvalidDecl(0),
+ HasAttrs(false), Implicit(false), Used(false), Referenced(false),
+ Access(AS_none), FromASTFile(0), Hidden(DC && cast<Decl>(DC)->Hidden),
+ IdentifierNamespace(getIdentifierNamespaceForKind(DK)),
+ CacheValidAndLinkage(0)
+ {
+ if (StatisticsEnabled) add(DK);
+ }
+
+ Decl(Kind DK, EmptyShell Empty)
+ : NextInContextAndBits(), DeclKind(DK), InvalidDecl(0),
+ HasAttrs(false), Implicit(false), Used(false), Referenced(false),
+ Access(AS_none), FromASTFile(0), Hidden(0),
+ IdentifierNamespace(getIdentifierNamespaceForKind(DK)),
+ CacheValidAndLinkage(0)
+ {
+ if (StatisticsEnabled) add(DK);
+ }
+
+ virtual ~Decl();
+
+ /// \brief Update a potentially out-of-date declaration.
+ void updateOutOfDate(IdentifierInfo &II) const;
+
+ Linkage getCachedLinkage() const {
+ return Linkage(CacheValidAndLinkage - 1);
+ }
+
+ void setCachedLinkage(Linkage L) const {
+ CacheValidAndLinkage = L + 1;
+ }
+
+ bool hasCachedLinkage() const {
+ return CacheValidAndLinkage;
+ }
+
+public:
+
+ /// \brief Source range that this declaration covers.
+ virtual SourceRange getSourceRange() const LLVM_READONLY {
+ return SourceRange(getLocation(), getLocation());
+ }
+ SourceLocation getLocStart() const LLVM_READONLY {
+ return getSourceRange().getBegin();
+ }
+ SourceLocation getLocEnd() const LLVM_READONLY {
+ 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 NextInContextAndBits.getPointer(); }
+ const Decl *getNextDeclInContext() const {return NextInContextAndBits.getPointer();}
+
+ DeclContext *getDeclContext() {
+ if (isInSemaDC())
+ return getSemanticDC();
+ return getMultipleDC()->SemanticDC;
+ }
+ const DeclContext *getDeclContext() const {
+ return const_cast<Decl*>(this)->getDeclContext();
+ }
+
+ /// Find the innermost non-closure ancestor of this declaration,
+ /// walking up through blocks, lambdas, etc. If that ancestor is
+ /// not a code context (!isFunctionOrMethod()), returns null.
+ ///
+ /// A declaration may be its own non-closure context.
+ Decl *getNonClosureContext();
+ const Decl *getNonClosureContext() const {
+ return const_cast<Decl*>(this)->getNonClosureContext();
+ }
+
+ TranslationUnitDecl *getTranslationUnitDecl();
+ const TranslationUnitDecl *getTranslationUnitDecl() const {
+ return const_cast<Decl*>(this)->getTranslationUnitDecl();
+ }
+
+ bool isInAnonymousNamespace() const;
+
+ bool isInStdNamespace() const;
+
+ ASTContext &getASTContext() const LLVM_READONLY;
+
+ void setAccess(AccessSpecifier AS) {
+ Access = AS;
+ assert(AccessDeclContextSanity());
+ }
+
+ AccessSpecifier getAccess() const {
+ assert(AccessDeclContextSanity());
+ return AccessSpecifier(Access);
+ }
+
+ /// \brief Retrieve the access specifier for this declaration, even though
+ /// it may not yet have been properly set.
+ AccessSpecifier getAccessUnsafe() const {
+ return AccessSpecifier(Access);
+ }
+
+ bool hasAttrs() const { return HasAttrs; }
+ void setAttrs(const AttrVec& Attrs) {
+ return setAttrsImpl(Attrs, getASTContext());
+ }
+ AttrVec &getAttrs() {
+ return const_cast<AttrVec&>(const_cast<const Decl*>(this)->getAttrs());
+ }
+ const AttrVec &getAttrs() const;
+ void dropAttrs();
+
+ void addAttr(Attr *A) {
+ if (hasAttrs())
+ getAttrs().push_back(A);
+ else
+ setAttrs(AttrVec(1, A));
+ }
+
+ typedef AttrVec::const_iterator attr_iterator;
+ typedef llvm::iterator_range<attr_iterator> attr_range;
+
+ attr_range attrs() const {
+ return attr_range(attr_begin(), attr_end());
+ }
+
+ attr_iterator attr_begin() const {
+ return hasAttrs() ? getAttrs().begin() : nullptr;
+ }
+ attr_iterator attr_end() const {
+ return hasAttrs() ? getAttrs().end() : nullptr;
+ }
+
+ template <typename T>
+ void dropAttr() {
+ if (!HasAttrs) return;
+
+ AttrVec &Vec = getAttrs();
+ Vec.erase(std::remove_if(Vec.begin(), Vec.end(), isa<T, Attr*>), Vec.end());
+
+ if (Vec.empty())
+ HasAttrs = false;
+ }
+
+ template <typename T>
+ llvm::iterator_range<specific_attr_iterator<T>> specific_attrs() const {
+ return llvm::make_range(specific_attr_begin<T>(), specific_attr_end<T>());
+ }
+
+ 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()) : nullptr;
+ }
+ 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;
+
+ /// 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;
+
+ /// \brief Set whether the declaration is used, in the sense of odr-use.
+ ///
+ /// This should only be used immediately after creating a declaration.
+ void setIsUsed() { Used = true; }
+
+ /// \brief Mark the declaration used, in the sense of odr-use.
+ ///
+ /// This notifies any mutation listeners in addition to setting a bit
+ /// indicating the declaration is used.
+ void markUsed(ASTContext &C);
+
+ /// \brief Whether any declaration of this entity was referenced.
+ bool isReferenced() const;
+
+ /// \brief Whether this declaration was referenced. This should not be relied
+ /// upon for anything other than debugging.
+ bool isThisDeclarationReferenced() const { return Referenced; }
+
+ void setReferenced(bool R = true) { Referenced = R; }
+
+ /// \brief Whether this declaration is a top-level declaration (function,
+ /// global variable, etc.) that is lexically inside an objc container
+ /// definition.
+ bool isTopLevelDeclInObjCContainer() const {
+ return NextInContextAndBits.getInt() & TopLevelDeclInObjCContainerFlag;
+ }
+
+ void setTopLevelDeclInObjCContainer(bool V = true) {
+ unsigned Bits = NextInContextAndBits.getInt();
+ if (V)
+ Bits |= TopLevelDeclInObjCContainerFlag;
+ else
+ Bits &= ~TopLevelDeclInObjCContainerFlag;
+ NextInContextAndBits.setInt(Bits);
+ }
+
+ /// \brief Whether this declaration was marked as being private to the
+ /// module in which it was defined.
+ bool isModulePrivate() const {
+ return NextInContextAndBits.getInt() & ModulePrivateFlag;
+ }
+
+protected:
+ /// \brief Specify whether this declaration was marked as being private
+ /// to the module in which it was defined.
+ void setModulePrivate(bool MP = true) {
+ unsigned Bits = NextInContextAndBits.getInt();
+ if (MP)
+ Bits |= ModulePrivateFlag;
+ else
+ Bits &= ~ModulePrivateFlag;
+ NextInContextAndBits.setInt(Bits);
+ }
+
+ /// \brief Set the owning module ID.
+ void setOwningModuleID(unsigned ID) {
+ assert(isFromASTFile() && "Only works on a deserialized declaration");
+ *((unsigned*)this - 2) = ID;
+ }
+
+public:
+
+ /// \brief Determine the availability of the given declaration.
+ ///
+ /// This routine will determine the most restrictive availability of
+ /// the given declaration (e.g., preferring 'unavailable' to
+ /// 'deprecated').
+ ///
+ /// \param Message If non-NULL and the result is not \c
+ /// AR_Available, will be set to a (possibly empty) message
+ /// describing why the declaration has not been introduced, is
+ /// deprecated, or is unavailable.
+ AvailabilityResult getAvailability(std::string *Message = nullptr) const;
+
+ /// \brief Determine whether this declaration is marked 'deprecated'.
+ ///
+ /// \param Message If non-NULL and the declaration is deprecated,
+ /// this will be set to the message describing why the declaration
+ /// was deprecated (which may be empty).
+ bool isDeprecated(std::string *Message = nullptr) const {
+ return getAvailability(Message) == AR_Deprecated;
+ }
+
+ /// \brief Determine whether this declaration is marked 'unavailable'.
+ ///
+ /// \param Message If non-NULL and the declaration is unavailable,
+ /// this will be set to the message describing why the declaration
+ /// was made unavailable (which may be empty).
+ bool isUnavailable(std::string *Message = nullptr) const {
+ return getAvailability(Message) == AR_Unavailable;
+ }
+
+ /// \brief Determine whether this is a weak-imported symbol.
+ ///
+ /// Weak-imported symbols are typically marked with the
+ /// 'weak_import' attribute, but may also be marked with an
+ /// 'availability' attribute where we're targing a platform prior to
+ /// the introduction of this feature.
+ bool isWeakImported() const;
+
+ /// \brief Determines whether this symbol can be weak-imported,
+ /// e.g., whether it would be well-formed to add the weak_import
+ /// attribute.
+ ///
+ /// \param IsDefinition Set to \c true to indicate that this
+ /// declaration cannot be weak-imported because it has a definition.
+ bool canBeWeakImported(bool &IsDefinition) const;
+
+ /// \brief Determine whether this declaration came from an AST file (such as
+ /// a precompiled header or module) rather than having been parsed.
+ bool isFromASTFile() const { return FromASTFile; }
+
+ /// \brief Retrieve the global declaration ID associated with this
+ /// declaration, which specifies where in the
+ unsigned getGlobalID() const {
+ if (isFromASTFile())
+ return *((const unsigned*)this - 1);
+ return 0;
+ }
+
+ /// \brief Retrieve the global ID of the module that owns this particular
+ /// declaration.
+ unsigned getOwningModuleID() const {
+ if (isFromASTFile())
+ return *((const unsigned*)this - 2);
+
+ return 0;
+ }
+
+private:
+ Module *getOwningModuleSlow() const;
+protected:
+ bool hasLocalOwningModuleStorage() const;
+
+public:
+ /// \brief Get the imported owning module, if this decl is from an imported
+ /// (non-local) module.
+ Module *getImportedOwningModule() const {
+ if (!isFromASTFile())
+ return nullptr;
+
+ return getOwningModuleSlow();
+ }
+
+ /// \brief Get the local owning module, if known. Returns nullptr if owner is
+ /// not yet known or declaration is not from a module.
+ Module *getLocalOwningModule() const {
+ if (isFromASTFile() || !Hidden)
+ return nullptr;
+ return reinterpret_cast<Module *const *>(this)[-1];
+ }
+ void setLocalOwningModule(Module *M) {
+ assert(!isFromASTFile() && Hidden && hasLocalOwningModuleStorage() &&
+ "should not have a cached owning module");
+ reinterpret_cast<Module **>(this)[-1] = M;
+ }
+
+ 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();
+ }
+
+ /// Determine whether this declaration is declared out of line (outside its
+ /// semantic context).
+ virtual bool isOutOfLine() const;
+
+ /// 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 {
+ return getParentFunctionOrMethod() == nullptr;
+ }
+
+ /// \brief Returns true if this declaration lexically is inside a function.
+ /// It recognizes non-defining declarations as well as members of local
+ /// classes:
+ /// \code
+ /// void foo() { void bar(); }
+ /// void foo2() { class ABC { void bar(); }; }
+ /// \endcode
+ bool isLexicallyWithinFunctionOrMethod() const;
+
+ /// \brief If this decl is defined inside a function/method/block it returns
+ /// the corresponding DeclContext, otherwise it returns null.
+ const DeclContext *getParentFunctionOrMethod() const;
+ DeclContext *getParentFunctionOrMethod() {
+ return const_cast<DeclContext*>(
+ const_cast<const Decl*>(this)->getParentFunctionOrMethod());
+ }
+
+ /// \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 *getNextRedeclarationImpl() { return this; }
+
+ /// \brief Implementation of getPreviousDecl(), to be overridden by any
+ /// subclass that has a redeclaration chain.
+ virtual Decl *getPreviousDeclImpl() { return nullptr; }
+
+ /// \brief Implementation of getMostRecentDecl(), to be overridden by any
+ /// subclass that has a redeclaration chain.
+ virtual Decl *getMostRecentDeclImpl() { 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 const value_type &reference;
+ typedef const value_type *pointer;
+ typedef std::forward_iterator_tag iterator_category;
+ typedef std::ptrdiff_t difference_type;
+
+ redecl_iterator() : Current(nullptr) { }
+ explicit redecl_iterator(Decl *C) : Current(C), Starter(C) { }
+
+ reference operator*() const { return Current; }
+ value_type 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->getNextRedeclarationImpl();
+ assert(Next && "Should return next redeclaration or itself, never null!");
+ Current = (Next != Starter) ? Next : nullptr;
+ 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;
+ }
+ };
+
+ typedef llvm::iterator_range<redecl_iterator> redecl_range;
+
+ /// \brief Returns an iterator range for all the redeclarations of the same
+ /// decl. It will iterate at least once (when this decl is the only one).
+ redecl_range redecls() const {
+ return redecl_range(redecls_begin(), redecls_end());
+ }
+
+ redecl_iterator redecls_begin() const {
+ return redecl_iterator(const_cast<Decl *>(this));
+ }
+ redecl_iterator redecls_end() const { return redecl_iterator(); }
+
+ /// \brief Retrieve the previous declaration that declares the same entity
+ /// as this declaration, or NULL if there is no previous declaration.
+ Decl *getPreviousDecl() { return getPreviousDeclImpl(); }
+
+ /// \brief Retrieve the most recent declaration that declares the same entity
+ /// as this declaration, or NULL if there is no previous declaration.
+ const Decl *getPreviousDecl() const {
+ return const_cast<Decl *>(this)->getPreviousDeclImpl();
+ }
+
+ /// \brief True if this is the first declaration in its redeclaration chain.
+ bool isFirstDecl() const {
+ return getPreviousDecl() == nullptr;
+ }
+
+ /// \brief Retrieve the most recent declaration that declares the same entity
+ /// as this declaration (which may be this declaration).
+ Decl *getMostRecentDecl() { return getMostRecentDeclImpl(); }
+
+ /// \brief Retrieve the most recent declaration that declares the same entity
+ /// as this declaration (which may be this declaration).
+ const Decl *getMostRecentDecl() const {
+ return const_cast<Decl *>(this)->getMostRecentDeclImpl();
+ }
+
+ /// 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 nullptr; }
+
+ /// \brief Returns true if this \c Decl represents a declaration for a body of
+ /// code, such as a function or method definition.
+ /// Note that \c hasBody can also return true if any redeclaration of this
+ /// \c Decl represents a declaration for a body of code.
+ virtual bool hasBody() const { return getBody() != nullptr; }
+
+ /// 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 void EnableStatistics();
+ 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 returns true if this declaration is a template
+ bool isTemplateDecl() const;
+
+ /// \brief Whether this declaration is a function or function template.
+ bool isFunctionOrFunctionTemplate() const {
+ return (DeclKind >= Decl::firstFunction &&
+ DeclKind <= Decl::lastFunction) ||
+ DeclKind == FunctionTemplate;
+ }
+
+ /// \brief Returns the function itself, or the templated function if this is a
+ /// function template.
+ FunctionDecl *getAsFunction() LLVM_READONLY;
+
+ const FunctionDecl *getAsFunction() const {
+ return const_cast<Decl *>(this)->getAsFunction();
+ }
+
+ /// \brief Changes the namespace of this declaration to reflect that it's
+ /// a function-local extern declaration.
+ ///
+ /// These declarations appear in the lexical context of the extern
+ /// declaration, but in the semantic context of the enclosing namespace
+ /// scope.
+ void setLocalExternDecl() {
+ assert((IdentifierNamespace == IDNS_Ordinary ||
+ IdentifierNamespace == IDNS_OrdinaryFriend) &&
+ "namespace is not ordinary");
+
+ Decl *Prev = getPreviousDecl();
+ IdentifierNamespace &= ~IDNS_Ordinary;
+
+ IdentifierNamespace |= IDNS_LocalExtern;
+ if (Prev && Prev->getIdentifierNamespace() & IDNS_Ordinary)
+ IdentifierNamespace |= IDNS_Ordinary;
+ }
+
+ /// \brief Determine whether this is a block-scope declaration with linkage.
+ /// This will either be a local variable declaration declared 'extern', or a
+ /// local function declaration.
+ bool isLocalExternDecl() {
+ return IdentifierNamespace & IDNS_LocalExtern;
+ }
+
+ /// \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 PerformFriendInjection = false) {
+ unsigned OldNS = IdentifierNamespace;
+ assert((OldNS & (IDNS_Tag | IDNS_Ordinary |
+ IDNS_TagFriend | IDNS_OrdinaryFriend |
+ IDNS_LocalExtern)) &&
+ "namespace includes neither ordinary nor tag");
+ assert(!(OldNS & ~(IDNS_Tag | IDNS_Ordinary | IDNS_Type |
+ IDNS_TagFriend | IDNS_OrdinaryFriend |
+ IDNS_LocalExtern)) &&
+ "namespace includes other than ordinary or tag");
+
+ Decl *Prev = getPreviousDecl();
+ IdentifierNamespace &= ~(IDNS_Ordinary | IDNS_Tag | IDNS_Type);
+
+ if (OldNS & (IDNS_Tag | IDNS_TagFriend)) {
+ IdentifierNamespace |= IDNS_TagFriend;
+ if (PerformFriendInjection ||
+ (Prev && Prev->getIdentifierNamespace() & IDNS_Tag))
+ IdentifierNamespace |= IDNS_Tag | IDNS_Type;
+ }
+
+ if (OldNS & (IDNS_Ordinary | IDNS_OrdinaryFriend | IDNS_LocalExtern)) {
+ IdentifierNamespace |= IDNS_OrdinaryFriend;
+ if (PerformFriendInjection ||
+ (Prev && Prev->getIdentifierNamespace() & IDNS_Ordinary))
+ 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;
+ }
+
+ static bool classofKind(Kind K) { return true; }
+ static DeclContext *castToDeclContext(const Decl *);
+ static Decl *castFromDeclContext(const DeclContext *);
+
+ void print(raw_ostream &Out, unsigned Indentation = 0,
+ bool PrintInstantiation = false) const;
+ void print(raw_ostream &Out, const PrintingPolicy &Policy,
+ unsigned Indentation = 0, bool PrintInstantiation = false) const;
+ static void printGroup(Decl** Begin, unsigned NumDecls,
+ raw_ostream &Out, const PrintingPolicy &Policy,
+ unsigned Indentation = 0);
+ // Debuggers don't usually respect default arguments.
+ void dump() const;
+ // Same as dump(), but forces color printing.
+ void dumpColor() const;
+ void dump(raw_ostream &Out) const;
+
+ /// \brief Looks through the Decl's underlying type to extract a FunctionType
+ /// when possible. Will return null if the type underlying the Decl does not
+ /// have a FunctionType.
+ const FunctionType *getFunctionType(bool BlocksToo = true) const;
+
+private:
+ void setAttrsImpl(const AttrVec& Attrs, ASTContext &Ctx);
+ void setDeclContextsImpl(DeclContext *SemaDC, DeclContext *LexicalDC,
+ ASTContext &Ctx);
+
+protected:
+ ASTMutationListener *getASTMutationListener() const;
+};
+
+/// \brief Determine whether two declarations declare the same entity.
+inline bool declaresSameEntity(const Decl *D1, const Decl *D2) {
+ if (!D1 || !D2)
+ return false;
+
+ if (D1 == D2)
+ return true;
+
+ return D1->getCanonicalDecl() == D2->getCanonicalDecl();
+}
+
+/// 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) {}
+
+ void print(raw_ostream &OS) const override;
+};
+
+/// \brief The results of name lookup within a DeclContext. This is either a
+/// single result (with no stable storage) or a collection of results (with
+/// stable storage provided by the lookup table).
+class DeclContextLookupResult {
+ typedef ArrayRef<NamedDecl *> ResultTy;
+ ResultTy Result;
+ // If there is only one lookup result, it would be invalidated by
+ // reallocations of the name table, so store it separately.
+ NamedDecl *Single;
+
+ static NamedDecl *const SingleElementDummyList;
+
+public:
+ DeclContextLookupResult() : Result(), Single() {}
+ DeclContextLookupResult(ArrayRef<NamedDecl *> Result)
+ : Result(Result), Single() {}
+ DeclContextLookupResult(NamedDecl *Single)
+ : Result(SingleElementDummyList), Single(Single) {}
+
+ class iterator;
+ typedef llvm::iterator_adaptor_base<iterator, ResultTy::iterator,
+ std::random_access_iterator_tag,
+ NamedDecl *const> IteratorBase;
+ class iterator : public IteratorBase {
+ value_type SingleElement;
+
+ public:
+ iterator() : IteratorBase(), SingleElement() {}
+ explicit iterator(pointer Pos, value_type Single = nullptr)
+ : IteratorBase(Pos), SingleElement(Single) {}
+
+ reference operator*() const {
+ return SingleElement ? SingleElement : IteratorBase::operator*();
+ }
+ };
+ typedef iterator const_iterator;
+ typedef iterator::pointer pointer;
+ typedef iterator::reference reference;
+
+ iterator begin() const { return iterator(Result.begin(), Single); }
+ iterator end() const { return iterator(Result.end(), Single); }
+
+ bool empty() const { return Result.empty(); }
+ pointer data() const { return Single ? &Single : Result.data(); }
+ size_t size() const { return Single ? 1 : Result.size(); }
+ reference front() const { return Single ? Single : Result.front(); }
+ reference back() const { return Single ? Single : Result.back(); }
+ reference operator[](size_t N) const { return Single ? Single : Result[N]; }
+
+ // FIXME: Remove this from the interface
+ DeclContextLookupResult slice(size_t N) const {
+ DeclContextLookupResult Sliced = Result.slice(N);
+ Sliced.Single = Single;
+ return Sliced;
+ }
+};
+
+/// 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 bool ExternalLexicalStorage : 1;
+
+ /// \brief Whether this declaration context also has some external
+ /// storage that contains additional declarations that are visible
+ /// in this context.
+ mutable bool ExternalVisibleStorage : 1;
+
+ /// \brief Whether this declaration context has had external visible
+ /// storage added since the last lookup. In this case, \c LookupPtr's
+ /// invariant may not hold and needs to be fixed before we perform
+ /// another lookup.
+ mutable bool NeedToReconcileExternalVisibleStorage : 1;
+
+ /// \brief If \c true, this context may have local lexical declarations
+ /// that are missing from the lookup table.
+ mutable bool HasLazyLocalLexicalLookups : 1;
+
+ /// \brief If \c true, the external source may have lexical declarations
+ /// that are missing from the lookup table.
+ mutable bool HasLazyExternalLexicalLookups : 1;
+
+ /// \brief If \c true, lookups should only return identifier from
+ /// DeclContext scope (for example TranslationUnit). Used in
+ /// LookupQualifiedName()
+ mutable bool UseQualifiedLookup : 1;
+
+ /// \brief Pointer to the data structure used to lookup declarations
+ /// within this context (or a DependentStoredDeclsMap if this is a
+ /// dependent context). We maintain the invariant that, if the map
+ /// contains an entry for a DeclarationName (and we haven't lazily
+ /// omitted anything), then it contains all relevant entries for that
+ /// name (modulo the hasExternalDecls() flag).
+ 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;
+ friend class ASTDeclReader;
+ friend class ASTWriter;
+
+ /// \brief Build up a chain of declarations.
+ ///
+ /// \returns the first/last pair of declarations.
+ static std::pair<Decl *, Decl *>
+ BuildDeclChain(ArrayRef<Decl*> Decls, bool FieldsAlreadyLoaded);
+
+ DeclContext(Decl::Kind K)
+ : DeclKind(K), ExternalLexicalStorage(false),
+ ExternalVisibleStorage(false),
+ NeedToReconcileExternalVisibleStorage(false),
+ HasLazyLocalLexicalLookups(false), HasLazyExternalLexicalLookups(false),
+ UseQualifiedLookup(false),
+ LookupPtr(nullptr), FirstDecl(nullptr), LastDecl(nullptr) {}
+
+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 isClosure() const {
+ return DeclKind == Decl::Block;
+ }
+
+ bool isObjCContainer() const {
+ switch (DeclKind) {
+ case Decl::ObjCCategory:
+ case Decl::ObjCCategoryImpl:
+ case Decl::ObjCImplementation:
+ case Decl::ObjCInterface:
+ case Decl::ObjCProtocol:
+ return true;
+ }
+ return false;
+ }
+
+ bool isFunctionOrMethod() const {
+ switch (DeclKind) {
+ case Decl::Block:
+ case Decl::Captured:
+ case Decl::ObjCMethod:
+ return true;
+ default:
+ return DeclKind >= Decl::firstFunction && DeclKind <= Decl::lastFunction;
+ }
+ }
+
+ /// \brief Test whether the context supports looking up names.
+ bool isLookupContext() const {
+ return !isFunctionOrMethod() && DeclKind != Decl::LinkageSpec;
+ }
+
+ 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 isStdNamespace() const;
+
+ 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 or some of its ancestors is a
+ /// linkage specification context that specifies C linkage.
+ bool isExternCContext() const;
+
+ /// \brief Determines whether this context or some of its ancestors is a
+ /// linkage specification context that specifies C++ linkage.
+ bool isExternCXXContext() 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;
+
+ /// \brief Find the nearest non-closure ancestor of this context,
+ /// i.e. the innermost semantic parent of this context which is not
+ /// a closure. A context may be its own non-closure ancestor.
+ Decl *getNonClosureAncestor();
+ const Decl *getNonClosureAncestor() const {
+ return const_cast<DeclContext*>(this)->getNonClosureAncestor();
+ }
+
+ /// 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 Retrieve the outermost lexically enclosing record context.
+ RecordDecl *getOuterLexicalRecordContext();
+ const RecordDecl *getOuterLexicalRecordContext() const {
+ return const_cast<DeclContext *>(this)->getOuterLexicalRecordContext();
+ }
+
+ /// \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;
+
+ /// \brief Collects all of the declaration contexts that are semantically
+ /// connected to this declaration context.
+ ///
+ /// For declaration contexts that have multiple semantically connected but
+ /// syntactically distinct contexts, such as C++ namespaces, this routine
+ /// retrieves the complete set of such declaration contexts in source order.
+ /// For example, given:
+ ///
+ /// \code
+ /// namespace N {
+ /// int x;
+ /// }
+ /// namespace N {
+ /// int y;
+ /// }
+ /// \endcode
+ ///
+ /// The \c Contexts parameter will contain both definitions of N.
+ ///
+ /// \param Contexts Will be cleared and set to the set of declaration
+ /// contexts that are semanticaly connected to this declaration context,
+ /// in source order, including this context (which may be the only result,
+ /// for non-namespace contexts).
+ void collectAllContexts(SmallVectorImpl<DeclContext *> &Contexts);
+
+ /// 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 const value_type &reference;
+ typedef const value_type *pointer;
+ typedef std::forward_iterator_tag iterator_category;
+ typedef std::ptrdiff_t difference_type;
+
+ decl_iterator() : Current(nullptr) { }
+ explicit decl_iterator(Decl *C) : Current(C) { }
+
+ reference operator*() const { return Current; }
+ // This doesn't meet the iterator requirements, but it's convenient
+ value_type 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;
+ }
+ };
+
+ typedef llvm::iterator_range<decl_iterator> decl_range;
+
+ /// decls_begin/decls_end - Iterate over the declarations stored in
+ /// this context.
+ decl_range decls() const { return decl_range(decls_begin(), decls_end()); }
+ decl_iterator decls_begin() const;
+ decl_iterator decls_end() const { return decl_iterator(); }
+ 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_range noload_decls() const {
+ return decl_range(noload_decls_begin(), noload_decls_end());
+ }
+ decl_iterator noload_decls_begin() const { return decl_iterator(FirstDecl); }
+ decl_iterator noload_decls_end() const { return decl_iterator(); }
+
+ /// 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;
+ // TODO: Add reference and pointer typedefs (with some appropriate proxy
+ // type) if we ever have a need for them.
+ typedef void reference;
+ typedef void 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();
+ }
+
+ value_type operator*() const { return cast<SpecificDecl>(*Current); }
+ // This doesn't meet the iterator requirements, but it's convenient
+ value_type operator->() const { return **this; }
+
+ 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;
+ // TODO: Add reference and pointer typedefs (with some appropriate proxy
+ // type) if we ever have a need for them.
+ typedef void reference;
+ typedef void pointer;
+ typedef std::iterator_traits<DeclContext::decl_iterator>::difference_type
+ difference_type;
+ typedef std::forward_iterator_tag iterator_category;
+
+ filtered_decl_iterator() : Current() { }
+
+ /// filtered_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();
+ }
+
+ value_type operator*() const { return cast<SpecificDecl>(*Current); }
+ value_type 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 into this context, but suppress
+ /// searches for external declarations with the same name.
+ ///
+ /// Although analogous in function to addDecl, this removes an
+ /// important check. This is only useful if the Decl is being
+ /// added in response to an external search; in all other cases,
+ /// addDecl() is the right function to use.
+ /// See the ASTImporter for use cases.
+ void addDeclInternal(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);
+
+ /// @brief Checks whether a declaration is in this context.
+ bool containsDecl(Decl *D) const;
+
+ typedef DeclContextLookupResult lookup_result;
+ typedef lookup_result::iterator lookup_iterator;
+
+ /// 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) const;
+
+ /// \brief Find the declarations with the given name that are visible
+ /// within this context; don't attempt to retrieve anything from an
+ /// external source.
+ lookup_result noload_lookup(DeclarationName Name);
+
+ /// \brief A simplistic name lookup mechanism that performs name lookup
+ /// into this declaration context without consulting the external source.
+ ///
+ /// This function should almost never be used, because it subverts the
+ /// usual relationship between a DeclContext and the external source.
+ /// See the ASTImporter for the (few, but important) use cases.
+ ///
+ /// FIXME: This is very inefficient; replace uses of it with uses of
+ /// noload_lookup.
+ void localUncachedLookup(DeclarationName Name,
+ SmallVectorImpl<NamedDecl *> &Results);
+
+ /// @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.
+ void makeDeclVisibleInContext(NamedDecl *D);
+
+ /// all_lookups_iterator - An iterator that provides a view over the results
+ /// of looking up every possible name.
+ class all_lookups_iterator;
+
+ typedef llvm::iterator_range<all_lookups_iterator> lookups_range;
+
+ lookups_range lookups() const;
+ lookups_range noload_lookups() const;
+
+ /// \brief Iterators over all possible lookups within this context.
+ all_lookups_iterator lookups_begin() const;
+ all_lookups_iterator lookups_end() const;
+
+ /// \brief Iterators over all possible lookups within this context that are
+ /// currently loaded; don't attempt to retrieve anything from an external
+ /// source.
+ all_lookups_iterator noload_lookups_begin() const;
+ all_lookups_iterator noload_lookups_end() const;
+
+ struct udir_iterator;
+ typedef llvm::iterator_adaptor_base<udir_iterator, lookup_iterator,
+ std::random_access_iterator_tag,
+ UsingDirectiveDecl *> udir_iterator_base;
+ struct udir_iterator : udir_iterator_base {
+ udir_iterator(lookup_iterator I) : udir_iterator_base(I) {}
+ UsingDirectiveDecl *operator*() const;
+ };
+
+ typedef llvm::iterator_range<udir_iterator> udir_range;
+
+ udir_range using_directives() const;
+
+ // These are all defined in DependentDiagnostic.h.
+ class ddiag_iterator;
+ typedef llvm::iterator_range<DeclContext::ddiag_iterator> ddiag_range;
+
+ inline ddiag_range ddiags() const;
+
+ // Low-level accessors
+
+ /// \brief Mark that there are external lexical declarations that we need
+ /// to include in our lookup table (and that are not available as external
+ /// visible lookups). These extra lookup results will be found by walking
+ /// the lexical declarations of this context. This should be used only if
+ /// setHasExternalLexicalStorage() has been called on any decl context for
+ /// which this is the primary context.
+ void setMustBuildLookupTable() {
+ assert(this == getPrimaryContext() &&
+ "should only be called on primary context");
+ HasLazyExternalLexicalLookups = true;
+ }
+
+ /// \brief Retrieve the internal representation of the lookup structure.
+ /// This may omit some names if we are lazily building the structure.
+ StoredDeclsMap *getLookupPtr() const { return LookupPtr; }
+
+ /// \brief Ensure the lookup structure is fully-built and return it.
+ StoredDeclsMap *buildLookup();
+
+ /// \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;
+ if (ES && LookupPtr)
+ NeedToReconcileExternalVisibleStorage = true;
+ }
+
+ /// \brief Determine whether the given declaration is stored in the list of
+ /// declarations lexically within this context.
+ bool isDeclInLexicalTraversal(const Decl *D) const {
+ return D && (D->NextInContextAndBits.getPointer() || D == FirstDecl ||
+ D == LastDecl);
+ }
+
+ bool setUseQualifiedLookup(bool use = true) {
+ bool old_value = UseQualifiedLookup;
+ UseQualifiedLookup = use;
+ return old_value;
+ }
+
+ bool shouldUseQualifiedLookup() const {
+ return UseQualifiedLookup;
+ }
+
+ static bool classof(const Decl *D);
+ static bool classof(const DeclContext *D) { return true; }
+
+ void dumpDeclContext() const;
+ void dumpLookups() const;
+ void dumpLookups(llvm::raw_ostream &OS, bool DumpDecls = false) const;
+
+private:
+ void reconcileExternalVisibleStorage() const;
+ bool LoadLexicalDeclsFromExternalStorage() const;
+
+ /// @brief Makes a declaration visible within this context, but
+ /// suppresses searches for external declarations with the same
+ /// name.
+ ///
+ /// Analogous to makeDeclVisibleInContext, but for the exclusive
+ /// use of addDeclInternal().
+ void makeDeclVisibleInContextInternal(NamedDecl *D);
+
+ friend class DependentDiagnostic;
+ StoredDeclsMap *CreateStoredDeclsMap(ASTContext &C) const;
+
+ void buildLookupImpl(DeclContext *DCtx, bool Internal);
+ void makeDeclVisibleInContextWithFlags(NamedDecl *D, bool Internal,
+ bool Rediscoverable);
+ void makeDeclVisibleInContextImpl(NamedDecl *D, bool Internal);
+};
+
+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 = ::std::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 <typename To>
+struct isa_impl<To, ::clang::DeclContext> {
+ static bool doit(const ::clang::DeclContext &Val) {
+ return To::classofKind(Val.getDeclKind());
+ }
+};
+
+/// 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..7c54901
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/AST/DeclCXX.h
@@ -0,0 +1,3249 @@
+//===-- 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.
+//
+//===----------------------------------------------------------------------===//
+///
+/// \file
+/// \brief Defines the C++ Decl subclasses, other than those for templates
+/// (found in DeclTemplate.h) and friends (in DeclFriend.h).
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_AST_DECLCXX_H
+#define LLVM_CLANG_AST_DECLCXX_H
+
+#include "clang/AST/ASTUnresolvedSet.h"
+#include "clang/AST/Attr.h"
+#include "clang/AST/Decl.h"
+#include "clang/AST/Expr.h"
+#include "clang/AST/LambdaCapture.h"
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/PointerIntPair.h"
+#include "llvm/Support/Compiler.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;
+class LambdaExpr;
+class UsingDecl;
+
+/// \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 {
+ // 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 {
+
+/// \brief Represents 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 {
+ virtual void anchor();
+ /// \brief 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:
+ /// \brief The location of the access specifier.
+ SourceLocation getAccessSpecifierLoc() const { return getLocation(); }
+ /// \brief Sets the location of the access specifier.
+ void setAccessSpecifierLoc(SourceLocation ASLoc) { setLocation(ASLoc); }
+
+ /// \brief The location of the colon following the access specifier.
+ SourceLocation getColonLoc() const { return ColonLoc; }
+ /// \brief Sets the location of the colon.
+ void setColonLoc(SourceLocation CLoc) { ColonLoc = CLoc; }
+
+ SourceRange getSourceRange() const override LLVM_READONLY {
+ return SourceRange(getAccessSpecifierLoc(), getColonLoc());
+ }
+
+ static AccessSpecDecl *Create(ASTContext &C, AccessSpecifier AS,
+ DeclContext *DC, SourceLocation ASLoc,
+ SourceLocation ColonLoc) {
+ return new (C, DC) AccessSpecDecl(AS, DC, ASLoc, ColonLoc);
+ }
+ static AccessSpecDecl *CreateDeserialized(ASTContext &C, unsigned ID);
+
+ // Implement isa/cast/dyncast/etc.
+ static bool classof(const Decl *D) { return classofKind(D->getKind()); }
+ static bool classofKind(Kind K) { return K == AccessSpec; }
+};
+
+
+/// \brief Represents 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 {
+ /// \brief 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;
+
+ /// \brief Whether this is a virtual base class or not.
+ bool Virtual : 1;
+
+ /// \brief 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;
+
+ /// \brief Access specifier as written in the source code (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;
+
+ /// \brief Whether the class contains a using declaration
+ /// to inherit the named class's constructors.
+ bool InheritConstructors : 1;
+
+ /// \brief 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 \c virtual or the 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) { }
+
+ /// \brief Retrieves the source range that contains the entire base specifier.
+ SourceRange getSourceRange() const LLVM_READONLY { return Range; }
+ SourceLocation getLocStart() const LLVM_READONLY { return Range.getBegin(); }
+ SourceLocation getLocEnd() const LLVM_READONLY { return Range.getEnd(); }
+
+ /// \brief 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;
+ }
+
+ /// \brief 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;
+ }
+
+ /// \brief 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;
+ }
+
+ /// \brief Retrieves the type of the base class.
+ ///
+ /// This type will always be an unqualified class type.
+ QualType getType() const {
+ return BaseTypeInfo->getType().getUnqualifiedType();
+ }
+
+ /// \brief Retrieves the type and source location of the base class.
+ TypeSourceInfo *getTypeSourceInfo() const { return BaseTypeInfo; }
+};
+
+/// \brief A lazy pointer to the definition data for a declaration.
+/// FIXME: This is a little CXXRecordDecl-specific that the moment.
+template<typename Decl, typename T> class LazyDefinitionDataPtr {
+ llvm::PointerUnion<T *, Decl *> DataOrCanonicalDecl;
+
+ LazyDefinitionDataPtr update() {
+ if (Decl *Canon = DataOrCanonicalDecl.template dyn_cast<Decl*>()) {
+ if (Canon->isCanonicalDecl())
+ Canon->getMostRecentDecl();
+ else
+ // Declaration isn't canonical any more;
+ // update it and perform path compression.
+ *this = Canon->getPreviousDecl()->DefinitionData.update();
+ }
+ return *this;
+ }
+
+public:
+ LazyDefinitionDataPtr(Decl *Canon) : DataOrCanonicalDecl(Canon) {}
+ LazyDefinitionDataPtr(T *Data) : DataOrCanonicalDecl(Data) {}
+ T *getNotUpdated() { return DataOrCanonicalDecl.template dyn_cast<T*>(); }
+ T *get() { return update().getNotUpdated(); }
+};
+
+/// \brief Represents a C++ struct/union/class.
+class CXXRecordDecl : public RecordDecl {
+
+ friend void TagDecl::startDefinition();
+
+ /// Values used in DefinitionData fields to represent special members.
+ enum SpecialMemberFlags {
+ SMF_DefaultConstructor = 0x1,
+ SMF_CopyConstructor = 0x2,
+ SMF_MoveConstructor = 0x4,
+ SMF_CopyAssignment = 0x8,
+ SMF_MoveAssignment = 0x10,
+ SMF_Destructor = 0x20,
+ SMF_All = 0x3f
+ };
+
+ struct DefinitionData {
+ DefinitionData(CXXRecordDecl *D);
+
+ /// \brief True if this class has any user-declared constructors.
+ bool UserDeclaredConstructor : 1;
+
+ /// \brief The user-declared special members which this class has.
+ unsigned UserDeclaredSpecialMembers : 6;
+
+ /// \brief True when this class is an aggregate.
+ bool Aggregate : 1;
+
+ /// \brief True when this class is a POD-type.
+ bool PlainOldData : 1;
+
+ /// 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;
+
+ /// \brief True when this class is polymorphic, i.e., has at
+ /// least one virtual member or derives from a polymorphic class.
+ bool Polymorphic : 1;
+
+ /// \brief 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;
+
+ /// \brief True when this class has standard layout.
+ ///
+ /// C++11 [class]p7. A standard-layout class is a class that:
+ /// * has no non-static data members of type non-standard-layout class (or
+ /// array of such types) or reference,
+ /// * has no virtual functions (10.3) and no virtual base classes (10.1),
+ /// * has the same access control (Clause 11) for all non-static data
+ /// members
+ /// * has no non-standard-layout base classes,
+ /// * either has no non-static data members in the most derived class and at
+ /// most one base class with non-static data members, or has no base
+ /// classes with non-static data members, and
+ /// * has no base classes of the same type as the first non-static data
+ /// member.
+ bool IsStandardLayout : 1;
+
+ /// \brief True when there are no non-empty base classes.
+ ///
+ /// This is a helper bit of state used to implement IsStandardLayout more
+ /// efficiently.
+ bool HasNoNonEmptyBases : 1;
+
+ /// \brief True when there are private non-static data members.
+ bool HasPrivateFields : 1;
+
+ /// \brief True when there are protected non-static data members.
+ bool HasProtectedFields : 1;
+
+ /// \brief True when there are private non-static data members.
+ bool HasPublicFields : 1;
+
+ /// \brief True if this class (or any subobject) has mutable fields.
+ bool HasMutableFields : 1;
+
+ /// \brief True if this class (or any nested anonymous struct or union)
+ /// has variant members.
+ bool HasVariantMembers : 1;
+
+ /// \brief True if there no non-field members declared by the user.
+ bool HasOnlyCMembers : 1;
+
+ /// \brief True if any field has an in-class initializer, including those
+ /// within anonymous unions or structs.
+ bool HasInClassInitializer : 1;
+
+ /// \brief True if any field is of reference type, and does not have an
+ /// in-class initializer.
+ ///
+ /// In this case, value-initialization of this class is illegal in C++98
+ /// even if the class has a trivial default constructor.
+ bool HasUninitializedReferenceMember : 1;
+
+ /// \brief These flags are \c true if a defaulted corresponding special
+ /// member can't be fully analyzed without performing overload resolution.
+ /// @{
+ bool NeedOverloadResolutionForMoveConstructor : 1;
+ bool NeedOverloadResolutionForMoveAssignment : 1;
+ bool NeedOverloadResolutionForDestructor : 1;
+ /// @}
+
+ /// \brief These flags are \c true if an implicit defaulted corresponding
+ /// special member would be defined as deleted.
+ /// @{
+ bool DefaultedMoveConstructorIsDeleted : 1;
+ bool DefaultedMoveAssignmentIsDeleted : 1;
+ bool DefaultedDestructorIsDeleted : 1;
+ /// @}
+
+ /// \brief The trivial special members which this class has, per
+ /// C++11 [class.ctor]p5, C++11 [class.copy]p12, C++11 [class.copy]p25,
+ /// C++11 [class.dtor]p5, or would have if the member were not suppressed.
+ ///
+ /// This excludes any user-declared but not user-provided special members
+ /// which have been declared but not yet defined.
+ unsigned HasTrivialSpecialMembers : 6;
+
+ /// \brief The declared special members of this class which are known to be
+ /// non-trivial.
+ ///
+ /// This excludes any user-declared but not user-provided special members
+ /// which have been declared but not yet defined, and any implicit special
+ /// members which have not yet been declared.
+ unsigned DeclaredNonTrivialSpecialMembers : 6;
+
+ /// \brief True when this class has a destructor with no semantic effect.
+ bool HasIrrelevantDestructor : 1;
+
+ /// \brief True when this class has at least one user-declared constexpr
+ /// constructor which is neither the copy nor move constructor.
+ bool HasConstexprNonCopyMoveConstructor : 1;
+
+ /// \brief True if a defaulted default constructor for this class would
+ /// be constexpr.
+ bool DefaultedDefaultConstructorIsConstexpr : 1;
+
+ /// \brief True if this class has a constexpr default constructor.
+ ///
+ /// This is true for either a user-declared constexpr default constructor
+ /// or an implicitly declared constexpr default constructor.
+ bool HasConstexprDefaultConstructor : 1;
+
+ /// \brief True when this class contains at least one non-static data
+ /// member or base class of non-literal or volatile type.
+ bool HasNonLiteralTypeFieldsOrBases : 1;
+
+ /// \brief True when visible conversion functions are already computed
+ /// and are available.
+ bool ComputedVisibleConversions : 1;
+
+ /// \brief Whether we have a C++11 user-provided default constructor (not
+ /// explicitly deleted or defaulted).
+ bool UserProvidedDefaultConstructor : 1;
+
+ /// \brief The special members which have been declared for this class,
+ /// either by the user or implicitly.
+ unsigned DeclaredSpecialMembers : 6;
+
+ /// \brief Whether an implicit copy constructor would have a const-qualified
+ /// parameter.
+ bool ImplicitCopyConstructorHasConstParam : 1;
+
+ /// \brief Whether an implicit copy assignment operator would have a
+ /// const-qualified parameter.
+ bool ImplicitCopyAssignmentHasConstParam : 1;
+
+ /// \brief Whether any declared copy constructor has a const-qualified
+ /// parameter.
+ bool HasDeclaredCopyConstructorWithConstParam : 1;
+
+ /// \brief Whether any declared copy assignment operator has either a
+ /// const-qualified reference parameter or a non-reference parameter.
+ bool HasDeclaredCopyAssignmentWithConstParam : 1;
+
+ /// \brief Whether this class describes a C++ lambda.
+ bool IsLambda : 1;
+
+ /// \brief Whether we are currently parsing base specifiers.
+ bool IsParsingBaseSpecifiers : 1;
+
+ /// \brief The number of base class specifiers in Bases.
+ unsigned NumBases;
+
+ /// \brief The number of virtual base class specifiers in VBases.
+ unsigned NumVBases;
+
+ /// \brief Base classes of this class.
+ ///
+ /// FIXME: This is wasted space for a union.
+ LazyCXXBaseSpecifiersPtr Bases;
+
+ /// \brief direct and indirect virtual base classes of this class.
+ LazyCXXBaseSpecifiersPtr VBases;
+
+ /// \brief The conversion functions of this C++ class (but not its
+ /// inherited conversion functions).
+ ///
+ /// Each of the entries in this overload set is a CXXConversionDecl.
+ LazyASTUnresolvedSet Conversions;
+
+ /// \brief 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.
+ LazyASTUnresolvedSet VisibleConversions;
+
+ /// \brief The declaration which defines this record.
+ CXXRecordDecl *Definition;
+
+ /// \brief The first friend declaration in this class, or null if there
+ /// aren't any.
+ ///
+ /// This is actually currently stored in reverse order.
+ LazyDeclPtr FirstFriend;
+
+ /// \brief Retrieve the set of direct base classes.
+ CXXBaseSpecifier *getBases() const {
+ if (!Bases.isOffset())
+ return Bases.get(nullptr);
+ return getBasesSlowCase();
+ }
+
+ /// \brief Retrieve the set of virtual base classes.
+ CXXBaseSpecifier *getVBases() const {
+ if (!VBases.isOffset())
+ return VBases.get(nullptr);
+ return getVBasesSlowCase();
+ }
+
+ private:
+ CXXBaseSpecifier *getBasesSlowCase() const;
+ CXXBaseSpecifier *getVBasesSlowCase() const;
+ };
+
+ typedef LazyDefinitionDataPtr<CXXRecordDecl, struct DefinitionData>
+ DefinitionDataPtr;
+ friend class LazyDefinitionDataPtr<CXXRecordDecl, struct DefinitionData>;
+
+ mutable DefinitionDataPtr DefinitionData;
+
+ /// \brief Describes a C++ closure type (generated by a lambda expression).
+ struct LambdaDefinitionData : public DefinitionData {
+ typedef LambdaCapture Capture;
+
+ LambdaDefinitionData(CXXRecordDecl *D, TypeSourceInfo *Info,
+ bool Dependent, bool IsGeneric,
+ LambdaCaptureDefault CaptureDefault)
+ : DefinitionData(D), Dependent(Dependent), IsGenericLambda(IsGeneric),
+ CaptureDefault(CaptureDefault), NumCaptures(0), NumExplicitCaptures(0),
+ ManglingNumber(0), ContextDecl(nullptr), Captures(nullptr),
+ MethodTyInfo(Info) {
+ IsLambda = true;
+
+ // C++11 [expr.prim.lambda]p3:
+ // This class type is neither an aggregate nor a literal type.
+ Aggregate = false;
+ PlainOldData = false;
+ HasNonLiteralTypeFieldsOrBases = true;
+ }
+
+ /// \brief Whether this lambda is known to be dependent, even if its
+ /// context isn't dependent.
+ ///
+ /// A lambda with a non-dependent context can be dependent if it occurs
+ /// within the default argument of a function template, because the
+ /// lambda will have been created with the enclosing context as its
+ /// declaration context, rather than function. This is an unfortunate
+ /// artifact of having to parse the default arguments before.
+ unsigned Dependent : 1;
+
+ /// \brief Whether this lambda is a generic lambda.
+ unsigned IsGenericLambda : 1;
+
+ /// \brief The Default Capture.
+ unsigned CaptureDefault : 2;
+
+ /// \brief The number of captures in this lambda is limited 2^NumCaptures.
+ unsigned NumCaptures : 15;
+
+ /// \brief The number of explicit captures in this lambda.
+ unsigned NumExplicitCaptures : 13;
+
+ /// \brief The number used to indicate this lambda expression for name
+ /// mangling in the Itanium C++ ABI.
+ unsigned ManglingNumber;
+
+ /// \brief The declaration that provides context for this lambda, if the
+ /// actual DeclContext does not suffice. This is used for lambdas that
+ /// occur within default arguments of function parameters within the class
+ /// or within a data member initializer.
+ Decl *ContextDecl;
+
+ /// \brief The list of captures, both explicit and implicit, for this
+ /// lambda.
+ Capture *Captures;
+
+ /// \brief The type of the call method.
+ TypeSourceInfo *MethodTyInfo;
+
+ };
+
+ struct DefinitionData &data() const {
+ auto *DD = DefinitionData.get();
+ assert(DD && "queried property of class with no definition");
+ return *DD;
+ }
+
+ struct LambdaDefinitionData &getLambdaData() const {
+ // No update required: a merged definition cannot change any lambda
+ // properties.
+ auto *DD = DefinitionData.getNotUpdated();
+ assert(DD && DD->IsLambda && "queried lambda property of non-lambda class");
+ return static_cast<LambdaDefinitionData&>(*DD);
+ }
+
+ /// \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;
+ friend class LambdaExpr;
+
+ /// \brief Called from setBases and addedMember to notify the class that a
+ /// direct or virtual base class or a member of class type has been added.
+ void addedClassSubobject(CXXRecordDecl *Base);
+
+ /// \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);
+
+ friend class ASTNodeImporter;
+
+ /// \brief Get the head of our list of friend declarations, possibly
+ /// deserializing the friends from an external AST source.
+ FriendDecl *getFirstFriend() const;
+
+protected:
+ CXXRecordDecl(Kind K, TagKind TK, const ASTContext &C, DeclContext *DC,
+ SourceLocation StartLoc, SourceLocation IdLoc,
+ IdentifierInfo *Id, CXXRecordDecl *PrevDecl);
+
+public:
+ /// \brief Iterator that traverses the base classes of a class.
+ typedef CXXBaseSpecifier* base_class_iterator;
+
+ /// \brief Iterator that traverses the base classes of a class.
+ typedef const CXXBaseSpecifier* base_class_const_iterator;
+
+ CXXRecordDecl *getCanonicalDecl() override {
+ return cast<CXXRecordDecl>(RecordDecl::getCanonicalDecl());
+ }
+ const CXXRecordDecl *getCanonicalDecl() const {
+ return const_cast<CXXRecordDecl*>(this)->getCanonicalDecl();
+ }
+
+ CXXRecordDecl *getPreviousDecl() {
+ return cast_or_null<CXXRecordDecl>(
+ static_cast<RecordDecl *>(this)->getPreviousDecl());
+ }
+ const CXXRecordDecl *getPreviousDecl() const {
+ return const_cast<CXXRecordDecl*>(this)->getPreviousDecl();
+ }
+
+ CXXRecordDecl *getMostRecentDecl() {
+ return cast<CXXRecordDecl>(
+ static_cast<RecordDecl *>(this)->getMostRecentDecl());
+ }
+
+ const CXXRecordDecl *getMostRecentDecl() const {
+ return const_cast<CXXRecordDecl*>(this)->getMostRecentDecl();
+ }
+
+ CXXRecordDecl *getDefinition() const {
+ auto *DD = DefinitionData.get();
+ return DD ? DD->Definition : nullptr;
+ }
+
+ bool hasDefinition() const { return DefinitionData.get(); }
+
+ static CXXRecordDecl *Create(const ASTContext &C, TagKind TK, DeclContext *DC,
+ SourceLocation StartLoc, SourceLocation IdLoc,
+ IdentifierInfo *Id,
+ CXXRecordDecl *PrevDecl = nullptr,
+ bool DelayTypeCreation = false);
+ static CXXRecordDecl *CreateLambda(const ASTContext &C, DeclContext *DC,
+ TypeSourceInfo *Info, SourceLocation Loc,
+ bool DependentLambda, bool IsGeneric,
+ LambdaCaptureDefault CaptureDefault);
+ static CXXRecordDecl *CreateDeserialized(const ASTContext &C, unsigned ID);
+
+ bool isDynamicClass() const {
+ return data().Polymorphic || data().NumVBases != 0;
+ }
+
+ void setIsParsingBaseSpecifiers() { data().IsParsingBaseSpecifiers = true; }
+
+ bool isParsingBaseSpecifiers() const {
+ return data().IsParsingBaseSpecifiers;
+ }
+
+ /// \brief Sets the base classes of this struct or class.
+ void setBases(CXXBaseSpecifier const * const *Bases, unsigned NumBases);
+
+ /// \brief Retrieves the number of base classes of this class.
+ unsigned getNumBases() const { return data().NumBases; }
+
+ typedef llvm::iterator_range<base_class_iterator> base_class_range;
+ typedef llvm::iterator_range<base_class_const_iterator>
+ base_class_const_range;
+
+ base_class_range bases() {
+ return base_class_range(bases_begin(), bases_end());
+ }
+ base_class_const_range bases() const {
+ return base_class_const_range(bases_begin(), bases_end());
+ }
+
+ 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;
+ }
+
+ /// \brief Retrieves the number of virtual base classes of this class.
+ unsigned getNumVBases() const { return data().NumVBases; }
+
+ base_class_range vbases() {
+ return base_class_range(vbases_begin(), vbases_end());
+ }
+ base_class_const_range vbases() const {
+ return base_class_const_range(vbases_begin(), vbases_end());
+ }
+
+ 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;
+ }
+
+ /// \brief Determine whether this class has any dependent base classes which
+ /// are not the current instantiation.
+ 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;
+ typedef llvm::iterator_range<specific_decl_iterator<CXXMethodDecl>>
+ method_range;
+
+ method_range methods() const {
+ return method_range(method_begin(), method_end());
+ }
+
+ /// \brief Method begin iterator. Iterates in the order the methods
+ /// were declared.
+ method_iterator method_begin() const {
+ return method_iterator(decls_begin());
+ }
+ /// \brief Method past-the-end iterator.
+ method_iterator method_end() const {
+ return method_iterator(decls_end());
+ }
+
+ /// Iterator access to constructor members.
+ typedef specific_decl_iterator<CXXConstructorDecl> ctor_iterator;
+ typedef llvm::iterator_range<specific_decl_iterator<CXXConstructorDecl>>
+ ctor_range;
+
+ ctor_range ctors() const { return ctor_range(ctor_begin(), ctor_end()); }
+
+ 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;
+ typedef llvm::iterator_range<friend_iterator> friend_range;
+
+ friend_range friends() const;
+ 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.isValid();
+ }
+
+ /// \brief \c true if we know for sure that this class has a single,
+ /// accessible, unambiguous move constructor that is not deleted.
+ bool hasSimpleMoveConstructor() const {
+ return !hasUserDeclaredMoveConstructor() && hasMoveConstructor() &&
+ !data().DefaultedMoveConstructorIsDeleted;
+ }
+ /// \brief \c true if we know for sure that this class has a single,
+ /// accessible, unambiguous move assignment operator that is not deleted.
+ bool hasSimpleMoveAssignment() const {
+ return !hasUserDeclaredMoveAssignment() && hasMoveAssignment() &&
+ !data().DefaultedMoveAssignmentIsDeleted;
+ }
+ /// \brief \c true if we know for sure that this class has an accessible
+ /// destructor that is not deleted.
+ bool hasSimpleDestructor() const {
+ return !hasUserDeclaredDestructor() &&
+ !data().DefaultedDestructorIsDeleted;
+ }
+
+ /// \brief Determine whether this class has any default constructors.
+ bool hasDefaultConstructor() const {
+ return (data().DeclaredSpecialMembers & SMF_DefaultConstructor) ||
+ needsImplicitDefaultConstructor();
+ }
+
+ /// \brief Determine if we need to declare a default constructor for
+ /// this class.
+ ///
+ /// This value is used for lazy creation of default constructors.
+ bool needsImplicitDefaultConstructor() const {
+ return !data().UserDeclaredConstructor &&
+ !(data().DeclaredSpecialMembers & SMF_DefaultConstructor) &&
+ // C++14 [expr.prim.lambda]p20:
+ // The closure type associated with a lambda-expression has no
+ // default constructor.
+ !isLambda();
+ }
+
+ /// \brief Determine whether this class has any user-declared constructors.
+ ///
+ /// When true, a default constructor will not be implicitly declared.
+ bool hasUserDeclaredConstructor() const {
+ return data().UserDeclaredConstructor;
+ }
+
+ /// \brief Whether this class has a user-provided default constructor
+ /// per C++11.
+ bool hasUserProvidedDefaultConstructor() const {
+ return data().UserProvidedDefaultConstructor;
+ }
+
+ /// \brief Determine whether this class has a user-declared copy constructor.
+ ///
+ /// When false, a copy constructor will be implicitly declared.
+ bool hasUserDeclaredCopyConstructor() const {
+ return data().UserDeclaredSpecialMembers & SMF_CopyConstructor;
+ }
+
+ /// \brief Determine whether this class needs an implicit copy
+ /// constructor to be lazily declared.
+ bool needsImplicitCopyConstructor() const {
+ return !(data().DeclaredSpecialMembers & SMF_CopyConstructor);
+ }
+
+ /// \brief Determine whether we need to eagerly declare a defaulted copy
+ /// constructor for this class.
+ bool needsOverloadResolutionForCopyConstructor() const {
+ return data().HasMutableFields;
+ }
+
+ /// \brief Determine whether an implicit copy constructor for this type
+ /// would have a parameter with a const-qualified reference type.
+ bool implicitCopyConstructorHasConstParam() const {
+ return data().ImplicitCopyConstructorHasConstParam;
+ }
+
+ /// \brief Determine whether this class has a copy constructor with
+ /// a parameter type which is a reference to a const-qualified type.
+ bool hasCopyConstructorWithConstParam() const {
+ return data().HasDeclaredCopyConstructorWithConstParam ||
+ (needsImplicitCopyConstructor() &&
+ implicitCopyConstructorHasConstParam());
+ }
+
+ /// \brief Whether this class has a user-declared move constructor or
+ /// assignment operator.
+ ///
+ /// When false, a move constructor and assignment operator may be
+ /// implicitly declared.
+ bool hasUserDeclaredMoveOperation() const {
+ return data().UserDeclaredSpecialMembers &
+ (SMF_MoveConstructor | SMF_MoveAssignment);
+ }
+
+ /// \brief Determine whether this class has had a move constructor
+ /// declared by the user.
+ bool hasUserDeclaredMoveConstructor() const {
+ return data().UserDeclaredSpecialMembers & SMF_MoveConstructor;
+ }
+
+ /// \brief Determine whether this class has a move constructor.
+ bool hasMoveConstructor() const {
+ return (data().DeclaredSpecialMembers & SMF_MoveConstructor) ||
+ needsImplicitMoveConstructor();
+ }
+
+ /// \brief Set that we attempted to declare an implicitly move
+ /// constructor, but overload resolution failed so we deleted it.
+ void setImplicitMoveConstructorIsDeleted() {
+ assert((data().DefaultedMoveConstructorIsDeleted ||
+ needsOverloadResolutionForMoveConstructor()) &&
+ "move constructor should not be deleted");
+ data().DefaultedMoveConstructorIsDeleted = true;
+ }
+
+ /// \brief Determine whether this class should get an implicit move
+ /// constructor or if any existing special member function inhibits this.
+ bool needsImplicitMoveConstructor() const {
+ return !(data().DeclaredSpecialMembers & SMF_MoveConstructor) &&
+ !hasUserDeclaredCopyConstructor() &&
+ !hasUserDeclaredCopyAssignment() &&
+ !hasUserDeclaredMoveAssignment() &&
+ !hasUserDeclaredDestructor();
+ }
+
+ /// \brief Determine whether we need to eagerly declare a defaulted move
+ /// constructor for this class.
+ bool needsOverloadResolutionForMoveConstructor() const {
+ return data().NeedOverloadResolutionForMoveConstructor;
+ }
+
+ /// \brief Determine 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().UserDeclaredSpecialMembers & SMF_CopyAssignment;
+ }
+
+ /// \brief Determine whether this class needs an implicit copy
+ /// assignment operator to be lazily declared.
+ bool needsImplicitCopyAssignment() const {
+ return !(data().DeclaredSpecialMembers & SMF_CopyAssignment);
+ }
+
+ /// \brief Determine whether we need to eagerly declare a defaulted copy
+ /// assignment operator for this class.
+ bool needsOverloadResolutionForCopyAssignment() const {
+ return data().HasMutableFields;
+ }
+
+ /// \brief Determine whether an implicit copy assignment operator for this
+ /// type would have a parameter with a const-qualified reference type.
+ bool implicitCopyAssignmentHasConstParam() const {
+ return data().ImplicitCopyAssignmentHasConstParam;
+ }
+
+ /// \brief Determine whether this class has a copy assignment operator with
+ /// a parameter type which is a reference to a const-qualified type or is not
+ /// a reference.
+ bool hasCopyAssignmentWithConstParam() const {
+ return data().HasDeclaredCopyAssignmentWithConstParam ||
+ (needsImplicitCopyAssignment() &&
+ implicitCopyAssignmentHasConstParam());
+ }
+
+ /// \brief Determine whether this class has had a move assignment
+ /// declared by the user.
+ bool hasUserDeclaredMoveAssignment() const {
+ return data().UserDeclaredSpecialMembers & SMF_MoveAssignment;
+ }
+
+ /// \brief Determine whether this class has a move assignment operator.
+ bool hasMoveAssignment() const {
+ return (data().DeclaredSpecialMembers & SMF_MoveAssignment) ||
+ needsImplicitMoveAssignment();
+ }
+
+ /// \brief Set that we attempted to declare an implicit move assignment
+ /// operator, but overload resolution failed so we deleted it.
+ void setImplicitMoveAssignmentIsDeleted() {
+ assert((data().DefaultedMoveAssignmentIsDeleted ||
+ needsOverloadResolutionForMoveAssignment()) &&
+ "move assignment should not be deleted");
+ data().DefaultedMoveAssignmentIsDeleted = true;
+ }
+
+ /// \brief Determine whether this class should get an implicit move
+ /// assignment operator or if any existing special member function inhibits
+ /// this.
+ bool needsImplicitMoveAssignment() const {
+ return !(data().DeclaredSpecialMembers & SMF_MoveAssignment) &&
+ !hasUserDeclaredCopyConstructor() &&
+ !hasUserDeclaredCopyAssignment() &&
+ !hasUserDeclaredMoveConstructor() &&
+ !hasUserDeclaredDestructor();
+ }
+
+ /// \brief Determine whether we need to eagerly declare a move assignment
+ /// operator for this class.
+ bool needsOverloadResolutionForMoveAssignment() const {
+ return data().NeedOverloadResolutionForMoveAssignment;
+ }
+
+ /// \brief Determine whether this class has a user-declared destructor.
+ ///
+ /// When false, a destructor will be implicitly declared.
+ bool hasUserDeclaredDestructor() const {
+ return data().UserDeclaredSpecialMembers & SMF_Destructor;
+ }
+
+ /// \brief Determine whether this class needs an implicit destructor to
+ /// be lazily declared.
+ bool needsImplicitDestructor() const {
+ return !(data().DeclaredSpecialMembers & SMF_Destructor);
+ }
+
+ /// \brief Determine whether we need to eagerly declare a destructor for this
+ /// class.
+ bool needsOverloadResolutionForDestructor() const {
+ return data().NeedOverloadResolutionForDestructor;
+ }
+
+ /// \brief Determine whether this class describes a lambda function object.
+ bool isLambda() const {
+ // An update record can't turn a non-lambda into a lambda.
+ auto *DD = DefinitionData.getNotUpdated();
+ return DD && DD->IsLambda;
+ }
+
+ /// \brief Determine whether this class describes a generic
+ /// lambda function object (i.e. function call operator is
+ /// a template).
+ bool isGenericLambda() const;
+
+ /// \brief Retrieve the lambda call operator of the closure type
+ /// if this is a closure type.
+ CXXMethodDecl *getLambdaCallOperator() const;
+
+ /// \brief Retrieve the lambda static invoker, the address of which
+ /// is returned by the conversion operator, and the body of which
+ /// is forwarded to the lambda call operator.
+ CXXMethodDecl *getLambdaStaticInvoker() const;
+
+ /// \brief Retrieve the generic lambda's template parameter list.
+ /// Returns null if the class does not represent a lambda or a generic
+ /// lambda.
+ TemplateParameterList *getGenericLambdaTemplateParameterList() const;
+
+ LambdaCaptureDefault getLambdaCaptureDefault() const {
+ assert(isLambda());
+ return static_cast<LambdaCaptureDefault>(getLambdaData().CaptureDefault);
+ }
+
+ /// \brief For a closure type, retrieve the mapping from captured
+ /// variables and \c this to the non-static data members that store the
+ /// values or references of the captures.
+ ///
+ /// \param Captures Will be populated with the mapping from captured
+ /// variables to the corresponding fields.
+ ///
+ /// \param ThisCapture Will be set to the field declaration for the
+ /// \c this capture.
+ ///
+ /// \note No entries will be added for init-captures, as they do not capture
+ /// variables.
+ void getCaptureFields(llvm::DenseMap<const VarDecl *, FieldDecl *> &Captures,
+ FieldDecl *&ThisCapture) const;
+
+ typedef const LambdaCapture *capture_const_iterator;
+ typedef llvm::iterator_range<capture_const_iterator> capture_const_range;
+
+ capture_const_range captures() const {
+ return capture_const_range(captures_begin(), captures_end());
+ }
+ capture_const_iterator captures_begin() const {
+ return isLambda() ? getLambdaData().Captures : nullptr;
+ }
+ capture_const_iterator captures_end() const {
+ return isLambda() ? captures_begin() + getLambdaData().NumCaptures
+ : nullptr;
+ }
+
+ typedef UnresolvedSetIterator conversion_iterator;
+ conversion_iterator conversion_begin() const {
+ return data().Conversions.get(getASTContext()).begin();
+ }
+ conversion_iterator conversion_end() const {
+ return data().Conversions.get(getASTContext()).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);
+
+ /// \brief Get all conversion functions visible in current class,
+ /// including conversion function templates.
+ llvm::iterator_range<conversion_iterator> getVisibleConversionFunctions();
+
+ /// Determine 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; }
+
+ /// \brief Whether this class has any in-class initializers
+ /// for non-static data members (including those in anonymous unions or
+ /// structs).
+ bool hasInClassInitializer() const { return data().HasInClassInitializer; }
+
+ /// \brief Whether this class or any of its subobjects has any members of
+ /// reference type which would make value-initialization ill-formed.
+ ///
+ /// Per C++03 [dcl.init]p5:
+ /// - if T is a non-union class type without a user-declared constructor,
+ /// then every non-static data member and base-class component of T is
+ /// value-initialized [...] A program that calls for [...]
+ /// value-initialization of an entity of reference type is ill-formed.
+ bool hasUninitializedReferenceMember() const {
+ return !isUnion() && !hasUserDeclaredConstructor() &&
+ data().HasUninitializedReferenceMember;
+ }
+
+ /// \brief Whether this class is a POD-type (C++ [class]p4)
+ ///
+ /// For purposes of this function a class is POD if it 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.
+ ///
+ /// Note that this is the C++ TR1 definition of POD.
+ bool isPOD() const { return data().PlainOldData; }
+
+ /// \brief True if this class is C-like, without C++-specific features, e.g.
+ /// it contains only public fields, no bases, tag kind is not 'class', etc.
+ bool isCLike() const;
+
+ /// \brief Determine whether this is an empty class in the sense of
+ /// (C++11 [meta.unary.prop]).
+ ///
+ /// A non-union class is empty iff it has a virtual function, virtual base,
+ /// data member (other than 0-width bit-field) or inherits from a non-empty
+ /// class.
+ ///
+ /// \note This does NOT include a check for union-ness.
+ bool isEmpty() const { return data().Empty; }
+
+ /// 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; }
+
+ /// \brief Determine whether this class has a pure virtual function.
+ ///
+ /// The class is is abstract per (C++ [class.abstract]p2) if it declares
+ /// a pure virtual function or inherits a pure virtual function that is
+ /// not overridden.
+ bool isAbstract() const { return data().Abstract; }
+
+ /// \brief Determine whether this class has standard layout per
+ /// (C++ [class]p7)
+ bool isStandardLayout() const { return data().IsStandardLayout; }
+
+ /// \brief Determine whether this class, or any of its class subobjects,
+ /// contains a mutable field.
+ bool hasMutableFields() const { return data().HasMutableFields; }
+
+ /// \brief Determine whether this class has any variant members.
+ bool hasVariantMembers() const { return data().HasVariantMembers; }
+
+ /// \brief Determine whether this class has a trivial default constructor
+ /// (C++11 [class.ctor]p5).
+ bool hasTrivialDefaultConstructor() const {
+ return hasDefaultConstructor() &&
+ (data().HasTrivialSpecialMembers & SMF_DefaultConstructor);
+ }
+
+ /// \brief Determine whether this class has a non-trivial default constructor
+ /// (C++11 [class.ctor]p5).
+ bool hasNonTrivialDefaultConstructor() const {
+ return (data().DeclaredNonTrivialSpecialMembers & SMF_DefaultConstructor) ||
+ (needsImplicitDefaultConstructor() &&
+ !(data().HasTrivialSpecialMembers & SMF_DefaultConstructor));
+ }
+
+ /// \brief Determine whether this class has at least one constexpr constructor
+ /// other than the copy or move constructors.
+ bool hasConstexprNonCopyMoveConstructor() const {
+ return data().HasConstexprNonCopyMoveConstructor ||
+ (needsImplicitDefaultConstructor() &&
+ defaultedDefaultConstructorIsConstexpr());
+ }
+
+ /// \brief Determine whether a defaulted default constructor for this class
+ /// would be constexpr.
+ bool defaultedDefaultConstructorIsConstexpr() const {
+ return data().DefaultedDefaultConstructorIsConstexpr &&
+ (!isUnion() || hasInClassInitializer() || !hasVariantMembers());
+ }
+
+ /// \brief Determine whether this class has a constexpr default constructor.
+ bool hasConstexprDefaultConstructor() const {
+ return data().HasConstexprDefaultConstructor ||
+ (needsImplicitDefaultConstructor() &&
+ defaultedDefaultConstructorIsConstexpr());
+ }
+
+ /// \brief Determine whether this class has a trivial copy constructor
+ /// (C++ [class.copy]p6, C++11 [class.copy]p12)
+ bool hasTrivialCopyConstructor() const {
+ return data().HasTrivialSpecialMembers & SMF_CopyConstructor;
+ }
+
+ /// \brief Determine whether this class has a non-trivial copy constructor
+ /// (C++ [class.copy]p6, C++11 [class.copy]p12)
+ bool hasNonTrivialCopyConstructor() const {
+ return data().DeclaredNonTrivialSpecialMembers & SMF_CopyConstructor ||
+ !hasTrivialCopyConstructor();
+ }
+
+ /// \brief Determine whether this class has a trivial move constructor
+ /// (C++11 [class.copy]p12)
+ bool hasTrivialMoveConstructor() const {
+ return hasMoveConstructor() &&
+ (data().HasTrivialSpecialMembers & SMF_MoveConstructor);
+ }
+
+ /// \brief Determine whether this class has a non-trivial move constructor
+ /// (C++11 [class.copy]p12)
+ bool hasNonTrivialMoveConstructor() const {
+ return (data().DeclaredNonTrivialSpecialMembers & SMF_MoveConstructor) ||
+ (needsImplicitMoveConstructor() &&
+ !(data().HasTrivialSpecialMembers & SMF_MoveConstructor));
+ }
+
+ /// \brief Determine whether this class has a trivial copy assignment operator
+ /// (C++ [class.copy]p11, C++11 [class.copy]p25)
+ bool hasTrivialCopyAssignment() const {
+ return data().HasTrivialSpecialMembers & SMF_CopyAssignment;
+ }
+
+ /// \brief Determine whether this class has a non-trivial copy assignment
+ /// operator (C++ [class.copy]p11, C++11 [class.copy]p25)
+ bool hasNonTrivialCopyAssignment() const {
+ return data().DeclaredNonTrivialSpecialMembers & SMF_CopyAssignment ||
+ !hasTrivialCopyAssignment();
+ }
+
+ /// \brief Determine whether this class has a trivial move assignment operator
+ /// (C++11 [class.copy]p25)
+ bool hasTrivialMoveAssignment() const {
+ return hasMoveAssignment() &&
+ (data().HasTrivialSpecialMembers & SMF_MoveAssignment);
+ }
+
+ /// \brief Determine whether this class has a non-trivial move assignment
+ /// operator (C++11 [class.copy]p25)
+ bool hasNonTrivialMoveAssignment() const {
+ return (data().DeclaredNonTrivialSpecialMembers & SMF_MoveAssignment) ||
+ (needsImplicitMoveAssignment() &&
+ !(data().HasTrivialSpecialMembers & SMF_MoveAssignment));
+ }
+
+ /// \brief Determine whether this class has a trivial destructor
+ /// (C++ [class.dtor]p3)
+ bool hasTrivialDestructor() const {
+ return data().HasTrivialSpecialMembers & SMF_Destructor;
+ }
+
+ /// \brief Determine whether this class has a non-trivial destructor
+ /// (C++ [class.dtor]p3)
+ bool hasNonTrivialDestructor() const {
+ return !(data().HasTrivialSpecialMembers & SMF_Destructor);
+ }
+
+ /// \brief Determine whether this class has a destructor which has no
+ /// semantic effect.
+ ///
+ /// Any such destructor will be trivial, public, defaulted and not deleted,
+ /// and will call only irrelevant destructors.
+ bool hasIrrelevantDestructor() const {
+ return data().HasIrrelevantDestructor;
+ }
+
+ /// \brief Determine whether this class has a non-literal or/ volatile type
+ /// non-static data member or base class.
+ bool hasNonLiteralTypeFieldsOrBases() const {
+ return data().HasNonLiteralTypeFieldsOrBases;
+ }
+
+ /// \brief Determine whether this class is considered trivially copyable per
+ /// (C++11 [class]p6).
+ bool isTriviallyCopyable() const;
+
+ /// \brief Determine whether this class is considered trivial.
+ ///
+ /// C++11 [class]p6:
+ /// "A trivial class is a class that has a trivial default constructor and
+ /// is trivially copiable."
+ bool isTrivial() const {
+ return isTriviallyCopyable() && hasTrivialDefaultConstructor();
+ }
+
+ /// \brief Determine whether this class is a literal type.
+ ///
+ /// C++11 [basic.types]p10:
+ /// A class type that has all the following properties:
+ /// - it has a trivial destructor
+ /// - every constructor call and full-expression in the
+ /// brace-or-equal-intializers for non-static data members (if any) is
+ /// a constant expression.
+ /// - it is an aggregate type or has at least one constexpr constructor
+ /// or constructor template that is not a copy or move constructor, and
+ /// - all of its non-static data members and base classes are of literal
+ /// types
+ ///
+ /// We resolve DR1361 by ignoring the second bullet. We resolve DR1452 by
+ /// treating types with trivial default constructors as literal types.
+ bool isLiteral() const {
+ return hasTrivialDestructor() &&
+ (isAggregate() || hasConstexprNonCopyMoveConstructor() ||
+ hasTrivialDefaultConstructor()) &&
+ !hasNonLiteralTypeFieldsOrBases();
+ }
+
+ /// \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 \p 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;
+
+ void setDescribedClassTemplate(ClassTemplateDecl *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);
+
+ /// \brief Retrieve the record declaration from which this record could be
+ /// instantiated. Returns null if this class is not a template instantiation.
+ const CXXRecordDecl *getTemplateInstantiationPattern() const;
+
+ CXXRecordDecl *getTemplateInstantiationPattern() {
+ return const_cast<CXXRecordDecl *>(const_cast<const CXXRecordDecl *>(this)
+ ->getTemplateInstantiationPattern());
+ }
+
+ /// \brief Returns the destructor decl for this class.
+ CXXDestructorDecl *getDestructor() const;
+
+ /// \brief Returns true if the class destructor, or any implicitly invoked
+ /// destructors are marked noreturn.
+ bool isAnyDestructorNoReturn() const;
+
+ /// \brief 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());
+ }
+
+ FunctionDecl *isLocalClass() {
+ return const_cast<FunctionDecl*>(
+ const_cast<const CXXRecordDecl*>(this)->isLocalClass());
+ }
+
+ /// \brief Determine whether this dependent class is a current instantiation,
+ /// when viewed from within the given context.
+ bool isCurrentInstantiation(const DeclContext *CurContext) const;
+
+ /// \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 \p Base, false otherwise.
+ ///
+ /// \todo add a separate parameter 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(const 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 BaseDefinition the definition of the base class
+ ///
+ /// \returns true if this base matched the search criteria
+ typedef llvm::function_ref<bool(const CXXRecordDecl *BaseDefinition)>
+ ForallBasesCallback;
+
+ /// \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 BaseMatches Callback invoked for each (direct or indirect) base
+ /// class of this type, or if \p AllowShortCircuit is true then until a call
+ /// returns false.
+ ///
+ /// \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,
+ 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.
+ ///
+ /// \returns true if this base matched the search criteria, false otherwise.
+ typedef llvm::function_ref<bool(const CXXBaseSpecifier *Specifier,
+ CXXBasePath &Path)> BaseMatchesCallback;
+
+ /// \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 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,
+ 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 base record pointer should refer to the canonical CXXRecordDecl of the
+ /// base class that we are searching for.
+ static bool FindBaseClass(const CXXBaseSpecifier *Specifier,
+ CXXBasePath &Path, const CXXRecordDecl *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 base record pointer should
+ /// refer to the canonical CXXRecordDecl of the base class that we
+ /// are searching for.
+ static bool FindVirtualBaseClass(const CXXBaseSpecifier *Specifier,
+ CXXBasePath &Path,
+ const CXXRecordDecl *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.
+ static bool FindTagMember(const CXXBaseSpecifier *Specifier,
+ CXXBasePath &Path, DeclarationName 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.
+ static bool FindOrdinaryMember(const CXXBaseSpecifier *Specifier,
+ CXXBasePath &Path, DeclarationName 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 members of
+ /// the given name within a C++ class hierarchy that can occur within
+ /// nested-name-specifiers.
+ static bool FindNestedNameSpecifierMember(const CXXBaseSpecifier *Specifier,
+ CXXBasePath &Path,
+ DeclarationName Name);
+
+ /// \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;
+
+ /// Renders and displays an inheritance diagram
+ /// for this C++ class and all of its base classes (transitively) using
+ /// GraphViz.
+ void viewInheritance(ASTContext& Context) const;
+
+ /// \brief 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 declaration of a defaulted or deleted special
+ /// member function is now complete.
+ void finishedDefaultedOrDeletedMember(CXXMethodDecl *MD);
+
+ /// \brief Indicates that the definition of this class is now complete.
+ void completeDefinition() override;
+
+ /// \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;
+
+ /// \brief If this is the closure type of a lambda expression, retrieve the
+ /// number to be used for name mangling in the Itanium C++ ABI.
+ ///
+ /// Zero indicates that this closure type has internal linkage, so the
+ /// mangling number does not matter, while a non-zero value indicates which
+ /// lambda expression this is in this particular context.
+ unsigned getLambdaManglingNumber() const {
+ assert(isLambda() && "Not a lambda closure type!");
+ return getLambdaData().ManglingNumber;
+ }
+
+ /// \brief Retrieve the declaration that provides additional context for a
+ /// lambda, when the normal declaration context is not specific enough.
+ ///
+ /// Certain contexts (default arguments of in-class function parameters and
+ /// the initializers of data members) have separate name mangling rules for
+ /// lambdas within the Itanium C++ ABI. For these cases, this routine provides
+ /// the declaration in which the lambda occurs, e.g., the function parameter
+ /// or the non-static data member. Otherwise, it returns NULL to imply that
+ /// the declaration context suffices.
+ Decl *getLambdaContextDecl() const {
+ assert(isLambda() && "Not a lambda closure type!");
+ return getLambdaData().ContextDecl;
+ }
+
+ /// \brief Set the mangling number and context declaration for a lambda
+ /// class.
+ void setLambdaMangling(unsigned ManglingNumber, Decl *ContextDecl) {
+ getLambdaData().ManglingNumber = ManglingNumber;
+ getLambdaData().ContextDecl = ContextDecl;
+ }
+
+ /// \brief Returns the inheritance model used for this record.
+ MSInheritanceAttr::Spelling getMSInheritanceModel() const;
+ /// \brief Calculate what the inheritance model would be for this class.
+ MSInheritanceAttr::Spelling calculateInheritanceModel() const;
+
+ /// In the Microsoft C++ ABI, use zero for the field offset of a null data
+ /// member pointer if we can guarantee that zero is not a valid field offset,
+ /// or if the member pointer has multiple fields. Polymorphic classes have a
+ /// vfptr at offset zero, so we can use zero for null. If there are multiple
+ /// fields, we can use zero even if it is a valid field offset because
+ /// null-ness testing will check the other fields.
+ bool nullFieldOffsetIsZero() const {
+ return !MSInheritanceAttr::hasOnlyOneField(/*IsMemberFunction=*/false,
+ getMSInheritanceModel()) ||
+ (hasDefinition() && isPolymorphic());
+ }
+
+ /// \brief Controls when vtordisps will be emitted if this record is used as a
+ /// virtual base.
+ MSVtorDispAttr::Mode getMSVtorDispMode() const;
+
+ /// \brief Determine whether this lambda expression was known to be dependent
+ /// at the time it was created, even if its context does not appear to be
+ /// dependent.
+ ///
+ /// This flag is a workaround for an issue with parsing, where default
+ /// arguments are parsed before their enclosing function declarations have
+ /// been created. This means that any lambda expressions within those
+ /// default arguments will have as their DeclContext the context enclosing
+ /// the function declaration, which may be non-dependent even when the
+ /// function declaration itself is dependent. This flag indicates when we
+ /// know that the lambda is dependent despite that.
+ bool isDependentLambda() const {
+ return isLambda() && getLambdaData().Dependent;
+ }
+
+ TypeSourceInfo *getLambdaTypeInfo() const {
+ return getLambdaData().MethodTyInfo;
+ }
+
+ static bool classof(const Decl *D) { return classofKind(D->getKind()); }
+ static bool classofKind(Kind K) {
+ return K >= firstCXXRecord && K <= lastCXXRecord;
+ }
+
+ friend class ASTDeclReader;
+ friend class ASTDeclWriter;
+ friend class ASTReader;
+ friend class ASTWriter;
+};
+
+/// \brief Represents a static or instance method of a struct/union/class.
+///
+/// In the terminology of the C++ Standard, these are the (static and
+/// non-static) member functions, whether virtual or not.
+class CXXMethodDecl : public FunctionDecl {
+ void anchor() override;
+protected:
+ CXXMethodDecl(Kind DK, ASTContext &C, CXXRecordDecl *RD,
+ SourceLocation StartLoc, const DeclarationNameInfo &NameInfo,
+ QualType T, TypeSourceInfo *TInfo,
+ StorageClass SC, bool isInline,
+ bool isConstexpr, SourceLocation EndLocation)
+ : FunctionDecl(DK, C, RD, StartLoc, NameInfo, T, TInfo,
+ SC, isInline, isConstexpr) {
+ if (EndLocation.isValid())
+ setRangeEnd(EndLocation);
+ }
+
+public:
+ static CXXMethodDecl *Create(ASTContext &C, CXXRecordDecl *RD,
+ SourceLocation StartLoc,
+ const DeclarationNameInfo &NameInfo,
+ QualType T, TypeSourceInfo *TInfo,
+ StorageClass SC,
+ bool isInline,
+ bool isConstexpr,
+ SourceLocation EndLocation);
+
+ static CXXMethodDecl *CreateDeserialized(ASTContext &C, unsigned ID);
+
+ bool isStatic() const;
+ bool isInstance() const { return !isStatic(); }
+
+ /// Returns true if the given operator is implicitly static in a record
+ /// context.
+ static bool isStaticOverloadedOperator(OverloadedOperatorKind OOK) {
+ // [class.free]p1:
+ // Any allocation function for a class T is a static member
+ // (even if not explicitly declared static).
+ // [class.free]p6 Any deallocation function for a class X is a static member
+ // (even if not explicitly declared static).
+ return OOK == OO_New || OOK == OO_Array_New || OOK == OO_Delete ||
+ OOK == OO_Array_Delete;
+ }
+
+ bool isConst() const { return getType()->castAs<FunctionType>()->isConst(); }
+ bool isVolatile() const { return getType()->castAs<FunctionType>()->isVolatile(); }
+
+ bool isVirtual() const {
+ CXXMethodDecl *CD =
+ cast<CXXMethodDecl>(const_cast<CXXMethodDecl*>(this)->getCanonicalDecl());
+
+ // Member function is virtual if it is marked explicitly so, or if it is
+ // declared in __interface -- then it is automatically pure virtual.
+ if (CD->isVirtualAsWritten() || CD->isPure())
+ 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;
+
+ /// \brief Determine whether this is a move assignment operator.
+ bool isMoveAssignmentOperator() const;
+
+ CXXMethodDecl *getCanonicalDecl() override {
+ return cast<CXXMethodDecl>(FunctionDecl::getCanonicalDecl());
+ }
+ const CXXMethodDecl *getCanonicalDecl() const {
+ return const_cast<CXXMethodDecl*>(this)->getCanonicalDecl();
+ }
+
+ CXXMethodDecl *getMostRecentDecl() {
+ return cast<CXXMethodDecl>(
+ static_cast<FunctionDecl *>(this)->getMostRecentDecl());
+ }
+ const CXXMethodDecl *getMostRecentDecl() const {
+ return const_cast<CXXMethodDecl*>(this)->getMostRecentDecl();
+ }
+
+ /// True if this method is user-declared and was not
+ /// deleted or defaulted on its first declaration.
+ bool isUserProvided() const {
+ return !(isDeleted() || getCanonicalDecl()->isDefaulted());
+ }
+
+ ///
+ void addOverriddenMethod(const CXXMethodDecl *MD);
+
+ typedef const CXXMethodDecl *const* method_iterator;
+
+ method_iterator begin_overridden_methods() const;
+ method_iterator end_overridden_methods() const;
+ unsigned size_overridden_methods() const;
+
+ /// 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());
+ }
+
+ /// 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()));
+ }
+
+ /// \brief Returns the type of the \c this pointer.
+ ///
+ /// Should only be called for instance (i.e., non-static) 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();
+ /// };
+ /// @endcode
+ RefQualifierKind getRefQualifier() const {
+ return getType()->getAs<FunctionProtoType>()->getRefQualifier();
+ }
+
+ bool hasInlineBody() const;
+
+ /// \brief Determine whether this is a lambda closure type's static member
+ /// function that is used for the result of the lambda's conversion to
+ /// function pointer (for a lambda with no captures).
+ ///
+ /// The function itself, if used, will have a placeholder body that will be
+ /// supplied by IR generation to either forward to the function call operator
+ /// or clone the function call operator.
+ bool isLambdaStaticInvoker() const;
+
+ /// \brief Find the method in \p RD that corresponds to this one.
+ ///
+ /// Find if \p RD or one of the classes it inherits from override this method.
+ /// If so, return it. \p RD is assumed to be a subclass of the class defining
+ /// this method (or be the class itself), unless \p MayBeBase is set to true.
+ CXXMethodDecl *
+ getCorrespondingMethodInClass(const CXXRecordDecl *RD,
+ bool MayBeBase = false);
+
+ const CXXMethodDecl *
+ getCorrespondingMethodInClass(const CXXRecordDecl *RD,
+ bool MayBeBase = false) const {
+ return const_cast<CXXMethodDecl *>(this)
+ ->getCorrespondingMethodInClass(RD, MayBeBase);
+ }
+
+ // Implement isa/cast/dyncast/etc.
+ static bool classof(const Decl *D) { return classofKind(D->getKind()); }
+ static bool classofKind(Kind K) {
+ return K >= firstCXXMethod && K <= lastCXXMethod;
+ }
+};
+
+/// \brief Represents a C++ base or member initializer.
+///
+/// This 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 final
+ : private llvm::TrailingObjects<CXXCtorInitializer, VarDecl *> {
+ /// \brief Either the base class name/delegating constructor type (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.
+ ///
+ /// In the case of a delegating
+ /// constructor, it will still include the type's source location as the
+ /// Initializee points to the CXXConstructorDecl (to allow loop detection).
+ 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;
+
+ /// \brief Location of the left paren of the ctor-initializer.
+ SourceLocation LParenLoc;
+
+ /// \brief Location of the right paren of the ctor-initializer.
+ SourceLocation RParenLoc;
+
+ /// \brief If the initializee is a type, whether that type makes this
+ /// a delegating initialization.
+ bool IsDelegating : 1;
+
+ /// \brief If the initializer is a base initializer, this keeps track
+ /// of whether the base is virtual or not.
+ bool IsVirtual : 1;
+
+ /// \brief Whether or not the initializer is explicitly written
+ /// in the sources.
+ bool IsWritten : 1;
+
+ /// If IsWritten is true, then this number keeps track of the textual order
+ /// of this initializer in the original sources, counting from 0; otherwise,
+ /// it stores the number of array index variables stored after this object
+ /// in memory.
+ unsigned SourceOrderOrNumArrayIndices : 13;
+
+ CXXCtorInitializer(ASTContext &Context, FieldDecl *Member,
+ SourceLocation MemberLoc, SourceLocation L, Expr *Init,
+ SourceLocation R, VarDecl **Indices, unsigned NumIndices);
+
+public:
+ /// \brief Creates a new base-class initializer.
+ explicit
+ CXXCtorInitializer(ASTContext &Context, TypeSourceInfo *TInfo, bool IsVirtual,
+ SourceLocation L, Expr *Init, SourceLocation R,
+ SourceLocation EllipsisLoc);
+
+ /// \brief Creates a new member initializer.
+ explicit
+ CXXCtorInitializer(ASTContext &Context, FieldDecl *Member,
+ SourceLocation MemberLoc, SourceLocation L, Expr *Init,
+ SourceLocation R);
+
+ /// \brief Creates a new anonymous field initializer.
+ explicit
+ CXXCtorInitializer(ASTContext &Context, IndirectFieldDecl *Member,
+ SourceLocation MemberLoc, SourceLocation L, Expr *Init,
+ SourceLocation R);
+
+ /// \brief Creates a new delegating initializer.
+ explicit
+ CXXCtorInitializer(ASTContext &Context, TypeSourceInfo *TInfo,
+ 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);
+
+ /// \brief Determine whether this initializer is initializing a base class.
+ bool isBaseInitializer() const {
+ return Initializee.is<TypeSourceInfo*>() && !IsDelegating;
+ }
+
+ /// \brief Determine whether 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 an implicit initializer
+ /// generated for a field with an initializer defined on the member
+ /// declaration.
+ ///
+ /// In-class member initializers (also known as "non-static data member
+ /// initializations", NSDMIs) were introduced in C++11.
+ bool isInClassMemberInitializer() const {
+ return Init->getStmtClass() == Stmt::CXXDefaultInitExprClass;
+ }
+
+ /// \brief Determine whether this initializer is creating a delegating
+ /// constructor.
+ bool isDelegatingInitializer() const {
+ return Initializee.is<TypeSourceInfo*>() && IsDelegating;
+ }
+
+ /// \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 or delegating
+ /// initializer.
+ TypeSourceInfo *getTypeSourceInfo() const {
+ return Initializee.dyn_cast<TypeSourceInfo *>();
+ }
+
+ /// \brief 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*>();
+ return nullptr;
+ }
+ FieldDecl *getAnyMember() const {
+ if (isMemberInitializer())
+ return Initializee.get<FieldDecl*>();
+ if (isIndirectMemberInitializer())
+ return Initializee.get<IndirectFieldDecl*>()->getAnonField();
+ return nullptr;
+ }
+
+ IndirectFieldDecl *getIndirectMember() const {
+ if (isIndirectMemberInitializer())
+ return Initializee.get<IndirectFieldDecl*>();
+ return nullptr;
+ }
+
+ 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 LLVM_READONLY;
+
+ /// \brief Determine whether 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 can only be called once for each initializer; it cannot be called
+ /// on an initializer having a positive number of (implicit) array indices.
+ ///
+ /// This assumes that the initializer was written in the source code, and
+ /// ensures that isWritten() returns true.
+ 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 getTrailingObjects<VarDecl *>()[I];
+ }
+ const VarDecl *getArrayIndex(unsigned I) const {
+ assert(I < getNumArrayIndices() && "Out of bounds member array index");
+ return getTrailingObjects<VarDecl *>()[I];
+ }
+ void setArrayIndex(unsigned I, VarDecl *Index) {
+ assert(I < getNumArrayIndices() && "Out of bounds member array index");
+ getTrailingObjects<VarDecl *>()[I] = Index;
+ }
+ ArrayRef<VarDecl *> getArrayIndexes() {
+ assert(getNumArrayIndices() != 0 && "Getting indexes for non-array init");
+ return llvm::makeArrayRef(getTrailingObjects<VarDecl *>(),
+ getNumArrayIndices());
+ }
+
+ /// \brief Get the initializer.
+ Expr *getInit() const { return static_cast<Expr*>(Init); }
+
+ friend TrailingObjects;
+};
+
+/// \brief 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 {
+ void anchor() override;
+ /// \brief Whether this constructor declaration has the \c explicit keyword
+ /// specified.
+ bool IsExplicitSpecified : 1;
+
+ /// \name Support for base and member initializers.
+ /// \{
+ /// \brief The arguments used to initialize the base or member.
+ LazyCXXCtorInitializersPtr CtorInitializers;
+ unsigned NumCtorInitializers;
+ /// \}
+
+ CXXConstructorDecl(ASTContext &C, CXXRecordDecl *RD, SourceLocation StartLoc,
+ const DeclarationNameInfo &NameInfo,
+ QualType T, TypeSourceInfo *TInfo,
+ bool isExplicitSpecified, bool isInline,
+ bool isImplicitlyDeclared, bool isConstexpr)
+ : CXXMethodDecl(CXXConstructor, C, RD, StartLoc, NameInfo, T, TInfo,
+ SC_None, isInline, isConstexpr, SourceLocation()),
+ IsExplicitSpecified(isExplicitSpecified), CtorInitializers(nullptr),
+ NumCtorInitializers(0) {
+ setImplicit(isImplicitlyDeclared);
+ }
+
+public:
+ static CXXConstructorDecl *CreateDeserialized(ASTContext &C, unsigned ID);
+ static CXXConstructorDecl *Create(ASTContext &C, CXXRecordDecl *RD,
+ SourceLocation StartLoc,
+ const DeclarationNameInfo &NameInfo,
+ QualType T, TypeSourceInfo *TInfo,
+ bool isExplicit,
+ bool isInline, bool isImplicitlyDeclared,
+ bool isConstexpr);
+
+ /// \brief Determine whether this constructor declaration has the
+ /// \c explicit keyword specified.
+ bool isExplicitSpecified() const { return IsExplicitSpecified; }
+
+ /// \brief Determine whether this constructor was marked "explicit" or not.
+ bool isExplicit() const {
+ return cast<CXXConstructorDecl>(getFirstDecl())->isExplicitSpecified();
+ }
+
+ /// \brief Iterates through the member/base initializer list.
+ typedef CXXCtorInitializer **init_iterator;
+
+ /// \brief Iterates through the member/base initializer list.
+ typedef CXXCtorInitializer *const *init_const_iterator;
+
+ typedef llvm::iterator_range<init_iterator> init_range;
+ typedef llvm::iterator_range<init_const_iterator> init_const_range;
+
+ init_range inits() { return init_range(init_begin(), init_end()); }
+ init_const_range inits() const {
+ return init_const_range(init_begin(), init_end());
+ }
+
+ /// \brief Retrieve an iterator to the first initializer.
+ init_iterator init_begin() {
+ const auto *ConstThis = this;
+ return const_cast<init_iterator>(ConstThis->init_begin());
+ }
+ /// \brief Retrieve an iterator to the first initializer.
+ init_const_iterator init_begin() const;
+
+ /// \brief Retrieve an iterator past the last initializer.
+ init_iterator init_end() {
+ return init_begin() + NumCtorInitializers;
+ }
+ /// \brief Retrieve an iterator past the last initializer.
+ init_const_iterator init_end() const {
+ return init_begin() + 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());
+ }
+
+ /// \brief 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;
+ }
+
+ /// \brief Determine whether this constructor is a delegating constructor.
+ bool isDelegatingConstructor() const {
+ return (getNumCtorInitializers() == 1) &&
+ init_begin()[0]->isDelegatingInitializer();
+ }
+
+ /// \brief When this constructor delegates to another, retrieve the target.
+ CXXConstructorDecl *getTargetConstructor() const;
+
+ /// 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;
+
+ /// \brief 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
+ /// Qualifiers::Const for the following copy constructor:
+ ///
+ /// \code
+ /// class X {
+ /// public:
+ /// X(const X&);
+ /// };
+ /// \endcode
+ bool isCopyConstructor(unsigned &TypeQuals) const;
+
+ /// 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++11 [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++11 [class.copy]p3), which can be used to move values of the class.
+ bool isMoveConstructor() const {
+ unsigned TypeQuals = 0;
+ return isMoveConstructor(TypeQuals);
+ }
+
+ /// \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);
+ }
+
+ /// 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);
+
+ CXXConstructorDecl *getCanonicalDecl() override {
+ return cast<CXXConstructorDecl>(FunctionDecl::getCanonicalDecl());
+ }
+ const CXXConstructorDecl *getCanonicalDecl() const {
+ return const_cast<CXXConstructorDecl*>(this)->getCanonicalDecl();
+ }
+
+ // Implement isa/cast/dyncast/etc.
+ static bool classof(const Decl *D) { return classofKind(D->getKind()); }
+ static bool classofKind(Kind K) { return K == CXXConstructor; }
+
+ friend class ASTDeclReader;
+ friend class ASTDeclWriter;
+};
+
+/// \brief Represents a C++ destructor within a class.
+///
+/// For example:
+///
+/// \code
+/// class X {
+/// public:
+/// ~X(); // represented by a CXXDestructorDecl.
+/// };
+/// \endcode
+class CXXDestructorDecl : public CXXMethodDecl {
+ void anchor() override;
+
+ FunctionDecl *OperatorDelete;
+
+ CXXDestructorDecl(ASTContext &C, CXXRecordDecl *RD, SourceLocation StartLoc,
+ const DeclarationNameInfo &NameInfo,
+ QualType T, TypeSourceInfo *TInfo,
+ bool isInline, bool isImplicitlyDeclared)
+ : CXXMethodDecl(CXXDestructor, C, RD, StartLoc, NameInfo, T, TInfo,
+ SC_None, isInline, /*isConstexpr=*/false, SourceLocation()),
+ OperatorDelete(nullptr) {
+ setImplicit(isImplicitlyDeclared);
+ }
+
+public:
+ static CXXDestructorDecl *Create(ASTContext &C, CXXRecordDecl *RD,
+ SourceLocation StartLoc,
+ const DeclarationNameInfo &NameInfo,
+ QualType T, TypeSourceInfo* TInfo,
+ bool isInline,
+ bool isImplicitlyDeclared);
+ static CXXDestructorDecl *CreateDeserialized(ASTContext & C, unsigned ID);
+
+ void setOperatorDelete(FunctionDecl *OD);
+ const FunctionDecl *getOperatorDelete() const {
+ return cast<CXXDestructorDecl>(getFirstDecl())->OperatorDelete;
+ }
+
+ // Implement isa/cast/dyncast/etc.
+ static bool classof(const Decl *D) { return classofKind(D->getKind()); }
+ static bool classofKind(Kind K) { return K == CXXDestructor; }
+
+ friend class ASTDeclReader;
+ friend class ASTDeclWriter;
+};
+
+/// \brief Represents a C++ conversion function within a class.
+///
+/// For example:
+///
+/// \code
+/// class X {
+/// public:
+/// operator bool();
+/// };
+/// \endcode
+class CXXConversionDecl : public CXXMethodDecl {
+ void anchor() override;
+ /// 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++11 feature.
+ bool IsExplicitSpecified : 1;
+
+ CXXConversionDecl(ASTContext &C, CXXRecordDecl *RD, SourceLocation StartLoc,
+ const DeclarationNameInfo &NameInfo,
+ QualType T, TypeSourceInfo *TInfo,
+ bool isInline, bool isExplicitSpecified,
+ bool isConstexpr, SourceLocation EndLocation)
+ : CXXMethodDecl(CXXConversion, C, RD, StartLoc, NameInfo, T, TInfo,
+ SC_None, isInline, isConstexpr, EndLocation),
+ IsExplicitSpecified(isExplicitSpecified) { }
+
+public:
+ static CXXConversionDecl *Create(ASTContext &C, CXXRecordDecl *RD,
+ SourceLocation StartLoc,
+ const DeclarationNameInfo &NameInfo,
+ QualType T, TypeSourceInfo *TInfo,
+ bool isInline, bool isExplicit,
+ bool isConstexpr,
+ SourceLocation EndLocation);
+ static CXXConversionDecl *CreateDeserialized(ASTContext &C, unsigned ID);
+
+ /// Whether this conversion function declaration is marked
+ /// "explicit", meaning that it can only be used for direct initialization
+ /// (including explitly written casts). This is a C++11 feature.
+ bool isExplicitSpecified() const { return IsExplicitSpecified; }
+
+ /// \brief Whether this is an explicit conversion operator (C++11 and later).
+ ///
+ /// Explicit conversion operators are only considered for direct
+ /// initialization, e.g., when the user has explicitly written a cast.
+ bool isExplicit() const {
+ return cast<CXXConversionDecl>(getFirstDecl())->isExplicitSpecified();
+ }
+
+ /// \brief Returns the type that this conversion function is converting to.
+ QualType getConversionType() const {
+ return getType()->getAs<FunctionType>()->getReturnType();
+ }
+
+ /// \brief Determine whether this conversion function is a conversion from
+ /// a lambda closure type to a block pointer.
+ bool isLambdaToBlockPointerConversion() const;
+
+ // Implement isa/cast/dyncast/etc.
+ static bool classof(const Decl *D) { return classofKind(D->getKind()); }
+ static bool classofKind(Kind K) { return K == CXXConversion; }
+
+ friend class ASTDeclReader;
+ friend class ASTDeclWriter;
+};
+
+/// \brief Represents a linkage specification.
+///
+/// For example:
+/// \code
+/// extern "C" void foo();
+/// \endcode
+class LinkageSpecDecl : public Decl, public DeclContext {
+ virtual void anchor();
+public:
+ /// \brief Represents 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:
+ /// \brief The language for this linkage specification.
+ unsigned Language : 3;
+ /// \brief True if this linkage spec has braces.
+ ///
+ /// This is needed so that hasBraces() returns the correct result while the
+ /// linkage spec body is being parsed. Once RBraceLoc has been set this is
+ /// not used, so it doesn't need to be serialized.
+ unsigned HasBraces : 1;
+ /// \brief The source location for the extern keyword.
+ SourceLocation ExternLoc;
+ /// \brief The source location for the right brace (if valid).
+ SourceLocation RBraceLoc;
+
+ LinkageSpecDecl(DeclContext *DC, SourceLocation ExternLoc,
+ SourceLocation LangLoc, LanguageIDs lang, bool HasBraces)
+ : Decl(LinkageSpec, DC, LangLoc), DeclContext(LinkageSpec),
+ Language(lang), HasBraces(HasBraces), ExternLoc(ExternLoc),
+ RBraceLoc(SourceLocation()) { }
+
+public:
+ static LinkageSpecDecl *Create(ASTContext &C, DeclContext *DC,
+ SourceLocation ExternLoc,
+ SourceLocation LangLoc, LanguageIDs Lang,
+ bool HasBraces);
+ static LinkageSpecDecl *CreateDeserialized(ASTContext &C, unsigned ID);
+
+ /// \brief Return the language specified by this linkage specification.
+ LanguageIDs getLanguage() const { return LanguageIDs(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 {
+ assert(!RBraceLoc.isValid() || HasBraces);
+ return HasBraces;
+ }
+
+ SourceLocation getExternLoc() const { return ExternLoc; }
+ SourceLocation getRBraceLoc() const { return RBraceLoc; }
+ void setExternLoc(SourceLocation L) { ExternLoc = L; }
+ void setRBraceLoc(SourceLocation L) {
+ RBraceLoc = L;
+ HasBraces = RBraceLoc.isValid();
+ }
+
+ SourceLocation getLocEnd() const LLVM_READONLY {
+ if (hasBraces())
+ return getRBraceLoc();
+ // No braces: get the end location of the (only) declaration in context
+ // (if present).
+ return decls_empty() ? getLocation() : decls_begin()->getLocEnd();
+ }
+
+ SourceRange getSourceRange() const override LLVM_READONLY {
+ return SourceRange(ExternLoc, getLocEnd());
+ }
+
+ static bool classof(const Decl *D) { return classofKind(D->getKind()); }
+ 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));
+ }
+};
+
+/// \brief Represents C++ using-directive.
+///
+/// For example:
+/// \code
+/// using namespace std;
+/// \endcode
+///
+/// \note UsingDirectiveDecl should be Decl not NamedDecl, but we provide
+/// artificial names for all using-directives in order to store
+/// them in DeclContext effectively.
+class UsingDirectiveDecl : public NamedDecl {
+ void anchor() override;
+ /// \brief The location of the \c using keyword.
+ SourceLocation UsingLoc;
+
+ /// \brief The location of the \c namespace keyword.
+ SourceLocation NamespaceLoc;
+
+ /// \brief The nested-name-specifier that precedes the namespace.
+ NestedNameSpecifierLoc QualifierLoc;
+
+ /// \brief The namespace nominated by this using-directive.
+ NamedDecl *NominatedNamespace;
+
+ /// Enclosing context containing both using-directive and nominated
+ /// namespace.
+ DeclContext *CommonAncestor;
+
+ /// \brief 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,
+ NestedNameSpecifierLoc QualifierLoc,
+ SourceLocation IdentLoc,
+ NamedDecl *Nominated,
+ DeclContext *CommonAncestor)
+ : NamedDecl(UsingDirective, DC, IdentLoc, getName()), UsingLoc(UsingLoc),
+ NamespaceLoc(NamespcLoc), QualifierLoc(QualifierLoc),
+ NominatedNamespace(Nominated), CommonAncestor(CommonAncestor) { }
+
+public:
+ /// \brief Retrieve the nested-name-specifier that qualifies the
+ /// name of the namespace, with source-location information.
+ NestedNameSpecifierLoc getQualifierLoc() const { return QualifierLoc; }
+
+ /// \brief Retrieve the nested-name-specifier that qualifies the
+ /// name of the namespace.
+ NestedNameSpecifier *getQualifier() const {
+ return QualifierLoc.getNestedNameSpecifier();
+ }
+
+ NamedDecl *getNominatedNamespaceAsWritten() { return NominatedNamespace; }
+ const NamedDecl *getNominatedNamespaceAsWritten() const {
+ return NominatedNamespace;
+ }
+
+ /// \brief Returns the namespace nominated by this 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 \c using keyword.
+ SourceLocation getUsingLoc() const { return UsingLoc; }
+
+ // FIXME: Could omit 'Key' in name.
+ /// \brief Returns the location of the \c namespace keyword.
+ SourceLocation getNamespaceKeyLocation() const { return NamespaceLoc; }
+
+ /// \brief Returns the location of this using declaration's identifier.
+ SourceLocation getIdentLocation() const { return getLocation(); }
+
+ static UsingDirectiveDecl *Create(ASTContext &C, DeclContext *DC,
+ SourceLocation UsingLoc,
+ SourceLocation NamespaceLoc,
+ NestedNameSpecifierLoc QualifierLoc,
+ SourceLocation IdentLoc,
+ NamedDecl *Nominated,
+ DeclContext *CommonAncestor);
+ static UsingDirectiveDecl *CreateDeserialized(ASTContext &C, unsigned ID);
+
+ SourceRange getSourceRange() const override LLVM_READONLY {
+ return SourceRange(UsingLoc, getLocation());
+ }
+
+ static bool classof(const Decl *D) { return classofKind(D->getKind()); }
+ static bool classofKind(Kind K) { return K == UsingDirective; }
+
+ // Friend for getUsingDirectiveName.
+ friend class DeclContext;
+
+ friend class ASTDeclReader;
+};
+
+/// \brief Represents a C++ namespace alias.
+///
+/// For example:
+///
+/// \code
+/// namespace Foo = Bar;
+/// \endcode
+class NamespaceAliasDecl : public NamedDecl,
+ public Redeclarable<NamespaceAliasDecl> {
+ void anchor() override;
+
+ /// \brief The location of the \c namespace keyword.
+ SourceLocation NamespaceLoc;
+
+ /// \brief The location of the namespace's identifier.
+ ///
+ /// This is accessed by TargetNameLoc.
+ SourceLocation IdentLoc;
+
+ /// \brief The nested-name-specifier that precedes the namespace.
+ NestedNameSpecifierLoc QualifierLoc;
+
+ /// \brief The Decl that this alias points to, either a NamespaceDecl or
+ /// a NamespaceAliasDecl.
+ NamedDecl *Namespace;
+
+ NamespaceAliasDecl(ASTContext &C, DeclContext *DC,
+ SourceLocation NamespaceLoc, SourceLocation AliasLoc,
+ IdentifierInfo *Alias, NestedNameSpecifierLoc QualifierLoc,
+ SourceLocation IdentLoc, NamedDecl *Namespace)
+ : NamedDecl(NamespaceAlias, DC, AliasLoc, Alias), redeclarable_base(C),
+ NamespaceLoc(NamespaceLoc), IdentLoc(IdentLoc),
+ QualifierLoc(QualifierLoc), Namespace(Namespace) {}
+
+ typedef Redeclarable<NamespaceAliasDecl> redeclarable_base;
+ NamespaceAliasDecl *getNextRedeclarationImpl() override;
+ NamespaceAliasDecl *getPreviousDeclImpl() override;
+ NamespaceAliasDecl *getMostRecentDeclImpl() override;
+
+ friend class ASTDeclReader;
+
+public:
+ static NamespaceAliasDecl *Create(ASTContext &C, DeclContext *DC,
+ SourceLocation NamespaceLoc,
+ SourceLocation AliasLoc,
+ IdentifierInfo *Alias,
+ NestedNameSpecifierLoc QualifierLoc,
+ SourceLocation IdentLoc,
+ NamedDecl *Namespace);
+
+ static NamespaceAliasDecl *CreateDeserialized(ASTContext &C, unsigned ID);
+
+ typedef redeclarable_base::redecl_range redecl_range;
+ typedef redeclarable_base::redecl_iterator redecl_iterator;
+ using redeclarable_base::redecls_begin;
+ using redeclarable_base::redecls_end;
+ using redeclarable_base::redecls;
+ using redeclarable_base::getPreviousDecl;
+ using redeclarable_base::getMostRecentDecl;
+
+ NamespaceAliasDecl *getCanonicalDecl() override {
+ return getFirstDecl();
+ }
+ const NamespaceAliasDecl *getCanonicalDecl() const {
+ return getFirstDecl();
+ }
+
+ /// \brief Retrieve the nested-name-specifier that qualifies the
+ /// name of the namespace, with source-location information.
+ NestedNameSpecifierLoc getQualifierLoc() const { return QualifierLoc; }
+
+ /// \brief Retrieve the nested-name-specifier that qualifies the
+ /// name of the namespace.
+ NestedNameSpecifier *getQualifier() const {
+ return QualifierLoc.getNestedNameSpecifier();
+ }
+
+ /// \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 \c 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; }
+
+ SourceRange getSourceRange() const override LLVM_READONLY {
+ return SourceRange(NamespaceLoc, IdentLoc);
+ }
+
+ static bool classof(const Decl *D) { return classofKind(D->getKind()); }
+ static bool classofKind(Kind K) { return K == NamespaceAlias; }
+};
+
+/// \brief Represents a shadow declaration introduced into a scope by a
+/// (resolved) using declaration.
+///
+/// For example,
+/// \code
+/// namespace A {
+/// void foo();
+/// }
+/// namespace B {
+/// using A::foo; // <- a UsingDecl
+/// // Also creates a UsingShadowDecl for A::foo() in B
+/// }
+/// \endcode
+class UsingShadowDecl : public NamedDecl, public Redeclarable<UsingShadowDecl> {
+ void anchor() override;
+
+ /// 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(ASTContext &C, DeclContext *DC, SourceLocation Loc,
+ UsingDecl *Using, NamedDecl *Target)
+ : NamedDecl(UsingShadow, DC, Loc, DeclarationName()),
+ redeclarable_base(C), Underlying(Target),
+ UsingOrNextShadow(reinterpret_cast<NamedDecl *>(Using)) {
+ if (Target) {
+ setDeclName(Target->getDeclName());
+ IdentifierNamespace = Target->getIdentifierNamespace();
+ }
+ setImplicit();
+ }
+
+ typedef Redeclarable<UsingShadowDecl> redeclarable_base;
+ UsingShadowDecl *getNextRedeclarationImpl() override {
+ return getNextRedeclaration();
+ }
+ UsingShadowDecl *getPreviousDeclImpl() override {
+ return getPreviousDecl();
+ }
+ UsingShadowDecl *getMostRecentDeclImpl() override {
+ return getMostRecentDecl();
+ }
+
+public:
+ static UsingShadowDecl *Create(ASTContext &C, DeclContext *DC,
+ SourceLocation Loc, UsingDecl *Using,
+ NamedDecl *Target) {
+ return new (C, DC) UsingShadowDecl(C, DC, Loc, Using, Target);
+ }
+
+ static UsingShadowDecl *CreateDeserialized(ASTContext &C, unsigned ID);
+
+ typedef redeclarable_base::redecl_range redecl_range;
+ typedef redeclarable_base::redecl_iterator redecl_iterator;
+ using redeclarable_base::redecls_begin;
+ using redeclarable_base::redecls_end;
+ using redeclarable_base::redecls;
+ using redeclarable_base::getPreviousDecl;
+ using redeclarable_base::getMostRecentDecl;
+
+ UsingShadowDecl *getCanonicalDecl() override {
+ return getFirstDecl();
+ }
+ const UsingShadowDecl *getCanonicalDecl() const {
+ return getFirstDecl();
+ }
+
+ /// \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 classofKind(Kind K) { return K == Decl::UsingShadow; }
+
+ friend class ASTDeclReader;
+ friend class ASTDeclWriter;
+};
+
+/// \brief Represents a C++ using-declaration.
+///
+/// For example:
+/// \code
+/// using someNameSpace::someIdentifier;
+/// \endcode
+class UsingDecl : public NamedDecl, public Mergeable<UsingDecl> {
+ void anchor() override;
+
+ /// \brief The source location of the 'using' keyword itself.
+ SourceLocation UsingLocation;
+
+ /// \brief The nested-name-specifier that precedes the name.
+ NestedNameSpecifierLoc QualifierLoc;
+
+ /// \brief 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.
+ ///
+ /// The bool member of the pair store whether this decl has the \c typename
+ /// keyword.
+ llvm::PointerIntPair<UsingShadowDecl *, 1, bool> FirstUsingShadow;
+
+ UsingDecl(DeclContext *DC, SourceLocation UL,
+ NestedNameSpecifierLoc QualifierLoc,
+ const DeclarationNameInfo &NameInfo, bool HasTypenameKeyword)
+ : NamedDecl(Using, DC, NameInfo.getLoc(), NameInfo.getName()),
+ UsingLocation(UL), QualifierLoc(QualifierLoc),
+ DNLoc(NameInfo.getInfo()), FirstUsingShadow(nullptr, HasTypenameKeyword) {
+ }
+
+public:
+ /// \brief Return the source location of the 'using' keyword.
+ SourceLocation getUsingLoc() const { return UsingLocation; }
+
+ /// \brief Set the source location of the 'using' keyword.
+ void setUsingLoc(SourceLocation L) { UsingLocation = L; }
+
+ /// \brief Retrieve the nested-name-specifier that qualifies the name,
+ /// with source-location information.
+ NestedNameSpecifierLoc getQualifierLoc() const { return QualifierLoc; }
+
+ /// \brief Retrieve the nested-name-specifier that qualifies the name.
+ NestedNameSpecifier *getQualifier() const {
+ return QualifierLoc.getNestedNameSpecifier();
+ }
+
+ DeclarationNameInfo getNameInfo() const {
+ return DeclarationNameInfo(getDeclName(), getLocation(), DNLoc);
+ }
+
+ /// \brief Return true if it is a C++03 access declaration (no 'using').
+ bool isAccessDeclaration() const { return UsingLocation.isInvalid(); }
+
+ /// \brief Return true if the using declaration has 'typename'.
+ bool hasTypename() const { return FirstUsingShadow.getInt(); }
+
+ /// \brief Sets whether the using declaration has 'typename'.
+ void setTypename(bool TN) { FirstUsingShadow.setInt(TN); }
+
+ /// \brief Iterates through the using shadow declarations associated 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(nullptr) { }
+ 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;
+ }
+ };
+
+ typedef llvm::iterator_range<shadow_iterator> shadow_range;
+
+ shadow_range shadows() const {
+ return shadow_range(shadow_begin(), shadow_end());
+ }
+ shadow_iterator shadow_begin() const {
+ return shadow_iterator(FirstUsingShadow.getPointer());
+ }
+ 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,
+ SourceLocation UsingL,
+ NestedNameSpecifierLoc QualifierLoc,
+ const DeclarationNameInfo &NameInfo,
+ bool HasTypenameKeyword);
+
+ static UsingDecl *CreateDeserialized(ASTContext &C, unsigned ID);
+
+ SourceRange getSourceRange() const override LLVM_READONLY;
+
+ /// Retrieves the canonical declaration of this declaration.
+ UsingDecl *getCanonicalDecl() override { return getFirstDecl(); }
+ const UsingDecl *getCanonicalDecl() const { return getFirstDecl(); }
+
+ static bool classof(const Decl *D) { return classofKind(D->getKind()); }
+ static bool classofKind(Kind K) { return K == Using; }
+
+ friend class ASTDeclReader;
+ friend class ASTDeclWriter;
+};
+
+/// \brief Represents a dependent using declaration which was not marked with
+/// \c typename.
+///
+/// Unlike non-dependent using declarations, these *only* bring through
+/// non-types; otherwise they would break two-phase lookup.
+///
+/// \code
+/// template \<class T> class A : public Base<T> {
+/// using Base<T>::foo;
+/// };
+/// \endcode
+class UnresolvedUsingValueDecl : public ValueDecl,
+ public Mergeable<UnresolvedUsingValueDecl> {
+ void anchor() override;
+
+ /// \brief The source location of the 'using' keyword
+ SourceLocation UsingLocation;
+
+ /// \brief The nested-name-specifier that precedes the name.
+ NestedNameSpecifierLoc QualifierLoc;
+
+ /// \brief Provides source/type location info for the declaration name
+ /// embedded in the ValueDecl base class.
+ DeclarationNameLoc DNLoc;
+
+ UnresolvedUsingValueDecl(DeclContext *DC, QualType Ty,
+ SourceLocation UsingLoc,
+ NestedNameSpecifierLoc QualifierLoc,
+ const DeclarationNameInfo &NameInfo)
+ : ValueDecl(UnresolvedUsingValue, DC,
+ NameInfo.getLoc(), NameInfo.getName(), Ty),
+ UsingLocation(UsingLoc), QualifierLoc(QualifierLoc),
+ DNLoc(NameInfo.getInfo())
+ { }
+
+public:
+ /// \brief Returns the source location of the 'using' keyword.
+ SourceLocation getUsingLoc() const { return UsingLocation; }
+
+ /// \brief Set the source location of the 'using' keyword.
+ void setUsingLoc(SourceLocation L) { UsingLocation = L; }
+
+ /// \brief Return true if it is a C++03 access declaration (no 'using').
+ bool isAccessDeclaration() const { return UsingLocation.isInvalid(); }
+
+ /// \brief Retrieve the nested-name-specifier that qualifies the name,
+ /// with source-location information.
+ NestedNameSpecifierLoc getQualifierLoc() const { return QualifierLoc; }
+
+ /// \brief Retrieve the nested-name-specifier that qualifies the name.
+ NestedNameSpecifier *getQualifier() const {
+ return QualifierLoc.getNestedNameSpecifier();
+ }
+
+ DeclarationNameInfo getNameInfo() const {
+ return DeclarationNameInfo(getDeclName(), getLocation(), DNLoc);
+ }
+
+ static UnresolvedUsingValueDecl *
+ Create(ASTContext &C, DeclContext *DC, SourceLocation UsingLoc,
+ NestedNameSpecifierLoc QualifierLoc,
+ const DeclarationNameInfo &NameInfo);
+
+ static UnresolvedUsingValueDecl *
+ CreateDeserialized(ASTContext &C, unsigned ID);
+
+ SourceRange getSourceRange() const override LLVM_READONLY;
+
+ /// Retrieves the canonical declaration of this declaration.
+ UnresolvedUsingValueDecl *getCanonicalDecl() override {
+ return getFirstDecl();
+ }
+ const UnresolvedUsingValueDecl *getCanonicalDecl() const {
+ return getFirstDecl();
+ }
+
+ static bool classof(const Decl *D) { return classofKind(D->getKind()); }
+ static bool classofKind(Kind K) { return K == UnresolvedUsingValue; }
+
+ friend class ASTDeclReader;
+ friend class ASTDeclWriter;
+};
+
+/// \brief Represents a dependent using declaration which was marked with
+/// \c typename.
+///
+/// \code
+/// template \<class T> class A : public Base<T> {
+/// using typename Base<T>::foo;
+/// };
+/// \endcode
+///
+/// The type associated with an unresolved using typename decl is
+/// currently always a typename type.
+class UnresolvedUsingTypenameDecl
+ : public TypeDecl,
+ public Mergeable<UnresolvedUsingTypenameDecl> {
+ void anchor() override;
+
+ /// \brief The source location of the 'typename' keyword
+ SourceLocation TypenameLocation;
+
+ /// \brief The nested-name-specifier that precedes the name.
+ NestedNameSpecifierLoc QualifierLoc;
+
+ UnresolvedUsingTypenameDecl(DeclContext *DC, SourceLocation UsingLoc,
+ SourceLocation TypenameLoc,
+ NestedNameSpecifierLoc QualifierLoc,
+ SourceLocation TargetNameLoc,
+ IdentifierInfo *TargetName)
+ : TypeDecl(UnresolvedUsingTypename, DC, TargetNameLoc, TargetName,
+ UsingLoc),
+ TypenameLocation(TypenameLoc), QualifierLoc(QualifierLoc) { }
+
+ friend class ASTDeclReader;
+
+public:
+ /// \brief Returns the source location of the 'using' keyword.
+ SourceLocation getUsingLoc() const { return getLocStart(); }
+
+ /// \brief Returns the source location of the 'typename' keyword.
+ SourceLocation getTypenameLoc() const { return TypenameLocation; }
+
+ /// \brief Retrieve the nested-name-specifier that qualifies the name,
+ /// with source-location information.
+ NestedNameSpecifierLoc getQualifierLoc() const { return QualifierLoc; }
+
+ /// \brief Retrieve the nested-name-specifier that qualifies the name.
+ NestedNameSpecifier *getQualifier() const {
+ return QualifierLoc.getNestedNameSpecifier();
+ }
+
+ static UnresolvedUsingTypenameDecl *
+ Create(ASTContext &C, DeclContext *DC, SourceLocation UsingLoc,
+ SourceLocation TypenameLoc, NestedNameSpecifierLoc QualifierLoc,
+ SourceLocation TargetNameLoc, DeclarationName TargetName);
+
+ static UnresolvedUsingTypenameDecl *
+ CreateDeserialized(ASTContext &C, unsigned ID);
+
+ /// Retrieves the canonical declaration of this declaration.
+ UnresolvedUsingTypenameDecl *getCanonicalDecl() override {
+ return getFirstDecl();
+ }
+ const UnresolvedUsingTypenameDecl *getCanonicalDecl() const {
+ return getFirstDecl();
+ }
+
+ static bool classof(const Decl *D) { return classofKind(D->getKind()); }
+ static bool classofKind(Kind K) { return K == UnresolvedUsingTypename; }
+};
+
+/// \brief Represents a C++11 static_assert declaration.
+class StaticAssertDecl : public Decl {
+ virtual void anchor();
+ llvm::PointerIntPair<Expr *, 1, bool> AssertExprAndFailed;
+ StringLiteral *Message;
+ SourceLocation RParenLoc;
+
+ StaticAssertDecl(DeclContext *DC, SourceLocation StaticAssertLoc,
+ Expr *AssertExpr, StringLiteral *Message,
+ SourceLocation RParenLoc, bool Failed)
+ : Decl(StaticAssert, DC, StaticAssertLoc),
+ AssertExprAndFailed(AssertExpr, Failed), Message(Message),
+ RParenLoc(RParenLoc) { }
+
+public:
+ static StaticAssertDecl *Create(ASTContext &C, DeclContext *DC,
+ SourceLocation StaticAssertLoc,
+ Expr *AssertExpr, StringLiteral *Message,
+ SourceLocation RParenLoc, bool Failed);
+ static StaticAssertDecl *CreateDeserialized(ASTContext &C, unsigned ID);
+
+ Expr *getAssertExpr() { return AssertExprAndFailed.getPointer(); }
+ const Expr *getAssertExpr() const { return AssertExprAndFailed.getPointer(); }
+
+ StringLiteral *getMessage() { return Message; }
+ const StringLiteral *getMessage() const { return Message; }
+
+ bool isFailed() const { return AssertExprAndFailed.getInt(); }
+
+ SourceLocation getRParenLoc() const { return RParenLoc; }
+
+ SourceRange getSourceRange() const override LLVM_READONLY {
+ return SourceRange(getLocation(), getRParenLoc());
+ }
+
+ static bool classof(const Decl *D) { return classofKind(D->getKind()); }
+ static bool classofKind(Kind K) { return K == StaticAssert; }
+
+ friend class ASTDeclReader;
+};
+
+/// An instance of this class represents the declaration of a property
+/// member. This is a Microsoft extension to C++, first introduced in
+/// Visual Studio .NET 2003 as a parallel to similar features in C#
+/// and Managed C++.
+///
+/// A property must always be a non-static class member.
+///
+/// A property member superficially resembles a non-static data
+/// member, except preceded by a property attribute:
+/// __declspec(property(get=GetX, put=PutX)) int x;
+/// Either (but not both) of the 'get' and 'put' names may be omitted.
+///
+/// A reference to a property is always an lvalue. If the lvalue
+/// undergoes lvalue-to-rvalue conversion, then a getter name is
+/// required, and that member is called with no arguments.
+/// If the lvalue is assigned into, then a setter name is required,
+/// and that member is called with one argument, the value assigned.
+/// Both operations are potentially overloaded. Compound assignments
+/// are permitted, as are the increment and decrement operators.
+///
+/// The getter and putter methods are permitted to be overloaded,
+/// although their return and parameter types are subject to certain
+/// restrictions according to the type of the property.
+///
+/// A property declared using an incomplete array type may
+/// additionally be subscripted, adding extra parameters to the getter
+/// and putter methods.
+class MSPropertyDecl : public DeclaratorDecl {
+ IdentifierInfo *GetterId, *SetterId;
+
+ MSPropertyDecl(DeclContext *DC, SourceLocation L, DeclarationName N,
+ QualType T, TypeSourceInfo *TInfo, SourceLocation StartL,
+ IdentifierInfo *Getter, IdentifierInfo *Setter)
+ : DeclaratorDecl(MSProperty, DC, L, N, T, TInfo, StartL),
+ GetterId(Getter), SetterId(Setter) {}
+
+public:
+ static MSPropertyDecl *Create(ASTContext &C, DeclContext *DC,
+ SourceLocation L, DeclarationName N, QualType T,
+ TypeSourceInfo *TInfo, SourceLocation StartL,
+ IdentifierInfo *Getter, IdentifierInfo *Setter);
+ static MSPropertyDecl *CreateDeserialized(ASTContext &C, unsigned ID);
+
+ static bool classof(const Decl *D) { return D->getKind() == MSProperty; }
+
+ bool hasGetter() const { return GetterId != nullptr; }
+ IdentifierInfo* getGetterId() const { return GetterId; }
+ bool hasSetter() const { return SetterId != nullptr; }
+ IdentifierInfo* getSetterId() const { return SetterId; }
+
+ friend class ASTDeclReader;
+};
+
+/// Insertion operator for diagnostics. This allows sending an AccessSpecifier
+/// into a diagnostic with <<.
+const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB,
+ AccessSpecifier AS);
+
+const PartialDiagnostic &operator<<(const PartialDiagnostic &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..ff37758
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/AST/DeclContextInternals.h
@@ -0,0 +1,264 @@
+//===-- 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/DeclCXX.h"
+#include "clang/AST/DeclarationName.h"
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/PointerIntPair.h"
+#include "llvm/ADT/PointerUnion.h"
+#include "llvm/ADT/SmallVector.h"
+#include <algorithm>
+
+namespace clang {
+
+class DependentDiagnostic;
+
+/// \brief An array of decls optimized for the common case of only containing
+/// one entry.
+struct StoredDeclsList {
+
+ /// \brief When in vector form, this is what the Data pointer points to.
+ typedef SmallVector<NamedDecl *, 4> DeclsTy;
+
+ /// \brief A collection of declarations, with a flag to indicate if we have
+ /// further external declarations.
+ typedef llvm::PointerIntPair<DeclsTy *, 1, bool> DeclsAndHasExternalTy;
+
+ /// \brief The stored data, which will be either a pointer to a NamedDecl,
+ /// or a pointer to a vector with a flag to indicate if there are further
+ /// external declarations.
+ llvm::PointerUnion<NamedDecl*, DeclsAndHasExternalTy> Data;
+
+public:
+ StoredDeclsList() {}
+
+ StoredDeclsList(StoredDeclsList &&RHS) : Data(RHS.Data) {
+ RHS.Data = (NamedDecl *)nullptr;
+ }
+
+ ~StoredDeclsList() {
+ // If this is a vector-form, free the vector.
+ if (DeclsTy *Vector = getAsVector())
+ delete Vector;
+ }
+
+ StoredDeclsList &operator=(StoredDeclsList &&RHS) {
+ if (DeclsTy *Vector = getAsVector())
+ delete Vector;
+ Data = RHS.Data;
+ RHS.Data = (NamedDecl *)nullptr;
+ return *this;
+ }
+
+ bool isNull() const { return Data.isNull(); }
+
+ NamedDecl *getAsDecl() const {
+ return Data.dyn_cast<NamedDecl *>();
+ }
+
+ DeclsAndHasExternalTy getAsVectorAndHasExternal() const {
+ return Data.dyn_cast<DeclsAndHasExternalTy>();
+ }
+
+ DeclsTy *getAsVector() const {
+ return getAsVectorAndHasExternal().getPointer();
+ }
+
+ bool hasExternalDecls() const {
+ return getAsVectorAndHasExternal().getInt();
+ }
+
+ void setHasExternalDecls() {
+ if (DeclsTy *Vec = getAsVector())
+ Data = DeclsAndHasExternalTy(Vec, true);
+ else {
+ DeclsTy *VT = new DeclsTy();
+ if (NamedDecl *OldD = getAsDecl())
+ VT->push_back(OldD);
+ Data = DeclsAndHasExternalTy(VT, true);
+ }
+ }
+
+ 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 *)nullptr;
+ 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");
+ }
+
+ /// \brief Remove any declarations which were imported from an external
+ /// AST source.
+ void removeExternalDecls() {
+ if (isNull()) {
+ // Nothing to do.
+ } else if (NamedDecl *Singleton = getAsDecl()) {
+ if (Singleton->isFromASTFile())
+ *this = StoredDeclsList();
+ } else {
+ DeclsTy &Vec = *getAsVector();
+ Vec.erase(std::remove_if(Vec.begin(), Vec.end(),
+ std::mem_fun(&Decl::isFromASTFile)),
+ Vec.end());
+ // Don't have any external decls any more.
+ Data = DeclsAndHasExternalTy(&Vec, false);
+ }
+ }
+
+ /// getLookupResult - Return an array of all the decls that this list
+ /// represents.
+ DeclContext::lookup_result getLookupResult() {
+ if (isNull())
+ return DeclContext::lookup_result();
+
+ // If we have a single NamedDecl, return it.
+ if (NamedDecl *ND = getAsDecl()) {
+ assert(!isNull() && "Empty list isn't allowed");
+
+ // Data is a raw pointer to a NamedDecl*, return it.
+ return DeclContext::lookup_result(ND);
+ }
+
+ assert(getAsVector() && "Must have a vector at this point");
+ DeclsTy &Vector = *getAsVector();
+
+ // Otherwise, we have a range result.
+ return DeclContext::lookup_result(Vector);
+ }
+
+ /// 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, bool IsKnownNewer) {
+ // Most decls only have one entry in their list, special case it.
+ if (NamedDecl *OldD = getAsDecl()) {
+ if (!D->declarationReplaces(OldD, IsKnownNewer))
+ 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, IsKnownNewer)) {
+ *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) {
+ assert(!isNull() && "don't AddSubsequentDecl when we have no decls");
+
+ // 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 = DeclsAndHasExternalTy(VT, false);
+ }
+
+ 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.empty() && Vec.back()->hasTagIdentifierNamespace()) {
+ NamedDecl *TagD = Vec.back();
+ Vec.back() = D;
+ Vec.push_back(TagD);
+ } else
+ Vec.push_back(D);
+ }
+};
+
+class StoredDeclsMap
+ : public llvm::SmallDenseMap<DeclarationName, StoredDeclsList, 4> {
+
+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(nullptr) {}
+
+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..27b0388
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/AST/DeclFriend.h
@@ -0,0 +1,243 @@
+//===-- 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"
+#include "clang/AST/DeclTemplate.h"
+#include "clang/AST/TypeLoc.h"
+#include "llvm/Support/Compiler.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 final
+ : public Decl,
+ private llvm::TrailingObjects<FriendDecl, TemplateParameterList *> {
+ virtual void anchor();
+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 : 1;
+
+ // The number of "outer" template parameter lists in non-templatic
+ // (currently unsupported) friend type declarations, such as
+ // template <class T> friend class A<T>::B;
+ unsigned NumTPLists : 31;
+
+ friend class CXXRecordDecl::friend_iterator;
+ friend class CXXRecordDecl;
+
+ FriendDecl(DeclContext *DC, SourceLocation L, FriendUnion Friend,
+ SourceLocation FriendL,
+ ArrayRef<TemplateParameterList*> FriendTypeTPLists)
+ : Decl(Decl::Friend, DC, L),
+ Friend(Friend),
+ NextFriend(),
+ FriendLoc(FriendL),
+ UnsupportedFriend(false),
+ NumTPLists(FriendTypeTPLists.size()) {
+ for (unsigned i = 0; i < NumTPLists; ++i)
+ getTrailingObjects<TemplateParameterList *>()[i] = FriendTypeTPLists[i];
+ }
+
+ FriendDecl(EmptyShell Empty, unsigned NumFriendTypeTPLists)
+ : Decl(Decl::Friend, Empty), NextFriend(),
+ NumTPLists(NumFriendTypeTPLists) { }
+
+ FriendDecl *getNextFriend() {
+ if (!NextFriend.isOffset())
+ return cast_or_null<FriendDecl>(NextFriend.get(nullptr));
+ return getNextFriendSlowCase();
+ }
+ FriendDecl *getNextFriendSlowCase();
+
+public:
+ static FriendDecl *Create(ASTContext &C, DeclContext *DC,
+ SourceLocation L, FriendUnion Friend_,
+ SourceLocation FriendL,
+ ArrayRef<TemplateParameterList*> FriendTypeTPLists
+ = None);
+ static FriendDecl *CreateDeserialized(ASTContext &C, unsigned ID,
+ unsigned FriendTypeNumTPLists);
+
+ /// 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*>();
+ }
+ unsigned getFriendTypeNumTemplateParameterLists() const {
+ return NumTPLists;
+ }
+ TemplateParameterList *getFriendTypeTemplateParameterList(unsigned N) const {
+ assert(N < NumTPLists);
+ return getTrailingObjects<TemplateParameterList *>()[N];
+ }
+
+ /// 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;
+ }
+
+ /// Retrieves the source range for the friend declaration.
+ SourceRange getSourceRange() const override LLVM_READONLY {
+ if (NamedDecl *ND = getFriendDecl()) {
+ if (FunctionDecl *FD = dyn_cast<FunctionDecl>(ND))
+ return FD->getSourceRange();
+ if (FunctionTemplateDecl *FTD = dyn_cast<FunctionTemplateDecl>(ND))
+ return FTD->getSourceRange();
+ if (ClassTemplateDecl *CTD = dyn_cast<ClassTemplateDecl>(ND))
+ return CTD->getSourceRange();
+ if (DeclaratorDecl *DD = dyn_cast<DeclaratorDecl>(ND)) {
+ if (DD->getOuterLocStart() != DD->getInnerLocStart())
+ return DD->getSourceRange();
+ }
+ return SourceRange(getFriendLoc(), ND->getLocEnd());
+ }
+ else if (TypeSourceInfo *TInfo = getFriendType()) {
+ SourceLocation StartL =
+ (NumTPLists == 0) ? getFriendLoc()
+ : getTrailingObjects<TemplateParameterList *>()[0]
+ ->getTemplateLoc();
+ return SourceRange(StartL, TInfo->getTypeLoc().getEndLoc());
+ }
+ else
+ return SourceRange(getFriendLoc(), getLocation());
+ }
+
+ /// 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 classofKind(Kind K) { return K == Decl::Friend; }
+
+ friend class ASTDeclReader;
+ friend class ASTDeclWriter;
+ friend TrailingObjects;
+};
+
+/// 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(getFirstFriend());
+}
+
+inline CXXRecordDecl::friend_iterator CXXRecordDecl::friend_end() const {
+ return friend_iterator(nullptr);
+}
+
+inline CXXRecordDecl::friend_range CXXRecordDecl::friends() const {
+ return friend_range(friend_begin(), friend_end());
+}
+
+inline void CXXRecordDecl::pushFriendDecl(FriendDecl *FD) {
+ assert(!FD->NextFriend && "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..c84bb5e
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/AST/DeclGroup.h
@@ -0,0 +1,154 @@
+//===--- 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 "llvm/Support/TrailingObjects.h"
+#include <cassert>
+
+namespace clang {
+
+class ASTContext;
+class Decl;
+class DeclGroup;
+class DeclGroupIterator;
+
+class DeclGroup final : private llvm::TrailingObjects<DeclGroup, Decl *> {
+ // 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 getTrailingObjects<Decl *>()[i];
+ }
+
+ Decl* const& operator[](unsigned i) const {
+ assert (i < NumDecls && "Out-of-bounds access.");
+ return getTrailingObjects<Decl *>()[i];
+ }
+
+ friend TrailingObjects;
+};
+
+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(nullptr) {}
+
+ 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 == nullptr; }
+ 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 : nullptr;
+ return &getDeclGroup()[0];
+ }
+
+ iterator end() {
+ if (isSingleDecl())
+ return D ? &D+1 : nullptr;
+ DeclGroup &G = getDeclGroup();
+ return &G[0] + G.size();
+ }
+
+ const_iterator begin() const {
+ if (isSingleDecl())
+ return D ? &D : nullptr;
+ return &getDeclGroup()[0];
+ }
+
+ const_iterator end() const {
+ if (isSingleDecl())
+ return D ? &D+1 : nullptr;
+ 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/DeclLookups.h b/contrib/llvm/tools/clang/include/clang/AST/DeclLookups.h
new file mode 100644
index 0000000..eba2266
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/AST/DeclLookups.h
@@ -0,0 +1,115 @@
+//===-- DeclLookups.h - Low-level interface to all names in a DC-*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines DeclContext::all_lookups_iterator.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_AST_DECLLOOKUPS_H
+#define LLVM_CLANG_AST_DECLLOOKUPS_H
+
+#include "clang/AST/ASTContext.h"
+#include "clang/AST/DeclBase.h"
+#include "clang/AST/DeclContextInternals.h"
+#include "clang/AST/DeclarationName.h"
+
+namespace clang {
+
+/// all_lookups_iterator - An iterator that provides a view over the results
+/// of looking up every possible name.
+class DeclContext::all_lookups_iterator {
+ StoredDeclsMap::iterator It, End;
+public:
+ typedef lookup_result value_type;
+ typedef lookup_result reference;
+ typedef lookup_result pointer;
+ typedef std::forward_iterator_tag iterator_category;
+ typedef std::ptrdiff_t difference_type;
+
+ all_lookups_iterator() {}
+ all_lookups_iterator(StoredDeclsMap::iterator It,
+ StoredDeclsMap::iterator End)
+ : It(It), End(End) {}
+
+ DeclarationName getLookupName() const { return It->first; }
+
+ reference operator*() const { return It->second.getLookupResult(); }
+ pointer operator->() const { return It->second.getLookupResult(); }
+
+ all_lookups_iterator& operator++() {
+ // Filter out using directives. They don't belong as results from name
+ // lookup anyways, except as an implementation detail. Users of the API
+ // should not expect to get them (or worse, rely on it).
+ do {
+ ++It;
+ } while (It != End &&
+ It->first == DeclarationName::getUsingDirectiveName());
+
+ return *this;
+ }
+
+ all_lookups_iterator operator++(int) {
+ all_lookups_iterator tmp(*this);
+ ++(*this);
+ return tmp;
+ }
+
+ friend bool operator==(all_lookups_iterator x, all_lookups_iterator y) {
+ return x.It == y.It;
+ }
+ friend bool operator!=(all_lookups_iterator x, all_lookups_iterator y) {
+ return x.It != y.It;
+ }
+};
+
+inline DeclContext::lookups_range DeclContext::lookups() const {
+ DeclContext *Primary = const_cast<DeclContext*>(this)->getPrimaryContext();
+ if (Primary->hasExternalVisibleStorage())
+ getParentASTContext().getExternalSource()->completeVisibleDeclsMap(Primary);
+ if (StoredDeclsMap *Map = Primary->buildLookup())
+ return lookups_range(all_lookups_iterator(Map->begin(), Map->end()),
+ all_lookups_iterator(Map->end(), Map->end()));
+
+ // Synthesize an empty range. This requires that two default constructed
+ // versions of these iterators form a valid empty range.
+ return lookups_range(all_lookups_iterator(), all_lookups_iterator());
+}
+
+inline DeclContext::all_lookups_iterator DeclContext::lookups_begin() const {
+ return lookups().begin();
+}
+
+inline DeclContext::all_lookups_iterator DeclContext::lookups_end() const {
+ return lookups().end();
+}
+
+inline DeclContext::lookups_range DeclContext::noload_lookups() const {
+ DeclContext *Primary = const_cast<DeclContext*>(this)->getPrimaryContext();
+ if (StoredDeclsMap *Map = Primary->getLookupPtr())
+ return lookups_range(all_lookups_iterator(Map->begin(), Map->end()),
+ all_lookups_iterator(Map->end(), Map->end()));
+
+ // Synthesize an empty range. This requires that two default constructed
+ // versions of these iterators form a valid empty range.
+ return lookups_range(all_lookups_iterator(), all_lookups_iterator());
+}
+
+inline
+DeclContext::all_lookups_iterator DeclContext::noload_lookups_begin() const {
+ return noload_lookups().begin();
+}
+
+inline
+DeclContext::all_lookups_iterator DeclContext::noload_lookups_end() const {
+ return noload_lookups().end();
+}
+
+} // end namespace clang
+
+#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..f46078f
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/AST/DeclObjC.h
@@ -0,0 +1,2742 @@
+//===--- 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 "clang/AST/SelectorLocationsKind.h"
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/Support/Compiler.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 {
+ ObjCListBase(const ObjCListBase &) = delete;
+ void operator=(const ObjCListBase &) = delete;
+protected:
+ /// List is an array of pointers to objects that are not owned by this object.
+ void **List;
+ unsigned NumElts;
+
+public:
+ ObjCListBase() : List(nullptr), 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(nullptr) { }
+
+ 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:
+ // The conventional meaning of this method; an ObjCMethodFamily.
+ // This is not serialized; instead, it is computed on demand and
+ // cached.
+ mutable unsigned Family : ObjCMethodFamilyBitWidth;
+
+ /// instance (true) or class (false) method.
+ unsigned IsInstance : 1;
+ unsigned IsVariadic : 1;
+
+ /// True if this method is the getter or setter for an explicit property.
+ unsigned IsPropertyAccessor : 1;
+
+ // Method has a definition.
+ unsigned IsDefined : 1;
+
+ /// \brief Method redeclaration in the same interface.
+ unsigned IsRedeclaration : 1;
+
+ /// \brief Is redeclared in the same interface.
+ mutable unsigned HasRedeclaration : 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 : 7;
+
+ /// \brief Indicates whether this method has a related result type.
+ unsigned RelatedResultType : 1;
+
+ /// \brief Whether the locations of the selector identifiers are in a
+ /// "standard" position, a enum SelectorLocationsKind.
+ unsigned SelLocsKind : 2;
+
+ /// \brief Whether this method overrides any other in the class hierarchy.
+ ///
+ /// A method is said to override any method in the class's
+ /// base classes, its protocols, or its categories' protocols, that has
+ /// the same selector and is of the same kind (class or instance).
+ /// A method in an implementation is not considered as overriding the same
+ /// method in the interface or its categories.
+ unsigned IsOverriding : 1;
+
+ /// \brief Indicates if the method was a definition but its body was skipped.
+ unsigned HasSkippedBody : 1;
+
+ // Return type of this method.
+ QualType MethodDeclType;
+
+ // Type source information for the return type.
+ TypeSourceInfo *ReturnTInfo;
+
+ /// \brief Array of ParmVarDecls for the formal parameters of this method
+ /// and optionally followed by selector locations.
+ void *ParamsAndSelLocs;
+ unsigned NumParams;
+
+ /// List of attributes for this method declaration.
+ SourceLocation DeclEndLoc; // the location of the ';' or '{'.
+
+ // The following are only used for method definitions, null otherwise.
+ LazyDeclStmtPtr 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;
+
+ SelectorLocationsKind getSelLocsKind() const {
+ return (SelectorLocationsKind)SelLocsKind;
+ }
+ bool hasStandardSelLocs() const {
+ return getSelLocsKind() != SelLoc_NonStandard;
+ }
+
+ /// \brief Get a pointer to the stored selector identifiers locations array.
+ /// No locations will be stored if HasStandardSelLocs is true.
+ SourceLocation *getStoredSelLocs() {
+ return reinterpret_cast<SourceLocation*>(getParams() + NumParams);
+ }
+ const SourceLocation *getStoredSelLocs() const {
+ return reinterpret_cast<const SourceLocation*>(getParams() + NumParams);
+ }
+
+ /// \brief Get a pointer to the stored selector identifiers locations array.
+ /// No locations will be stored if HasStandardSelLocs is true.
+ ParmVarDecl **getParams() {
+ return reinterpret_cast<ParmVarDecl **>(ParamsAndSelLocs);
+ }
+ const ParmVarDecl *const *getParams() const {
+ return reinterpret_cast<const ParmVarDecl *const *>(ParamsAndSelLocs);
+ }
+
+ /// \brief Get the number of stored selector identifiers locations.
+ /// No locations will be stored if HasStandardSelLocs is true.
+ unsigned getNumStoredSelLocs() const {
+ if (hasStandardSelLocs())
+ return 0;
+ return getNumSelectorLocs();
+ }
+
+ void setParamsAndSelLocs(ASTContext &C,
+ ArrayRef<ParmVarDecl*> Params,
+ ArrayRef<SourceLocation> SelLocs);
+
+ ObjCMethodDecl(SourceLocation beginLoc, SourceLocation endLoc,
+ Selector SelInfo, QualType T, TypeSourceInfo *ReturnTInfo,
+ DeclContext *contextDecl, bool isInstance = true,
+ bool isVariadic = false, bool isPropertyAccessor = false,
+ bool isImplicitlyDeclared = false, bool isDefined = false,
+ ImplementationControl impControl = None,
+ bool HasRelatedResultType = false)
+ : NamedDecl(ObjCMethod, contextDecl, beginLoc, SelInfo),
+ DeclContext(ObjCMethod), Family(InvalidObjCMethodFamily),
+ IsInstance(isInstance), IsVariadic(isVariadic),
+ IsPropertyAccessor(isPropertyAccessor), IsDefined(isDefined),
+ IsRedeclaration(0), HasRedeclaration(0), DeclImplementation(impControl),
+ objcDeclQualifier(OBJC_TQ_None),
+ RelatedResultType(HasRelatedResultType),
+ SelLocsKind(SelLoc_StandardNoSpace), IsOverriding(0), HasSkippedBody(0),
+ MethodDeclType(T), ReturnTInfo(ReturnTInfo), ParamsAndSelLocs(nullptr),
+ NumParams(0), DeclEndLoc(endLoc), Body(), SelfDecl(nullptr),
+ CmdDecl(nullptr) {
+ setImplicit(isImplicitlyDeclared);
+ }
+
+ /// \brief A definition will return its interface declaration.
+ /// An interface declaration will return its definition.
+ /// Otherwise it will return itself.
+ ObjCMethodDecl *getNextRedeclarationImpl() override;
+
+public:
+ static ObjCMethodDecl *
+ Create(ASTContext &C, SourceLocation beginLoc, SourceLocation endLoc,
+ Selector SelInfo, QualType T, TypeSourceInfo *ReturnTInfo,
+ DeclContext *contextDecl, bool isInstance = true,
+ bool isVariadic = false, bool isPropertyAccessor = false,
+ bool isImplicitlyDeclared = false, bool isDefined = false,
+ ImplementationControl impControl = None,
+ bool HasRelatedResultType = false);
+
+ static ObjCMethodDecl *CreateDeserialized(ASTContext &C, unsigned ID);
+
+ ObjCMethodDecl *getCanonicalDecl() override;
+ const ObjCMethodDecl *getCanonicalDecl() const {
+ return const_cast<ObjCMethodDecl*>(this)->getCanonicalDecl();
+ }
+
+ ObjCDeclQualifier getObjCDeclQualifier() const {
+ return ObjCDeclQualifier(objcDeclQualifier);
+ }
+ void setObjCDeclQualifier(ObjCDeclQualifier QV) { objcDeclQualifier = QV; }
+
+ /// \brief Determine whether this method has a result type that is related
+ /// to the message receiver's type.
+ bool hasRelatedResultType() const { return RelatedResultType; }
+
+ /// \brief Note whether this method has a related result type.
+ void SetRelatedResultType(bool RRT = true) { RelatedResultType = RRT; }
+
+ /// \brief True if this is a method redeclaration in the same interface.
+ bool isRedeclaration() const { return IsRedeclaration; }
+ void setAsRedeclaration(const ObjCMethodDecl *PrevMethod);
+
+ /// \brief Returns the location where the declarator ends. It will be
+ /// the location of ';' for a method declaration and the location of '{'
+ /// for a method definition.
+ SourceLocation getDeclaratorEndLoc() const { return DeclEndLoc; }
+
+ // Location information, modeled after the Stmt API.
+ SourceLocation getLocStart() const LLVM_READONLY { return getLocation(); }
+ SourceLocation getLocEnd() const LLVM_READONLY;
+ SourceRange getSourceRange() const override LLVM_READONLY {
+ return SourceRange(getLocation(), getLocEnd());
+ }
+
+ SourceLocation getSelectorStartLoc() const {
+ if (isImplicit())
+ return getLocStart();
+ return getSelectorLoc(0);
+ }
+ SourceLocation getSelectorLoc(unsigned Index) const {
+ assert(Index < getNumSelectorLocs() && "Index out of range!");
+ if (hasStandardSelLocs())
+ return getStandardSelectorLoc(Index, getSelector(),
+ getSelLocsKind() == SelLoc_StandardWithSpace,
+ parameters(),
+ DeclEndLoc);
+ return getStoredSelLocs()[Index];
+ }
+
+ void getSelectorLocs(SmallVectorImpl<SourceLocation> &SelLocs) const;
+
+ unsigned getNumSelectorLocs() const {
+ if (isImplicit())
+ return 0;
+ Selector Sel = getSelector();
+ if (Sel.isUnarySelector())
+ return 1;
+ return Sel.getNumArgs();
+ }
+
+ ObjCInterfaceDecl *getClassInterface();
+ const ObjCInterfaceDecl *getClassInterface() const {
+ return const_cast<ObjCMethodDecl*>(this)->getClassInterface();
+ }
+
+ Selector getSelector() const { return getDeclName().getObjCSelector(); }
+
+ QualType getReturnType() const { return MethodDeclType; }
+ void setReturnType(QualType T) { MethodDeclType = T; }
+ SourceRange getReturnTypeSourceRange() const;
+
+ /// \brief Determine the type of an expression that sends a message to this
+ /// function. This replaces the type parameters with the types they would
+ /// get if the receiver was parameterless (e.g. it may replace the type
+ /// parameter with 'id').
+ QualType getSendResultType() const;
+
+ /// Determine the type of an expression that sends a message to this
+ /// function with the given receiver type.
+ QualType getSendResultType(QualType receiverType) const;
+
+ TypeSourceInfo *getReturnTypeSourceInfo() const { return ReturnTInfo; }
+ void setReturnTypeSourceInfo(TypeSourceInfo *TInfo) { ReturnTInfo = TInfo; }
+
+ // Iterator access to formal parameters.
+ unsigned param_size() const { return NumParams; }
+ typedef const ParmVarDecl *const *param_const_iterator;
+ typedef ParmVarDecl *const *param_iterator;
+ typedef llvm::iterator_range<param_iterator> param_range;
+ typedef llvm::iterator_range<param_const_iterator> param_const_range;
+
+ param_range params() { return param_range(param_begin(), param_end()); }
+ param_const_range params() const {
+ return param_const_range(param_begin(), param_end());
+ }
+
+ param_const_iterator param_begin() const {
+ return param_const_iterator(getParams());
+ }
+ param_const_iterator param_end() const {
+ return param_const_iterator(getParams() + NumParams);
+ }
+ param_iterator param_begin() { return param_iterator(getParams()); }
+ param_iterator param_end() { return param_iterator(getParams() + NumParams); }
+
+ // This method returns and of the parameters which are part of the selector
+ // name mangling requirements.
+ param_const_iterator sel_param_end() const {
+ return param_begin() + getSelector().getNumArgs();
+ }
+
+ // ArrayRef access to formal parameters. This should eventually
+ // replace the iterator interface above.
+ ArrayRef<ParmVarDecl*> parameters() const {
+ return llvm::makeArrayRef(const_cast<ParmVarDecl**>(getParams()),
+ NumParams);
+ }
+
+ /// \brief Sets the method's parameters and selector source locations.
+ /// If the method is implicit (not coming from source) \p SelLocs is
+ /// ignored.
+ void setMethodParams(ASTContext &C,
+ ArrayRef<ParmVarDecl*> Params,
+ ArrayRef<SourceLocation> SelLocs = llvm::None);
+
+ // Iterator access to parameter types.
+ typedef std::const_mem_fun_t<QualType, ParmVarDecl> deref_fun;
+ typedef llvm::mapped_iterator<param_const_iterator, deref_fun>
+ param_type_iterator;
+
+ param_type_iterator param_type_begin() const {
+ return llvm::map_iterator(param_begin(), deref_fun(&ParmVarDecl::getType));
+ }
+ param_type_iterator param_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);
+
+ /// \return the type for \c self and set \arg selfIsPseudoStrong and
+ /// \arg selfIsConsumed accordingly.
+ QualType getSelfType(ASTContext &Context, const ObjCInterfaceDecl *OID,
+ bool &selfIsPseudoStrong, bool &selfIsConsumed);
+
+ ImplicitParamDecl * getSelfDecl() const { return SelfDecl; }
+ void setSelfDecl(ImplicitParamDecl *SD) { SelfDecl = SD; }
+ ImplicitParamDecl * getCmdDecl() const { return CmdDecl; }
+ void setCmdDecl(ImplicitParamDecl *CD) { CmdDecl = CD; }
+
+ /// Determines the family of this method.
+ ObjCMethodFamily getMethodFamily() const;
+
+ 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 isPropertyAccessor() const { return IsPropertyAccessor; }
+ void setPropertyAccessor(bool isAccessor) { IsPropertyAccessor = isAccessor; }
+
+ bool isDefined() const { return IsDefined; }
+ void setDefined(bool isDefined) { IsDefined = isDefined; }
+
+ /// \brief Whether this method overrides any other in the class hierarchy.
+ ///
+ /// A method is said to override any method in the class's
+ /// base classes, its protocols, or its categories' protocols, that has
+ /// the same selector and is of the same kind (class or instance).
+ /// A method in an implementation is not considered as overriding the same
+ /// method in the interface or its categories.
+ bool isOverriding() const { return IsOverriding; }
+ void setOverriding(bool isOverriding) { IsOverriding = isOverriding; }
+
+ /// \brief Return overridden methods for the given \p Method.
+ ///
+ /// An ObjC method is considered to override any method in the class's
+ /// base classes (and base's categories), its protocols, or its categories'
+ /// protocols, that has
+ /// the same selector and is of the same kind (class or instance).
+ /// A method in an implementation is not considered as overriding the same
+ /// method in the interface or its categories.
+ void getOverriddenMethods(
+ SmallVectorImpl<const ObjCMethodDecl *> &Overridden) const;
+
+ /// \brief True if the method was a definition but its body was skipped.
+ bool hasSkippedBody() const { return HasSkippedBody; }
+ void setHasSkippedBody(bool Skipped = true) { HasSkippedBody = Skipped; }
+
+ /// \brief Returns the property associated with this method's selector.
+ ///
+ /// Note that even if this particular method is not marked as a property
+ /// accessor, it is still possible for it to match a property declared in a
+ /// superclass. Pass \c false if you only want to check the current class.
+ const ObjCPropertyDecl *findPropertyDecl(bool CheckOverrides = true) const;
+
+ // Related to protocols declared in \@protocol
+ void setDeclImplementation(ImplementationControl ic) {
+ DeclImplementation = ic;
+ }
+ ImplementationControl getImplementationControl() const {
+ return ImplementationControl(DeclImplementation);
+ }
+
+ /// Returns true if this specific method declaration is marked with the
+ /// designated initializer attribute.
+ bool isThisDeclarationADesignatedInitializer() const;
+
+ /// Returns true if the method selector resolves to a designated initializer
+ /// in the class's interface.
+ ///
+ /// \param InitMethod if non-null and the function returns true, it receives
+ /// the method declaration that was marked with the designated initializer
+ /// attribute.
+ bool isDesignatedInitializerForTheInterface(
+ const ObjCMethodDecl **InitMethod = nullptr) const;
+
+ /// \brief Determine whether this method has a body.
+ bool hasBody() const override { return Body.isValid(); }
+
+ /// \brief Retrieve the body of this method, if it has one.
+ Stmt *getBody() const override;
+
+ void setLazyBody(uint64_t Offset) { Body = Offset; }
+
+ CompoundStmt *getCompoundBody() { return (CompoundStmt*)getBody(); }
+ void setBody(Stmt *B) { Body = B; }
+
+ /// \brief Returns whether this specific method is a definition.
+ bool isThisDeclarationADefinition() const { return hasBody(); }
+
+ // Implement isa/cast/dyncast/etc.
+ static bool classof(const Decl *D) { return classofKind(D->getKind()); }
+ 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));
+ }
+
+ friend class ASTDeclReader;
+ friend class ASTDeclWriter;
+};
+
+/// Describes the variance of a given generic parameter.
+enum class ObjCTypeParamVariance : uint8_t {
+ /// The parameter is invariant: must match exactly.
+ Invariant,
+ /// The parameter is covariant, e.g., X<T> is a subtype of X<U> when
+ /// the type parameter is covariant and T is a subtype of U.
+ Covariant,
+ /// The parameter is contravariant, e.g., X<T> is a subtype of X<U>
+ /// when the type parameter is covariant and U is a subtype of T.
+ Contravariant,
+};
+
+/// Represents the declaration of an Objective-C type parameter.
+///
+/// \code
+/// @interface NSDictionary<Key : id<NSCopying>, Value>
+/// @end
+/// \endcode
+///
+/// In the example above, both \c Key and \c Value are represented by
+/// \c ObjCTypeParamDecl. \c Key has an explicit bound of \c id<NSCopying>,
+/// while \c Value gets an implicit bound of \c id.
+///
+/// Objective-C type parameters are typedef-names in the grammar,
+class ObjCTypeParamDecl : public TypedefNameDecl {
+ void anchor() override;
+
+ /// Index of this type parameter in the type parameter list.
+ unsigned Index : 14;
+
+ /// The variance of the type parameter.
+ unsigned Variance : 2;
+
+ /// The location of the variance, if any.
+ SourceLocation VarianceLoc;
+
+ /// The location of the ':', which will be valid when the bound was
+ /// explicitly specified.
+ SourceLocation ColonLoc;
+
+ ObjCTypeParamDecl(ASTContext &ctx, DeclContext *dc,
+ ObjCTypeParamVariance variance, SourceLocation varianceLoc,
+ unsigned index,
+ SourceLocation nameLoc, IdentifierInfo *name,
+ SourceLocation colonLoc, TypeSourceInfo *boundInfo)
+ : TypedefNameDecl(ObjCTypeParam, ctx, dc, nameLoc, nameLoc, name,
+ boundInfo),
+ Index(index), Variance(static_cast<unsigned>(variance)),
+ VarianceLoc(varianceLoc), ColonLoc(colonLoc) { }
+
+public:
+ static ObjCTypeParamDecl *Create(ASTContext &ctx, DeclContext *dc,
+ ObjCTypeParamVariance variance,
+ SourceLocation varianceLoc,
+ unsigned index,
+ SourceLocation nameLoc,
+ IdentifierInfo *name,
+ SourceLocation colonLoc,
+ TypeSourceInfo *boundInfo);
+ static ObjCTypeParamDecl *CreateDeserialized(ASTContext &ctx, unsigned ID);
+
+ SourceRange getSourceRange() const override LLVM_READONLY;
+
+ /// Determine the variance of this type parameter.
+ ObjCTypeParamVariance getVariance() const {
+ return static_cast<ObjCTypeParamVariance>(Variance);
+ }
+
+ /// Set the variance of this type parameter.
+ void setVariance(ObjCTypeParamVariance variance) {
+ Variance = static_cast<unsigned>(variance);
+ }
+
+ /// Retrieve the location of the variance keyword.
+ SourceLocation getVarianceLoc() const { return VarianceLoc; }
+
+ /// Retrieve the index into its type parameter list.
+ unsigned getIndex() const { return Index; }
+
+ /// Whether this type parameter has an explicitly-written type bound, e.g.,
+ /// "T : NSView".
+ bool hasExplicitBound() const { return ColonLoc.isValid(); }
+
+ /// Retrieve the location of the ':' separating the type parameter name
+ /// from the explicitly-specified bound.
+ SourceLocation getColonLoc() const { return ColonLoc; }
+
+ // Implement isa/cast/dyncast/etc.
+ static bool classof(const Decl *D) { return classofKind(D->getKind()); }
+ static bool classofKind(Kind K) { return K == ObjCTypeParam; }
+
+ friend class ASTDeclReader;
+ friend class ASTDeclWriter;
+};
+
+/// Stores a list of Objective-C type parameters for a parameterized class
+/// or a category/extension thereof.
+///
+/// \code
+/// @interface NSArray<T> // stores the <T>
+/// @end
+/// \endcode
+class ObjCTypeParamList final
+ : private llvm::TrailingObjects<ObjCTypeParamList, ObjCTypeParamDecl *> {
+ /// Stores the components of a SourceRange as a POD.
+ struct PODSourceRange {
+ unsigned Begin;
+ unsigned End;
+ };
+
+ union {
+ /// Location of the left and right angle brackets.
+ PODSourceRange Brackets;
+
+ // Used only for alignment.
+ ObjCTypeParamDecl *AlignmentHack;
+ };
+
+ /// The number of parameters in the list, which are tail-allocated.
+ unsigned NumParams;
+
+ ObjCTypeParamList(SourceLocation lAngleLoc,
+ ArrayRef<ObjCTypeParamDecl *> typeParams,
+ SourceLocation rAngleLoc);
+
+public:
+ /// Create a new Objective-C type parameter list.
+ static ObjCTypeParamList *create(ASTContext &ctx,
+ SourceLocation lAngleLoc,
+ ArrayRef<ObjCTypeParamDecl *> typeParams,
+ SourceLocation rAngleLoc);
+
+ /// Iterate through the type parameters in the list.
+ typedef ObjCTypeParamDecl **iterator;
+
+ iterator begin() { return getTrailingObjects<ObjCTypeParamDecl *>(); }
+
+ iterator end() { return begin() + size(); }
+
+ /// Determine the number of type parameters in this list.
+ unsigned size() const { return NumParams; }
+
+ // Iterate through the type parameters in the list.
+ typedef ObjCTypeParamDecl * const *const_iterator;
+
+ const_iterator begin() const {
+ return getTrailingObjects<ObjCTypeParamDecl *>();
+ }
+
+ const_iterator end() const {
+ return begin() + size();
+ }
+
+ ObjCTypeParamDecl *front() const {
+ assert(size() > 0 && "empty Objective-C type parameter list");
+ return *begin();
+ }
+
+ ObjCTypeParamDecl *back() const {
+ assert(size() > 0 && "empty Objective-C type parameter list");
+ return *(end() - 1);
+ }
+
+ SourceLocation getLAngleLoc() const {
+ return SourceLocation::getFromRawEncoding(Brackets.Begin);
+ }
+ SourceLocation getRAngleLoc() const {
+ return SourceLocation::getFromRawEncoding(Brackets.End);
+ }
+ SourceRange getSourceRange() const {
+ return SourceRange(getLAngleLoc(), getRAngleLoc());
+ }
+
+ /// Gather the default set of type arguments to be substituted for
+ /// these type parameters when dealing with an unspecialized type.
+ void gatherDefaultTypeArgs(SmallVectorImpl<QualType> &typeArgs) const;
+ friend TrailingObjects;
+};
+
+/// ObjCContainerDecl - Represents a container for method declarations.
+/// Current sub-classes are ObjCInterfaceDecl, ObjCCategoryDecl,
+/// ObjCProtocolDecl, and ObjCImplDecl.
+///
+class ObjCContainerDecl : public NamedDecl, public DeclContext {
+ void anchor() override;
+
+ SourceLocation AtStart;
+
+ // 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,
+ IdentifierInfo *Id, SourceLocation nameLoc,
+ SourceLocation atStartLoc)
+ : NamedDecl(DK, DC, nameLoc, Id), DeclContext(DK), AtStart(atStartLoc) {}
+
+ // Iterator access to properties.
+ typedef specific_decl_iterator<ObjCPropertyDecl> prop_iterator;
+ typedef llvm::iterator_range<specific_decl_iterator<ObjCPropertyDecl>>
+ prop_range;
+
+ prop_range properties() const { return prop_range(prop_begin(), prop_end()); }
+ 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;
+ typedef llvm::iterator_range<specific_decl_iterator<ObjCMethodDecl>>
+ method_range;
+
+ method_range methods() const {
+ return method_range(meth_begin(), meth_end());
+ }
+ 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;
+ typedef llvm::iterator_range<instmeth_iterator> instmeth_range;
+
+ instmeth_range instance_methods() const {
+ return instmeth_range(instmeth_begin(), instmeth_end());
+ }
+ 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;
+ typedef llvm::iterator_range<classmeth_iterator> classmeth_range;
+
+ classmeth_range class_methods() const {
+ return classmeth_range(classmeth_begin(), classmeth_end());
+ }
+ 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,
+ bool AllowHidden = false) const;
+ ObjCMethodDecl *getInstanceMethod(Selector Sel,
+ bool AllowHidden = false) const {
+ return getMethod(Sel, true/*isInstance*/, AllowHidden);
+ }
+ ObjCMethodDecl *getClassMethod(Selector Sel, bool AllowHidden = false) const {
+ return getMethod(Sel, false/*isInstance*/, AllowHidden);
+ }
+ bool HasUserDeclaredSetterMethod(const ObjCPropertyDecl *P) const;
+ ObjCIvarDecl *getIvarDecl(IdentifierInfo *Id) const;
+
+ ObjCPropertyDecl *
+ FindPropertyDeclaration(const IdentifierInfo *PropertyId) const;
+
+ typedef llvm::DenseMap<IdentifierInfo*, ObjCPropertyDecl*> PropertyMap;
+
+ typedef llvm::DenseMap<const ObjCProtocolDecl *, ObjCPropertyDecl*>
+ ProtocolPropertyMap;
+
+ typedef llvm::SmallVector<ObjCPropertyDecl*, 8> PropertyDeclOrder;
+
+ /// This routine collects list of properties to be implemented in the class.
+ /// This includes, class's and its conforming protocols' properties.
+ /// Note, the superclass's properties are not included in the list.
+ virtual void collectPropertiesToImplement(PropertyMap &PM,
+ PropertyDeclOrder &PO) const {}
+
+ SourceLocation getAtStartLoc() const { return AtStart; }
+ void setAtStartLoc(SourceLocation Loc) { AtStart = Loc; }
+
+ // Marks the end of the container.
+ SourceRange getAtEndRange() const {
+ return AtEnd;
+ }
+ void setAtEndRange(SourceRange atEnd) {
+ AtEnd = atEnd;
+ }
+
+ SourceRange getSourceRange() const override LLVM_READONLY {
+ return SourceRange(AtStart, getAtEndRange().getEnd());
+ }
+
+ // Implement isa/cast/dyncast/etc.
+ static bool classof(const Decl *D) { return classofKind(D->getKind()); }
+ 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));
+ }
+};
+
+/// \brief Represents an ObjC class declaration.
+///
+/// For example:
+///
+/// \code
+/// // 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.
+/// \endcode
+///
+/// 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
+ , public Redeclarable<ObjCInterfaceDecl> {
+ void anchor() override;
+
+ /// 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;
+
+ struct DefinitionData {
+ /// \brief The definition of this class, for quick access from any
+ /// declaration.
+ ObjCInterfaceDecl *Definition;
+
+ /// When non-null, this is always an ObjCObjectType.
+ TypeSourceInfo *SuperClassTInfo;
+
+ /// 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 wherever possible.
+ ObjCCategoryDecl *CategoryList;
+
+ /// IvarList - List of all ivars defined by this class; including class
+ /// extensions and implementation. This list is built lazily.
+ ObjCIvarDecl *IvarList;
+
+ /// \brief Indicates that the contents of this Objective-C class will be
+ /// completed by the external AST source when required.
+ mutable bool ExternallyCompleted : 1;
+
+ /// \brief Indicates that the ivar cache does not yet include ivars
+ /// declared in the implementation.
+ mutable bool IvarListMissingImplementation : 1;
+
+ /// Indicates that this interface decl contains at least one initializer
+ /// marked with the 'objc_designated_initializer' attribute.
+ bool HasDesignatedInitializers : 1;
+
+ enum InheritedDesignatedInitializersState {
+ /// We didn't calculate whether the designated initializers should be
+ /// inherited or not.
+ IDI_Unknown = 0,
+ /// Designated initializers are inherited for the super class.
+ IDI_Inherited = 1,
+ /// The class does not inherit designated initializers.
+ IDI_NotInherited = 2
+ };
+ /// One of the \c InheritedDesignatedInitializersState enumeratos.
+ mutable unsigned InheritedDesignatedInitializers : 2;
+
+ /// \brief The location of the last location in this declaration, before
+ /// the properties/methods. For example, this will be the '>', '}', or
+ /// identifier,
+ SourceLocation EndLoc;
+
+ DefinitionData() : Definition(), SuperClassTInfo(), CategoryList(), IvarList(),
+ ExternallyCompleted(),
+ IvarListMissingImplementation(true),
+ HasDesignatedInitializers(),
+ InheritedDesignatedInitializers(IDI_Unknown) { }
+ };
+
+ ObjCInterfaceDecl(const ASTContext &C, DeclContext *DC, SourceLocation AtLoc,
+ IdentifierInfo *Id, ObjCTypeParamList *typeParamList,
+ SourceLocation CLoc, ObjCInterfaceDecl *PrevDecl,
+ bool IsInternal);
+
+ void LoadExternalDefinition() const;
+
+ /// The type parameters associated with this class, if any.
+ ObjCTypeParamList *TypeParamList;
+
+ /// \brief Contains a pointer to the data associated with this class,
+ /// which will be NULL if this class has not yet been defined.
+ ///
+ /// The bit indicates when we don't need to check for out-of-date
+ /// declarations. It will be set unless modules are enabled.
+ llvm::PointerIntPair<DefinitionData *, 1, bool> Data;
+
+ DefinitionData &data() const {
+ assert(Data.getPointer() && "Declaration has no definition!");
+ return *Data.getPointer();
+ }
+
+ /// \brief Allocate the definition data for this class.
+ void allocateDefinitionData();
+
+ typedef Redeclarable<ObjCInterfaceDecl> redeclarable_base;
+ ObjCInterfaceDecl *getNextRedeclarationImpl() override {
+ return getNextRedeclaration();
+ }
+ ObjCInterfaceDecl *getPreviousDeclImpl() override {
+ return getPreviousDecl();
+ }
+ ObjCInterfaceDecl *getMostRecentDeclImpl() override {
+ return getMostRecentDecl();
+ }
+
+public:
+ static ObjCInterfaceDecl *Create(const ASTContext &C, DeclContext *DC,
+ SourceLocation atLoc,
+ IdentifierInfo *Id,
+ ObjCTypeParamList *typeParamList,
+ ObjCInterfaceDecl *PrevDecl,
+ SourceLocation ClassLoc = SourceLocation(),
+ bool isInternal = false);
+
+ static ObjCInterfaceDecl *CreateDeserialized(const ASTContext &C, unsigned ID);
+
+ /// Retrieve the type parameters of this class.
+ ///
+ /// This function looks for a type parameter list for the given
+ /// class; if the class has been declared (with \c \@class) but not
+ /// defined (with \c \@interface), it will search for a declaration that
+ /// has type parameters, skipping any declarations that do not.
+ ObjCTypeParamList *getTypeParamList() const;
+
+ /// Set the type parameters of this class.
+ ///
+ /// This function is used by the AST importer, which must import the type
+ /// parameters after creating their DeclContext to avoid loops.
+ void setTypeParamList(ObjCTypeParamList *TPL);
+
+ /// Retrieve the type parameters written on this particular declaration of
+ /// the class.
+ ObjCTypeParamList *getTypeParamListAsWritten() const {
+ return TypeParamList;
+ }
+
+ SourceRange getSourceRange() const override LLVM_READONLY {
+ if (isThisDeclarationADefinition())
+ return ObjCContainerDecl::getSourceRange();
+
+ return SourceRange(getAtStartLoc(), getLocation());
+ }
+
+ /// \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();
+
+ /// Indicate that this interface decl contains at least one initializer
+ /// marked with the 'objc_designated_initializer' attribute.
+ void setHasDesignatedInitializers();
+
+ /// Returns true if this interface decl contains at least one initializer
+ /// marked with the 'objc_designated_initializer' attribute.
+ bool hasDesignatedInitializers() const;
+
+ /// Returns true if this interface decl declares a designated initializer
+ /// or it inherites one from its super class.
+ bool declaresOrInheritsDesignatedInitializers() const {
+ return hasDesignatedInitializers() || inheritsDesignatedInitializers();
+ }
+
+ const ObjCProtocolList &getReferencedProtocols() const {
+ assert(hasDefinition() && "Caller did not check for forward reference!");
+ if (data().ExternallyCompleted)
+ LoadExternalDefinition();
+
+ return data().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 ? getCategoryInstanceMethod(Sel)
+ : getCategoryClassMethod(Sel);
+ }
+
+ typedef ObjCProtocolList::iterator protocol_iterator;
+ typedef llvm::iterator_range<protocol_iterator> protocol_range;
+
+ protocol_range protocols() const {
+ return protocol_range(protocol_begin(), protocol_end());
+ }
+ protocol_iterator protocol_begin() const {
+ // FIXME: Should make sure no callers ever do this.
+ if (!hasDefinition())
+ return protocol_iterator();
+
+ if (data().ExternallyCompleted)
+ LoadExternalDefinition();
+
+ return data().ReferencedProtocols.begin();
+ }
+ protocol_iterator protocol_end() const {
+ // FIXME: Should make sure no callers ever do this.
+ if (!hasDefinition())
+ return protocol_iterator();
+
+ if (data().ExternallyCompleted)
+ LoadExternalDefinition();
+
+ return data().ReferencedProtocols.end();
+ }
+
+ typedef ObjCProtocolList::loc_iterator protocol_loc_iterator;
+ typedef llvm::iterator_range<protocol_loc_iterator> protocol_loc_range;
+
+ protocol_loc_range protocol_locs() const {
+ return protocol_loc_range(protocol_loc_begin(), protocol_loc_end());
+ }
+ protocol_loc_iterator protocol_loc_begin() const {
+ // FIXME: Should make sure no callers ever do this.
+ if (!hasDefinition())
+ return protocol_loc_iterator();
+
+ if (data().ExternallyCompleted)
+ LoadExternalDefinition();
+
+ return data().ReferencedProtocols.loc_begin();
+ }
+
+ protocol_loc_iterator protocol_loc_end() const {
+ // FIXME: Should make sure no callers ever do this.
+ if (!hasDefinition())
+ return protocol_loc_iterator();
+
+ if (data().ExternallyCompleted)
+ LoadExternalDefinition();
+
+ return data().ReferencedProtocols.loc_end();
+ }
+
+ typedef ObjCList<ObjCProtocolDecl>::iterator all_protocol_iterator;
+ typedef llvm::iterator_range<all_protocol_iterator> all_protocol_range;
+
+ all_protocol_range all_referenced_protocols() const {
+ return all_protocol_range(all_referenced_protocol_begin(),
+ all_referenced_protocol_end());
+ }
+ all_protocol_iterator all_referenced_protocol_begin() const {
+ // FIXME: Should make sure no callers ever do this.
+ if (!hasDefinition())
+ return all_protocol_iterator();
+
+ if (data().ExternallyCompleted)
+ LoadExternalDefinition();
+
+ return data().AllReferencedProtocols.empty()
+ ? protocol_begin()
+ : data().AllReferencedProtocols.begin();
+ }
+ all_protocol_iterator all_referenced_protocol_end() const {
+ // FIXME: Should make sure no callers ever do this.
+ if (!hasDefinition())
+ return all_protocol_iterator();
+
+ if (data().ExternallyCompleted)
+ LoadExternalDefinition();
+
+ return data().AllReferencedProtocols.empty()
+ ? protocol_end()
+ : data().AllReferencedProtocols.end();
+ }
+
+ typedef specific_decl_iterator<ObjCIvarDecl> ivar_iterator;
+ typedef llvm::iterator_range<specific_decl_iterator<ObjCIvarDecl>> ivar_range;
+
+ ivar_range ivars() const { return ivar_range(ivar_begin(), ivar_end()); }
+ ivar_iterator ivar_begin() const {
+ if (const ObjCInterfaceDecl *Def = getDefinition())
+ return ivar_iterator(Def->decls_begin());
+
+ // FIXME: Should make sure no callers ever do this.
+ return ivar_iterator();
+ }
+ ivar_iterator ivar_end() const {
+ if (const ObjCInterfaceDecl *Def = getDefinition())
+ return ivar_iterator(Def->decls_end());
+
+ // FIXME: Should make sure no callers ever do this.
+ return ivar_iterator();
+ }
+
+ 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();
+ const ObjCIvarDecl *all_declared_ivar_begin() const {
+ // Even though this modifies IvarList, it's conceptually const:
+ // the ivar chain is essentially a cached property of ObjCInterfaceDecl.
+ return const_cast<ObjCInterfaceDecl *>(this)->all_declared_ivar_begin();
+ }
+ void setIvarList(ObjCIvarDecl *ivar) { data().IvarList = ivar; }
+
+ /// setProtocolList - Set the list of protocols that this interface
+ /// implements.
+ void setProtocolList(ObjCProtocolDecl *const* List, unsigned Num,
+ const SourceLocation *Locs, ASTContext &C) {
+ data().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);
+
+ /// Produce a name to be used for class's metadata. It comes either via
+ /// objc_runtime_name attribute or class name.
+ StringRef getObjCRuntimeNameAsString() const;
+
+ /// Returns the designated initializers for the interface.
+ ///
+ /// If this declaration does not have methods marked as designated
+ /// initializers then the interface inherits the designated initializers of
+ /// its super class.
+ void getDesignatedInitializers(
+ llvm::SmallVectorImpl<const ObjCMethodDecl *> &Methods) const;
+
+ /// Returns true if the given selector is a designated initializer for the
+ /// interface.
+ ///
+ /// If this declaration does not have methods marked as designated
+ /// initializers then the interface inherits the designated initializers of
+ /// its super class.
+ ///
+ /// \param InitMethod if non-null and the function returns true, it receives
+ /// the method that was marked as a designated initializer.
+ bool
+ isDesignatedInitializer(Selector Sel,
+ const ObjCMethodDecl **InitMethod = nullptr) const;
+
+ /// \brief Determine whether this particular declaration of this class is
+ /// actually also a definition.
+ bool isThisDeclarationADefinition() const {
+ return getDefinition() == this;
+ }
+
+ /// \brief Determine whether this class has been defined.
+ bool hasDefinition() const {
+ // If the name of this class is out-of-date, bring it up-to-date, which
+ // might bring in a definition.
+ // Note: a null value indicates that we don't have a definition and that
+ // modules are enabled.
+ if (!Data.getOpaqueValue())
+ getMostRecentDecl();
+
+ return Data.getPointer();
+ }
+
+ /// \brief Retrieve the definition of this class, or NULL if this class
+ /// has been forward-declared (with \@class) but not yet defined (with
+ /// \@interface).
+ ObjCInterfaceDecl *getDefinition() {
+ return hasDefinition()? Data.getPointer()->Definition : nullptr;
+ }
+
+ /// \brief Retrieve the definition of this class, or NULL if this class
+ /// has been forward-declared (with \@class) but not yet defined (with
+ /// \@interface).
+ const ObjCInterfaceDecl *getDefinition() const {
+ return hasDefinition()? Data.getPointer()->Definition : nullptr;
+ }
+
+ /// \brief Starts the definition of this Objective-C class, taking it from
+ /// a forward declaration (\@class) to a definition (\@interface).
+ void startDefinition();
+
+ /// Retrieve the superclass type.
+ const ObjCObjectType *getSuperClassType() const {
+ if (TypeSourceInfo *TInfo = getSuperClassTInfo())
+ return TInfo->getType()->castAs<ObjCObjectType>();
+
+ return nullptr;
+ }
+
+ // Retrieve the type source information for the superclass.
+ TypeSourceInfo *getSuperClassTInfo() const {
+ // FIXME: Should make sure no callers ever do this.
+ if (!hasDefinition())
+ return nullptr;
+
+ if (data().ExternallyCompleted)
+ LoadExternalDefinition();
+
+ return data().SuperClassTInfo;
+ }
+
+ // Retrieve the declaration for the superclass of this class, which
+ // does not include any type arguments that apply to the superclass.
+ ObjCInterfaceDecl *getSuperClass() const;
+
+ void setSuperClass(TypeSourceInfo *superClass) {
+ data().SuperClassTInfo = superClass;
+ }
+
+ /// \brief Iterator that walks over the list of categories, filtering out
+ /// those that do not meet specific criteria.
+ ///
+ /// This class template is used for the various permutations of category
+ /// and extension iterators.
+ template<bool (*Filter)(ObjCCategoryDecl *)>
+ class filtered_category_iterator {
+ ObjCCategoryDecl *Current;
+
+ void findAcceptableCategory();
+
+ public:
+ typedef ObjCCategoryDecl * value_type;
+ typedef value_type reference;
+ typedef value_type pointer;
+ typedef std::ptrdiff_t difference_type;
+ typedef std::input_iterator_tag iterator_category;
+
+ filtered_category_iterator() : Current(nullptr) { }
+ explicit filtered_category_iterator(ObjCCategoryDecl *Current)
+ : Current(Current)
+ {
+ findAcceptableCategory();
+ }
+
+ reference operator*() const { return Current; }
+ pointer operator->() const { return Current; }
+
+ filtered_category_iterator &operator++();
+
+ filtered_category_iterator operator++(int) {
+ filtered_category_iterator Tmp = *this;
+ ++(*this);
+ return Tmp;
+ }
+
+ friend bool operator==(filtered_category_iterator X,
+ filtered_category_iterator Y) {
+ return X.Current == Y.Current;
+ }
+
+ friend bool operator!=(filtered_category_iterator X,
+ filtered_category_iterator Y) {
+ return X.Current != Y.Current;
+ }
+ };
+
+private:
+ /// \brief Test whether the given category is visible.
+ ///
+ /// Used in the \c visible_categories_iterator.
+ static bool isVisibleCategory(ObjCCategoryDecl *Cat);
+
+public:
+ /// \brief Iterator that walks over the list of categories and extensions
+ /// that are visible, i.e., not hidden in a non-imported submodule.
+ typedef filtered_category_iterator<isVisibleCategory>
+ visible_categories_iterator;
+
+ typedef llvm::iterator_range<visible_categories_iterator>
+ visible_categories_range;
+
+ visible_categories_range visible_categories() const {
+ return visible_categories_range(visible_categories_begin(),
+ visible_categories_end());
+ }
+
+ /// \brief Retrieve an iterator to the beginning of the visible-categories
+ /// list.
+ visible_categories_iterator visible_categories_begin() const {
+ return visible_categories_iterator(getCategoryListRaw());
+ }
+
+ /// \brief Retrieve an iterator to the end of the visible-categories list.
+ visible_categories_iterator visible_categories_end() const {
+ return visible_categories_iterator();
+ }
+
+ /// \brief Determine whether the visible-categories list is empty.
+ bool visible_categories_empty() const {
+ return visible_categories_begin() == visible_categories_end();
+ }
+
+private:
+ /// \brief Test whether the given category... is a category.
+ ///
+ /// Used in the \c known_categories_iterator.
+ static bool isKnownCategory(ObjCCategoryDecl *) { return true; }
+
+public:
+ /// \brief Iterator that walks over all of the known categories and
+ /// extensions, including those that are hidden.
+ typedef filtered_category_iterator<isKnownCategory> known_categories_iterator;
+ typedef llvm::iterator_range<known_categories_iterator>
+ known_categories_range;
+
+ known_categories_range known_categories() const {
+ return known_categories_range(known_categories_begin(),
+ known_categories_end());
+ }
+
+ /// \brief Retrieve an iterator to the beginning of the known-categories
+ /// list.
+ known_categories_iterator known_categories_begin() const {
+ return known_categories_iterator(getCategoryListRaw());
+ }
+
+ /// \brief Retrieve an iterator to the end of the known-categories list.
+ known_categories_iterator known_categories_end() const {
+ return known_categories_iterator();
+ }
+
+ /// \brief Determine whether the known-categories list is empty.
+ bool known_categories_empty() const {
+ return known_categories_begin() == known_categories_end();
+ }
+
+private:
+ /// \brief Test whether the given category is a visible extension.
+ ///
+ /// Used in the \c visible_extensions_iterator.
+ static bool isVisibleExtension(ObjCCategoryDecl *Cat);
+
+public:
+ /// \brief Iterator that walks over all of the visible extensions, skipping
+ /// any that are known but hidden.
+ typedef filtered_category_iterator<isVisibleExtension>
+ visible_extensions_iterator;
+
+ typedef llvm::iterator_range<visible_extensions_iterator>
+ visible_extensions_range;
+
+ visible_extensions_range visible_extensions() const {
+ return visible_extensions_range(visible_extensions_begin(),
+ visible_extensions_end());
+ }
+
+ /// \brief Retrieve an iterator to the beginning of the visible-extensions
+ /// list.
+ visible_extensions_iterator visible_extensions_begin() const {
+ return visible_extensions_iterator(getCategoryListRaw());
+ }
+
+ /// \brief Retrieve an iterator to the end of the visible-extensions list.
+ visible_extensions_iterator visible_extensions_end() const {
+ return visible_extensions_iterator();
+ }
+
+ /// \brief Determine whether the visible-extensions list is empty.
+ bool visible_extensions_empty() const {
+ return visible_extensions_begin() == visible_extensions_end();
+ }
+
+private:
+ /// \brief Test whether the given category is an extension.
+ ///
+ /// Used in the \c known_extensions_iterator.
+ static bool isKnownExtension(ObjCCategoryDecl *Cat);
+
+public:
+ /// \brief Iterator that walks over all of the known extensions.
+ typedef filtered_category_iterator<isKnownExtension>
+ known_extensions_iterator;
+ typedef llvm::iterator_range<known_extensions_iterator>
+ known_extensions_range;
+
+ known_extensions_range known_extensions() const {
+ return known_extensions_range(known_extensions_begin(),
+ known_extensions_end());
+ }
+
+ /// \brief Retrieve an iterator to the beginning of the known-extensions
+ /// list.
+ known_extensions_iterator known_extensions_begin() const {
+ return known_extensions_iterator(getCategoryListRaw());
+ }
+
+ /// \brief Retrieve an iterator to the end of the known-extensions list.
+ known_extensions_iterator known_extensions_end() const {
+ return known_extensions_iterator();
+ }
+
+ /// \brief Determine whether the known-extensions list is empty.
+ bool known_extensions_empty() const {
+ return known_extensions_begin() == known_extensions_end();
+ }
+
+ /// \brief Retrieve the raw pointer to the start of the category/extension
+ /// list.
+ ObjCCategoryDecl* getCategoryListRaw() const {
+ // FIXME: Should make sure no callers ever do this.
+ if (!hasDefinition())
+ return nullptr;
+
+ if (data().ExternallyCompleted)
+ LoadExternalDefinition();
+
+ return data().CategoryList;
+ }
+
+ /// \brief Set the raw pointer to the start of the category/extension
+ /// list.
+ void setCategoryListRaw(ObjCCategoryDecl *category) {
+ data().CategoryList = category;
+ }
+
+ ObjCPropertyDecl
+ *FindPropertyVisibleInPrimaryClass(IdentifierInfo *PropertyId) const;
+
+ void collectPropertiesToImplement(PropertyMap &PM,
+ PropertyDeclOrder &PO) const override;
+
+ /// 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 != nullptr) {
+ if (declaresSameEntity(this, I))
+ return true;
+
+ I = I->getSuperClass();
+ }
+ return false;
+ }
+
+ /// isArcWeakrefUnavailable - Checks for a class or one of its super classes
+ /// to be incompatible with __weak references. Returns true if it is.
+ bool isArcWeakrefUnavailable() const;
+
+ /// isObjCRequiresPropertyDefs - Checks that a class or one of its super
+ /// classes must not be auto-synthesized. Returns class decl. if it must not
+ /// be; 0, otherwise.
+ const ObjCInterfaceDecl *isObjCRequiresPropertyDefs() const;
+
+ ObjCIvarDecl *lookupInstanceVariable(IdentifierInfo *IVarName,
+ ObjCInterfaceDecl *&ClassDeclared);
+ ObjCIvarDecl *lookupInstanceVariable(IdentifierInfo *IVarName) {
+ ObjCInterfaceDecl *ClassDeclared;
+ return lookupInstanceVariable(IVarName, ClassDeclared);
+ }
+
+ ObjCProtocolDecl *lookupNestedProtocol(IdentifierInfo *Name);
+
+ // 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,
+ bool shallowCategoryLookup = false,
+ bool followSuper = true,
+ const ObjCCategoryDecl *C = nullptr) const;
+
+ /// Lookup an instance method for a given selector.
+ ObjCMethodDecl *lookupInstanceMethod(Selector Sel) const {
+ return lookupMethod(Sel, true/*isInstance*/);
+ }
+
+ /// Lookup a class method for a given selector.
+ ObjCMethodDecl *lookupClassMethod(Selector Sel) const {
+ return lookupMethod(Sel, false/*isInstance*/);
+ }
+ ObjCInterfaceDecl *lookupInheritedClass(const IdentifierInfo *ICName);
+
+ /// \brief Lookup a method in the classes implementation hierarchy.
+ ObjCMethodDecl *lookupPrivateMethod(const Selector &Sel,
+ bool Instance=true) const;
+
+ ObjCMethodDecl *lookupPrivateClassMethod(const Selector &Sel) {
+ return lookupPrivateMethod(Sel, false);
+ }
+
+ /// \brief Lookup a setter or getter in the class hierarchy,
+ /// including in all categories except for category passed
+ /// as argument.
+ ObjCMethodDecl *lookupPropertyAccessor(const Selector Sel,
+ const ObjCCategoryDecl *Cat) const {
+ return lookupMethod(Sel, true/*isInstance*/,
+ false/*shallowCategoryLookup*/,
+ true /* followsSuper */,
+ Cat);
+ }
+
+ SourceLocation getEndOfDefinitionLoc() const {
+ if (!hasDefinition())
+ return getLocation();
+
+ return data().EndLoc;
+ }
+
+ void setEndOfDefinitionLoc(SourceLocation LE) { data().EndLoc = LE; }
+
+ /// Retrieve the starting location of the superclass.
+ SourceLocation getSuperClassLoc() const;
+
+ /// 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 hasDefinition() ? data().Definition->isImplicit() : isImplicit();
+ }
+
+ /// 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);
+
+ typedef redeclarable_base::redecl_range redecl_range;
+ typedef redeclarable_base::redecl_iterator redecl_iterator;
+ using redeclarable_base::redecls_begin;
+ using redeclarable_base::redecls_end;
+ using redeclarable_base::redecls;
+ using redeclarable_base::getPreviousDecl;
+ using redeclarable_base::getMostRecentDecl;
+ using redeclarable_base::isFirstDecl;
+
+ /// Retrieves the canonical declaration of this Objective-C class.
+ ObjCInterfaceDecl *getCanonicalDecl() override { return getFirstDecl(); }
+ const ObjCInterfaceDecl *getCanonicalDecl() const { return getFirstDecl(); }
+
+ // 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 classofKind(Kind K) { return K == ObjCInterface; }
+
+ friend class ASTReader;
+ friend class ASTDeclReader;
+ friend class ASTDeclWriter;
+
+private:
+ const ObjCInterfaceDecl *findInterfaceWithDesignatedInitializers() const;
+ bool inheritsDesignatedInitializers() const;
+};
+
+/// 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 {
+ void anchor() override;
+
+public:
+ enum AccessControl {
+ None, Private, Protected, Public, Package
+ };
+
+private:
+ ObjCIvarDecl(ObjCContainerDecl *DC, SourceLocation StartLoc,
+ SourceLocation IdLoc, IdentifierInfo *Id,
+ QualType T, TypeSourceInfo *TInfo, AccessControl ac, Expr *BW,
+ bool synthesized)
+ : FieldDecl(ObjCIvar, DC, StartLoc, IdLoc, Id, T, TInfo, BW,
+ /*Mutable=*/false, /*HasInit=*/ICIS_NoInit),
+ NextIvar(nullptr), DeclAccess(ac), Synthesized(synthesized) {}
+
+public:
+ static ObjCIvarDecl *Create(ASTContext &C, ObjCContainerDecl *DC,
+ SourceLocation StartLoc, SourceLocation IdLoc,
+ IdentifierInfo *Id, QualType T,
+ TypeSourceInfo *TInfo,
+ AccessControl ac, Expr *BW = nullptr,
+ bool synthesized=false);
+
+ static ObjCIvarDecl *CreateDeserialized(ASTContext &C, unsigned ID);
+
+ /// \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; }
+ const ObjCIvarDecl *getNextIvar() const { 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; }
+
+ /// Retrieve the type of this instance variable when viewed as a member of a
+ /// specific object type.
+ QualType getUsageType(QualType objectType) const;
+
+ // Implement isa/cast/dyncast/etc.
+ static bool classof(const Decl *D) { return classofKind(D->getKind()); }
+ 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;
+};
+
+
+/// \brief Represents a field declaration created by an \@defs(...).
+class ObjCAtDefsFieldDecl : public FieldDecl {
+ void anchor() override;
+ ObjCAtDefsFieldDecl(DeclContext *DC, SourceLocation StartLoc,
+ SourceLocation IdLoc, IdentifierInfo *Id,
+ QualType T, Expr *BW)
+ : FieldDecl(ObjCAtDefsField, DC, StartLoc, IdLoc, Id, T,
+ /*TInfo=*/nullptr, // FIXME: Do ObjCAtDefs have declarators ?
+ BW, /*Mutable=*/false, /*HasInit=*/ICIS_NoInit) {}
+
+public:
+ static ObjCAtDefsFieldDecl *Create(ASTContext &C, DeclContext *DC,
+ SourceLocation StartLoc,
+ SourceLocation IdLoc, IdentifierInfo *Id,
+ QualType T, Expr *BW);
+
+ static ObjCAtDefsFieldDecl *CreateDeserialized(ASTContext &C, unsigned ID);
+
+ // Implement isa/cast/dyncast/etc.
+ static bool classof(const Decl *D) { return classofKind(D->getKind()); }
+ static bool classofKind(Kind K) { return K == ObjCAtDefsField; }
+};
+
+/// \brief Represents an Objective-C protocol declaration.
+///
+/// Objective-C protocols declare a pure abstract type (i.e., no instance
+/// variables are permitted). Protocols originally drew inspiration from
+/// C++ pure virtual functions (a C++ feature with nice semantics and lousy
+/// syntax:-). Here is an example:
+///
+/// \code
+/// \@protocol NSDraggingInfo <refproto1, refproto2>
+/// - (NSWindow *)draggingDestinationWindow;
+/// - (NSImage *)draggedImage;
+/// \@end
+/// \endcode
+///
+/// This says that NSDraggingInfo requires two methods and requires everything
+/// that the two "referenced protocols" 'refproto1' and 'refproto2' require as
+/// well.
+///
+/// \code
+/// \@interface ImplementsNSDraggingInfo : NSObject \<NSDraggingInfo>
+/// \@end
+/// \endcode
+///
+/// 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,
+ public Redeclarable<ObjCProtocolDecl> {
+ void anchor() override;
+
+ struct DefinitionData {
+ // \brief The declaration that defines this protocol.
+ ObjCProtocolDecl *Definition;
+
+ /// \brief Referenced protocols
+ ObjCProtocolList ReferencedProtocols;
+ };
+
+ /// \brief Contains a pointer to the data associated with this class,
+ /// which will be NULL if this class has not yet been defined.
+ ///
+ /// The bit indicates when we don't need to check for out-of-date
+ /// declarations. It will be set unless modules are enabled.
+ llvm::PointerIntPair<DefinitionData *, 1, bool> Data;
+
+ DefinitionData &data() const {
+ assert(Data.getPointer() && "Objective-C protocol has no definition!");
+ return *Data.getPointer();
+ }
+
+ ObjCProtocolDecl(ASTContext &C, DeclContext *DC, IdentifierInfo *Id,
+ SourceLocation nameLoc, SourceLocation atStartLoc,
+ ObjCProtocolDecl *PrevDecl);
+
+ void allocateDefinitionData();
+
+ typedef Redeclarable<ObjCProtocolDecl> redeclarable_base;
+ ObjCProtocolDecl *getNextRedeclarationImpl() override {
+ return getNextRedeclaration();
+ }
+ ObjCProtocolDecl *getPreviousDeclImpl() override {
+ return getPreviousDecl();
+ }
+ ObjCProtocolDecl *getMostRecentDeclImpl() override {
+ return getMostRecentDecl();
+ }
+
+public:
+ static ObjCProtocolDecl *Create(ASTContext &C, DeclContext *DC,
+ IdentifierInfo *Id,
+ SourceLocation nameLoc,
+ SourceLocation atStartLoc,
+ ObjCProtocolDecl *PrevDecl);
+
+ static ObjCProtocolDecl *CreateDeserialized(ASTContext &C, unsigned ID);
+
+ const ObjCProtocolList &getReferencedProtocols() const {
+ assert(hasDefinition() && "No definition available!");
+ return data().ReferencedProtocols;
+ }
+ typedef ObjCProtocolList::iterator protocol_iterator;
+ typedef llvm::iterator_range<protocol_iterator> protocol_range;
+
+ protocol_range protocols() const {
+ return protocol_range(protocol_begin(), protocol_end());
+ }
+ protocol_iterator protocol_begin() const {
+ if (!hasDefinition())
+ return protocol_iterator();
+
+ return data().ReferencedProtocols.begin();
+ }
+ protocol_iterator protocol_end() const {
+ if (!hasDefinition())
+ return protocol_iterator();
+
+ return data().ReferencedProtocols.end();
+ }
+ typedef ObjCProtocolList::loc_iterator protocol_loc_iterator;
+ typedef llvm::iterator_range<protocol_loc_iterator> protocol_loc_range;
+
+ protocol_loc_range protocol_locs() const {
+ return protocol_loc_range(protocol_loc_begin(), protocol_loc_end());
+ }
+ protocol_loc_iterator protocol_loc_begin() const {
+ if (!hasDefinition())
+ return protocol_loc_iterator();
+
+ return data().ReferencedProtocols.loc_begin();
+ }
+ protocol_loc_iterator protocol_loc_end() const {
+ if (!hasDefinition())
+ return protocol_loc_iterator();
+
+ return data().ReferencedProtocols.loc_end();
+ }
+ unsigned protocol_size() const {
+ if (!hasDefinition())
+ return 0;
+
+ return data().ReferencedProtocols.size();
+ }
+
+ /// setProtocolList - Set the list of protocols that this interface
+ /// implements.
+ void setProtocolList(ObjCProtocolDecl *const*List, unsigned Num,
+ const SourceLocation *Locs, ASTContext &C) {
+ assert(hasDefinition() && "Protocol is not defined");
+ data().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*/);
+ }
+
+ /// \brief Determine whether this protocol has a definition.
+ bool hasDefinition() const {
+ // If the name of this protocol is out-of-date, bring it up-to-date, which
+ // might bring in a definition.
+ // Note: a null value indicates that we don't have a definition and that
+ // modules are enabled.
+ if (!Data.getOpaqueValue())
+ getMostRecentDecl();
+
+ return Data.getPointer();
+ }
+
+ /// \brief Retrieve the definition of this protocol, if any.
+ ObjCProtocolDecl *getDefinition() {
+ return hasDefinition()? Data.getPointer()->Definition : nullptr;
+ }
+
+ /// \brief Retrieve the definition of this protocol, if any.
+ const ObjCProtocolDecl *getDefinition() const {
+ return hasDefinition()? Data.getPointer()->Definition : nullptr;
+ }
+
+ /// \brief Determine whether this particular declaration is also the
+ /// definition.
+ bool isThisDeclarationADefinition() const {
+ return getDefinition() == this;
+ }
+
+ /// \brief Starts the definition of this Objective-C protocol.
+ void startDefinition();
+
+ /// Produce a name to be used for protocol's metadata. It comes either via
+ /// objc_runtime_name attribute or protocol name.
+ StringRef getObjCRuntimeNameAsString() const;
+
+ SourceRange getSourceRange() const override LLVM_READONLY {
+ if (isThisDeclarationADefinition())
+ return ObjCContainerDecl::getSourceRange();
+
+ return SourceRange(getAtStartLoc(), getLocation());
+ }
+
+ typedef redeclarable_base::redecl_range redecl_range;
+ typedef redeclarable_base::redecl_iterator redecl_iterator;
+ using redeclarable_base::redecls_begin;
+ using redeclarable_base::redecls_end;
+ using redeclarable_base::redecls;
+ using redeclarable_base::getPreviousDecl;
+ using redeclarable_base::getMostRecentDecl;
+ using redeclarable_base::isFirstDecl;
+
+ /// Retrieves the canonical declaration of this Objective-C protocol.
+ ObjCProtocolDecl *getCanonicalDecl() override { return getFirstDecl(); }
+ const ObjCProtocolDecl *getCanonicalDecl() const { return getFirstDecl(); }
+
+ void collectPropertiesToImplement(PropertyMap &PM,
+ PropertyDeclOrder &PO) const override;
+
+ void collectInheritedProtocolProperties(const ObjCPropertyDecl *Property,
+ ProtocolPropertyMap &PM) const;
+
+ static bool classof(const Decl *D) { return classofKind(D->getKind()); }
+ static bool classofKind(Kind K) { return K == ObjCProtocol; }
+
+ friend class ASTReader;
+ friend class ASTDeclReader;
+ friend class ASTDeclWriter;
+};
+
+/// 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 {
+ void anchor() override;
+
+ /// Interface belonging to this category
+ ObjCInterfaceDecl *ClassInterface;
+
+ /// The type parameters associated with this category, if any.
+ ObjCTypeParamList *TypeParamList;
+
+ /// 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;
+
+ /// \brief The location of the category name in this declaration.
+ SourceLocation CategoryNameLoc;
+
+ /// class extension may have private ivars.
+ SourceLocation IvarLBraceLoc;
+ SourceLocation IvarRBraceLoc;
+
+ ObjCCategoryDecl(DeclContext *DC, SourceLocation AtLoc,
+ SourceLocation ClassNameLoc, SourceLocation CategoryNameLoc,
+ IdentifierInfo *Id, ObjCInterfaceDecl *IDecl,
+ ObjCTypeParamList *typeParamList,
+ SourceLocation IvarLBraceLoc=SourceLocation(),
+ SourceLocation IvarRBraceLoc=SourceLocation());
+
+public:
+
+ static ObjCCategoryDecl *Create(ASTContext &C, DeclContext *DC,
+ SourceLocation AtLoc,
+ SourceLocation ClassNameLoc,
+ SourceLocation CategoryNameLoc,
+ IdentifierInfo *Id,
+ ObjCInterfaceDecl *IDecl,
+ ObjCTypeParamList *typeParamList,
+ SourceLocation IvarLBraceLoc=SourceLocation(),
+ SourceLocation IvarRBraceLoc=SourceLocation());
+ static ObjCCategoryDecl *CreateDeserialized(ASTContext &C, unsigned ID);
+
+ ObjCInterfaceDecl *getClassInterface() { return ClassInterface; }
+ const ObjCInterfaceDecl *getClassInterface() const { return ClassInterface; }
+
+ /// Retrieve the type parameter list associated with this category or
+ /// extension.
+ ObjCTypeParamList *getTypeParamList() const { return TypeParamList; }
+
+ /// Set the type parameters of this category.
+ ///
+ /// This function is used by the AST importer, which must import the type
+ /// parameters after creating their DeclContext to avoid loops.
+ void setTypeParamList(ObjCTypeParamList *TPL);
+
+
+ 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;
+ typedef llvm::iterator_range<protocol_iterator> protocol_range;
+
+ protocol_range protocols() const {
+ return protocol_range(protocol_begin(), protocol_end());
+ }
+ 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;
+ typedef llvm::iterator_range<protocol_loc_iterator> protocol_loc_range;
+
+ protocol_loc_range protocol_locs() const {
+ return protocol_loc_range(protocol_loc_begin(), protocol_loc_end());
+ }
+ 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; }
+
+ /// \brief Retrieve the pointer to the next stored category (or extension),
+ /// which may be hidden.
+ ObjCCategoryDecl *getNextClassCategoryRaw() const {
+ return NextClassCategory;
+ }
+
+ bool IsClassExtension() const { return getIdentifier() == nullptr; }
+
+ typedef specific_decl_iterator<ObjCIvarDecl> ivar_iterator;
+ typedef llvm::iterator_range<specific_decl_iterator<ObjCIvarDecl>> ivar_range;
+
+ ivar_range ivars() const { return ivar_range(ivar_begin(), ivar_end()); }
+ 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 getCategoryNameLoc() const { return CategoryNameLoc; }
+ void setCategoryNameLoc(SourceLocation Loc) { CategoryNameLoc = Loc; }
+
+ void setIvarLBraceLoc(SourceLocation Loc) { IvarLBraceLoc = Loc; }
+ SourceLocation getIvarLBraceLoc() const { return IvarLBraceLoc; }
+ void setIvarRBraceLoc(SourceLocation Loc) { IvarRBraceLoc = Loc; }
+ SourceLocation getIvarRBraceLoc() const { return IvarRBraceLoc; }
+
+ static bool classof(const Decl *D) { return classofKind(D->getKind()); }
+ static bool classofKind(Kind K) { return K == ObjCCategory; }
+
+ friend class ASTDeclReader;
+ friend class ASTDeclWriter;
+};
+
+class ObjCImplDecl : public ObjCContainerDecl {
+ void anchor() override;
+
+ /// Class interface for this class/category implementation
+ ObjCInterfaceDecl *ClassInterface;
+
+protected:
+ ObjCImplDecl(Kind DK, DeclContext *DC,
+ ObjCInterfaceDecl *classInterface,
+ SourceLocation nameLoc, SourceLocation atStartLoc)
+ : ObjCContainerDecl(DK, DC,
+ classInterface? classInterface->getIdentifier()
+ : nullptr,
+ nameLoc, atStartLoc),
+ 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;
+ typedef llvm::iterator_range<specific_decl_iterator<ObjCPropertyImplDecl>>
+ propimpl_range;
+
+ propimpl_range property_impls() const {
+ return propimpl_range(propimpl_begin(), propimpl_end());
+ }
+ 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 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 {
+ void anchor() override;
+
+ // Category name
+ IdentifierInfo *Id;
+
+ // Category name location
+ SourceLocation CategoryNameLoc;
+
+ ObjCCategoryImplDecl(DeclContext *DC, IdentifierInfo *Id,
+ ObjCInterfaceDecl *classInterface,
+ SourceLocation nameLoc, SourceLocation atStartLoc,
+ SourceLocation CategoryNameLoc)
+ : ObjCImplDecl(ObjCCategoryImpl, DC, classInterface, nameLoc, atStartLoc),
+ Id(Id), CategoryNameLoc(CategoryNameLoc) {}
+public:
+ static ObjCCategoryImplDecl *Create(ASTContext &C, DeclContext *DC,
+ IdentifierInfo *Id,
+ ObjCInterfaceDecl *classInterface,
+ SourceLocation nameLoc,
+ SourceLocation atStartLoc,
+ SourceLocation CategoryNameLoc);
+ static ObjCCategoryImplDecl *CreateDeserialized(ASTContext &C, unsigned ID);
+
+ /// getIdentifier - Get the identifier that names the category
+ /// interface associated with this implementation.
+ /// FIXME: This is a bad API, we are hiding NamedDecl::getIdentifier()
+ /// with a different meaning. 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;
+
+ SourceLocation getCategoryNameLoc() const { return CategoryNameLoc; }
+
+ /// 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 hiding NamedDecl::getName with a different
+ // meaning.
+ StringRef getName() const { return Id ? Id->getName() : StringRef(); }
+
+ /// @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 classofKind(Kind K) { return K == ObjCCategoryImpl;}
+
+ friend class ASTDeclReader;
+ friend class ASTDeclWriter;
+};
+
+raw_ostream &operator<<(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
+///
+/// In a non-fragile runtime, instance variables can appear in the class
+/// interface, class extensions (nameless categories), and in the implementation
+/// itself, as well as being synthesized as backing storage for properties.
+///
+/// In a fragile runtime, instance variables are specified in the class
+/// interface, \em not in the implementation. Nevertheless (for legacy reasons),
+/// we allow instance variables to be specified in the implementation. When
+/// specified, they need to be \em identical to the interface.
+class ObjCImplementationDecl : public ObjCImplDecl {
+ void anchor() override;
+ /// Implementation Class's super class.
+ ObjCInterfaceDecl *SuperClass;
+ SourceLocation SuperLoc;
+
+ /// \@implementation may have private ivars.
+ SourceLocation IvarLBraceLoc;
+ SourceLocation IvarRBraceLoc;
+
+ /// Support for ivar initialization.
+ /// \brief The arguments used to initialize the ivars
+ LazyCXXCtorInitializersPtr IvarInitializers;
+ unsigned NumIvarInitializers;
+
+ /// Do the ivars of this class require initialization other than
+ /// zero-initialization?
+ bool HasNonZeroConstructors : 1;
+
+ /// Do the ivars of this class require non-trivial destruction?
+ bool HasDestructors : 1;
+
+ ObjCImplementationDecl(DeclContext *DC,
+ ObjCInterfaceDecl *classInterface,
+ ObjCInterfaceDecl *superDecl,
+ SourceLocation nameLoc, SourceLocation atStartLoc,
+ SourceLocation superLoc = SourceLocation(),
+ SourceLocation IvarLBraceLoc=SourceLocation(),
+ SourceLocation IvarRBraceLoc=SourceLocation())
+ : ObjCImplDecl(ObjCImplementation, DC, classInterface, nameLoc, atStartLoc),
+ SuperClass(superDecl), SuperLoc(superLoc), IvarLBraceLoc(IvarLBraceLoc),
+ IvarRBraceLoc(IvarRBraceLoc),
+ IvarInitializers(nullptr), NumIvarInitializers(0),
+ HasNonZeroConstructors(false), HasDestructors(false) {}
+public:
+ static ObjCImplementationDecl *Create(ASTContext &C, DeclContext *DC,
+ ObjCInterfaceDecl *classInterface,
+ ObjCInterfaceDecl *superDecl,
+ SourceLocation nameLoc,
+ SourceLocation atStartLoc,
+ SourceLocation superLoc = SourceLocation(),
+ SourceLocation IvarLBraceLoc=SourceLocation(),
+ SourceLocation IvarRBraceLoc=SourceLocation());
+
+ static ObjCImplementationDecl *CreateDeserialized(ASTContext &C, unsigned ID);
+
+ /// 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;
+
+ typedef llvm::iterator_range<init_iterator> init_range;
+ typedef llvm::iterator_range<init_const_iterator> init_const_range;
+
+ init_range inits() { return init_range(init_begin(), init_end()); }
+ init_const_range inits() const {
+ return init_const_range(init_begin(), init_end());
+ }
+
+ /// init_begin() - Retrieve an iterator to the first initializer.
+ init_iterator init_begin() {
+ const auto *ConstThis = this;
+ return const_cast<init_iterator>(ConstThis->init_begin());
+ }
+ /// begin() - Retrieve an iterator to the first initializer.
+ init_const_iterator init_begin() const;
+
+ /// init_end() - Retrieve an iterator past the last initializer.
+ init_iterator init_end() {
+ return init_begin() + NumIvarInitializers;
+ }
+ /// end() - Retrieve an iterator past the last initializer.
+ init_const_iterator init_end() const {
+ return init_begin() + 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);
+
+ /// Do any of the ivars of this class (not counting its base classes)
+ /// require construction other than zero-initialization?
+ bool hasNonZeroConstructors() const { return HasNonZeroConstructors; }
+ void setHasNonZeroConstructors(bool val) { HasNonZeroConstructors = val; }
+
+ /// Do any of the ivars of this class (not counting its base classes)
+ /// require non-trivial destruction?
+ bool hasDestructors() const { return HasDestructors; }
+ void setHasDestructors(bool val) { HasDestructors = 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 hiding NamedDecl::getName with a different
+ // meaning.
+ StringRef getName() const {
+ assert(getIdentifier() && "Name is not a simple identifier");
+ return getIdentifier()->getName();
+ }
+
+ /// @brief Get the name of the class associated with this interface.
+ //
+ // FIXME: Move to StringRef API.
+ std::string getNameAsString() const {
+ return getName();
+ }
+
+ /// Produce a name to be used for class's metadata. It comes either via
+ /// class's objc_runtime_name attribute or class name.
+ StringRef getObjCRuntimeNameAsString() const;
+
+ const ObjCInterfaceDecl *getSuperClass() const { return SuperClass; }
+ ObjCInterfaceDecl *getSuperClass() { return SuperClass; }
+ SourceLocation getSuperClassLoc() const { return SuperLoc; }
+
+ void setSuperClass(ObjCInterfaceDecl * superCls) { SuperClass = superCls; }
+
+ void setIvarLBraceLoc(SourceLocation Loc) { IvarLBraceLoc = Loc; }
+ SourceLocation getIvarLBraceLoc() const { return IvarLBraceLoc; }
+ void setIvarRBraceLoc(SourceLocation Loc) { IvarRBraceLoc = Loc; }
+ SourceLocation getIvarRBraceLoc() const { return IvarRBraceLoc; }
+
+ typedef specific_decl_iterator<ObjCIvarDecl> ivar_iterator;
+ typedef llvm::iterator_range<specific_decl_iterator<ObjCIvarDecl>> ivar_range;
+
+ ivar_range ivars() const { return ivar_range(ivar_begin(), ivar_end()); }
+ 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 classofKind(Kind K) { return K == ObjCImplementation; }
+
+ friend class ASTDeclReader;
+ friend class ASTDeclWriter;
+};
+
+raw_ostream &operator<<(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 {
+ void anchor() override;
+ /// 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);
+
+ static ObjCCompatibleAliasDecl *CreateDeserialized(ASTContext &C,
+ unsigned ID);
+
+ 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 classofKind(Kind K) { return K == ObjCCompatibleAlias; }
+
+};
+
+/// \brief Represents one property declaration in an Objective-C interface.
+///
+/// For example:
+/// \code{.mm}
+/// \@property (assign, readwrite) int MyProperty;
+/// \endcode
+class ObjCPropertyDecl : public NamedDecl {
+ void anchor() override;
+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,
+ OBJC_PR_weak = 0x200,
+ OBJC_PR_strong = 0x400,
+ OBJC_PR_unsafe_unretained = 0x800,
+ /// Indicates that the nullability of the type was spelled with a
+ /// property attribute rather than a type qualifier.
+ OBJC_PR_nullability = 0x1000,
+ OBJC_PR_null_resettable = 0x2000
+ // Adding a property should change NumPropertyAttrsBits
+ };
+
+ enum {
+ /// \brief Number of bits fitting all the property attributes.
+ NumPropertyAttrsBits = 14
+ };
+
+ enum SetterKind { Assign, Retain, Copy, Weak };
+ enum PropertyControl { None, Required, Optional };
+private:
+ SourceLocation AtLoc; // location of \@property
+ SourceLocation LParenLoc; // location of '(' starting attribute list or null.
+ QualType DeclType;
+ TypeSourceInfo *DeclTypeSourceInfo;
+ unsigned PropertyAttributes : NumPropertyAttrsBits;
+ unsigned PropertyAttributesAsWritten : NumPropertyAttrsBits;
+ // \@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, SourceLocation LParenLocation,
+ QualType T, TypeSourceInfo *TSI,
+ PropertyControl propControl)
+ : NamedDecl(ObjCProperty, DC, L, Id), AtLoc(AtLocation),
+ LParenLoc(LParenLocation), DeclType(T), DeclTypeSourceInfo(TSI),
+ PropertyAttributes(OBJC_PR_noattr),
+ PropertyAttributesAsWritten(OBJC_PR_noattr),
+ PropertyImplementation(propControl),
+ GetterName(Selector()),
+ SetterName(Selector()),
+ GetterMethodDecl(nullptr), SetterMethodDecl(nullptr),
+ PropertyIvarDecl(nullptr) {}
+
+public:
+ static ObjCPropertyDecl *Create(ASTContext &C, DeclContext *DC,
+ SourceLocation L,
+ IdentifierInfo *Id, SourceLocation AtLocation,
+ SourceLocation LParenLocation,
+ QualType T,
+ TypeSourceInfo *TSI,
+ PropertyControl propControl = None);
+
+ static ObjCPropertyDecl *CreateDeserialized(ASTContext &C, unsigned ID);
+
+ SourceLocation getAtLoc() const { return AtLoc; }
+ void setAtLoc(SourceLocation L) { AtLoc = L; }
+
+ SourceLocation getLParenLoc() const { return LParenLoc; }
+ void setLParenLoc(SourceLocation L) { LParenLoc = L; }
+
+ TypeSourceInfo *getTypeSourceInfo() const { return DeclTypeSourceInfo; }
+
+ QualType getType() const { return DeclType; }
+
+ void setType(QualType T, TypeSourceInfo *TSI) {
+ DeclType = T;
+ DeclTypeSourceInfo = TSI;
+ }
+
+ /// Retrieve the type when this property is used with a specific base object
+ /// type.
+ QualType getUsageType(QualType objectType) const;
+
+ PropertyAttributeKind getPropertyAttributes() const {
+ return PropertyAttributeKind(PropertyAttributes);
+ }
+ void setPropertyAttributes(PropertyAttributeKind PRVal) {
+ PropertyAttributes |= PRVal;
+ }
+ void overwritePropertyAttributes(unsigned PRVal) {
+ PropertyAttributes = PRVal;
+ }
+
+ PropertyAttributeKind getPropertyAttributesAsWritten() const {
+ return PropertyAttributeKind(PropertyAttributesAsWritten);
+ }
+
+ void setPropertyAttributesAsWritten(PropertyAttributeKind PRVal) {
+ PropertyAttributesAsWritten = PRVal;
+ }
+
+ // Helper methods for accessing attributes.
+
+ /// isReadOnly - Return true iff the property has a setter.
+ bool isReadOnly() const {
+ return (PropertyAttributes & OBJC_PR_readonly);
+ }
+
+ /// isAtomic - Return true if the property is atomic.
+ bool isAtomic() const {
+ return (PropertyAttributes & OBJC_PR_atomic);
+ }
+
+ /// isRetaining - Return true if the property retains its value.
+ bool isRetaining() const {
+ return (PropertyAttributes &
+ (OBJC_PR_retain | OBJC_PR_strong | OBJC_PR_copy));
+ }
+
+ /// 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_strong)
+ return getType()->isBlockPointerType() ? Copy : Retain;
+ if (PropertyAttributes & OBJC_PR_retain)
+ return Retain;
+ if (PropertyAttributes & OBJC_PR_copy)
+ return Copy;
+ if (PropertyAttributes & OBJC_PR_weak)
+ return Weak;
+ 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;
+ }
+
+ SourceRange getSourceRange() const override LLVM_READONLY {
+ return SourceRange(AtLoc, getLocation());
+ }
+
+ /// Get the default name of the synthesized ivar.
+ IdentifierInfo *getDefaultSynthIvarName(ASTContext &Ctx) const;
+
+ /// Lookup a property by name in the specified DeclContext.
+ static ObjCPropertyDecl *findPropertyDecl(const DeclContext *DC,
+ const IdentifierInfo *propertyID);
+
+ static bool classof(const Decl *D) { return classofKind(D->getKind()); }
+ 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(nullptr), SetterCXXAssignment(nullptr) {
+ assert (PK == Dynamic || PropertyIvarDecl);
+ }
+
+public:
+ static ObjCPropertyImplDecl *Create(ASTContext &C, DeclContext *DC,
+ SourceLocation atLoc, SourceLocation L,
+ ObjCPropertyDecl *property,
+ Kind PK,
+ ObjCIvarDecl *ivarDecl,
+ SourceLocation ivarLoc);
+
+ static ObjCPropertyImplDecl *CreateDeserialized(ASTContext &C, unsigned ID);
+
+ SourceRange getSourceRange() const override LLVM_READONLY;
+
+ SourceLocation getLocStart() const LLVM_READONLY { 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;
+ }
+
+ /// \brief For \@synthesize, returns true if an ivar name was explicitly
+ /// specified.
+ ///
+ /// \code
+ /// \@synthesize int a = b; // true
+ /// \@synthesize int a; // false
+ /// \endcode
+ bool isIvarNameSpecified() const {
+ return IvarLoc.isValid() && IvarLoc != getLocation();
+ }
+
+ 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 classofKind(Decl::Kind K) { return K == ObjCPropertyImpl; }
+
+ friend class ASTDeclReader;
+};
+
+template<bool (*Filter)(ObjCCategoryDecl *)>
+void
+ObjCInterfaceDecl::filtered_category_iterator<Filter>::
+findAcceptableCategory() {
+ while (Current && !Filter(Current))
+ Current = Current->getNextClassCategoryRaw();
+}
+
+template<bool (*Filter)(ObjCCategoryDecl *)>
+inline ObjCInterfaceDecl::filtered_category_iterator<Filter> &
+ObjCInterfaceDecl::filtered_category_iterator<Filter>::operator++() {
+ Current = Current->getNextClassCategoryRaw();
+ findAcceptableCategory();
+ return *this;
+}
+
+inline bool ObjCInterfaceDecl::isVisibleCategory(ObjCCategoryDecl *Cat) {
+ return !Cat->isHidden();
+}
+
+inline bool ObjCInterfaceDecl::isVisibleExtension(ObjCCategoryDecl *Cat) {
+ return Cat->IsClassExtension() && !Cat->isHidden();
+}
+
+inline bool ObjCInterfaceDecl::isKnownExtension(ObjCCategoryDecl *Cat) {
+ return Cat->IsClassExtension();
+}
+
+} // end namespace clang
+#endif
diff --git a/contrib/llvm/tools/clang/include/clang/AST/DeclOpenMP.h b/contrib/llvm/tools/clang/include/clang/AST/DeclOpenMP.h
new file mode 100644
index 0000000..598f418
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/AST/DeclOpenMP.h
@@ -0,0 +1,91 @@
+//===- DeclOpenMP.h - Classes for representing OpenMP directives -*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+///
+/// \file
+/// \brief This file defines OpenMP nodes for declarative directives.
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_AST_DECLOPENMP_H
+#define LLVM_CLANG_AST_DECLOPENMP_H
+
+#include "clang/AST/DeclBase.h"
+#include "llvm/ADT/ArrayRef.h"
+
+namespace clang {
+class Expr;
+
+/// \brief This represents '#pragma omp threadprivate ...' directive.
+/// For example, in the following, both 'a' and 'A::b' are threadprivate:
+///
+/// \code
+/// int a;
+/// #pragma omp threadprivate(a)
+/// struct A {
+/// static int b;
+/// #pragma omp threadprivate(b)
+/// };
+/// \endcode
+///
+class OMPThreadPrivateDecl final
+ : public Decl,
+ private llvm::TrailingObjects<OMPThreadPrivateDecl, Expr *> {
+ friend class ASTDeclReader;
+ friend TrailingObjects;
+
+ unsigned NumVars;
+
+ virtual void anchor();
+
+ OMPThreadPrivateDecl(Kind DK, DeclContext *DC, SourceLocation L) :
+ Decl(DK, DC, L), NumVars(0) { }
+
+ ArrayRef<const Expr *> getVars() const {
+ return llvm::makeArrayRef(getTrailingObjects<Expr *>(), NumVars);
+ }
+
+ MutableArrayRef<Expr *> getVars() {
+ return MutableArrayRef<Expr *>(getTrailingObjects<Expr *>(), NumVars);
+ }
+
+ void setVars(ArrayRef<Expr *> VL);
+
+public:
+ static OMPThreadPrivateDecl *Create(ASTContext &C, DeclContext *DC,
+ SourceLocation L,
+ ArrayRef<Expr *> VL);
+ static OMPThreadPrivateDecl *CreateDeserialized(ASTContext &C,
+ unsigned ID, unsigned N);
+
+ typedef MutableArrayRef<Expr *>::iterator varlist_iterator;
+ typedef ArrayRef<const Expr *>::iterator varlist_const_iterator;
+ typedef llvm::iterator_range<varlist_iterator> varlist_range;
+ typedef llvm::iterator_range<varlist_const_iterator> varlist_const_range;
+
+ unsigned varlist_size() const { return NumVars; }
+ bool varlist_empty() const { return NumVars == 0; }
+
+ varlist_range varlists() {
+ return varlist_range(varlist_begin(), varlist_end());
+ }
+ varlist_const_range varlists() const {
+ return varlist_const_range(varlist_begin(), varlist_end());
+ }
+ varlist_iterator varlist_begin() { return getVars().begin(); }
+ varlist_iterator varlist_end() { return getVars().end(); }
+ varlist_const_iterator varlist_begin() const { return getVars().begin(); }
+ varlist_const_iterator varlist_end() const { return getVars().end(); }
+
+ static bool classof(const Decl *D) { return classofKind(D->getKind()); }
+ static bool classofKind(Kind K) { return K == OMPThreadPrivate; }
+};
+
+} // 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..a9109ef
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/AST/DeclTemplate.h
@@ -0,0 +1,2927 @@
+//===-- 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.
+//
+//===----------------------------------------------------------------------===//
+///
+/// \file
+/// \brief 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/Redeclarable.h"
+#include "clang/AST/TemplateBase.h"
+#include "llvm/ADT/PointerUnion.h"
+#include "llvm/Support/Compiler.h"
+#include "llvm/Support/TrailingObjects.h"
+#include <limits>
+
+namespace clang {
+
+enum BuiltinTemplateKind : int;
+class TemplateParameterList;
+class TemplateDecl;
+class RedeclarableTemplateDecl;
+class FunctionTemplateDecl;
+class ClassTemplateDecl;
+class ClassTemplatePartialSpecializationDecl;
+class TemplateTypeParmDecl;
+class NonTypeTemplateParmDecl;
+class TemplateTemplateParmDecl;
+class TypeAliasTemplateDecl;
+class VarTemplateDecl;
+class VarTemplatePartialSpecializationDecl;
+
+/// \brief Stores a template parameter of any kind.
+typedef llvm::PointerUnion3<TemplateTypeParmDecl*, NonTypeTemplateParmDecl*,
+ TemplateTemplateParmDecl*> TemplateParameter;
+
+/// \brief Stores a list of template parameters for a TemplateDecl and its
+/// derived classes.
+class TemplateParameterList final
+ : private llvm::TrailingObjects<TemplateParameterList, NamedDecl *> {
+
+ /// 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 : 31;
+
+ /// Whether this template parameter list contains an unexpanded parameter
+ /// pack.
+ unsigned ContainsUnexpandedParameterPack : 1;
+
+protected:
+ size_t numTrailingObjects(OverloadToken<NamedDecl *>) const {
+ return NumParams;
+ }
+
+ TemplateParameterList(SourceLocation TemplateLoc, SourceLocation LAngleLoc,
+ ArrayRef<NamedDecl *> Params, SourceLocation RAngleLoc);
+
+public:
+ static TemplateParameterList *Create(const ASTContext &C,
+ SourceLocation TemplateLoc,
+ SourceLocation LAngleLoc,
+ ArrayRef<NamedDecl *> Params,
+ SourceLocation RAngleLoc);
+
+ /// \brief Iterates through the template parameters in this list.
+ typedef NamedDecl** iterator;
+
+ /// \brief Iterates through the template parameters in this list.
+ typedef NamedDecl* const* const_iterator;
+
+ iterator begin() { return getTrailingObjects<NamedDecl *>(); }
+ const_iterator begin() const { return getTrailingObjects<NamedDecl *>(); }
+ iterator end() { return begin() + NumParams; }
+ const_iterator end() const { return begin() + NumParams; }
+
+ unsigned size() const { return NumParams; }
+
+ ArrayRef<NamedDecl*> asArray() {
+ return llvm::makeArrayRef(begin(), end());
+ }
+ ArrayRef<const NamedDecl*> asArray() const {
+ return llvm::makeArrayRef(begin(), size());
+ }
+
+ 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;
+
+ /// \brief Determine whether this template parameter list contains an
+ /// unexpanded parameter pack.
+ bool containsUnexpandedParameterPack() const {
+ return ContainsUnexpandedParameterPack;
+ }
+
+ SourceLocation getTemplateLoc() const { return TemplateLoc; }
+ SourceLocation getLAngleLoc() const { return LAngleLoc; }
+ SourceLocation getRAngleLoc() const { return RAngleLoc; }
+
+ SourceRange getSourceRange() const LLVM_READONLY {
+ return SourceRange(TemplateLoc, RAngleLoc);
+ }
+
+ friend TrailingObjects;
+ template <size_t N> friend class FixedSizeTemplateParameterListStorage;
+};
+
+/// \brief Stores a list of template parameters for a TemplateDecl and its
+/// derived classes. Suitable for creating on the stack.
+template <size_t N> class FixedSizeTemplateParameterListStorage {
+ // This is kinda ugly: TemplateParameterList usually gets allocated
+ // in a block of memory with NamedDecls appended to it. Here, to get
+ // it stack allocated, we include the params as a separate
+ // variable. After allocation, the TemplateParameterList object
+ // treats them as part of itself.
+ TemplateParameterList List;
+ NamedDecl *Params[N];
+
+public:
+ FixedSizeTemplateParameterListStorage(SourceLocation TemplateLoc,
+ SourceLocation LAngleLoc,
+ ArrayRef<NamedDecl *> Params,
+ SourceLocation RAngleLoc)
+ : List(TemplateLoc, LAngleLoc, Params, RAngleLoc) {
+ // Because we're doing an evil layout hack above, have some
+ // asserts, just to double-check everything is laid out like
+ // expected.
+ assert(sizeof(*this) ==
+ TemplateParameterList::totalSizeToAlloc<NamedDecl *>(N) &&
+ "Object layout not as expected");
+ assert(this->Params == List.getTrailingObjects<NamedDecl *>() &&
+ "Object layout not as expected");
+ }
+ TemplateParameterList *get() { return &List; }
+};
+
+/// \brief A template argument list.
+class TemplateArgumentList final
+ : private llvm::TrailingObjects<TemplateArgumentList, TemplateArgument> {
+ /// \brief The template argument list.
+ const TemplateArgument *Arguments;
+
+ /// \brief The number of template arguments in this template
+ /// argument list.
+ unsigned NumArguments;
+
+ TemplateArgumentList(const TemplateArgumentList &Other) = delete;
+ void operator=(const TemplateArgumentList &Other) = delete;
+
+ // Constructs an instance with an internal Argument list, containing
+ // a copy of the Args array. (Called by CreateCopy)
+ TemplateArgumentList(const TemplateArgument *Args, unsigned 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), 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()), 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 Produce this as an array ref.
+ ArrayRef<TemplateArgument> asArray() const {
+ return llvm::makeArrayRef(data(), size());
+ }
+
+ /// \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; }
+
+ friend TrailingObjects;
+};
+
+void *allocateDefaultArgStorageChain(const ASTContext &C);
+
+/// Storage for a default argument. This is conceptually either empty, or an
+/// argument value, or a pointer to a previous declaration that had a default
+/// argument.
+///
+/// However, this is complicated by modules: while we require all the default
+/// arguments for a template to be equivalent, there may be more than one, and
+/// we need to track all the originating parameters to determine if the default
+/// argument is visible.
+template<typename ParmDecl, typename ArgType>
+class DefaultArgStorage {
+ /// Storage for both the value *and* another parameter from which we inherit
+ /// the default argument. This is used when multiple default arguments for a
+ /// parameter are merged together from different modules.
+ struct Chain {
+ ParmDecl *PrevDeclWithDefaultArg;
+ ArgType Value;
+ };
+ static_assert(sizeof(Chain) == sizeof(void *) * 2,
+ "non-pointer argument type?");
+
+ llvm::PointerUnion3<ArgType, ParmDecl*, Chain*> ValueOrInherited;
+
+ static ParmDecl *getParmOwningDefaultArg(ParmDecl *Parm) {
+ const DefaultArgStorage &Storage = Parm->getDefaultArgStorage();
+ if (auto *Prev = Storage.ValueOrInherited.template dyn_cast<ParmDecl*>())
+ Parm = Prev;
+ assert(!Parm->getDefaultArgStorage()
+ .ValueOrInherited.template is<ParmDecl *>() &&
+ "should only be one level of indirection");
+ return Parm;
+ }
+
+public:
+ DefaultArgStorage() : ValueOrInherited(ArgType()) {}
+
+ /// Determine whether there is a default argument for this parameter.
+ bool isSet() const { return !ValueOrInherited.isNull(); }
+ /// Determine whether the default argument for this parameter was inherited
+ /// from a previous declaration of the same entity.
+ bool isInherited() const { return ValueOrInherited.template is<ParmDecl*>(); }
+ /// Get the default argument's value. This does not consider whether the
+ /// default argument is visible.
+ ArgType get() const {
+ const DefaultArgStorage *Storage = this;
+ if (auto *Prev = ValueOrInherited.template dyn_cast<ParmDecl*>())
+ Storage = &Prev->getDefaultArgStorage();
+ if (auto *C = Storage->ValueOrInherited.template dyn_cast<Chain*>())
+ return C->Value;
+ return Storage->ValueOrInherited.template get<ArgType>();
+ }
+ /// Get the parameter from which we inherit the default argument, if any.
+ /// This is the parameter on which the default argument was actually written.
+ const ParmDecl *getInheritedFrom() const {
+ if (auto *D = ValueOrInherited.template dyn_cast<ParmDecl*>())
+ return D;
+ if (auto *C = ValueOrInherited.template dyn_cast<Chain*>())
+ return C->PrevDeclWithDefaultArg;
+ return nullptr;
+ }
+ /// Set the default argument.
+ void set(ArgType Arg) {
+ assert(!isSet() && "default argument already set");
+ ValueOrInherited = Arg;
+ }
+ /// Set that the default argument was inherited from another parameter.
+ void setInherited(const ASTContext &C, ParmDecl *InheritedFrom) {
+ assert(!isInherited() && "default argument already inherited");
+ InheritedFrom = getParmOwningDefaultArg(InheritedFrom);
+ if (!isSet())
+ ValueOrInherited = InheritedFrom;
+ else
+ ValueOrInherited = new (allocateDefaultArgStorageChain(C))
+ Chain{InheritedFrom, ValueOrInherited.template get<ArgType>()};
+ }
+ /// Remove the default argument, even if it was inherited.
+ void clear() {
+ ValueOrInherited = ArgType();
+ }
+};
+
+//===----------------------------------------------------------------------===//
+// Kinds of Templates
+//===----------------------------------------------------------------------===//
+
+/// \brief 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 {
+ void anchor() override;
+protected:
+ // This is probably never used.
+ TemplateDecl(Kind DK, DeclContext *DC, SourceLocation L,
+ DeclarationName Name)
+ : NamedDecl(DK, DC, L, Name), TemplatedDecl(nullptr),
+ TemplateParams(nullptr) {}
+
+ // Construct a template decl with the given name and parameters.
+ // Used when there is not templated element (tt-params).
+ TemplateDecl(Kind DK, DeclContext *DC, SourceLocation L,
+ DeclarationName Name, TemplateParameterList *Params)
+ : NamedDecl(DK, DC, L, Name), TemplatedDecl(nullptr),
+ 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 classofKind(Kind K) {
+ return K >= firstTemplate && K <= lastTemplate;
+ }
+
+ SourceRange getSourceRange() const override LLVM_READONLY {
+ 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 && "TemplatedDecl already set!");
+ assert(!TemplateParams && "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 ASTTemplateArgumentListInfo *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);
+
+ /// \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 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 ASTTemplateArgumentListInfo *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);
+ }
+
+ bool isExplicitSpecialization() const {
+ return getTemplateSpecializationKind() == TSK_ExplicitSpecialization;
+ }
+
+ /// \brief True if this declaration is an explicit specialization,
+ /// explicit instantiation declaration, or explicit instantiation
+ /// definition.
+ bool isExplicitInstantiationOrSpecialization() const {
+ return isTemplateExplicitInstantiationOrSpecialization(
+ getTemplateSpecializationKind());
+ }
+
+ /// \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->asArray(),
+ Function->getASTContext());
+ }
+
+ static void
+ Profile(llvm::FoldingSetNodeID &ID, ArrayRef<TemplateArgument> TemplateArgs,
+ ASTContext &Context) {
+ ID.AddInteger(TemplateArgs.size());
+ for (unsigned Arg = 0; Arg != TemplateArgs.size(); ++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,
+/// member class or member enumeration.
+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);
+ }
+
+ bool isExplicitSpecialization() const {
+ return getTemplateSpecializationKind() == TSK_ExplicitSpecialization;
+ }
+
+ /// \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:
+///
+/// \code
+/// template \<class T> void foo(T);
+/// template \<class T> class A {
+/// friend void foo<>(T);
+/// };
+/// \endcode
+class DependentFunctionTemplateSpecializationInfo final
+ : private llvm::TrailingObjects<DependentFunctionTemplateSpecializationInfo,
+ TemplateArgumentLoc,
+ FunctionTemplateDecl *> {
+ /// The number of potential template candidates.
+ unsigned NumTemplates;
+
+ /// The number of template arguments.
+ unsigned NumArgs;
+
+ /// The locations of the left and right angle brackets.
+ SourceRange AngleLocs;
+
+ size_t numTrailingObjects(OverloadToken<TemplateArgumentLoc>) const {
+ return NumArgs;
+ }
+ size_t numTrailingObjects(OverloadToken<FunctionTemplateDecl *>) const {
+ return NumTemplates;
+ }
+
+ DependentFunctionTemplateSpecializationInfo(
+ const UnresolvedSetImpl &Templates,
+ const TemplateArgumentListInfo &TemplateArgs);
+
+public:
+ static DependentFunctionTemplateSpecializationInfo *
+ Create(ASTContext &Context, const UnresolvedSetImpl &Templates,
+ const TemplateArgumentListInfo &TemplateArgs);
+
+ /// \brief Returns the number of function templates that this might
+ /// be a specialization of.
+ unsigned getNumTemplates() const { return NumTemplates; }
+
+ /// \brief Returns the i'th template candidate.
+ FunctionTemplateDecl *getTemplate(unsigned I) const {
+ assert(I < getNumTemplates() && "template index out of range");
+ return getTrailingObjects<FunctionTemplateDecl *>()[I];
+ }
+
+ /// \brief Returns the explicit template arguments that were given.
+ const TemplateArgumentLoc *getTemplateArgs() const {
+ return getTrailingObjects<TemplateArgumentLoc>();
+ }
+
+ /// \brief Returns the number of explicit template arguments that were given.
+ unsigned getNumTemplateArgs() const { return 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();
+ }
+
+ friend TrailingObjects;
+};
+
+/// Declaration of a redeclarable template.
+class RedeclarableTemplateDecl : public TemplateDecl,
+ public Redeclarable<RedeclarableTemplateDecl>
+{
+ typedef Redeclarable<RedeclarableTemplateDecl> redeclarable_base;
+ RedeclarableTemplateDecl *getNextRedeclarationImpl() override {
+ return getNextRedeclaration();
+ }
+ RedeclarableTemplateDecl *getPreviousDeclImpl() override {
+ return getPreviousDecl();
+ }
+ RedeclarableTemplateDecl *getMostRecentDeclImpl() override {
+ return getMostRecentDecl();
+ }
+
+protected:
+ template <typename EntryType> struct SpecEntryTraits {
+ typedef EntryType DeclType;
+
+ static DeclType *getDecl(EntryType *D) {
+ return D;
+ }
+ static ArrayRef<TemplateArgument> getTemplateArgs(EntryType *D) {
+ return D->getTemplateArgs().asArray();
+ }
+ };
+
+ template <typename EntryType, typename SETraits = SpecEntryTraits<EntryType>,
+ typename DeclType = typename SETraits::DeclType>
+ struct SpecIterator
+ : llvm::iterator_adaptor_base<
+ SpecIterator<EntryType, SETraits, DeclType>,
+ typename llvm::FoldingSetVector<EntryType>::iterator,
+ typename std::iterator_traits<typename llvm::FoldingSetVector<
+ EntryType>::iterator>::iterator_category,
+ DeclType *, ptrdiff_t, DeclType *, DeclType *> {
+ SpecIterator() {}
+ explicit SpecIterator(
+ typename llvm::FoldingSetVector<EntryType>::iterator SetIter)
+ : SpecIterator::iterator_adaptor_base(std::move(SetIter)) {}
+
+ DeclType *operator*() const {
+ return SETraits::getDecl(&*this->I)->getMostRecentDecl();
+ }
+ DeclType *operator->() const { return **this; }
+ };
+
+ template <typename EntryType>
+ static SpecIterator<EntryType>
+ makeSpecIterator(llvm::FoldingSetVector<EntryType> &Specs, bool isEnd) {
+ return SpecIterator<EntryType>(isEnd ? Specs.end() : Specs.begin());
+ }
+
+ template <class EntryType> typename SpecEntryTraits<EntryType>::DeclType*
+ findSpecializationImpl(llvm::FoldingSetVector<EntryType> &Specs,
+ ArrayRef<TemplateArgument> Args, void *&InsertPos);
+
+ template <class Derived, class EntryType>
+ void addSpecializationImpl(llvm::FoldingSetVector<EntryType> &Specs,
+ EntryType *Entry, void *InsertPos);
+
+ struct CommonBase {
+ CommonBase() : InstantiatedFromMember(nullptr, 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 Pointer to the common data shared by all declarations of this
+ /// template.
+ mutable CommonBase *Common;
+
+ /// \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() const;
+
+ virtual CommonBase *newCommon(ASTContext &C) const = 0;
+
+ // Construct a template decl with name, parameters, and templated element.
+ RedeclarableTemplateDecl(Kind DK, ASTContext &C, DeclContext *DC,
+ SourceLocation L, DeclarationName Name,
+ TemplateParameterList *Params, NamedDecl *Decl)
+ : TemplateDecl(DK, DC, L, Name, Params, Decl), redeclarable_base(C),
+ Common() {}
+
+public:
+ template <class decl_type> friend class RedeclarableTemplate;
+
+ /// \brief Retrieves the canonical declaration of this template.
+ RedeclarableTemplateDecl *getCanonicalDecl() override {
+ return getFirstDecl();
+ }
+ const RedeclarableTemplateDecl *getCanonicalDecl() const {
+ return getFirstDecl();
+ }
+
+ /// \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() const {
+ 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 member template from which this template was
+ /// instantiated, or NULL if this template was not instantiated from a
+ /// member template.
+ ///
+ /// A template is instantiated from a member template when the member
+ /// template itself is part of a class template (or member thereof). For
+ /// example, given
+ ///
+ /// \code
+ /// template<typename T>
+ /// struct X {
+ /// template<typename U> void f(T, U);
+ /// };
+ ///
+ /// void test(X<int> x) {
+ /// x.f(1, 'a');
+ /// };
+ /// \endcode
+ ///
+ /// \c X<int>::f is a FunctionTemplateDecl that describes the function
+ /// template
+ ///
+ /// \code
+ /// template<typename U> void X<int>::f(int, U);
+ /// \endcode
+ ///
+ /// which was itself created during the instantiation of \c X<int>. Calling
+ /// getInstantiatedFromMemberTemplate() on this FunctionTemplateDecl will
+ /// retrieve the FunctionTemplateDecl for the original template \c f within
+ /// the class template \c X<T>, i.e.,
+ ///
+ /// \code
+ /// template<typename T>
+ /// template<typename U>
+ /// void X<T>::f(T, U);
+ /// \endcode
+ RedeclarableTemplateDecl *getInstantiatedFromMemberTemplate() const {
+ return getCommonPtr()->InstantiatedFromMember.getPointer();
+ }
+
+ void setInstantiatedFromMemberTemplate(RedeclarableTemplateDecl *TD) {
+ assert(!getCommonPtr()->InstantiatedFromMember.getPointer());
+ getCommonPtr()->InstantiatedFromMember.setPointer(TD);
+ }
+
+ typedef redeclarable_base::redecl_range redecl_range;
+ typedef redeclarable_base::redecl_iterator redecl_iterator;
+ using redeclarable_base::redecls_begin;
+ using redeclarable_base::redecls_end;
+ using redeclarable_base::redecls;
+ using redeclarable_base::getPreviousDecl;
+ using redeclarable_base::getMostRecentDecl;
+ using redeclarable_base::isFirstDecl;
+
+ // Implement isa/cast/dyncast/etc.
+ static bool classof(const Decl *D) { return classofKind(D->getKind()); }
+ static bool classofKind(Kind K) {
+ return K >= firstRedeclarableTemplate && K <= lastRedeclarableTemplate;
+ }
+
+ friend class ASTReader;
+ friend class ASTDeclReader;
+ friend class ASTDeclWriter;
+};
+
+template <> struct RedeclarableTemplateDecl::
+SpecEntryTraits<FunctionTemplateSpecializationInfo> {
+ typedef FunctionDecl DeclType;
+
+ static DeclType *getDecl(FunctionTemplateSpecializationInfo *I) {
+ return I->Function;
+ }
+ static ArrayRef<TemplateArgument>
+ getTemplateArgs(FunctionTemplateSpecializationInfo *I) {
+ return I->TemplateArguments->asArray();
+ }
+};
+
+/// Declaration of a template function.
+class FunctionTemplateDecl : public RedeclarableTemplateDecl {
+ static void DeallocateCommon(void *Ptr);
+
+protected:
+ /// \brief Data that is common to all of the declarations of a given
+ /// function template.
+ struct Common : CommonBase {
+ Common() : InjectedArgs(), LazySpecializations() { }
+
+ /// \brief The function template specializations for this function
+ /// template, including explicit specializations and instantiations.
+ llvm::FoldingSetVector<FunctionTemplateSpecializationInfo> Specializations;
+
+ /// \brief The set of "injected" template arguments used within this
+ /// function template.
+ ///
+ /// This pointer refers to the template arguments (there are as
+ /// many template arguments as template parameaters) for the function
+ /// template, and is allocated lazily, since most function templates do not
+ /// require the use of this information.
+ TemplateArgument *InjectedArgs;
+
+ /// \brief If non-null, points to an array of specializations known only
+ /// by their external declaration IDs.
+ ///
+ /// The first value in the array is the number of of specializations
+ /// that follow.
+ uint32_t *LazySpecializations;
+ };
+
+ FunctionTemplateDecl(ASTContext &C, DeclContext *DC, SourceLocation L,
+ DeclarationName Name, TemplateParameterList *Params,
+ NamedDecl *Decl)
+ : RedeclarableTemplateDecl(FunctionTemplate, C, DC, L, Name, Params,
+ Decl) {}
+
+ CommonBase *newCommon(ASTContext &C) const override;
+
+ Common *getCommonPtr() const {
+ return static_cast<Common *>(RedeclarableTemplateDecl::getCommonPtr());
+ }
+
+ friend class FunctionDecl;
+
+ /// \brief Retrieve the set of function template specializations of this
+ /// function template.
+ llvm::FoldingSetVector<FunctionTemplateSpecializationInfo> &
+ getSpecializations() const;
+
+ /// \brief Add a specialization of this function template.
+ ///
+ /// \param InsertPos Insert position in the FoldingSetVector, must have been
+ /// retrieved by an earlier call to findSpecialization().
+ void addSpecialization(FunctionTemplateSpecializationInfo* Info,
+ void *InsertPos);
+
+public:
+ /// \brief Load any lazily-loaded specializations from the external source.
+ void LoadLazySpecializations() const;
+
+ /// 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(ArrayRef<TemplateArgument> Args,
+ void *&InsertPos);
+
+ FunctionTemplateDecl *getCanonicalDecl() override {
+ return cast<FunctionTemplateDecl>(
+ RedeclarableTemplateDecl::getCanonicalDecl());
+ }
+ const FunctionTemplateDecl *getCanonicalDecl() const {
+ return cast<FunctionTemplateDecl>(
+ RedeclarableTemplateDecl::getCanonicalDecl());
+ }
+
+ /// \brief Retrieve the previous declaration of this function template, or
+ /// NULL if no such declaration exists.
+ FunctionTemplateDecl *getPreviousDecl() {
+ return cast_or_null<FunctionTemplateDecl>(
+ static_cast<RedeclarableTemplateDecl *>(this)->getPreviousDecl());
+ }
+
+ /// \brief Retrieve the previous declaration of this function template, or
+ /// NULL if no such declaration exists.
+ const FunctionTemplateDecl *getPreviousDecl() const {
+ return cast_or_null<FunctionTemplateDecl>(
+ static_cast<const RedeclarableTemplateDecl *>(this)->getPreviousDecl());
+ }
+
+ FunctionTemplateDecl *getMostRecentDecl() {
+ return cast<FunctionTemplateDecl>(
+ static_cast<RedeclarableTemplateDecl *>(this)
+ ->getMostRecentDecl());
+ }
+ const FunctionTemplateDecl *getMostRecentDecl() const {
+ return const_cast<FunctionTemplateDecl*>(this)->getMostRecentDecl();
+ }
+
+ FunctionTemplateDecl *getInstantiatedFromMemberTemplate() const {
+ return cast_or_null<FunctionTemplateDecl>(
+ RedeclarableTemplateDecl::getInstantiatedFromMemberTemplate());
+ }
+
+ typedef SpecIterator<FunctionTemplateSpecializationInfo> spec_iterator;
+ typedef llvm::iterator_range<spec_iterator> spec_range;
+
+ spec_range specializations() const {
+ return spec_range(spec_begin(), spec_end());
+ }
+ spec_iterator spec_begin() const {
+ return makeSpecIterator(getSpecializations(), false);
+ }
+
+ spec_iterator spec_end() const {
+ return makeSpecIterator(getSpecializations(), true);
+ }
+
+ /// \brief Retrieve the "injected" template arguments that correspond to the
+ /// template parameters of this function template.
+ ///
+ /// Although the C++ standard has no notion of the "injected" template
+ /// arguments for a function template, the notion is convenient when
+ /// we need to perform substitutions inside the definition of a function
+ /// template.
+ ArrayRef<TemplateArgument> getInjectedTemplateArgs();
+
+ /// \brief Create a function template node.
+ static FunctionTemplateDecl *Create(ASTContext &C, DeclContext *DC,
+ SourceLocation L,
+ DeclarationName Name,
+ TemplateParameterList *Params,
+ NamedDecl *Decl);
+
+ /// \brief Create an empty function template node.
+ static FunctionTemplateDecl *CreateDeserialized(ASTContext &C, unsigned ID);
+
+ // Implement isa/cast/dyncast support
+ static bool classof(const Decl *D) { return classofKind(D->getKind()); }
+ static bool classofKind(Kind K) { return K == FunctionTemplate; }
+
+ friend class ASTDeclReader;
+ friend class ASTDeclWriter;
+};
+
+//===----------------------------------------------------------------------===//
+// Kinds of Template Parameters
+//===----------------------------------------------------------------------===//
+
+/// \brief 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 {
+ TemplateParmPosition() = delete;
+
+protected:
+ 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; }
+};
+
+/// \brief Declaration of a template type parameter.
+///
+/// For example, "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 The default template argument, if any.
+ typedef DefaultArgStorage<TemplateTypeParmDecl, TypeSourceInfo *>
+ DefArgStorage;
+ DefArgStorage DefaultArgument;
+
+ TemplateTypeParmDecl(DeclContext *DC, SourceLocation KeyLoc,
+ SourceLocation IdLoc, IdentifierInfo *Id,
+ bool Typename)
+ : TypeDecl(TemplateTypeParm, DC, IdLoc, Id, KeyLoc), Typename(Typename),
+ DefaultArgument() { }
+
+ /// Sema creates these on the stack during auto type deduction.
+ friend class Sema;
+
+public:
+ static TemplateTypeParmDecl *Create(const ASTContext &C, DeclContext *DC,
+ SourceLocation KeyLoc,
+ SourceLocation NameLoc,
+ unsigned D, unsigned P,
+ IdentifierInfo *Id, bool Typename,
+ bool ParameterPack);
+ static TemplateTypeParmDecl *CreateDeserialized(const ASTContext &C,
+ unsigned ID);
+
+ /// \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; }
+
+ const DefArgStorage &getDefaultArgStorage() const { return DefaultArgument; }
+
+ /// \brief Determine whether this template parameter has a default
+ /// argument.
+ bool hasDefaultArgument() const { return DefaultArgument.isSet(); }
+
+ /// \brief Retrieve the default argument, if any.
+ QualType getDefaultArgument() const {
+ return DefaultArgument.get()->getType();
+ }
+
+ /// \brief Retrieves the default argument's source information, if any.
+ TypeSourceInfo *getDefaultArgumentInfo() const {
+ return DefaultArgument.get();
+ }
+
+ /// \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 DefaultArgument.isInherited();
+ }
+
+ /// \brief Set the default argument for this template parameter.
+ void setDefaultArgument(TypeSourceInfo *DefArg) {
+ DefaultArgument.set(DefArg);
+ }
+ /// \brief Set that this default argument was inherited from another
+ /// parameter.
+ void setInheritedDefaultArgument(const ASTContext &C,
+ TemplateTypeParmDecl *Prev) {
+ DefaultArgument.setInherited(C, Prev);
+ }
+
+ /// \brief Removes the default argument of this template parameter.
+ void removeDefaultArgument() {
+ DefaultArgument.clear();
+ }
+
+ /// \brief Set whether this template type parameter was declared with
+ /// the 'typename' or 'class' keyword.
+ void setDeclaredWithTypename(bool withTypename) { Typename = withTypename; }
+
+ /// \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;
+
+ SourceRange getSourceRange() const override LLVM_READONLY;
+
+ // Implement isa/cast/dyncast/etc.
+ static bool classof(const Decl *D) { return classofKind(D->getKind()); }
+ 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 final
+ : public DeclaratorDecl,
+ protected TemplateParmPosition,
+ private llvm::TrailingObjects<NonTypeTemplateParmDecl,
+ std::pair<QualType, TypeSourceInfo *>> {
+ /// \brief The default template argument, if any, and whether or not
+ /// it was inherited.
+ typedef DefaultArgStorage<NonTypeTemplateParmDecl, Expr*> DefArgStorage;
+ DefArgStorage DefaultArgument;
+
+ // 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;
+
+ size_t numTrailingObjects(
+ OverloadToken<std::pair<QualType, TypeSourceInfo *>>) const {
+ return NumExpandedTypes;
+ }
+
+ NonTypeTemplateParmDecl(DeclContext *DC, SourceLocation StartLoc,
+ SourceLocation IdLoc, unsigned D, unsigned P,
+ IdentifierInfo *Id, QualType T,
+ bool ParameterPack, TypeSourceInfo *TInfo)
+ : DeclaratorDecl(NonTypeTemplateParm, DC, IdLoc, Id, T, TInfo, StartLoc),
+ TemplateParmPosition(D, P), ParameterPack(ParameterPack),
+ ExpandedParameterPack(false), NumExpandedTypes(0)
+ { }
+
+ NonTypeTemplateParmDecl(DeclContext *DC, SourceLocation StartLoc,
+ SourceLocation IdLoc, unsigned D, unsigned P,
+ IdentifierInfo *Id, QualType T,
+ TypeSourceInfo *TInfo,
+ const QualType *ExpandedTypes,
+ unsigned NumExpandedTypes,
+ TypeSourceInfo **ExpandedTInfos);
+
+ friend class ASTDeclReader;
+ friend TrailingObjects;
+
+public:
+ static NonTypeTemplateParmDecl *
+ Create(const ASTContext &C, DeclContext *DC, SourceLocation StartLoc,
+ SourceLocation IdLoc, unsigned D, unsigned P, IdentifierInfo *Id,
+ QualType T, bool ParameterPack, TypeSourceInfo *TInfo);
+
+ static NonTypeTemplateParmDecl *
+ Create(const ASTContext &C, DeclContext *DC, SourceLocation StartLoc,
+ SourceLocation IdLoc, unsigned D, unsigned P, IdentifierInfo *Id,
+ QualType T, TypeSourceInfo *TInfo,
+ const QualType *ExpandedTypes, unsigned NumExpandedTypes,
+ TypeSourceInfo **ExpandedTInfos);
+
+ static NonTypeTemplateParmDecl *CreateDeserialized(ASTContext &C,
+ unsigned ID);
+ static NonTypeTemplateParmDecl *CreateDeserialized(ASTContext &C,
+ unsigned ID,
+ unsigned NumExpandedTypes);
+
+ using TemplateParmPosition::getDepth;
+ using TemplateParmPosition::setDepth;
+ using TemplateParmPosition::getPosition;
+ using TemplateParmPosition::setPosition;
+ using TemplateParmPosition::getIndex;
+
+ SourceRange getSourceRange() const override LLVM_READONLY;
+
+ const DefArgStorage &getDefaultArgStorage() const { return DefaultArgument; }
+
+ /// \brief Determine whether this template parameter has a default
+ /// argument.
+ bool hasDefaultArgument() const { return DefaultArgument.isSet(); }
+
+ /// \brief Retrieve the default argument, if any.
+ Expr *getDefaultArgument() const { return DefaultArgument.get(); }
+
+ /// \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 DefaultArgument.isInherited();
+ }
+
+ /// \brief Set the default argument for this template parameter, and
+ /// whether that default argument was inherited from another
+ /// declaration.
+ void setDefaultArgument(Expr *DefArg) { DefaultArgument.set(DefArg); }
+ void setInheritedDefaultArgument(const ASTContext &C,
+ NonTypeTemplateParmDecl *Parm) {
+ DefaultArgument.setInherited(C, Parm);
+ }
+
+ /// \brief Removes the default argument of this template parameter.
+ void removeDefaultArgument() { DefaultArgument.clear(); }
+
+ /// \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 pack is a pack expansion.
+ ///
+ /// A non-type template parameter pack is a pack expansion if its type
+ /// contains an unexpanded parameter pack. In this case, we will have
+ /// built a PackExpansionType wrapping the type.
+ bool isPackExpansion() const {
+ return ParameterPack && getType()->getAs<PackExpansionType>();
+ }
+
+ /// \brief Whether this parameter is a non-type template parameter pack
+ /// that has a known list of 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");
+ auto TypesAndInfos =
+ getTrailingObjects<std::pair<QualType, TypeSourceInfo *>>();
+ return TypesAndInfos[I].first;
+ }
+
+ /// \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");
+ auto TypesAndInfos =
+ getTrailingObjects<std::pair<QualType, TypeSourceInfo *>>();
+ return TypesAndInfos[I].second;
+ }
+
+ // Implement isa/cast/dyncast/etc.
+ static bool classof(const Decl *D) { return classofKind(D->getKind()); }
+ 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 final
+ : public TemplateDecl,
+ protected TemplateParmPosition,
+ private llvm::TrailingObjects<TemplateTemplateParmDecl,
+ TemplateParameterList *> {
+ void anchor() override;
+
+ /// \brief The default template argument, if any.
+ typedef DefaultArgStorage<TemplateTemplateParmDecl, TemplateArgumentLoc *>
+ DefArgStorage;
+ DefArgStorage DefaultArgument;
+
+ /// \brief Whether this parameter is a parameter pack.
+ bool ParameterPack;
+
+ /// \brief Whether this template template parameter is an "expanded"
+ /// parameter pack, meaning that it is a pack expansion and we
+ /// already know the set of template parameters that expansion expands to.
+ bool ExpandedParameterPack;
+
+ /// \brief The number of parameters in an expanded parameter pack.
+ unsigned NumExpandedParams;
+
+ TemplateTemplateParmDecl(DeclContext *DC, SourceLocation L,
+ unsigned D, unsigned P, bool ParameterPack,
+ IdentifierInfo *Id, TemplateParameterList *Params)
+ : TemplateDecl(TemplateTemplateParm, DC, L, Id, Params),
+ TemplateParmPosition(D, P), ParameterPack(ParameterPack),
+ ExpandedParameterPack(false), NumExpandedParams(0)
+ { }
+
+ TemplateTemplateParmDecl(DeclContext *DC, SourceLocation L,
+ unsigned D, unsigned P,
+ IdentifierInfo *Id, TemplateParameterList *Params,
+ unsigned NumExpansions,
+ TemplateParameterList * const *Expansions);
+
+public:
+ static TemplateTemplateParmDecl *Create(const ASTContext &C, DeclContext *DC,
+ SourceLocation L, unsigned D,
+ unsigned P, bool ParameterPack,
+ IdentifierInfo *Id,
+ TemplateParameterList *Params);
+ static TemplateTemplateParmDecl *Create(const ASTContext &C, DeclContext *DC,
+ SourceLocation L, unsigned D,
+ unsigned P,
+ IdentifierInfo *Id,
+ TemplateParameterList *Params,
+ ArrayRef<TemplateParameterList *> Expansions);
+
+ static TemplateTemplateParmDecl *CreateDeserialized(ASTContext &C,
+ unsigned ID);
+ static TemplateTemplateParmDecl *CreateDeserialized(ASTContext &C,
+ unsigned ID,
+ unsigned NumExpansions);
+
+ 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 Whether this parameter pack is a pack expansion.
+ ///
+ /// A template template parameter pack is a pack expansion if its template
+ /// parameter list contains an unexpanded parameter pack.
+ bool isPackExpansion() const {
+ return ParameterPack &&
+ getTemplateParameters()->containsUnexpandedParameterPack();
+ }
+
+ /// \brief Whether this parameter is a template template parameter pack that
+ /// has a known list of different template parameter lists at different
+ /// positions.
+ ///
+ /// A parameter pack is an expanded parameter pack when the original parameter
+ /// pack's template parameter list was itself a pack expansion, and that
+ /// expansion has already been expanded. For exampe, given:
+ ///
+ /// \code
+ /// template<typename...Types> struct Outer {
+ /// template<template<Types> class...Templates> struct Inner;
+ /// };
+ /// \endcode
+ ///
+ /// The parameter pack \c Templates is a pack expansion, which expands the
+ /// pack \c Types. When \c Types is supplied with template arguments by
+ /// instantiating \c Outer, the instantiation of \c Templates is an expanded
+ /// parameter pack.
+ bool isExpandedParameterPack() const { return ExpandedParameterPack; }
+
+ /// \brief Retrieves the number of expansion template parameters in
+ /// an expanded parameter pack.
+ unsigned getNumExpansionTemplateParameters() const {
+ assert(ExpandedParameterPack && "Not an expansion parameter pack");
+ return NumExpandedParams;
+ }
+
+ /// \brief Retrieve a particular expansion type within an expanded parameter
+ /// pack.
+ TemplateParameterList *getExpansionTemplateParameters(unsigned I) const {
+ assert(I < NumExpandedParams && "Out-of-range expansion type index");
+ return getTrailingObjects<TemplateParameterList *>()[I];
+ }
+
+ const DefArgStorage &getDefaultArgStorage() const { return DefaultArgument; }
+
+ /// \brief Determine whether this template parameter has a default
+ /// argument.
+ bool hasDefaultArgument() const { return DefaultArgument.isSet(); }
+
+ /// \brief Retrieve the default argument, if any.
+ const TemplateArgumentLoc &getDefaultArgument() const {
+ static const TemplateArgumentLoc None;
+ return DefaultArgument.isSet() ? *DefaultArgument.get() : None;
+ }
+
+ /// \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 DefaultArgument.isInherited();
+ }
+
+ /// \brief Set the default argument for this template parameter, and
+ /// whether that default argument was inherited from another
+ /// declaration.
+ void setDefaultArgument(const ASTContext &C,
+ const TemplateArgumentLoc &DefArg);
+ void setInheritedDefaultArgument(const ASTContext &C,
+ TemplateTemplateParmDecl *Prev) {
+ DefaultArgument.setInherited(C, Prev);
+ }
+
+ /// \brief Removes the default argument of this template parameter.
+ void removeDefaultArgument() { DefaultArgument.clear(); }
+
+ SourceRange getSourceRange() const override LLVM_READONLY {
+ 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 classofKind(Kind K) { return K == TemplateTemplateParm; }
+
+ friend class ASTDeclReader;
+ friend class ASTDeclWriter;
+ friend TrailingObjects;
+};
+
+/// \brief Represents the builtin template declaration which is used to
+/// implement __make_integer_seq. It serves no real purpose beyond existing as
+/// a place to hold template parameters.
+class BuiltinTemplateDecl : public TemplateDecl {
+ void anchor() override;
+
+ BuiltinTemplateDecl(const ASTContext &C, DeclContext *DC,
+ DeclarationName Name, BuiltinTemplateKind BTK);
+
+ BuiltinTemplateKind BTK;
+
+public:
+ // Implement isa/cast/dyncast support
+ static bool classof(const Decl *D) { return classofKind(D->getKind()); }
+ static bool classofKind(Kind K) { return K == BuiltinTemplate; }
+
+ static BuiltinTemplateDecl *Create(const ASTContext &C, DeclContext *DC,
+ DeclarationName Name,
+ BuiltinTemplateKind BTK) {
+ return new (C, DC) BuiltinTemplateDecl(C, DC, Name, BTK);
+ }
+
+ SourceRange getSourceRange() const override LLVM_READONLY {
+ return SourceRange();
+ }
+
+ BuiltinTemplateKind getBuiltinTemplateKind() const { return BTK; }
+};
+
+/// \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.
+ const 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(nullptr), 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.
+ const 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 StartLoc,
+ SourceLocation IdLoc,
+ ClassTemplateDecl *SpecializedTemplate,
+ const TemplateArgument *Args,
+ unsigned NumArgs,
+ ClassTemplateSpecializationDecl *PrevDecl);
+
+ explicit ClassTemplateSpecializationDecl(ASTContext &C, Kind DK);
+
+public:
+ static ClassTemplateSpecializationDecl *
+ Create(ASTContext &Context, TagKind TK, DeclContext *DC,
+ SourceLocation StartLoc, SourceLocation IdLoc,
+ ClassTemplateDecl *SpecializedTemplate,
+ const TemplateArgument *Args,
+ unsigned NumArgs,
+ ClassTemplateSpecializationDecl *PrevDecl);
+ static ClassTemplateSpecializationDecl *
+ CreateDeserialized(ASTContext &C, unsigned ID);
+
+ void getNameForDiagnostic(raw_ostream &OS, const PrintingPolicy &Policy,
+ bool Qualified) const override;
+
+ // FIXME: This is broken. CXXRecordDecl::getMostRecentDecl() returns a
+ // different "most recent" declaration from this function for the same
+ // declaration, because we don't override getMostRecentDeclImpl(). But
+ // it's not clear that we should override that, because the most recent
+ // declaration as a CXXRecordDecl sometimes is the injected-class-name.
+ ClassTemplateSpecializationDecl *getMostRecentDecl() {
+ CXXRecordDecl *Recent = static_cast<CXXRecordDecl *>(
+ this)->getMostRecentDecl();
+ while (!isa<ClassTemplateSpecializationDecl>(Recent)) {
+ // FIXME: Does injected class name need to be in the redeclarations chain?
+ assert(Recent->isInjectedClassName() && Recent->getPreviousDecl());
+ Recent = Recent->getPreviousDecl();
+ }
+ 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);
+ }
+
+ bool isExplicitSpecialization() const {
+ return getSpecializationKind() == TSK_ExplicitSpecialization;
+ }
+
+ /// \brief True if this declaration is an explicit specialization,
+ /// explicit instantiation declaration, or explicit instantiation
+ /// definition.
+ bool isExplicitInstantiationOrSpecialization() const {
+ return isTemplateExplicitInstantiationOrSpecialization(
+ getTemplateSpecializationKind());
+ }
+
+ 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 (!isTemplateInstantiation(getSpecializationKind()))
+ return llvm::PointerUnion<ClassTemplateDecl *,
+ ClassTemplatePartialSpecializationDecl *>();
+
+ return getSpecializedTemplateOrPartial();
+ }
+
+ /// \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 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,
+ const 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 : nullptr;
+ }
+
+ /// \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();
+ }
+
+ SourceRange getSourceRange() const override LLVM_READONLY;
+
+ void Profile(llvm::FoldingSetNodeID &ID) const {
+ Profile(ID, TemplateArgs->asArray(), getASTContext());
+ }
+
+ static void
+ Profile(llvm::FoldingSetNodeID &ID, ArrayRef<TemplateArgument> TemplateArgs,
+ ASTContext &Context) {
+ ID.AddInteger(TemplateArgs.size());
+ for (unsigned Arg = 0; Arg != TemplateArgs.size(); ++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;
+ }
+
+ friend class ASTDeclReader;
+ friend class ASTDeclWriter;
+};
+
+class ClassTemplatePartialSpecializationDecl
+ : public ClassTemplateSpecializationDecl {
+ void anchor() override;
+
+ /// \brief The list of template parameters
+ TemplateParameterList* TemplateParams;
+
+ /// \brief The source info for the template arguments as written.
+ /// FIXME: redundant with TypeAsWritten?
+ const ASTTemplateArgumentListInfo *ArgsAsWritten;
+
+ /// \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 StartLoc,
+ SourceLocation IdLoc,
+ TemplateParameterList *Params,
+ ClassTemplateDecl *SpecializedTemplate,
+ const TemplateArgument *Args,
+ unsigned NumArgs,
+ const ASTTemplateArgumentListInfo *ArgsAsWritten,
+ ClassTemplatePartialSpecializationDecl *PrevDecl);
+
+ ClassTemplatePartialSpecializationDecl(ASTContext &C)
+ : ClassTemplateSpecializationDecl(C, ClassTemplatePartialSpecialization),
+ TemplateParams(nullptr), ArgsAsWritten(nullptr),
+ InstantiatedFromMember(nullptr, false) {}
+
+public:
+ static ClassTemplatePartialSpecializationDecl *
+ Create(ASTContext &Context, TagKind TK, DeclContext *DC,
+ SourceLocation StartLoc, SourceLocation IdLoc,
+ TemplateParameterList *Params,
+ ClassTemplateDecl *SpecializedTemplate,
+ const TemplateArgument *Args,
+ unsigned NumArgs,
+ const TemplateArgumentListInfo &ArgInfos,
+ QualType CanonInjectedType,
+ ClassTemplatePartialSpecializationDecl *PrevDecl);
+
+ static ClassTemplatePartialSpecializationDecl *
+ CreateDeserialized(ASTContext &C, unsigned ID);
+
+ ClassTemplatePartialSpecializationDecl *getMostRecentDecl() {
+ return cast<ClassTemplatePartialSpecializationDecl>(
+ static_cast<ClassTemplateSpecializationDecl *>(
+ this)->getMostRecentDecl());
+ }
+
+ /// Get the list of template parameters
+ TemplateParameterList *getTemplateParameters() const {
+ return TemplateParams;
+ }
+
+ /// Get the template arguments as written.
+ const ASTTemplateArgumentListInfo *getTemplateArgsAsWritten() const {
+ return ArgsAsWritten;
+ }
+
+ /// \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() const {
+ const ClassTemplatePartialSpecializationDecl *First =
+ cast<ClassTemplatePartialSpecializationDecl>(getFirstDecl());
+ return First->InstantiatedFromMember.getPointer();
+ }
+
+ void setInstantiatedFromMember(
+ ClassTemplatePartialSpecializationDecl *PartialSpec) {
+ ClassTemplatePartialSpecializationDecl *First =
+ cast<ClassTemplatePartialSpecializationDecl>(getFirstDecl());
+ 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>(getFirstDecl());
+ return First->InstantiatedFromMember.getInt();
+ }
+
+ /// \brief Note that this member template is a specialization.
+ void setMemberSpecialization() {
+ ClassTemplatePartialSpecializationDecl *First =
+ cast<ClassTemplatePartialSpecializationDecl>(getFirstDecl());
+ 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;
+ }
+
+ friend class ASTDeclReader;
+ friend class ASTDeclWriter;
+};
+
+/// Declaration of a class template.
+class ClassTemplateDecl : public RedeclarableTemplateDecl {
+ static void DeallocateCommon(void *Ptr);
+
+protected:
+ /// \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::FoldingSetVector<ClassTemplateSpecializationDecl> Specializations;
+
+ /// \brief The class template partial specializations for this class
+ /// template.
+ llvm::FoldingSetVector<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 only 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 Retrieve the set of specializations of this class template.
+ llvm::FoldingSetVector<ClassTemplateSpecializationDecl> &
+ getSpecializations() const;
+
+ /// \brief Retrieve the set of partial specializations of this class
+ /// template.
+ llvm::FoldingSetVector<ClassTemplatePartialSpecializationDecl> &
+ getPartialSpecializations();
+
+ ClassTemplateDecl(ASTContext &C, DeclContext *DC, SourceLocation L,
+ DeclarationName Name, TemplateParameterList *Params,
+ NamedDecl *Decl)
+ : RedeclarableTemplateDecl(ClassTemplate, C, DC, L, Name, Params, Decl) {}
+
+ CommonBase *newCommon(ASTContext &C) const override;
+
+ Common *getCommonPtr() const {
+ return static_cast<Common *>(RedeclarableTemplateDecl::getCommonPtr());
+ }
+
+public:
+ /// \brief Load any lazily-loaded specializations from the external source.
+ void LoadLazySpecializations() const;
+
+ /// \brief Get the underlying class declarations of the template.
+ CXXRecordDecl *getTemplatedDecl() const {
+ return static_cast<CXXRecordDecl *>(TemplatedDecl);
+ }
+
+ /// \brief Returns whether this template declaration defines the primary
+ /// class pattern.
+ bool isThisDeclarationADefinition() const {
+ return getTemplatedDecl()->isThisDeclarationADefinition();
+ }
+
+ /// \brief Create a class template node.
+ static ClassTemplateDecl *Create(ASTContext &C, DeclContext *DC,
+ SourceLocation L,
+ DeclarationName Name,
+ TemplateParameterList *Params,
+ NamedDecl *Decl,
+ ClassTemplateDecl *PrevDecl);
+
+ /// \brief Create an empty class template node.
+ static ClassTemplateDecl *CreateDeserialized(ASTContext &C, unsigned ID);
+
+ /// \brief Return the specialization with the provided arguments if it exists,
+ /// otherwise return the insertion point.
+ ClassTemplateSpecializationDecl *
+ findSpecialization(ArrayRef<TemplateArgument> Args, 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() override {
+ return cast<ClassTemplateDecl>(
+ RedeclarableTemplateDecl::getCanonicalDecl());
+ }
+ const ClassTemplateDecl *getCanonicalDecl() const {
+ return cast<ClassTemplateDecl>(
+ RedeclarableTemplateDecl::getCanonicalDecl());
+ }
+
+ /// \brief Retrieve the previous declaration of this class template, or
+ /// NULL if no such declaration exists.
+ ClassTemplateDecl *getPreviousDecl() {
+ return cast_or_null<ClassTemplateDecl>(
+ static_cast<RedeclarableTemplateDecl *>(this)->getPreviousDecl());
+ }
+
+ /// \brief Retrieve the previous declaration of this class template, or
+ /// NULL if no such declaration exists.
+ const ClassTemplateDecl *getPreviousDecl() const {
+ return cast_or_null<ClassTemplateDecl>(
+ static_cast<const RedeclarableTemplateDecl *>(
+ this)->getPreviousDecl());
+ }
+
+ ClassTemplateDecl *getMostRecentDecl() {
+ return cast<ClassTemplateDecl>(
+ static_cast<RedeclarableTemplateDecl *>(this)->getMostRecentDecl());
+ }
+ const ClassTemplateDecl *getMostRecentDecl() const {
+ return const_cast<ClassTemplateDecl*>(this)->getMostRecentDecl();
+ }
+
+ ClassTemplateDecl *getInstantiatedFromMemberTemplate() const {
+ return cast_or_null<ClassTemplateDecl>(
+ RedeclarableTemplateDecl::getInstantiatedFromMemberTemplate());
+ }
+
+ /// \brief Return the partial specialization with the provided arguments if it
+ /// exists, otherwise return the insertion point.
+ ClassTemplatePartialSpecializationDecl *
+ findPartialSpecialization(ArrayRef<TemplateArgument> Args, 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 Retrieve the partial specializations as an ordered list.
+ void getPartialSpecializations(
+ 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;
+ typedef llvm::iterator_range<spec_iterator> spec_range;
+
+ spec_range specializations() const {
+ return spec_range(spec_begin(), spec_end());
+ }
+
+ spec_iterator spec_begin() const {
+ return makeSpecIterator(getSpecializations(), false);
+ }
+
+ spec_iterator spec_end() const {
+ return makeSpecIterator(getSpecializations(), true);
+ }
+
+ // Implement isa/cast/dyncast support
+ static bool classof(const Decl *D) { return classofKind(D->getKind()); }
+ static bool classofKind(Kind K) { return K == ClassTemplate; }
+
+ friend class ASTDeclReader;
+ friend class ASTDeclWriter;
+};
+
+/// \brief Declaration of a friend template.
+///
+/// For example:
+/// \code
+/// 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
+/// };
+/// \endcode
+///
+/// \note This class is not currently in use. All of the above
+/// will yield a FriendDecl, not a FriendTemplateDecl.
+class FriendTemplateDecl : public Decl {
+ virtual void anchor();
+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(nullptr)
+ {}
+
+public:
+ static FriendTemplateDecl *Create(ASTContext &Context,
+ DeclContext *DC, SourceLocation Loc,
+ unsigned NParams,
+ TemplateParameterList **Params,
+ FriendUnion Friend,
+ SourceLocation FriendLoc);
+
+ static FriendTemplateDecl *CreateDeserialized(ASTContext &C, unsigned ID);
+
+ /// 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*>();
+ }
+
+ /// \brief 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; }
+
+ friend class ASTDeclReader;
+};
+
+/// \brief Declaration of an alias template.
+///
+/// For example:
+/// \code
+/// template \<typename T> using V = std::map<T*, int, MyCompare<T>>;
+/// \endcode
+class TypeAliasTemplateDecl : public RedeclarableTemplateDecl {
+ static void DeallocateCommon(void *Ptr);
+
+protected:
+ typedef CommonBase Common;
+
+ TypeAliasTemplateDecl(ASTContext &C, DeclContext *DC, SourceLocation L,
+ DeclarationName Name, TemplateParameterList *Params,
+ NamedDecl *Decl)
+ : RedeclarableTemplateDecl(TypeAliasTemplate, C, DC, L, Name, Params,
+ Decl) {}
+
+ CommonBase *newCommon(ASTContext &C) const override;
+
+ Common *getCommonPtr() {
+ return static_cast<Common *>(RedeclarableTemplateDecl::getCommonPtr());
+ }
+
+public:
+ /// Get the underlying function declaration of the template.
+ TypeAliasDecl *getTemplatedDecl() const {
+ return static_cast<TypeAliasDecl*>(TemplatedDecl);
+ }
+
+
+ TypeAliasTemplateDecl *getCanonicalDecl() override {
+ return cast<TypeAliasTemplateDecl>(
+ RedeclarableTemplateDecl::getCanonicalDecl());
+ }
+ const TypeAliasTemplateDecl *getCanonicalDecl() const {
+ return cast<TypeAliasTemplateDecl>(
+ RedeclarableTemplateDecl::getCanonicalDecl());
+ }
+
+ /// \brief Retrieve the previous declaration of this function template, or
+ /// NULL if no such declaration exists.
+ TypeAliasTemplateDecl *getPreviousDecl() {
+ return cast_or_null<TypeAliasTemplateDecl>(
+ static_cast<RedeclarableTemplateDecl *>(this)->getPreviousDecl());
+ }
+
+ /// \brief Retrieve the previous declaration of this function template, or
+ /// NULL if no such declaration exists.
+ const TypeAliasTemplateDecl *getPreviousDecl() const {
+ return cast_or_null<TypeAliasTemplateDecl>(
+ static_cast<const RedeclarableTemplateDecl *>(
+ this)->getPreviousDecl());
+ }
+
+ TypeAliasTemplateDecl *getInstantiatedFromMemberTemplate() const {
+ return cast_or_null<TypeAliasTemplateDecl>(
+ RedeclarableTemplateDecl::getInstantiatedFromMemberTemplate());
+ }
+
+
+ /// \brief Create a function template node.
+ static TypeAliasTemplateDecl *Create(ASTContext &C, DeclContext *DC,
+ SourceLocation L,
+ DeclarationName Name,
+ TemplateParameterList *Params,
+ NamedDecl *Decl);
+
+ /// \brief Create an empty alias template node.
+ static TypeAliasTemplateDecl *CreateDeserialized(ASTContext &C, unsigned ID);
+
+ // Implement isa/cast/dyncast support
+ static bool classof(const Decl *D) { return classofKind(D->getKind()); }
+ static bool classofKind(Kind K) { return K == TypeAliasTemplate; }
+
+ friend class ASTDeclReader;
+ friend class ASTDeclWriter;
+};
+
+/// \brief Declaration of a function specialization at template class scope.
+///
+/// This is a non-standard extension needed to support MSVC.
+///
+/// For example:
+/// \code
+/// template <class T>
+/// class A {
+/// template <class U> void foo(U a) { }
+/// template<> void foo(int a) { }
+/// }
+/// \endcode
+///
+/// "template<> foo(int a)" will be saved in Specialization as a normal
+/// CXXMethodDecl. Then during an instantiation of class A, it will be
+/// transformed into an actual function specialization.
+class ClassScopeFunctionSpecializationDecl : public Decl {
+ virtual void anchor();
+
+ ClassScopeFunctionSpecializationDecl(DeclContext *DC, SourceLocation Loc,
+ CXXMethodDecl *FD, bool Args,
+ TemplateArgumentListInfo TemplArgs)
+ : Decl(Decl::ClassScopeFunctionSpecialization, DC, Loc),
+ Specialization(FD), HasExplicitTemplateArgs(Args),
+ TemplateArgs(TemplArgs) {}
+
+ ClassScopeFunctionSpecializationDecl(EmptyShell Empty)
+ : Decl(Decl::ClassScopeFunctionSpecialization, Empty) {}
+
+ CXXMethodDecl *Specialization;
+ bool HasExplicitTemplateArgs;
+ TemplateArgumentListInfo TemplateArgs;
+
+public:
+ CXXMethodDecl *getSpecialization() const { return Specialization; }
+ bool hasExplicitTemplateArgs() const { return HasExplicitTemplateArgs; }
+ const TemplateArgumentListInfo& templateArgs() const { return TemplateArgs; }
+
+ static ClassScopeFunctionSpecializationDecl *Create(ASTContext &C,
+ DeclContext *DC,
+ SourceLocation Loc,
+ CXXMethodDecl *FD,
+ bool HasExplicitTemplateArgs,
+ TemplateArgumentListInfo TemplateArgs) {
+ return new (C, DC) ClassScopeFunctionSpecializationDecl(
+ DC, Loc, FD, HasExplicitTemplateArgs, TemplateArgs);
+ }
+
+ static ClassScopeFunctionSpecializationDecl *
+ CreateDeserialized(ASTContext &Context, unsigned ID);
+
+ // Implement isa/cast/dyncast/etc.
+ static bool classof(const Decl *D) { return classofKind(D->getKind()); }
+ static bool classofKind(Kind K) {
+ return K == Decl::ClassScopeFunctionSpecialization;
+ }
+
+ friend class ASTDeclReader;
+ friend class ASTDeclWriter;
+};
+
+/// Implementation of inline functions that require the template declarations
+inline AnyFunctionDecl::AnyFunctionDecl(FunctionTemplateDecl *FTD)
+ : Function(FTD) { }
+
+/// \brief Represents a variable template specialization, which refers to
+/// a variable template with a given set of template arguments.
+///
+/// Variable template specializations represent both explicit
+/// specializations of variable templates, as in the example below, and
+/// implicit instantiations of variable templates.
+///
+/// \code
+/// template<typename T> constexpr T pi = T(3.1415926535897932385);
+///
+/// template<>
+/// constexpr float pi<float>; // variable template specialization pi<float>
+/// \endcode
+class VarTemplateSpecializationDecl : public VarDecl,
+ public llvm::FoldingSetNode {
+
+ /// \brief Structure that stores information about a variable template
+ /// specialization that was instantiated from a variable template partial
+ /// specialization.
+ struct SpecializedPartialSpecialization {
+ /// \brief The variable template partial specialization from which this
+ /// variable template specialization was instantiated.
+ VarTemplatePartialSpecializationDecl *PartialSpecialization;
+
+ /// \brief The template argument list deduced for the variable template
+ /// partial specialization itself.
+ const TemplateArgumentList *TemplateArgs;
+ };
+
+ /// \brief The template that this specialization specializes.
+ llvm::PointerUnion<VarTemplateDecl *, 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(nullptr), 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.
+ const TemplateArgumentList *TemplateArgs;
+ TemplateArgumentListInfo TemplateArgsInfo;
+
+ /// \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:
+ VarTemplateSpecializationDecl(Kind DK, ASTContext &Context, DeclContext *DC,
+ SourceLocation StartLoc, SourceLocation IdLoc,
+ VarTemplateDecl *SpecializedTemplate,
+ QualType T, TypeSourceInfo *TInfo,
+ StorageClass S, const TemplateArgument *Args,
+ unsigned NumArgs);
+
+ explicit VarTemplateSpecializationDecl(Kind DK, ASTContext &Context);
+
+public:
+ static VarTemplateSpecializationDecl *
+ Create(ASTContext &Context, DeclContext *DC, SourceLocation StartLoc,
+ SourceLocation IdLoc, VarTemplateDecl *SpecializedTemplate, QualType T,
+ TypeSourceInfo *TInfo, StorageClass S, const TemplateArgument *Args,
+ unsigned NumArgs);
+ static VarTemplateSpecializationDecl *CreateDeserialized(ASTContext &C,
+ unsigned ID);
+
+ void getNameForDiagnostic(raw_ostream &OS, const PrintingPolicy &Policy,
+ bool Qualified) const override;
+
+ VarTemplateSpecializationDecl *getMostRecentDecl() {
+ VarDecl *Recent = static_cast<VarDecl *>(this)->getMostRecentDecl();
+ return cast<VarTemplateSpecializationDecl>(Recent);
+ }
+
+ /// \brief Retrieve the template that this specialization specializes.
+ VarTemplateDecl *getSpecializedTemplate() const;
+
+ /// \brief Retrieve the template arguments of the variable template
+ /// specialization.
+ const TemplateArgumentList &getTemplateArgs() const { return *TemplateArgs; }
+
+ // TODO: Always set this when creating the new specialization?
+ void setTemplateArgsInfo(const TemplateArgumentListInfo &ArgsInfo);
+
+ const TemplateArgumentListInfo &getTemplateArgsInfo() const {
+ return TemplateArgsInfo;
+ }
+
+ /// \brief Determine the kind of specialization that this
+ /// declaration represents.
+ TemplateSpecializationKind getSpecializationKind() const {
+ return static_cast<TemplateSpecializationKind>(SpecializationKind);
+ }
+
+ bool isExplicitSpecialization() const {
+ return getSpecializationKind() == TSK_ExplicitSpecialization;
+ }
+
+ /// \brief True if this declaration is an explicit specialization,
+ /// explicit instantiation declaration, or explicit instantiation
+ /// definition.
+ bool isExplicitInstantiationOrSpecialization() const {
+ return isTemplateExplicitInstantiationOrSpecialization(
+ getTemplateSpecializationKind());
+ }
+
+ 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 variable template specialization is an instantiation of
+ /// a template (rather than an explicit specialization), return the
+ /// variable template or variable template partial specialization from which
+ /// it was instantiated.
+ llvm::PointerUnion<VarTemplateDecl *, VarTemplatePartialSpecializationDecl *>
+ getInstantiatedFrom() const {
+ if (getSpecializationKind() != TSK_ImplicitInstantiation &&
+ getSpecializationKind() != TSK_ExplicitInstantiationDefinition &&
+ getSpecializationKind() != TSK_ExplicitInstantiationDeclaration)
+ return llvm::PointerUnion<VarTemplateDecl *,
+ VarTemplatePartialSpecializationDecl *>();
+
+ if (SpecializedPartialSpecialization *PartialSpec =
+ SpecializedTemplate.dyn_cast<SpecializedPartialSpecialization *>())
+ return PartialSpec->PartialSpecialization;
+
+ return SpecializedTemplate.get<VarTemplateDecl *>();
+ }
+
+ /// \brief Retrieve the variable template or variable template partial
+ /// specialization which was specialized by this.
+ llvm::PointerUnion<VarTemplateDecl *, VarTemplatePartialSpecializationDecl *>
+ getSpecializedTemplateOrPartial() const {
+ if (SpecializedPartialSpecialization *PartialSpec =
+ SpecializedTemplate.dyn_cast<SpecializedPartialSpecialization *>())
+ return PartialSpec->PartialSpecialization;
+
+ return SpecializedTemplate.get<VarTemplateDecl *>();
+ }
+
+ /// \brief Retrieve the set of template arguments that should be used
+ /// to instantiate the initializer of the variable template or variable
+ /// template partial specialization from which this variable template
+ /// specialization was instantiated.
+ ///
+ /// \returns For a variable template specialization instantiated from the
+ /// primary template, this function will return the same template arguments
+ /// as getTemplateArgs(). For a variable template specialization instantiated
+ /// from a variable template partial specialization, this function will the
+ /// return deduced template arguments for the variable template partial
+ /// specialization itself.
+ const TemplateArgumentList &getTemplateInstantiationArgs() const {
+ if (SpecializedPartialSpecialization *PartialSpec =
+ SpecializedTemplate.dyn_cast<SpecializedPartialSpecialization *>())
+ return *PartialSpec->TemplateArgs;
+
+ return getTemplateArgs();
+ }
+
+ /// \brief Note that this variable template specialization is actually an
+ /// instantiation of the given variable template partial specialization whose
+ /// template arguments have been deduced.
+ void setInstantiationOf(VarTemplatePartialSpecializationDecl *PartialSpec,
+ const TemplateArgumentList *TemplateArgs) {
+ assert(!SpecializedTemplate.is<SpecializedPartialSpecialization *>() &&
+ "Already set to a variable template partial specialization!");
+ SpecializedPartialSpecialization *PS =
+ new (getASTContext()) SpecializedPartialSpecialization();
+ PS->PartialSpecialization = PartialSpec;
+ PS->TemplateArgs = TemplateArgs;
+ SpecializedTemplate = PS;
+ }
+
+ /// \brief Note that this variable template specialization is an instantiation
+ /// of the given variable template.
+ void setInstantiationOf(VarTemplateDecl *TemplDecl) {
+ assert(!SpecializedTemplate.is<SpecializedPartialSpecialization *>() &&
+ "Previously set to a variable template partial specialization!");
+ SpecializedTemplate = TemplDecl;
+ }
+
+ /// \brief Sets the type of this specialization as it was written by
+ /// the user.
+ 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 : nullptr;
+ }
+
+ /// \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();
+ }
+
+ void Profile(llvm::FoldingSetNodeID &ID) const {
+ Profile(ID, TemplateArgs->asArray(), getASTContext());
+ }
+
+ static void Profile(llvm::FoldingSetNodeID &ID,
+ ArrayRef<TemplateArgument> TemplateArgs,
+ ASTContext &Context) {
+ ID.AddInteger(TemplateArgs.size());
+ for (unsigned Arg = 0; Arg != TemplateArgs.size(); ++Arg)
+ TemplateArgs[Arg].Profile(ID, Context);
+ }
+
+ static bool classof(const Decl *D) { return classofKind(D->getKind()); }
+ static bool classofKind(Kind K) {
+ return K >= firstVarTemplateSpecialization &&
+ K <= lastVarTemplateSpecialization;
+ }
+
+ friend class ASTDeclReader;
+ friend class ASTDeclWriter;
+};
+
+class VarTemplatePartialSpecializationDecl
+ : public VarTemplateSpecializationDecl {
+ void anchor() override;
+
+ /// \brief The list of template parameters
+ TemplateParameterList *TemplateParams;
+
+ /// \brief The source info for the template arguments as written.
+ /// FIXME: redundant with TypeAsWritten?
+ const ASTTemplateArgumentListInfo *ArgsAsWritten;
+
+ /// \brief The variable template partial specialization from which this
+ /// variable template partial specialization was instantiated.
+ ///
+ /// The boolean value will be true to indicate that this variable template
+ /// partial specialization was specialized at this level.
+ llvm::PointerIntPair<VarTemplatePartialSpecializationDecl *, 1, bool>
+ InstantiatedFromMember;
+
+ VarTemplatePartialSpecializationDecl(
+ ASTContext &Context, DeclContext *DC, SourceLocation StartLoc,
+ SourceLocation IdLoc, TemplateParameterList *Params,
+ VarTemplateDecl *SpecializedTemplate, QualType T, TypeSourceInfo *TInfo,
+ StorageClass S, const TemplateArgument *Args, unsigned NumArgs,
+ const ASTTemplateArgumentListInfo *ArgInfos);
+
+ VarTemplatePartialSpecializationDecl(ASTContext &Context)
+ : VarTemplateSpecializationDecl(VarTemplatePartialSpecialization, Context),
+ TemplateParams(nullptr), ArgsAsWritten(nullptr),
+ InstantiatedFromMember(nullptr, false) {}
+
+public:
+ static VarTemplatePartialSpecializationDecl *
+ Create(ASTContext &Context, DeclContext *DC, SourceLocation StartLoc,
+ SourceLocation IdLoc, TemplateParameterList *Params,
+ VarTemplateDecl *SpecializedTemplate, QualType T,
+ TypeSourceInfo *TInfo, StorageClass S, const TemplateArgument *Args,
+ unsigned NumArgs, const TemplateArgumentListInfo &ArgInfos);
+
+ static VarTemplatePartialSpecializationDecl *CreateDeserialized(ASTContext &C,
+ unsigned ID);
+
+ VarTemplatePartialSpecializationDecl *getMostRecentDecl() {
+ return cast<VarTemplatePartialSpecializationDecl>(
+ static_cast<VarTemplateSpecializationDecl *>(
+ this)->getMostRecentDecl());
+ }
+
+ /// Get the list of template parameters
+ TemplateParameterList *getTemplateParameters() const {
+ return TemplateParams;
+ }
+
+ /// Get the template arguments as written.
+ const ASTTemplateArgumentListInfo *getTemplateArgsAsWritten() const {
+ return ArgsAsWritten;
+ }
+
+ /// \brief Retrieve the member variable template partial specialization from
+ /// which this particular variable template partial specialization was
+ /// instantiated.
+ ///
+ /// \code
+ /// template<typename T>
+ /// struct Outer {
+ /// template<typename U> U Inner;
+ /// template<typename U> U* Inner<U*> = (U*)(0); // #1
+ /// };
+ ///
+ /// template int* Outer<float>::Inner<int*>;
+ /// \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
+ /// variable template partial specialization \c Outer<T>::Inner<U*>. Given
+ /// \c Outer<float>::Inner<U*>, this function would return
+ /// \c Outer<T>::Inner<U*>.
+ VarTemplatePartialSpecializationDecl *getInstantiatedFromMember() const {
+ const VarTemplatePartialSpecializationDecl *First =
+ cast<VarTemplatePartialSpecializationDecl>(getFirstDecl());
+ return First->InstantiatedFromMember.getPointer();
+ }
+
+ void
+ setInstantiatedFromMember(VarTemplatePartialSpecializationDecl *PartialSpec) {
+ VarTemplatePartialSpecializationDecl *First =
+ cast<VarTemplatePartialSpecializationDecl>(getFirstDecl());
+ First->InstantiatedFromMember.setPointer(PartialSpec);
+ }
+
+ /// \brief Determines whether this variable template partial specialization
+ /// 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> U Inner;
+ /// template<typename U> U* Inner<U*> = (U*)(0);
+ /// };
+ ///
+ /// template<> template<typename T>
+ /// U* X<int>::Inner<T*> = (T*)(0) + 1;
+ /// \endcode
+ bool isMemberSpecialization() {
+ VarTemplatePartialSpecializationDecl *First =
+ cast<VarTemplatePartialSpecializationDecl>(getFirstDecl());
+ return First->InstantiatedFromMember.getInt();
+ }
+
+ /// \brief Note that this member template is a specialization.
+ void setMemberSpecialization() {
+ VarTemplatePartialSpecializationDecl *First =
+ cast<VarTemplatePartialSpecializationDecl>(getFirstDecl());
+ assert(First->InstantiatedFromMember.getPointer() &&
+ "Only member templates can be member template specializations");
+ return First->InstantiatedFromMember.setInt(true);
+ }
+
+ static bool classof(const Decl *D) { return classofKind(D->getKind()); }
+ static bool classofKind(Kind K) {
+ return K == VarTemplatePartialSpecialization;
+ }
+
+ friend class ASTDeclReader;
+ friend class ASTDeclWriter;
+};
+
+/// Declaration of a variable template.
+class VarTemplateDecl : public RedeclarableTemplateDecl {
+ static void DeallocateCommon(void *Ptr);
+
+protected:
+ /// \brief Data that is common to all of the declarations of a given
+ /// variable template.
+ struct Common : CommonBase {
+ Common() : LazySpecializations() {}
+
+ /// \brief The variable template specializations for this variable
+ /// template, including explicit specializations and instantiations.
+ llvm::FoldingSetVector<VarTemplateSpecializationDecl> Specializations;
+
+ /// \brief The variable template partial specializations for this variable
+ /// template.
+ llvm::FoldingSetVector<VarTemplatePartialSpecializationDecl>
+ PartialSpecializations;
+
+ /// \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 Retrieve the set of specializations of this variable template.
+ llvm::FoldingSetVector<VarTemplateSpecializationDecl> &
+ getSpecializations() const;
+
+ /// \brief Retrieve the set of partial specializations of this class
+ /// template.
+ llvm::FoldingSetVector<VarTemplatePartialSpecializationDecl> &
+ getPartialSpecializations();
+
+ VarTemplateDecl(ASTContext &C, DeclContext *DC, SourceLocation L,
+ DeclarationName Name, TemplateParameterList *Params,
+ NamedDecl *Decl)
+ : RedeclarableTemplateDecl(VarTemplate, C, DC, L, Name, Params, Decl) {}
+
+ CommonBase *newCommon(ASTContext &C) const override;
+
+ Common *getCommonPtr() const {
+ return static_cast<Common *>(RedeclarableTemplateDecl::getCommonPtr());
+ }
+
+public:
+ /// \brief Load any lazily-loaded specializations from the external source.
+ void LoadLazySpecializations() const;
+
+ /// \brief Get the underlying variable declarations of the template.
+ VarDecl *getTemplatedDecl() const {
+ return static_cast<VarDecl *>(TemplatedDecl);
+ }
+
+ /// \brief Returns whether this template declaration defines the primary
+ /// variable pattern.
+ bool isThisDeclarationADefinition() const {
+ return getTemplatedDecl()->isThisDeclarationADefinition();
+ }
+
+ VarTemplateDecl *getDefinition();
+
+ /// \brief Create a variable template node.
+ static VarTemplateDecl *Create(ASTContext &C, DeclContext *DC,
+ SourceLocation L, DeclarationName Name,
+ TemplateParameterList *Params,
+ VarDecl *Decl);
+
+ /// \brief Create an empty variable template node.
+ static VarTemplateDecl *CreateDeserialized(ASTContext &C, unsigned ID);
+
+ /// \brief Return the specialization with the provided arguments if it exists,
+ /// otherwise return the insertion point.
+ VarTemplateSpecializationDecl *
+ findSpecialization(ArrayRef<TemplateArgument> Args, void *&InsertPos);
+
+ /// \brief Insert the specified specialization knowing that it is not already
+ /// in. InsertPos must be obtained from findSpecialization.
+ void AddSpecialization(VarTemplateSpecializationDecl *D, void *InsertPos);
+
+ VarTemplateDecl *getCanonicalDecl() override {
+ return cast<VarTemplateDecl>(RedeclarableTemplateDecl::getCanonicalDecl());
+ }
+ const VarTemplateDecl *getCanonicalDecl() const {
+ return cast<VarTemplateDecl>(RedeclarableTemplateDecl::getCanonicalDecl());
+ }
+
+ /// \brief Retrieve the previous declaration of this variable template, or
+ /// NULL if no such declaration exists.
+ VarTemplateDecl *getPreviousDecl() {
+ return cast_or_null<VarTemplateDecl>(
+ static_cast<RedeclarableTemplateDecl *>(this)->getPreviousDecl());
+ }
+
+ /// \brief Retrieve the previous declaration of this variable template, or
+ /// NULL if no such declaration exists.
+ const VarTemplateDecl *getPreviousDecl() const {
+ return cast_or_null<VarTemplateDecl>(
+ static_cast<const RedeclarableTemplateDecl *>(
+ this)->getPreviousDecl());
+ }
+
+ VarTemplateDecl *getMostRecentDecl() {
+ return cast<VarTemplateDecl>(
+ static_cast<RedeclarableTemplateDecl *>(this)->getMostRecentDecl());
+ }
+ const VarTemplateDecl *getMostRecentDecl() const {
+ return const_cast<VarTemplateDecl *>(this)->getMostRecentDecl();
+ }
+
+ VarTemplateDecl *getInstantiatedFromMemberTemplate() const {
+ return cast_or_null<VarTemplateDecl>(
+ RedeclarableTemplateDecl::getInstantiatedFromMemberTemplate());
+ }
+
+ /// \brief Return the partial specialization with the provided arguments if it
+ /// exists, otherwise return the insertion point.
+ VarTemplatePartialSpecializationDecl *
+ findPartialSpecialization(ArrayRef<TemplateArgument> Args, void *&InsertPos);
+
+ /// \brief Insert the specified partial specialization knowing that it is not
+ /// already in. InsertPos must be obtained from findPartialSpecialization.
+ void AddPartialSpecialization(VarTemplatePartialSpecializationDecl *D,
+ void *InsertPos);
+
+ /// \brief Retrieve the partial specializations as an ordered list.
+ void getPartialSpecializations(
+ SmallVectorImpl<VarTemplatePartialSpecializationDecl *> &PS);
+
+ /// \brief Find a variable template partial specialization which was
+ /// instantiated
+ /// from the given member partial specialization.
+ ///
+ /// \param D a member variable template partial specialization.
+ ///
+ /// \returns the variable template partial specialization which was
+ /// instantiated
+ /// from the given member partial specialization, or NULL if no such partial
+ /// specialization exists.
+ VarTemplatePartialSpecializationDecl *findPartialSpecInstantiatedFromMember(
+ VarTemplatePartialSpecializationDecl *D);
+
+ typedef SpecIterator<VarTemplateSpecializationDecl> spec_iterator;
+ typedef llvm::iterator_range<spec_iterator> spec_range;
+
+ spec_range specializations() const {
+ return spec_range(spec_begin(), spec_end());
+ }
+
+ spec_iterator spec_begin() const {
+ return makeSpecIterator(getSpecializations(), false);
+ }
+
+ spec_iterator spec_end() const {
+ return makeSpecIterator(getSpecializations(), true);
+ }
+
+ // Implement isa/cast/dyncast support
+ static bool classof(const Decl *D) { return classofKind(D->getKind()); }
+ static bool classofKind(Kind K) { return K == VarTemplate; }
+
+ friend class ASTDeclReader;
+ friend class ASTDeclWriter;
+};
+
+} /* 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..4eaae35
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/AST/DeclVisitor.h
@@ -0,0 +1,79 @@
+//===--- 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/DeclCXX.h"
+#include "clang/AST/DeclFriend.h"
+#include "clang/AST/DeclObjC.h"
+#include "clang/AST/DeclOpenMP.h"
+#include "clang/AST/DeclTemplate.h"
+
+namespace clang {
+namespace declvisitor {
+
+template <typename T> struct make_ptr { typedef T *type; };
+template <typename T> struct make_const_ptr { typedef const T *type; };
+
+/// \brief A simple visitor class that helps create declaration visitors.
+template<template <typename> class Ptr, typename ImplClass, typename RetTy=void>
+class Base {
+public:
+
+#define PTR(CLASS) typename Ptr<CLASS>::type
+#define DISPATCH(NAME, CLASS) \
+ return static_cast<ImplClass*>(this)->Visit##NAME(static_cast<PTR(CLASS)>(D))
+
+ RetTy Visit(PTR(Decl) D) {
+ switch (D->getKind()) {
+#define DECL(DERIVED, BASE) \
+ case Decl::DERIVED: DISPATCH(DERIVED##Decl, DERIVED##Decl);
+#define ABSTRACT_DECL(DECL)
+#include "clang/AST/DeclNodes.inc"
+ }
+ llvm_unreachable("Decl that isn't part of 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(PTR(DERIVED##Decl) D) { DISPATCH(BASE, BASE); }
+#include "clang/AST/DeclNodes.inc"
+
+ RetTy VisitDecl(PTR(Decl) D) { return RetTy(); }
+
+#undef PTR
+#undef DISPATCH
+};
+
+} // end namespace declvisitor
+
+/// \brief A simple visitor class that helps create declaration visitors.
+///
+/// This class does not preserve constness of Decl pointers (see also
+/// ConstDeclVisitor).
+template<typename ImplClass, typename RetTy=void>
+class DeclVisitor
+ : public declvisitor::Base<declvisitor::make_ptr, ImplClass, RetTy> {};
+
+/// \brief A simple visitor class that helps create declaration visitors.
+///
+/// This class preserves constness of Decl pointers (see also DeclVisitor).
+template<typename ImplClass, typename RetTy=void>
+class ConstDeclVisitor
+ : public declvisitor::Base<declvisitor::make_const_ptr, ImplClass, RetTy> {};
+
+} // 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..9482e83e
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/AST/DeclarationName.h
@@ -0,0 +1,598 @@
+//===-- 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/Basic/PartialDiagnostic.h"
+#include "llvm/Support/Compiler.h"
+
+namespace llvm {
+ template <typename T> struct DenseMapInfo;
+}
+
+namespace clang {
+ class ASTContext;
+ class CXXLiteralOperatorIdName;
+ class CXXOperatorIdName;
+ class CXXSpecialName;
+ class DeclarationNameExtra;
+ class IdentifierInfo;
+ class MultiKeywordSelector;
+ enum OverloadedOperatorKind : int;
+ class QualType;
+ class Type;
+ class TypeSourceInfo;
+ class UsingDirectiveDecl;
+
+ template <typename> class CanQual;
+ typedef CanQual<Type> CanQualType;
+
+/// 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
+ };
+ static const unsigned NumNameKinds = CXXUsingDirective + 1;
+
+private:
+ /// StoredNameKind - The kind of name that is actually stored in the
+ /// upper bits of the Ptr field. This is only used internally.
+ ///
+ /// Note: The entries here are synchronized with the entries in Selector,
+ /// for efficient translation between the two.
+ enum StoredNameKind {
+ StoredIdentifier = 0,
+ StoredObjCZeroArgSelector = 0x01,
+ StoredObjCOneArgSelector = 0x02,
+ StoredDeclarationNameExtra = 0x03,
+ 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 {
+ NameKind Kind = getNameKind();
+ if (Kind >= CXXConstructorName && Kind <= CXXConversionFunctionName)
+ return reinterpret_cast<CXXSpecialName *>(Ptr & ~PtrMask);
+ return nullptr;
+ }
+
+ /// getAsCXXOperatorIdName
+ CXXOperatorIdName *getAsCXXOperatorIdName() const {
+ if (getNameKind() == CXXOperatorName)
+ return reinterpret_cast<CXXOperatorIdName *>(Ptr & ~PtrMask);
+ return nullptr;
+ }
+
+ CXXLiteralOperatorIdName *getAsCXXLiteralOperatorIdName() const {
+ if (getNameKind() == CXXLiteralOperatorName)
+ return reinterpret_cast<CXXLiteralOperatorIdName *>(Ptr & ~PtrMask);
+ return nullptr;
+ }
+
+ // 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;
+
+ /// getFETokenInfoAsVoidSlow - Retrieves the front end-specified pointer
+ /// for this name as a void pointer if it's not an identifier.
+ void *getFETokenInfoAsVoidSlow() 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) : Ptr(Sel.InfoPtr) { }
+
+ /// getUsingDirectiveName - Return name for all using-directives.
+ static DeclarationName getUsingDirectiveName();
+
+ // operator bool() - Evaluates true when this declaration name is
+ // non-empty.
+ explicit operator bool() const {
+ return ((Ptr & PtrMask) != 0) ||
+ (reinterpret_cast<IdentifierInfo *>(Ptr & ~PtrMask));
+ }
+
+ /// \brief Evaluates true when this declaration name is empty.
+ bool isEmpty() const {
+ return !*this;
+ }
+
+ /// 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;
+
+ /// 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 nullptr;
+ }
+
+ /// 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 {
+ assert((getNameKind() == ObjCZeroArgSelector ||
+ getNameKind() == ObjCOneArgSelector ||
+ getNameKind() == ObjCMultiArgSelector ||
+ Ptr == 0) && "Not a selector!");
+ return Selector(Ptr);
+ }
+
+ /// 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 {
+ if (const IdentifierInfo *Info = getAsIdentifierInfo())
+ return Info->getFETokenInfo<T>();
+ return static_cast<T*>(getFETokenInfoAsVoidSlow());
+ }
+
+ 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;
+};
+
+raw_ostream &operator<<(raw_ostream &OS, DeclarationName N);
+
+/// 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&) = delete;
+ void operator=(const DeclarationNameTable&) = delete;
+
+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);
+
+ /// getCXXDestructorName - Returns the name of a C++ destructor
+ /// for the given Type.
+ DeclarationName getCXXDestructorName(CanQualType Ty);
+
+ /// getCXXConversionFunctionName - Returns the name of a C++
+ /// conversion function for the given Type.
+ DeclarationName getCXXConversionFunctionName(CanQualType 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 {
+ // 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 NT {
+ TypeSourceInfo *TInfo;
+ };
+
+ // The location (if any) of the operator keyword is stored elsewhere.
+ struct CXXOpName {
+ unsigned BeginOpNameLoc;
+ unsigned EndOpNameLoc;
+ };
+
+ // The location (if any) of the operator keyword is stored elsewhere.
+ struct CXXLitOpName {
+ unsigned OpNameLoc;
+ };
+
+ // struct {} CXXUsingDirective;
+ // struct {} ObjCZeroArgSelector;
+ // struct {} ObjCOneArgSelector;
+ // struct {} ObjCMultiArgSelector;
+ union {
+ struct NT NamedType;
+ struct CXXOpName CXXOperatorName;
+ struct CXXLitOpName CXXLiteralOperatorName;
+ };
+
+ 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 involves a template parameter.
+ bool isInstantiationDependent() const;
+
+ /// \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(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 LLVM_READONLY {
+ return SourceRange(getLocStart(), getLocEnd());
+ }
+ SourceLocation getLocStart() const LLVM_READONLY {
+ return getBeginLoc();
+ }
+ SourceLocation getLocEnd() const LLVM_READONLY {
+ SourceLocation EndLoc = getEndLoc();
+ return EndLoc.isValid() ? EndLoc : getLocStart();
+ }
+};
+
+/// 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(),
+ DiagnosticsEngine::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(),
+ DiagnosticsEngine::ak_declarationname);
+ return PD;
+}
+
+inline raw_ostream &operator<<(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 Name) {
+ return DenseMapInfo<void*>::getHashValue(Name.getAsOpaquePtr());
+ }
+
+ 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..8e038c8
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/AST/DependentDiagnostic.h
@@ -0,0 +1,189 @@
+//===-- 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_DEPENDENTDIAGNOSTIC_H
+#define LLVM_CLANG_AST_DEPENDENTDIAGNOSTIC_H
+
+#include "clang/AST/DeclBase.h"
+#include "clang/AST/DeclContextInternals.h"
+#include "clang/AST/Type.h"
+#include "clang/Basic/PartialDiagnostic.h"
+#include "clang/Basic/SourceLocation.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;
+
+ 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(nullptr) {}
+ 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_range DeclContext::ddiags() const {
+ assert(isDependentContext()
+ && "cannot iterate dependent diagnostics of non-dependent context");
+ const DependentStoredDeclsMap *Map
+ = static_cast<DependentStoredDeclsMap*>(getPrimaryContext()->getLookupPtr());
+
+ if (!Map)
+ // Return an empty range using the always-end default constructor.
+ return ddiag_range(ddiag_iterator(), ddiag_iterator());
+
+ return ddiag_range(ddiag_iterator(Map->FirstDiagnostic), 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..aad7726
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/AST/EvaluatedExprVisitor.h
@@ -0,0 +1,129 @@
+//===--- 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/DeclCXX.h"
+#include "clang/AST/Expr.h"
+#include "clang/AST/ExprCXX.h"
+#include "clang/AST/StmtVisitor.h"
+
+namespace clang {
+
+class ASTContext;
+
+/// \brief Given a potentially-evaluated expression, this visitor visits all
+/// of its potentially-evaluated subexpressions, recursively.
+template<template <typename> class Ptr, typename ImplClass>
+class EvaluatedExprVisitorBase : public StmtVisitorBase<Ptr, ImplClass, void> {
+protected:
+ const ASTContext &Context;
+
+public:
+#define PTR(CLASS) typename Ptr<CLASS>::type
+
+ explicit EvaluatedExprVisitorBase(const ASTContext &Context) : Context(Context) { }
+
+ // Expressions that have no potentially-evaluated subexpressions (but may have
+ // other sub-expressions).
+ void VisitDeclRefExpr(PTR(DeclRefExpr) E) { }
+ void VisitOffsetOfExpr(PTR(OffsetOfExpr) E) { }
+ void VisitUnaryExprOrTypeTraitExpr(PTR(UnaryExprOrTypeTraitExpr) E) { }
+ void VisitExpressionTraitExpr(PTR(ExpressionTraitExpr) E) { }
+ void VisitBlockExpr(PTR(BlockExpr) E) { }
+ void VisitCXXUuidofExpr(PTR(CXXUuidofExpr) E) { }
+ void VisitCXXNoexceptExpr(PTR(CXXNoexceptExpr) E) { }
+
+ void VisitMemberExpr(PTR(MemberExpr) E) {
+ // Only the base matters.
+ return this->Visit(E->getBase());
+ }
+
+ void VisitChooseExpr(PTR(ChooseExpr) E) {
+ // Don't visit either child expression if the condition is dependent.
+ if (E->getCond()->isValueDependent())
+ return;
+ // Only the selected subexpression matters; the other one is not evaluated.
+ return this->Visit(E->getChosenSubExpr());
+ }
+
+ void VisitGenericSelectionExpr(PTR(GenericSelectionExpr) E) {
+ // The controlling expression of a generic selection is not evaluated.
+
+ // Don't visit either child expression if the condition is type-dependent.
+ if (E->isResultDependent())
+ return;
+ // Only the selected subexpression matters; the other subexpressions and the
+ // controlling expression are not evaluated.
+ return this->Visit(E->getResultExpr());
+ }
+
+ void VisitDesignatedInitExpr(PTR(DesignatedInitExpr) E) {
+ // Only the actual initializer matters; the designators are all constant
+ // expressions.
+ return this->Visit(E->getInit());
+ }
+
+ void VisitCXXTypeidExpr(PTR(CXXTypeidExpr) E) {
+ if (E->isPotentiallyEvaluated())
+ return this->Visit(E->getExprOperand());
+ }
+
+ void VisitCallExpr(PTR(CallExpr) CE) {
+ if (!CE->isUnevaluatedBuiltinCall(Context))
+ return static_cast<ImplClass*>(this)->VisitExpr(CE);
+ }
+
+ void VisitLambdaExpr(PTR(LambdaExpr) LE) {
+ // Only visit the capture initializers, and not the body.
+ for (LambdaExpr::const_capture_init_iterator I = LE->capture_init_begin(),
+ E = LE->capture_init_end();
+ I != E; ++I)
+ if (*I)
+ this->Visit(*I);
+ }
+
+ /// \brief The basis case walks all of the children of the statement or
+ /// expression, assuming they are all potentially evaluated.
+ void VisitStmt(PTR(Stmt) S) {
+ for (auto *SubStmt : S->children())
+ if (SubStmt)
+ this->Visit(SubStmt);
+ }
+
+#undef PTR
+};
+
+/// EvaluatedExprVisitor - This class visits 'Expr *'s
+template<typename ImplClass>
+class EvaluatedExprVisitor
+ : public EvaluatedExprVisitorBase<make_ptr, ImplClass> {
+public:
+ explicit EvaluatedExprVisitor(const ASTContext &Context) :
+ EvaluatedExprVisitorBase<make_ptr, ImplClass>(Context) { }
+};
+
+/// ConstEvaluatedExprVisitor - This class visits 'const Expr *'s.
+template<typename ImplClass>
+class ConstEvaluatedExprVisitor
+ : public EvaluatedExprVisitorBase<make_const_ptr, ImplClass> {
+public:
+ explicit ConstEvaluatedExprVisitor(const ASTContext &Context) :
+ EvaluatedExprVisitorBase<make_const_ptr, ImplClass>(Context) { }
+};
+
+}
+
+#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..095dd6a
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/AST/Expr.h
@@ -0,0 +1,4941 @@
+//===--- 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/ASTVector.h"
+#include "clang/AST/Decl.h"
+#include "clang/AST/DeclAccessPair.h"
+#include "clang/AST/OperationKinds.h"
+#include "clang/AST/Stmt.h"
+#include "clang/AST/TemplateBase.h"
+#include "clang/AST/Type.h"
+#include "clang/Basic/CharInfo.h"
+#include "clang/Basic/LangOptions.h"
+#include "clang/Basic/TypeTraits.h"
+#include "llvm/ADT/APFloat.h"
+#include "llvm/ADT/APSInt.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/Support/Compiler.h"
+
+namespace clang {
+ class APValue;
+ class ASTContext;
+ class BlockDecl;
+ class CXXBaseSpecifier;
+ class CXXMemberCallExpr;
+ class CXXOperatorCallExpr;
+ class CastExpr;
+ class Decl;
+ class IdentifierInfo;
+ class MaterializeTemporaryExpr;
+ class NamedDecl;
+ class ObjCPropertyRefExpr;
+ class OpaqueValueExpr;
+ class ParmVarDecl;
+ class StringLiteral;
+ class TargetInfo;
+ class ValueDecl;
+
+/// \brief A simple array of base specifiers.
+typedef SmallVector<CXXBaseSpecifier*, 4> CXXCastPath;
+
+/// \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,
+ MemberPointerAdjustment
+ } Kind;
+
+ struct DTB {
+ const CastExpr *BasePath;
+ const CXXRecordDecl *DerivedClass;
+ };
+
+ struct P {
+ const MemberPointerType *MPT;
+ Expr *RHS;
+ };
+
+ union {
+ struct DTB DerivedToBase;
+ FieldDecl *Field;
+ struct P Ptr;
+ };
+
+ SubobjectAdjustment(const CastExpr *BasePath,
+ const CXXRecordDecl *DerivedClass)
+ : Kind(DerivedToBaseAdjustment) {
+ DerivedToBase.BasePath = BasePath;
+ DerivedToBase.DerivedClass = DerivedClass;
+ }
+
+ SubobjectAdjustment(FieldDecl *Field)
+ : Kind(FieldAdjustment) {
+ this->Field = Field;
+ }
+
+ SubobjectAdjustment(const MemberPointerType *MPT, Expr *RHS)
+ : Kind(MemberPointerAdjustment) {
+ this->Ptr.MPT = MPT;
+ this->Ptr.RHS = RHS;
+ }
+};
+
+/// 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 ID, bool ContainsUnexpandedParameterPack)
+ : Stmt(SC)
+ {
+ ExprBits.TypeDependent = TD;
+ ExprBits.ValueDependent = VD;
+ ExprBits.InstantiationDependent = ID;
+ 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 (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 is instantiation-dependent, meaning that
+ /// it depends in some way on a template parameter, even if neither its type
+ /// nor (constant) value can change due to the template instantiation.
+ ///
+ /// In the following example, the expression \c sizeof(sizeof(T() + T())) is
+ /// instantiation-dependent (since it involves a template parameter \c T), but
+ /// is neither type- nor value-dependent, since the type of the inner
+ /// \c sizeof is known (\c std::size_t) and therefore the size of the outer
+ /// \c sizeof is known.
+ ///
+ /// \code
+ /// template<typename T>
+ /// void f(T x, T y) {
+ /// sizeof(sizeof(T() + T());
+ /// }
+ /// \endcode
+ ///
+ bool isInstantiationDependent() const {
+ return ExprBits.InstantiationDependent;
+ }
+
+ /// \brief Set whether this expression is instantiation-dependent or not.
+ void setInstantiationDependent(bool ID) {
+ ExprBits.InstantiationDependent = ID;
+ }
+
+ /// \brief Whether this expression contains an unexpanded parameter
+ /// pack (for C++11 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 LLVM_READONLY;
+
+ /// isUnusedResultAWarning - Return true if this immediate expression should
+ /// be warned about if the result is unused. If so, fill in expr, location,
+ /// and ranges with expr to warn on and source locations/ranges appropriate
+ /// for a warning.
+ bool isUnusedResultAWarning(const Expr *&WarnExpr, 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++11 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_InvalidMessageExpression,
+ LV_MemberFunction,
+ LV_SubObjCPropertySetting,
+ LV_ClassTemporary,
+ LV_ArrayTemporary
+ };
+ /// Reasons why an expression might not be an l-value.
+ LValueClassification ClassifyLValue(ASTContext &Ctx) const;
+
+ enum isModifiableLvalueResult {
+ MLV_Valid,
+ MLV_NotObjectType,
+ MLV_IncompleteVoidType,
+ MLV_DuplicateVectorComponents,
+ MLV_InvalidExpression,
+ MLV_LValueCast, // Specialized form of MLV_InvalidExpression.
+ MLV_IncompleteType,
+ MLV_ConstQualified,
+ MLV_ConstAddrSpace,
+ MLV_ArrayType,
+ MLV_NoSetterProperty,
+ MLV_MemberFunction,
+ MLV_SubObjCPropertySetting,
+ MLV_InvalidMessageExpression,
+ MLV_ClassTemporary,
+ MLV_ArrayTemporary
+ };
+ /// 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.
+ isModifiableLvalueResult
+ isModifiableLvalue(ASTContext &Ctx, SourceLocation *Loc = nullptr) const;
+
+ /// \brief The return type of classify(). Represents the C++11 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_AddressableVoid, // Void expression whose address can be taken in C.
+ CL_DuplicateVectorComponents, // A vector shuffle with dupes.
+ CL_MemberFunction, // An expression referring to a member function
+ CL_SubObjCPropertySetting,
+ CL_ClassTemporary, // A temporary of class type, or subobject thereof.
+ CL_ArrayTemporary, // A temporary of array type.
+ CL_ObjCMessageRValue, // ObjC message is an rvalue
+ 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_NoSetterProperty,// Implicit assignment to ObjC property without setter
+ CM_ConstQualified,
+ CM_ConstAddrSpace,
+ 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++11
+ /// expression taxonomy.
+ ///
+ /// C++11 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, nullptr);
+ }
+
+ /// \brief ClassifyModifiable - Classify this expression according to the
+ /// C++11 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 Returns true if this expression is a gl-value that
+ /// potentially refers to a bit-field.
+ ///
+ /// In C++, whether a gl-value refers to a bitfield is essentially
+ /// an aspect of the value-kind type system.
+ bool refersToBitField() const { return getObjectKind() == OK_BitField; }
+
+ /// \brief If this expression refers to a bit-field, retrieve the
+ /// declaration of that bit-field.
+ ///
+ /// Note that this returns a non-null pointer in subtly different
+ /// places than refersToBitField returns true. In particular, this can
+ /// return a non-null pointer even for r-values loaded from
+ /// bit-fields, but it will return null for a conditional bit-field.
+ FieldDecl *getSourceBitField();
+
+ const FieldDecl *getSourceBitField() const {
+ return const_cast<Expr*>(this)->getSourceBitField();
+ }
+
+ /// \brief If this expression is an l-value for an Objective C
+ /// property, find the underlying property reference expression.
+ const ObjCPropertyRefExpr *getObjCProperty() const;
+
+ /// \brief Check if this expression is the ObjC 'self' implicit parameter.
+ bool isObjCSelfExpr() const;
+
+ /// \brief Returns whether this expression refers to a vector element.
+ bool refersToVectorElement() const;
+
+ /// \brief Returns whether this expression refers to a global register
+ /// variable.
+ bool refersToGlobalRegisterVar() const;
+
+ /// \brief Returns whether this expression has a placeholder type.
+ bool hasPlaceholderType() const {
+ return getType()->isPlaceholderType();
+ }
+
+ /// \brief Returns whether this expression has a specific placeholder type.
+ bool hasPlaceholderType(BuiltinType::Kind K) const {
+ assert(BuiltinType::isPlaceholderTypeKind(K));
+ if (const BuiltinType *BT = dyn_cast<BuiltinType>(getType()))
+ return BT->getKind() == K;
+ return false;
+ }
+
+ /// 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.
+ ///
+ /// Note: This does not perform the implicit conversions required by C++11
+ /// [expr.const]p5.
+ bool isIntegerConstantExpr(llvm::APSInt &Result, const ASTContext &Ctx,
+ SourceLocation *Loc = nullptr,
+ bool isEvaluated = true) const;
+ bool isIntegerConstantExpr(const ASTContext &Ctx,
+ SourceLocation *Loc = nullptr) const;
+
+ /// isCXX98IntegralConstantExpr - Return true if this expression is an
+ /// integral constant expression in C++98. Can only be used in C++.
+ bool isCXX98IntegralConstantExpr(const ASTContext &Ctx) const;
+
+ /// isCXX11ConstantExpr - Return true if this expression is a constant
+ /// expression in C++11. Can only be used in C++.
+ ///
+ /// Note: This does not perform the implicit conversions required by C++11
+ /// [expr.const]p5.
+ bool isCXX11ConstantExpr(const ASTContext &Ctx, APValue *Result = nullptr,
+ SourceLocation *Loc = nullptr) const;
+
+ /// isPotentialConstantExpr - Return true if this function's definition
+ /// might be usable in a constant expression in C++11, if it were marked
+ /// constexpr. Return false if the function can never produce a constant
+ /// expression, along with diagnostics describing why not.
+ static bool isPotentialConstantExpr(const FunctionDecl *FD,
+ SmallVectorImpl<
+ PartialDiagnosticAt> &Diags);
+
+ /// isPotentialConstantExprUnevaluted - Return true if this expression might
+ /// be usable in a constant expression in C++11 in an unevaluated context, if
+ /// it were in function FD marked constexpr. Return false if the function can
+ /// never produce a constant expression, along with diagnostics describing
+ /// why not.
+ static bool isPotentialConstantExprUnevaluated(Expr *E,
+ const FunctionDecl *FD,
+ SmallVectorImpl<
+ PartialDiagnosticAt> &Diags);
+
+ /// isConstantInitializer - Returns true if this expression can be emitted to
+ /// IR as a constant, and thus can be used as a constant initializer in C.
+ /// If this expression is not constant and Culprit is non-null,
+ /// it is used to store the address of first non constant expr.
+ bool isConstantInitializer(ASTContext &Ctx, bool ForRef,
+ const Expr **Culprit = nullptr) const;
+
+ /// EvalStatus is a struct with detailed info about an evaluation in progress.
+ struct EvalStatus {
+ /// \brief Whether the evaluated expression has side effects.
+ /// For example, (f() && 0) can be folded, but it still has side effects.
+ bool HasSideEffects;
+
+ /// \brief Whether the evaluation hit undefined behavior.
+ /// For example, 1.0 / 0.0 can be folded to Inf, but has undefined behavior.
+ /// Likewise, INT_MAX + 1 can be folded to INT_MIN, but has UB.
+ bool HasUndefinedBehavior;
+
+ /// Diag - If this is non-null, it will be filled in with a stack of notes
+ /// indicating why evaluation failed (or why it failed to produce a constant
+ /// expression).
+ /// If the expression is unfoldable, the notes will indicate why it's not
+ /// foldable. If the expression is foldable, but not a constant expression,
+ /// the notes will describes why it isn't a constant expression. If the
+ /// expression *is* a constant expression, no notes will be produced.
+ SmallVectorImpl<PartialDiagnosticAt> *Diag;
+
+ EvalStatus()
+ : HasSideEffects(false), HasUndefinedBehavior(false), Diag(nullptr) {}
+
+ // hasSideEffects - Return true if the evaluated expression has
+ // side effects.
+ bool hasSideEffects() const {
+ return HasSideEffects;
+ }
+ };
+
+ /// EvalResult is a struct with detailed info about an evaluated expression.
+ struct EvalResult : EvalStatus {
+ /// Val - This is the value the expression can be folded to.
+ APValue Val;
+
+ // isGlobalLValue - Return true if the evaluated lvalue expression
+ // is global.
+ bool isGlobalLValue() const;
+ };
+
+ /// EvaluateAsRValue - Return true if this is a constant which we can fold to
+ /// an rvalue using any crazy technique (that has nothing to do with language
+ /// standards) that we want to, even if the expression has side-effects. If
+ /// this function returns true, it returns the folded constant in Result. If
+ /// the expression is a glvalue, an lvalue-to-rvalue conversion will be
+ /// applied.
+ bool EvaluateAsRValue(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, even if the expression has
+ /// side-effects.
+ bool EvaluateAsBooleanCondition(bool &Result, const ASTContext &Ctx) const;
+
+ enum SideEffectsKind {
+ SE_NoSideEffects, ///< Strictly evaluate the expression.
+ SE_AllowUndefinedBehavior, ///< Allow UB that we can give a value, but not
+ ///< arbitrary unmodeled side effects.
+ SE_AllowSideEffects ///< Allow any unmodeled side effect.
+ };
+
+ /// EvaluateAsInt - Return true if this is a constant which we can fold and
+ /// convert to an integer, using any crazy technique that we want to.
+ bool EvaluateAsInt(llvm::APSInt &Result, const ASTContext &Ctx,
+ SideEffectsKind AllowSideEffects = SE_NoSideEffects) const;
+
+ /// isEvaluatable - Call EvaluateAsRValue to see if this expression can be
+ /// constant folded without side-effects, but discard the result.
+ bool isEvaluatable(const ASTContext &Ctx,
+ SideEffectsKind AllowSideEffects = SE_NoSideEffects) const;
+
+ /// HasSideEffects - This routine returns true for all those expressions
+ /// which have any effect other than producing a value. Example is a function
+ /// call, volatile variable read, or throwing an exception. If
+ /// IncludePossibleEffects is false, this call treats certain expressions with
+ /// potential side effects (such as function call-like expressions,
+ /// instantiation-dependent expressions, or invocations from a macro) as not
+ /// having side effects.
+ bool HasSideEffects(const ASTContext &Ctx,
+ bool IncludePossibleEffects = true) const;
+
+ /// \brief Determine whether this expression involves a call to any function
+ /// that is not trivial.
+ bool hasNonTrivialCall(const ASTContext &Ctx) const;
+
+ /// EvaluateKnownConstInt - Call EvaluateAsRValue and return the folded
+ /// integer. This must be called on an expression that constant folds to an
+ /// integer.
+ llvm::APSInt EvaluateKnownConstInt(const ASTContext &Ctx,
+ SmallVectorImpl<PartialDiagnosticAt> *Diag = nullptr) const;
+
+ void EvaluateForOverflow(const ASTContext &Ctx) const;
+
+ /// EvaluateAsLValue - Evaluate an expression to see if we can fold it to an
+ /// lvalue with link time known address, with no side-effects.
+ bool EvaluateAsLValue(EvalResult &Result, const ASTContext &Ctx) const;
+
+ /// EvaluateAsInitializer - Evaluate an expression as if it were the
+ /// initializer of the given declaration. Returns true if the initializer
+ /// can be folded to a constant, and produces any relevant notes. In C++11,
+ /// notes will be produced if the expression is not a constant expression.
+ bool EvaluateAsInitializer(APValue &Result, const ASTContext &Ctx,
+ const VarDecl *VD,
+ SmallVectorImpl<PartialDiagnosticAt> &Notes) const;
+
+ /// EvaluateWithSubstitution - Evaluate an expression as if from the context
+ /// of a call to the given function with the given arguments, inside an
+ /// unevaluated context. Returns true if the expression could be folded to a
+ /// constant.
+ bool EvaluateWithSubstitution(APValue &Value, ASTContext &Ctx,
+ const FunctionDecl *Callee,
+ ArrayRef<const Expr*> Args) const;
+
+ /// \brief If the current Expr is a pointer, this will try to statically
+ /// determine the number of bytes available where the pointer is pointing.
+ /// Returns true if all of the above holds and we were able to figure out the
+ /// size, false otherwise.
+ ///
+ /// \param Type - How to evaluate the size of the Expr, as defined by the
+ /// "type" parameter of __builtin_object_size
+ bool tryEvaluateObjectSize(uint64_t &Result, ASTContext &Ctx,
+ unsigned Type) 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
+ /// expression that is not a simple, possibly parenthesized, zero literal.
+ /// C++ Core Issue 903 will classify these expressions as "not pointers"
+ /// once it is adopted.
+ /// http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#903
+ NPCK_ZeroExpression,
+
+ /// \brief Expression is a Null pointer constant built from a literal zero.
+ NPCK_ZeroLiteral,
+
+ /// \brief Expression is a C++11 nullptr.
+ NPCK_CXX11_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 Given an expression of bound-member type, find the type
+ /// of the member. Returns null if this is an *overloaded* bound
+ /// member expression.
+ static QualType findBoundMemberType(const Expr *expr);
+
+ /// IgnoreImpCasts - Skip past any implicit casts which might
+ /// surround this expression. Only skips ImplicitCastExprs.
+ Expr *IgnoreImpCasts() LLVM_READONLY;
+
+ /// IgnoreImplicit - Skip past any implicit AST nodes which might
+ /// surround this expression.
+ Expr *IgnoreImplicit() LLVM_READONLY {
+ return cast<Expr>(Stmt::IgnoreImplicit());
+ }
+
+ const Expr *IgnoreImplicit() const LLVM_READONLY {
+ return const_cast<Expr*>(this)->IgnoreImplicit();
+ }
+
+ /// 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() LLVM_READONLY;
+
+ /// IgnoreParenCasts - Ignore parentheses and casts. Strip off any ParenExpr
+ /// or CastExprs, returning their operand.
+ Expr *IgnoreParenCasts() LLVM_READONLY;
+
+ /// Ignore casts. Strip off any CastExprs, returning their operand.
+ Expr *IgnoreCasts() LLVM_READONLY;
+
+ /// IgnoreParenImpCasts - Ignore parentheses and implicit casts. Strip off
+ /// any ParenExpr or ImplicitCastExprs, returning their operand.
+ Expr *IgnoreParenImpCasts() LLVM_READONLY;
+
+ /// IgnoreConversionOperator - Ignore conversion operator. If this Expr is a
+ /// call to a conversion operator, return the argument.
+ Expr *IgnoreConversionOperator() LLVM_READONLY;
+
+ const Expr *IgnoreConversionOperator() const LLVM_READONLY {
+ return const_cast<Expr*>(this)->IgnoreConversionOperator();
+ }
+
+ const Expr *IgnoreParenImpCasts() const LLVM_READONLY {
+ 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() LLVM_READONLY;
+
+ const Expr *IgnoreParenLValueCasts() const LLVM_READONLY {
+ 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) LLVM_READONLY;
+
+ /// Ignore parentheses and derived-to-base casts.
+ Expr *ignoreParenBaseCasts() LLVM_READONLY;
+
+ const Expr *ignoreParenBaseCasts() const LLVM_READONLY {
+ return const_cast<Expr*>(this)->ignoreParenBaseCasts();
+ }
+
+ /// \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;
+
+ /// \brief Whether this expression is an implicit reference to 'this' in C++.
+ bool isImplicitCXXThis() const;
+
+ const Expr *IgnoreImpCasts() const LLVM_READONLY {
+ return const_cast<Expr*>(this)->IgnoreImpCasts();
+ }
+ const Expr *IgnoreParens() const LLVM_READONLY {
+ return const_cast<Expr*>(this)->IgnoreParens();
+ }
+ const Expr *IgnoreParenCasts() const LLVM_READONLY {
+ return const_cast<Expr*>(this)->IgnoreParenCasts();
+ }
+ /// Strip off casts, but keep parentheses.
+ const Expr *IgnoreCasts() const LLVM_READONLY {
+ return const_cast<Expr*>(this)->IgnoreCasts();
+ }
+
+ const Expr *IgnoreParenNoopCasts(ASTContext &Ctx) const LLVM_READONLY {
+ return const_cast<Expr*>(this)->IgnoreParenNoopCasts(Ctx);
+ }
+
+ static bool hasAnyTypeDependentArguments(ArrayRef<Expr *> Exprs);
+
+ /// \brief For an expression of class type or pointer to class type,
+ /// return the most derived class decl the expression is known to refer to.
+ ///
+ /// If this expression is a cast, this method looks through it to find the
+ /// most derived decl that can be inferred from the expression.
+ /// This is valid because derived-to-base conversions have undefined
+ /// behavior if the object isn't dynamically of the derived type.
+ const CXXRecordDecl *getBestDynamicClassType() const;
+
+ /// Walk outwards from an expression we want to bind a reference to and
+ /// find the expression whose lifetime needs to be extended. Record
+ /// the LHSs of comma expressions and adjustments needed along the path.
+ const Expr *skipRValueSubobjectAdjustments(
+ SmallVectorImpl<const Expr *> &CommaLHS,
+ SmallVectorImpl<SubobjectAdjustment> &Adjustments) const;
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() >= firstExprConstant &&
+ T->getStmtClass() <= lastExprConstant;
+ }
+};
+
+//===----------------------------------------------------------------------===//
+// 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 *SourceExpr = nullptr)
+ : Expr(OpaqueValueExprClass, T, VK, OK,
+ T->isDependentType(),
+ T->isDependentType() ||
+ (SourceExpr && SourceExpr->isValueDependent()),
+ T->isInstantiationDependentType(),
+ false),
+ SourceExpr(SourceExpr), 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; }
+
+ SourceLocation getLocStart() const LLVM_READONLY {
+ return SourceExpr ? SourceExpr->getLocStart() : Loc;
+ }
+ SourceLocation getLocEnd() const LLVM_READONLY {
+ return SourceExpr ? SourceExpr->getLocEnd() : Loc;
+ }
+ SourceLocation getExprLoc() const LLVM_READONLY {
+ if (SourceExpr) return SourceExpr->getExprLoc();
+ return Loc;
+ }
+
+ child_range children() {
+ return child_range(child_iterator(), child_iterator());
+ }
+
+ /// 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; }
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == OpaqueValueExprClass;
+ }
+};
+
+/// \brief A reference to a declared variable, function, enum, etc.
+/// [C99 6.5.1p2]
+///
+/// This encodes all the information about how a declaration is referenced
+/// within an expression.
+///
+/// There are several optional constructs attached to DeclRefExprs only when
+/// they apply in order to conserve memory. These are laid out past the end of
+/// the object, and flags in the DeclRefExprBitfield track whether they exist:
+///
+/// DeclRefExprBits.HasQualifier:
+/// Specifies when this declaration reference expression has a C++
+/// nested-name-specifier.
+/// DeclRefExprBits.HasFoundDecl:
+/// Specifies when this declaration reference expression has a record of
+/// a NamedDecl (different from the referenced ValueDecl) which was found
+/// during name lookup and/or overload resolution.
+/// DeclRefExprBits.HasTemplateKWAndArgsInfo:
+/// Specifies when this declaration reference expression has an explicit
+/// C++ template keyword and/or template argument list.
+/// DeclRefExprBits.RefersToEnclosingVariableOrCapture
+/// Specifies when this declaration reference expression (validly)
+/// refers to an enclosed local or a captured variable.
+class DeclRefExpr final
+ : public Expr,
+ private llvm::TrailingObjects<DeclRefExpr, NestedNameSpecifierLoc,
+ NamedDecl *, ASTTemplateKWAndArgsInfo,
+ TemplateArgumentLoc> {
+ /// \brief The declaration that we are referencing.
+ ValueDecl *D;
+
+ /// \brief The location of the declaration name itself.
+ SourceLocation Loc;
+
+ /// \brief Provides source/type location info for the declaration name
+ /// embedded in D.
+ DeclarationNameLoc DNLoc;
+
+ size_t numTrailingObjects(OverloadToken<NestedNameSpecifierLoc>) const {
+ return hasQualifier() ? 1 : 0;
+ }
+
+ size_t numTrailingObjects(OverloadToken<NamedDecl *>) const {
+ return hasFoundDecl() ? 1 : 0;
+ }
+
+ size_t numTrailingObjects(OverloadToken<ASTTemplateKWAndArgsInfo>) const {
+ return hasTemplateKWAndArgsInfo() ? 1 : 0;
+ }
+
+ /// \brief Test whether there is a distinct FoundDecl attached to the end of
+ /// this DRE.
+ bool hasFoundDecl() const { return DeclRefExprBits.HasFoundDecl; }
+
+ DeclRefExpr(const ASTContext &Ctx,
+ NestedNameSpecifierLoc QualifierLoc,
+ SourceLocation TemplateKWLoc,
+ ValueDecl *D, bool RefersToEnlosingVariableOrCapture,
+ const DeclarationNameInfo &NameInfo,
+ NamedDecl *FoundD,
+ 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(const ASTContext &C);
+
+public:
+ DeclRefExpr(ValueDecl *D, bool RefersToEnclosingVariableOrCapture, QualType T,
+ ExprValueKind VK, SourceLocation L,
+ const DeclarationNameLoc &LocInfo = DeclarationNameLoc())
+ : Expr(DeclRefExprClass, T, VK, OK_Ordinary, false, false, false, false),
+ D(D), Loc(L), DNLoc(LocInfo) {
+ DeclRefExprBits.HasQualifier = 0;
+ DeclRefExprBits.HasTemplateKWAndArgsInfo = 0;
+ DeclRefExprBits.HasFoundDecl = 0;
+ DeclRefExprBits.HadMultipleCandidates = 0;
+ DeclRefExprBits.RefersToEnclosingVariableOrCapture =
+ RefersToEnclosingVariableOrCapture;
+ computeDependence(D->getASTContext());
+ }
+
+ static DeclRefExpr *
+ Create(const ASTContext &Context, NestedNameSpecifierLoc QualifierLoc,
+ SourceLocation TemplateKWLoc, ValueDecl *D,
+ bool RefersToEnclosingVariableOrCapture, SourceLocation NameLoc,
+ QualType T, ExprValueKind VK, NamedDecl *FoundD = nullptr,
+ const TemplateArgumentListInfo *TemplateArgs = nullptr);
+
+ static DeclRefExpr *
+ Create(const ASTContext &Context, NestedNameSpecifierLoc QualifierLoc,
+ SourceLocation TemplateKWLoc, ValueDecl *D,
+ bool RefersToEnclosingVariableOrCapture,
+ const DeclarationNameInfo &NameInfo, QualType T, ExprValueKind VK,
+ NamedDecl *FoundD = nullptr,
+ const TemplateArgumentListInfo *TemplateArgs = nullptr);
+
+ /// \brief Construct an empty declaration reference expression.
+ static DeclRefExpr *CreateEmpty(const ASTContext &Context,
+ bool HasQualifier,
+ bool HasFoundDecl,
+ bool HasTemplateKWAndArgsInfo,
+ unsigned NumTemplateArgs);
+
+ ValueDecl *getDecl() { return D; }
+ const ValueDecl *getDecl() const { return D; }
+ void setDecl(ValueDecl *NewD) { D = NewD; }
+
+ DeclarationNameInfo getNameInfo() const {
+ return DeclarationNameInfo(getDecl()->getDeclName(), Loc, DNLoc);
+ }
+
+ SourceLocation getLocation() const { return Loc; }
+ void setLocation(SourceLocation L) { Loc = L; }
+ SourceLocation getLocStart() const LLVM_READONLY;
+ SourceLocation getLocEnd() const LLVM_READONLY;
+
+ /// \brief Determine whether this declaration reference was preceded by a
+ /// C++ nested-name-specifier, e.g., \c N::foo.
+ bool hasQualifier() const { return DeclRefExprBits.HasQualifier; }
+
+ /// \brief If the name was qualified, retrieves the nested-name-specifier
+ /// that precedes the name, with source-location information.
+ NestedNameSpecifierLoc getQualifierLoc() const {
+ if (!hasQualifier())
+ return NestedNameSpecifierLoc();
+ return *getTrailingObjects<NestedNameSpecifierLoc>();
+ }
+
+ /// \brief If the name was qualified, retrieves the nested-name-specifier
+ /// that precedes the name. Otherwise, returns NULL.
+ NestedNameSpecifier *getQualifier() const {
+ return getQualifierLoc().getNestedNameSpecifier();
+ }
+
+ /// \brief Get the NamedDecl through which this reference occurred.
+ ///
+ /// This Decl may be different from the ValueDecl actually referred to in the
+ /// presence of using declarations, etc. It always returns non-NULL, and may
+ /// simple return the ValueDecl when appropriate.
+
+ NamedDecl *getFoundDecl() {
+ return hasFoundDecl() ? *getTrailingObjects<NamedDecl *>() : D;
+ }
+
+ /// \brief Get the NamedDecl through which this reference occurred.
+ /// See non-const variant.
+ const NamedDecl *getFoundDecl() const {
+ return hasFoundDecl() ? *getTrailingObjects<NamedDecl *>() : D;
+ }
+
+ bool hasTemplateKWAndArgsInfo() const {
+ return DeclRefExprBits.HasTemplateKWAndArgsInfo;
+ }
+
+ /// \brief Retrieve the location of the template keyword preceding
+ /// this name, if any.
+ SourceLocation getTemplateKeywordLoc() const {
+ if (!hasTemplateKWAndArgsInfo()) return SourceLocation();
+ return getTrailingObjects<ASTTemplateKWAndArgsInfo>()->TemplateKWLoc;
+ }
+
+ /// \brief Retrieve the location of the left angle bracket starting the
+ /// explicit template argument list following the name, if any.
+ SourceLocation getLAngleLoc() const {
+ if (!hasTemplateKWAndArgsInfo()) return SourceLocation();
+ return getTrailingObjects<ASTTemplateKWAndArgsInfo>()->LAngleLoc;
+ }
+
+ /// \brief Retrieve the location of the right angle bracket ending the
+ /// explicit template argument list following the name, if any.
+ SourceLocation getRAngleLoc() const {
+ if (!hasTemplateKWAndArgsInfo()) return SourceLocation();
+ return getTrailingObjects<ASTTemplateKWAndArgsInfo>()->RAngleLoc;
+ }
+
+ /// \brief Determines whether the name in this declaration reference
+ /// was preceded by the template keyword.
+ bool hasTemplateKeyword() const { return getTemplateKeywordLoc().isValid(); }
+
+ /// \brief Determines whether this declaration reference was followed by an
+ /// explicit template argument list.
+ bool hasExplicitTemplateArgs() const { return getLAngleLoc().isValid(); }
+
+ /// \brief Copies the template arguments (if present) into the given
+ /// structure.
+ void copyTemplateArgumentsInto(TemplateArgumentListInfo &List) const {
+ if (hasExplicitTemplateArgs())
+ getTrailingObjects<ASTTemplateKWAndArgsInfo>()->copyInto(
+ getTrailingObjects<TemplateArgumentLoc>(), List);
+ }
+
+ /// \brief Retrieve the template arguments provided as part of this
+ /// template-id.
+ const TemplateArgumentLoc *getTemplateArgs() const {
+ if (!hasExplicitTemplateArgs())
+ return nullptr;
+
+ return getTrailingObjects<TemplateArgumentLoc>();
+ }
+
+ /// \brief Retrieve the number of template arguments provided as part of this
+ /// template-id.
+ unsigned getNumTemplateArgs() const {
+ if (!hasExplicitTemplateArgs())
+ return 0;
+
+ return getTrailingObjects<ASTTemplateKWAndArgsInfo>()->NumTemplateArgs;
+ }
+
+ /// \brief Returns true if this expression refers to a function that
+ /// was resolved from an overloaded set having size greater than 1.
+ bool hadMultipleCandidates() const {
+ return DeclRefExprBits.HadMultipleCandidates;
+ }
+ /// \brief Sets the flag telling whether this expression refers to
+ /// a function that was resolved from an overloaded set having size
+ /// greater than 1.
+ void setHadMultipleCandidates(bool V = true) {
+ DeclRefExprBits.HadMultipleCandidates = V;
+ }
+
+ /// \brief Does this DeclRefExpr refer to an enclosing local or a captured
+ /// variable?
+ bool refersToEnclosingVariableOrCapture() const {
+ return DeclRefExprBits.RefersToEnclosingVariableOrCapture;
+ }
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == DeclRefExprClass;
+ }
+
+ // Iterators
+ child_range children() {
+ return child_range(child_iterator(), child_iterator());
+ }
+
+ friend TrailingObjects;
+ friend class ASTStmtReader;
+ friend class ASTStmtWriter;
+};
+
+/// \brief [C99 6.4.2.2] - A predefined identifier such as __func__.
+class PredefinedExpr : public Expr {
+public:
+ enum IdentType {
+ Func,
+ Function,
+ LFunction, // Same as Function, but as wide string.
+ FuncDName,
+ FuncSig,
+ PrettyFunction,
+ /// \brief The same as PrettyFunction, except that the
+ /// 'virtual' keyword is omitted for virtual member functions.
+ PrettyFunctionNoVirtual
+ };
+
+private:
+ SourceLocation Loc;
+ IdentType Type;
+ Stmt *FnName;
+
+public:
+ PredefinedExpr(SourceLocation L, QualType FNTy, IdentType IT,
+ StringLiteral *SL);
+
+ /// \brief Construct an empty predefined expression.
+ explicit PredefinedExpr(EmptyShell Empty)
+ : Expr(PredefinedExprClass, Empty), Loc(), Type(Func), FnName(nullptr) {}
+
+ IdentType getIdentType() const { return Type; }
+
+ SourceLocation getLocation() const { return Loc; }
+ void setLocation(SourceLocation L) { Loc = L; }
+
+ StringLiteral *getFunctionName();
+ const StringLiteral *getFunctionName() const {
+ return const_cast<PredefinedExpr *>(this)->getFunctionName();
+ }
+
+ static StringRef getIdentTypeName(IdentType IT);
+ static std::string ComputeName(IdentType IT, const Decl *CurrentDecl);
+
+ SourceLocation getLocStart() const LLVM_READONLY { return Loc; }
+ SourceLocation getLocEnd() const LLVM_READONLY { return Loc; }
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == PredefinedExprClass;
+ }
+
+ // Iterators
+ child_range children() { return child_range(&FnName, &FnName + 1); }
+
+ friend class ASTStmtReader;
+};
+
+/// \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 {
+ union {
+ uint64_t VAL; ///< Used to store the <= 64 bits integer value.
+ uint64_t *pVal; ///< Used to store the >64 bits integer value.
+ };
+ unsigned BitWidth;
+
+ bool hasAllocation() const { return llvm::APInt::getNumWords(BitWidth) > 1; }
+
+ APNumericStorage(const APNumericStorage &) = delete;
+ void operator=(const APNumericStorage &) = delete;
+
+protected:
+ APNumericStorage() : VAL(0), BitWidth(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(const ASTContext &C, const llvm::APInt &Val);
+};
+
+class APIntStorage : private APNumericStorage {
+public:
+ llvm::APInt getValue() const { return getIntValue(); }
+ void setValue(const ASTContext &C, const llvm::APInt &Val) {
+ setIntValue(C, Val);
+ }
+};
+
+class APFloatStorage : private APNumericStorage {
+public:
+ llvm::APFloat getValue(const llvm::fltSemantics &Semantics) const {
+ return llvm::APFloat(Semantics, getIntValue());
+ }
+ void setValue(const ASTContext &C, const llvm::APFloat &Val) {
+ setIntValue(C, Val.bitcastToAPInt());
+ }
+};
+
+class IntegerLiteral : public Expr, public APIntStorage {
+ SourceLocation Loc;
+
+ /// \brief Construct an empty integer literal.
+ explicit IntegerLiteral(EmptyShell Empty)
+ : Expr(IntegerLiteralClass, Empty) { }
+
+public:
+ // type should be IntTy, LongTy, LongLongTy, UnsignedIntTy, UnsignedLongTy,
+ // or UnsignedLongLongTy
+ IntegerLiteral(const ASTContext &C, const llvm::APInt &V, QualType type,
+ SourceLocation l);
+
+ /// \brief Returns a new integer literal with value 'V' and type 'type'.
+ /// \param type - either IntTy, LongTy, LongLongTy, UnsignedIntTy,
+ /// UnsignedLongTy, or UnsignedLongLongTy which should match the size of V
+ /// \param V - the value that the returned integer literal contains.
+ static IntegerLiteral *Create(const ASTContext &C, const llvm::APInt &V,
+ QualType type, SourceLocation l);
+ /// \brief Returns a new empty integer literal.
+ static IntegerLiteral *Create(const ASTContext &C, EmptyShell Empty);
+
+ SourceLocation getLocStart() const LLVM_READONLY { return Loc; }
+ SourceLocation getLocEnd() const LLVM_READONLY { return Loc; }
+
+ /// \brief Retrieve the location of the literal.
+ SourceLocation getLocation() const { return Loc; }
+
+ void setLocation(SourceLocation Location) { Loc = Location; }
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == IntegerLiteralClass;
+ }
+
+ // Iterators
+ child_range children() {
+ return child_range(child_iterator(), child_iterator());
+ }
+};
+
+class CharacterLiteral : public Expr {
+public:
+ enum CharacterKind {
+ Ascii,
+ Wide,
+ UTF16,
+ UTF32
+ };
+
+private:
+ unsigned Value;
+ SourceLocation Loc;
+public:
+ // type should be IntTy
+ CharacterLiteral(unsigned value, CharacterKind kind, QualType type,
+ SourceLocation l)
+ : Expr(CharacterLiteralClass, type, VK_RValue, OK_Ordinary, false, false,
+ false, false),
+ Value(value), Loc(l) {
+ CharacterLiteralBits.Kind = kind;
+ }
+
+ /// \brief Construct an empty character literal.
+ CharacterLiteral(EmptyShell Empty) : Expr(CharacterLiteralClass, Empty) { }
+
+ SourceLocation getLocation() const { return Loc; }
+ CharacterKind getKind() const {
+ return static_cast<CharacterKind>(CharacterLiteralBits.Kind);
+ }
+
+ SourceLocation getLocStart() const LLVM_READONLY { return Loc; }
+ SourceLocation getLocEnd() const LLVM_READONLY { return Loc; }
+
+ unsigned getValue() const { return Value; }
+
+ void setLocation(SourceLocation Location) { Loc = Location; }
+ void setKind(CharacterKind kind) { CharacterLiteralBits.Kind = kind; }
+ void setValue(unsigned Val) { Value = Val; }
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == CharacterLiteralClass;
+ }
+
+ // Iterators
+ child_range children() {
+ return child_range(child_iterator(), child_iterator());
+ }
+};
+
+class FloatingLiteral : public Expr, private APFloatStorage {
+ SourceLocation Loc;
+
+ FloatingLiteral(const ASTContext &C, const llvm::APFloat &V, bool isexact,
+ QualType Type, SourceLocation L);
+
+ /// \brief Construct an empty floating-point literal.
+ explicit FloatingLiteral(const ASTContext &C, EmptyShell Empty);
+
+public:
+ static FloatingLiteral *Create(const ASTContext &C, const llvm::APFloat &V,
+ bool isexact, QualType Type, SourceLocation L);
+ static FloatingLiteral *Create(const ASTContext &C, EmptyShell Empty);
+
+ llvm::APFloat getValue() const {
+ return APFloatStorage::getValue(getSemantics());
+ }
+ void setValue(const ASTContext &C, const llvm::APFloat &Val) {
+ assert(&getSemantics() == &Val.getSemantics() && "Inconsistent semantics");
+ APFloatStorage::setValue(C, Val);
+ }
+
+ /// Get a raw enumeration value representing the floating-point semantics of
+ /// this literal (32-bit IEEE, x87, ...), suitable for serialisation.
+ APFloatSemantics getRawSemantics() const {
+ return static_cast<APFloatSemantics>(FloatingLiteralBits.Semantics);
+ }
+
+ /// Set the raw enumeration value representing the floating-point semantics of
+ /// this literal (32-bit IEEE, x87, ...), suitable for serialisation.
+ void setRawSemantics(APFloatSemantics Sem) {
+ FloatingLiteralBits.Semantics = Sem;
+ }
+
+ /// Return the APFloat semantics this literal uses.
+ const llvm::fltSemantics &getSemantics() const;
+
+ /// Set the APFloat semantics this literal uses.
+ void setSemantics(const llvm::fltSemantics &Sem);
+
+ bool isExact() const { return FloatingLiteralBits.IsExact; }
+ void setExact(bool E) { FloatingLiteralBits.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; }
+
+ SourceLocation getLocStart() const LLVM_READONLY { return Loc; }
+ SourceLocation getLocEnd() const LLVM_READONLY { return Loc; }
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == FloatingLiteralClass;
+ }
+
+ // Iterators
+ child_range children() {
+ return child_range(child_iterator(), child_iterator());
+ }
+};
+
+/// 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, 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; }
+
+ SourceLocation getLocStart() const LLVM_READONLY { return Val->getLocStart(); }
+ SourceLocation getLocEnd() const LLVM_READONLY { return Val->getLocEnd(); }
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == ImaginaryLiteralClass;
+ }
+
+ // 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 getBytes()
+/// 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 {
+public:
+ enum StringKind {
+ Ascii,
+ Wide,
+ UTF8,
+ UTF16,
+ UTF32
+ };
+
+private:
+ friend class ASTStmtReader;
+
+ union {
+ const char *asChar;
+ const uint16_t *asUInt16;
+ const uint32_t *asUInt32;
+ } StrData;
+ unsigned Length;
+ unsigned CharByteWidth : 4;
+ unsigned Kind : 3;
+ unsigned IsPascal : 1;
+ unsigned NumConcatenated;
+ SourceLocation TokLocs[1];
+
+ StringLiteral(QualType Ty) :
+ Expr(StringLiteralClass, Ty, VK_LValue, OK_Ordinary, false, false, false,
+ false) {}
+
+ static int mapCharByteWidth(TargetInfo const &target,StringKind k);
+
+public:
+ /// This is the "fully general" constructor that allows representation of
+ /// strings formed from multiple concatenated tokens.
+ static StringLiteral *Create(const ASTContext &C, StringRef Str,
+ StringKind Kind, bool Pascal, QualType Ty,
+ const SourceLocation *Loc, unsigned NumStrs);
+
+ /// Simple constructor for string literals made from one token.
+ static StringLiteral *Create(const ASTContext &C, StringRef Str,
+ StringKind Kind, bool Pascal, QualType Ty,
+ SourceLocation Loc) {
+ return Create(C, Str, Kind, Pascal, Ty, &Loc, 1);
+ }
+
+ /// \brief Construct an empty string literal.
+ static StringLiteral *CreateEmpty(const ASTContext &C, unsigned NumStrs);
+
+ StringRef getString() const {
+ assert(CharByteWidth==1
+ && "This function is used in places that assume strings use char");
+ return StringRef(StrData.asChar, getByteLength());
+ }
+
+ /// Allow access to clients that need the byte representation, such as
+ /// ASTWriterStmt::VisitStringLiteral().
+ StringRef getBytes() const {
+ // FIXME: StringRef may not be the right type to use as a result for this.
+ if (CharByteWidth == 1)
+ return StringRef(StrData.asChar, getByteLength());
+ if (CharByteWidth == 4)
+ return StringRef(reinterpret_cast<const char*>(StrData.asUInt32),
+ getByteLength());
+ assert(CharByteWidth == 2 && "unsupported CharByteWidth");
+ return StringRef(reinterpret_cast<const char*>(StrData.asUInt16),
+ getByteLength());
+ }
+
+ void outputString(raw_ostream &OS) const;
+
+ uint32_t getCodeUnit(size_t i) const {
+ assert(i < Length && "out of bounds access");
+ if (CharByteWidth == 1)
+ return static_cast<unsigned char>(StrData.asChar[i]);
+ if (CharByteWidth == 4)
+ return StrData.asUInt32[i];
+ assert(CharByteWidth == 2 && "unsupported CharByteWidth");
+ return StrData.asUInt16[i];
+ }
+
+ unsigned getByteLength() const { return CharByteWidth*Length; }
+ unsigned getLength() const { return Length; }
+ unsigned getCharByteWidth() const { return CharByteWidth; }
+
+ /// \brief Sets the string data to the given string data.
+ void setString(const ASTContext &C, StringRef Str,
+ StringKind Kind, bool IsPascal);
+
+ StringKind getKind() const { return static_cast<StringKind>(Kind); }
+
+
+ bool isAscii() const { return Kind == Ascii; }
+ bool isWide() const { return Kind == Wide; }
+ bool isUTF8() const { return Kind == UTF8; }
+ bool isUTF16() const { return Kind == UTF16; }
+ bool isUTF32() const { return Kind == UTF32; }
+ bool isPascal() const { return IsPascal; }
+
+ bool containsNonAsciiOrNull() const {
+ 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,
+ unsigned *StartToken = nullptr,
+ unsigned *StartTokenByteOffset = nullptr) const;
+
+ typedef const SourceLocation *tokloc_iterator;
+ tokloc_iterator tokloc_begin() const { return TokLocs; }
+ tokloc_iterator tokloc_end() const { return TokLocs + NumConcatenated; }
+
+ SourceLocation getLocStart() const LLVM_READONLY { return TokLocs[0]; }
+ SourceLocation getLocEnd() const LLVM_READONLY {
+ return TokLocs[NumConcatenated - 1];
+ }
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == StringLiteralClass;
+ }
+
+ // Iterators
+ child_range children() {
+ return child_range(child_iterator(), child_iterator());
+ }
+};
+
+/// 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->isInstantiationDependent(),
+ 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; }
+
+ SourceLocation getLocStart() const LLVM_READONLY { return L; }
+ SourceLocation getLocEnd() const LLVM_READONLY { return 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;
+ }
+
+ // 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->isInstantiationDependent() ||
+ type->isInstantiationDependentType()),
+ 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()); }
+
+ static bool isIncrementOp(Opcode Op) {
+ return Op == UO_PreInc || Op == UO_PostInc;
+ }
+ bool isIncrementOp() const {
+ return isIncrementOp(getOpcode());
+ }
+
+ static bool isDecrementOp(Opcode Op) {
+ return Op == UO_PreDec || Op == UO_PostDec;
+ }
+ bool isDecrementOp() const {
+ return isDecrementOp(getOpcode());
+ }
+
+ static bool isIncrementDecrementOp(Opcode Op) { return Op <= UO_PreDec; }
+ bool isIncrementDecrementOp() const {
+ return isIncrementDecrementOp(getOpcode());
+ }
+
+ 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 StringRef 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);
+
+ SourceLocation getLocStart() const LLVM_READONLY {
+ return isPostfix() ? Val->getLocStart() : Loc;
+ }
+ SourceLocation getLocEnd() const LLVM_READONLY {
+ return isPostfix() ? Loc : Val->getLocEnd();
+ }
+ SourceLocation getExprLoc() const LLVM_READONLY { return Loc; }
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == UnaryOperatorClass;
+ }
+
+ // Iterators
+ child_range children() { return child_range(&Val, &Val+1); }
+};
+
+/// Helper class for OffsetOfExpr.
+
+// __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 getSourceRange() const LLVM_READONLY { return Range; }
+ SourceLocation getLocStart() const LLVM_READONLY { return Range.getBegin(); }
+ SourceLocation getLocEnd() const LLVM_READONLY { return Range.getEnd(); }
+};
+
+/// 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 final
+ : public Expr,
+ private llvm::TrailingObjects<OffsetOfExpr, OffsetOfNode, Expr *> {
+ 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;
+
+ size_t numTrailingObjects(OverloadToken<OffsetOfNode>) const {
+ return NumComps;
+ }
+
+ OffsetOfExpr(const ASTContext &C, QualType type,
+ SourceLocation OperatorLoc, TypeSourceInfo *tsi,
+ ArrayRef<OffsetOfNode> comps, ArrayRef<Expr*> exprs,
+ SourceLocation RParenLoc);
+
+ explicit OffsetOfExpr(unsigned numComps, unsigned numExprs)
+ : Expr(OffsetOfExprClass, EmptyShell()),
+ TSInfo(nullptr), NumComps(numComps), NumExprs(numExprs) {}
+
+public:
+
+ static OffsetOfExpr *Create(const ASTContext &C, QualType type,
+ SourceLocation OperatorLoc, TypeSourceInfo *tsi,
+ ArrayRef<OffsetOfNode> comps,
+ ArrayRef<Expr*> exprs, SourceLocation RParenLoc);
+
+ static OffsetOfExpr *CreateEmpty(const 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) const {
+ assert(Idx < NumComps && "Subscript out of range");
+ return getTrailingObjects<OffsetOfNode>()[Idx];
+ }
+
+ void setComponent(unsigned Idx, OffsetOfNode ON) {
+ assert(Idx < NumComps && "Subscript out of range");
+ getTrailingObjects<OffsetOfNode>()[Idx] = ON;
+ }
+
+ unsigned getNumComponents() const {
+ return NumComps;
+ }
+
+ Expr* getIndexExpr(unsigned Idx) {
+ assert(Idx < NumExprs && "Subscript out of range");
+ return getTrailingObjects<Expr *>()[Idx];
+ }
+
+ const Expr *getIndexExpr(unsigned Idx) const {
+ assert(Idx < NumExprs && "Subscript out of range");
+ return getTrailingObjects<Expr *>()[Idx];
+ }
+
+ void setIndexExpr(unsigned Idx, Expr* E) {
+ assert(Idx < NumComps && "Subscript out of range");
+ getTrailingObjects<Expr *>()[Idx] = E;
+ }
+
+ unsigned getNumExpressions() const {
+ return NumExprs;
+ }
+
+ SourceLocation getLocStart() const LLVM_READONLY { return OperatorLoc; }
+ SourceLocation getLocEnd() const LLVM_READONLY { return RParenLoc; }
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == OffsetOfExprClass;
+ }
+
+ // Iterators
+ child_range children() {
+ Stmt **begin = reinterpret_cast<Stmt **>(getTrailingObjects<Expr *>());
+ return child_range(begin, begin + NumExprs);
+ }
+ friend TrailingObjects;
+};
+
+/// UnaryExprOrTypeTraitExpr - expression with either a type or (unevaluated)
+/// expression operand. Used for sizeof/alignof (C99 6.5.3.4) and
+/// vec_step (OpenCL 1.1 6.11.12).
+class UnaryExprOrTypeTraitExpr : public Expr {
+ union {
+ TypeSourceInfo *Ty;
+ Stmt *Ex;
+ } Argument;
+ SourceLocation OpLoc, RParenLoc;
+
+public:
+ UnaryExprOrTypeTraitExpr(UnaryExprOrTypeTrait ExprKind, TypeSourceInfo *TInfo,
+ QualType resultType, SourceLocation op,
+ SourceLocation rp) :
+ Expr(UnaryExprOrTypeTraitExprClass, 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()->isInstantiationDependentType(),
+ TInfo->getType()->containsUnexpandedParameterPack()),
+ OpLoc(op), RParenLoc(rp) {
+ UnaryExprOrTypeTraitExprBits.Kind = ExprKind;
+ UnaryExprOrTypeTraitExprBits.IsType = true;
+ Argument.Ty = TInfo;
+ }
+
+ UnaryExprOrTypeTraitExpr(UnaryExprOrTypeTrait ExprKind, Expr *E,
+ QualType resultType, SourceLocation op,
+ SourceLocation rp);
+
+ /// \brief Construct an empty sizeof/alignof expression.
+ explicit UnaryExprOrTypeTraitExpr(EmptyShell Empty)
+ : Expr(UnaryExprOrTypeTraitExprClass, Empty) { }
+
+ UnaryExprOrTypeTrait getKind() const {
+ return static_cast<UnaryExprOrTypeTrait>(UnaryExprOrTypeTraitExprBits.Kind);
+ }
+ void setKind(UnaryExprOrTypeTrait K) { UnaryExprOrTypeTraitExprBits.Kind = K;}
+
+ bool isArgumentType() const { return UnaryExprOrTypeTraitExprBits.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<UnaryExprOrTypeTraitExpr*>(this)->getArgumentExpr();
+ }
+
+ void setArgument(Expr *E) {
+ Argument.Ex = E;
+ UnaryExprOrTypeTraitExprBits.IsType = false;
+ }
+ void setArgument(TypeSourceInfo *TInfo) {
+ Argument.Ty = TInfo;
+ UnaryExprOrTypeTraitExprBits.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; }
+
+ SourceLocation getLocStart() const LLVM_READONLY { return OpLoc; }
+ SourceLocation getLocEnd() const LLVM_READONLY { return RParenLoc; }
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == UnaryExprOrTypeTraitExprClass;
+ }
+
+ // 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->isInstantiationDependent() ||
+ rhs->isInstantiationDependent()),
+ (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());
+ }
+
+ SourceLocation getLocStart() const LLVM_READONLY {
+ return getLHS()->getLocStart();
+ }
+ SourceLocation getLocEnd() const LLVM_READONLY { return RBracketLoc; }
+
+ SourceLocation getRBracketLoc() const { return RBracketLoc; }
+ void setRBracketLoc(SourceLocation L) { RBracketLoc = L; }
+
+ SourceLocation getExprLoc() const LLVM_READONLY {
+ return getBase()->getExprLoc();
+ }
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == ArraySubscriptExprClass;
+ }
+
+ // 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(const ASTContext& C, StmtClass SC, Expr *fn, unsigned NumPreArgs,
+ ArrayRef<Expr*> args, QualType t, ExprValueKind VK,
+ SourceLocation rparenloc);
+ CallExpr(const 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(const ASTContext& C, Expr *fn, ArrayRef<Expr*> args, QualType t,
+ ExprValueKind VK, SourceLocation rparenloc);
+
+ /// \brief Build an empty call expression.
+ CallExpr(const 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);
+ }
+ const Expr *const *getArgs() const {
+ 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_or_null<Expr>(SubExprs[Arg + getNumPreArgs() + PREARGS_START]);
+ }
+ const Expr *getArg(unsigned Arg) const {
+ assert(Arg < NumArgs && "Arg access out of range!");
+ return cast_or_null<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(const ASTContext& C, unsigned NumArgs);
+
+ typedef ExprIterator arg_iterator;
+ typedef ConstExprIterator const_arg_iterator;
+ typedef llvm::iterator_range<arg_iterator> arg_range;
+ typedef llvm::iterator_range<const_arg_iterator> arg_const_range;
+
+ arg_range arguments() { return arg_range(arg_begin(), arg_end()); }
+ arg_const_range arguments() const {
+ return arg_const_range(arg_begin(), arg_end());
+ }
+
+ 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();
+ }
+
+ /// This method provides fast access to all the subexpressions of
+ /// a CallExpr without going through the slower virtual child_iterator
+ /// interface. This provides efficient reverse iteration of the
+ /// subexpressions. This is currently used for CFG construction.
+ ArrayRef<Stmt*> getRawSubExprs() {
+ return llvm::makeArrayRef(SubExprs,
+ getNumPreArgs() + PREARGS_START + getNumArgs());
+ }
+
+ /// getNumCommas - Return the number of commas that must have been present in
+ /// this function call.
+ unsigned getNumCommas() const { return NumArgs ? NumArgs - 1 : 0; }
+
+ /// getBuiltinCallee - If this is a call to a builtin, return the builtin ID
+ /// of the callee. If not, return 0.
+ unsigned getBuiltinCallee() const;
+
+ /// \brief Returns \c true if this is a call to a builtin which does not
+ /// evaluate side-effects within its arguments.
+ bool isUnevaluatedBuiltinCall(const ASTContext &Ctx) 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 ASTContext &Ctx) const;
+
+ SourceLocation getRParenLoc() const { return RParenLoc; }
+ void setRParenLoc(SourceLocation L) { RParenLoc = L; }
+
+ SourceLocation getLocStart() const LLVM_READONLY;
+ SourceLocation getLocEnd() const LLVM_READONLY;
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() >= firstCallExprConstant &&
+ T->getStmtClass() <= lastCallExprConstant;
+ }
+
+ // Iterators
+ child_range children() {
+ return child_range(&SubExprs[0],
+ &SubExprs[0]+NumArgs+getNumPreArgs()+PREARGS_START);
+ }
+};
+
+/// Extra data stored in some MemberExpr objects.
+struct MemberExprNameQualifier {
+ /// \brief The nested-name-specifier that qualifies the name, including
+ /// source-location information.
+ NestedNameSpecifierLoc QualifierLoc;
+
+ /// \brief The DeclAccessPair through which the MemberDecl was found due to
+ /// name qualifiers.
+ DeclAccessPair FoundDecl;
+};
+
+/// MemberExpr - [C99 6.5.2.3] Structure and Union Members. X->F and X.F.
+///
+class MemberExpr final
+ : public Expr,
+ private llvm::TrailingObjects<MemberExpr, MemberExprNameQualifier,
+ ASTTemplateKWAndArgsInfo,
+ TemplateArgumentLoc> {
+ /// 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;
+
+ /// MemberDNLoc - Provides source/type location info for the
+ /// declaration name embedded in MemberDecl.
+ DeclarationNameLoc MemberDNLoc;
+
+ /// MemberLoc - This is the location of the member name.
+ SourceLocation MemberLoc;
+
+ /// This is the location of the -> or . in the expression.
+ SourceLocation OperatorLoc;
+
+ /// 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 MemberExprNameQualifier
+ /// structure is allocated immediately after the MemberExpr.
+ bool HasQualifierOrFoundDecl : 1;
+
+ /// \brief True if this member expression specified a template keyword
+ /// and/or a template argument list explicitly, e.g., x->f<int>,
+ /// x->template f, x->template f<int>.
+ /// When true, an ASTTemplateKWAndArgsInfo structure and its
+ /// TemplateArguments (if any) are present.
+ bool HasTemplateKWAndArgsInfo : 1;
+
+ /// \brief True if this member expression refers to a method that
+ /// was resolved from an overloaded set having size greater than 1.
+ bool HadMultipleCandidates : 1;
+
+ size_t numTrailingObjects(OverloadToken<MemberExprNameQualifier>) const {
+ return HasQualifierOrFoundDecl ? 1 : 0;
+ }
+
+ size_t numTrailingObjects(OverloadToken<ASTTemplateKWAndArgsInfo>) const {
+ return HasTemplateKWAndArgsInfo ? 1 : 0;
+ }
+
+public:
+ MemberExpr(Expr *base, bool isarrow, SourceLocation operatorloc,
+ ValueDecl *memberdecl, const DeclarationNameInfo &NameInfo,
+ QualType ty, ExprValueKind VK, ExprObjectKind OK)
+ : Expr(MemberExprClass, ty, VK, OK, base->isTypeDependent(),
+ base->isValueDependent(), base->isInstantiationDependent(),
+ base->containsUnexpandedParameterPack()),
+ Base(base), MemberDecl(memberdecl), MemberDNLoc(NameInfo.getInfo()),
+ MemberLoc(NameInfo.getLoc()), OperatorLoc(operatorloc),
+ IsArrow(isarrow), HasQualifierOrFoundDecl(false),
+ HasTemplateKWAndArgsInfo(false), HadMultipleCandidates(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 operators).
+ MemberExpr(Expr *base, bool isarrow, SourceLocation operatorloc,
+ ValueDecl *memberdecl, SourceLocation l, QualType ty,
+ ExprValueKind VK, ExprObjectKind OK)
+ : Expr(MemberExprClass, ty, VK, OK, base->isTypeDependent(),
+ base->isValueDependent(), base->isInstantiationDependent(),
+ base->containsUnexpandedParameterPack()),
+ Base(base), MemberDecl(memberdecl), MemberDNLoc(), MemberLoc(l),
+ OperatorLoc(operatorloc), IsArrow(isarrow),
+ HasQualifierOrFoundDecl(false), HasTemplateKWAndArgsInfo(false),
+ HadMultipleCandidates(false) {}
+
+ static MemberExpr *Create(const ASTContext &C, Expr *base, bool isarrow,
+ SourceLocation OperatorLoc,
+ NestedNameSpecifierLoc QualifierLoc,
+ SourceLocation TemplateKWLoc, 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 getTrailingObjects<MemberExprNameQualifier>()->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() != nullptr; }
+
+ /// \brief If the member name was qualified, retrieves the
+ /// nested-name-specifier that precedes the member name, with source-location
+ /// information.
+ NestedNameSpecifierLoc getQualifierLoc() const {
+ if (!HasQualifierOrFoundDecl)
+ return NestedNameSpecifierLoc();
+
+ return getTrailingObjects<MemberExprNameQualifier>()->QualifierLoc;
+ }
+
+ /// \brief If the member name was qualified, retrieves the
+ /// nested-name-specifier that precedes the member name. Otherwise, returns
+ /// NULL.
+ NestedNameSpecifier *getQualifier() const {
+ return getQualifierLoc().getNestedNameSpecifier();
+ }
+
+ /// \brief Retrieve the location of the template keyword preceding
+ /// the member name, if any.
+ SourceLocation getTemplateKeywordLoc() const {
+ if (!HasTemplateKWAndArgsInfo) return SourceLocation();
+ return getTrailingObjects<ASTTemplateKWAndArgsInfo>()->TemplateKWLoc;
+ }
+
+ /// \brief Retrieve the location of the left angle bracket starting the
+ /// explicit template argument list following the member name, if any.
+ SourceLocation getLAngleLoc() const {
+ if (!HasTemplateKWAndArgsInfo) return SourceLocation();
+ return getTrailingObjects<ASTTemplateKWAndArgsInfo>()->LAngleLoc;
+ }
+
+ /// \brief Retrieve the location of the right angle bracket ending the
+ /// explicit template argument list following the member name, if any.
+ SourceLocation getRAngleLoc() const {
+ if (!HasTemplateKWAndArgsInfo) return SourceLocation();
+ return getTrailingObjects<ASTTemplateKWAndArgsInfo>()->RAngleLoc;
+ }
+
+ /// Determines whether the member name was preceded by the template keyword.
+ bool hasTemplateKeyword() const { return getTemplateKeywordLoc().isValid(); }
+
+ /// \brief Determines whether the member name was followed by an
+ /// explicit template argument list.
+ bool hasExplicitTemplateArgs() const { return getLAngleLoc().isValid(); }
+
+ /// \brief Copies the template arguments (if present) into the given
+ /// structure.
+ void copyTemplateArgumentsInto(TemplateArgumentListInfo &List) const {
+ if (hasExplicitTemplateArgs())
+ getTrailingObjects<ASTTemplateKWAndArgsInfo>()->copyInto(
+ getTrailingObjects<TemplateArgumentLoc>(), List);
+ }
+
+ /// \brief Retrieve the template arguments provided as part of this
+ /// template-id.
+ const TemplateArgumentLoc *getTemplateArgs() const {
+ if (!hasExplicitTemplateArgs())
+ return nullptr;
+
+ return getTrailingObjects<TemplateArgumentLoc>();
+ }
+
+ /// \brief Retrieve the number of template arguments provided as part of this
+ /// template-id.
+ unsigned getNumTemplateArgs() const {
+ if (!hasExplicitTemplateArgs())
+ return 0;
+
+ return getTrailingObjects<ASTTemplateKWAndArgsInfo>()->NumTemplateArgs;
+ }
+
+ /// \brief Retrieve the member declaration name info.
+ DeclarationNameInfo getMemberNameInfo() const {
+ return DeclarationNameInfo(MemberDecl->getDeclName(),
+ MemberLoc, MemberDNLoc);
+ }
+
+ SourceLocation getOperatorLoc() const LLVM_READONLY { return OperatorLoc; }
+
+ 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; }
+
+ SourceLocation getLocStart() const LLVM_READONLY;
+ SourceLocation getLocEnd() const LLVM_READONLY;
+
+ SourceLocation getExprLoc() const LLVM_READONLY { return MemberLoc; }
+
+ /// \brief Determine whether the base of this explicit is implicit.
+ bool isImplicitAccess() const {
+ return getBase() && getBase()->isImplicitCXXThis();
+ }
+
+ /// \brief Returns true if this member expression refers to a method that
+ /// was resolved from an overloaded set having size greater than 1.
+ bool hadMultipleCandidates() const {
+ return HadMultipleCandidates;
+ }
+ /// \brief Sets the flag telling whether this expression refers to
+ /// a method that was resolved from an overloaded set having size
+ /// greater than 1.
+ void setHadMultipleCandidates(bool V = true) {
+ HadMultipleCandidates = V;
+ }
+
+ /// \brief Returns true if virtual dispatch is performed.
+ /// If the member access is fully qualified, (i.e. X::f()), virtual
+ /// dispatching is not performed. In -fapple-kext mode qualified
+ /// calls to virtual method will still go through the vtable.
+ bool performsVirtualDispatch(const LangOptions &LO) const {
+ return LO.AppleKext || !hasQualifier();
+ }
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == MemberExprClass;
+ }
+
+ // Iterators
+ child_range children() { return child_range(&Base, &Base+1); }
+
+ friend TrailingObjects;
+ 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.
+ /// The int part of the pair stores whether this expr is file scope.
+ llvm::PointerIntPair<TypeSourceInfo *, 1, bool> TInfoAndScope;
+ Stmt *Init;
+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->isInstantiationDependent() ||
+ tinfo->getType()->isInstantiationDependentType()),
+ init->containsUnexpandedParameterPack()),
+ LParenLoc(lparenloc), TInfoAndScope(tinfo, fileScope), Init(init) {}
+
+ /// \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 TInfoAndScope.getInt(); }
+ void setFileScope(bool FS) { TInfoAndScope.setInt(FS); }
+
+ SourceLocation getLParenLoc() const { return LParenLoc; }
+ void setLParenLoc(SourceLocation L) { LParenLoc = L; }
+
+ TypeSourceInfo *getTypeSourceInfo() const {
+ return TInfoAndScope.getPointer();
+ }
+ void setTypeSourceInfo(TypeSourceInfo *tinfo) {
+ TInfoAndScope.setPointer(tinfo);
+ }
+
+ SourceLocation getLocStart() const LLVM_READONLY {
+ // FIXME: Init should never be null.
+ if (!Init)
+ return SourceLocation();
+ if (LParenLoc.isInvalid())
+ return Init->getLocStart();
+ return LParenLoc;
+ }
+ SourceLocation getLocEnd() const LLVM_READONLY {
+ // FIXME: Init should never be null.
+ if (!Init)
+ return SourceLocation();
+ return Init->getLocEnd();
+ }
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == CompoundLiteralExprClass;
+ }
+
+ // 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 {
+private:
+ Stmt *Op;
+
+ bool CastConsistency() const;
+
+ const CXXBaseSpecifier * const *path_buffer() const {
+ return const_cast<CastExpr*>(this)->path_buffer();
+ }
+ CXXBaseSpecifier **path_buffer();
+
+ void setBasePathSize(unsigned basePathSize) {
+ CastExprBits.BasePathSize = basePathSize;
+ assert(CastExprBits.BasePathSize == basePathSize &&
+ "basePathSize doesn't fit in bits of CastExprBits.BasePathSize!");
+ }
+
+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->isInstantiationDependentType() ||
+ (op && op->isInstantiationDependent())),
+ // An implicit cast expression doesn't (lexically) contain an
+ // unexpanded pack, even if its target type does.
+ ((SC != ImplicitCastExprClass &&
+ ty->containsUnexpandedParameterPack()) ||
+ (op && op->containsUnexpandedParameterPack()))),
+ Op(op) {
+ assert(kind != CK_Invalid && "creating cast with invalid cast kind");
+ CastExprBits.Kind = kind;
+ setBasePathSize(BasePathSize);
+ assert(CastConsistency());
+ }
+
+ /// \brief Construct an empty cast.
+ CastExpr(StmtClass SC, EmptyShell Empty, unsigned BasePathSize)
+ : Expr(SC, Empty) {
+ setBasePathSize(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(); }
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() >= firstCastExprConstant &&
+ T->getStmtClass() <= lastCastExprConstant;
+ }
+
+ // 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 final
+ : public CastExpr,
+ private llvm::TrailingObjects<ImplicitCastExpr, CXXBaseSpecifier *> {
+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(const ASTContext &Context, QualType T,
+ CastKind Kind, Expr *Operand,
+ const CXXCastPath *BasePath,
+ ExprValueKind Cat);
+
+ static ImplicitCastExpr *CreateEmpty(const ASTContext &Context,
+ unsigned PathSize);
+
+ SourceLocation getLocStart() const LLVM_READONLY {
+ return getSubExpr()->getLocStart();
+ }
+ SourceLocation getLocEnd() const LLVM_READONLY {
+ return getSubExpr()->getLocEnd();
+ }
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == ImplicitCastExprClass;
+ }
+
+ friend TrailingObjects;
+ friend class CastExpr;
+};
+
+inline Expr *Expr::IgnoreImpCasts() {
+ Expr *e = this;
+ while (ImplicitCastExpr *ice = dyn_cast<ImplicitCastExpr>(e))
+ e = ice->getSubExpr();
+ return e;
+}
+
+/// 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;
+ }
+};
+
+/// 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 final
+ : public ExplicitCastExpr,
+ private llvm::TrailingObjects<CStyleCastExpr, CXXBaseSpecifier *> {
+ 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(const ASTContext &Context, QualType T,
+ ExprValueKind VK, CastKind K,
+ Expr *Op, const CXXCastPath *BasePath,
+ TypeSourceInfo *WrittenTy, SourceLocation L,
+ SourceLocation R);
+
+ static CStyleCastExpr *CreateEmpty(const 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; }
+
+ SourceLocation getLocStart() const LLVM_READONLY { return LPLoc; }
+ SourceLocation getLocEnd() const LLVM_READONLY {
+ return getSubExpr()->getLocEnd();
+ }
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == CStyleCastExprClass;
+ }
+
+ friend TrailingObjects;
+ friend class CastExpr;
+};
+
+/// \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;
+
+ // Records the FP_CONTRACT pragma status at the point that this binary
+ // operator was parsed. This bit is only meaningful for operations on
+ // floating point types. For all other types it should default to
+ // false.
+ unsigned FPContractable : 1;
+ 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, bool fpContractable)
+ : Expr(BinaryOperatorClass, ResTy, VK, OK,
+ lhs->isTypeDependent() || rhs->isTypeDependent(),
+ lhs->isValueDependent() || rhs->isValueDependent(),
+ (lhs->isInstantiationDependent() ||
+ rhs->isInstantiationDependent()),
+ (lhs->containsUnexpandedParameterPack() ||
+ rhs->containsUnexpandedParameterPack())),
+ Opc(opc), FPContractable(fpContractable), OpLoc(opLoc) {
+ SubExprs[LHS] = lhs;
+ SubExprs[RHS] = rhs;
+ assert(!isCompoundAssignmentOp() &&
+ "Use CompoundAssignOperator for compound assignments");
+ }
+
+ /// \brief Construct an empty binary operator.
+ explicit BinaryOperator(EmptyShell Empty)
+ : Expr(BinaryOperatorClass, Empty), Opc(BO_Comma) { }
+
+ SourceLocation getExprLoc() const LLVM_READONLY { return OpLoc; }
+ 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; }
+
+ SourceLocation getLocStart() const LLVM_READONLY {
+ return getLHS()->getLocStart();
+ }
+ SourceLocation getLocEnd() const LLVM_READONLY {
+ return getRHS()->getLocEnd();
+ }
+
+ /// getOpcodeStr - Turn an Opcode enum value into the punctuation char it
+ /// corresponds to, e.g. "<<=".
+ static StringRef getOpcodeStr(Opcode Op);
+
+ StringRef 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; }
+ static bool isMultiplicativeOp(Opcode Opc) {
+ return Opc >= BO_Mul && Opc <= BO_Rem;
+ }
+ bool isMultiplicativeOp() const { return isMultiplicativeOp(getOpcode()); }
+ 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 Opcode negateComparisonOp(Opcode Opc) {
+ switch (Opc) {
+ default:
+ llvm_unreachable("Not a comparsion operator.");
+ 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 Opcode reverseComparisonOp(Opcode Opc) {
+ switch (Opc) {
+ default:
+ llvm_unreachable("Not a comparsion operator.");
+ 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 Opc;
+ }
+ }
+
+ 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 Opcode getOpForCompoundAssignment(Opcode Opc) {
+ assert(isCompoundAssignmentOp(Opc));
+ if (Opc >= BO_AndAssign)
+ return Opcode(unsigned(Opc) - BO_AndAssign + BO_And);
+ else
+ return Opcode(unsigned(Opc) - BO_MulAssign + BO_Mul);
+ }
+
+ 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;
+ }
+
+ // Iterators
+ child_range children() {
+ return child_range(&SubExprs[0], &SubExprs[0]+END_EXPR);
+ }
+
+ // Set the FP contractability status of this operator. Only meaningful for
+ // operations on floating point types.
+ void setFPContractable(bool FPC) { FPContractable = FPC; }
+
+ // Get the FP contractability status of this operator. Only meaningful for
+ // operations on floating point types.
+ bool isFPContractable() const { return FPContractable; }
+
+protected:
+ BinaryOperator(Expr *lhs, Expr *rhs, Opcode opc, QualType ResTy,
+ ExprValueKind VK, ExprObjectKind OK,
+ SourceLocation opLoc, bool fpContractable, bool dead2)
+ : Expr(CompoundAssignOperatorClass, ResTy, VK, OK,
+ lhs->isTypeDependent() || rhs->isTypeDependent(),
+ lhs->isValueDependent() || rhs->isValueDependent(),
+ (lhs->isInstantiationDependent() ||
+ rhs->isInstantiationDependent()),
+ (lhs->containsUnexpandedParameterPack() ||
+ rhs->containsUnexpandedParameterPack())),
+ Opc(opc), FPContractable(fpContractable), 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 arithmetic 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, bool fpContractable)
+ : BinaryOperator(lhs, rhs, opc, ResType, VK, OK, OpLoc, fpContractable,
+ 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 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 ID,
+ bool ContainsUnexpandedParameterPack,
+ SourceLocation qloc,
+ SourceLocation cloc)
+ : Expr(SC, T, VK, OK, TD, VD, ID, 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;
+ }
+};
+
+/// 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->isInstantiationDependent() ||
+ lhs->isInstantiationDependent() ||
+ rhs->isInstantiationDependent()),
+ (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]); }
+
+ SourceLocation getLocStart() const LLVM_READONLY {
+ return getCond()->getLocStart();
+ }
+ SourceLocation getLocEnd() const LLVM_READONLY {
+ return getRHS()->getLocEnd();
+ }
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == ConditionalOperatorClass;
+ }
+
+ // 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->isInstantiationDependent() ||
+ rhs->isInstantiationDependent()),
+ (common->containsUnexpandedParameterPack() ||
+ rhs->containsUnexpandedParameterPack()),
+ qloc, cloc),
+ OpaqueValue(opaqueValue) {
+ SubExprs[COMMON] = common;
+ SubExprs[COND] = cond;
+ SubExprs[LHS] = lhs;
+ SubExprs[RHS] = rhs;
+ assert(OpaqueValue->getSourceExpr() == common && "Wrong opaque value");
+ }
+
+ /// \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]);
+ }
+
+ SourceLocation getLocStart() const LLVM_READONLY {
+ return getCommon()->getLocStart();
+ }
+ SourceLocation getLocEnd() const LLVM_READONLY {
+ return getFalseExpr()->getLocEnd();
+ }
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == BinaryConditionalOperatorClass;
+ }
+
+ // 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,
+ 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; }
+
+ SourceLocation getLocStart() const LLVM_READONLY { return AmpAmpLoc; }
+ SourceLocation getLocEnd() const LLVM_READONLY { return LabelLoc; }
+
+ LabelDecl *getLabel() const { return Label; }
+ void setLabel(LabelDecl *L) { Label = L; }
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == AddrLabelExprClass;
+ }
+
+ // Iterators
+ child_range children() {
+ return child_range(child_iterator(), child_iterator());
+ }
+};
+
+/// 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?
+ // FIXME: Do we need to compute instantiation instantiation-dependence for
+ // statements? (ugh!)
+ StmtExpr(CompoundStmt *substmt, QualType T,
+ SourceLocation lp, SourceLocation rp) :
+ Expr(StmtExprClass, T, VK_RValue, OK_Ordinary,
+ T->isDependentType(), false, 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; }
+
+ SourceLocation getLocStart() const LLVM_READONLY { return LParenLoc; }
+ SourceLocation getLocEnd() const LLVM_READONLY { return 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;
+ }
+
+ // 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(const ASTContext &C, ArrayRef<Expr*> args, QualType Type,
+ SourceLocation BLoc, SourceLocation RP);
+
+ /// \brief Build an empty vector-shuffle expression.
+ explicit ShuffleVectorExpr(EmptyShell Empty)
+ : Expr(ShuffleVectorExprClass, Empty), SubExprs(nullptr) { }
+
+ SourceLocation getBuiltinLoc() const { return BuiltinLoc; }
+ void setBuiltinLoc(SourceLocation L) { BuiltinLoc = L; }
+
+ SourceLocation getRParenLoc() const { return RParenLoc; }
+ void setRParenLoc(SourceLocation L) { RParenLoc = L; }
+
+ SourceLocation getLocStart() const LLVM_READONLY { return BuiltinLoc; }
+ SourceLocation getLocEnd() const LLVM_READONLY { return RParenLoc; }
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == ShuffleVectorExprClass;
+ }
+
+ /// 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(const ASTContext &C, ArrayRef<Expr *> Exprs);
+
+ llvm::APSInt getShuffleMaskIdx(const ASTContext &Ctx, unsigned N) const {
+ assert((N < NumExprs - 2) && "Shuffle idx out of range!");
+ return getExpr(N+2)->EvaluateKnownConstInt(Ctx);
+ }
+
+ // Iterators
+ child_range children() {
+ return child_range(&SubExprs[0], &SubExprs[0]+NumExprs);
+ }
+};
+
+/// ConvertVectorExpr - Clang builtin function __builtin_convertvector
+/// This AST node provides support for converting a vector type to another
+/// vector type of the same arity.
+class ConvertVectorExpr : public Expr {
+private:
+ Stmt *SrcExpr;
+ TypeSourceInfo *TInfo;
+ SourceLocation BuiltinLoc, RParenLoc;
+
+ friend class ASTReader;
+ friend class ASTStmtReader;
+ explicit ConvertVectorExpr(EmptyShell Empty) : Expr(ConvertVectorExprClass, Empty) {}
+
+public:
+ ConvertVectorExpr(Expr* SrcExpr, TypeSourceInfo *TI, QualType DstType,
+ ExprValueKind VK, ExprObjectKind OK,
+ SourceLocation BuiltinLoc, SourceLocation RParenLoc)
+ : Expr(ConvertVectorExprClass, DstType, VK, OK,
+ DstType->isDependentType(),
+ DstType->isDependentType() || SrcExpr->isValueDependent(),
+ (DstType->isInstantiationDependentType() ||
+ SrcExpr->isInstantiationDependent()),
+ (DstType->containsUnexpandedParameterPack() ||
+ SrcExpr->containsUnexpandedParameterPack())),
+ SrcExpr(SrcExpr), TInfo(TI), BuiltinLoc(BuiltinLoc), RParenLoc(RParenLoc) {}
+
+ /// getSrcExpr - Return the Expr to be converted.
+ Expr *getSrcExpr() const { return cast<Expr>(SrcExpr); }
+
+ /// getTypeSourceInfo - Return the destination type.
+ TypeSourceInfo *getTypeSourceInfo() const {
+ return TInfo;
+ }
+ void setTypeSourceInfo(TypeSourceInfo *ti) {
+ TInfo = ti;
+ }
+
+ /// getBuiltinLoc - Return the location of the __builtin_convertvector token.
+ SourceLocation getBuiltinLoc() const { return BuiltinLoc; }
+
+ /// getRParenLoc - Return the location of final right parenthesis.
+ SourceLocation getRParenLoc() const { return RParenLoc; }
+
+ SourceLocation getLocStart() const LLVM_READONLY { return BuiltinLoc; }
+ SourceLocation getLocEnd() const LLVM_READONLY { return RParenLoc; }
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == ConvertVectorExprClass;
+ }
+
+ // Iterators
+ child_range children() { return child_range(&SrcExpr, &SrcExpr+1); }
+};
+
+/// 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;
+ bool CondIsTrue;
+public:
+ ChooseExpr(SourceLocation BLoc, Expr *cond, Expr *lhs, Expr *rhs,
+ QualType t, ExprValueKind VK, ExprObjectKind OK,
+ SourceLocation RP, bool condIsTrue,
+ bool TypeDependent, bool ValueDependent)
+ : Expr(ChooseExprClass, t, VK, OK, TypeDependent, ValueDependent,
+ (cond->isInstantiationDependent() ||
+ lhs->isInstantiationDependent() ||
+ rhs->isInstantiationDependent()),
+ (cond->containsUnexpandedParameterPack() ||
+ lhs->containsUnexpandedParameterPack() ||
+ rhs->containsUnexpandedParameterPack())),
+ BuiltinLoc(BLoc), RParenLoc(RP), CondIsTrue(condIsTrue) {
+ 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 {
+ assert(!isConditionDependent() &&
+ "Dependent condition isn't true or false");
+ return CondIsTrue;
+ }
+ void setIsConditionTrue(bool isTrue) { CondIsTrue = isTrue; }
+
+ bool isConditionDependent() const {
+ return getCond()->isTypeDependent() || getCond()->isValueDependent();
+ }
+
+ /// getChosenSubExpr - Return the subexpression chosen according to the
+ /// condition.
+ Expr *getChosenSubExpr() const {
+ return isConditionTrue() ? 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; }
+
+ SourceLocation getLocStart() const LLVM_READONLY { return BuiltinLoc; }
+ SourceLocation getLocEnd() const LLVM_READONLY { return RParenLoc; }
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == ChooseExprClass;
+ }
+
+ // 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,
+ 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; }
+
+ SourceLocation getLocStart() const LLVM_READONLY { return TokenLoc; }
+ SourceLocation getLocEnd() const LLVM_READONLY { return TokenLoc; }
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == GNUNullExprClass;
+ }
+
+ // Iterators
+ child_range children() {
+ return child_range(child_iterator(), child_iterator());
+ }
+};
+
+/// Represents a call to the builtin function \c __builtin_va_arg.
+class VAArgExpr : public Expr {
+ Stmt *Val;
+ llvm::PointerIntPair<TypeSourceInfo *, 1, bool> TInfo;
+ SourceLocation BuiltinLoc, RParenLoc;
+public:
+ VAArgExpr(SourceLocation BLoc, Expr *e, TypeSourceInfo *TInfo,
+ SourceLocation RPLoc, QualType t, bool IsMS)
+ : Expr(VAArgExprClass, t, VK_RValue, OK_Ordinary, t->isDependentType(),
+ false, (TInfo->getType()->isInstantiationDependentType() ||
+ e->isInstantiationDependent()),
+ (TInfo->getType()->containsUnexpandedParameterPack() ||
+ e->containsUnexpandedParameterPack())),
+ Val(e), TInfo(TInfo, IsMS), BuiltinLoc(BLoc), RParenLoc(RPLoc) {}
+
+ /// Create an empty __builtin_va_arg expression.
+ explicit VAArgExpr(EmptyShell Empty)
+ : Expr(VAArgExprClass, Empty), Val(nullptr), TInfo(nullptr, false) {}
+
+ const Expr *getSubExpr() const { return cast<Expr>(Val); }
+ Expr *getSubExpr() { return cast<Expr>(Val); }
+ void setSubExpr(Expr *E) { Val = E; }
+
+ /// Returns whether this is really a Win64 ABI va_arg expression.
+ bool isMicrosoftABI() const { return TInfo.getInt(); }
+ void setIsMicrosoftABI(bool IsMS) { TInfo.setInt(IsMS); }
+
+ TypeSourceInfo *getWrittenTypeInfo() const { return TInfo.getPointer(); }
+ void setWrittenTypeInfo(TypeSourceInfo *TI) { TInfo.setPointer(TI); }
+
+ SourceLocation getBuiltinLoc() const { return BuiltinLoc; }
+ void setBuiltinLoc(SourceLocation L) { BuiltinLoc = L; }
+
+ SourceLocation getRParenLoc() const { return RParenLoc; }
+ void setRParenLoc(SourceLocation L) { RParenLoc = L; }
+
+ SourceLocation getLocStart() const LLVM_READONLY { return BuiltinLoc; }
+ SourceLocation getLocEnd() const LLVM_READONLY { return RParenLoc; }
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == VAArgExprClass;
+ }
+
+ // 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.
+///
+/// After semantic analysis has completed, given an initializer list,
+/// method isSemanticForm() returns true if and only if this is the
+/// semantic form of the initializer list (note: the same AST node
+/// may at the same time be the syntactic form).
+/// Given the semantic form of the initializer list, one can retrieve
+/// the syntactic form of that initializer list (when different)
+/// using method getSyntacticForm(); the method returns null if applied
+/// to a initializer list which is already in syntactic form.
+/// Similarly, given the syntactic form (i.e., an initializer list such
+/// that isSemanticForm() returns false), one can retrieve the semantic
+/// form using method getSemanticForm().
+/// Since many initializer lists have the same syntactic and semantic forms,
+/// getSyntacticForm() may return NULL, indicating that the current
+/// semantic 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;
+
+ /// The alternative form of the initializer list (if it exists).
+ /// The int part of the pair stores whether this initializer list is
+ /// in semantic form. If not null, the pointer points to:
+ /// - the syntactic form, if this is in semantic form;
+ /// - the semantic form, if this is in syntactic form.
+ llvm::PointerIntPair<InitListExpr *, 1, bool> AltForm;
+
+ /// \brief Either:
+ /// If this initializer list initializes an array with more elements than
+ /// there are initializers in the list, specifies an expression to be used
+ /// for value initialization of the rest of the elements.
+ /// Or
+ /// If this initializer list initializes a union, specifies which
+ /// field within the union will be initialized.
+ llvm::PointerUnion<Expr *, FieldDecl *> ArrayFillerOrUnionFieldInit;
+
+public:
+ InitListExpr(const ASTContext &C, SourceLocation lbraceloc,
+ ArrayRef<Expr*> initExprs, SourceLocation rbraceloc);
+
+ /// \brief Build an empty initializer list.
+ explicit InitListExpr(EmptyShell Empty)
+ : Expr(InitListExprClass, Empty) { }
+
+ unsigned getNumInits() const { return InitExprs.size(); }
+
+ /// \brief Retrieve the set of initializers.
+ Expr **getInits() { return reinterpret_cast<Expr **>(InitExprs.data()); }
+
+ ArrayRef<Expr *> inits() {
+ return llvm::makeArrayRef(getInits(), getNumInits());
+ }
+
+ 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;
+
+ if (expr) {
+ ExprBits.TypeDependent |= expr->isTypeDependent();
+ ExprBits.ValueDependent |= expr->isValueDependent();
+ ExprBits.InstantiationDependent |= expr->isInstantiationDependent();
+ ExprBits.ContainsUnexpandedParameterPack |=
+ expr->containsUnexpandedParameterPack();
+ }
+ }
+
+ /// \brief Reserve space for some number of initializers.
+ void reserveInits(const 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(const 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
+ /// accommodate the new entry.
+ Expr *updateInit(const ASTContext &C, unsigned Init, Expr *expr);
+
+ /// \brief If this initializer list initializes an array with more elements
+ /// than there are initializers in the list, specifies an expression to be
+ /// used for value initialization of the rest of the elements.
+ Expr *getArrayFiller() {
+ return ArrayFillerOrUnionFieldInit.dyn_cast<Expr *>();
+ }
+ const Expr *getArrayFiller() const {
+ return const_cast<InitListExpr *>(this)->getArrayFiller();
+ }
+ void setArrayFiller(Expr *filler);
+
+ /// \brief Return true if this is an array initializer and its array "filler"
+ /// has been set.
+ bool hasArrayFiller() const { return getArrayFiller(); }
+
+ /// \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 ArrayFillerOrUnionFieldInit.dyn_cast<FieldDecl *>();
+ }
+ const FieldDecl *getInitializedFieldInUnion() const {
+ return const_cast<InitListExpr *>(this)->getInitializedFieldInUnion();
+ }
+ void setInitializedFieldInUnion(FieldDecl *FD) {
+ assert((FD == nullptr
+ || getInitializedFieldInUnion() == nullptr
+ || getInitializedFieldInUnion() == FD)
+ && "Only one field of a union may be initialized at a time!");
+ ArrayFillerOrUnionFieldInit = 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();
+ }
+
+ // Is this an initializer for an array of characters, initialized by a string
+ // literal or an @encode?
+ bool isStringLiteralInit() const;
+
+ SourceLocation getLBraceLoc() const { return LBraceLoc; }
+ void setLBraceLoc(SourceLocation Loc) { LBraceLoc = Loc; }
+ SourceLocation getRBraceLoc() const { return RBraceLoc; }
+ void setRBraceLoc(SourceLocation Loc) { RBraceLoc = Loc; }
+
+ bool isSemanticForm() const { return AltForm.getInt(); }
+ InitListExpr *getSemanticForm() const {
+ return isSemanticForm() ? nullptr : AltForm.getPointer();
+ }
+ InitListExpr *getSyntacticForm() const {
+ return isSemanticForm() ? AltForm.getPointer() : nullptr;
+ }
+
+ void setSyntacticForm(InitListExpr *Init) {
+ AltForm.setPointer(Init);
+ AltForm.setInt(true);
+ Init->AltForm.setPointer(this);
+ Init->AltForm.setInt(false);
+ }
+
+ bool hadArrayRangeDesignator() const {
+ return InitListExprBits.HadArrayRangeDesignator != 0;
+ }
+ void sawArrayRangeDesignator(bool ARD = true) {
+ InitListExprBits.HadArrayRangeDesignator = ARD;
+ }
+
+ SourceLocation getLocStart() const LLVM_READONLY;
+ SourceLocation getLocEnd() const LLVM_READONLY;
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == InitListExprClass;
+ }
+
+ // Iterators
+ child_range children() {
+ // FIXME: This does not include the array filler expression.
+ if (InitExprs.empty())
+ return child_range(child_iterator(), child_iterator());
+ 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(); }
+
+ friend class ASTStmtReader;
+ friend class ASTStmtWriter;
+};
+
+/// @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 initialization expression will be 1.0.
+class DesignatedInitExpr final
+ : public Expr,
+ private llvm::TrailingObjects<DesignatedInitExpr, Stmt *> {
+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;
+
+ /// 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;
+
+ /// \brief The designators in this designated initialization
+ /// expression.
+ Designator *Designators;
+
+
+ DesignatedInitExpr(const ASTContext &C, QualType Ty, unsigned NumDesignators,
+ const Designator *Designators,
+ SourceLocation EqualOrColonLoc, bool GNUSyntax,
+ ArrayRef<Expr*> IndexExprs, Expr *Init);
+
+ explicit DesignatedInitExpr(unsigned NumSubExprs)
+ : Expr(DesignatedInitExprClass, EmptyShell()),
+ NumDesignators(0), NumSubExprs(NumSubExprs), Designators(nullptr) { }
+
+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() const;
+
+ FieldDecl *getField() const {
+ assert(Kind == FieldDesignator && "Only valid on a field designator");
+ if (Field.NameOrField & 0x01)
+ return nullptr;
+ 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 getLocStart() const LLVM_READONLY {
+ if (Kind == FieldDesignator)
+ return getDotLoc().isInvalid()? getFieldLoc() : getDotLoc();
+ else
+ return getLBracketLoc();
+ }
+ SourceLocation getLocEnd() const LLVM_READONLY {
+ return Kind == FieldDesignator ? getFieldLoc() : getRBracketLoc();
+ }
+ SourceRange getSourceRange() const LLVM_READONLY {
+ return SourceRange(getLocStart(), getLocEnd());
+ }
+ };
+
+ static DesignatedInitExpr *Create(const ASTContext &C,
+ Designator *Designators,
+ unsigned NumDesignators,
+ ArrayRef<Expr*> IndexExprs,
+ SourceLocation EqualOrColonLoc,
+ bool GNUSyntax, Expr *Init);
+
+ static DesignatedInitExpr *CreateEmpty(const 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 const Designator *const_designators_iterator;
+ const_designators_iterator designators_begin() const { return Designators; }
+ const_designators_iterator designators_end() const {
+ return Designators + NumDesignators;
+ }
+
+ typedef llvm::iterator_range<designators_iterator> designators_range;
+ designators_range designators() {
+ return designators_range(designators_begin(), designators_end());
+ }
+
+ typedef llvm::iterator_range<const_designators_iterator>
+ designators_const_range;
+ designators_const_range designators() const {
+ return designators_const_range(designators_begin(), designators_end());
+ }
+
+ 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());
+ }
+
+ typedef std::reverse_iterator<const_designators_iterator>
+ const_reverse_designators_iterator;
+ const_reverse_designators_iterator designators_rbegin() const {
+ return const_reverse_designators_iterator(designators_end());
+ }
+ const_reverse_designators_iterator designators_rend() const {
+ return const_reverse_designators_iterator(designators_begin());
+ }
+
+ Designator *getDesignator(unsigned Idx) { return &designators_begin()[Idx]; }
+
+ void setDesignators(const ASTContext &C, const Designator *Desigs,
+ unsigned NumDesigs);
+
+ Expr *getArrayIndex(const Designator &D) const;
+ Expr *getArrayRangeStart(const Designator &D) const;
+ Expr *getArrayRangeEnd(const Designator &D) const;
+
+ /// @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) const {
+ assert(Idx < NumSubExprs && "Subscript out of range");
+ return cast<Expr>(getTrailingObjects<Stmt *>()[Idx]);
+ }
+
+ void setSubExpr(unsigned Idx, Expr *E) {
+ assert(Idx < NumSubExprs && "Subscript out of range");
+ getTrailingObjects<Stmt *>()[Idx] = E;
+ }
+
+ /// \brief Replaces the designator at index @p Idx with the series
+ /// of designators in [First, Last).
+ void ExpandDesignator(const ASTContext &C, unsigned Idx,
+ const Designator *First, const Designator *Last);
+
+ SourceRange getDesignatorsSourceRange() const;
+
+ SourceLocation getLocStart() const LLVM_READONLY;
+ SourceLocation getLocEnd() const LLVM_READONLY;
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == DesignatedInitExprClass;
+ }
+
+ // Iterators
+ child_range children() {
+ Stmt **begin = getTrailingObjects<Stmt *>();
+ return child_range(begin, begin + NumSubExprs);
+ }
+
+ friend TrailingObjects;
+};
+
+/// \brief Represents a place-holder for an object not to be initialized by
+/// anything.
+///
+/// This only makes sense when it appears as part of an updater of a
+/// DesignatedInitUpdateExpr (see below). The base expression of a DIUE
+/// initializes a big object, and the NoInitExpr's mark the spots within the
+/// big object not to be overwritten by the updater.
+///
+/// \see DesignatedInitUpdateExpr
+class NoInitExpr : public Expr {
+public:
+ explicit NoInitExpr(QualType ty)
+ : Expr(NoInitExprClass, ty, VK_RValue, OK_Ordinary,
+ false, false, ty->isInstantiationDependentType(), false) { }
+
+ explicit NoInitExpr(EmptyShell Empty)
+ : Expr(NoInitExprClass, Empty) { }
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == NoInitExprClass;
+ }
+
+ SourceLocation getLocStart() const LLVM_READONLY { return SourceLocation(); }
+ SourceLocation getLocEnd() const LLVM_READONLY { return SourceLocation(); }
+
+ // Iterators
+ child_range children() {
+ return child_range(child_iterator(), child_iterator());
+ }
+};
+
+// In cases like:
+// struct Q { int a, b, c; };
+// Q *getQ();
+// void foo() {
+// struct A { Q q; } a = { *getQ(), .q.b = 3 };
+// }
+//
+// We will have an InitListExpr for a, with type A, and then a
+// DesignatedInitUpdateExpr for "a.q" with type Q. The "base" for this DIUE
+// is the call expression *getQ(); the "updater" for the DIUE is ".q.b = 3"
+//
+class DesignatedInitUpdateExpr : public Expr {
+ // BaseAndUpdaterExprs[0] is the base expression;
+ // BaseAndUpdaterExprs[1] is an InitListExpr overwriting part of the base.
+ Stmt *BaseAndUpdaterExprs[2];
+
+public:
+ DesignatedInitUpdateExpr(const ASTContext &C, SourceLocation lBraceLoc,
+ Expr *baseExprs, SourceLocation rBraceLoc);
+
+ explicit DesignatedInitUpdateExpr(EmptyShell Empty)
+ : Expr(DesignatedInitUpdateExprClass, Empty) { }
+
+ SourceLocation getLocStart() const LLVM_READONLY;
+ SourceLocation getLocEnd() const LLVM_READONLY;
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == DesignatedInitUpdateExprClass;
+ }
+
+ Expr *getBase() const { return cast<Expr>(BaseAndUpdaterExprs[0]); }
+ void setBase(Expr *Base) { BaseAndUpdaterExprs[0] = Base; }
+
+ InitListExpr *getUpdater() const {
+ return cast<InitListExpr>(BaseAndUpdaterExprs[1]);
+ }
+ void setUpdater(Expr *Updater) { BaseAndUpdaterExprs[1] = Updater; }
+
+ // Iterators
+ // children = the base and the updater
+ child_range children() {
+ return child_range(&BaseAndUpdaterExprs[0], &BaseAndUpdaterExprs[0] + 2);
+ }
+};
+
+/// \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, ty->isInstantiationDependentType(), 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;
+ }
+
+ SourceLocation getLocStart() const LLVM_READONLY { return SourceLocation(); }
+ SourceLocation getLocEnd() const LLVM_READONLY { return SourceLocation(); }
+
+ // Iterators
+ child_range children() {
+ return child_range(child_iterator(), child_iterator());
+ }
+};
+
+class ParenListExpr : public Expr {
+ Stmt **Exprs;
+ unsigned NumExprs;
+ SourceLocation LParenLoc, RParenLoc;
+
+public:
+ ParenListExpr(const ASTContext& C, SourceLocation lparenloc,
+ ArrayRef<Expr*> exprs, 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); }
+
+ ArrayRef<Expr *> exprs() {
+ return llvm::makeArrayRef(getExprs(), getNumExprs());
+ }
+
+ SourceLocation getLParenLoc() const { return LParenLoc; }
+ SourceLocation getRParenLoc() const { return RParenLoc; }
+
+ SourceLocation getLocStart() const LLVM_READONLY { return LParenLoc; }
+ SourceLocation getLocEnd() const LLVM_READONLY { return RParenLoc; }
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == ParenListExprClass;
+ }
+
+ // Iterators
+ child_range children() {
+ return child_range(&Exprs[0], &Exprs[0]+NumExprs);
+ }
+
+ friend class ASTStmtReader;
+ friend class ASTStmtWriter;
+};
+
+/// \brief Represents a C11 generic selection.
+///
+/// A generic selection (C11 6.5.1.1) contains an unevaluated controlling
+/// expression, followed by one or more generic associations. Each generic
+/// association specifies a type name and an expression, or "default" and an
+/// expression (in which case it is known as a default generic association).
+/// The type and value of the generic selection are identical to those of its
+/// result expression, which is defined as the expression in the generic
+/// association with a type name that is compatible with the type of the
+/// controlling expression, or the expression in the default generic association
+/// if no types are compatible. For example:
+///
+/// @code
+/// _Generic(X, double: 1, float: 2, default: 3)
+/// @endcode
+///
+/// The above expression evaluates to 1 if 1.0 is substituted for X, 2 if 1.0f
+/// or 3 if "hello".
+///
+/// As an extension, generic selections are allowed in C++, where the following
+/// additional semantics apply:
+///
+/// Any generic selection whose controlling expression is type-dependent or
+/// which names a dependent type in its association list is result-dependent,
+/// which means that the choice of result expression is dependent.
+/// Result-dependent generic associations are both type- and value-dependent.
+class GenericSelectionExpr : public Expr {
+ enum { CONTROLLING, END_EXPR };
+ TypeSourceInfo **AssocTypes;
+ Stmt **SubExprs;
+ unsigned NumAssocs, ResultIndex;
+ SourceLocation GenericLoc, DefaultLoc, RParenLoc;
+
+public:
+ GenericSelectionExpr(const ASTContext &Context,
+ SourceLocation GenericLoc, Expr *ControllingExpr,
+ ArrayRef<TypeSourceInfo*> AssocTypes,
+ ArrayRef<Expr*> AssocExprs,
+ SourceLocation DefaultLoc, SourceLocation RParenLoc,
+ bool ContainsUnexpandedParameterPack,
+ unsigned ResultIndex);
+
+ /// This constructor is used in the result-dependent case.
+ GenericSelectionExpr(const ASTContext &Context,
+ SourceLocation GenericLoc, Expr *ControllingExpr,
+ ArrayRef<TypeSourceInfo*> AssocTypes,
+ ArrayRef<Expr*> AssocExprs,
+ SourceLocation DefaultLoc, SourceLocation RParenLoc,
+ bool ContainsUnexpandedParameterPack);
+
+ explicit GenericSelectionExpr(EmptyShell Empty)
+ : Expr(GenericSelectionExprClass, Empty) { }
+
+ unsigned getNumAssocs() const { return NumAssocs; }
+
+ SourceLocation getGenericLoc() const { return GenericLoc; }
+ SourceLocation getDefaultLoc() const { return DefaultLoc; }
+ SourceLocation getRParenLoc() const { return RParenLoc; }
+
+ const Expr *getAssocExpr(unsigned i) const {
+ return cast<Expr>(SubExprs[END_EXPR+i]);
+ }
+ Expr *getAssocExpr(unsigned i) { return cast<Expr>(SubExprs[END_EXPR+i]); }
+
+ const TypeSourceInfo *getAssocTypeSourceInfo(unsigned i) const {
+ return AssocTypes[i];
+ }
+ TypeSourceInfo *getAssocTypeSourceInfo(unsigned i) { return AssocTypes[i]; }
+
+ QualType getAssocType(unsigned i) const {
+ if (const TypeSourceInfo *TS = getAssocTypeSourceInfo(i))
+ return TS->getType();
+ else
+ return QualType();
+ }
+
+ const Expr *getControllingExpr() const {
+ return cast<Expr>(SubExprs[CONTROLLING]);
+ }
+ Expr *getControllingExpr() { return cast<Expr>(SubExprs[CONTROLLING]); }
+
+ /// Whether this generic selection is result-dependent.
+ bool isResultDependent() const { return ResultIndex == -1U; }
+
+ /// The zero-based index of the result expression's generic association in
+ /// the generic selection's association list. Defined only if the
+ /// generic selection is not result-dependent.
+ unsigned getResultIndex() const {
+ assert(!isResultDependent() && "Generic selection is result-dependent");
+ return ResultIndex;
+ }
+
+ /// The generic selection's result expression. Defined only if the
+ /// generic selection is not result-dependent.
+ const Expr *getResultExpr() const { return getAssocExpr(getResultIndex()); }
+ Expr *getResultExpr() { return getAssocExpr(getResultIndex()); }
+
+ SourceLocation getLocStart() const LLVM_READONLY { return GenericLoc; }
+ SourceLocation getLocEnd() const LLVM_READONLY { return RParenLoc; }
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == GenericSelectionExprClass;
+ }
+
+ child_range children() {
+ return child_range(SubExprs, SubExprs+END_EXPR+NumAssocs);
+ }
+
+ friend class ASTStmtReader;
+};
+
+//===----------------------------------------------------------------------===//
+// 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->isInstantiationDependent(),
+ 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(SmallVectorImpl<uint32_t> &Elts) const;
+
+ SourceLocation getLocStart() const LLVM_READONLY {
+ return getBase()->getLocStart();
+ }
+ SourceLocation getLocEnd() const LLVM_READONLY { return 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;
+ }
+
+ // 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(), ty->isDependentType(),
+ ty->isInstantiationDependentType() || BD->isDependentContext(),
+ 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();
+
+ SourceLocation getLocStart() const LLVM_READONLY { return getCaretLocation(); }
+ SourceLocation getLocEnd() const LLVM_READONLY { return getBody()->getLocEnd(); }
+
+ /// getFunctionType - Return the underlying function type for this block.
+ const FunctionProtoType *getFunctionType() const;
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == BlockExprClass;
+ }
+
+ // Iterators
+ child_range children() {
+ return child_range(child_iterator(), child_iterator());
+ }
+};
+
+/// AsTypeExpr - Clang builtin function __builtin_astype [OpenCL 6.2.4.2]
+/// This AST node provides support for reinterpreting a type to another
+/// type of the same size.
+class AsTypeExpr : public Expr {
+private:
+ Stmt *SrcExpr;
+ SourceLocation BuiltinLoc, RParenLoc;
+
+ friend class ASTReader;
+ friend class ASTStmtReader;
+ explicit AsTypeExpr(EmptyShell Empty) : Expr(AsTypeExprClass, Empty) {}
+
+public:
+ AsTypeExpr(Expr* SrcExpr, QualType DstType,
+ ExprValueKind VK, ExprObjectKind OK,
+ SourceLocation BuiltinLoc, SourceLocation RParenLoc)
+ : Expr(AsTypeExprClass, DstType, VK, OK,
+ DstType->isDependentType(),
+ DstType->isDependentType() || SrcExpr->isValueDependent(),
+ (DstType->isInstantiationDependentType() ||
+ SrcExpr->isInstantiationDependent()),
+ (DstType->containsUnexpandedParameterPack() ||
+ SrcExpr->containsUnexpandedParameterPack())),
+ SrcExpr(SrcExpr), BuiltinLoc(BuiltinLoc), RParenLoc(RParenLoc) {}
+
+ /// getSrcExpr - Return the Expr to be converted.
+ Expr *getSrcExpr() const { return cast<Expr>(SrcExpr); }
+
+ /// getBuiltinLoc - Return the location of the __builtin_astype token.
+ SourceLocation getBuiltinLoc() const { return BuiltinLoc; }
+
+ /// getRParenLoc - Return the location of final right parenthesis.
+ SourceLocation getRParenLoc() const { return RParenLoc; }
+
+ SourceLocation getLocStart() const LLVM_READONLY { return BuiltinLoc; }
+ SourceLocation getLocEnd() const LLVM_READONLY { return RParenLoc; }
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == AsTypeExprClass;
+ }
+
+ // Iterators
+ child_range children() { return child_range(&SrcExpr, &SrcExpr+1); }
+};
+
+/// PseudoObjectExpr - An expression which accesses a pseudo-object
+/// l-value. A pseudo-object is an abstract object, accesses to which
+/// are translated to calls. The pseudo-object expression has a
+/// syntactic form, which shows how the expression was actually
+/// written in the source code, and a semantic form, which is a series
+/// of expressions to be executed in order which detail how the
+/// operation is actually evaluated. Optionally, one of the semantic
+/// forms may also provide a result value for the expression.
+///
+/// If any of the semantic-form expressions is an OpaqueValueExpr,
+/// that OVE is required to have a source expression, and it is bound
+/// to the result of that source expression. Such OVEs may appear
+/// only in subsequent semantic-form expressions and as
+/// sub-expressions of the syntactic form.
+///
+/// PseudoObjectExpr should be used only when an operation can be
+/// usefully described in terms of fairly simple rewrite rules on
+/// objects and functions that are meant to be used by end-developers.
+/// For example, under the Itanium ABI, dynamic casts are implemented
+/// as a call to a runtime function called __dynamic_cast; using this
+/// class to describe that would be inappropriate because that call is
+/// not really part of the user-visible semantics, and instead the
+/// cast is properly reflected in the AST and IR-generation has been
+/// taught to generate the call as necessary. In contrast, an
+/// Objective-C property access is semantically defined to be
+/// equivalent to a particular message send, and this is very much
+/// part of the user model. The name of this class encourages this
+/// modelling design.
+class PseudoObjectExpr final
+ : public Expr,
+ private llvm::TrailingObjects<PseudoObjectExpr, Expr *> {
+ // PseudoObjectExprBits.NumSubExprs - The number of sub-expressions.
+ // Always at least two, because the first sub-expression is the
+ // syntactic form.
+
+ // PseudoObjectExprBits.ResultIndex - The index of the
+ // sub-expression holding the result. 0 means the result is void,
+ // which is unambiguous because it's the index of the syntactic
+ // form. Note that this is therefore 1 higher than the value passed
+ // in to Create, which is an index within the semantic forms.
+ // Note also that ASTStmtWriter assumes this encoding.
+
+ Expr **getSubExprsBuffer() { return getTrailingObjects<Expr *>(); }
+ const Expr * const *getSubExprsBuffer() const {
+ return getTrailingObjects<Expr *>();
+ }
+
+ PseudoObjectExpr(QualType type, ExprValueKind VK,
+ Expr *syntactic, ArrayRef<Expr*> semantic,
+ unsigned resultIndex);
+
+ PseudoObjectExpr(EmptyShell shell, unsigned numSemanticExprs);
+
+ unsigned getNumSubExprs() const {
+ return PseudoObjectExprBits.NumSubExprs;
+ }
+
+public:
+ /// NoResult - A value for the result index indicating that there is
+ /// no semantic result.
+ enum : unsigned { NoResult = ~0U };
+
+ static PseudoObjectExpr *Create(const ASTContext &Context, Expr *syntactic,
+ ArrayRef<Expr*> semantic,
+ unsigned resultIndex);
+
+ static PseudoObjectExpr *Create(const ASTContext &Context, EmptyShell shell,
+ unsigned numSemanticExprs);
+
+ /// Return the syntactic form of this expression, i.e. the
+ /// expression it actually looks like. Likely to be expressed in
+ /// terms of OpaqueValueExprs bound in the semantic form.
+ Expr *getSyntacticForm() { return getSubExprsBuffer()[0]; }
+ const Expr *getSyntacticForm() const { return getSubExprsBuffer()[0]; }
+
+ /// Return the index of the result-bearing expression into the semantics
+ /// expressions, or PseudoObjectExpr::NoResult if there is none.
+ unsigned getResultExprIndex() const {
+ if (PseudoObjectExprBits.ResultIndex == 0) return NoResult;
+ return PseudoObjectExprBits.ResultIndex - 1;
+ }
+
+ /// Return the result-bearing expression, or null if there is none.
+ Expr *getResultExpr() {
+ if (PseudoObjectExprBits.ResultIndex == 0)
+ return nullptr;
+ return getSubExprsBuffer()[PseudoObjectExprBits.ResultIndex];
+ }
+ const Expr *getResultExpr() const {
+ return const_cast<PseudoObjectExpr*>(this)->getResultExpr();
+ }
+
+ unsigned getNumSemanticExprs() const { return getNumSubExprs() - 1; }
+
+ typedef Expr * const *semantics_iterator;
+ typedef const Expr * const *const_semantics_iterator;
+ semantics_iterator semantics_begin() {
+ return getSubExprsBuffer() + 1;
+ }
+ const_semantics_iterator semantics_begin() const {
+ return getSubExprsBuffer() + 1;
+ }
+ semantics_iterator semantics_end() {
+ return getSubExprsBuffer() + getNumSubExprs();
+ }
+ const_semantics_iterator semantics_end() const {
+ return getSubExprsBuffer() + getNumSubExprs();
+ }
+
+ llvm::iterator_range<semantics_iterator> semantics() {
+ return llvm::make_range(semantics_begin(), semantics_end());
+ }
+ llvm::iterator_range<const_semantics_iterator> semantics() const {
+ return llvm::make_range(semantics_begin(), semantics_end());
+ }
+
+ Expr *getSemanticExpr(unsigned index) {
+ assert(index + 1 < getNumSubExprs());
+ return getSubExprsBuffer()[index + 1];
+ }
+ const Expr *getSemanticExpr(unsigned index) const {
+ return const_cast<PseudoObjectExpr*>(this)->getSemanticExpr(index);
+ }
+
+ SourceLocation getExprLoc() const LLVM_READONLY {
+ return getSyntacticForm()->getExprLoc();
+ }
+
+ SourceLocation getLocStart() const LLVM_READONLY {
+ return getSyntacticForm()->getLocStart();
+ }
+ SourceLocation getLocEnd() const LLVM_READONLY {
+ return getSyntacticForm()->getLocEnd();
+ }
+
+ child_range children() {
+ Stmt **cs = reinterpret_cast<Stmt**>(getSubExprsBuffer());
+ return child_range(cs, cs + getNumSubExprs());
+ }
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == PseudoObjectExprClass;
+ }
+
+ friend TrailingObjects;
+ friend class ASTStmtReader;
+};
+
+/// AtomicExpr - Variadic atomic builtins: __atomic_exchange, __atomic_fetch_*,
+/// __atomic_load, __atomic_store, and __atomic_compare_exchange_*, for the
+/// similarly-named C++11 instructions, and __c11 variants for <stdatomic.h>.
+/// All of these instructions take one primary pointer and at least one memory
+/// order.
+class AtomicExpr : public Expr {
+public:
+ enum AtomicOp {
+#define BUILTIN(ID, TYPE, ATTRS)
+#define ATOMIC_BUILTIN(ID, TYPE, ATTRS) AO ## ID,
+#include "clang/Basic/Builtins.def"
+ // Avoid trailing comma
+ BI_First = 0
+ };
+
+ // The ABI values for various atomic memory orderings.
+ enum AtomicOrderingKind {
+ AO_ABI_memory_order_relaxed = 0,
+ AO_ABI_memory_order_consume = 1,
+ AO_ABI_memory_order_acquire = 2,
+ AO_ABI_memory_order_release = 3,
+ AO_ABI_memory_order_acq_rel = 4,
+ AO_ABI_memory_order_seq_cst = 5
+ };
+
+private:
+ enum { PTR, ORDER, VAL1, ORDER_FAIL, VAL2, WEAK, END_EXPR };
+ Stmt* SubExprs[END_EXPR];
+ unsigned NumSubExprs;
+ SourceLocation BuiltinLoc, RParenLoc;
+ AtomicOp Op;
+
+ friend class ASTStmtReader;
+
+public:
+ AtomicExpr(SourceLocation BLoc, ArrayRef<Expr*> args, QualType t,
+ AtomicOp op, SourceLocation RP);
+
+ /// \brief Determine the number of arguments the specified atomic builtin
+ /// should have.
+ static unsigned getNumSubExprs(AtomicOp Op);
+
+ /// \brief Build an empty AtomicExpr.
+ explicit AtomicExpr(EmptyShell Empty) : Expr(AtomicExprClass, Empty) { }
+
+ Expr *getPtr() const {
+ return cast<Expr>(SubExprs[PTR]);
+ }
+ Expr *getOrder() const {
+ return cast<Expr>(SubExprs[ORDER]);
+ }
+ Expr *getVal1() const {
+ if (Op == AO__c11_atomic_init)
+ return cast<Expr>(SubExprs[ORDER]);
+ assert(NumSubExprs > VAL1);
+ return cast<Expr>(SubExprs[VAL1]);
+ }
+ Expr *getOrderFail() const {
+ assert(NumSubExprs > ORDER_FAIL);
+ return cast<Expr>(SubExprs[ORDER_FAIL]);
+ }
+ Expr *getVal2() const {
+ if (Op == AO__atomic_exchange)
+ return cast<Expr>(SubExprs[ORDER_FAIL]);
+ assert(NumSubExprs > VAL2);
+ return cast<Expr>(SubExprs[VAL2]);
+ }
+ Expr *getWeak() const {
+ assert(NumSubExprs > WEAK);
+ return cast<Expr>(SubExprs[WEAK]);
+ }
+
+ AtomicOp getOp() const { return Op; }
+ unsigned getNumSubExprs() { return NumSubExprs; }
+
+ Expr **getSubExprs() { return reinterpret_cast<Expr **>(SubExprs); }
+
+ bool isVolatile() const {
+ return getPtr()->getType()->getPointeeType().isVolatileQualified();
+ }
+
+ bool isCmpXChg() const {
+ return getOp() == AO__c11_atomic_compare_exchange_strong ||
+ getOp() == AO__c11_atomic_compare_exchange_weak ||
+ getOp() == AO__atomic_compare_exchange ||
+ getOp() == AO__atomic_compare_exchange_n;
+ }
+
+ SourceLocation getBuiltinLoc() const { return BuiltinLoc; }
+ SourceLocation getRParenLoc() const { return RParenLoc; }
+
+ SourceLocation getLocStart() const LLVM_READONLY { return BuiltinLoc; }
+ SourceLocation getLocEnd() const LLVM_READONLY { return RParenLoc; }
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == AtomicExprClass;
+ }
+
+ // Iterators
+ child_range children() {
+ return child_range(SubExprs, SubExprs+NumSubExprs);
+ }
+};
+
+/// TypoExpr - Internal placeholder for expressions where typo correction
+/// still needs to be performed and/or an error diagnostic emitted.
+class TypoExpr : public Expr {
+public:
+ TypoExpr(QualType T)
+ : Expr(TypoExprClass, T, VK_LValue, OK_Ordinary,
+ /*isTypeDependent*/ true,
+ /*isValueDependent*/ true,
+ /*isInstantiationDependent*/ true,
+ /*containsUnexpandedParameterPack*/ false) {
+ assert(T->isDependentType() && "TypoExpr given a non-dependent type");
+ }
+
+ child_range children() {
+ return child_range(child_iterator(), child_iterator());
+ }
+ SourceLocation getLocStart() const LLVM_READONLY { return SourceLocation(); }
+ SourceLocation getLocEnd() const LLVM_READONLY { return SourceLocation(); }
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == TypoExprClass;
+ }
+
+};
+} // end namespace clang
+
+#endif // LLVM_CLANG_AST_EXPR_H
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..0608aba
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/AST/ExprCXX.h
@@ -0,0 +1,4179 @@
+//===--- 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.
+//
+//===----------------------------------------------------------------------===//
+///
+/// \file
+/// \brief Defines the clang::Expr interface and subclasses for C++ expressions.
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_AST_EXPRCXX_H
+#define LLVM_CLANG_AST_EXPRCXX_H
+
+#include "clang/AST/Decl.h"
+#include "clang/AST/Expr.h"
+#include "clang/AST/LambdaCapture.h"
+#include "clang/AST/TemplateBase.h"
+#include "clang/AST/UnresolvedSet.h"
+#include "clang/Basic/ExpressionTraits.h"
+#include "clang/Basic/TypeTraits.h"
+#include "llvm/Support/Compiler.h"
+
+namespace clang {
+
+class CXXConstructorDecl;
+class CXXDestructorDecl;
+class CXXMethodDecl;
+class CXXTemporary;
+class MSPropertyDecl;
+class TemplateArgumentListInfo;
+class UuidAttr;
+
+//===--------------------------------------------------------------------===//
+// 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;
+ SourceRange Range;
+
+ // Record the FP_CONTRACT state that applies to this operator call. Only
+ // meaningful for floating point types. For other types this value can be
+ // set to false.
+ unsigned FPContractable : 1;
+
+ SourceRange getSourceRangeImpl() const LLVM_READONLY;
+public:
+ CXXOperatorCallExpr(ASTContext& C, OverloadedOperatorKind Op, Expr *fn,
+ ArrayRef<Expr*> args, QualType t, ExprValueKind VK,
+ SourceLocation operatorloc, bool fpContractable)
+ : CallExpr(C, CXXOperatorCallExprClass, fn, 0, args, t, VK,
+ operatorloc),
+ Operator(Op), FPContractable(fpContractable) {
+ Range = getSourceRangeImpl();
+ }
+ explicit CXXOperatorCallExpr(ASTContext& C, EmptyShell Empty) :
+ CallExpr(C, CXXOperatorCallExprClass, Empty) { }
+
+
+ /// \brief Returns the kind of overloaded operator that this
+ /// expression refers to.
+ OverloadedOperatorKind getOperator() const { return Operator; }
+
+ /// \brief 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(); }
+
+ SourceLocation getExprLoc() const LLVM_READONLY {
+ return (Operator < OO_Plus || Operator >= OO_Arrow ||
+ Operator == OO_PlusPlus || Operator == OO_MinusMinus)
+ ? getLocStart()
+ : getOperatorLoc();
+ }
+
+ SourceLocation getLocStart() const LLVM_READONLY { return Range.getBegin(); }
+ SourceLocation getLocEnd() const LLVM_READONLY { return Range.getEnd(); }
+ SourceRange getSourceRange() const { return Range; }
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == CXXOperatorCallExprClass;
+ }
+
+ // Set the FP contractability status of this operator. Only meaningful for
+ // operations on floating point types.
+ void setFPContractable(bool FPC) { FPContractable = FPC; }
+
+ // Get the FP contractability status of this operator. Only meaningful for
+ // operations on floating point types.
+ bool isFPContractable() const { return FPContractable; }
+
+ friend class ASTStmtReader;
+ friend class ASTStmtWriter;
+};
+
+/// 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, ArrayRef<Expr*> args,
+ QualType t, ExprValueKind VK, SourceLocation RP)
+ : CallExpr(C, CXXMemberCallExprClass, fn, 0, args, t, VK, RP) {}
+
+ CXXMemberCallExpr(ASTContext &C, EmptyShell Empty)
+ : CallExpr(C, CXXMemberCallExprClass, Empty) { }
+
+ /// \brief Retrieves the implicit object argument for the member call.
+ ///
+ /// For example, in "x.f(5)", this returns the sub-expression "x".
+ Expr *getImplicitObjectArgument() const;
+
+ /// \brief Retrieves the declaration of the called method.
+ CXXMethodDecl *getMethodDecl() const;
+
+ /// \brief 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() const;
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == CXXMemberCallExprClass;
+ }
+};
+
+/// \brief 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,
+ ArrayRef<Expr*> args, QualType t, ExprValueKind VK,
+ SourceLocation RP)
+ : CallExpr(C, CUDAKernelCallExprClass, fn, END_PREARG, args, 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;
+ }
+};
+
+/// \brief Abstract class common to all of the C++ "named"/"keyword" casts.
+///
+/// This abstract class is inherited by all of the classes
+/// representing "named" casts: CXXStaticCastExpr for \c static_cast,
+/// CXXDynamicCastExpr for \c dynamic_cast, CXXReinterpretCastExpr for
+/// reinterpret_cast, and CXXConstCastExpr for \c const_cast.
+class CXXNamedCastExpr : public ExplicitCastExpr {
+private:
+ SourceLocation Loc; // the location of the casting op
+ SourceLocation RParenLoc; // the location of the right parenthesis
+ SourceRange AngleBrackets; // range for '<' '>'
+
+protected:
+ CXXNamedCastExpr(StmtClass SC, QualType ty, ExprValueKind VK,
+ CastKind kind, Expr *op, unsigned PathSize,
+ TypeSourceInfo *writtenTy, SourceLocation l,
+ SourceLocation RParenLoc,
+ SourceRange AngleBrackets)
+ : ExplicitCastExpr(SC, ty, VK, kind, op, PathSize, writtenTy), Loc(l),
+ RParenLoc(RParenLoc), AngleBrackets(AngleBrackets) {}
+
+ 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.,
+ /// \c static_cast.
+ SourceLocation getOperatorLoc() const { return Loc; }
+
+ /// \brief Retrieve the location of the closing parenthesis.
+ SourceLocation getRParenLoc() const { return RParenLoc; }
+
+ SourceLocation getLocStart() const LLVM_READONLY { return Loc; }
+ SourceLocation getLocEnd() const LLVM_READONLY { return RParenLoc; }
+ SourceRange getAngleBrackets() const LLVM_READONLY { return AngleBrackets; }
+
+ static bool classof(const Stmt *T) {
+ switch (T->getStmtClass()) {
+ case CXXStaticCastExprClass:
+ case CXXDynamicCastExprClass:
+ case CXXReinterpretCastExprClass:
+ case CXXConstCastExprClass:
+ return true;
+ default:
+ return false;
+ }
+ }
+};
+
+/// \brief 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 final
+ : public CXXNamedCastExpr,
+ private llvm::TrailingObjects<CXXStaticCastExpr, CXXBaseSpecifier *> {
+ CXXStaticCastExpr(QualType ty, ExprValueKind vk, CastKind kind, Expr *op,
+ unsigned pathSize, TypeSourceInfo *writtenTy,
+ SourceLocation l, SourceLocation RParenLoc,
+ SourceRange AngleBrackets)
+ : CXXNamedCastExpr(CXXStaticCastExprClass, ty, vk, kind, op, pathSize,
+ writtenTy, l, RParenLoc, AngleBrackets) {}
+
+ explicit CXXStaticCastExpr(EmptyShell Empty, unsigned PathSize)
+ : CXXNamedCastExpr(CXXStaticCastExprClass, Empty, PathSize) { }
+
+public:
+ static CXXStaticCastExpr *Create(const ASTContext &Context, QualType T,
+ ExprValueKind VK, CastKind K, Expr *Op,
+ const CXXCastPath *Path,
+ TypeSourceInfo *Written, SourceLocation L,
+ SourceLocation RParenLoc,
+ SourceRange AngleBrackets);
+ static CXXStaticCastExpr *CreateEmpty(const ASTContext &Context,
+ unsigned PathSize);
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == CXXStaticCastExprClass;
+ }
+
+ friend TrailingObjects;
+ friend class CastExpr;
+};
+
+/// \brief A C++ @c dynamic_cast expression (C++ [expr.dynamic.cast]).
+///
+/// This expression node represents a dynamic cast, e.g.,
+/// \c dynamic_cast<Derived*>(BasePtr). Such a cast may perform a run-time
+/// check to determine how to perform the type conversion.
+class CXXDynamicCastExpr final
+ : public CXXNamedCastExpr,
+ private llvm::TrailingObjects<CXXDynamicCastExpr, CXXBaseSpecifier *> {
+ CXXDynamicCastExpr(QualType ty, ExprValueKind VK, CastKind kind,
+ Expr *op, unsigned pathSize, TypeSourceInfo *writtenTy,
+ SourceLocation l, SourceLocation RParenLoc,
+ SourceRange AngleBrackets)
+ : CXXNamedCastExpr(CXXDynamicCastExprClass, ty, VK, kind, op, pathSize,
+ writtenTy, l, RParenLoc, AngleBrackets) {}
+
+ explicit CXXDynamicCastExpr(EmptyShell Empty, unsigned pathSize)
+ : CXXNamedCastExpr(CXXDynamicCastExprClass, Empty, pathSize) { }
+
+public:
+ static CXXDynamicCastExpr *Create(const ASTContext &Context, QualType T,
+ ExprValueKind VK, CastKind Kind, Expr *Op,
+ const CXXCastPath *Path,
+ TypeSourceInfo *Written, SourceLocation L,
+ SourceLocation RParenLoc,
+ SourceRange AngleBrackets);
+
+ static CXXDynamicCastExpr *CreateEmpty(const ASTContext &Context,
+ unsigned pathSize);
+
+ bool isAlwaysNull() const;
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == CXXDynamicCastExprClass;
+ }
+
+ friend TrailingObjects;
+ friend class CastExpr;
+};
+
+/// \brief A C++ @c reinterpret_cast expression (C++ [expr.reinterpret.cast]).
+///
+/// This expression node represents a reinterpret cast, e.g.,
+/// @c reinterpret_cast<int>(VoidPtr).
+///
+/// A reinterpret_cast provides a differently-typed view of a value but
+/// (in Clang, as in most C++ implementations) performs no actual work at
+/// run time.
+class CXXReinterpretCastExpr final
+ : public CXXNamedCastExpr,
+ private llvm::TrailingObjects<CXXReinterpretCastExpr,
+ CXXBaseSpecifier *> {
+ CXXReinterpretCastExpr(QualType ty, ExprValueKind vk, CastKind kind,
+ Expr *op, unsigned pathSize,
+ TypeSourceInfo *writtenTy, SourceLocation l,
+ SourceLocation RParenLoc,
+ SourceRange AngleBrackets)
+ : CXXNamedCastExpr(CXXReinterpretCastExprClass, ty, vk, kind, op,
+ pathSize, writtenTy, l, RParenLoc, AngleBrackets) {}
+
+ CXXReinterpretCastExpr(EmptyShell Empty, unsigned pathSize)
+ : CXXNamedCastExpr(CXXReinterpretCastExprClass, Empty, pathSize) { }
+
+public:
+ static CXXReinterpretCastExpr *Create(const ASTContext &Context, QualType T,
+ ExprValueKind VK, CastKind Kind,
+ Expr *Op, const CXXCastPath *Path,
+ TypeSourceInfo *WrittenTy, SourceLocation L,
+ SourceLocation RParenLoc,
+ SourceRange AngleBrackets);
+ static CXXReinterpretCastExpr *CreateEmpty(const ASTContext &Context,
+ unsigned pathSize);
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == CXXReinterpretCastExprClass;
+ }
+
+ friend TrailingObjects;
+ friend class CastExpr;
+};
+
+/// \brief A C++ \c const_cast expression (C++ [expr.const.cast]).
+///
+/// This expression node represents a const cast, e.g.,
+/// \c const_cast<char*>(PtrToConstChar).
+///
+/// A const_cast can remove type qualifiers but does not change the underlying
+/// value.
+class CXXConstCastExpr final
+ : public CXXNamedCastExpr,
+ private llvm::TrailingObjects<CXXConstCastExpr, CXXBaseSpecifier *> {
+ CXXConstCastExpr(QualType ty, ExprValueKind VK, Expr *op,
+ TypeSourceInfo *writtenTy, SourceLocation l,
+ SourceLocation RParenLoc, SourceRange AngleBrackets)
+ : CXXNamedCastExpr(CXXConstCastExprClass, ty, VK, CK_NoOp, op,
+ 0, writtenTy, l, RParenLoc, AngleBrackets) {}
+
+ explicit CXXConstCastExpr(EmptyShell Empty)
+ : CXXNamedCastExpr(CXXConstCastExprClass, Empty, 0) { }
+
+public:
+ static CXXConstCastExpr *Create(const ASTContext &Context, QualType T,
+ ExprValueKind VK, Expr *Op,
+ TypeSourceInfo *WrittenTy, SourceLocation L,
+ SourceLocation RParenLoc,
+ SourceRange AngleBrackets);
+ static CXXConstCastExpr *CreateEmpty(const ASTContext &Context);
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == CXXConstCastExprClass;
+ }
+
+ friend TrailingObjects;
+ friend class CastExpr;
+};
+
+/// \brief A call to a literal operator (C++11 [over.literal])
+/// written as a user-defined literal (C++11 [lit.ext]).
+///
+/// Represents a user-defined literal, e.g. "foo"_bar or 1.23_xyz. While this
+/// is semantically equivalent to a normal call, this AST node provides better
+/// information about the syntactic representation of the literal.
+///
+/// Since literal operators are never found by ADL and can only be declared at
+/// namespace scope, a user-defined literal is never dependent.
+class UserDefinedLiteral : public CallExpr {
+ /// \brief The location of a ud-suffix within the literal.
+ SourceLocation UDSuffixLoc;
+
+public:
+ UserDefinedLiteral(const ASTContext &C, Expr *Fn, ArrayRef<Expr*> Args,
+ QualType T, ExprValueKind VK, SourceLocation LitEndLoc,
+ SourceLocation SuffixLoc)
+ : CallExpr(C, UserDefinedLiteralClass, Fn, 0, Args, T, VK, LitEndLoc),
+ UDSuffixLoc(SuffixLoc) {}
+ explicit UserDefinedLiteral(const ASTContext &C, EmptyShell Empty)
+ : CallExpr(C, UserDefinedLiteralClass, Empty) {}
+
+ /// The kind of literal operator which is invoked.
+ enum LiteralOperatorKind {
+ LOK_Raw, ///< Raw form: operator "" X (const char *)
+ LOK_Template, ///< Raw form: operator "" X<cs...> ()
+ LOK_Integer, ///< operator "" X (unsigned long long)
+ LOK_Floating, ///< operator "" X (long double)
+ LOK_String, ///< operator "" X (const CharT *, size_t)
+ LOK_Character ///< operator "" X (CharT)
+ };
+
+ /// \brief Returns the kind of literal operator invocation
+ /// which this expression represents.
+ LiteralOperatorKind getLiteralOperatorKind() const;
+
+ /// \brief If this is not a raw user-defined literal, get the
+ /// underlying cooked literal (representing the literal with the suffix
+ /// removed).
+ Expr *getCookedLiteral();
+ const Expr *getCookedLiteral() const {
+ return const_cast<UserDefinedLiteral*>(this)->getCookedLiteral();
+ }
+
+ SourceLocation getLocStart() const {
+ if (getLiteralOperatorKind() == LOK_Template)
+ return getRParenLoc();
+ return getArg(0)->getLocStart();
+ }
+ SourceLocation getLocEnd() const { return getRParenLoc(); }
+
+
+ /// \brief Returns the location of a ud-suffix in the expression.
+ ///
+ /// For a string literal, there may be multiple identical suffixes. This
+ /// returns the first.
+ SourceLocation getUDSuffixLoc() const { return UDSuffixLoc; }
+
+ /// \brief Returns the ud-suffix specified for this literal.
+ const IdentifierInfo *getUDSuffix() const;
+
+ static bool classof(const Stmt *S) {
+ return S->getStmtClass() == UserDefinedLiteralClass;
+ }
+
+ friend class ASTStmtReader;
+ friend class ASTStmtWriter;
+};
+
+/// \brief A boolean literal, per ([C++ lex.bool] Boolean literals).
+///
+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, false),
+ Value(val), Loc(l) {}
+
+ explicit CXXBoolLiteralExpr(EmptyShell Empty)
+ : Expr(CXXBoolLiteralExprClass, Empty) { }
+
+ bool getValue() const { return Value; }
+ void setValue(bool V) { Value = V; }
+
+ SourceLocation getLocStart() const LLVM_READONLY { return Loc; }
+ SourceLocation getLocEnd() const LLVM_READONLY { return Loc; }
+
+ SourceLocation getLocation() const { return Loc; }
+ void setLocation(SourceLocation L) { Loc = L; }
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == CXXBoolLiteralExprClass;
+ }
+
+ // Iterators
+ child_range children() {
+ return child_range(child_iterator(), child_iterator());
+ }
+};
+
+/// \brief The null pointer literal (C++11 [lex.nullptr])
+///
+/// Introduced in C++11, the only literal of type \c nullptr_t is \c nullptr.
+class CXXNullPtrLiteralExpr : public Expr {
+ SourceLocation Loc;
+public:
+ CXXNullPtrLiteralExpr(QualType Ty, SourceLocation l) :
+ Expr(CXXNullPtrLiteralExprClass, Ty, VK_RValue, OK_Ordinary, false, false,
+ false, false),
+ Loc(l) {}
+
+ explicit CXXNullPtrLiteralExpr(EmptyShell Empty)
+ : Expr(CXXNullPtrLiteralExprClass, Empty) { }
+
+ SourceLocation getLocStart() const LLVM_READONLY { return Loc; }
+ SourceLocation getLocEnd() const LLVM_READONLY { return Loc; }
+
+ SourceLocation getLocation() const { return Loc; }
+ void setLocation(SourceLocation L) { Loc = L; }
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == CXXNullPtrLiteralExprClass;
+ }
+
+ child_range children() {
+ return child_range(child_iterator(), child_iterator());
+ }
+};
+
+/// \brief Implicit construction of a std::initializer_list<T> object from an
+/// array temporary within list-initialization (C++11 [dcl.init.list]p5).
+class CXXStdInitializerListExpr : public Expr {
+ Stmt *SubExpr;
+
+ CXXStdInitializerListExpr(EmptyShell Empty)
+ : Expr(CXXStdInitializerListExprClass, Empty), SubExpr(nullptr) {}
+
+public:
+ CXXStdInitializerListExpr(QualType Ty, Expr *SubExpr)
+ : Expr(CXXStdInitializerListExprClass, Ty, VK_RValue, OK_Ordinary,
+ Ty->isDependentType(), SubExpr->isValueDependent(),
+ SubExpr->isInstantiationDependent(),
+ SubExpr->containsUnexpandedParameterPack()),
+ SubExpr(SubExpr) {}
+
+ Expr *getSubExpr() { return static_cast<Expr*>(SubExpr); }
+ const Expr *getSubExpr() const { return static_cast<const Expr*>(SubExpr); }
+
+ SourceLocation getLocStart() const LLVM_READONLY {
+ return SubExpr->getLocStart();
+ }
+ SourceLocation getLocEnd() const LLVM_READONLY {
+ return SubExpr->getLocEnd();
+ }
+ SourceRange getSourceRange() const LLVM_READONLY {
+ return SubExpr->getSourceRange();
+ }
+
+ static bool classof(const Stmt *S) {
+ return S->getStmtClass() == CXXStdInitializerListExprClass;
+ }
+
+ child_range children() { return child_range(&SubExpr, &SubExpr + 1); }
+
+ friend class ASTReader;
+ friend class ASTStmtReader;
+};
+
+/// A C++ \c typeid expression (C++ [expr.typeid]), which gets
+/// the \c 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()->isInstantiationDependentType(),
+ 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->isInstantiationDependent(),
+ Operand->containsUnexpandedParameterPack()),
+ Operand(Operand), Range(R) { }
+
+ CXXTypeidExpr(EmptyShell Empty, bool isExpr)
+ : Expr(CXXTypeidExprClass, Empty) {
+ if (isExpr)
+ Operand = (Expr*)nullptr;
+ else
+ Operand = (TypeSourceInfo*)nullptr;
+ }
+
+ /// Determine whether this typeid has a type operand which is potentially
+ /// evaluated, per C++11 [expr.typeid]p3.
+ bool isPotentiallyEvaluated() const;
+
+ 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(ASTContext &Context) 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;
+ }
+
+ SourceLocation getLocStart() const LLVM_READONLY { return Range.getBegin(); }
+ SourceLocation getLocEnd() const LLVM_READONLY { return Range.getEnd(); }
+ SourceRange getSourceRange() const LLVM_READONLY { return Range; }
+ void setSourceRange(SourceRange R) { Range = R; }
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == CXXTypeidExprClass;
+ }
+
+ // Iterators
+ child_range children() {
+ if (isTypeOperand())
+ return child_range(child_iterator(), child_iterator());
+ Stmt **begin = reinterpret_cast<Stmt**>(&Operand);
+ return child_range(begin, begin + 1);
+ }
+};
+
+/// \brief A member reference to an MSPropertyDecl.
+///
+/// This expression always has pseudo-object type, and therefore it is
+/// typically not encountered in a fully-typechecked expression except
+/// within the syntactic form of a PseudoObjectExpr.
+class MSPropertyRefExpr : public Expr {
+ Expr *BaseExpr;
+ MSPropertyDecl *TheDecl;
+ SourceLocation MemberLoc;
+ bool IsArrow;
+ NestedNameSpecifierLoc QualifierLoc;
+
+public:
+ MSPropertyRefExpr(Expr *baseExpr, MSPropertyDecl *decl, bool isArrow,
+ QualType ty, ExprValueKind VK,
+ NestedNameSpecifierLoc qualifierLoc,
+ SourceLocation nameLoc)
+ : Expr(MSPropertyRefExprClass, ty, VK, OK_Ordinary,
+ /*type-dependent*/ false, baseExpr->isValueDependent(),
+ baseExpr->isInstantiationDependent(),
+ baseExpr->containsUnexpandedParameterPack()),
+ BaseExpr(baseExpr), TheDecl(decl),
+ MemberLoc(nameLoc), IsArrow(isArrow),
+ QualifierLoc(qualifierLoc) {}
+
+ MSPropertyRefExpr(EmptyShell Empty) : Expr(MSPropertyRefExprClass, Empty) {}
+
+ SourceRange getSourceRange() const LLVM_READONLY {
+ return SourceRange(getLocStart(), getLocEnd());
+ }
+ bool isImplicitAccess() const {
+ return getBaseExpr() && getBaseExpr()->isImplicitCXXThis();
+ }
+ SourceLocation getLocStart() const {
+ if (!isImplicitAccess())
+ return BaseExpr->getLocStart();
+ else if (QualifierLoc)
+ return QualifierLoc.getBeginLoc();
+ else
+ return MemberLoc;
+ }
+ SourceLocation getLocEnd() const { return getMemberLoc(); }
+
+ child_range children() {
+ return child_range((Stmt**)&BaseExpr, (Stmt**)&BaseExpr + 1);
+ }
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == MSPropertyRefExprClass;
+ }
+
+ Expr *getBaseExpr() const { return BaseExpr; }
+ MSPropertyDecl *getPropertyDecl() const { return TheDecl; }
+ bool isArrow() const { return IsArrow; }
+ SourceLocation getMemberLoc() const { return MemberLoc; }
+ NestedNameSpecifierLoc getQualifierLoc() const { return QualifierLoc; }
+
+ friend class ASTStmtReader;
+};
+
+/// MS property subscript expression.
+/// MSVC supports 'property' attribute and allows to apply it to the
+/// declaration of an empty array in a class or structure definition.
+/// For example:
+/// \code
+/// __declspec(property(get=GetX, put=PutX)) int x[];
+/// \endcode
+/// The above statement indicates that x[] can be used with one or more array
+/// indices. In this case, i=p->x[a][b] will be turned into i=p->GetX(a, b), and
+/// p->x[a][b] = i will be turned into p->PutX(a, b, i).
+/// This is a syntactic pseudo-object expression.
+class MSPropertySubscriptExpr : public Expr {
+ friend class ASTStmtReader;
+ enum { BASE_EXPR, IDX_EXPR, NUM_SUBEXPRS = 2 };
+ Stmt *SubExprs[NUM_SUBEXPRS];
+ SourceLocation RBracketLoc;
+
+ void setBase(Expr *Base) { SubExprs[BASE_EXPR] = Base; }
+ void setIdx(Expr *Idx) { SubExprs[IDX_EXPR] = Idx; }
+
+public:
+ MSPropertySubscriptExpr(Expr *Base, Expr *Idx, QualType Ty, ExprValueKind VK,
+ ExprObjectKind OK, SourceLocation RBracketLoc)
+ : Expr(MSPropertySubscriptExprClass, Ty, VK, OK, Idx->isTypeDependent(),
+ Idx->isValueDependent(), Idx->isInstantiationDependent(),
+ Idx->containsUnexpandedParameterPack()),
+ RBracketLoc(RBracketLoc) {
+ SubExprs[BASE_EXPR] = Base;
+ SubExprs[IDX_EXPR] = Idx;
+ }
+
+ /// \brief Create an empty array subscript expression.
+ explicit MSPropertySubscriptExpr(EmptyShell Shell)
+ : Expr(MSPropertySubscriptExprClass, Shell) {}
+
+ Expr *getBase() { return cast<Expr>(SubExprs[BASE_EXPR]); }
+ const Expr *getBase() const { return cast<Expr>(SubExprs[BASE_EXPR]); }
+
+ Expr *getIdx() { return cast<Expr>(SubExprs[IDX_EXPR]); }
+ const Expr *getIdx() const { return cast<Expr>(SubExprs[IDX_EXPR]); }
+
+ SourceLocation getLocStart() const LLVM_READONLY {
+ return getBase()->getLocStart();
+ }
+ SourceLocation getLocEnd() const LLVM_READONLY { return RBracketLoc; }
+
+ SourceLocation getRBracketLoc() const { return RBracketLoc; }
+ void setRBracketLoc(SourceLocation L) { RBracketLoc = L; }
+
+ SourceLocation getExprLoc() const LLVM_READONLY {
+ return getBase()->getExprLoc();
+ }
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == MSPropertySubscriptExprClass;
+ }
+
+ // Iterators
+ child_range children() {
+ return child_range(&SubExprs[0], &SubExprs[0] + NUM_SUBEXPRS);
+ }
+};
+
+/// 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()->isInstantiationDependentType(),
+ 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->isInstantiationDependent(),
+ Operand->containsUnexpandedParameterPack()),
+ Operand(Operand), Range(R) { }
+
+ CXXUuidofExpr(EmptyShell Empty, bool isExpr)
+ : Expr(CXXUuidofExprClass, Empty) {
+ if (isExpr)
+ Operand = (Expr*)nullptr;
+ else
+ Operand = (TypeSourceInfo*)nullptr;
+ }
+
+ 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(ASTContext &Context) 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;
+ }
+
+ StringRef getUuidAsStringRef(ASTContext &Context) const;
+
+ SourceLocation getLocStart() const LLVM_READONLY { return Range.getBegin(); }
+ SourceLocation getLocEnd() const LLVM_READONLY { return Range.getEnd(); }
+ SourceRange getSourceRange() const LLVM_READONLY { return Range; }
+ void setSourceRange(SourceRange R) { Range = R; }
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == CXXUuidofExprClass;
+ }
+
+ /// Grabs __declspec(uuid()) off a type, or returns 0 if we cannot resolve to
+ /// a single GUID.
+ static const UuidAttr *GetUuidAttrOfType(QualType QT,
+ bool *HasMultipleGUIDsPtr = nullptr);
+
+ // Iterators
+ child_range children() {
+ if (isTypeOperand())
+ return child_range(child_iterator(), child_iterator());
+ Stmt **begin = reinterpret_cast<Stmt**>(&Operand);
+ return child_range(begin, begin + 1);
+ }
+};
+
+/// \brief Represents the \c this expression in C++.
+///
+/// This 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(),
+ Type->isInstantiationDependentType(),
+ /*ContainsUnexpandedParameterPack=*/false),
+ Loc(L), Implicit(isImplicit) { }
+
+ CXXThisExpr(EmptyShell Empty) : Expr(CXXThisExprClass, Empty) {}
+
+ SourceLocation getLocation() const { return Loc; }
+ void setLocation(SourceLocation L) { Loc = L; }
+
+ SourceLocation getLocStart() const LLVM_READONLY { return Loc; }
+ SourceLocation getLocEnd() const LLVM_READONLY { return Loc; }
+
+ bool isImplicit() const { return Implicit; }
+ void setImplicit(bool I) { Implicit = I; }
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == CXXThisExprClass;
+ }
+
+ // Iterators
+ child_range children() {
+ return child_range(child_iterator(), child_iterator());
+ }
+};
+
+/// \brief A C++ throw-expression (C++ [except.throw]).
+///
+/// This handles 'throw' (for re-throwing the current exception) and
+/// 'throw' assignment-expression. When assignment-expression isn't
+/// present, Op will be null.
+class CXXThrowExpr : public Expr {
+ Stmt *Op;
+ SourceLocation ThrowLoc;
+ /// \brief Whether the thrown variable (if any) is in scope.
+ unsigned IsThrownVariableInScope : 1;
+
+ friend class ASTStmtReader;
+
+public:
+ // \p Ty is the void type which is used as the result type of the
+ // expression. The \p l is the location of the throw keyword. \p expr
+ // can by null, if the optional expression to throw isn't present.
+ CXXThrowExpr(Expr *expr, QualType Ty, SourceLocation l,
+ bool IsThrownVariableInScope) :
+ Expr(CXXThrowExprClass, Ty, VK_RValue, OK_Ordinary, false, false,
+ expr && expr->isInstantiationDependent(),
+ expr && expr->containsUnexpandedParameterPack()),
+ Op(expr), ThrowLoc(l), IsThrownVariableInScope(IsThrownVariableInScope) {}
+ CXXThrowExpr(EmptyShell Empty) : Expr(CXXThrowExprClass, Empty) {}
+
+ const Expr *getSubExpr() const { return cast_or_null<Expr>(Op); }
+ Expr *getSubExpr() { return cast_or_null<Expr>(Op); }
+
+ SourceLocation getThrowLoc() const { return ThrowLoc; }
+
+ /// \brief Determines whether the variable thrown by this expression (if any!)
+ /// is within the innermost try block.
+ ///
+ /// This information is required to determine whether the NRVO can apply to
+ /// this variable.
+ bool isThrownVariableInScope() const { return IsThrownVariableInScope; }
+
+ SourceLocation getLocStart() const LLVM_READONLY { return ThrowLoc; }
+ SourceLocation getLocEnd() const LLVM_READONLY {
+ if (!getSubExpr())
+ return ThrowLoc;
+ return getSubExpr()->getLocEnd();
+ }
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == CXXThrowExprClass;
+ }
+
+ // Iterators
+ child_range children() {
+ return child_range(&Op, Op ? &Op+1 : &Op);
+ }
+};
+
+/// \brief A default argument (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 final
+ : public Expr,
+ private llvm::TrailingObjects<CXXDefaultArgExpr, 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, 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, false),
+ Param(param, true), Loc(Loc) {
+ *getTrailingObjects<Expr *>() = SubExpr;
+ }
+
+public:
+ CXXDefaultArgExpr(EmptyShell Empty) : Expr(CXXDefaultArgExprClass, Empty) {}
+
+ // \p Param is the parameter whose default argument is used by this
+ // expression.
+ static CXXDefaultArgExpr *Create(const ASTContext &C, SourceLocation Loc,
+ ParmVarDecl *Param) {
+ return new (C) CXXDefaultArgExpr(CXXDefaultArgExprClass, Loc, Param);
+ }
+
+ // \p Param is the parameter whose default argument is used by this
+ // expression, and \p SubExpr is the expression that will actually be used.
+ static CXXDefaultArgExpr *Create(const 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 *getTrailingObjects<Expr *>();
+ return getParam()->getDefaultArg();
+ }
+ Expr *getExpr() {
+ if (Param.getInt())
+ return *getTrailingObjects<Expr *>();
+ return getParam()->getDefaultArg();
+ }
+
+ /// \brief Retrieve the location where this default argument was actually
+ /// used.
+ SourceLocation getUsedLocation() const { return Loc; }
+
+ /// Default argument expressions have no representation in the
+ /// source, so they have an empty source range.
+ SourceLocation getLocStart() const LLVM_READONLY { return SourceLocation(); }
+ SourceLocation getLocEnd() const LLVM_READONLY { return SourceLocation(); }
+
+ SourceLocation getExprLoc() const LLVM_READONLY { return Loc; }
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == CXXDefaultArgExprClass;
+ }
+
+ // Iterators
+ child_range children() {
+ return child_range(child_iterator(), child_iterator());
+ }
+
+ friend TrailingObjects;
+ friend class ASTStmtReader;
+ friend class ASTStmtWriter;
+};
+
+/// \brief A use of a default initializer in a constructor or in aggregate
+/// initialization.
+///
+/// This wraps a use of a C++ default initializer (technically,
+/// a brace-or-equal-initializer for a non-static data member) when it
+/// is implicitly used in a mem-initializer-list in a constructor
+/// (C++11 [class.base.init]p8) or in aggregate initialization
+/// (C++1y [dcl.init.aggr]p7).
+class CXXDefaultInitExpr : public Expr {
+ /// \brief The field whose default is being used.
+ FieldDecl *Field;
+
+ /// \brief The location where the default initializer expression was used.
+ SourceLocation Loc;
+
+ CXXDefaultInitExpr(const ASTContext &C, SourceLocation Loc, FieldDecl *Field,
+ QualType T);
+
+ CXXDefaultInitExpr(EmptyShell Empty) : Expr(CXXDefaultInitExprClass, Empty) {}
+
+public:
+ /// \p Field is the non-static data member whose default initializer is used
+ /// by this expression.
+ static CXXDefaultInitExpr *Create(const ASTContext &C, SourceLocation Loc,
+ FieldDecl *Field) {
+ return new (C) CXXDefaultInitExpr(C, Loc, Field, Field->getType());
+ }
+
+ /// \brief Get the field whose initializer will be used.
+ FieldDecl *getField() { return Field; }
+ const FieldDecl *getField() const { return Field; }
+
+ /// \brief Get the initialization expression that will be used.
+ const Expr *getExpr() const {
+ assert(Field->getInClassInitializer() && "initializer hasn't been parsed");
+ return Field->getInClassInitializer();
+ }
+ Expr *getExpr() {
+ assert(Field->getInClassInitializer() && "initializer hasn't been parsed");
+ return Field->getInClassInitializer();
+ }
+
+ SourceLocation getLocStart() const LLVM_READONLY { return Loc; }
+ SourceLocation getLocEnd() const LLVM_READONLY { return Loc; }
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == CXXDefaultInitExprClass;
+ }
+
+ // Iterators
+ child_range children() {
+ return child_range(child_iterator(), child_iterator());
+ }
+
+ friend class ASTReader;
+ friend class ASTStmtReader;
+};
+
+/// \brief Represents a C++ temporary.
+class CXXTemporary {
+ /// \brief The destructor that needs to be called.
+ const CXXDestructorDecl *Destructor;
+
+ explicit CXXTemporary(const CXXDestructorDecl *destructor)
+ : Destructor(destructor) { }
+
+public:
+ static CXXTemporary *Create(const ASTContext &C,
+ const CXXDestructorDecl *Destructor);
+
+ const CXXDestructorDecl *getDestructor() const { return Destructor; }
+ void setDestructor(const CXXDestructorDecl *Dtor) {
+ Destructor = Dtor;
+ }
+};
+
+/// \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->isInstantiationDependent(),
+ SubExpr->containsUnexpandedParameterPack()),
+ Temp(temp), SubExpr(SubExpr) { }
+
+public:
+ CXXBindTemporaryExpr(EmptyShell Empty)
+ : Expr(CXXBindTemporaryExprClass, Empty), Temp(nullptr), SubExpr(nullptr) {}
+
+ static CXXBindTemporaryExpr *Create(const 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; }
+
+ SourceLocation getLocStart() const LLVM_READONLY {
+ return SubExpr->getLocStart();
+ }
+ SourceLocation getLocEnd() const LLVM_READONLY { return SubExpr->getLocEnd();}
+
+ // Implement isa/cast/dyncast/etc.
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == CXXBindTemporaryExprClass;
+ }
+
+ // Iterators
+ child_range children() { return child_range(&SubExpr, &SubExpr + 1); }
+};
+
+/// \brief Represents a call to a C++ constructor.
+class CXXConstructExpr : public Expr {
+public:
+ enum ConstructionKind {
+ CK_Complete,
+ CK_NonVirtualBase,
+ CK_VirtualBase,
+ CK_Delegating
+ };
+
+private:
+ CXXConstructorDecl *Constructor;
+
+ SourceLocation Loc;
+ SourceRange ParenOrBraceRange;
+ unsigned NumArgs : 16;
+ bool Elidable : 1;
+ bool HadMultipleCandidates : 1;
+ bool ListInitialization : 1;
+ bool StdInitListInitialization : 1;
+ bool ZeroInitialization : 1;
+ unsigned ConstructKind : 2;
+ Stmt **Args;
+
+protected:
+ CXXConstructExpr(const ASTContext &C, StmtClass SC, QualType T,
+ SourceLocation Loc,
+ CXXConstructorDecl *d, bool elidable,
+ ArrayRef<Expr *> Args,
+ bool HadMultipleCandidates,
+ bool ListInitialization,
+ bool StdInitListInitialization,
+ bool ZeroInitialization,
+ ConstructionKind ConstructKind,
+ SourceRange ParenOrBraceRange);
+
+ /// \brief Construct an empty C++ construction expression.
+ CXXConstructExpr(StmtClass SC, EmptyShell Empty)
+ : Expr(SC, Empty), Constructor(nullptr), NumArgs(0), Elidable(false),
+ HadMultipleCandidates(false), ListInitialization(false),
+ ZeroInitialization(false), ConstructKind(0), Args(nullptr)
+ { }
+
+public:
+ /// \brief Construct an empty C++ construction expression.
+ explicit CXXConstructExpr(EmptyShell Empty)
+ : Expr(CXXConstructExprClass, Empty), Constructor(nullptr),
+ NumArgs(0), Elidable(false), HadMultipleCandidates(false),
+ ListInitialization(false), ZeroInitialization(false),
+ ConstructKind(0), Args(nullptr)
+ { }
+
+ static CXXConstructExpr *Create(const ASTContext &C, QualType T,
+ SourceLocation Loc,
+ CXXConstructorDecl *D, bool Elidable,
+ ArrayRef<Expr *> Args,
+ bool HadMultipleCandidates,
+ bool ListInitialization,
+ bool StdInitListInitialization,
+ bool ZeroInitialization,
+ ConstructionKind ConstructKind,
+ SourceRange ParenOrBraceRange);
+
+ 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 the referred constructor was resolved from
+ /// an overloaded set having size greater than 1.
+ bool hadMultipleCandidates() const { return HadMultipleCandidates; }
+ void setHadMultipleCandidates(bool V) { HadMultipleCandidates = V; }
+
+ /// \brief Whether this constructor call was written as list-initialization.
+ bool isListInitialization() const { return ListInitialization; }
+ void setListInitialization(bool V) { ListInitialization = V; }
+
+ /// \brief Whether this constructor call was written as list-initialization,
+ /// but was interpreted as forming a std::initializer_list<T> from the list
+ /// and passing that as a single constructor argument.
+ /// See C++11 [over.match.list]p1 bullet 1.
+ bool isStdInitListInitialization() const { return StdInitListInitialization; }
+ void setStdInitListInitialization(bool V) { StdInitListInitialization = V; }
+
+ /// \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 Determine 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;
+ typedef llvm::iterator_range<arg_iterator> arg_range;
+ typedef llvm::iterator_range<const_arg_iterator> arg_const_range;
+
+ arg_range arguments() { return arg_range(arg_begin(), arg_end()); }
+ arg_const_range arguments() const {
+ return arg_const_range(arg_begin(), arg_end());
+ }
+
+ 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() { return reinterpret_cast<Expr **>(Args); }
+ const Expr *const *getArgs() const {
+ return const_cast<CXXConstructExpr *>(this)->getArgs();
+ }
+ unsigned getNumArgs() const { return NumArgs; }
+
+ /// \brief 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]);
+ }
+
+ /// \brief Set the specified argument.
+ void setArg(unsigned Arg, Expr *ArgExpr) {
+ assert(Arg < NumArgs && "Arg access out of range!");
+ Args[Arg] = ArgExpr;
+ }
+
+ SourceLocation getLocStart() const LLVM_READONLY;
+ SourceLocation getLocEnd() const LLVM_READONLY;
+ SourceRange getParenOrBraceRange() const { return ParenOrBraceRange; }
+ void setParenOrBraceRange(SourceRange Range) { ParenOrBraceRange = Range; }
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == CXXConstructExprClass ||
+ T->getStmtClass() == CXXTemporaryObjectExprClass;
+ }
+
+ // Iterators
+ child_range children() {
+ return child_range(&Args[0], &Args[0]+NumArgs);
+ }
+
+ friend class ASTStmtReader;
+};
+
+/// \brief Represents an explicit C++ type conversion that uses "functional"
+/// notation (C++ [expr.type.conv]).
+///
+/// Example:
+/// \code
+/// x = int(0.5);
+/// \endcode
+class CXXFunctionalCastExpr final
+ : public ExplicitCastExpr,
+ private llvm::TrailingObjects<CXXFunctionalCastExpr, CXXBaseSpecifier *> {
+ SourceLocation LParenLoc;
+ SourceLocation RParenLoc;
+
+ CXXFunctionalCastExpr(QualType ty, ExprValueKind VK,
+ TypeSourceInfo *writtenTy,
+ CastKind kind, Expr *castExpr, unsigned pathSize,
+ SourceLocation lParenLoc, SourceLocation rParenLoc)
+ : ExplicitCastExpr(CXXFunctionalCastExprClass, ty, VK, kind,
+ castExpr, pathSize, writtenTy),
+ LParenLoc(lParenLoc), RParenLoc(rParenLoc) {}
+
+ explicit CXXFunctionalCastExpr(EmptyShell Shell, unsigned PathSize)
+ : ExplicitCastExpr(CXXFunctionalCastExprClass, Shell, PathSize) { }
+
+public:
+ static CXXFunctionalCastExpr *Create(const ASTContext &Context, QualType T,
+ ExprValueKind VK,
+ TypeSourceInfo *Written,
+ CastKind Kind, Expr *Op,
+ const CXXCastPath *Path,
+ SourceLocation LPLoc,
+ SourceLocation RPLoc);
+ static CXXFunctionalCastExpr *CreateEmpty(const ASTContext &Context,
+ unsigned PathSize);
+
+ SourceLocation getLParenLoc() const { return LParenLoc; }
+ void setLParenLoc(SourceLocation L) { LParenLoc = L; }
+ SourceLocation getRParenLoc() const { return RParenLoc; }
+ void setRParenLoc(SourceLocation L) { RParenLoc = L; }
+
+ SourceLocation getLocStart() const LLVM_READONLY;
+ SourceLocation getLocEnd() const LLVM_READONLY;
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == CXXFunctionalCastExprClass;
+ }
+
+ friend TrailingObjects;
+ friend class CastExpr;
+};
+
+/// @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(const ASTContext &C, CXXConstructorDecl *Cons,
+ TypeSourceInfo *Type,
+ ArrayRef<Expr *> Args,
+ SourceRange ParenOrBraceRange,
+ bool HadMultipleCandidates,
+ bool ListInitialization,
+ bool StdInitListInitialization,
+ bool ZeroInitialization);
+ explicit CXXTemporaryObjectExpr(EmptyShell Empty)
+ : CXXConstructExpr(CXXTemporaryObjectExprClass, Empty), Type() { }
+
+ TypeSourceInfo *getTypeSourceInfo() const { return Type; }
+
+ SourceLocation getLocStart() const LLVM_READONLY;
+ SourceLocation getLocEnd() const LLVM_READONLY;
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == CXXTemporaryObjectExprClass;
+ }
+
+ friend class ASTStmtReader;
+};
+
+/// \brief A C++ lambda expression, which produces a function object
+/// (of unspecified type) that can be invoked later.
+///
+/// Example:
+/// \code
+/// void low_pass_filter(std::vector<double> &values, double cutoff) {
+/// values.erase(std::remove_if(values.begin(), values.end(),
+/// [=](double value) { return value > cutoff; });
+/// }
+/// \endcode
+///
+/// C++11 lambda expressions can capture local variables, either by copying
+/// the values of those local variables at the time the function
+/// object is constructed (not when it is called!) or by holding a
+/// reference to the local variable. These captures can occur either
+/// implicitly or can be written explicitly between the square
+/// brackets ([...]) that start the lambda expression.
+///
+/// C++1y introduces a new form of "capture" called an init-capture that
+/// includes an initializing expression (rather than capturing a variable),
+/// and which can never occur implicitly.
+class LambdaExpr final
+ : public Expr,
+ private llvm::TrailingObjects<LambdaExpr, Stmt *, unsigned, VarDecl *> {
+ /// \brief The source range that covers the lambda introducer ([...]).
+ SourceRange IntroducerRange;
+
+ /// \brief The source location of this lambda's capture-default ('=' or '&').
+ SourceLocation CaptureDefaultLoc;
+
+ /// \brief The number of captures.
+ unsigned NumCaptures : 16;
+
+ /// \brief The default capture kind, which is a value of type
+ /// LambdaCaptureDefault.
+ unsigned CaptureDefault : 2;
+
+ /// \brief Whether this lambda had an explicit parameter list vs. an
+ /// implicit (and empty) parameter list.
+ unsigned ExplicitParams : 1;
+
+ /// \brief Whether this lambda had the result type explicitly specified.
+ unsigned ExplicitResultType : 1;
+
+ /// \brief Whether there are any array index variables stored at the end of
+ /// this lambda expression.
+ unsigned HasArrayIndexVars : 1;
+
+ /// \brief The location of the closing brace ('}') that completes
+ /// the lambda.
+ ///
+ /// The location of the brace is also available by looking up the
+ /// function call operator in the lambda class. However, it is
+ /// stored here to improve the performance of getSourceRange(), and
+ /// to avoid having to deserialize the function call operator from a
+ /// module file just to determine the source range.
+ SourceLocation ClosingBrace;
+
+ size_t numTrailingObjects(OverloadToken<Stmt *>) const {
+ return NumCaptures + 1;
+ }
+
+ size_t numTrailingObjects(OverloadToken<unsigned>) const {
+ return HasArrayIndexVars ? NumCaptures + 1 : 0;
+ }
+
+ /// \brief Construct a lambda expression.
+ LambdaExpr(QualType T, SourceRange IntroducerRange,
+ LambdaCaptureDefault CaptureDefault,
+ SourceLocation CaptureDefaultLoc, ArrayRef<LambdaCapture> Captures,
+ bool ExplicitParams, bool ExplicitResultType,
+ ArrayRef<Expr *> CaptureInits, ArrayRef<VarDecl *> ArrayIndexVars,
+ ArrayRef<unsigned> ArrayIndexStarts, SourceLocation ClosingBrace,
+ bool ContainsUnexpandedParameterPack);
+
+ /// \brief Construct an empty lambda expression.
+ LambdaExpr(EmptyShell Empty, unsigned NumCaptures, bool HasArrayIndexVars)
+ : Expr(LambdaExprClass, Empty),
+ NumCaptures(NumCaptures), CaptureDefault(LCD_None), ExplicitParams(false),
+ ExplicitResultType(false), HasArrayIndexVars(true) {
+ getStoredStmts()[NumCaptures] = nullptr;
+ }
+
+ Stmt **getStoredStmts() { return getTrailingObjects<Stmt *>(); }
+
+ Stmt *const *getStoredStmts() const { return getTrailingObjects<Stmt *>(); }
+
+ /// \brief Retrieve the mapping from captures to the first array index
+ /// variable.
+ unsigned *getArrayIndexStarts() { return getTrailingObjects<unsigned>(); }
+
+ const unsigned *getArrayIndexStarts() const {
+ return getTrailingObjects<unsigned>();
+ }
+
+ /// \brief Retrieve the complete set of array-index variables.
+ VarDecl **getArrayIndexVars() { return getTrailingObjects<VarDecl *>(); }
+
+ VarDecl *const *getArrayIndexVars() const {
+ return getTrailingObjects<VarDecl *>();
+ }
+
+public:
+ /// \brief Construct a new lambda expression.
+ static LambdaExpr *
+ Create(const ASTContext &C, CXXRecordDecl *Class, SourceRange IntroducerRange,
+ LambdaCaptureDefault CaptureDefault, SourceLocation CaptureDefaultLoc,
+ ArrayRef<LambdaCapture> Captures, bool ExplicitParams,
+ bool ExplicitResultType, ArrayRef<Expr *> CaptureInits,
+ ArrayRef<VarDecl *> ArrayIndexVars,
+ ArrayRef<unsigned> ArrayIndexStarts, SourceLocation ClosingBrace,
+ bool ContainsUnexpandedParameterPack);
+
+ /// \brief Construct a new lambda expression that will be deserialized from
+ /// an external source.
+ static LambdaExpr *CreateDeserialized(const ASTContext &C,
+ unsigned NumCaptures,
+ unsigned NumArrayIndexVars);
+
+ /// \brief Determine the default capture kind for this lambda.
+ LambdaCaptureDefault getCaptureDefault() const {
+ return static_cast<LambdaCaptureDefault>(CaptureDefault);
+ }
+
+ /// \brief Retrieve the location of this lambda's capture-default, if any.
+ SourceLocation getCaptureDefaultLoc() const {
+ return CaptureDefaultLoc;
+ }
+
+ /// \brief Determine whether one of this lambda's captures is an init-capture.
+ bool isInitCapture(const LambdaCapture *Capture) const;
+
+ /// \brief An iterator that walks over the captures of the lambda,
+ /// both implicit and explicit.
+ typedef const LambdaCapture *capture_iterator;
+
+ /// \brief An iterator over a range of lambda captures.
+ typedef llvm::iterator_range<capture_iterator> capture_range;
+
+ /// \brief Retrieve this lambda's captures.
+ capture_range captures() const;
+
+ /// \brief Retrieve an iterator pointing to the first lambda capture.
+ capture_iterator capture_begin() const;
+
+ /// \brief Retrieve an iterator pointing past the end of the
+ /// sequence of lambda captures.
+ capture_iterator capture_end() const;
+
+ /// \brief Determine the number of captures in this lambda.
+ unsigned capture_size() const { return NumCaptures; }
+
+ /// \brief Retrieve this lambda's explicit captures.
+ capture_range explicit_captures() const;
+
+ /// \brief Retrieve an iterator pointing to the first explicit
+ /// lambda capture.
+ capture_iterator explicit_capture_begin() const;
+
+ /// \brief Retrieve an iterator pointing past the end of the sequence of
+ /// explicit lambda captures.
+ capture_iterator explicit_capture_end() const;
+
+ /// \brief Retrieve this lambda's implicit captures.
+ capture_range implicit_captures() const;
+
+ /// \brief Retrieve an iterator pointing to the first implicit
+ /// lambda capture.
+ capture_iterator implicit_capture_begin() const;
+
+ /// \brief Retrieve an iterator pointing past the end of the sequence of
+ /// implicit lambda captures.
+ capture_iterator implicit_capture_end() const;
+
+ /// \brief Iterator that walks over the capture initialization
+ /// arguments.
+ typedef Expr **capture_init_iterator;
+
+ /// \brief Const iterator that walks over the capture initialization
+ /// arguments.
+ typedef Expr *const *const_capture_init_iterator;
+
+ /// \brief Retrieve the initialization expressions for this lambda's captures.
+ llvm::iterator_range<capture_init_iterator> capture_inits() {
+ return llvm::make_range(capture_init_begin(), capture_init_end());
+ }
+
+ /// \brief Retrieve the initialization expressions for this lambda's captures.
+ llvm::iterator_range<const_capture_init_iterator> capture_inits() const {
+ return llvm::make_range(capture_init_begin(), capture_init_end());
+ }
+
+ /// \brief Retrieve the first initialization argument for this
+ /// lambda expression (which initializes the first capture field).
+ capture_init_iterator capture_init_begin() {
+ return reinterpret_cast<Expr **>(getStoredStmts());
+ }
+
+ /// \brief Retrieve the first initialization argument for this
+ /// lambda expression (which initializes the first capture field).
+ const_capture_init_iterator capture_init_begin() const {
+ return reinterpret_cast<Expr *const *>(getStoredStmts());
+ }
+
+ /// \brief Retrieve the iterator pointing one past the last
+ /// initialization argument for this lambda expression.
+ capture_init_iterator capture_init_end() {
+ return capture_init_begin() + NumCaptures;
+ }
+
+ /// \brief Retrieve the iterator pointing one past the last
+ /// initialization argument for this lambda expression.
+ const_capture_init_iterator capture_init_end() const {
+ return capture_init_begin() + NumCaptures;
+ }
+
+ /// \brief Retrieve the set of index variables used in the capture
+ /// initializer of an array captured by copy.
+ ///
+ /// \param Iter The iterator that points at the capture initializer for
+ /// which we are extracting the corresponding index variables.
+ ArrayRef<VarDecl *>
+ getCaptureInitIndexVars(const_capture_init_iterator Iter) const;
+
+ /// \brief Retrieve the source range covering the lambda introducer,
+ /// which contains the explicit capture list surrounded by square
+ /// brackets ([...]).
+ SourceRange getIntroducerRange() const { return IntroducerRange; }
+
+ /// \brief Retrieve the class that corresponds to the lambda.
+ ///
+ /// This is the "closure type" (C++1y [expr.prim.lambda]), and stores the
+ /// captures in its fields and provides the various operations permitted
+ /// on a lambda (copying, calling).
+ CXXRecordDecl *getLambdaClass() const;
+
+ /// \brief Retrieve the function call operator associated with this
+ /// lambda expression.
+ CXXMethodDecl *getCallOperator() const;
+
+ /// \brief If this is a generic lambda expression, retrieve the template
+ /// parameter list associated with it, or else return null.
+ TemplateParameterList *getTemplateParameterList() const;
+
+ /// \brief Whether this is a generic lambda.
+ bool isGenericLambda() const { return getTemplateParameterList(); }
+
+ /// \brief Retrieve the body of the lambda.
+ CompoundStmt *getBody() const;
+
+ /// \brief Determine whether the lambda is mutable, meaning that any
+ /// captures values can be modified.
+ bool isMutable() const;
+
+ /// \brief Determine whether this lambda has an explicit parameter
+ /// list vs. an implicit (empty) parameter list.
+ bool hasExplicitParameters() const { return ExplicitParams; }
+
+ /// \brief Whether this lambda had its result type explicitly specified.
+ bool hasExplicitResultType() const { return ExplicitResultType; }
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == LambdaExprClass;
+ }
+
+ SourceLocation getLocStart() const LLVM_READONLY {
+ return IntroducerRange.getBegin();
+ }
+ SourceLocation getLocEnd() const LLVM_READONLY { return ClosingBrace; }
+
+ child_range children() {
+ // Includes initialization exprs plus body stmt
+ return child_range(getStoredStmts(), getStoredStmts() + NumCaptures + 1);
+ }
+
+ friend TrailingObjects;
+ friend class ASTStmtReader;
+ friend class ASTStmtWriter;
+};
+
+/// An expression "T()" which creates a value-initialized rvalue of type
+/// T, which is a non-class type. See (C++98 [5.2.3p2]).
+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, Type->isInstantiationDependentType(),
+ Type->containsUnexpandedParameterPack()),
+ RParenLoc(rParenLoc), TypeInfo(TypeInfo) {}
+
+ explicit CXXScalarValueInitExpr(EmptyShell Shell)
+ : Expr(CXXScalarValueInitExprClass, Shell) { }
+
+ TypeSourceInfo *getTypeSourceInfo() const {
+ return TypeInfo;
+ }
+
+ SourceLocation getRParenLoc() const { return RParenLoc; }
+
+ SourceLocation getLocStart() const LLVM_READONLY;
+ SourceLocation getLocEnd() const LLVM_READONLY { return RParenLoc; }
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == CXXScalarValueInitExprClass;
+ }
+
+ // Iterators
+ child_range children() {
+ return child_range(child_iterator(), child_iterator());
+ }
+};
+
+/// \brief Represents a new-expression for memory allocation and constructor
+/// calls, e.g: "new CXXNewExpr(foo)".
+class CXXNewExpr : public Expr {
+ /// Contains an optional array size expression, an optional initialization
+ /// expression, and any number of optional placement arguments, in that order.
+ Stmt **SubExprs;
+ /// \brief Points to the allocation function used.
+ FunctionDecl *OperatorNew;
+ /// \brief Points to the deallocation function used in case of error. May be
+ /// null.
+ FunctionDecl *OperatorDelete;
+
+ /// \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;
+
+ /// \brief Range of the entire new expression.
+ SourceRange Range;
+
+ /// \brief Source-range of a paren-delimited initializer.
+ SourceRange DirectInitRange;
+
+ /// Was the usage ::new, i.e. is the global new to be used?
+ bool GlobalNew : 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 : 13;
+ /// What kind of initializer do we have? Could be none, parens, or braces.
+ /// In storage, we distinguish between "none, and no initializer expr", and
+ /// "none, but an implicit initializer expr".
+ unsigned StoredInitializationStyle : 2;
+
+ friend class ASTStmtReader;
+ friend class ASTStmtWriter;
+public:
+ enum InitializationStyle {
+ NoInit, ///< New-expression has no initializer as written.
+ CallInit, ///< New-expression has a C++98 paren-delimited initializer.
+ ListInit ///< New-expression has a C++11 list-initializer.
+ };
+
+ CXXNewExpr(const ASTContext &C, bool globalNew, FunctionDecl *operatorNew,
+ FunctionDecl *operatorDelete, bool usualArrayDeleteWantsSize,
+ ArrayRef<Expr*> placementArgs,
+ SourceRange typeIdParens, Expr *arraySize,
+ InitializationStyle initializationStyle, Expr *initializer,
+ QualType ty, TypeSourceInfo *AllocatedTypeInfo,
+ SourceRange Range, SourceRange directInitRange);
+ explicit CXXNewExpr(EmptyShell Shell)
+ : Expr(CXXNewExprClass, Shell), SubExprs(nullptr) { }
+
+ void AllocateArgsArray(const ASTContext &C, bool isArray,
+ unsigned numPlaceArgs, bool hasInitializer);
+
+ QualType getAllocatedType() const {
+ assert(getType()->isPointerType());
+ return getType()->getAs<PointerType>()->getPointeeType();
+ }
+
+ TypeSourceInfo *getAllocatedTypeSourceInfo() const {
+ return AllocatedTypeInfo;
+ }
+
+ /// \brief True if the allocation result needs to be null-checked.
+ ///
+ /// C++11 [expr.new]p13:
+ /// If the allocation function returns null, initialization shall
+ /// not be done, the deallocation function shall not be called,
+ /// and the value of the new-expression shall be null.
+ ///
+ /// C++ DR1748:
+ /// If the allocation function is a reserved placement allocation
+ /// function that returns null, the behavior is undefined.
+ ///
+ /// An allocation function is not allowed to return null unless it
+ /// has a non-throwing exception-specification. The '03 rule is
+ /// identical except that the definition of a non-throwing
+ /// exception specification is just "is it throw()?".
+ bool shouldNullCheckAllocation(const ASTContext &Ctx) const;
+
+ FunctionDecl *getOperatorNew() const { return OperatorNew; }
+ void setOperatorNew(FunctionDecl *D) { OperatorNew = D; }
+ FunctionDecl *getOperatorDelete() const { return OperatorDelete; }
+ void setOperatorDelete(FunctionDecl *D) { OperatorDelete = D; }
+
+ bool isArray() const { return Array; }
+ Expr *getArraySize() {
+ return Array ? cast<Expr>(SubExprs[0]) : nullptr;
+ }
+ const Expr *getArraySize() const {
+ return Array ? cast<Expr>(SubExprs[0]) : nullptr;
+ }
+
+ unsigned getNumPlacementArgs() const { return NumPlacementArgs; }
+ Expr **getPlacementArgs() {
+ return reinterpret_cast<Expr **>(SubExprs + Array + hasInitializer());
+ }
+
+ Expr *getPlacementArg(unsigned i) {
+ assert(i < NumPlacementArgs && "Index out of range");
+ return getPlacementArgs()[i];
+ }
+ const Expr *getPlacementArg(unsigned i) const {
+ assert(i < NumPlacementArgs && "Index out of range");
+ return const_cast<CXXNewExpr*>(this)->getPlacementArg(i);
+ }
+
+ bool isParenTypeId() const { return TypeIdParens.isValid(); }
+ SourceRange getTypeIdParens() const { return TypeIdParens; }
+
+ bool isGlobalNew() const { return GlobalNew; }
+
+ /// \brief Whether this new-expression has any initializer at all.
+ bool hasInitializer() const { return StoredInitializationStyle > 0; }
+
+ /// \brief The kind of initializer this new-expression has.
+ InitializationStyle getInitializationStyle() const {
+ if (StoredInitializationStyle == 0)
+ return NoInit;
+ return static_cast<InitializationStyle>(StoredInitializationStyle-1);
+ }
+
+ /// \brief The initializer of this new-expression.
+ Expr *getInitializer() {
+ return hasInitializer() ? cast<Expr>(SubExprs[Array]) : nullptr;
+ }
+ const Expr *getInitializer() const {
+ return hasInitializer() ? cast<Expr>(SubExprs[Array]) : nullptr;
+ }
+
+ /// \brief Returns the CXXConstructExpr from this new-expression, or null.
+ const CXXConstructExpr* getConstructExpr() const {
+ return dyn_cast_or_null<CXXConstructExpr>(getInitializer());
+ }
+
+ /// 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;
+ }
+
+ typedef ExprIterator arg_iterator;
+ typedef ConstExprIterator const_arg_iterator;
+
+ llvm::iterator_range<arg_iterator> placement_arguments() {
+ return llvm::make_range(placement_arg_begin(), placement_arg_end());
+ }
+
+ llvm::iterator_range<const_arg_iterator> placement_arguments() const {
+ return llvm::make_range(placement_arg_begin(), placement_arg_end());
+ }
+
+ arg_iterator placement_arg_begin() {
+ return SubExprs + Array + hasInitializer();
+ }
+ arg_iterator placement_arg_end() {
+ return SubExprs + Array + hasInitializer() + getNumPlacementArgs();
+ }
+ const_arg_iterator placement_arg_begin() const {
+ return SubExprs + Array + hasInitializer();
+ }
+ const_arg_iterator placement_arg_end() const {
+ return SubExprs + Array + hasInitializer() + getNumPlacementArgs();
+ }
+
+ typedef Stmt **raw_arg_iterator;
+ raw_arg_iterator raw_arg_begin() { return SubExprs; }
+ raw_arg_iterator raw_arg_end() {
+ return SubExprs + Array + hasInitializer() + getNumPlacementArgs();
+ }
+ const_arg_iterator raw_arg_begin() const { return SubExprs; }
+ const_arg_iterator raw_arg_end() const {
+ return SubExprs + Array + hasInitializer() + getNumPlacementArgs();
+ }
+
+ SourceLocation getStartLoc() const { return Range.getBegin(); }
+ SourceLocation getEndLoc() const { return Range.getEnd(); }
+
+ SourceRange getDirectInitRange() const { return DirectInitRange; }
+
+ SourceRange getSourceRange() const LLVM_READONLY {
+ return Range;
+ }
+ SourceLocation getLocStart() const LLVM_READONLY { return getStartLoc(); }
+ SourceLocation getLocEnd() const LLVM_READONLY { return getEndLoc(); }
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == CXXNewExprClass;
+ }
+
+ // Iterators
+ child_range children() {
+ return child_range(raw_arg_begin(), raw_arg_end());
+ }
+};
+
+/// \brief Represents a \c delete expression for memory deallocation and
+/// destructor calls, e.g. "delete[] pArray".
+class CXXDeleteExpr : public Expr {
+ /// 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;
+ /// 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;
+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->isInstantiationDependent(),
+ arg->containsUnexpandedParameterPack()),
+ OperatorDelete(operatorDelete), Argument(arg), Loc(loc),
+ GlobalDelete(globalDelete),
+ ArrayForm(arrayForm), ArrayFormAsWritten(arrayFormAsWritten),
+ UsualArrayDeleteWantsSize(usualArrayDeleteWantsSize) { }
+ explicit CXXDeleteExpr(EmptyShell Shell)
+ : Expr(CXXDeleteExprClass, Shell), OperatorDelete(nullptr),
+ Argument(nullptr) {}
+
+ 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;
+
+ SourceLocation getLocStart() const LLVM_READONLY { return Loc; }
+ SourceLocation getLocEnd() const LLVM_READONLY {return Argument->getLocEnd();}
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == CXXDeleteExprClass;
+ }
+
+ // Iterators
+ child_range children() { return child_range(&Argument, &Argument+1); }
+
+ friend class ASTStmtReader;
+};
+
+/// \brief Stores 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.
+ NestedNameSpecifierLoc QualifierLoc;
+
+ /// \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;
+
+ friend class ASTStmtReader;
+
+public:
+ CXXPseudoDestructorExpr(const ASTContext &Context,
+ Expr *Base, bool isArrow, SourceLocation OperatorLoc,
+ NestedNameSpecifierLoc QualifierLoc,
+ TypeSourceInfo *ScopeType,
+ SourceLocation ColonColonLoc,
+ SourceLocation TildeLoc,
+ PseudoDestructorTypeStorage DestroyedType);
+
+ explicit CXXPseudoDestructorExpr(EmptyShell Shell)
+ : Expr(CXXPseudoDestructorExprClass, Shell),
+ Base(nullptr), IsArrow(false), QualifierLoc(), ScopeType(nullptr) { }
+
+ 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 QualifierLoc.hasQualifier(); }
+
+ /// \brief Retrieves the nested-name-specifier that qualifies the type name,
+ /// with source-location information.
+ NestedNameSpecifierLoc getQualifierLoc() const { return QualifierLoc; }
+
+ /// \brief If the member name was qualified, retrieves the
+ /// nested-name-specifier that precedes the member name. Otherwise, returns
+ /// null.
+ NestedNameSpecifier *getQualifier() const {
+ return QualifierLoc.getNestedNameSpecifier();
+ }
+
+ /// \brief Determine whether this pseudo-destructor expression was written
+ /// using an '->' (otherwise, it used a '.').
+ bool isArrow() const { return IsArrow; }
+
+ /// \brief Retrieve the location of the '.' or '->' operator.
+ SourceLocation getOperatorLoc() const { return OperatorLoc; }
+
+ /// \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; }
+
+ /// \brief Retrieve the location of the '::' in a qualified pseudo-destructor
+ /// expression.
+ SourceLocation getColonColonLoc() const { return ColonColonLoc; }
+
+ /// \brief Retrieve the location of the '~'.
+ SourceLocation getTildeLoc() const { return TildeLoc; }
+
+ /// \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);
+ }
+
+ SourceLocation getLocStart() const LLVM_READONLY {return Base->getLocStart();}
+ SourceLocation getLocEnd() const LLVM_READONLY;
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == CXXPseudoDestructorExprClass;
+ }
+
+ // Iterators
+ child_range children() { return child_range(&Base, &Base + 1); }
+};
+
+/// \brief A type trait used in the implementation of various C++11 and
+/// Library TR1 trait templates.
+///
+/// \code
+/// __is_pod(int) == true
+/// __is_enum(std::string) == false
+/// __is_trivially_constructible(vector<int>, int*, int*)
+/// \endcode
+class TypeTraitExpr final
+ : public Expr,
+ private llvm::TrailingObjects<TypeTraitExpr, TypeSourceInfo *> {
+ /// \brief The location of the type trait keyword.
+ SourceLocation Loc;
+
+ /// \brief The location of the closing parenthesis.
+ SourceLocation RParenLoc;
+
+ // Note: The TypeSourceInfos for the arguments are allocated after the
+ // TypeTraitExpr.
+
+ TypeTraitExpr(QualType T, SourceLocation Loc, TypeTrait Kind,
+ ArrayRef<TypeSourceInfo *> Args,
+ SourceLocation RParenLoc,
+ bool Value);
+
+ TypeTraitExpr(EmptyShell Empty) : Expr(TypeTraitExprClass, Empty) { }
+
+ size_t numTrailingObjects(OverloadToken<TypeSourceInfo *>) const {
+ return getNumArgs();
+ }
+
+public:
+ /// \brief Create a new type trait expression.
+ static TypeTraitExpr *Create(const ASTContext &C, QualType T,
+ SourceLocation Loc, TypeTrait Kind,
+ ArrayRef<TypeSourceInfo *> Args,
+ SourceLocation RParenLoc,
+ bool Value);
+
+ static TypeTraitExpr *CreateDeserialized(const ASTContext &C,
+ unsigned NumArgs);
+
+ /// \brief Determine which type trait this expression uses.
+ TypeTrait getTrait() const {
+ return static_cast<TypeTrait>(TypeTraitExprBits.Kind);
+ }
+
+ bool getValue() const {
+ assert(!isValueDependent());
+ return TypeTraitExprBits.Value;
+ }
+
+ /// \brief Determine the number of arguments to this type trait.
+ unsigned getNumArgs() const { return TypeTraitExprBits.NumArgs; }
+
+ /// \brief Retrieve the Ith argument.
+ TypeSourceInfo *getArg(unsigned I) const {
+ assert(I < getNumArgs() && "Argument out-of-range");
+ return getArgs()[I];
+ }
+
+ /// \brief Retrieve the argument types.
+ ArrayRef<TypeSourceInfo *> getArgs() const {
+ return llvm::makeArrayRef(getTrailingObjects<TypeSourceInfo *>(),
+ getNumArgs());
+ }
+
+ SourceLocation getLocStart() const LLVM_READONLY { return Loc; }
+ SourceLocation getLocEnd() const LLVM_READONLY { return RParenLoc; }
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == TypeTraitExprClass;
+ }
+
+ // Iterators
+ child_range children() {
+ return child_range(child_iterator(), child_iterator());
+ }
+
+ friend TrailingObjects;
+ friend class ASTStmtReader;
+ friend class ASTStmtWriter;
+};
+
+/// \brief An Embarcadero array type trait, as used in the implementation of
+/// __array_rank and __array_extent.
+///
+/// Example:
+/// \code
+/// __array_rank(int[10][20]) == 2
+/// __array_extent(int, 1) == 20
+/// \endcode
+class ArrayTypeTraitExpr : public Expr {
+ virtual void anchor();
+
+ /// \brief The trait. An ArrayTypeTrait enum in MSVC compat unsigned.
+ unsigned ATT : 2;
+
+ /// \brief The value of the type trait. Unspecified if dependent.
+ uint64_t Value;
+
+ /// \brief The array dimension being queried, or -1 if not used.
+ Expr *Dimension;
+
+ /// \brief The location of the type trait keyword.
+ SourceLocation Loc;
+
+ /// \brief The location of the closing paren.
+ SourceLocation RParen;
+
+ /// \brief The type being queried.
+ TypeSourceInfo *QueriedType;
+
+public:
+ ArrayTypeTraitExpr(SourceLocation loc, ArrayTypeTrait att,
+ TypeSourceInfo *queried, uint64_t value,
+ Expr *dimension, SourceLocation rparen, QualType ty)
+ : Expr(ArrayTypeTraitExprClass, ty, VK_RValue, OK_Ordinary,
+ false, queried->getType()->isDependentType(),
+ (queried->getType()->isInstantiationDependentType() ||
+ (dimension && dimension->isInstantiationDependent())),
+ queried->getType()->containsUnexpandedParameterPack()),
+ ATT(att), Value(value), Dimension(dimension),
+ Loc(loc), RParen(rparen), QueriedType(queried) { }
+
+
+ explicit ArrayTypeTraitExpr(EmptyShell Empty)
+ : Expr(ArrayTypeTraitExprClass, Empty), ATT(0), Value(false),
+ QueriedType() { }
+
+ virtual ~ArrayTypeTraitExpr() { }
+
+ SourceLocation getLocStart() const LLVM_READONLY { return Loc; }
+ SourceLocation getLocEnd() const LLVM_READONLY { return RParen; }
+
+ ArrayTypeTrait getTrait() const { return static_cast<ArrayTypeTrait>(ATT); }
+
+ QualType getQueriedType() const { return QueriedType->getType(); }
+
+ TypeSourceInfo *getQueriedTypeSourceInfo() const { return QueriedType; }
+
+ uint64_t getValue() const { assert(!isTypeDependent()); return Value; }
+
+ Expr *getDimensionExpression() const { return Dimension; }
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == ArrayTypeTraitExprClass;
+ }
+
+ // Iterators
+ child_range children() {
+ return child_range(child_iterator(), child_iterator());
+ }
+
+ friend class ASTStmtReader;
+};
+
+/// \brief An expression trait intrinsic.
+///
+/// Example:
+/// \code
+/// __is_lvalue_expr(std::cout) == true
+/// __is_lvalue_expr(1) == false
+/// \endcode
+class ExpressionTraitExpr : public Expr {
+ /// \brief The trait. A ExpressionTrait enum in MSVC compatible unsigned.
+ unsigned ET : 31;
+ /// \brief The value of the type trait. Unspecified if dependent.
+ bool Value : 1;
+
+ /// \brief The location of the type trait keyword.
+ SourceLocation Loc;
+
+ /// \brief The location of the closing paren.
+ SourceLocation RParen;
+
+ /// \brief The expression being queried.
+ Expr* QueriedExpression;
+public:
+ ExpressionTraitExpr(SourceLocation loc, ExpressionTrait et,
+ Expr *queried, bool value,
+ SourceLocation rparen, QualType resultType)
+ : Expr(ExpressionTraitExprClass, resultType, VK_RValue, OK_Ordinary,
+ false, // Not type-dependent
+ // Value-dependent if the argument is type-dependent.
+ queried->isTypeDependent(),
+ queried->isInstantiationDependent(),
+ queried->containsUnexpandedParameterPack()),
+ ET(et), Value(value), Loc(loc), RParen(rparen),
+ QueriedExpression(queried) { }
+
+ explicit ExpressionTraitExpr(EmptyShell Empty)
+ : Expr(ExpressionTraitExprClass, Empty), ET(0), Value(false),
+ QueriedExpression() { }
+
+ SourceLocation getLocStart() const LLVM_READONLY { return Loc; }
+ SourceLocation getLocEnd() const LLVM_READONLY { return RParen; }
+
+ ExpressionTrait getTrait() const { return static_cast<ExpressionTrait>(ET); }
+
+ Expr *getQueriedExpression() const { return QueriedExpression; }
+
+ bool getValue() const { return Value; }
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == ExpressionTraitExprClass;
+ }
+
+ // Iterators
+ child_range children() {
+ return child_range(child_iterator(), child_iterator());
+ }
+
+ friend class ASTStmtReader;
+};
+
+
+/// \brief A reference to an overloaded function set, either an
+/// \c UnresolvedLookupExpr or an \c UnresolvedMemberExpr.
+class OverloadExpr : public Expr {
+ /// \brief The common name of these declarations.
+ DeclarationNameInfo NameInfo;
+
+ /// \brief The nested-name-specifier that qualifies the name, if any.
+ NestedNameSpecifierLoc QualifierLoc;
+
+ /// 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;
+
+protected:
+ /// \brief Whether the name includes info for explicit template
+ /// keyword and arguments.
+ bool HasTemplateKWAndArgsInfo;
+
+ /// \brief Return the optional template keyword and arguments info.
+ ASTTemplateKWAndArgsInfo *
+ getTrailingASTTemplateKWAndArgsInfo(); // defined far below.
+
+ /// \brief Return the optional template keyword and arguments info.
+ const ASTTemplateKWAndArgsInfo *getTrailingASTTemplateKWAndArgsInfo() const {
+ return const_cast<OverloadExpr *>(this)
+ ->getTrailingASTTemplateKWAndArgsInfo();
+ }
+
+ /// Return the optional template arguments.
+ TemplateArgumentLoc *getTrailingTemplateArgumentLoc(); // defined far below
+
+ OverloadExpr(StmtClass K, const ASTContext &C,
+ NestedNameSpecifierLoc QualifierLoc,
+ SourceLocation TemplateKWLoc,
+ const DeclarationNameInfo &NameInfo,
+ const TemplateArgumentListInfo *TemplateArgs,
+ UnresolvedSetIterator Begin, UnresolvedSetIterator End,
+ bool KnownDependent,
+ bool KnownInstantiationDependent,
+ bool KnownContainsUnexpandedParameterPack);
+
+ OverloadExpr(StmtClass K, EmptyShell Empty)
+ : Expr(K, Empty), QualifierLoc(), Results(nullptr), NumResults(0),
+ HasTemplateKWAndArgsInfo(false) { }
+
+ void initializeResults(const ASTContext &C,
+ UnresolvedSetIterator Begin,
+ UnresolvedSetIterator End);
+
+public:
+ struct FindResult {
+ OverloadExpr *Expression;
+ bool IsAddressOfOperand;
+ bool HasFormOfMemberPointer;
+ };
+
+ /// \brief Finds the overloaded expression in the given expression \p E 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;
+ }
+
+ /// \brief 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);
+ }
+ llvm::iterator_range<decls_iterator> decls() const {
+ return llvm::make_range(decls_begin(), decls_end());
+ }
+
+ /// \brief Gets the number of declarations in the unresolved set.
+ unsigned getNumDecls() const { return NumResults; }
+
+ /// \brief Gets the full name info.
+ const DeclarationNameInfo &getNameInfo() const { return NameInfo; }
+
+ /// \brief Gets the name looked up.
+ DeclarationName getName() const { return NameInfo.getName(); }
+
+ /// \brief Gets the location of the name.
+ SourceLocation getNameLoc() const { return NameInfo.getLoc(); }
+
+ /// \brief Fetches the nested-name qualifier, if one was given.
+ NestedNameSpecifier *getQualifier() const {
+ return QualifierLoc.getNestedNameSpecifier();
+ }
+
+ /// \brief Fetches the nested-name qualifier with source-location
+ /// information, if one was given.
+ NestedNameSpecifierLoc getQualifierLoc() const { return QualifierLoc; }
+
+ /// \brief Retrieve the location of the template keyword preceding
+ /// this name, if any.
+ SourceLocation getTemplateKeywordLoc() const {
+ if (!HasTemplateKWAndArgsInfo) return SourceLocation();
+ return getTrailingASTTemplateKWAndArgsInfo()->TemplateKWLoc;
+ }
+
+ /// \brief Retrieve the location of the left angle bracket starting the
+ /// explicit template argument list following the name, if any.
+ SourceLocation getLAngleLoc() const {
+ if (!HasTemplateKWAndArgsInfo) return SourceLocation();
+ return getTrailingASTTemplateKWAndArgsInfo()->LAngleLoc;
+ }
+
+ /// \brief Retrieve the location of the right angle bracket ending the
+ /// explicit template argument list following the name, if any.
+ SourceLocation getRAngleLoc() const {
+ if (!HasTemplateKWAndArgsInfo) return SourceLocation();
+ return getTrailingASTTemplateKWAndArgsInfo()->RAngleLoc;
+ }
+
+ /// \brief Determines whether the name was preceded by the template keyword.
+ bool hasTemplateKeyword() const { return getTemplateKeywordLoc().isValid(); }
+
+ /// \brief Determines whether this expression had explicit template arguments.
+ bool hasExplicitTemplateArgs() const { return getLAngleLoc().isValid(); }
+
+ TemplateArgumentLoc const *getTemplateArgs() const {
+ if (!hasExplicitTemplateArgs())
+ return nullptr;
+ return const_cast<OverloadExpr *>(this)->getTrailingTemplateArgumentLoc();
+ }
+
+ unsigned getNumTemplateArgs() const {
+ if (!hasExplicitTemplateArgs())
+ return 0;
+
+ return getTrailingASTTemplateKWAndArgsInfo()->NumTemplateArgs;
+ }
+
+ /// \brief Copies the template arguments into the given structure.
+ void copyTemplateArgumentsInto(TemplateArgumentListInfo &List) const {
+ if (hasExplicitTemplateArgs())
+ getTrailingASTTemplateKWAndArgsInfo()->copyInto(getTemplateArgs(), List);
+ }
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == UnresolvedLookupExprClass ||
+ T->getStmtClass() == UnresolvedMemberExprClass;
+ }
+
+ 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 final
+ : public OverloadExpr,
+ private llvm::TrailingObjects<
+ UnresolvedLookupExpr, ASTTemplateKWAndArgsInfo, TemplateArgumentLoc> {
+ /// 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;
+
+ size_t numTrailingObjects(OverloadToken<ASTTemplateKWAndArgsInfo>) const {
+ return HasTemplateKWAndArgsInfo ? 1 : 0;
+ }
+
+ UnresolvedLookupExpr(const ASTContext &C,
+ CXXRecordDecl *NamingClass,
+ NestedNameSpecifierLoc QualifierLoc,
+ SourceLocation TemplateKWLoc,
+ const DeclarationNameInfo &NameInfo,
+ bool RequiresADL, bool Overloaded,
+ const TemplateArgumentListInfo *TemplateArgs,
+ UnresolvedSetIterator Begin, UnresolvedSetIterator End)
+ : OverloadExpr(UnresolvedLookupExprClass, C, QualifierLoc, TemplateKWLoc,
+ NameInfo, TemplateArgs, Begin, End, false, false, false),
+ RequiresADL(RequiresADL),
+ Overloaded(Overloaded), NamingClass(NamingClass)
+ {}
+
+ UnresolvedLookupExpr(EmptyShell Empty)
+ : OverloadExpr(UnresolvedLookupExprClass, Empty),
+ RequiresADL(false), Overloaded(false), NamingClass(nullptr)
+ {}
+
+ friend TrailingObjects;
+ friend class OverloadExpr;
+ friend class ASTStmtReader;
+
+public:
+ static UnresolvedLookupExpr *Create(const ASTContext &C,
+ CXXRecordDecl *NamingClass,
+ NestedNameSpecifierLoc QualifierLoc,
+ const DeclarationNameInfo &NameInfo,
+ bool ADL, bool Overloaded,
+ UnresolvedSetIterator Begin,
+ UnresolvedSetIterator End) {
+ return new(C) UnresolvedLookupExpr(C, NamingClass, QualifierLoc,
+ SourceLocation(), NameInfo,
+ ADL, Overloaded, nullptr, Begin, End);
+ }
+
+ static UnresolvedLookupExpr *Create(const ASTContext &C,
+ CXXRecordDecl *NamingClass,
+ NestedNameSpecifierLoc QualifierLoc,
+ SourceLocation TemplateKWLoc,
+ const DeclarationNameInfo &NameInfo,
+ bool ADL,
+ const TemplateArgumentListInfo *Args,
+ UnresolvedSetIterator Begin,
+ UnresolvedSetIterator End);
+
+ static UnresolvedLookupExpr *CreateEmpty(const ASTContext &C,
+ bool HasTemplateKWAndArgsInfo,
+ unsigned NumTemplateArgs);
+
+ /// True if this declaration should be extended by
+ /// argument-dependent lookup.
+ bool requiresADL() const { return RequiresADL; }
+
+ /// True if this lookup is overloaded.
+ bool isOverloaded() const { return Overloaded; }
+
+ /// 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; }
+
+ SourceLocation getLocStart() const LLVM_READONLY {
+ if (NestedNameSpecifierLoc l = getQualifierLoc())
+ return l.getBeginLoc();
+ return getNameInfo().getLocStart();
+ }
+ SourceLocation getLocEnd() const LLVM_READONLY {
+ if (hasExplicitTemplateArgs())
+ return getRAngleLoc();
+ return getNameInfo().getLocEnd();
+ }
+
+ child_range children() {
+ return child_range(child_iterator(), child_iterator());
+ }
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == UnresolvedLookupExprClass;
+ }
+};
+
+/// \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 one 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 final
+ : public Expr,
+ private llvm::TrailingObjects<DependentScopeDeclRefExpr,
+ ASTTemplateKWAndArgsInfo,
+ TemplateArgumentLoc> {
+ /// \brief The nested-name-specifier that qualifies this unresolved
+ /// declaration name.
+ NestedNameSpecifierLoc QualifierLoc;
+
+ /// \brief The name of the entity we will be referencing.
+ DeclarationNameInfo NameInfo;
+
+ /// \brief Whether the name includes info for explicit template
+ /// keyword and arguments.
+ bool HasTemplateKWAndArgsInfo;
+
+ size_t numTrailingObjects(OverloadToken<ASTTemplateKWAndArgsInfo>) const {
+ return HasTemplateKWAndArgsInfo ? 1 : 0;
+ }
+
+ DependentScopeDeclRefExpr(QualType T,
+ NestedNameSpecifierLoc QualifierLoc,
+ SourceLocation TemplateKWLoc,
+ const DeclarationNameInfo &NameInfo,
+ const TemplateArgumentListInfo *Args);
+
+public:
+ static DependentScopeDeclRefExpr *Create(const ASTContext &C,
+ NestedNameSpecifierLoc QualifierLoc,
+ SourceLocation TemplateKWLoc,
+ const DeclarationNameInfo &NameInfo,
+ const TemplateArgumentListInfo *TemplateArgs);
+
+ static DependentScopeDeclRefExpr *CreateEmpty(const ASTContext &C,
+ bool HasTemplateKWAndArgsInfo,
+ unsigned NumTemplateArgs);
+
+ /// \brief Retrieve the name that this expression refers to.
+ const DeclarationNameInfo &getNameInfo() const { return NameInfo; }
+
+ /// \brief Retrieve the name that this expression refers to.
+ DeclarationName getDeclName() const { return NameInfo.getName(); }
+
+ /// \brief Retrieve the location of the name within the expression.
+ ///
+ /// For example, in "X<T>::value" this is the location of "value".
+ SourceLocation getLocation() const { return NameInfo.getLoc(); }
+
+ /// \brief Retrieve the nested-name-specifier that qualifies the
+ /// name, with source location information.
+ NestedNameSpecifierLoc getQualifierLoc() const { return QualifierLoc; }
+
+ /// \brief Retrieve the nested-name-specifier that qualifies this
+ /// declaration.
+ NestedNameSpecifier *getQualifier() const {
+ return QualifierLoc.getNestedNameSpecifier();
+ }
+
+ /// \brief Retrieve the location of the template keyword preceding
+ /// this name, if any.
+ SourceLocation getTemplateKeywordLoc() const {
+ if (!HasTemplateKWAndArgsInfo) return SourceLocation();
+ return getTrailingObjects<ASTTemplateKWAndArgsInfo>()->TemplateKWLoc;
+ }
+
+ /// \brief Retrieve the location of the left angle bracket starting the
+ /// explicit template argument list following the name, if any.
+ SourceLocation getLAngleLoc() const {
+ if (!HasTemplateKWAndArgsInfo) return SourceLocation();
+ return getTrailingObjects<ASTTemplateKWAndArgsInfo>()->LAngleLoc;
+ }
+
+ /// \brief Retrieve the location of the right angle bracket ending the
+ /// explicit template argument list following the name, if any.
+ SourceLocation getRAngleLoc() const {
+ if (!HasTemplateKWAndArgsInfo) return SourceLocation();
+ return getTrailingObjects<ASTTemplateKWAndArgsInfo>()->RAngleLoc;
+ }
+
+ /// Determines whether the name was preceded by the template keyword.
+ bool hasTemplateKeyword() const { return getTemplateKeywordLoc().isValid(); }
+
+ /// Determines whether this lookup had explicit template arguments.
+ bool hasExplicitTemplateArgs() const { return getLAngleLoc().isValid(); }
+
+ /// \brief Copies the template arguments (if present) into the given
+ /// structure.
+ void copyTemplateArgumentsInto(TemplateArgumentListInfo &List) const {
+ if (hasExplicitTemplateArgs())
+ getTrailingObjects<ASTTemplateKWAndArgsInfo>()->copyInto(
+ getTrailingObjects<TemplateArgumentLoc>(), List);
+ }
+
+ TemplateArgumentLoc const *getTemplateArgs() const {
+ if (!hasExplicitTemplateArgs())
+ return nullptr;
+
+ return getTrailingObjects<TemplateArgumentLoc>();
+ }
+
+ unsigned getNumTemplateArgs() const {
+ if (!hasExplicitTemplateArgs())
+ return 0;
+
+ return getTrailingObjects<ASTTemplateKWAndArgsInfo>()->NumTemplateArgs;
+ }
+
+ /// Note: getLocStart() is the start of the whole DependentScopeDeclRefExpr,
+ /// and differs from getLocation().getStart().
+ SourceLocation getLocStart() const LLVM_READONLY {
+ return QualifierLoc.getBeginLoc();
+ }
+ SourceLocation getLocEnd() const LLVM_READONLY {
+ if (hasExplicitTemplateArgs())
+ return getRAngleLoc();
+ return getLocation();
+ }
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == DependentScopeDeclRefExprClass;
+ }
+
+ child_range children() {
+ return child_range(child_iterator(), child_iterator());
+ }
+
+ friend TrailingObjects;
+ friend class ASTStmtReader;
+ friend class ASTStmtWriter;
+};
+
+/// Represents an expression -- generally a full-expression -- that
+/// 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 kinds of
+/// expressions can create cleanups, including basically every
+/// call in ARC that returns an Objective-C pointer.
+///
+/// This expression also tracks whether the sub-expression contains a
+/// potentially-evaluated block literal. The lifetime of a block
+/// literal is the extent of the enclosing scope.
+class ExprWithCleanups final
+ : public Expr,
+ private llvm::TrailingObjects<ExprWithCleanups, BlockDecl *> {
+public:
+ /// The type of objects that are kept in the cleanup.
+ /// It's useful to remember the set of blocks; we could also
+ /// remember the set of temporaries, but there's currently
+ /// no need.
+ typedef BlockDecl *CleanupObject;
+
+private:
+ Stmt *SubExpr;
+
+ ExprWithCleanups(EmptyShell, unsigned NumObjects);
+ ExprWithCleanups(Expr *SubExpr, ArrayRef<CleanupObject> Objects);
+
+ friend TrailingObjects;
+ friend class ASTStmtReader;
+
+public:
+ static ExprWithCleanups *Create(const ASTContext &C, EmptyShell empty,
+ unsigned numObjects);
+
+ static ExprWithCleanups *Create(const ASTContext &C, Expr *subexpr,
+ ArrayRef<CleanupObject> objects);
+
+ ArrayRef<CleanupObject> getObjects() const {
+ return llvm::makeArrayRef(getTrailingObjects<CleanupObject>(),
+ getNumObjects());
+ }
+
+ unsigned getNumObjects() const { return ExprWithCleanupsBits.NumObjects; }
+
+ CleanupObject getObject(unsigned i) const {
+ assert(i < getNumObjects() && "Index out of range");
+ return getObjects()[i];
+ }
+
+ Expr *getSubExpr() { return cast<Expr>(SubExpr); }
+ const Expr *getSubExpr() const { return cast<Expr>(SubExpr); }
+
+ /// As with any mutator of the AST, be very careful
+ /// when modifying an existing AST to preserve its invariants.
+ void setSubExpr(Expr *E) { SubExpr = E; }
+
+ SourceLocation getLocStart() const LLVM_READONLY {
+ return SubExpr->getLocStart();
+ }
+ SourceLocation getLocEnd() const LLVM_READONLY { return SubExpr->getLocEnd();}
+
+ // Implement isa/cast/dyncast/etc.
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == ExprWithCleanupsClass;
+ }
+
+ // 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 <tt>T(a1, a2, ..., aN)</tt>,
+/// where \c T is some type and \c a1, \c a2, ..., \c aN are values, and
+/// either \c T is a dependent type or one or more of the <tt>a</tt>'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 final
+ : public Expr,
+ private llvm::TrailingObjects<CXXUnresolvedConstructExpr, 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,
+ ArrayRef<Expr*> Args,
+ SourceLocation RParenLoc);
+
+ CXXUnresolvedConstructExpr(EmptyShell Empty, unsigned NumArgs)
+ : Expr(CXXUnresolvedConstructExprClass, Empty), Type(), NumArgs(NumArgs) { }
+
+ friend TrailingObjects;
+ friend class ASTStmtReader;
+
+public:
+ static CXXUnresolvedConstructExpr *Create(const ASTContext &C,
+ TypeSourceInfo *Type,
+ SourceLocation LParenLoc,
+ ArrayRef<Expr*> Args,
+ SourceLocation RParenLoc);
+
+ static CXXUnresolvedConstructExpr *CreateEmpty(const 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 getTrailingObjects<Expr *>(); }
+ arg_iterator arg_end() { return arg_begin() + NumArgs; }
+
+ typedef const Expr* const * const_arg_iterator;
+ const_arg_iterator arg_begin() const { return getTrailingObjects<Expr *>(); }
+ 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;
+ }
+
+ SourceLocation getLocStart() const LLVM_READONLY;
+ SourceLocation getLocEnd() const LLVM_READONLY {
+ if (!RParenLoc.isValid() && NumArgs > 0)
+ return getArg(NumArgs - 1)->getLocEnd();
+ return RParenLoc;
+ }
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == CXXUnresolvedConstructExprClass;
+ }
+
+ // Iterators
+ child_range children() {
+ Stmt **begin = reinterpret_cast<Stmt **>(arg_begin());
+ 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 final
+ : public Expr,
+ private llvm::TrailingObjects<CXXDependentScopeMemberExpr,
+ ASTTemplateKWAndArgsInfo,
+ TemplateArgumentLoc> {
+ /// \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 info for explicit template
+ /// keyword and arguments.
+ bool HasTemplateKWAndArgsInfo : 1;
+
+ /// \brief The location of the '->' or '.' operator.
+ SourceLocation OperatorLoc;
+
+ /// \brief The nested-name-specifier that precedes the member name, if any.
+ NestedNameSpecifierLoc QualifierLoc;
+
+ /// \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 QualifierLoc, 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;
+
+ size_t numTrailingObjects(OverloadToken<ASTTemplateKWAndArgsInfo>) const {
+ return HasTemplateKWAndArgsInfo ? 1 : 0;
+ }
+
+ CXXDependentScopeMemberExpr(const ASTContext &C, Expr *Base,
+ QualType BaseType, bool IsArrow,
+ SourceLocation OperatorLoc,
+ NestedNameSpecifierLoc QualifierLoc,
+ SourceLocation TemplateKWLoc,
+ NamedDecl *FirstQualifierFoundInScope,
+ DeclarationNameInfo MemberNameInfo,
+ const TemplateArgumentListInfo *TemplateArgs);
+
+public:
+ CXXDependentScopeMemberExpr(const ASTContext &C, Expr *Base,
+ QualType BaseType, bool IsArrow,
+ SourceLocation OperatorLoc,
+ NestedNameSpecifierLoc QualifierLoc,
+ NamedDecl *FirstQualifierFoundInScope,
+ DeclarationNameInfo MemberNameInfo);
+
+ static CXXDependentScopeMemberExpr *
+ Create(const ASTContext &C, Expr *Base, QualType BaseType, bool IsArrow,
+ SourceLocation OperatorLoc, NestedNameSpecifierLoc QualifierLoc,
+ SourceLocation TemplateKWLoc, NamedDecl *FirstQualifierFoundInScope,
+ DeclarationNameInfo MemberNameInfo,
+ const TemplateArgumentListInfo *TemplateArgs);
+
+ static CXXDependentScopeMemberExpr *
+ CreateEmpty(const ASTContext &C, bool HasTemplateKWAndArgsInfo,
+ 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;
+
+ /// \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);
+ }
+
+ QualType getBaseType() const { return BaseType; }
+
+ /// \brief Determine whether this member expression used the '->'
+ /// operator; otherwise, it used the '.' operator.
+ bool isArrow() const { return IsArrow; }
+
+ /// \brief Retrieve the location of the '->' or '.' operator.
+ SourceLocation getOperatorLoc() const { return OperatorLoc; }
+
+ /// \brief Retrieve the nested-name-specifier that qualifies the member
+ /// name.
+ NestedNameSpecifier *getQualifier() const {
+ return QualifierLoc.getNestedNameSpecifier();
+ }
+
+ /// \brief Retrieve the nested-name-specifier that qualifies the member
+ /// name, with source location information.
+ NestedNameSpecifierLoc getQualifierLoc() const { return QualifierLoc; }
+
+
+ /// \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;
+ }
+
+ /// \brief Retrieve the name of the member that this expression
+ /// refers to.
+ const DeclarationNameInfo &getMemberNameInfo() const {
+ return MemberNameInfo;
+ }
+
+ /// \brief Retrieve the name of the member that this expression
+ /// refers to.
+ DeclarationName getMember() const { return MemberNameInfo.getName(); }
+
+ // \brief Retrieve the location of the name of the member that this
+ // expression refers to.
+ SourceLocation getMemberLoc() const { return MemberNameInfo.getLoc(); }
+
+ /// \brief Retrieve the location of the template keyword preceding the
+ /// member name, if any.
+ SourceLocation getTemplateKeywordLoc() const {
+ if (!HasTemplateKWAndArgsInfo) return SourceLocation();
+ return getTrailingObjects<ASTTemplateKWAndArgsInfo>()->TemplateKWLoc;
+ }
+
+ /// \brief Retrieve the location of the left angle bracket starting the
+ /// explicit template argument list following the member name, if any.
+ SourceLocation getLAngleLoc() const {
+ if (!HasTemplateKWAndArgsInfo) return SourceLocation();
+ return getTrailingObjects<ASTTemplateKWAndArgsInfo>()->LAngleLoc;
+ }
+
+ /// \brief Retrieve the location of the right angle bracket ending the
+ /// explicit template argument list following the member name, if any.
+ SourceLocation getRAngleLoc() const {
+ if (!HasTemplateKWAndArgsInfo) return SourceLocation();
+ return getTrailingObjects<ASTTemplateKWAndArgsInfo>()->RAngleLoc;
+ }
+
+ /// Determines whether the member name was preceded by the template keyword.
+ bool hasTemplateKeyword() const { return getTemplateKeywordLoc().isValid(); }
+
+ /// \brief Determines whether this member expression actually had a C++
+ /// template argument list explicitly specified, e.g., x.f<int>.
+ bool hasExplicitTemplateArgs() const { return getLAngleLoc().isValid(); }
+
+ /// \brief Copies the template arguments (if present) into the given
+ /// structure.
+ void copyTemplateArgumentsInto(TemplateArgumentListInfo &List) const {
+ if (hasExplicitTemplateArgs())
+ getTrailingObjects<ASTTemplateKWAndArgsInfo>()->copyInto(
+ getTrailingObjects<TemplateArgumentLoc>(), List);
+ }
+
+ /// \brief Retrieve the template arguments provided as part of this
+ /// template-id.
+ const TemplateArgumentLoc *getTemplateArgs() const {
+ if (!hasExplicitTemplateArgs())
+ return nullptr;
+
+ return getTrailingObjects<TemplateArgumentLoc>();
+ }
+
+ /// \brief Retrieve the number of template arguments provided as part of this
+ /// template-id.
+ unsigned getNumTemplateArgs() const {
+ if (!hasExplicitTemplateArgs())
+ return 0;
+
+ return getTrailingObjects<ASTTemplateKWAndArgsInfo>()->NumTemplateArgs;
+ }
+
+ SourceLocation getLocStart() const LLVM_READONLY {
+ if (!isImplicitAccess())
+ return Base->getLocStart();
+ if (getQualifier())
+ return getQualifierLoc().getBeginLoc();
+ return MemberNameInfo.getBeginLoc();
+ }
+
+ SourceLocation getLocEnd() const LLVM_READONLY {
+ if (hasExplicitTemplateArgs())
+ return getRAngleLoc();
+ return MemberNameInfo.getEndLoc();
+ }
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == CXXDependentScopeMemberExprClass;
+ }
+
+ // Iterators
+ child_range children() {
+ if (isImplicitAccess())
+ return child_range(child_iterator(), child_iterator());
+ return child_range(&Base, &Base + 1);
+ }
+
+ friend TrailingObjects;
+ 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:
+/// \code
+/// struct A {
+/// int a, b;
+/// int explicitAccess() { return this->a + this->A::b; }
+/// int implicitAccess() { return a + A::b; }
+/// };
+/// \endcode
+///
+/// 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 final
+ : public OverloadExpr,
+ private llvm::TrailingObjects<
+ UnresolvedMemberExpr, ASTTemplateKWAndArgsInfo, TemplateArgumentLoc> {
+ /// \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;
+
+ size_t numTrailingObjects(OverloadToken<ASTTemplateKWAndArgsInfo>) const {
+ return HasTemplateKWAndArgsInfo ? 1 : 0;
+ }
+
+ UnresolvedMemberExpr(const ASTContext &C, bool HasUnresolvedUsing,
+ Expr *Base, QualType BaseType, bool IsArrow,
+ SourceLocation OperatorLoc,
+ NestedNameSpecifierLoc QualifierLoc,
+ SourceLocation TemplateKWLoc,
+ const DeclarationNameInfo &MemberNameInfo,
+ const TemplateArgumentListInfo *TemplateArgs,
+ UnresolvedSetIterator Begin, UnresolvedSetIterator End);
+
+ UnresolvedMemberExpr(EmptyShell Empty)
+ : OverloadExpr(UnresolvedMemberExprClass, Empty), IsArrow(false),
+ HasUnresolvedUsing(false), Base(nullptr) { }
+
+ friend TrailingObjects;
+ friend class OverloadExpr;
+ friend class ASTStmtReader;
+
+public:
+ static UnresolvedMemberExpr *
+ Create(const ASTContext &C, bool HasUnresolvedUsing,
+ Expr *Base, QualType BaseType, bool IsArrow,
+ SourceLocation OperatorLoc,
+ NestedNameSpecifierLoc QualifierLoc,
+ SourceLocation TemplateKWLoc,
+ const DeclarationNameInfo &MemberNameInfo,
+ const TemplateArgumentListInfo *TemplateArgs,
+ UnresolvedSetIterator Begin, UnresolvedSetIterator End);
+
+ static UnresolvedMemberExpr *
+ CreateEmpty(const ASTContext &C, bool HasTemplateKWAndArgsInfo,
+ 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;
+
+ /// \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);
+ }
+
+ QualType getBaseType() const { return BaseType; }
+
+ /// \brief Determine whether the lookup results contain an unresolved using
+ /// declaration.
+ bool hasUnresolvedUsing() const { return HasUnresolvedUsing; }
+
+ /// \brief Determine whether this member expression used the '->'
+ /// operator; otherwise, it used the '.' operator.
+ bool isArrow() const { return IsArrow; }
+
+ /// \brief Retrieve the location of the '->' or '.' operator.
+ SourceLocation getOperatorLoc() const { return OperatorLoc; }
+
+ /// \brief Retrieve 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(); }
+
+ /// \brief Retrieve the name of the member that this expression
+ /// refers to.
+ DeclarationName getMemberName() const { return getName(); }
+
+ // \brief Retrieve the location of the name of the member that this
+ // expression refers to.
+ SourceLocation getMemberLoc() const { return getNameLoc(); }
+
+ // \brief Return the preferred location (the member name) for the arrow when
+ // diagnosing a problem with this expression.
+ SourceLocation getExprLoc() const LLVM_READONLY { return getMemberLoc(); }
+
+ SourceLocation getLocStart() const LLVM_READONLY {
+ if (!isImplicitAccess())
+ return Base->getLocStart();
+ if (NestedNameSpecifierLoc l = getQualifierLoc())
+ return l.getBeginLoc();
+ return getMemberNameInfo().getLocStart();
+ }
+ SourceLocation getLocEnd() const LLVM_READONLY {
+ if (hasExplicitTemplateArgs())
+ return getRAngleLoc();
+ return getMemberNameInfo().getLocEnd();
+ }
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == UnresolvedMemberExprClass;
+ }
+
+ // Iterators
+ child_range children() {
+ if (isImplicitAccess())
+ return child_range(child_iterator(), child_iterator());
+ return child_range(&Base, &Base + 1);
+ }
+};
+
+inline ASTTemplateKWAndArgsInfo *
+OverloadExpr::getTrailingASTTemplateKWAndArgsInfo() {
+ if (!HasTemplateKWAndArgsInfo)
+ return nullptr;
+
+ if (isa<UnresolvedLookupExpr>(this))
+ return cast<UnresolvedLookupExpr>(this)
+ ->getTrailingObjects<ASTTemplateKWAndArgsInfo>();
+ else
+ return cast<UnresolvedMemberExpr>(this)
+ ->getTrailingObjects<ASTTemplateKWAndArgsInfo>();
+}
+
+inline TemplateArgumentLoc *OverloadExpr::getTrailingTemplateArgumentLoc() {
+ if (isa<UnresolvedLookupExpr>(this))
+ return cast<UnresolvedLookupExpr>(this)
+ ->getTrailingObjects<TemplateArgumentLoc>();
+ else
+ return cast<UnresolvedMemberExpr>(this)
+ ->getTrailingObjects<TemplateArgumentLoc>();
+}
+
+/// \brief Represents a C++11 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,
+ Val == CT_Dependent || Operand->isInstantiationDependent(),
+ 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); }
+
+ SourceLocation getLocStart() const LLVM_READONLY { return Range.getBegin(); }
+ SourceLocation getLocEnd() const LLVM_READONLY { return Range.getEnd(); }
+ SourceRange getSourceRange() const LLVM_READONLY { return Range; }
+
+ bool getValue() const { return Value; }
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == CXXNoexceptExprClass;
+ }
+
+ // Iterators
+ child_range children() { return child_range(&Operand, &Operand + 1); }
+};
+
+/// \brief Represents a C++11 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,
+ Optional<unsigned> NumExpansions)
+ : Expr(PackExpansionExprClass, T, Pattern->getValueKind(),
+ Pattern->getObjectKind(), /*TypeDependent=*/true,
+ /*ValueDependent=*/true, /*InstantiationDependent=*/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.
+ Optional<unsigned> getNumExpansions() const {
+ if (NumExpansions)
+ return NumExpansions - 1;
+
+ return None;
+ }
+
+ SourceLocation getLocStart() const LLVM_READONLY {
+ return Pattern->getLocStart();
+ }
+ SourceLocation getLocEnd() const LLVM_READONLY { return EllipsisLoc; }
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == PackExpansionExprClass;
+ }
+
+ // Iterators
+ child_range children() {
+ return child_range(&Pattern, &Pattern + 1);
+ }
+};
+
+
+/// \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 final
+ : public Expr,
+ private llvm::TrailingObjects<SizeOfPackExpr, TemplateArgument> {
+ /// \brief The location of the \c 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 not value-dependent, this is the length of
+ /// the pack. When the expression was parsed rather than instantiated
+ /// (and thus is value-dependent), this is zero.
+ ///
+ /// After partial substitution into a sizeof...(X) expression (for instance,
+ /// within an alias template or during function template argument deduction),
+ /// we store a trailing array of partially-substituted TemplateArguments,
+ /// and this is the length of that array.
+ unsigned Length;
+
+ /// \brief The parameter pack.
+ NamedDecl *Pack;
+
+ friend TrailingObjects;
+ friend class ASTStmtReader;
+ friend class ASTStmtWriter;
+
+ /// \brief Create an expression that computes the length of
+ /// the given parameter pack.
+ SizeOfPackExpr(QualType SizeType, SourceLocation OperatorLoc, NamedDecl *Pack,
+ SourceLocation PackLoc, SourceLocation RParenLoc,
+ Optional<unsigned> Length, ArrayRef<TemplateArgument> PartialArgs)
+ : Expr(SizeOfPackExprClass, SizeType, VK_RValue, OK_Ordinary,
+ /*TypeDependent=*/false, /*ValueDependent=*/!Length,
+ /*InstantiationDependent=*/!Length,
+ /*ContainsUnexpandedParameterPack=*/false),
+ OperatorLoc(OperatorLoc), PackLoc(PackLoc), RParenLoc(RParenLoc),
+ Length(Length ? *Length : PartialArgs.size()), Pack(Pack) {
+ assert((!Length || PartialArgs.empty()) &&
+ "have partial args for non-dependent sizeof... expression");
+ TemplateArgument *Args = getTrailingObjects<TemplateArgument>();
+ std::uninitialized_copy(PartialArgs.begin(), PartialArgs.end(), Args);
+ }
+
+ /// \brief Create an empty expression.
+ SizeOfPackExpr(EmptyShell Empty, unsigned NumPartialArgs)
+ : Expr(SizeOfPackExprClass, Empty), Length(NumPartialArgs), Pack() {}
+
+public:
+ static SizeOfPackExpr *Create(ASTContext &Context, SourceLocation OperatorLoc,
+ NamedDecl *Pack, SourceLocation PackLoc,
+ SourceLocation RParenLoc,
+ Optional<unsigned> Length = None,
+ ArrayRef<TemplateArgument> PartialArgs = None);
+ static SizeOfPackExpr *CreateDeserialized(ASTContext &Context,
+ unsigned NumPartialArgs);
+
+ /// \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;
+ }
+
+ /// \brief Determine whether this represents a partially-substituted sizeof...
+ /// expression, such as is produced for:
+ ///
+ /// template<typename ...Ts> using X = int[sizeof...(Ts)];
+ /// template<typename ...Us> void f(X<Us..., 1, 2, 3, Us...>);
+ bool isPartiallySubstituted() const {
+ return isValueDependent() && Length;
+ }
+
+ /// \brief Get
+ ArrayRef<TemplateArgument> getPartialArguments() const {
+ assert(isPartiallySubstituted());
+ const TemplateArgument *Args = getTrailingObjects<TemplateArgument>();
+ return llvm::makeArrayRef(Args, Args + Length);
+ }
+
+ SourceLocation getLocStart() const LLVM_READONLY { return OperatorLoc; }
+ SourceLocation getLocEnd() const LLVM_READONLY { return RParenLoc; }
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == SizeOfPackExprClass;
+ }
+
+ // Iterators
+ child_range children() {
+ return child_range(child_iterator(), child_iterator());
+ }
+};
+
+/// \brief Represents a reference to a non-type template parameter
+/// that has been substituted with a template argument.
+class SubstNonTypeTemplateParmExpr : public Expr {
+ /// \brief The replaced parameter.
+ NonTypeTemplateParmDecl *Param;
+
+ /// \brief The replacement expression.
+ Stmt *Replacement;
+
+ /// \brief The location of the non-type template parameter reference.
+ SourceLocation NameLoc;
+
+ friend class ASTReader;
+ friend class ASTStmtReader;
+ explicit SubstNonTypeTemplateParmExpr(EmptyShell Empty)
+ : Expr(SubstNonTypeTemplateParmExprClass, Empty) { }
+
+public:
+ SubstNonTypeTemplateParmExpr(QualType type,
+ ExprValueKind valueKind,
+ SourceLocation loc,
+ NonTypeTemplateParmDecl *param,
+ Expr *replacement)
+ : Expr(SubstNonTypeTemplateParmExprClass, type, valueKind, OK_Ordinary,
+ replacement->isTypeDependent(), replacement->isValueDependent(),
+ replacement->isInstantiationDependent(),
+ replacement->containsUnexpandedParameterPack()),
+ Param(param), Replacement(replacement), NameLoc(loc) {}
+
+ SourceLocation getNameLoc() const { return NameLoc; }
+ SourceLocation getLocStart() const LLVM_READONLY { return NameLoc; }
+ SourceLocation getLocEnd() const LLVM_READONLY { return NameLoc; }
+
+ Expr *getReplacement() const { return cast<Expr>(Replacement); }
+
+ NonTypeTemplateParmDecl *getParameter() const { return Param; }
+
+ static bool classof(const Stmt *s) {
+ return s->getStmtClass() == SubstNonTypeTemplateParmExprClass;
+ }
+
+ // Iterators
+ child_range children() { return child_range(&Replacement, &Replacement+1); }
+};
+
+/// \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 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 ASTReader;
+ friend class ASTStmtReader;
+ explicit SubstNonTypeTemplateParmPackExpr(EmptyShell Empty)
+ : Expr(SubstNonTypeTemplateParmPackExprClass, Empty) { }
+
+public:
+ SubstNonTypeTemplateParmPackExpr(QualType T,
+ NonTypeTemplateParmDecl *Param,
+ SourceLocation NameLoc,
+ const TemplateArgument &ArgPack);
+
+ /// \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;
+
+ SourceLocation getLocStart() const LLVM_READONLY { return NameLoc; }
+ SourceLocation getLocEnd() const LLVM_READONLY { return NameLoc; }
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == SubstNonTypeTemplateParmPackExprClass;
+ }
+
+ // Iterators
+ child_range children() {
+ return child_range(child_iterator(), child_iterator());
+ }
+};
+
+/// \brief Represents a reference to a function parameter pack that has been
+/// substituted but not yet expanded.
+///
+/// When a pack expansion contains multiple parameter packs at different levels,
+/// this node is used to represent a function parameter pack at an outer level
+/// which we have already substituted to refer to expanded parameters, but where
+/// the containing pack expansion cannot yet be expanded.
+///
+/// \code
+/// template<typename...Ts> struct S {
+/// template<typename...Us> auto f(Ts ...ts) -> decltype(g(Us(ts)...));
+/// };
+/// template struct S<int, int>;
+/// \endcode
+class FunctionParmPackExpr final
+ : public Expr,
+ private llvm::TrailingObjects<FunctionParmPackExpr, ParmVarDecl *> {
+ /// \brief The function parameter pack which was referenced.
+ ParmVarDecl *ParamPack;
+
+ /// \brief The location of the function parameter pack reference.
+ SourceLocation NameLoc;
+
+ /// \brief The number of expansions of this pack.
+ unsigned NumParameters;
+
+ FunctionParmPackExpr(QualType T, ParmVarDecl *ParamPack,
+ SourceLocation NameLoc, unsigned NumParams,
+ ParmVarDecl *const *Params);
+
+ friend TrailingObjects;
+ friend class ASTReader;
+ friend class ASTStmtReader;
+
+public:
+ static FunctionParmPackExpr *Create(const ASTContext &Context, QualType T,
+ ParmVarDecl *ParamPack,
+ SourceLocation NameLoc,
+ ArrayRef<ParmVarDecl *> Params);
+ static FunctionParmPackExpr *CreateEmpty(const ASTContext &Context,
+ unsigned NumParams);
+
+ /// \brief Get the parameter pack which this expression refers to.
+ ParmVarDecl *getParameterPack() const { return ParamPack; }
+
+ /// \brief Get the location of the parameter pack.
+ SourceLocation getParameterPackLocation() const { return NameLoc; }
+
+ /// \brief Iterators over the parameters which the parameter pack expanded
+ /// into.
+ typedef ParmVarDecl * const *iterator;
+ iterator begin() const { return getTrailingObjects<ParmVarDecl *>(); }
+ iterator end() const { return begin() + NumParameters; }
+
+ /// \brief Get the number of parameters in this parameter pack.
+ unsigned getNumExpansions() const { return NumParameters; }
+
+ /// \brief Get an expansion of the parameter pack by index.
+ ParmVarDecl *getExpansion(unsigned I) const { return begin()[I]; }
+
+ SourceLocation getLocStart() const LLVM_READONLY { return NameLoc; }
+ SourceLocation getLocEnd() const LLVM_READONLY { return NameLoc; }
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == FunctionParmPackExprClass;
+ }
+
+ child_range children() {
+ return child_range(child_iterator(), child_iterator());
+ }
+};
+
+/// \brief Represents a prvalue temporary that is written into memory so that
+/// a reference can bind to it.
+///
+/// Prvalue expressions are materialized when they need to have an address
+/// in memory for a reference to bind to. This happens when binding a
+/// reference to the result of a conversion, e.g.,
+///
+/// \code
+/// const int &r = 1.0;
+/// \endcode
+///
+/// Here, 1.0 is implicitly converted to an \c int. That resulting \c int is
+/// then materialized via a \c MaterializeTemporaryExpr, and the reference
+/// binds to the temporary. \c MaterializeTemporaryExprs are always glvalues
+/// (either an lvalue or an xvalue, depending on the kind of reference binding
+/// to it), maintaining the invariant that references always bind to glvalues.
+///
+/// Reference binding and copy-elision can both extend the lifetime of a
+/// temporary. When either happens, the expression will also track the
+/// declaration which is responsible for the lifetime extension.
+class MaterializeTemporaryExpr : public Expr {
+private:
+ struct ExtraState {
+ /// \brief The temporary-generating expression whose value will be
+ /// materialized.
+ Stmt *Temporary;
+
+ /// \brief The declaration which lifetime-extended this reference, if any.
+ /// Either a VarDecl, or (for a ctor-initializer) a FieldDecl.
+ const ValueDecl *ExtendingDecl;
+
+ unsigned ManglingNumber;
+ };
+ llvm::PointerUnion<Stmt *, ExtraState *> State;
+
+ friend class ASTStmtReader;
+ friend class ASTStmtWriter;
+
+ void initializeExtraState(const ValueDecl *ExtendedBy,
+ unsigned ManglingNumber);
+
+public:
+ MaterializeTemporaryExpr(QualType T, Expr *Temporary,
+ bool BoundToLvalueReference)
+ : Expr(MaterializeTemporaryExprClass, T,
+ BoundToLvalueReference? VK_LValue : VK_XValue, OK_Ordinary,
+ Temporary->isTypeDependent(), Temporary->isValueDependent(),
+ Temporary->isInstantiationDependent(),
+ Temporary->containsUnexpandedParameterPack()),
+ State(Temporary) {}
+
+ MaterializeTemporaryExpr(EmptyShell Empty)
+ : Expr(MaterializeTemporaryExprClass, Empty) { }
+
+ Stmt *getTemporary() const {
+ return State.is<Stmt *>() ? State.get<Stmt *>()
+ : State.get<ExtraState *>()->Temporary;
+ }
+
+ /// \brief Retrieve the temporary-generating subexpression whose value will
+ /// be materialized into a glvalue.
+ Expr *GetTemporaryExpr() const { return static_cast<Expr *>(getTemporary()); }
+
+ /// \brief Retrieve the storage duration for the materialized temporary.
+ StorageDuration getStorageDuration() const {
+ const ValueDecl *ExtendingDecl = getExtendingDecl();
+ if (!ExtendingDecl)
+ return SD_FullExpression;
+ // FIXME: This is not necessarily correct for a temporary materialized
+ // within a default initializer.
+ if (isa<FieldDecl>(ExtendingDecl))
+ return SD_Automatic;
+ return cast<VarDecl>(ExtendingDecl)->getStorageDuration();
+ }
+
+ /// \brief Get the declaration which triggered the lifetime-extension of this
+ /// temporary, if any.
+ const ValueDecl *getExtendingDecl() const {
+ return State.is<Stmt *>() ? nullptr
+ : State.get<ExtraState *>()->ExtendingDecl;
+ }
+
+ void setExtendingDecl(const ValueDecl *ExtendedBy, unsigned ManglingNumber);
+
+ unsigned getManglingNumber() const {
+ return State.is<Stmt *>() ? 0 : State.get<ExtraState *>()->ManglingNumber;
+ }
+
+ /// \brief Determine whether this materialized temporary is bound to an
+ /// lvalue reference; otherwise, it's bound to an rvalue reference.
+ bool isBoundToLvalueReference() const {
+ return getValueKind() == VK_LValue;
+ }
+
+ SourceLocation getLocStart() const LLVM_READONLY {
+ return getTemporary()->getLocStart();
+ }
+ SourceLocation getLocEnd() const LLVM_READONLY {
+ return getTemporary()->getLocEnd();
+ }
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == MaterializeTemporaryExprClass;
+ }
+
+ // Iterators
+ child_range children() {
+ if (State.is<Stmt *>())
+ return child_range(State.getAddrOfPtr1(), State.getAddrOfPtr1() + 1);
+
+ auto ES = State.get<ExtraState *>();
+ return child_range(&ES->Temporary, &ES->Temporary + 1);
+ }
+};
+
+/// \brief Represents a folding of a pack over an operator.
+///
+/// This expression is always dependent and represents a pack expansion of the
+/// forms:
+///
+/// ( expr op ... )
+/// ( ... op expr )
+/// ( expr op ... op expr )
+class CXXFoldExpr : public Expr {
+ SourceLocation LParenLoc;
+ SourceLocation EllipsisLoc;
+ SourceLocation RParenLoc;
+ Stmt *SubExprs[2];
+ BinaryOperatorKind Opcode;
+
+ friend class ASTStmtReader;
+ friend class ASTStmtWriter;
+public:
+ CXXFoldExpr(QualType T, SourceLocation LParenLoc, Expr *LHS,
+ BinaryOperatorKind Opcode, SourceLocation EllipsisLoc, Expr *RHS,
+ SourceLocation RParenLoc)
+ : Expr(CXXFoldExprClass, T, VK_RValue, OK_Ordinary,
+ /*Dependent*/ true, true, true,
+ /*ContainsUnexpandedParameterPack*/ false),
+ LParenLoc(LParenLoc), EllipsisLoc(EllipsisLoc), RParenLoc(RParenLoc),
+ Opcode(Opcode) {
+ SubExprs[0] = LHS;
+ SubExprs[1] = RHS;
+ }
+ CXXFoldExpr(EmptyShell Empty) : Expr(CXXFoldExprClass, Empty) {}
+
+ Expr *getLHS() const { return static_cast<Expr*>(SubExprs[0]); }
+ Expr *getRHS() const { return static_cast<Expr*>(SubExprs[1]); }
+
+ /// Does this produce a right-associated sequence of operators?
+ bool isRightFold() const {
+ return getLHS() && getLHS()->containsUnexpandedParameterPack();
+ }
+ /// Does this produce a left-associated sequence of operators?
+ bool isLeftFold() const { return !isRightFold(); }
+ /// Get the pattern, that is, the operand that contains an unexpanded pack.
+ Expr *getPattern() const { return isLeftFold() ? getRHS() : getLHS(); }
+ /// Get the operand that doesn't contain a pack, for a binary fold.
+ Expr *getInit() const { return isLeftFold() ? getLHS() : getRHS(); }
+
+ SourceLocation getEllipsisLoc() const { return EllipsisLoc; }
+ BinaryOperatorKind getOperator() const { return Opcode; }
+
+ SourceLocation getLocStart() const LLVM_READONLY {
+ return LParenLoc;
+ }
+ SourceLocation getLocEnd() const LLVM_READONLY {
+ return RParenLoc;
+ }
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == CXXFoldExprClass;
+ }
+
+ // Iterators
+ child_range children() { return child_range(SubExprs, SubExprs + 2); }
+};
+
+/// \brief Represents an expression that might suspend coroutine execution;
+/// either a co_await or co_yield expression.
+///
+/// Evaluation of this expression first evaluates its 'ready' expression. If
+/// that returns 'false':
+/// -- execution of the coroutine is suspended
+/// -- the 'suspend' expression is evaluated
+/// -- if the 'suspend' expression returns 'false', the coroutine is
+/// resumed
+/// -- otherwise, control passes back to the resumer.
+/// If the coroutine is not suspended, or when it is resumed, the 'resume'
+/// expression is evaluated, and its result is the result of the overall
+/// expression.
+class CoroutineSuspendExpr : public Expr {
+ SourceLocation KeywordLoc;
+
+ enum SubExpr { Common, Ready, Suspend, Resume, Count };
+ Stmt *SubExprs[SubExpr::Count];
+
+ friend class ASTStmtReader;
+public:
+ CoroutineSuspendExpr(StmtClass SC, SourceLocation KeywordLoc, Expr *Common,
+ Expr *Ready, Expr *Suspend, Expr *Resume)
+ : Expr(SC, Resume->getType(), Resume->getValueKind(),
+ Resume->getObjectKind(), Resume->isTypeDependent(),
+ Resume->isValueDependent(), Common->isInstantiationDependent(),
+ Common->containsUnexpandedParameterPack()),
+ KeywordLoc(KeywordLoc) {
+ SubExprs[SubExpr::Common] = Common;
+ SubExprs[SubExpr::Ready] = Ready;
+ SubExprs[SubExpr::Suspend] = Suspend;
+ SubExprs[SubExpr::Resume] = Resume;
+ }
+ CoroutineSuspendExpr(StmtClass SC, SourceLocation KeywordLoc, QualType Ty,
+ Expr *Common)
+ : Expr(SC, Ty, VK_RValue, OK_Ordinary, true, true, true,
+ Common->containsUnexpandedParameterPack()),
+ KeywordLoc(KeywordLoc) {
+ assert(Common->isTypeDependent() && Ty->isDependentType() &&
+ "wrong constructor for non-dependent co_await/co_yield expression");
+ SubExprs[SubExpr::Common] = Common;
+ SubExprs[SubExpr::Ready] = nullptr;
+ SubExprs[SubExpr::Suspend] = nullptr;
+ SubExprs[SubExpr::Resume] = nullptr;
+ }
+ CoroutineSuspendExpr(StmtClass SC, EmptyShell Empty) : Expr(SC, Empty) {
+ SubExprs[SubExpr::Common] = nullptr;
+ SubExprs[SubExpr::Ready] = nullptr;
+ SubExprs[SubExpr::Suspend] = nullptr;
+ SubExprs[SubExpr::Resume] = nullptr;
+ }
+
+ SourceLocation getKeywordLoc() const { return KeywordLoc; }
+ Expr *getCommonExpr() const {
+ return static_cast<Expr*>(SubExprs[SubExpr::Common]);
+ }
+
+ Expr *getReadyExpr() const {
+ return static_cast<Expr*>(SubExprs[SubExpr::Ready]);
+ }
+ Expr *getSuspendExpr() const {
+ return static_cast<Expr*>(SubExprs[SubExpr::Suspend]);
+ }
+ Expr *getResumeExpr() const {
+ return static_cast<Expr*>(SubExprs[SubExpr::Resume]);
+ }
+
+ SourceLocation getLocStart() const LLVM_READONLY {
+ return KeywordLoc;
+ }
+ SourceLocation getLocEnd() const LLVM_READONLY {
+ return getCommonExpr()->getLocEnd();
+ }
+
+ child_range children() {
+ return child_range(SubExprs, SubExprs + SubExpr::Count);
+ }
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == CoawaitExprClass ||
+ T->getStmtClass() == CoyieldExprClass;
+ }
+};
+
+/// \brief Represents a 'co_await' expression.
+class CoawaitExpr : public CoroutineSuspendExpr {
+ friend class ASTStmtReader;
+public:
+ CoawaitExpr(SourceLocation CoawaitLoc, Expr *Operand, Expr *Ready,
+ Expr *Suspend, Expr *Resume)
+ : CoroutineSuspendExpr(CoawaitExprClass, CoawaitLoc, Operand, Ready,
+ Suspend, Resume) {}
+ CoawaitExpr(SourceLocation CoawaitLoc, QualType Ty, Expr *Operand)
+ : CoroutineSuspendExpr(CoawaitExprClass, CoawaitLoc, Ty, Operand) {}
+ CoawaitExpr(EmptyShell Empty)
+ : CoroutineSuspendExpr(CoawaitExprClass, Empty) {}
+
+ Expr *getOperand() const {
+ // FIXME: Dig out the actual operand or store it.
+ return getCommonExpr();
+ }
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == CoawaitExprClass;
+ }
+};
+
+/// \brief Represents a 'co_yield' expression.
+class CoyieldExpr : public CoroutineSuspendExpr {
+ friend class ASTStmtReader;
+public:
+ CoyieldExpr(SourceLocation CoyieldLoc, Expr *Operand, Expr *Ready,
+ Expr *Suspend, Expr *Resume)
+ : CoroutineSuspendExpr(CoyieldExprClass, CoyieldLoc, Operand, Ready,
+ Suspend, Resume) {}
+ CoyieldExpr(SourceLocation CoyieldLoc, QualType Ty, Expr *Operand)
+ : CoroutineSuspendExpr(CoyieldExprClass, CoyieldLoc, Ty, Operand) {}
+ CoyieldExpr(EmptyShell Empty)
+ : CoroutineSuspendExpr(CoyieldExprClass, Empty) {}
+
+ Expr *getOperand() const {
+ // FIXME: Dig out the actual operand or store it.
+ return getCommonExpr();
+ }
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == CoyieldExprClass;
+ }
+};
+
+} // 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..61e6383
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/AST/ExprObjC.h
@@ -0,0 +1,1568 @@
+//===--- 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/AST/SelectorLocationsKind.h"
+#include "clang/Basic/IdentifierTable.h"
+#include "llvm/Support/Compiler.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, 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; }
+
+ SourceLocation getLocStart() const LLVM_READONLY { return AtLoc; }
+ SourceLocation getLocEnd() const LLVM_READONLY { return String->getLocEnd(); }
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == ObjCStringLiteralClass;
+ }
+
+ // Iterators
+ child_range children() { return child_range(&String, &String+1); }
+};
+
+/// ObjCBoolLiteralExpr - Objective-C Boolean Literal.
+///
+class ObjCBoolLiteralExpr : public Expr {
+ bool Value;
+ SourceLocation Loc;
+public:
+ ObjCBoolLiteralExpr(bool val, QualType Ty, SourceLocation l) :
+ Expr(ObjCBoolLiteralExprClass, Ty, VK_RValue, OK_Ordinary, false, false,
+ false, false), Value(val), Loc(l) {}
+
+ explicit ObjCBoolLiteralExpr(EmptyShell Empty)
+ : Expr(ObjCBoolLiteralExprClass, Empty) { }
+
+ bool getValue() const { return Value; }
+ void setValue(bool V) { Value = V; }
+
+ SourceLocation getLocStart() const LLVM_READONLY { return Loc; }
+ SourceLocation getLocEnd() const LLVM_READONLY { return Loc; }
+
+ SourceLocation getLocation() const { return Loc; }
+ void setLocation(SourceLocation L) { Loc = L; }
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == ObjCBoolLiteralExprClass;
+ }
+
+ // Iterators
+ child_range children() {
+ return child_range(child_iterator(), child_iterator());
+ }
+};
+
+/// ObjCBoxedExpr - used for generalized expression boxing.
+/// as in: @(strdup("hello world")), @(random()) or @(view.frame)
+/// Also used for boxing non-parenthesized numeric literals;
+/// as in: @42 or \@true (c++/objc++) or \@__yes (c/objc).
+class ObjCBoxedExpr : public Expr {
+ Stmt *SubExpr;
+ ObjCMethodDecl *BoxingMethod;
+ SourceRange Range;
+public:
+ ObjCBoxedExpr(Expr *E, QualType T, ObjCMethodDecl *method,
+ SourceRange R)
+ : Expr(ObjCBoxedExprClass, T, VK_RValue, OK_Ordinary,
+ E->isTypeDependent(), E->isValueDependent(),
+ E->isInstantiationDependent(), E->containsUnexpandedParameterPack()),
+ SubExpr(E), BoxingMethod(method), Range(R) {}
+ explicit ObjCBoxedExpr(EmptyShell Empty)
+ : Expr(ObjCBoxedExprClass, Empty) {}
+
+ Expr *getSubExpr() { return cast<Expr>(SubExpr); }
+ const Expr *getSubExpr() const { return cast<Expr>(SubExpr); }
+
+ ObjCMethodDecl *getBoxingMethod() const {
+ return BoxingMethod;
+ }
+
+ SourceLocation getAtLoc() const { return Range.getBegin(); }
+
+ SourceLocation getLocStart() const LLVM_READONLY { return Range.getBegin(); }
+ SourceLocation getLocEnd() const LLVM_READONLY { return Range.getEnd(); }
+ SourceRange getSourceRange() const LLVM_READONLY {
+ return Range;
+ }
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == ObjCBoxedExprClass;
+ }
+
+ // Iterators
+ child_range children() { return child_range(&SubExpr, &SubExpr+1); }
+
+ typedef ConstExprIterator const_arg_iterator;
+
+ const_arg_iterator arg_begin() const {
+ return reinterpret_cast<Stmt const * const*>(&SubExpr);
+ }
+ const_arg_iterator arg_end() const {
+ return reinterpret_cast<Stmt const * const*>(&SubExpr + 1);
+ }
+
+ friend class ASTStmtReader;
+};
+
+/// ObjCArrayLiteral - used for objective-c array containers; as in:
+/// @[@"Hello", NSApp, [NSNumber numberWithInt:42]];
+class ObjCArrayLiteral final
+ : public Expr,
+ private llvm::TrailingObjects<ObjCArrayLiteral, Expr *> {
+ unsigned NumElements;
+ SourceRange Range;
+ ObjCMethodDecl *ArrayWithObjectsMethod;
+
+ ObjCArrayLiteral(ArrayRef<Expr *> Elements,
+ QualType T, ObjCMethodDecl * Method,
+ SourceRange SR);
+
+ explicit ObjCArrayLiteral(EmptyShell Empty, unsigned NumElements)
+ : Expr(ObjCArrayLiteralClass, Empty), NumElements(NumElements) {}
+
+public:
+ static ObjCArrayLiteral *Create(const ASTContext &C,
+ ArrayRef<Expr *> Elements,
+ QualType T, ObjCMethodDecl * Method,
+ SourceRange SR);
+
+ static ObjCArrayLiteral *CreateEmpty(const ASTContext &C,
+ unsigned NumElements);
+
+ SourceLocation getLocStart() const LLVM_READONLY { return Range.getBegin(); }
+ SourceLocation getLocEnd() const LLVM_READONLY { return Range.getEnd(); }
+ SourceRange getSourceRange() const LLVM_READONLY { return Range; }
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == ObjCArrayLiteralClass;
+ }
+
+ /// \brief Retrieve elements of array of literals.
+ Expr **getElements() { return getTrailingObjects<Expr *>(); }
+
+ /// \brief Retrieve elements of array of literals.
+ const Expr * const *getElements() const {
+ return getTrailingObjects<Expr *>();
+ }
+
+ /// getNumElements - Return number of elements of objective-c array literal.
+ unsigned getNumElements() const { return NumElements; }
+
+ /// getExpr - Return the Expr at the specified index.
+ Expr *getElement(unsigned Index) {
+ assert((Index < NumElements) && "Arg access out of range!");
+ return cast<Expr>(getElements()[Index]);
+ }
+ const Expr *getElement(unsigned Index) const {
+ assert((Index < NumElements) && "Arg access out of range!");
+ return cast<Expr>(getElements()[Index]);
+ }
+
+ ObjCMethodDecl *getArrayWithObjectsMethod() const {
+ return ArrayWithObjectsMethod;
+ }
+
+ // Iterators
+ child_range children() {
+ return child_range(reinterpret_cast<Stmt **>(getElements()),
+ reinterpret_cast<Stmt **>(getElements()) + NumElements);
+ }
+
+ friend TrailingObjects;
+ friend class ASTStmtReader;
+};
+
+/// \brief An element in an Objective-C dictionary literal.
+///
+struct ObjCDictionaryElement {
+ /// \brief The key for the dictionary element.
+ Expr *Key;
+
+ /// \brief The value of the dictionary element.
+ Expr *Value;
+
+ /// \brief The location of the ellipsis, if this is a pack expansion.
+ SourceLocation EllipsisLoc;
+
+ /// \brief The number of elements this pack expansion will expand to, if
+ /// this is a pack expansion and is known.
+ Optional<unsigned> NumExpansions;
+
+ /// \brief Determines whether this dictionary element is a pack expansion.
+ bool isPackExpansion() const { return EllipsisLoc.isValid(); }
+};
+} // end namespace clang
+
+namespace llvm {
+template <> struct isPodLike<clang::ObjCDictionaryElement> : std::true_type {};
+}
+
+namespace clang {
+/// \brief Internal struct for storing Key/value pair.
+struct ObjCDictionaryLiteral_KeyValuePair {
+ Expr *Key;
+ Expr *Value;
+};
+
+/// \brief Internal struct to describes an element that is a pack
+/// expansion, used if any of the elements in the dictionary literal
+/// are pack expansions.
+struct ObjCDictionaryLiteral_ExpansionData {
+ /// \brief The location of the ellipsis, if this element is a pack
+ /// expansion.
+ SourceLocation EllipsisLoc;
+
+ /// \brief If non-zero, the number of elements that this pack
+ /// expansion will expand to (+1).
+ unsigned NumExpansionsPlusOne;
+};
+
+/// ObjCDictionaryLiteral - AST node to represent objective-c dictionary
+/// literals; as in: @{@"name" : NSUserName(), @"date" : [NSDate date] };
+class ObjCDictionaryLiteral final
+ : public Expr,
+ private llvm::TrailingObjects<ObjCDictionaryLiteral,
+ ObjCDictionaryLiteral_KeyValuePair,
+ ObjCDictionaryLiteral_ExpansionData> {
+ /// \brief The number of elements in this dictionary literal.
+ unsigned NumElements : 31;
+
+ /// \brief Determine whether this dictionary literal has any pack expansions.
+ ///
+ /// If the dictionary literal has pack expansions, then there will
+ /// be an array of pack expansion data following the array of
+ /// key/value pairs, which provide the locations of the ellipses (if
+ /// any) and number of elements in the expansion (if known). If
+ /// there are no pack expansions, we optimize away this storage.
+ unsigned HasPackExpansions : 1;
+
+ SourceRange Range;
+ ObjCMethodDecl *DictWithObjectsMethod;
+
+ typedef ObjCDictionaryLiteral_KeyValuePair KeyValuePair;
+ typedef ObjCDictionaryLiteral_ExpansionData ExpansionData;
+
+ size_t numTrailingObjects(OverloadToken<KeyValuePair>) const {
+ return NumElements;
+ }
+
+ ObjCDictionaryLiteral(ArrayRef<ObjCDictionaryElement> VK,
+ bool HasPackExpansions,
+ QualType T, ObjCMethodDecl *method,
+ SourceRange SR);
+
+ explicit ObjCDictionaryLiteral(EmptyShell Empty, unsigned NumElements,
+ bool HasPackExpansions)
+ : Expr(ObjCDictionaryLiteralClass, Empty), NumElements(NumElements),
+ HasPackExpansions(HasPackExpansions) {}
+
+public:
+ static ObjCDictionaryLiteral *Create(const ASTContext &C,
+ ArrayRef<ObjCDictionaryElement> VK,
+ bool HasPackExpansions,
+ QualType T, ObjCMethodDecl *method,
+ SourceRange SR);
+
+ static ObjCDictionaryLiteral *CreateEmpty(const ASTContext &C,
+ unsigned NumElements,
+ bool HasPackExpansions);
+
+ /// getNumElements - Return number of elements of objective-c dictionary
+ /// literal.
+ unsigned getNumElements() const { return NumElements; }
+
+ ObjCDictionaryElement getKeyValueElement(unsigned Index) const {
+ assert((Index < NumElements) && "Arg access out of range!");
+ const KeyValuePair &KV = getTrailingObjects<KeyValuePair>()[Index];
+ ObjCDictionaryElement Result = { KV.Key, KV.Value, SourceLocation(), None };
+ if (HasPackExpansions) {
+ const ExpansionData &Expansion =
+ getTrailingObjects<ExpansionData>()[Index];
+ Result.EllipsisLoc = Expansion.EllipsisLoc;
+ if (Expansion.NumExpansionsPlusOne > 0)
+ Result.NumExpansions = Expansion.NumExpansionsPlusOne - 1;
+ }
+ return Result;
+ }
+
+ ObjCMethodDecl *getDictWithObjectsMethod() const
+ { return DictWithObjectsMethod; }
+
+ SourceLocation getLocStart() const LLVM_READONLY { return Range.getBegin(); }
+ SourceLocation getLocEnd() const LLVM_READONLY { return Range.getEnd(); }
+ SourceRange getSourceRange() const LLVM_READONLY { return Range; }
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == ObjCDictionaryLiteralClass;
+ }
+
+ // Iterators
+ child_range children() {
+ // Note: we're taking advantage of the layout of the KeyValuePair struct
+ // here. If that struct changes, this code will need to change as well.
+ static_assert(sizeof(KeyValuePair) == sizeof(Stmt *) * 2,
+ "KeyValuePair is expected size");
+ return child_range(
+ reinterpret_cast<Stmt **>(getTrailingObjects<KeyValuePair>()),
+ reinterpret_cast<Stmt **>(getTrailingObjects<KeyValuePair>()) +
+ NumElements * 2);
+ }
+
+ friend class ASTStmtReader;
+ friend class ASTStmtWriter;
+ friend TrailingObjects;
+};
+
+
+/// 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()->isInstantiationDependentType(),
+ 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;
+ }
+
+ SourceLocation getLocStart() const LLVM_READONLY { return AtLoc; }
+ SourceLocation getLocEnd() const LLVM_READONLY { return RParenLoc; }
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == ObjCEncodeExprClass;
+ }
+
+ // Iterators
+ child_range children() {
+ return child_range(child_iterator(), child_iterator());
+ }
+};
+
+/// 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, 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; }
+
+ SourceLocation getLocStart() const LLVM_READONLY { return AtLoc; }
+ SourceLocation getLocEnd() const LLVM_READONLY { return 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;
+ }
+
+ // Iterators
+ child_range children() {
+ return child_range(child_iterator(), child_iterator());
+ }
+};
+
+/// ObjCProtocolExpr used for protocol expression in Objective-C.
+///
+/// This is used as: \@protocol(foo), as in:
+/// \code
+/// [obj conformsToProtocol:@protocol(foo)]
+/// \endcode
+///
+/// The return type is "Protocol*".
+class ObjCProtocolExpr : public Expr {
+ ObjCProtocolDecl *TheProtocol;
+ SourceLocation AtLoc, ProtoLoc, RParenLoc;
+public:
+ ObjCProtocolExpr(QualType T, ObjCProtocolDecl *protocol,
+ SourceLocation at, SourceLocation protoLoc, SourceLocation rp)
+ : Expr(ObjCProtocolExprClass, T, VK_RValue, OK_Ordinary, false, false,
+ false, false),
+ TheProtocol(protocol), AtLoc(at), ProtoLoc(protoLoc), RParenLoc(rp) {}
+ explicit ObjCProtocolExpr(EmptyShell Empty)
+ : Expr(ObjCProtocolExprClass, Empty) {}
+
+ ObjCProtocolDecl *getProtocol() const { return TheProtocol; }
+ void setProtocol(ObjCProtocolDecl *P) { TheProtocol = P; }
+
+ SourceLocation getProtocolIdLoc() const { return ProtoLoc; }
+ SourceLocation getAtLoc() const { return AtLoc; }
+ SourceLocation getRParenLoc() const { return RParenLoc; }
+ void setAtLoc(SourceLocation L) { AtLoc = L; }
+ void setRParenLoc(SourceLocation L) { RParenLoc = L; }
+
+ SourceLocation getLocStart() const LLVM_READONLY { return AtLoc; }
+ SourceLocation getLocEnd() const LLVM_READONLY { return RParenLoc; }
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == ObjCProtocolExprClass;
+ }
+
+ // Iterators
+ child_range children() {
+ return child_range(child_iterator(), child_iterator());
+ }
+
+ friend class ASTStmtReader;
+ friend class ASTStmtWriter;
+};
+
+/// ObjCIvarRefExpr - A reference to an ObjC instance variable.
+class ObjCIvarRefExpr : public Expr {
+ ObjCIvarDecl *D;
+ Stmt *Base;
+ SourceLocation Loc;
+ /// OpLoc - This is the location of '.' or '->'
+ SourceLocation OpLoc;
+
+ 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, SourceLocation oploc,
+ Expr *base,
+ bool arrow = false, bool freeIvar = false) :
+ Expr(ObjCIvarRefExprClass, t, VK_LValue,
+ d->isBitField() ? OK_BitField : OK_Ordinary,
+ /*TypeDependent=*/false, base->isValueDependent(),
+ base->isInstantiationDependent(),
+ base->containsUnexpandedParameterPack()),
+ D(d), Base(base), Loc(l), OpLoc(oploc),
+ 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; }
+
+ SourceLocation getLocStart() const LLVM_READONLY {
+ return isFreeIvar() ? Loc : getBase()->getLocStart();
+ }
+ SourceLocation getLocEnd() const LLVM_READONLY { return Loc; }
+
+ SourceLocation getOpLoc() const { return OpLoc; }
+ void setOpLoc(SourceLocation L) { OpLoc = L; }
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == ObjCIvarRefExprClass;
+ }
+
+ // 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;
+
+ /// \brief Indicates whether the property reference will result in a message
+ /// to the getter, the setter, or both.
+ /// This applies to both implicit and explicit property references.
+ enum MethodRefFlags {
+ MethodRef_None = 0,
+ MethodRef_Getter = 0x1,
+ MethodRef_Setter = 0x2
+ };
+
+ /// \brief Contains the Setter method pointer and MethodRefFlags bit flags.
+ llvm::PointerIntPair<ObjCMethodDecl *, 2, unsigned> SetterAndMethodRefFlags;
+
+ // FIXME: Maybe we should store the property identifier here,
+ // because it's not rederivable from the other data when there's an
+ // implicit property with no getter (because the 'foo' -> 'setFoo:'
+ // transformation is lossy on the first character).
+
+ 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->isInstantiationDependent(),
+ base->containsUnexpandedParameterPack()),
+ PropertyOrGetter(PD, false), SetterAndMethodRefFlags(),
+ IdLoc(l), ReceiverLoc(), Receiver(base) {
+ assert(t->isSpecificPlaceholderType(BuiltinType::PseudoObject));
+ }
+
+ ObjCPropertyRefExpr(ObjCPropertyDecl *PD, QualType t,
+ ExprValueKind VK, ExprObjectKind OK,
+ SourceLocation l, SourceLocation sl, QualType st)
+ : Expr(ObjCPropertyRefExprClass, t, VK, OK,
+ /*TypeDependent=*/false, false, st->isInstantiationDependentType(),
+ st->containsUnexpandedParameterPack()),
+ PropertyOrGetter(PD, false), SetterAndMethodRefFlags(),
+ IdLoc(l), ReceiverLoc(sl), Receiver(st.getTypePtr()) {
+ assert(t->isSpecificPlaceholderType(BuiltinType::PseudoObject));
+ }
+
+ ObjCPropertyRefExpr(ObjCMethodDecl *Getter, ObjCMethodDecl *Setter,
+ QualType T, ExprValueKind VK, ExprObjectKind OK,
+ SourceLocation IdLoc, Expr *Base)
+ : Expr(ObjCPropertyRefExprClass, T, VK, OK, false,
+ Base->isValueDependent(), Base->isInstantiationDependent(),
+ Base->containsUnexpandedParameterPack()),
+ PropertyOrGetter(Getter, true), SetterAndMethodRefFlags(Setter, 0),
+ IdLoc(IdLoc), ReceiverLoc(), Receiver(Base) {
+ assert(T->isSpecificPlaceholderType(BuiltinType::PseudoObject));
+ }
+
+ 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, false),
+ PropertyOrGetter(Getter, true), SetterAndMethodRefFlags(Setter, 0),
+ IdLoc(IdLoc), ReceiverLoc(SuperLoc), Receiver(SuperTy.getTypePtr()) {
+ assert(T->isSpecificPlaceholderType(BuiltinType::PseudoObject));
+ }
+
+ 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, false),
+ PropertyOrGetter(Getter, true), SetterAndMethodRefFlags(Setter, 0),
+ IdLoc(IdLoc), ReceiverLoc(ReceiverLoc), Receiver(Receiver) {
+ assert(T->isSpecificPlaceholderType(BuiltinType::PseudoObject));
+ }
+
+ 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 SetterAndMethodRefFlags.getPointer();
+ }
+
+ Selector getGetterSelector() const {
+ if (isImplicitProperty())
+ return getImplicitPropertyGetter()->getSelector();
+ return getExplicitProperty()->getGetterName();
+ }
+
+ Selector getSetterSelector() const {
+ if (isImplicitProperty())
+ return getImplicitPropertySetter()->getSelector();
+ return getExplicitProperty()->getSetterName();
+ }
+
+ /// \brief True if the property reference will result in a message to the
+ /// getter.
+ /// This applies to both implicit and explicit property references.
+ bool isMessagingGetter() const {
+ return SetterAndMethodRefFlags.getInt() & MethodRef_Getter;
+ }
+
+ /// \brief True if the property reference will result in a message to the
+ /// setter.
+ /// This applies to both implicit and explicit property references.
+ bool isMessagingSetter() const {
+ return SetterAndMethodRefFlags.getInt() & MethodRef_Setter;
+ }
+
+ void setIsMessagingGetter(bool val = true) {
+ setMethodRefFlag(MethodRef_Getter, val);
+ }
+
+ void setIsMessagingSetter(bool val = true) {
+ setMethodRefFlag(MethodRef_Setter, val);
+ }
+
+ 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*>(); }
+
+ /// Determine the type of the base, regardless of the kind of receiver.
+ QualType getReceiverType(const ASTContext &ctx) const;
+
+ SourceLocation getLocStart() const LLVM_READONLY {
+ return isObjectReceiver() ? getBase()->getLocStart() :getReceiverLocation();
+ }
+ SourceLocation getLocEnd() const LLVM_READONLY { return IdLoc; }
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == ObjCPropertyRefExprClass;
+ }
+
+ // Iterators
+ child_range children() {
+ if (Receiver.is<Stmt*>()) {
+ Stmt **begin = reinterpret_cast<Stmt**>(&Receiver); // hack!
+ return child_range(begin, begin+1);
+ }
+ return child_range(child_iterator(), child_iterator());
+ }
+
+private:
+ friend class ASTStmtReader;
+ friend class ASTStmtWriter;
+ void setExplicitProperty(ObjCPropertyDecl *D, unsigned methRefFlags) {
+ PropertyOrGetter.setPointer(D);
+ PropertyOrGetter.setInt(false);
+ SetterAndMethodRefFlags.setPointer(nullptr);
+ SetterAndMethodRefFlags.setInt(methRefFlags);
+ }
+ void setImplicitProperty(ObjCMethodDecl *Getter, ObjCMethodDecl *Setter,
+ unsigned methRefFlags) {
+ PropertyOrGetter.setPointer(Getter);
+ PropertyOrGetter.setInt(true);
+ SetterAndMethodRefFlags.setPointer(Setter);
+ SetterAndMethodRefFlags.setInt(methRefFlags);
+ }
+ 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; }
+
+ void setMethodRefFlag(MethodRefFlags flag, bool val) {
+ unsigned f = SetterAndMethodRefFlags.getInt();
+ if (val)
+ f |= flag;
+ else
+ f &= ~flag;
+ SetterAndMethodRefFlags.setInt(f);
+ }
+};
+
+/// ObjCSubscriptRefExpr - used for array and dictionary subscripting.
+/// array[4] = array[3]; dictionary[key] = dictionary[alt_key];
+///
+class ObjCSubscriptRefExpr : public Expr {
+ // Location of ']' in an indexing expression.
+ SourceLocation RBracket;
+ // array/dictionary base expression.
+ // for arrays, this is a numeric expression. For dictionaries, this is
+ // an objective-c object pointer expression.
+ enum { BASE, KEY, END_EXPR };
+ Stmt* SubExprs[END_EXPR];
+
+ ObjCMethodDecl *GetAtIndexMethodDecl;
+
+ // For immutable objects this is null. When ObjCSubscriptRefExpr is to read
+ // an indexed object this is null too.
+ ObjCMethodDecl *SetAtIndexMethodDecl;
+
+public:
+
+ ObjCSubscriptRefExpr(Expr *base, Expr *key, QualType T,
+ ExprValueKind VK, ExprObjectKind OK,
+ ObjCMethodDecl *getMethod,
+ ObjCMethodDecl *setMethod, SourceLocation RB)
+ : Expr(ObjCSubscriptRefExprClass, T, VK, OK,
+ base->isTypeDependent() || key->isTypeDependent(),
+ base->isValueDependent() || key->isValueDependent(),
+ base->isInstantiationDependent() || key->isInstantiationDependent(),
+ (base->containsUnexpandedParameterPack() ||
+ key->containsUnexpandedParameterPack())),
+ RBracket(RB),
+ GetAtIndexMethodDecl(getMethod),
+ SetAtIndexMethodDecl(setMethod)
+ {SubExprs[BASE] = base; SubExprs[KEY] = key;}
+
+ explicit ObjCSubscriptRefExpr(EmptyShell Empty)
+ : Expr(ObjCSubscriptRefExprClass, Empty) {}
+
+ SourceLocation getRBracket() const { return RBracket; }
+ void setRBracket(SourceLocation RB) { RBracket = RB; }
+
+ SourceLocation getLocStart() const LLVM_READONLY {
+ return SubExprs[BASE]->getLocStart();
+ }
+ SourceLocation getLocEnd() const LLVM_READONLY { return RBracket; }
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == ObjCSubscriptRefExprClass;
+ }
+
+ Expr *getBaseExpr() const { return cast<Expr>(SubExprs[BASE]); }
+ void setBaseExpr(Stmt *S) { SubExprs[BASE] = S; }
+
+ Expr *getKeyExpr() const { return cast<Expr>(SubExprs[KEY]); }
+ void setKeyExpr(Stmt *S) { SubExprs[KEY] = S; }
+
+ ObjCMethodDecl *getAtIndexMethodDecl() const {
+ return GetAtIndexMethodDecl;
+ }
+
+ ObjCMethodDecl *setAtIndexMethodDecl() const {
+ return SetAtIndexMethodDecl;
+ }
+
+ bool isArraySubscriptRefExpr() const {
+ return getKeyExpr()->getType()->isIntegralOrEnumerationType();
+ }
+
+ child_range children() {
+ return child_range(SubExprs, SubExprs+END_EXPR);
+ }
+private:
+ friend class ASTStmtReader;
+};
+
+
+/// \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:
+///
+/// The "void *" trailing objects are actually ONE void * (the
+/// receiver pointer), and NumArgs Expr *. But due to the
+/// implementation of children(), these must be together contiguously.
+
+class ObjCMessageExpr final
+ : public Expr,
+ private llvm::TrailingObjects<ObjCMessageExpr, void *, SourceLocation> {
+ /// \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;
+
+ enum { NumArgsBitWidth = 16 };
+
+ /// \brief The number of arguments in the message send, not
+ /// including the receiver.
+ unsigned NumArgs : NumArgsBitWidth;
+
+ /// \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 : 1;
+
+ /// \brief Whether this message send is a "delegate init call",
+ /// i.e. a call of an init method on self from within an init method.
+ unsigned IsDelegateInitCall : 1;
+
+ /// \brief Whether this message send was implicitly generated by
+ /// the implementation rather than explicitly written by the user.
+ unsigned IsImplicit : 1;
+
+ /// \brief Whether the locations of the selector identifiers are in a
+ /// "standard" position, a enum SelectorLocationsKind.
+ unsigned SelLocsKind : 2;
+
+ /// \brief When the message expression is a send to 'super', this is
+ /// the location of the 'super' keyword.
+ SourceLocation SuperLoc;
+
+ /// \brief The source locations of the open and close square
+ /// brackets ('[' and ']', respectively).
+ SourceLocation LBracLoc, RBracLoc;
+
+ size_t numTrailingObjects(OverloadToken<void *>) const { return NumArgs + 1; }
+
+ void setNumArgs(unsigned Num) {
+ assert((Num >> NumArgsBitWidth) == 0 && "Num of args is out of range!");
+ NumArgs = Num;
+ }
+
+ ObjCMessageExpr(EmptyShell Empty, unsigned NumArgs)
+ : Expr(ObjCMessageExprClass, Empty), SelectorOrMethod(0), Kind(0),
+ HasMethod(0), IsDelegateInitCall(0), IsImplicit(0), SelLocsKind(0) {
+ setNumArgs(NumArgs);
+ }
+
+ ObjCMessageExpr(QualType T, ExprValueKind VK,
+ SourceLocation LBracLoc,
+ SourceLocation SuperLoc,
+ bool IsInstanceSuper,
+ QualType SuperType,
+ Selector Sel,
+ ArrayRef<SourceLocation> SelLocs,
+ SelectorLocationsKind SelLocsK,
+ ObjCMethodDecl *Method,
+ ArrayRef<Expr *> Args,
+ SourceLocation RBracLoc,
+ bool isImplicit);
+ ObjCMessageExpr(QualType T, ExprValueKind VK,
+ SourceLocation LBracLoc,
+ TypeSourceInfo *Receiver,
+ Selector Sel,
+ ArrayRef<SourceLocation> SelLocs,
+ SelectorLocationsKind SelLocsK,
+ ObjCMethodDecl *Method,
+ ArrayRef<Expr *> Args,
+ SourceLocation RBracLoc,
+ bool isImplicit);
+ ObjCMessageExpr(QualType T, ExprValueKind VK,
+ SourceLocation LBracLoc,
+ Expr *Receiver,
+ Selector Sel,
+ ArrayRef<SourceLocation> SelLocs,
+ SelectorLocationsKind SelLocsK,
+ ObjCMethodDecl *Method,
+ ArrayRef<Expr *> Args,
+ SourceLocation RBracLoc,
+ bool isImplicit);
+
+ void initArgsAndSelLocs(ArrayRef<Expr *> Args,
+ ArrayRef<SourceLocation> SelLocs,
+ SelectorLocationsKind SelLocsK);
+
+ /// \brief Retrieve the pointer value of the message receiver.
+ void *getReceiverPointer() const { return *getTrailingObjects<void *>(); }
+
+ /// \brief Set the pointer value of the message receiver.
+ void setReceiverPointer(void *Value) {
+ *getTrailingObjects<void *>() = Value;
+ }
+
+ SelectorLocationsKind getSelLocsKind() const {
+ return (SelectorLocationsKind)SelLocsKind;
+ }
+ bool hasStandardSelLocs() const {
+ return getSelLocsKind() != SelLoc_NonStandard;
+ }
+
+ /// \brief Get a pointer to the stored selector identifiers locations array.
+ /// No locations will be stored if HasStandardSelLocs is true.
+ SourceLocation *getStoredSelLocs() {
+ return getTrailingObjects<SourceLocation>();
+ }
+ const SourceLocation *getStoredSelLocs() const {
+ return getTrailingObjects<SourceLocation>();
+ }
+
+ /// \brief Get the number of stored selector identifiers locations.
+ /// No locations will be stored if HasStandardSelLocs is true.
+ unsigned getNumStoredSelLocs() const {
+ if (hasStandardSelLocs())
+ return 0;
+ return getNumSelectorLocs();
+ }
+
+ static ObjCMessageExpr *alloc(const ASTContext &C,
+ ArrayRef<Expr *> Args,
+ SourceLocation RBraceLoc,
+ ArrayRef<SourceLocation> SelLocs,
+ Selector Sel,
+ SelectorLocationsKind &SelLocsK);
+ static ObjCMessageExpr *alloc(const ASTContext &C,
+ unsigned NumArgs,
+ unsigned NumStoredSelLocs);
+
+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 LBracLoc 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 RBracLoc The location of the closing square bracket ']'.
+ static ObjCMessageExpr *Create(const ASTContext &Context, QualType T,
+ ExprValueKind VK,
+ SourceLocation LBracLoc,
+ SourceLocation SuperLoc,
+ bool IsInstanceSuper,
+ QualType SuperType,
+ Selector Sel,
+ ArrayRef<SourceLocation> SelLocs,
+ ObjCMethodDecl *Method,
+ ArrayRef<Expr *> Args,
+ SourceLocation RBracLoc,
+ bool isImplicit);
+
+ /// \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 LBracLoc 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 RBracLoc The location of the closing square bracket ']'.
+ static ObjCMessageExpr *Create(const ASTContext &Context, QualType T,
+ ExprValueKind VK,
+ SourceLocation LBracLoc,
+ TypeSourceInfo *Receiver,
+ Selector Sel,
+ ArrayRef<SourceLocation> SelLocs,
+ ObjCMethodDecl *Method,
+ ArrayRef<Expr *> Args,
+ SourceLocation RBracLoc,
+ bool isImplicit);
+
+ /// \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 LBracLoc 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 RBracLoc The location of the closing square bracket ']'.
+ static ObjCMessageExpr *Create(const ASTContext &Context, QualType T,
+ ExprValueKind VK,
+ SourceLocation LBracLoc,
+ Expr *Receiver,
+ Selector Sel,
+ ArrayRef<SourceLocation> SeLocs,
+ ObjCMethodDecl *Method,
+ ArrayRef<Expr *> Args,
+ SourceLocation RBracLoc,
+ bool isImplicit);
+
+ /// \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(const ASTContext &Context,
+ unsigned NumArgs,
+ unsigned NumStoredSelLocs);
+
+ /// \brief Indicates whether the message send was implicitly
+ /// generated by the implementation. If false, it was written explicitly
+ /// in the source code.
+ bool isImplicit() const { return IsImplicit; }
+
+ /// \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 object expression (receiver) 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 nullptr;
+ }
+ 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 nullptr;
+ }
+
+ 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 receiver type to which this message is being directed.
+ ///
+ /// 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 type of the receiver.
+ QualType getReceiverType() const;
+
+ /// \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 nullptr;
+ }
+
+ ObjCMethodDecl *getMethodDecl() {
+ if (HasMethod)
+ return reinterpret_cast<ObjCMethodDecl *>(SelectorOrMethod);
+
+ return nullptr;
+ }
+
+ void setMethodDecl(ObjCMethodDecl *MD) {
+ HasMethod = true;
+ SelectorOrMethod = reinterpret_cast<uintptr_t>(MD);
+ }
+
+ ObjCMethodFamily getMethodFamily() const {
+ if (HasMethod) return getMethodDecl()->getMethodFamily();
+ return getSelector().getMethodFamily();
+ }
+
+ /// \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 **>(getTrailingObjects<void *>() + 1);
+ }
+ const Expr * const *getArgs() const {
+ return reinterpret_cast<const Expr *const *>(getTrailingObjects<void *>() +
+ 1);
+ }
+
+ /// getArg - Return the specified argument.
+ Expr *getArg(unsigned Arg) {
+ assert(Arg < NumArgs && "Arg access out of range!");
+ return getArgs()[Arg];
+ }
+ const Expr *getArg(unsigned Arg) const {
+ assert(Arg < NumArgs && "Arg access out of range!");
+ return getArgs()[Arg];
+ }
+ /// setArg - Set the specified argument.
+ void setArg(unsigned Arg, Expr *ArgExpr) {
+ assert(Arg < NumArgs && "Arg access out of range!");
+ getArgs()[Arg] = ArgExpr;
+ }
+
+ /// isDelegateInitCall - Answers whether this message send has been
+ /// tagged as a "delegate init call", i.e. a call to a method in the
+ /// -init family on self from within an -init method implementation.
+ bool isDelegateInitCall() const { return IsDelegateInitCall; }
+ void setDelegateInitCall(bool isDelegate) { IsDelegateInitCall = isDelegate; }
+
+ SourceLocation getLeftLoc() const { return LBracLoc; }
+ SourceLocation getRightLoc() const { return RBracLoc; }
+
+ SourceLocation getSelectorStartLoc() const {
+ if (isImplicit())
+ return getLocStart();
+ return getSelectorLoc(0);
+ }
+ SourceLocation getSelectorLoc(unsigned Index) const {
+ assert(Index < getNumSelectorLocs() && "Index out of range!");
+ if (hasStandardSelLocs())
+ return getStandardSelectorLoc(Index, getSelector(),
+ getSelLocsKind() == SelLoc_StandardWithSpace,
+ llvm::makeArrayRef(const_cast<Expr**>(getArgs()),
+ getNumArgs()),
+ RBracLoc);
+ return getStoredSelLocs()[Index];
+ }
+
+ void getSelectorLocs(SmallVectorImpl<SourceLocation> &SelLocs) const;
+
+ unsigned getNumSelectorLocs() const {
+ if (isImplicit())
+ return 0;
+ Selector Sel = getSelector();
+ if (Sel.isUnarySelector())
+ return 1;
+ return Sel.getNumArgs();
+ }
+
+ void setSourceRange(SourceRange R) {
+ LBracLoc = R.getBegin();
+ RBracLoc = R.getEnd();
+ }
+ SourceLocation getLocStart() const LLVM_READONLY { return LBracLoc; }
+ SourceLocation getLocEnd() const LLVM_READONLY { return RBracLoc; }
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == ObjCMessageExprClass;
+ }
+
+ // Iterators
+ child_range children();
+
+ typedef ExprIterator arg_iterator;
+ typedef ConstExprIterator const_arg_iterator;
+
+ llvm::iterator_range<arg_iterator> arguments() {
+ return llvm::make_range(arg_begin(), arg_end());
+ }
+
+ llvm::iterator_range<const_arg_iterator> arguments() const {
+ return llvm::make_range(arg_begin(), arg_end());
+ }
+
+ 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 TrailingObjects;
+ friend class ASTStmtReader;
+ friend class ASTStmtWriter;
+};
+
+/// ObjCIsaExpr - Represent X->isa and X.isa when X is an ObjC 'id' type.
+/// (similar 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;
+
+ /// OpLoc - This is the location of '.' or '->'
+ SourceLocation OpLoc;
+
+ /// IsArrow - True if this is "X->F", false if this is "X.F".
+ bool IsArrow;
+public:
+ ObjCIsaExpr(Expr *base, bool isarrow, SourceLocation l, SourceLocation oploc,
+ QualType ty)
+ : Expr(ObjCIsaExprClass, ty, VK_LValue, OK_Ordinary,
+ /*TypeDependent=*/false, base->isValueDependent(),
+ base->isInstantiationDependent(),
+ /*ContainsUnexpandedParameterPack=*/false),
+ Base(base), IsaMemberLoc(l), OpLoc(oploc), 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; }
+
+ SourceLocation getOpLoc() const { return OpLoc; }
+ void setOpLoc(SourceLocation L) { OpLoc = L; }
+
+ SourceLocation getLocStart() const LLVM_READONLY {
+ return getBase()->getLocStart();
+ }
+
+ SourceLocation getBaseLocEnd() const LLVM_READONLY {
+ return getBase()->getLocEnd();
+ }
+
+ SourceLocation getLocEnd() const LLVM_READONLY { return IsaMemberLoc; }
+
+ SourceLocation getExprLoc() const LLVM_READONLY { return IsaMemberLoc; }
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == ObjCIsaExprClass;
+ }
+
+ // Iterators
+ child_range children() { return child_range(&Base, &Base+1); }
+};
+
+
+/// ObjCIndirectCopyRestoreExpr - Represents the passing of a function
+/// argument by indirect copy-restore in ARC. This is used to support
+/// passing indirect arguments with the wrong lifetime, e.g. when
+/// passing the address of a __strong local variable to an 'out'
+/// parameter. This expression kind is only valid in an "argument"
+/// position to some sort of call expression.
+///
+/// The parameter must have type 'pointer to T', and the argument must
+/// have type 'pointer to U', where T and U agree except possibly in
+/// qualification. If the argument value is null, then a null pointer
+/// is passed; otherwise it points to an object A, and:
+/// 1. A temporary object B of type T is initialized, either by
+/// zero-initialization (used when initializing an 'out' parameter)
+/// or copy-initialization (used when initializing an 'inout'
+/// parameter).
+/// 2. The address of the temporary is passed to the function.
+/// 3. If the call completes normally, A is move-assigned from B.
+/// 4. Finally, A is destroyed immediately.
+///
+/// Currently 'T' must be a retainable object lifetime and must be
+/// __autoreleasing; this qualifier is ignored when initializing
+/// the value.
+class ObjCIndirectCopyRestoreExpr : public Expr {
+ Stmt *Operand;
+
+ // unsigned ObjCIndirectCopyRestoreBits.ShouldCopy : 1;
+
+ friend class ASTReader;
+ friend class ASTStmtReader;
+
+ void setShouldCopy(bool shouldCopy) {
+ ObjCIndirectCopyRestoreExprBits.ShouldCopy = shouldCopy;
+ }
+
+ explicit ObjCIndirectCopyRestoreExpr(EmptyShell Empty)
+ : Expr(ObjCIndirectCopyRestoreExprClass, Empty) { }
+
+public:
+ ObjCIndirectCopyRestoreExpr(Expr *operand, QualType type, bool shouldCopy)
+ : Expr(ObjCIndirectCopyRestoreExprClass, type, VK_LValue, OK_Ordinary,
+ operand->isTypeDependent(), operand->isValueDependent(),
+ operand->isInstantiationDependent(),
+ operand->containsUnexpandedParameterPack()),
+ Operand(operand) {
+ setShouldCopy(shouldCopy);
+ }
+
+ Expr *getSubExpr() { return cast<Expr>(Operand); }
+ const Expr *getSubExpr() const { return cast<Expr>(Operand); }
+
+ /// shouldCopy - True if we should do the 'copy' part of the
+ /// copy-restore. If false, the temporary will be zero-initialized.
+ bool shouldCopy() const { return ObjCIndirectCopyRestoreExprBits.ShouldCopy; }
+
+ child_range children() { return child_range(&Operand, &Operand+1); }
+
+ // Source locations are determined by the subexpression.
+ SourceLocation getLocStart() const LLVM_READONLY {
+ return Operand->getLocStart();
+ }
+ SourceLocation getLocEnd() const LLVM_READONLY { return Operand->getLocEnd();}
+
+ SourceLocation getExprLoc() const LLVM_READONLY {
+ return getSubExpr()->getExprLoc();
+ }
+
+ static bool classof(const Stmt *s) {
+ return s->getStmtClass() == ObjCIndirectCopyRestoreExprClass;
+ }
+};
+
+/// \brief An Objective-C "bridged" cast expression, which casts between
+/// Objective-C pointers and C pointers, transferring ownership in the process.
+///
+/// \code
+/// NSString *str = (__bridge_transfer NSString *)CFCreateString();
+/// \endcode
+class ObjCBridgedCastExpr final
+ : public ExplicitCastExpr,
+ private llvm::TrailingObjects<ObjCBridgedCastExpr, CXXBaseSpecifier *> {
+ SourceLocation LParenLoc;
+ SourceLocation BridgeKeywordLoc;
+ unsigned Kind : 2;
+
+ friend TrailingObjects;
+ friend class CastExpr;
+ friend class ASTStmtReader;
+ friend class ASTStmtWriter;
+
+public:
+ ObjCBridgedCastExpr(SourceLocation LParenLoc, ObjCBridgeCastKind Kind,
+ CastKind CK, SourceLocation BridgeKeywordLoc,
+ TypeSourceInfo *TSInfo, Expr *Operand)
+ : ExplicitCastExpr(ObjCBridgedCastExprClass, TSInfo->getType(), VK_RValue,
+ CK, Operand, 0, TSInfo),
+ LParenLoc(LParenLoc), BridgeKeywordLoc(BridgeKeywordLoc), Kind(Kind) { }
+
+ /// \brief Construct an empty Objective-C bridged cast.
+ explicit ObjCBridgedCastExpr(EmptyShell Shell)
+ : ExplicitCastExpr(ObjCBridgedCastExprClass, Shell, 0) { }
+
+ SourceLocation getLParenLoc() const { return LParenLoc; }
+
+ /// \brief Determine which kind of bridge is being performed via this cast.
+ ObjCBridgeCastKind getBridgeKind() const {
+ return static_cast<ObjCBridgeCastKind>(Kind);
+ }
+
+ /// \brief Retrieve the kind of bridge being performed as a string.
+ StringRef getBridgeKindName() const;
+
+ /// \brief The location of the bridge keyword.
+ SourceLocation getBridgeKeywordLoc() const { return BridgeKeywordLoc; }
+
+ SourceLocation getLocStart() const LLVM_READONLY { return LParenLoc; }
+ SourceLocation getLocEnd() const LLVM_READONLY {
+ return getSubExpr()->getLocEnd();
+ }
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == ObjCBridgedCastExprClass;
+ }
+};
+
+} // end namespace clang
+
+#endif
diff --git a/contrib/llvm/tools/clang/include/clang/AST/ExprOpenMP.h b/contrib/llvm/tools/clang/include/clang/AST/ExprOpenMP.h
new file mode 100644
index 0000000..2d71a3a
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/AST/ExprOpenMP.h
@@ -0,0 +1,129 @@
+//===--- ExprOpenMP.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_EXPROPENMP_H
+#define LLVM_CLANG_AST_EXPROPENMP_H
+
+#include "clang/AST/Expr.h"
+
+namespace clang {
+/// \brief OpenMP 4.0 [2.4, Array Sections].
+/// To specify an array section in an OpenMP construct, array subscript
+/// expressions are extended with the following syntax:
+/// \code
+/// [ lower-bound : length ]
+/// [ lower-bound : ]
+/// [ : length ]
+/// [ : ]
+/// \endcode
+/// The array section must be a subset of the original array.
+/// Array sections are allowed on multidimensional arrays. Base language array
+/// subscript expressions can be used to specify length-one dimensions of
+/// multidimensional array sections.
+/// The lower-bound and length are integral type expressions. When evaluated
+/// they represent a set of integer values as follows:
+/// \code
+/// { lower-bound, lower-bound + 1, lower-bound + 2,... , lower-bound + length -
+/// 1 }
+/// \endcode
+/// The lower-bound and length must evaluate to non-negative integers.
+/// When the size of the array dimension is not known, the length must be
+/// specified explicitly.
+/// When the length is absent, it defaults to the size of the array dimension
+/// minus the lower-bound.
+/// When the lower-bound is absent it defaults to 0.
+class OMPArraySectionExpr : public Expr {
+ enum { BASE, LOWER_BOUND, LENGTH, END_EXPR };
+ Stmt *SubExprs[END_EXPR];
+ SourceLocation ColonLoc;
+ SourceLocation RBracketLoc;
+
+public:
+ OMPArraySectionExpr(Expr *Base, Expr *LowerBound, Expr *Length, QualType Type,
+ ExprValueKind VK, ExprObjectKind OK,
+ SourceLocation ColonLoc, SourceLocation RBracketLoc)
+ : Expr(
+ OMPArraySectionExprClass, Type, VK, OK,
+ Base->isTypeDependent() ||
+ (LowerBound && LowerBound->isTypeDependent()) ||
+ (Length && Length->isTypeDependent()),
+ Base->isValueDependent() ||
+ (LowerBound && LowerBound->isValueDependent()) ||
+ (Length && Length->isValueDependent()),
+ Base->isInstantiationDependent() ||
+ (LowerBound && LowerBound->isInstantiationDependent()) ||
+ (Length && Length->isInstantiationDependent()),
+ Base->containsUnexpandedParameterPack() ||
+ (LowerBound && LowerBound->containsUnexpandedParameterPack()) ||
+ (Length && Length->containsUnexpandedParameterPack())),
+ ColonLoc(ColonLoc), RBracketLoc(RBracketLoc) {
+ SubExprs[BASE] = Base;
+ SubExprs[LOWER_BOUND] = LowerBound;
+ SubExprs[LENGTH] = Length;
+ }
+
+ /// \brief Create an empty array section expression.
+ explicit OMPArraySectionExpr(EmptyShell Shell)
+ : Expr(OMPArraySectionExprClass, Shell) {}
+
+ /// An array section can be written only as Base[LowerBound:Length].
+
+ /// \brief Get base of the array section.
+ Expr *getBase() { return cast<Expr>(SubExprs[BASE]); }
+ const Expr *getBase() const { return cast<Expr>(SubExprs[BASE]); }
+ /// \brief Set base of the array section.
+ void setBase(Expr *E) { SubExprs[BASE] = E; }
+
+ /// \brief Return original type of the base expression for array section.
+ static QualType getBaseOriginalType(Expr *Base);
+
+ /// \brief Get lower bound of array section.
+ Expr *getLowerBound() { return cast_or_null<Expr>(SubExprs[LOWER_BOUND]); }
+ const Expr *getLowerBound() const {
+ return cast_or_null<Expr>(SubExprs[LOWER_BOUND]);
+ }
+ /// \brief Set lower bound of the array section.
+ void setLowerBound(Expr *E) { SubExprs[LOWER_BOUND] = E; }
+
+ /// \brief Get length of array section.
+ Expr *getLength() { return cast_or_null<Expr>(SubExprs[LENGTH]); }
+ const Expr *getLength() const { return cast_or_null<Expr>(SubExprs[LENGTH]); }
+ /// \brief Set length of the array section.
+ void setLength(Expr *E) { SubExprs[LENGTH] = E; }
+
+ SourceLocation getLocStart() const LLVM_READONLY {
+ return getBase()->getLocStart();
+ }
+ SourceLocation getLocEnd() const LLVM_READONLY { return RBracketLoc; }
+
+ SourceLocation getColonLoc() const { return ColonLoc; }
+ void setColonLoc(SourceLocation L) { ColonLoc = L; }
+
+ SourceLocation getRBracketLoc() const { return RBracketLoc; }
+ void setRBracketLoc(SourceLocation L) { RBracketLoc = L; }
+
+ SourceLocation getExprLoc() const LLVM_READONLY {
+ return getBase()->getExprLoc();
+ }
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == OMPArraySectionExprClass;
+ }
+
+ child_range children() {
+ return child_range(&SubExprs[BASE], &SubExprs[END_EXPR]);
+ }
+};
+} // 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..81cf631
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/AST/ExternalASTSource.h
@@ -0,0 +1,578 @@
+//===--- 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.
+//
+//===----------------------------------------------------------------------===//
+#ifndef LLVM_CLANG_AST_EXTERNALASTSOURCE_H
+#define LLVM_CLANG_AST_EXTERNALASTSOURCE_H
+
+#include "clang/AST/CharUnits.h"
+#include "clang/AST/DeclBase.h"
+#include "llvm/ADT/DenseMap.h"
+
+namespace clang {
+
+class ASTConsumer;
+class CXXBaseSpecifier;
+class CXXCtorInitializer;
+class DeclarationName;
+class ExternalSemaSource; // layering violation required for downcasting
+class FieldDecl;
+class Module;
+class NamedDecl;
+class RecordDecl;
+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 : public RefCountedBase<ExternalASTSource> {
+ /// Generation number for this external AST source. Must be increased
+ /// whenever we might have added new redeclarations for existing decls.
+ uint32_t CurrentGeneration;
+
+ /// \brief Whether this AST source also provides information for
+ /// semantic analysis.
+ bool SemaSource;
+
+ friend class ExternalSemaSource;
+
+public:
+ ExternalASTSource() : CurrentGeneration(0), 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 Get the current generation of this AST source. This number
+ /// is incremented each time the AST source lazily extends an existing
+ /// entity.
+ uint32_t getGeneration() const { return CurrentGeneration; }
+
+ /// \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.
+ ///
+ /// The default implementation of this method is a no-op.
+ virtual Decl *GetExternalDecl(uint32_t ID);
+
+ /// \brief Resolve a selector ID into a selector.
+ ///
+ /// This operation only needs to be implemented if the AST source
+ /// returns non-zero for GetNumKnownSelectors().
+ ///
+ /// The default implementation of this method is a no-op.
+ virtual Selector GetExternalSelector(uint32_t ID);
+
+ /// \brief Returns the number of selectors known to the external AST
+ /// source.
+ ///
+ /// The default implementation of this method is a no-op.
+ virtual uint32_t GetNumExternalSelectors();
+
+ /// \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.
+ ///
+ /// The default implementation of this method is a no-op.
+ virtual Stmt *GetExternalDeclStmt(uint64_t Offset);
+
+ /// \brief Resolve the offset of a set of C++ constructor initializers in
+ /// the decl stream into an array of initializers.
+ ///
+ /// The default implementation of this method is a no-op.
+ virtual CXXCtorInitializer **GetExternalCXXCtorInitializers(uint64_t Offset);
+
+ /// \brief Resolve the offset of a set of C++ base specifiers in the decl
+ /// stream into an array of specifiers.
+ ///
+ /// The default implementation of this method is a no-op.
+ virtual CXXBaseSpecifier *GetExternalCXXBaseSpecifiers(uint64_t Offset);
+
+ /// \brief Update an out-of-date identifier.
+ virtual void updateOutOfDateIdentifier(IdentifierInfo &II) { }
+
+ /// \brief Find all declarations with the given name in the given context,
+ /// and add them to the context by calling SetExternalVisibleDeclsForName
+ /// or SetNoExternalVisibleDeclsForName.
+ /// \return \c true if any declarations might have been found, \c false if
+ /// we definitely have no declarations with tbis name.
+ ///
+ /// The default implementation of this method is a no-op returning \c false.
+ virtual bool
+ FindExternalVisibleDeclsByName(const DeclContext *DC, DeclarationName Name);
+
+ /// \brief Ensures that the table of all visible declarations inside this
+ /// context is up to date.
+ ///
+ /// The default implementation of this function is a no-op.
+ virtual void completeVisibleDeclsMap(const DeclContext *DC);
+
+ /// \brief Retrieve the module that corresponds to the given module ID.
+ virtual Module *getModule(unsigned ID) { return nullptr; }
+
+ /// Abstracts clang modules and precompiled header files and holds
+ /// everything needed to generate debug info for an imported module
+ /// or PCH.
+ class ASTSourceDescriptor {
+ StringRef PCHModuleName;
+ StringRef Path;
+ StringRef ASTFile;
+ uint64_t Signature = 0;
+ const Module *ClangModule = nullptr;
+
+ public:
+ ASTSourceDescriptor(){};
+ ASTSourceDescriptor(StringRef Name, StringRef Path, StringRef ASTFile,
+ uint64_t Signature)
+ : PCHModuleName(std::move(Name)), Path(std::move(Path)),
+ ASTFile(std::move(ASTFile)), Signature(Signature){};
+ ASTSourceDescriptor(const Module &M);
+ std::string getModuleName() const;
+ StringRef getPath() const { return Path; }
+ StringRef getASTFile() const { return ASTFile; }
+ uint64_t getSignature() const { return Signature; }
+ const Module *getModuleOrNull() const { return ClangModule; }
+ };
+
+ /// Return a descriptor for the corresponding module, if one exists.
+ virtual llvm::Optional<ASTSourceDescriptor> getSourceDescriptor(unsigned ID);
+
+ /// \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.
+ ///
+ /// The default implementation of this method is a no-op.
+ virtual void
+ FindExternalLexicalDecls(const DeclContext *DC,
+ llvm::function_ref<bool(Decl::Kind)> IsKindWeWant,
+ SmallVectorImpl<Decl *> &Result);
+
+ /// \brief Finds all declarations lexically contained within the given
+ /// DeclContext.
+ void FindExternalLexicalDecls(const DeclContext *DC,
+ SmallVectorImpl<Decl *> &Result) {
+ FindExternalLexicalDecls(DC, [](Decl::Kind) { return true; }, Result);
+ }
+
+ /// \brief Get the decls that are contained in a file in the Offset/Length
+ /// range. \p Length can be 0 to indicate a point at \p Offset instead of
+ /// a range.
+ virtual void FindFileRegionDecls(FileID File, unsigned Offset,
+ unsigned Length,
+ SmallVectorImpl<Decl *> &Decls);
+
+ /// \brief Gives the external AST source an opportunity to complete
+ /// the redeclaration chain for a declaration. Called each time we
+ /// need the most recent declaration of a declaration after the
+ /// generation count is incremented.
+ virtual void CompleteRedeclChain(const Decl *D);
+
+ /// \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 Loads comment ranges.
+ virtual void ReadComments();
+
+ /// \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();
+
+
+ /// \brief Perform layout on the given record.
+ ///
+ /// This routine allows the external AST source to provide an specific
+ /// layout for a record, overriding the layout that would normally be
+ /// constructed. It is intended for clients who receive specific layout
+ /// details rather than source code (such as LLDB). The client is expected
+ /// to fill in the field offsets, base offsets, virtual base offsets, and
+ /// complete object size.
+ ///
+ /// \param Record The record whose layout is being requested.
+ ///
+ /// \param Size The final size of the record, in bits.
+ ///
+ /// \param Alignment The final alignment of the record, in bits.
+ ///
+ /// \param FieldOffsets The offset of each of the fields within the record,
+ /// expressed in bits. All of the fields must be provided with offsets.
+ ///
+ /// \param BaseOffsets The offset of each of the direct, non-virtual base
+ /// classes. If any bases are not given offsets, the bases will be laid
+ /// out according to the ABI.
+ ///
+ /// \param VirtualBaseOffsets The offset of each of the virtual base classes
+ /// (either direct or not). If any bases are not given offsets, the bases will be laid
+ /// out according to the ABI.
+ ///
+ /// \returns true if the record layout was provided, false otherwise.
+ virtual bool layoutRecordType(
+ const RecordDecl *Record, uint64_t &Size, uint64_t &Alignment,
+ llvm::DenseMap<const FieldDecl *, uint64_t> &FieldOffsets,
+ llvm::DenseMap<const CXXRecordDecl *, CharUnits> &BaseOffsets,
+ llvm::DenseMap<const CXXRecordDecl *, CharUnits> &VirtualBaseOffsets);
+
+ //===--------------------------------------------------------------------===//
+ // Queries for performance analysis.
+ //===--------------------------------------------------------------------===//
+
+ struct MemoryBufferSizes {
+ size_t malloc_bytes;
+ size_t mmap_bytes;
+
+ MemoryBufferSizes(size_t malloc_bytes, size_t mmap_bytes)
+ : malloc_bytes(malloc_bytes), mmap_bytes(mmap_bytes) {}
+ };
+
+ /// Return the amount of memory used by memory buffers, breaking down
+ /// by heap-backed versus mmap'ed memory.
+ MemoryBufferSizes getMemoryBufferSizes() const {
+ MemoryBufferSizes sizes(0, 0);
+ getMemoryBufferSizes(sizes);
+ return sizes;
+ }
+
+ virtual void getMemoryBufferSizes(MemoryBufferSizes &sizes) const;
+
+protected:
+ static DeclContextLookupResult
+ SetExternalVisibleDeclsForName(const DeclContext *DC,
+ DeclarationName Name,
+ ArrayRef<NamedDecl*> Decls);
+
+ static DeclContextLookupResult
+ SetNoExternalVisibleDeclsForName(const DeclContext *DC,
+ DeclarationName Name);
+
+ /// \brief Increment the current generation.
+ uint32_t incrementGeneration(ASTContext &C);
+};
+
+/// \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.
+ explicit operator bool() const { return Ptr != 0; }
+
+ /// \brief Whether this pointer is non-NULL.
+ ///
+ /// This operation does not require the AST node to be deserialized.
+ bool isValid() 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 value (of type T) that is within an AST node of type Owner,
+/// where the value might change in later generations of the external AST
+/// source.
+template<typename Owner, typename T, void (ExternalASTSource::*Update)(Owner)>
+struct LazyGenerationalUpdatePtr {
+ /// A cache of the value of this pointer, in the most recent generation in
+ /// which we queried it.
+ struct LazyData {
+ LazyData(ExternalASTSource *Source, T Value)
+ : ExternalSource(Source), LastGeneration(0), LastValue(Value) {}
+ ExternalASTSource *ExternalSource;
+ uint32_t LastGeneration;
+ T LastValue;
+ };
+
+ // Our value is represented as simply T if there is no external AST source.
+ typedef llvm::PointerUnion<T, LazyData*> ValueType;
+ ValueType Value;
+
+ LazyGenerationalUpdatePtr(ValueType V) : Value(V) {}
+
+ // Defined in ASTContext.h
+ static ValueType makeValue(const ASTContext &Ctx, T Value);
+
+public:
+ explicit LazyGenerationalUpdatePtr(const ASTContext &Ctx, T Value = T())
+ : Value(makeValue(Ctx, Value)) {}
+
+ /// Create a pointer that is not potentially updated by later generations of
+ /// the external AST source.
+ enum NotUpdatedTag { NotUpdated };
+ LazyGenerationalUpdatePtr(NotUpdatedTag, T Value = T())
+ : Value(Value) {}
+
+ /// Forcibly set this pointer (which must be lazy) as needing updates.
+ void markIncomplete() {
+ Value.template get<LazyData *>()->LastGeneration = 0;
+ }
+
+ /// Set the value of this pointer, in the current generation.
+ void set(T NewValue) {
+ if (LazyData *LazyVal = Value.template dyn_cast<LazyData*>()) {
+ LazyVal->LastValue = NewValue;
+ return;
+ }
+ Value = NewValue;
+ }
+
+ /// Set the value of this pointer, for this and all future generations.
+ void setNotUpdated(T NewValue) { Value = NewValue; }
+
+ /// Get the value of this pointer, updating its owner if necessary.
+ T get(Owner O) {
+ if (LazyData *LazyVal = Value.template dyn_cast<LazyData*>()) {
+ if (LazyVal->LastGeneration != LazyVal->ExternalSource->getGeneration()) {
+ LazyVal->LastGeneration = LazyVal->ExternalSource->getGeneration();
+ (LazyVal->ExternalSource->*Update)(O);
+ }
+ return LazyVal->LastValue;
+ }
+ return Value.template get<T>();
+ }
+
+ /// Get the most recently computed value of this pointer without updating it.
+ T getNotUpdated() const {
+ if (LazyData *LazyVal = Value.template dyn_cast<LazyData*>())
+ return LazyVal->LastValue;
+ return Value.template get<T>();
+ }
+
+ void *getOpaqueValue() { return Value.getOpaqueValue(); }
+ static LazyGenerationalUpdatePtr getFromOpaqueValue(void *Ptr) {
+ return LazyGenerationalUpdatePtr(ValueType::getFromOpaqueValue(Ptr));
+ }
+};
+} // end namespace clang
+
+/// Specialize PointerLikeTypeTraits to allow LazyGenerationalUpdatePtr to be
+/// placed into a PointerUnion.
+namespace llvm {
+template<typename Owner, typename T,
+ void (clang::ExternalASTSource::*Update)(Owner)>
+struct PointerLikeTypeTraits<
+ clang::LazyGenerationalUpdatePtr<Owner, T, Update>> {
+ typedef clang::LazyGenerationalUpdatePtr<Owner, T, Update> Ptr;
+ static void *getAsVoidPointer(Ptr P) { return P.getOpaqueValue(); }
+ static Ptr getFromVoidPointer(void *P) { return Ptr::getFromOpaqueValue(P); }
+ enum {
+ NumLowBitsAvailable = PointerLikeTypeTraits<T>::NumLowBitsAvailable - 1
+ };
+};
+}
+
+namespace clang {
+/// \brief Represents a lazily-loaded vector of data.
+///
+/// The lazily-loaded vector of data contains data that is partially loaded
+/// from an external source and partially added by local translation. The
+/// items loaded from the external source are loaded lazily, when needed for
+/// iteration over the complete vector.
+template<typename T, typename Source,
+ void (Source::*Loader)(SmallVectorImpl<T>&),
+ unsigned LoadedStorage = 2, unsigned LocalStorage = 4>
+class LazyVector {
+ SmallVector<T, LoadedStorage> Loaded;
+ SmallVector<T, LocalStorage> Local;
+
+public:
+ /// Iteration over the elements in the vector.
+ ///
+ /// In a complete iteration, the iterator walks the range [-M, N),
+ /// where negative values are used to indicate elements
+ /// loaded from the external source while non-negative values are used to
+ /// indicate elements added via \c push_back().
+ /// However, to provide iteration in source order (for, e.g., chained
+ /// precompiled headers), dereferencing the iterator flips the negative
+ /// values (corresponding to loaded entities), so that position -M
+ /// corresponds to element 0 in the loaded entities vector, position -M+1
+ /// corresponds to element 1 in the loaded entities vector, etc. This
+ /// gives us a reasonably efficient, source-order walk.
+ ///
+ /// We define this as a wrapping iterator around an int. The
+ /// iterator_adaptor_base class forwards the iterator methods to basic integer
+ /// arithmetic.
+ class iterator : public llvm::iterator_adaptor_base<
+ iterator, int, std::random_access_iterator_tag, T, int> {
+ LazyVector *Self;
+
+ iterator(LazyVector *Self, int Position)
+ : iterator::iterator_adaptor_base(Position), Self(Self) {}
+
+ bool isLoaded() const { return this->I < 0; }
+ friend class LazyVector;
+
+ public:
+ iterator() : iterator(nullptr, 0) {}
+
+ typename iterator::reference operator*() const {
+ if (isLoaded())
+ return Self->Loaded.end()[this->I];
+ return Self->Local.begin()[this->I];
+ }
+ };
+
+ iterator begin(Source *source, bool LocalOnly = false) {
+ if (LocalOnly)
+ return iterator(this, 0);
+
+ if (source)
+ (source->*Loader)(Loaded);
+ return iterator(this, -(int)Loaded.size());
+ }
+
+ iterator end() {
+ return iterator(this, Local.size());
+ }
+
+ void push_back(const T& LocalValue) {
+ Local.push_back(LocalValue);
+ }
+
+ void erase(iterator From, iterator To) {
+ if (From.isLoaded() && To.isLoaded()) {
+ Loaded.erase(&*From, &*To);
+ return;
+ }
+
+ if (From.isLoaded()) {
+ Loaded.erase(&*From, Loaded.end());
+ From = begin(nullptr, true);
+ }
+
+ Local.erase(&*From, &*To);
+ }
+};
+
+/// \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 CXXCtorInitializers.
+typedef LazyOffsetPtr<CXXCtorInitializer *, uint64_t,
+ &ExternalASTSource::GetExternalCXXCtorInitializers>
+ LazyCXXCtorInitializersPtr;
+
+/// \brief A lazy pointer to a set of CXXBaseSpecifiers.
+typedef LazyOffsetPtr<CXXBaseSpecifier, uint64_t,
+ &ExternalASTSource::GetExternalCXXBaseSpecifiers>
+ LazyCXXBaseSpecifiersPtr;
+
+} // end namespace clang
+
+#endif
diff --git a/contrib/llvm/tools/clang/include/clang/AST/GlobalDecl.h b/contrib/llvm/tools/clang/include/clang/AST/GlobalDecl.h
new file mode 100644
index 0000000..54c9d88
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/AST/GlobalDecl.h
@@ -0,0 +1,125 @@
+//===--- 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 LLVM_CLANG_AST_GLOBALDECL_H
+#define LLVM_CLANG_AST_GLOBALDECL_H
+
+#include "clang/AST/DeclCXX.h"
+#include "clang/AST/DeclObjC.h"
+#include "clang/Basic/ABI.h"
+
+namespace clang {
+
+/// 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 CapturedDecl *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 clang
+
+namespace llvm {
+ template<class> struct DenseMapInfo;
+
+ template<> struct DenseMapInfo<clang::GlobalDecl> {
+ static inline clang::GlobalDecl getEmptyKey() {
+ return clang::GlobalDecl();
+ }
+
+ static inline clang::GlobalDecl getTombstoneKey() {
+ return clang::GlobalDecl::
+ getFromOpaquePtr(reinterpret_cast<void*>(-1));
+ }
+
+ static unsigned getHashValue(clang::GlobalDecl GD) {
+ return DenseMapInfo<void*>::getHashValue(GD.getAsOpaquePtr());
+ }
+
+ static bool isEqual(clang::GlobalDecl LHS,
+ clang::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::GlobalDecl> {
+ static const bool value = true;
+ };
+} // end namespace llvm
+
+#endif
diff --git a/contrib/llvm/tools/clang/include/clang/AST/LambdaCapture.h b/contrib/llvm/tools/clang/include/clang/AST/LambdaCapture.h
new file mode 100644
index 0000000..ddefa88
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/AST/LambdaCapture.h
@@ -0,0 +1,128 @@
+//===--- LambdaCapture.h - Types for C++ Lambda Captures --------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+///
+/// \file
+/// \brief Defines the LambdaCapture class.
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_AST_LAMBDACAPTURE_H
+#define LLVM_CLANG_AST_LAMBDACAPTURE_H
+
+#include "clang/AST/Decl.h"
+#include "clang/Basic/Lambda.h"
+#include "llvm/ADT/PointerIntPair.h"
+
+namespace clang {
+
+/// \brief Describes the capture of a variable or of \c this, or of a
+/// C++1y init-capture.
+class LambdaCapture {
+ enum {
+ /// \brief Flag used by the Capture class to indicate that the given
+ /// capture was implicit.
+ Capture_Implicit = 0x01,
+
+ /// \brief Flag used by the Capture class to indicate that the
+ /// given capture was by-copy.
+ ///
+ /// This includes the case of a non-reference init-capture.
+ Capture_ByCopy = 0x02
+ };
+
+ llvm::PointerIntPair<Decl *, 2> DeclAndBits;
+ SourceLocation Loc;
+ SourceLocation EllipsisLoc;
+
+ friend class ASTStmtReader;
+ friend class ASTStmtWriter;
+
+public:
+ /// \brief Create a new capture of a variable or of \c this.
+ ///
+ /// \param Loc The source location associated with this capture.
+ ///
+ /// \param Kind The kind of capture (this, byref, bycopy), which must
+ /// not be init-capture.
+ ///
+ /// \param Implicit Whether the capture was implicit or explicit.
+ ///
+ /// \param Var The local variable being captured, or null if capturing
+ /// \c this.
+ ///
+ /// \param EllipsisLoc The location of the ellipsis (...) for a
+ /// capture that is a pack expansion, or an invalid source
+ /// location to indicate that this is not a pack expansion.
+ LambdaCapture(SourceLocation Loc, bool Implicit, LambdaCaptureKind Kind,
+ VarDecl *Var = nullptr,
+ SourceLocation EllipsisLoc = SourceLocation());
+
+ /// \brief Determine the kind of capture.
+ LambdaCaptureKind getCaptureKind() const;
+
+ /// \brief Determine whether this capture handles the C++ \c this
+ /// pointer.
+ bool capturesThis() const {
+ return (DeclAndBits.getPointer() == nullptr) &&
+ !(DeclAndBits.getInt() & Capture_ByCopy);
+ }
+
+ /// \brief Determine whether this capture handles a variable.
+ bool capturesVariable() const {
+ return dyn_cast_or_null<VarDecl>(DeclAndBits.getPointer());
+ }
+
+ /// \brief Determine whether this captures a variable length array bound
+ /// expression.
+ bool capturesVLAType() const {
+ return (DeclAndBits.getPointer() == nullptr) &&
+ (DeclAndBits.getInt() & Capture_ByCopy);
+ }
+
+ /// \brief Retrieve the declaration of the local variable being
+ /// captured.
+ ///
+ /// This operation is only valid if this capture is a variable capture
+ /// (other than a capture of \c this).
+ VarDecl *getCapturedVar() const {
+ assert(capturesVariable() && "No variable available for 'this' capture");
+ return cast<VarDecl>(DeclAndBits.getPointer());
+ }
+
+ /// \brief Determine whether this was an implicit capture (not
+ /// written between the square brackets introducing the lambda).
+ bool isImplicit() const { return DeclAndBits.getInt() & Capture_Implicit; }
+
+ /// \brief Determine whether this was an explicit capture (written
+ /// between the square brackets introducing the lambda).
+ bool isExplicit() const { return !isImplicit(); }
+
+ /// \brief Retrieve the source location of the capture.
+ ///
+ /// For an explicit capture, this returns the location of the
+ /// explicit capture in the source. For an implicit capture, this
+ /// returns the location at which the variable or \c this was first
+ /// used.
+ SourceLocation getLocation() const { return Loc; }
+
+ /// \brief Determine whether this capture is a pack expansion,
+ /// which captures a function parameter pack.
+ bool isPackExpansion() const { return EllipsisLoc.isValid(); }
+
+ /// \brief Retrieve the location of the ellipsis for a capture
+ /// that is a pack expansion.
+ SourceLocation getEllipsisLoc() const {
+ assert(isPackExpansion() && "No ellipsis location for a non-expansion");
+ return EllipsisLoc;
+ }
+};
+
+} // end namespace clang
+
+#endif // LLVM_CLANG_AST_LAMBDACAPTURE_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..4872738
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/AST/Mangle.h
@@ -0,0 +1,243 @@
+//===--- 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/SmallString.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/Support/Casting.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 StringLiteral;
+ struct ThisAdjustment;
+ struct ThunkInfo;
+ class VarDecl;
+
+/// MangleContext - Context for tracking state which persists across multiple
+/// calls to the C++ name mangler.
+class MangleContext {
+public:
+ enum ManglerKind {
+ MK_Itanium,
+ MK_Microsoft
+ };
+
+private:
+ virtual void anchor();
+
+ ASTContext &Context;
+ DiagnosticsEngine &Diags;
+ const ManglerKind Kind;
+
+ llvm::DenseMap<const BlockDecl*, unsigned> GlobalBlockIds;
+ llvm::DenseMap<const BlockDecl*, unsigned> LocalBlockIds;
+ llvm::DenseMap<const TagDecl*, uint64_t> AnonStructIds;
+
+public:
+ ManglerKind getKind() const { return Kind; }
+
+ explicit MangleContext(ASTContext &Context,
+ DiagnosticsEngine &Diags,
+ ManglerKind Kind)
+ : Context(Context), Diags(Diags), Kind(Kind) {}
+
+ virtual ~MangleContext() { }
+
+ ASTContext &getASTContext() const { return Context; }
+
+ DiagnosticsEngine &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;
+ }
+
+ 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;
+ }
+
+ /// @name Mangler Entry Points
+ /// @{
+
+ bool shouldMangleDeclName(const NamedDecl *D);
+ virtual bool shouldMangleCXXName(const NamedDecl *D) = 0;
+ virtual bool shouldMangleStringLiteral(const StringLiteral *SL) = 0;
+
+ // FIXME: consider replacing raw_ostream & with something like SmallString &.
+ void mangleName(const NamedDecl *D, raw_ostream &);
+ virtual void mangleCXXName(const NamedDecl *D, raw_ostream &) = 0;
+ virtual void mangleThunk(const CXXMethodDecl *MD,
+ const ThunkInfo &Thunk,
+ raw_ostream &) = 0;
+ virtual void mangleCXXDtorThunk(const CXXDestructorDecl *DD, CXXDtorType Type,
+ const ThisAdjustment &ThisAdjustment,
+ raw_ostream &) = 0;
+ virtual void mangleReferenceTemporary(const VarDecl *D,
+ unsigned ManglingNumber,
+ raw_ostream &) = 0;
+ virtual void mangleCXXRTTI(QualType T, raw_ostream &) = 0;
+ virtual void mangleCXXRTTIName(QualType T, raw_ostream &) = 0;
+ virtual void mangleCXXCtor(const CXXConstructorDecl *D, CXXCtorType Type,
+ raw_ostream &) = 0;
+ virtual void mangleCXXDtor(const CXXDestructorDecl *D, CXXDtorType Type,
+ raw_ostream &) = 0;
+ virtual void mangleStringLiteral(const StringLiteral *SL, raw_ostream &) = 0;
+
+ void mangleGlobalBlock(const BlockDecl *BD,
+ const NamedDecl *ID,
+ raw_ostream &Out);
+ void mangleCtorBlock(const CXXConstructorDecl *CD, CXXCtorType CT,
+ const BlockDecl *BD, raw_ostream &Out);
+ void mangleDtorBlock(const CXXDestructorDecl *CD, CXXDtorType DT,
+ const BlockDecl *BD, raw_ostream &Out);
+ void mangleBlock(const DeclContext *DC, const BlockDecl *BD,
+ raw_ostream &Out);
+
+ void mangleObjCMethodName(const ObjCMethodDecl *MD, raw_ostream &);
+
+ virtual void mangleStaticGuardVariable(const VarDecl *D, raw_ostream &) = 0;
+
+ virtual void mangleDynamicInitializer(const VarDecl *D, raw_ostream &) = 0;
+
+ virtual void mangleDynamicAtExitDestructor(const VarDecl *D,
+ raw_ostream &) = 0;
+
+ virtual void mangleSEHFilterExpression(const NamedDecl *EnclosingDecl,
+ raw_ostream &Out) = 0;
+
+ virtual void mangleSEHFinallyBlock(const NamedDecl *EnclosingDecl,
+ raw_ostream &Out) = 0;
+
+ /// Generates a unique string for an externally visible type for use with TBAA
+ /// or type uniquing.
+ /// TODO: Extend this to internal types by generating names that are unique
+ /// across translation units so it can be used with LTO.
+ virtual void mangleTypeName(QualType T, raw_ostream &) = 0;
+
+ /// @}
+};
+
+class ItaniumMangleContext : public MangleContext {
+public:
+ explicit ItaniumMangleContext(ASTContext &C, DiagnosticsEngine &D)
+ : MangleContext(C, D, MK_Itanium) {}
+
+ virtual void mangleCXXVTable(const CXXRecordDecl *RD, raw_ostream &) = 0;
+ virtual void mangleCXXVTT(const CXXRecordDecl *RD, raw_ostream &) = 0;
+ virtual void mangleCXXCtorVTable(const CXXRecordDecl *RD, int64_t Offset,
+ const CXXRecordDecl *Type,
+ raw_ostream &) = 0;
+ virtual void mangleItaniumThreadLocalInit(const VarDecl *D,
+ raw_ostream &) = 0;
+ virtual void mangleItaniumThreadLocalWrapper(const VarDecl *D,
+ raw_ostream &) = 0;
+
+ virtual void mangleCXXCtorComdat(const CXXConstructorDecl *D,
+ raw_ostream &) = 0;
+ virtual void mangleCXXDtorComdat(const CXXDestructorDecl *D,
+ raw_ostream &) = 0;
+
+ static bool classof(const MangleContext *C) {
+ return C->getKind() == MK_Itanium;
+ }
+
+ static ItaniumMangleContext *create(ASTContext &Context,
+ DiagnosticsEngine &Diags);
+};
+
+class MicrosoftMangleContext : public MangleContext {
+public:
+ explicit MicrosoftMangleContext(ASTContext &C, DiagnosticsEngine &D)
+ : MangleContext(C, D, MK_Microsoft) {}
+
+ /// \brief Mangle vftable symbols. Only a subset of the bases along the path
+ /// to the vftable are included in the name. It's up to the caller to pick
+ /// them correctly.
+ virtual void mangleCXXVFTable(const CXXRecordDecl *Derived,
+ ArrayRef<const CXXRecordDecl *> BasePath,
+ raw_ostream &Out) = 0;
+
+ /// \brief Mangle vbtable symbols. Only a subset of the bases along the path
+ /// to the vbtable are included in the name. It's up to the caller to pick
+ /// them correctly.
+ virtual void mangleCXXVBTable(const CXXRecordDecl *Derived,
+ ArrayRef<const CXXRecordDecl *> BasePath,
+ raw_ostream &Out) = 0;
+
+ virtual void mangleThreadSafeStaticGuardVariable(const VarDecl *VD,
+ unsigned GuardNum,
+ raw_ostream &Out) = 0;
+
+ virtual void mangleVirtualMemPtrThunk(const CXXMethodDecl *MD,
+ raw_ostream &) = 0;
+
+ virtual void mangleCXXVirtualDisplacementMap(const CXXRecordDecl *SrcRD,
+ const CXXRecordDecl *DstRD,
+ raw_ostream &Out) = 0;
+
+ virtual void mangleCXXThrowInfo(QualType T, bool IsConst, bool IsVolatile,
+ uint32_t NumEntries, raw_ostream &Out) = 0;
+
+ virtual void mangleCXXCatchableTypeArray(QualType T, uint32_t NumEntries,
+ raw_ostream &Out) = 0;
+
+ virtual void mangleCXXCatchableType(QualType T, const CXXConstructorDecl *CD,
+ CXXCtorType CT, uint32_t Size,
+ uint32_t NVOffset, int32_t VBPtrOffset,
+ uint32_t VBIndex, raw_ostream &Out) = 0;
+
+ virtual void mangleCXXRTTIBaseClassDescriptor(
+ const CXXRecordDecl *Derived, uint32_t NVOffset, int32_t VBPtrOffset,
+ uint32_t VBTableOffset, uint32_t Flags, raw_ostream &Out) = 0;
+
+ virtual void mangleCXXRTTIBaseClassArray(const CXXRecordDecl *Derived,
+ raw_ostream &Out) = 0;
+ virtual void
+ mangleCXXRTTIClassHierarchyDescriptor(const CXXRecordDecl *Derived,
+ raw_ostream &Out) = 0;
+
+ virtual void
+ mangleCXXRTTICompleteObjectLocator(const CXXRecordDecl *Derived,
+ ArrayRef<const CXXRecordDecl *> BasePath,
+ raw_ostream &Out) = 0;
+
+ static bool classof(const MangleContext *C) {
+ return C->getKind() == MK_Microsoft;
+ }
+
+ static MicrosoftMangleContext *create(ASTContext &Context,
+ DiagnosticsEngine &Diags);
+};
+}
+
+#endif
diff --git a/contrib/llvm/tools/clang/include/clang/AST/MangleNumberingContext.h b/contrib/llvm/tools/clang/include/clang/AST/MangleNumberingContext.h
new file mode 100644
index 0000000..7a81855
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/AST/MangleNumberingContext.h
@@ -0,0 +1,60 @@
+//=== MangleNumberingContext.h - Context for mangling numbers ---*- C++ -*-===//
+//
+// 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 LambdaBlockMangleContext interface, which keeps track
+// of the Itanium C++ ABI mangling numbers for lambda expressions and block
+// literals.
+//
+//===----------------------------------------------------------------------===//
+#ifndef LLVM_CLANG_AST_MANGLENUMBERINGCONTEXT_H
+#define LLVM_CLANG_AST_MANGLENUMBERINGCONTEXT_H
+
+#include "clang/Basic/LLVM.h"
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/IntrusiveRefCntPtr.h"
+
+namespace clang {
+
+class BlockDecl;
+class CXXMethodDecl;
+class IdentifierInfo;
+class TagDecl;
+class Type;
+class VarDecl;
+
+/// \brief Keeps track of the mangled names of lambda expressions and block
+/// literals within a particular context.
+class MangleNumberingContext : public RefCountedBase<MangleNumberingContext> {
+public:
+ virtual ~MangleNumberingContext() {}
+
+ /// \brief Retrieve the mangling number of a new lambda expression with the
+ /// given call operator within this context.
+ virtual unsigned getManglingNumber(const CXXMethodDecl *CallOperator) = 0;
+
+ /// \brief Retrieve the mangling number of a new block literal within this
+ /// context.
+ virtual unsigned getManglingNumber(const BlockDecl *BD) = 0;
+
+ /// Static locals are numbered by source order.
+ virtual unsigned getStaticLocalNumber(const VarDecl *VD) = 0;
+
+ /// \brief Retrieve the mangling number of a static local variable within
+ /// this context.
+ virtual unsigned getManglingNumber(const VarDecl *VD,
+ unsigned MSLocalManglingNumber) = 0;
+
+ /// \brief Retrieve the mangling number of a static local variable within
+ /// this context.
+ virtual unsigned getManglingNumber(const TagDecl *TD,
+ unsigned MSLocalManglingNumber) = 0;
+};
+
+} // end namespace clang
+#endif
diff --git a/contrib/llvm/tools/clang/include/clang/AST/NSAPI.h b/contrib/llvm/tools/clang/include/clang/AST/NSAPI.h
new file mode 100644
index 0000000..583f9d9
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/AST/NSAPI.h
@@ -0,0 +1,262 @@
+//===--- NSAPI.h - NSFoundation APIs ----------------------------*- 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_AST_NSAPI_H
+#define LLVM_CLANG_AST_NSAPI_H
+
+#include "clang/Basic/IdentifierTable.h"
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/Optional.h"
+
+namespace clang {
+ class ASTContext;
+ class ObjCInterfaceDecl;
+ class QualType;
+ class Expr;
+
+// \brief Provides info and caches identifiers/selectors for NSFoundation API.
+class NSAPI {
+public:
+ explicit NSAPI(ASTContext &Ctx);
+
+ ASTContext &getASTContext() const { return Ctx; }
+
+ enum NSClassIdKindKind {
+ ClassId_NSObject,
+ ClassId_NSString,
+ ClassId_NSArray,
+ ClassId_NSMutableArray,
+ ClassId_NSDictionary,
+ ClassId_NSMutableDictionary,
+ ClassId_NSNumber,
+ ClassId_NSMutableSet,
+ ClassId_NSMutableOrderedSet,
+ ClassId_NSValue
+ };
+ static const unsigned NumClassIds = 10;
+
+ enum NSStringMethodKind {
+ NSStr_stringWithString,
+ NSStr_stringWithUTF8String,
+ NSStr_stringWithCStringEncoding,
+ NSStr_stringWithCString,
+ NSStr_initWithString,
+ NSStr_initWithUTF8String
+ };
+ static const unsigned NumNSStringMethods = 5;
+
+ IdentifierInfo *getNSClassId(NSClassIdKindKind K) const;
+
+ /// \brief The Objective-C NSString selectors.
+ Selector getNSStringSelector(NSStringMethodKind MK) const;
+
+ /// \brief Return NSStringMethodKind if \param Sel is such a selector.
+ Optional<NSStringMethodKind> getNSStringMethodKind(Selector Sel) const;
+
+ /// \brief Returns true if the expression \param E is a reference of
+ /// "NSUTF8StringEncoding" enum constant.
+ bool isNSUTF8StringEncodingConstant(const Expr *E) const {
+ return isObjCEnumerator(E, "NSUTF8StringEncoding", NSUTF8StringEncodingId);
+ }
+
+ /// \brief Returns true if the expression \param E is a reference of
+ /// "NSASCIIStringEncoding" enum constant.
+ bool isNSASCIIStringEncodingConstant(const Expr *E) const {
+ return isObjCEnumerator(E, "NSASCIIStringEncoding",NSASCIIStringEncodingId);
+ }
+
+ /// \brief Enumerates the NSArray/NSMutableArray methods used to generate
+ /// literals and to apply some checks.
+ enum NSArrayMethodKind {
+ NSArr_array,
+ NSArr_arrayWithArray,
+ NSArr_arrayWithObject,
+ NSArr_arrayWithObjects,
+ NSArr_arrayWithObjectsCount,
+ NSArr_initWithArray,
+ NSArr_initWithObjects,
+ NSArr_objectAtIndex,
+ NSMutableArr_replaceObjectAtIndex,
+ NSMutableArr_addObject,
+ NSMutableArr_insertObjectAtIndex,
+ NSMutableArr_setObjectAtIndexedSubscript
+ };
+ static const unsigned NumNSArrayMethods = 12;
+
+ /// \brief The Objective-C NSArray selectors.
+ Selector getNSArraySelector(NSArrayMethodKind MK) const;
+
+ /// \brief Return NSArrayMethodKind if \p Sel is such a selector.
+ Optional<NSArrayMethodKind> getNSArrayMethodKind(Selector Sel);
+
+ /// \brief Enumerates the NSDictionary/NSMutableDictionary methods used
+ /// to generate literals and to apply some checks.
+ enum NSDictionaryMethodKind {
+ NSDict_dictionary,
+ NSDict_dictionaryWithDictionary,
+ NSDict_dictionaryWithObjectForKey,
+ NSDict_dictionaryWithObjectsForKeys,
+ NSDict_dictionaryWithObjectsForKeysCount,
+ NSDict_dictionaryWithObjectsAndKeys,
+ NSDict_initWithDictionary,
+ NSDict_initWithObjectsAndKeys,
+ NSDict_initWithObjectsForKeys,
+ NSDict_objectForKey,
+ NSMutableDict_setObjectForKey,
+ NSMutableDict_setObjectForKeyedSubscript,
+ NSMutableDict_setValueForKey
+ };
+ static const unsigned NumNSDictionaryMethods = 14;
+
+ /// \brief The Objective-C NSDictionary selectors.
+ Selector getNSDictionarySelector(NSDictionaryMethodKind MK) const;
+
+ /// \brief Return NSDictionaryMethodKind if \p Sel is such a selector.
+ Optional<NSDictionaryMethodKind> getNSDictionaryMethodKind(Selector Sel);
+
+ /// \brief Enumerates the NSMutableSet/NSOrderedSet methods used
+ /// to apply some checks.
+ enum NSSetMethodKind {
+ NSMutableSet_addObject,
+ NSOrderedSet_insertObjectAtIndex,
+ NSOrderedSet_setObjectAtIndex,
+ NSOrderedSet_setObjectAtIndexedSubscript,
+ NSOrderedSet_replaceObjectAtIndexWithObject
+ };
+ static const unsigned NumNSSetMethods = 5;
+
+ /// \brief The Objective-C NSSet selectors.
+ Selector getNSSetSelector(NSSetMethodKind MK) const;
+
+ /// \brief Return NSSetMethodKind if \p Sel is such a selector.
+ Optional<NSSetMethodKind> getNSSetMethodKind(Selector Sel);
+
+ /// \brief Returns selector for "objectForKeyedSubscript:".
+ Selector getObjectForKeyedSubscriptSelector() const {
+ return getOrInitSelector(StringRef("objectForKeyedSubscript"),
+ objectForKeyedSubscriptSel);
+ }
+
+ /// \brief Returns selector for "objectAtIndexedSubscript:".
+ Selector getObjectAtIndexedSubscriptSelector() const {
+ return getOrInitSelector(StringRef("objectAtIndexedSubscript"),
+ objectAtIndexedSubscriptSel);
+ }
+
+ /// \brief Returns selector for "setObject:forKeyedSubscript".
+ Selector getSetObjectForKeyedSubscriptSelector() const {
+ StringRef Ids[] = { "setObject", "forKeyedSubscript" };
+ return getOrInitSelector(Ids, setObjectForKeyedSubscriptSel);
+ }
+
+ /// \brief Returns selector for "setObject:atIndexedSubscript".
+ Selector getSetObjectAtIndexedSubscriptSelector() const {
+ StringRef Ids[] = { "setObject", "atIndexedSubscript" };
+ return getOrInitSelector(Ids, setObjectAtIndexedSubscriptSel);
+ }
+
+ /// \brief Returns selector for "isEqual:".
+ Selector getIsEqualSelector() const {
+ return getOrInitSelector(StringRef("isEqual"), isEqualSel);
+ }
+
+ /// \brief Enumerates the NSNumber methods used to generate literals.
+ enum NSNumberLiteralMethodKind {
+ NSNumberWithChar,
+ NSNumberWithUnsignedChar,
+ NSNumberWithShort,
+ NSNumberWithUnsignedShort,
+ NSNumberWithInt,
+ NSNumberWithUnsignedInt,
+ NSNumberWithLong,
+ NSNumberWithUnsignedLong,
+ NSNumberWithLongLong,
+ NSNumberWithUnsignedLongLong,
+ NSNumberWithFloat,
+ NSNumberWithDouble,
+ NSNumberWithBool,
+ NSNumberWithInteger,
+ NSNumberWithUnsignedInteger
+ };
+ static const unsigned NumNSNumberLiteralMethods = 15;
+
+ /// \brief The Objective-C NSNumber selectors used to create NSNumber literals.
+ /// \param Instance if true it will return the selector for the init* method
+ /// otherwise it will return the selector for the number* method.
+ Selector getNSNumberLiteralSelector(NSNumberLiteralMethodKind MK,
+ bool Instance) const;
+
+ bool isNSNumberLiteralSelector(NSNumberLiteralMethodKind MK,
+ Selector Sel) const {
+ return Sel == getNSNumberLiteralSelector(MK, false) ||
+ Sel == getNSNumberLiteralSelector(MK, true);
+ }
+
+ /// \brief Return NSNumberLiteralMethodKind if \p Sel is such a selector.
+ Optional<NSNumberLiteralMethodKind>
+ getNSNumberLiteralMethodKind(Selector Sel) const;
+
+ /// \brief Determine the appropriate NSNumber factory method kind for a
+ /// literal of the given type.
+ Optional<NSNumberLiteralMethodKind>
+ getNSNumberFactoryMethodKind(QualType T) const;
+
+ /// \brief Returns true if \param T is a typedef of "BOOL" in objective-c.
+ bool isObjCBOOLType(QualType T) const;
+ /// \brief Returns true if \param T is a typedef of "NSInteger" in objective-c.
+ bool isObjCNSIntegerType(QualType T) const;
+ /// \brief Returns true if \param T is a typedef of "NSUInteger" in objective-c.
+ bool isObjCNSUIntegerType(QualType T) const;
+ /// \brief Returns one of NSIntegral typedef names if \param T is a typedef
+ /// of that name in objective-c.
+ StringRef GetNSIntegralKind(QualType T) const;
+
+ /// \brief Returns \c true if \p Id is currently defined as a macro.
+ bool isMacroDefined(StringRef Id) const;
+
+ /// \brief Returns \c true if \p InterfaceDecl is subclass of \p NSClassKind
+ bool isSubclassOfNSClass(ObjCInterfaceDecl *InterfaceDecl,
+ NSClassIdKindKind NSClassKind) const;
+
+private:
+ bool isObjCTypedef(QualType T, StringRef name, IdentifierInfo *&II) const;
+ bool isObjCEnumerator(const Expr *E,
+ StringRef name, IdentifierInfo *&II) const;
+ Selector getOrInitSelector(ArrayRef<StringRef> Ids, Selector &Sel) const;
+
+ ASTContext &Ctx;
+
+ mutable IdentifierInfo *ClassIds[NumClassIds];
+
+ mutable Selector NSStringSelectors[NumNSStringMethods];
+
+ /// \brief The selectors for Objective-C NSArray methods.
+ mutable Selector NSArraySelectors[NumNSArrayMethods];
+
+ /// \brief The selectors for Objective-C NSDictionary methods.
+ mutable Selector NSDictionarySelectors[NumNSDictionaryMethods];
+
+ /// \brief The selectors for Objective-C NSSet methods.
+ mutable Selector NSSetSelectors[NumNSSetMethods];
+
+ /// \brief The Objective-C NSNumber selectors used to create NSNumber literals.
+ mutable Selector NSNumberClassSelectors[NumNSNumberLiteralMethods];
+ mutable Selector NSNumberInstanceSelectors[NumNSNumberLiteralMethods];
+
+ mutable Selector objectForKeyedSubscriptSel, objectAtIndexedSubscriptSel,
+ setObjectForKeyedSubscriptSel,setObjectAtIndexedSubscriptSel,
+ isEqualSel;
+
+ mutable IdentifierInfo *BOOLId, *NSIntegerId, *NSUIntegerId;
+ mutable IdentifierInfo *NSASCIIStringEncodingId, *NSUTF8StringEncodingId;
+};
+
+} // end namespace clang
+
+#endif // LLVM_CLANG_AST_NSAPI_H
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..b1ff9bd
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/AST/NestedNameSpecifier.h
@@ -0,0 +1,516 @@
+//===--- 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"
+#include "llvm/Support/Compiler.h"
+
+namespace clang {
+
+class ASTContext;
+class CXXRecordDecl;
+class NamespaceAliasDecl;
+class NamespaceDecl;
+class IdentifierInfo;
+struct PrintingPolicy;
+class Type;
+class TypeLoc;
+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), decltype specifier, or the global specifier ('::').
+/// The last two specifiers can only appear at the start of a
+/// nested-namespace-specifier.
+class NestedNameSpecifier : public llvm::FoldingSetNode {
+
+ /// \brief Enumeration describing
+ enum StoredSpecifierKind {
+ StoredIdentifier = 0,
+ StoredDecl = 1,
+ StoredTypeSpec = 2,
+ StoredTypeSpecWithTemplate = 3
+ };
+
+ /// \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, StoredSpecifierKind> 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,
+ /// \brief A namespace, stored as a NamespaceDecl*.
+ Namespace,
+ /// \brief A namespace alias, stored as a NamespaceAliasDecl*.
+ NamespaceAlias,
+ /// \brief A type, stored as a Type*.
+ TypeSpec,
+ /// \brief A type that was preceded by the 'template' keyword,
+ /// stored as a Type*.
+ TypeSpecWithTemplate,
+ /// \brief The global specifier '::'. There is no stored value.
+ Global,
+ /// \brief Microsoft's '__super' specifier, stored as a CXXRecordDecl* of
+ /// the class it appeared in.
+ Super
+ };
+
+private:
+ /// \brief Builds the global specifier.
+ NestedNameSpecifier()
+ : Prefix(nullptr, StoredIdentifier), Specifier(nullptr) {}
+
+ /// \brief Copy constructor used internally to clone nested name
+ /// specifiers.
+ NestedNameSpecifier(const NestedNameSpecifier &Other)
+ : llvm::FoldingSetNode(Other), Prefix(Other.Prefix),
+ Specifier(Other.Specifier) {
+ }
+
+ void operator=(const NestedNameSpecifier &) = delete;
+
+ /// \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,
+ const NamespaceDecl *NS);
+
+ /// \brief Builds a nested name specifier that names a namespace alias.
+ static NestedNameSpecifier *Create(const ASTContext &Context,
+ NestedNameSpecifier *Prefix,
+ NamespaceAliasDecl *Alias);
+
+ /// \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 Returns the nested name specifier representing the __super scope
+ /// for the given CXXRecordDecl.
+ static NestedNameSpecifier *SuperSpecifier(const ASTContext &Context,
+ CXXRecordDecl *RD);
+
+ /// \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;
+
+ /// \brief Retrieve the identifier stored in this nested name
+ /// specifier.
+ IdentifierInfo *getAsIdentifier() const {
+ if (Prefix.getInt() == StoredIdentifier)
+ return (IdentifierInfo *)Specifier;
+
+ return nullptr;
+ }
+
+ /// \brief Retrieve the namespace stored in this nested name
+ /// specifier.
+ NamespaceDecl *getAsNamespace() const;
+
+ /// \brief Retrieve the namespace alias stored in this nested name
+ /// specifier.
+ NamespaceAliasDecl *getAsNamespaceAlias() const;
+
+ /// \brief Retrieve the record declaration stored in this nested name
+ /// specifier.
+ CXXRecordDecl *getAsRecordDecl() const;
+
+ /// \brief Retrieve the type stored in this nested name specifier.
+ const Type *getAsType() const {
+ if (Prefix.getInt() == StoredTypeSpec ||
+ Prefix.getInt() == StoredTypeSpecWithTemplate)
+ return (const Type *)Specifier;
+
+ return nullptr;
+ }
+
+ /// \brief Whether this nested name specifier refers to a dependent
+ /// type or not.
+ bool isDependent() const;
+
+ /// \brief Whether this nested name specifier involves a template
+ /// parameter.
+ bool isInstantiationDependent() const;
+
+ /// \brief Whether this nested-name-specifier contains an unexpanded
+ /// parameter pack (for C++11 variadic templates).
+ bool containsUnexpandedParameterPack() const;
+
+ /// \brief Print this nested name specifier to the given output
+ /// stream.
+ void print(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) const;
+ void dump() const;
+};
+
+/// \brief A C++ nested-name-specifier augmented with source location
+/// information.
+class NestedNameSpecifierLoc {
+ NestedNameSpecifier *Qualifier;
+ void *Data;
+
+ /// \brief Determines the data length for the last component in the
+ /// given nested-name-specifier.
+ static unsigned getLocalDataLength(NestedNameSpecifier *Qualifier);
+
+ /// \brief Determines the data length for the entire
+ /// nested-name-specifier.
+ static unsigned getDataLength(NestedNameSpecifier *Qualifier);
+
+public:
+ /// \brief Construct an empty nested-name-specifier.
+ NestedNameSpecifierLoc() : Qualifier(nullptr), Data(nullptr) { }
+
+ /// \brief Construct a nested-name-specifier with source location information
+ /// from
+ NestedNameSpecifierLoc(NestedNameSpecifier *Qualifier, void *Data)
+ : Qualifier(Qualifier), Data(Data) { }
+
+ /// \brief Evalutes true when this nested-name-specifier location is
+ /// non-empty.
+ explicit operator bool() const { return Qualifier; }
+
+ /// \brief Evalutes true when this nested-name-specifier location is
+ /// empty.
+ bool hasQualifier() const { return Qualifier; }
+
+ /// \brief Retrieve the nested-name-specifier to which this instance
+ /// refers.
+ NestedNameSpecifier *getNestedNameSpecifier() const {
+ return Qualifier;
+ }
+
+ /// \brief Retrieve the opaque pointer that refers to source-location data.
+ void *getOpaqueData() const { return Data; }
+
+ /// \brief Retrieve the source range covering the entirety of this
+ /// nested-name-specifier.
+ ///
+ /// For example, if this instance refers to a nested-name-specifier
+ /// \c \::std::vector<int>::, the returned source range would cover
+ /// from the initial '::' to the last '::'.
+ SourceRange getSourceRange() const LLVM_READONLY;
+
+ /// \brief Retrieve the source range covering just the last part of
+ /// this nested-name-specifier, not including the prefix.
+ ///
+ /// For example, if this instance refers to a nested-name-specifier
+ /// \c \::std::vector<int>::, the returned source range would cover
+ /// from "vector" to the last '::'.
+ SourceRange getLocalSourceRange() const;
+
+ /// \brief Retrieve the location of the beginning of this
+ /// nested-name-specifier.
+ SourceLocation getBeginLoc() const {
+ return getSourceRange().getBegin();
+ }
+
+ /// \brief Retrieve the location of the end of this
+ /// nested-name-specifier.
+ SourceLocation getEndLoc() const {
+ return getSourceRange().getEnd();
+ }
+
+ /// \brief Retrieve the location of the beginning of this
+ /// component of the nested-name-specifier.
+ SourceLocation getLocalBeginLoc() const {
+ return getLocalSourceRange().getBegin();
+ }
+
+ /// \brief Retrieve the location of the end of this component of the
+ /// nested-name-specifier.
+ SourceLocation getLocalEndLoc() const {
+ return getLocalSourceRange().getEnd();
+ }
+
+ /// \brief Return the prefix of this nested-name-specifier.
+ ///
+ /// For example, if this instance refers to a nested-name-specifier
+ /// \c \::std::vector<int>::, the prefix is \c \::std::. Note that the
+ /// returned prefix may be empty, if this is the first component of
+ /// the nested-name-specifier.
+ NestedNameSpecifierLoc getPrefix() const {
+ if (!Qualifier)
+ return *this;
+
+ return NestedNameSpecifierLoc(Qualifier->getPrefix(), Data);
+ }
+
+ /// \brief For a nested-name-specifier that refers to a type,
+ /// retrieve the type with source-location information.
+ TypeLoc getTypeLoc() const;
+
+ /// \brief Determines the data length for the entire
+ /// nested-name-specifier.
+ unsigned getDataLength() const { return getDataLength(Qualifier); }
+
+ friend bool operator==(NestedNameSpecifierLoc X,
+ NestedNameSpecifierLoc Y) {
+ return X.Qualifier == Y.Qualifier && X.Data == Y.Data;
+ }
+
+ friend bool operator!=(NestedNameSpecifierLoc X,
+ NestedNameSpecifierLoc Y) {
+ return !(X == Y);
+ }
+};
+
+/// \brief Class that aids in the construction of nested-name-specifiers along
+/// with source-location information for all of the components of the
+/// nested-name-specifier.
+class NestedNameSpecifierLocBuilder {
+ /// \brief The current representation of the nested-name-specifier we're
+ /// building.
+ NestedNameSpecifier *Representation;
+
+ /// \brief Buffer used to store source-location information for the
+ /// nested-name-specifier.
+ ///
+ /// Note that we explicitly manage the buffer (rather than using a
+ /// SmallVector) because \c Declarator expects it to be possible to memcpy()
+ /// a \c CXXScopeSpec, and CXXScopeSpec uses a NestedNameSpecifierLocBuilder.
+ char *Buffer;
+
+ /// \brief The size of the buffer used to store source-location information
+ /// for the nested-name-specifier.
+ unsigned BufferSize;
+
+ /// \brief The capacity of the buffer used to store source-location
+ /// information for the nested-name-specifier.
+ unsigned BufferCapacity;
+
+public:
+ NestedNameSpecifierLocBuilder()
+ : Representation(nullptr), Buffer(nullptr), BufferSize(0),
+ BufferCapacity(0) {}
+
+ NestedNameSpecifierLocBuilder(const NestedNameSpecifierLocBuilder &Other);
+
+ NestedNameSpecifierLocBuilder &
+ operator=(const NestedNameSpecifierLocBuilder &Other);
+
+ ~NestedNameSpecifierLocBuilder() {
+ if (BufferCapacity)
+ free(Buffer);
+ }
+
+ /// \brief Retrieve the representation of the nested-name-specifier.
+ NestedNameSpecifier *getRepresentation() const { return Representation; }
+
+ /// \brief Extend the current nested-name-specifier by another
+ /// nested-name-specifier component of the form 'type::'.
+ ///
+ /// \param Context The AST context in which this nested-name-specifier
+ /// resides.
+ ///
+ /// \param TemplateKWLoc The location of the 'template' keyword, if present.
+ ///
+ /// \param TL The TypeLoc that describes the type preceding the '::'.
+ ///
+ /// \param ColonColonLoc The location of the trailing '::'.
+ void Extend(ASTContext &Context, SourceLocation TemplateKWLoc, TypeLoc TL,
+ SourceLocation ColonColonLoc);
+
+ /// \brief Extend the current nested-name-specifier by another
+ /// nested-name-specifier component of the form 'identifier::'.
+ ///
+ /// \param Context The AST context in which this nested-name-specifier
+ /// resides.
+ ///
+ /// \param Identifier The identifier.
+ ///
+ /// \param IdentifierLoc The location of the identifier.
+ ///
+ /// \param ColonColonLoc The location of the trailing '::'.
+ void Extend(ASTContext &Context, IdentifierInfo *Identifier,
+ SourceLocation IdentifierLoc, SourceLocation ColonColonLoc);
+
+ /// \brief Extend the current nested-name-specifier by another
+ /// nested-name-specifier component of the form 'namespace::'.
+ ///
+ /// \param Context The AST context in which this nested-name-specifier
+ /// resides.
+ ///
+ /// \param Namespace The namespace.
+ ///
+ /// \param NamespaceLoc The location of the namespace name.
+ ///
+ /// \param ColonColonLoc The location of the trailing '::'.
+ void Extend(ASTContext &Context, NamespaceDecl *Namespace,
+ SourceLocation NamespaceLoc, SourceLocation ColonColonLoc);
+
+ /// \brief Extend the current nested-name-specifier by another
+ /// nested-name-specifier component of the form 'namespace-alias::'.
+ ///
+ /// \param Context The AST context in which this nested-name-specifier
+ /// resides.
+ ///
+ /// \param Alias The namespace alias.
+ ///
+ /// \param AliasLoc The location of the namespace alias
+ /// name.
+ ///
+ /// \param ColonColonLoc The location of the trailing '::'.
+ void Extend(ASTContext &Context, NamespaceAliasDecl *Alias,
+ SourceLocation AliasLoc, SourceLocation ColonColonLoc);
+
+ /// \brief Turn this (empty) nested-name-specifier into the global
+ /// nested-name-specifier '::'.
+ void MakeGlobal(ASTContext &Context, SourceLocation ColonColonLoc);
+
+ /// \brief Turns this (empty) nested-name-specifier into '__super'
+ /// nested-name-specifier.
+ ///
+ /// \param Context The AST context in which this nested-name-specifier
+ /// resides.
+ ///
+ /// \param RD The declaration of the class in which nested-name-specifier
+ /// appeared.
+ ///
+ /// \param SuperLoc The location of the '__super' keyword.
+ /// name.
+ ///
+ /// \param ColonColonLoc The location of the trailing '::'.
+ void MakeSuper(ASTContext &Context, CXXRecordDecl *RD,
+ SourceLocation SuperLoc, SourceLocation ColonColonLoc);
+ /// \brief Make a new nested-name-specifier from incomplete source-location
+ /// information.
+ ///
+ /// This routine should be used very, very rarely, in cases where we
+ /// need to synthesize a nested-name-specifier. Most code should instead use
+ /// \c Adopt() with a proper \c NestedNameSpecifierLoc.
+ void MakeTrivial(ASTContext &Context, NestedNameSpecifier *Qualifier,
+ SourceRange R);
+
+ /// \brief Adopt an existing nested-name-specifier (with source-range
+ /// information).
+ void Adopt(NestedNameSpecifierLoc Other);
+
+ /// \brief Retrieve the source range covered by this nested-name-specifier.
+ SourceRange getSourceRange() const LLVM_READONLY {
+ return NestedNameSpecifierLoc(Representation, Buffer).getSourceRange();
+ }
+
+ /// \brief Retrieve a nested-name-specifier with location information,
+ /// copied into the given AST context.
+ ///
+ /// \param Context The context into which this nested-name-specifier will be
+ /// copied.
+ NestedNameSpecifierLoc getWithLocInContext(ASTContext &Context) const;
+
+ /// \brief Retrieve a nested-name-specifier with location
+ /// information based on the information in this builder.
+ ///
+ /// This loc will contain references to the builder's internal data and may
+ /// be invalidated by any change to the builder.
+ NestedNameSpecifierLoc getTemporary() const {
+ return NestedNameSpecifierLoc(Representation, Buffer);
+ }
+
+ /// \brief Clear out this builder, and prepare it to build another
+ /// nested-name-specifier with source-location information.
+ void Clear() {
+ Representation = nullptr;
+ BufferSize = 0;
+ }
+
+ /// \brief Retrieve the underlying buffer.
+ ///
+ /// \returns A pair containing a pointer to the buffer of source-location
+ /// data and the size of the source-location data that resides in that
+ /// buffer.
+ std::pair<char *, unsigned> getBuffer() const {
+ return std::make_pair(Buffer, BufferSize);
+ }
+};
+
+/// 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),
+ DiagnosticsEngine::ak_nestednamespec);
+ return DB;
+}
+
+}
+
+#endif
diff --git a/contrib/llvm/tools/clang/include/clang/AST/OpenMPClause.h b/contrib/llvm/tools/clang/include/clang/AST/OpenMPClause.h
new file mode 100644
index 0000000..7632a4b
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/AST/OpenMPClause.h
@@ -0,0 +1,3198 @@
+//===- OpenMPClause.h - Classes for OpenMP clauses --------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+/// \file
+/// \brief This file defines OpenMP AST classes for clauses.
+/// There are clauses for executable directives, clauses for declarative
+/// directives and clauses which can be used in both kinds of directives.
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_AST_OPENMPCLAUSE_H
+#define LLVM_CLANG_AST_OPENMPCLAUSE_H
+
+#include "clang/AST/Expr.h"
+#include "clang/AST/Stmt.h"
+#include "clang/Basic/OpenMPKinds.h"
+#include "clang/Basic/SourceLocation.h"
+
+namespace clang {
+
+//===----------------------------------------------------------------------===//
+// AST classes for clauses.
+//===----------------------------------------------------------------------===//
+
+/// \brief This is a basic class for representing single OpenMP clause.
+///
+class OMPClause {
+ /// \brief Starting location of the clause (the clause keyword).
+ SourceLocation StartLoc;
+ /// \brief Ending location of the clause.
+ SourceLocation EndLoc;
+ /// \brief Kind of the clause.
+ OpenMPClauseKind Kind;
+
+protected:
+ OMPClause(OpenMPClauseKind K, SourceLocation StartLoc, SourceLocation EndLoc)
+ : StartLoc(StartLoc), EndLoc(EndLoc), Kind(K) {}
+
+public:
+ /// \brief Returns the starting location of the clause.
+ SourceLocation getLocStart() const { return StartLoc; }
+ /// \brief Returns the ending location of the clause.
+ SourceLocation getLocEnd() const { return EndLoc; }
+
+ /// \brief Sets the starting location of the clause.
+ void setLocStart(SourceLocation Loc) { StartLoc = Loc; }
+ /// \brief Sets the ending location of the clause.
+ void setLocEnd(SourceLocation Loc) { EndLoc = Loc; }
+
+ /// \brief Returns kind of OpenMP clause (private, shared, reduction, etc.).
+ OpenMPClauseKind getClauseKind() const { return Kind; }
+
+ bool isImplicit() const { return StartLoc.isInvalid(); }
+
+ typedef StmtIterator child_iterator;
+ typedef ConstStmtIterator const_child_iterator;
+ typedef llvm::iterator_range<child_iterator> child_range;
+ typedef llvm::iterator_range<const_child_iterator> const_child_range;
+
+ child_range children();
+ const_child_range children() const {
+ auto Children = const_cast<OMPClause *>(this)->children();
+ return const_child_range(Children.begin(), Children.end());
+ }
+ static bool classof(const OMPClause *) { return true; }
+};
+
+/// \brief This represents clauses with the list of variables like 'private',
+/// 'firstprivate', 'copyin', 'shared', or 'reduction' clauses in the
+/// '#pragma omp ...' directives.
+template <class T> class OMPVarListClause : public OMPClause {
+ friend class OMPClauseReader;
+ /// \brief Location of '('.
+ SourceLocation LParenLoc;
+ /// \brief Number of variables in the list.
+ unsigned NumVars;
+
+protected:
+ /// \brief Fetches list of variables associated with this clause.
+ MutableArrayRef<Expr *> getVarRefs() {
+ return MutableArrayRef<Expr *>(
+ static_cast<T *>(this)->template getTrailingObjects<Expr *>(), NumVars);
+ }
+
+ /// \brief Sets the list of variables for this clause.
+ void setVarRefs(ArrayRef<Expr *> VL) {
+ assert(VL.size() == NumVars &&
+ "Number of variables is not the same as the preallocated buffer");
+ std::copy(VL.begin(), VL.end(),
+ static_cast<T *>(this)->template getTrailingObjects<Expr *>());
+ }
+
+ /// \brief Build a clause with \a N variables
+ ///
+ /// \param K Kind of the clause.
+ /// \param StartLoc Starting location of the clause (the clause keyword).
+ /// \param LParenLoc Location of '('.
+ /// \param EndLoc Ending location of the clause.
+ /// \param N Number of the variables in the clause.
+ ///
+ OMPVarListClause(OpenMPClauseKind K, SourceLocation StartLoc,
+ SourceLocation LParenLoc, SourceLocation EndLoc, unsigned N)
+ : OMPClause(K, StartLoc, EndLoc), LParenLoc(LParenLoc), NumVars(N) {}
+
+public:
+ typedef MutableArrayRef<Expr *>::iterator varlist_iterator;
+ typedef ArrayRef<const Expr *>::iterator varlist_const_iterator;
+ typedef llvm::iterator_range<varlist_iterator> varlist_range;
+ typedef llvm::iterator_range<varlist_const_iterator> varlist_const_range;
+
+ unsigned varlist_size() const { return NumVars; }
+ bool varlist_empty() const { return NumVars == 0; }
+
+ varlist_range varlists() {
+ return varlist_range(varlist_begin(), varlist_end());
+ }
+ varlist_const_range varlists() const {
+ return varlist_const_range(varlist_begin(), varlist_end());
+ }
+
+ varlist_iterator varlist_begin() { return getVarRefs().begin(); }
+ varlist_iterator varlist_end() { return getVarRefs().end(); }
+ varlist_const_iterator varlist_begin() const { return getVarRefs().begin(); }
+ varlist_const_iterator varlist_end() const { return getVarRefs().end(); }
+
+ /// \brief Sets the location of '('.
+ void setLParenLoc(SourceLocation Loc) { LParenLoc = Loc; }
+ /// \brief Returns the location of '('.
+ SourceLocation getLParenLoc() const { return LParenLoc; }
+
+ /// \brief Fetches list of all variables in the clause.
+ ArrayRef<const Expr *> getVarRefs() const {
+ return llvm::makeArrayRef(
+ static_cast<const T *>(this)->template getTrailingObjects<Expr *>(),
+ NumVars);
+ }
+};
+
+/// \brief This represents 'if' clause in the '#pragma omp ...' directive.
+///
+/// \code
+/// #pragma omp parallel if(parallel:a > 5)
+/// \endcode
+/// In this example directive '#pragma omp parallel' has simple 'if' clause with
+/// condition 'a > 5' and directive name modifier 'parallel'.
+///
+class OMPIfClause : public OMPClause {
+ friend class OMPClauseReader;
+ /// \brief Location of '('.
+ SourceLocation LParenLoc;
+ /// \brief Condition of the 'if' clause.
+ Stmt *Condition;
+ /// \brief Location of ':' (if any).
+ SourceLocation ColonLoc;
+ /// \brief Directive name modifier for the clause.
+ OpenMPDirectiveKind NameModifier;
+ /// \brief Name modifier location.
+ SourceLocation NameModifierLoc;
+
+ /// \brief Set condition.
+ ///
+ void setCondition(Expr *Cond) { Condition = Cond; }
+ /// \brief Set directive name modifier for the clause.
+ ///
+ void setNameModifier(OpenMPDirectiveKind NM) { NameModifier = NM; }
+ /// \brief Set location of directive name modifier for the clause.
+ ///
+ void setNameModifierLoc(SourceLocation Loc) { NameModifierLoc = Loc; }
+ /// \brief Set location of ':'.
+ ///
+ void setColonLoc(SourceLocation Loc) { ColonLoc = Loc; }
+
+public:
+ /// \brief Build 'if' clause with condition \a Cond.
+ ///
+ /// \param NameModifier [OpenMP 4.1] Directive name modifier of clause.
+ /// \param Cond Condition of the clause.
+ /// \param StartLoc Starting location of the clause.
+ /// \param LParenLoc Location of '('.
+ /// \param NameModifierLoc Location of directive name modifier.
+ /// \param ColonLoc [OpenMP 4.1] Location of ':'.
+ /// \param EndLoc Ending location of the clause.
+ ///
+ OMPIfClause(OpenMPDirectiveKind NameModifier, Expr *Cond,
+ SourceLocation StartLoc, SourceLocation LParenLoc,
+ SourceLocation NameModifierLoc, SourceLocation ColonLoc,
+ SourceLocation EndLoc)
+ : OMPClause(OMPC_if, StartLoc, EndLoc), LParenLoc(LParenLoc),
+ Condition(Cond), ColonLoc(ColonLoc), NameModifier(NameModifier),
+ NameModifierLoc(NameModifierLoc) {}
+
+ /// \brief Build an empty clause.
+ ///
+ OMPIfClause()
+ : OMPClause(OMPC_if, SourceLocation(), SourceLocation()), LParenLoc(),
+ Condition(nullptr), ColonLoc(), NameModifier(OMPD_unknown),
+ NameModifierLoc() {}
+
+ /// \brief Sets the location of '('.
+ void setLParenLoc(SourceLocation Loc) { LParenLoc = Loc; }
+ /// \brief Returns the location of '('.
+ SourceLocation getLParenLoc() const { return LParenLoc; }
+
+ /// \brief Return the location of ':'.
+ SourceLocation getColonLoc() const { return ColonLoc; }
+
+ /// \brief Returns condition.
+ Expr *getCondition() const { return cast_or_null<Expr>(Condition); }
+ /// \brief Return directive name modifier associated with the clause.
+ OpenMPDirectiveKind getNameModifier() const { return NameModifier; }
+
+ /// \brief Return the location of directive name modifier.
+ SourceLocation getNameModifierLoc() const { return NameModifierLoc; }
+
+ static bool classof(const OMPClause *T) {
+ return T->getClauseKind() == OMPC_if;
+ }
+
+ child_range children() { return child_range(&Condition, &Condition + 1); }
+};
+
+/// \brief This represents 'final' clause in the '#pragma omp ...' directive.
+///
+/// \code
+/// #pragma omp task final(a > 5)
+/// \endcode
+/// In this example directive '#pragma omp task' has simple 'final'
+/// clause with condition 'a > 5'.
+///
+class OMPFinalClause : public OMPClause {
+ friend class OMPClauseReader;
+ /// \brief Location of '('.
+ SourceLocation LParenLoc;
+ /// \brief Condition of the 'if' clause.
+ Stmt *Condition;
+
+ /// \brief Set condition.
+ ///
+ void setCondition(Expr *Cond) { Condition = Cond; }
+
+public:
+ /// \brief Build 'final' clause with condition \a Cond.
+ ///
+ /// \param StartLoc Starting location of the clause.
+ /// \param LParenLoc Location of '('.
+ /// \param Cond Condition of the clause.
+ /// \param EndLoc Ending location of the clause.
+ ///
+ OMPFinalClause(Expr *Cond, SourceLocation StartLoc, SourceLocation LParenLoc,
+ SourceLocation EndLoc)
+ : OMPClause(OMPC_final, StartLoc, EndLoc), LParenLoc(LParenLoc),
+ Condition(Cond) {}
+
+ /// \brief Build an empty clause.
+ ///
+ OMPFinalClause()
+ : OMPClause(OMPC_final, SourceLocation(), SourceLocation()),
+ LParenLoc(SourceLocation()), Condition(nullptr) {}
+
+ /// \brief Sets the location of '('.
+ void setLParenLoc(SourceLocation Loc) { LParenLoc = Loc; }
+ /// \brief Returns the location of '('.
+ SourceLocation getLParenLoc() const { return LParenLoc; }
+
+ /// \brief Returns condition.
+ Expr *getCondition() const { return cast_or_null<Expr>(Condition); }
+
+ static bool classof(const OMPClause *T) {
+ return T->getClauseKind() == OMPC_final;
+ }
+
+ child_range children() { return child_range(&Condition, &Condition + 1); }
+};
+
+/// \brief This represents 'num_threads' clause in the '#pragma omp ...'
+/// directive.
+///
+/// \code
+/// #pragma omp parallel num_threads(6)
+/// \endcode
+/// In this example directive '#pragma omp parallel' has simple 'num_threads'
+/// clause with number of threads '6'.
+///
+class OMPNumThreadsClause : public OMPClause {
+ friend class OMPClauseReader;
+ /// \brief Location of '('.
+ SourceLocation LParenLoc;
+ /// \brief Condition of the 'num_threads' clause.
+ Stmt *NumThreads;
+
+ /// \brief Set condition.
+ ///
+ void setNumThreads(Expr *NThreads) { NumThreads = NThreads; }
+
+public:
+ /// \brief Build 'num_threads' clause with condition \a NumThreads.
+ ///
+ /// \param NumThreads Number of threads for the construct.
+ /// \param StartLoc Starting location of the clause.
+ /// \param LParenLoc Location of '('.
+ /// \param EndLoc Ending location of the clause.
+ ///
+ OMPNumThreadsClause(Expr *NumThreads, SourceLocation StartLoc,
+ SourceLocation LParenLoc, SourceLocation EndLoc)
+ : OMPClause(OMPC_num_threads, StartLoc, EndLoc), LParenLoc(LParenLoc),
+ NumThreads(NumThreads) {}
+
+ /// \brief Build an empty clause.
+ ///
+ OMPNumThreadsClause()
+ : OMPClause(OMPC_num_threads, SourceLocation(), SourceLocation()),
+ LParenLoc(SourceLocation()), NumThreads(nullptr) {}
+
+ /// \brief Sets the location of '('.
+ void setLParenLoc(SourceLocation Loc) { LParenLoc = Loc; }
+ /// \brief Returns the location of '('.
+ SourceLocation getLParenLoc() const { return LParenLoc; }
+
+ /// \brief Returns number of threads.
+ Expr *getNumThreads() const { return cast_or_null<Expr>(NumThreads); }
+
+ static bool classof(const OMPClause *T) {
+ return T->getClauseKind() == OMPC_num_threads;
+ }
+
+ child_range children() { return child_range(&NumThreads, &NumThreads + 1); }
+};
+
+/// \brief This represents 'safelen' clause in the '#pragma omp ...'
+/// directive.
+///
+/// \code
+/// #pragma omp simd safelen(4)
+/// \endcode
+/// In this example directive '#pragma omp simd' has clause 'safelen'
+/// with single expression '4'.
+/// If the safelen clause is used then no two iterations executed
+/// concurrently with SIMD instructions can have a greater distance
+/// in the logical iteration space than its value. The parameter of
+/// the safelen clause must be a constant positive integer expression.
+///
+class OMPSafelenClause : public OMPClause {
+ friend class OMPClauseReader;
+ /// \brief Location of '('.
+ SourceLocation LParenLoc;
+ /// \brief Safe iteration space distance.
+ Stmt *Safelen;
+
+ /// \brief Set safelen.
+ void setSafelen(Expr *Len) { Safelen = Len; }
+
+public:
+ /// \brief Build 'safelen' clause.
+ ///
+ /// \param Len Expression associated with this clause.
+ /// \param StartLoc Starting location of the clause.
+ /// \param EndLoc Ending location of the clause.
+ ///
+ OMPSafelenClause(Expr *Len, SourceLocation StartLoc, SourceLocation LParenLoc,
+ SourceLocation EndLoc)
+ : OMPClause(OMPC_safelen, StartLoc, EndLoc), LParenLoc(LParenLoc),
+ Safelen(Len) {}
+
+ /// \brief Build an empty clause.
+ ///
+ explicit OMPSafelenClause()
+ : OMPClause(OMPC_safelen, SourceLocation(), SourceLocation()),
+ LParenLoc(SourceLocation()), Safelen(nullptr) {}
+
+ /// \brief Sets the location of '('.
+ void setLParenLoc(SourceLocation Loc) { LParenLoc = Loc; }
+ /// \brief Returns the location of '('.
+ SourceLocation getLParenLoc() const { return LParenLoc; }
+
+ /// \brief Return safe iteration space distance.
+ Expr *getSafelen() const { return cast_or_null<Expr>(Safelen); }
+
+ static bool classof(const OMPClause *T) {
+ return T->getClauseKind() == OMPC_safelen;
+ }
+
+ child_range children() { return child_range(&Safelen, &Safelen + 1); }
+};
+
+/// \brief This represents 'simdlen' clause in the '#pragma omp ...'
+/// directive.
+///
+/// \code
+/// #pragma omp simd simdlen(4)
+/// \endcode
+/// In this example directive '#pragma omp simd' has clause 'simdlen'
+/// with single expression '4'.
+/// If the 'simdlen' clause is used then it specifies the preferred number of
+/// iterations to be executed concurrently. The parameter of the 'simdlen'
+/// clause must be a constant positive integer expression.
+///
+class OMPSimdlenClause : public OMPClause {
+ friend class OMPClauseReader;
+ /// \brief Location of '('.
+ SourceLocation LParenLoc;
+ /// \brief Safe iteration space distance.
+ Stmt *Simdlen;
+
+ /// \brief Set simdlen.
+ void setSimdlen(Expr *Len) { Simdlen = Len; }
+
+public:
+ /// \brief Build 'simdlen' clause.
+ ///
+ /// \param Len Expression associated with this clause.
+ /// \param StartLoc Starting location of the clause.
+ /// \param EndLoc Ending location of the clause.
+ ///
+ OMPSimdlenClause(Expr *Len, SourceLocation StartLoc, SourceLocation LParenLoc,
+ SourceLocation EndLoc)
+ : OMPClause(OMPC_simdlen, StartLoc, EndLoc), LParenLoc(LParenLoc),
+ Simdlen(Len) {}
+
+ /// \brief Build an empty clause.
+ ///
+ explicit OMPSimdlenClause()
+ : OMPClause(OMPC_simdlen, SourceLocation(), SourceLocation()),
+ LParenLoc(SourceLocation()), Simdlen(nullptr) {}
+
+ /// \brief Sets the location of '('.
+ void setLParenLoc(SourceLocation Loc) { LParenLoc = Loc; }
+ /// \brief Returns the location of '('.
+ SourceLocation getLParenLoc() const { return LParenLoc; }
+
+ /// \brief Return safe iteration space distance.
+ Expr *getSimdlen() const { return cast_or_null<Expr>(Simdlen); }
+
+ static bool classof(const OMPClause *T) {
+ return T->getClauseKind() == OMPC_simdlen;
+ }
+
+ child_range children() { return child_range(&Simdlen, &Simdlen + 1); }
+};
+
+/// \brief This represents 'collapse' clause in the '#pragma omp ...'
+/// directive.
+///
+/// \code
+/// #pragma omp simd collapse(3)
+/// \endcode
+/// In this example directive '#pragma omp simd' has clause 'collapse'
+/// with single expression '3'.
+/// The parameter must be a constant positive integer expression, it specifies
+/// the number of nested loops that should be collapsed into a single iteration
+/// space.
+///
+class OMPCollapseClause : public OMPClause {
+ friend class OMPClauseReader;
+ /// \brief Location of '('.
+ SourceLocation LParenLoc;
+ /// \brief Number of for-loops.
+ Stmt *NumForLoops;
+
+ /// \brief Set the number of associated for-loops.
+ void setNumForLoops(Expr *Num) { NumForLoops = Num; }
+
+public:
+ /// \brief Build 'collapse' clause.
+ ///
+ /// \param Num Expression associated with this clause.
+ /// \param StartLoc Starting location of the clause.
+ /// \param LParenLoc Location of '('.
+ /// \param EndLoc Ending location of the clause.
+ ///
+ OMPCollapseClause(Expr *Num, SourceLocation StartLoc,
+ SourceLocation LParenLoc, SourceLocation EndLoc)
+ : OMPClause(OMPC_collapse, StartLoc, EndLoc), LParenLoc(LParenLoc),
+ NumForLoops(Num) {}
+
+ /// \brief Build an empty clause.
+ ///
+ explicit OMPCollapseClause()
+ : OMPClause(OMPC_collapse, SourceLocation(), SourceLocation()),
+ LParenLoc(SourceLocation()), NumForLoops(nullptr) {}
+
+ /// \brief Sets the location of '('.
+ void setLParenLoc(SourceLocation Loc) { LParenLoc = Loc; }
+ /// \brief Returns the location of '('.
+ SourceLocation getLParenLoc() const { return LParenLoc; }
+
+ /// \brief Return the number of associated for-loops.
+ Expr *getNumForLoops() const { return cast_or_null<Expr>(NumForLoops); }
+
+ static bool classof(const OMPClause *T) {
+ return T->getClauseKind() == OMPC_collapse;
+ }
+
+ child_range children() { return child_range(&NumForLoops, &NumForLoops + 1); }
+};
+
+/// \brief This represents 'default' clause in the '#pragma omp ...' directive.
+///
+/// \code
+/// #pragma omp parallel default(shared)
+/// \endcode
+/// In this example directive '#pragma omp parallel' has simple 'default'
+/// clause with kind 'shared'.
+///
+class OMPDefaultClause : public OMPClause {
+ friend class OMPClauseReader;
+ /// \brief Location of '('.
+ SourceLocation LParenLoc;
+ /// \brief A kind of the 'default' clause.
+ OpenMPDefaultClauseKind Kind;
+ /// \brief Start location of the kind in source code.
+ SourceLocation KindKwLoc;
+
+ /// \brief Set kind of the clauses.
+ ///
+ /// \param K Argument of clause.
+ ///
+ void setDefaultKind(OpenMPDefaultClauseKind K) { Kind = K; }
+
+ /// \brief Set argument location.
+ ///
+ /// \param KLoc Argument location.
+ ///
+ void setDefaultKindKwLoc(SourceLocation KLoc) { KindKwLoc = KLoc; }
+
+public:
+ /// \brief Build 'default' clause with argument \a A ('none' or 'shared').
+ ///
+ /// \param A Argument of the clause ('none' or 'shared').
+ /// \param ALoc Starting location of the argument.
+ /// \param StartLoc Starting location of the clause.
+ /// \param LParenLoc Location of '('.
+ /// \param EndLoc Ending location of the clause.
+ ///
+ OMPDefaultClause(OpenMPDefaultClauseKind A, SourceLocation ALoc,
+ SourceLocation StartLoc, SourceLocation LParenLoc,
+ SourceLocation EndLoc)
+ : OMPClause(OMPC_default, StartLoc, EndLoc), LParenLoc(LParenLoc),
+ Kind(A), KindKwLoc(ALoc) {}
+
+ /// \brief Build an empty clause.
+ ///
+ OMPDefaultClause()
+ : OMPClause(OMPC_default, SourceLocation(), SourceLocation()),
+ LParenLoc(SourceLocation()), Kind(OMPC_DEFAULT_unknown),
+ KindKwLoc(SourceLocation()) {}
+
+ /// \brief Sets the location of '('.
+ void setLParenLoc(SourceLocation Loc) { LParenLoc = Loc; }
+ /// \brief Returns the location of '('.
+ SourceLocation getLParenLoc() const { return LParenLoc; }
+
+ /// \brief Returns kind of the clause.
+ OpenMPDefaultClauseKind getDefaultKind() const { return Kind; }
+
+ /// \brief Returns location of clause kind.
+ SourceLocation getDefaultKindKwLoc() const { return KindKwLoc; }
+
+ static bool classof(const OMPClause *T) {
+ return T->getClauseKind() == OMPC_default;
+ }
+
+ child_range children() {
+ return child_range(child_iterator(), child_iterator());
+ }
+};
+
+/// \brief This represents 'proc_bind' clause in the '#pragma omp ...'
+/// directive.
+///
+/// \code
+/// #pragma omp parallel proc_bind(master)
+/// \endcode
+/// In this example directive '#pragma omp parallel' has simple 'proc_bind'
+/// clause with kind 'master'.
+///
+class OMPProcBindClause : public OMPClause {
+ friend class OMPClauseReader;
+ /// \brief Location of '('.
+ SourceLocation LParenLoc;
+ /// \brief A kind of the 'proc_bind' clause.
+ OpenMPProcBindClauseKind Kind;
+ /// \brief Start location of the kind in source code.
+ SourceLocation KindKwLoc;
+
+ /// \brief Set kind of the clause.
+ ///
+ /// \param K Kind of clause.
+ ///
+ void setProcBindKind(OpenMPProcBindClauseKind K) { Kind = K; }
+
+ /// \brief Set clause kind location.
+ ///
+ /// \param KLoc Kind location.
+ ///
+ void setProcBindKindKwLoc(SourceLocation KLoc) { KindKwLoc = KLoc; }
+
+public:
+ /// \brief Build 'proc_bind' clause with argument \a A ('master', 'close' or
+ /// 'spread').
+ ///
+ /// \param A Argument of the clause ('master', 'close' or 'spread').
+ /// \param ALoc Starting location of the argument.
+ /// \param StartLoc Starting location of the clause.
+ /// \param LParenLoc Location of '('.
+ /// \param EndLoc Ending location of the clause.
+ ///
+ OMPProcBindClause(OpenMPProcBindClauseKind A, SourceLocation ALoc,
+ SourceLocation StartLoc, SourceLocation LParenLoc,
+ SourceLocation EndLoc)
+ : OMPClause(OMPC_proc_bind, StartLoc, EndLoc), LParenLoc(LParenLoc),
+ Kind(A), KindKwLoc(ALoc) {}
+
+ /// \brief Build an empty clause.
+ ///
+ OMPProcBindClause()
+ : OMPClause(OMPC_proc_bind, SourceLocation(), SourceLocation()),
+ LParenLoc(SourceLocation()), Kind(OMPC_PROC_BIND_unknown),
+ KindKwLoc(SourceLocation()) {}
+
+ /// \brief Sets the location of '('.
+ void setLParenLoc(SourceLocation Loc) { LParenLoc = Loc; }
+ /// \brief Returns the location of '('.
+ SourceLocation getLParenLoc() const { return LParenLoc; }
+
+ /// \brief Returns kind of the clause.
+ OpenMPProcBindClauseKind getProcBindKind() const { return Kind; }
+
+ /// \brief Returns location of clause kind.
+ SourceLocation getProcBindKindKwLoc() const { return KindKwLoc; }
+
+ static bool classof(const OMPClause *T) {
+ return T->getClauseKind() == OMPC_proc_bind;
+ }
+
+ child_range children() {
+ return child_range(child_iterator(), child_iterator());
+ }
+};
+
+/// \brief This represents 'schedule' clause in the '#pragma omp ...' directive.
+///
+/// \code
+/// #pragma omp for schedule(static, 3)
+/// \endcode
+/// In this example directive '#pragma omp for' has 'schedule' clause with
+/// arguments 'static' and '3'.
+///
+class OMPScheduleClause : public OMPClause {
+ friend class OMPClauseReader;
+ /// \brief Location of '('.
+ SourceLocation LParenLoc;
+ /// \brief A kind of the 'schedule' clause.
+ OpenMPScheduleClauseKind Kind;
+ /// \brief Modifiers for 'schedule' clause.
+ enum {FIRST, SECOND, NUM_MODIFIERS};
+ OpenMPScheduleClauseModifier Modifiers[NUM_MODIFIERS];
+ /// \brief Locations of modifiers.
+ SourceLocation ModifiersLoc[NUM_MODIFIERS];
+ /// \brief Start location of the schedule ind in source code.
+ SourceLocation KindLoc;
+ /// \brief Location of ',' (if any).
+ SourceLocation CommaLoc;
+ /// \brief Chunk size and a reference to pseudo variable for combined
+ /// directives.
+ enum { CHUNK_SIZE, HELPER_CHUNK_SIZE, NUM_EXPRS };
+ Stmt *ChunkSizes[NUM_EXPRS];
+
+ /// \brief Set schedule kind.
+ ///
+ /// \param K Schedule kind.
+ ///
+ void setScheduleKind(OpenMPScheduleClauseKind K) { Kind = K; }
+ /// \brief Set the first schedule modifier.
+ ///
+ /// \param M Schedule modifier.
+ ///
+ void setFirstScheduleModifier(OpenMPScheduleClauseModifier M) {
+ Modifiers[FIRST] = M;
+ }
+ /// \brief Set the second schedule modifier.
+ ///
+ /// \param M Schedule modifier.
+ ///
+ void setSecondScheduleModifier(OpenMPScheduleClauseModifier M) {
+ Modifiers[SECOND] = M;
+ }
+ /// \brief Set location of the first schedule modifier.
+ ///
+ void setFirstScheduleModifierLoc(SourceLocation Loc) {
+ ModifiersLoc[FIRST] = Loc;
+ }
+ /// \brief Set location of the second schedule modifier.
+ ///
+ void setSecondScheduleModifierLoc(SourceLocation Loc) {
+ ModifiersLoc[SECOND] = Loc;
+ }
+ /// \brief Set schedule modifier location.
+ ///
+ /// \param M Schedule modifier location.
+ ///
+ void setScheduleModifer(OpenMPScheduleClauseModifier M) {
+ if (Modifiers[FIRST] == OMPC_SCHEDULE_MODIFIER_unknown)
+ Modifiers[FIRST] = M;
+ else {
+ assert(Modifiers[SECOND] == OMPC_SCHEDULE_MODIFIER_unknown);
+ Modifiers[SECOND] = M;
+ }
+ }
+ /// \brief Sets the location of '('.
+ ///
+ /// \param Loc Location of '('.
+ ///
+ void setLParenLoc(SourceLocation Loc) { LParenLoc = Loc; }
+ /// \brief Set schedule kind start location.
+ ///
+ /// \param KLoc Schedule kind location.
+ ///
+ void setScheduleKindLoc(SourceLocation KLoc) { KindLoc = KLoc; }
+ /// \brief Set location of ','.
+ ///
+ /// \param Loc Location of ','.
+ ///
+ void setCommaLoc(SourceLocation Loc) { CommaLoc = Loc; }
+ /// \brief Set chunk size.
+ ///
+ /// \param E Chunk size.
+ ///
+ void setChunkSize(Expr *E) { ChunkSizes[CHUNK_SIZE] = E; }
+ /// \brief Set helper chunk size.
+ ///
+ /// \param E Helper chunk size.
+ ///
+ void setHelperChunkSize(Expr *E) { ChunkSizes[HELPER_CHUNK_SIZE] = E; }
+
+public:
+ /// \brief Build 'schedule' clause with schedule kind \a Kind and chunk size
+ /// expression \a ChunkSize.
+ ///
+ /// \param StartLoc Starting location of the clause.
+ /// \param LParenLoc Location of '('.
+ /// \param KLoc Starting location of the argument.
+ /// \param CommaLoc Location of ','.
+ /// \param EndLoc Ending location of the clause.
+ /// \param Kind Schedule kind.
+ /// \param ChunkSize Chunk size.
+ /// \param HelperChunkSize Helper chunk size for combined directives.
+ /// \param M1 The first modifier applied to 'schedule' clause.
+ /// \param M1Loc Location of the first modifier
+ /// \param M2 The second modifier applied to 'schedule' clause.
+ /// \param M2Loc Location of the second modifier
+ ///
+ OMPScheduleClause(SourceLocation StartLoc, SourceLocation LParenLoc,
+ SourceLocation KLoc, SourceLocation CommaLoc,
+ SourceLocation EndLoc, OpenMPScheduleClauseKind Kind,
+ Expr *ChunkSize, Expr *HelperChunkSize,
+ OpenMPScheduleClauseModifier M1, SourceLocation M1Loc,
+ OpenMPScheduleClauseModifier M2, SourceLocation M2Loc)
+ : OMPClause(OMPC_schedule, StartLoc, EndLoc), LParenLoc(LParenLoc),
+ Kind(Kind), KindLoc(KLoc), CommaLoc(CommaLoc) {
+ ChunkSizes[CHUNK_SIZE] = ChunkSize;
+ ChunkSizes[HELPER_CHUNK_SIZE] = HelperChunkSize;
+ Modifiers[FIRST] = M1;
+ Modifiers[SECOND] = M2;
+ ModifiersLoc[FIRST] = M1Loc;
+ ModifiersLoc[SECOND] = M2Loc;
+ }
+
+ /// \brief Build an empty clause.
+ ///
+ explicit OMPScheduleClause()
+ : OMPClause(OMPC_schedule, SourceLocation(), SourceLocation()),
+ Kind(OMPC_SCHEDULE_unknown) {
+ ChunkSizes[CHUNK_SIZE] = nullptr;
+ ChunkSizes[HELPER_CHUNK_SIZE] = nullptr;
+ Modifiers[FIRST] = OMPC_SCHEDULE_MODIFIER_unknown;
+ Modifiers[SECOND] = OMPC_SCHEDULE_MODIFIER_unknown;
+ }
+
+ /// \brief Get kind of the clause.
+ ///
+ OpenMPScheduleClauseKind getScheduleKind() const { return Kind; }
+ /// \brief Get the first modifier of the clause.
+ ///
+ OpenMPScheduleClauseModifier getFirstScheduleModifier() const {
+ return Modifiers[FIRST];
+ }
+ /// \brief Get the second modifier of the clause.
+ ///
+ OpenMPScheduleClauseModifier getSecondScheduleModifier() const {
+ return Modifiers[SECOND];
+ }
+ /// \brief Get location of '('.
+ ///
+ SourceLocation getLParenLoc() { return LParenLoc; }
+ /// \brief Get kind location.
+ ///
+ SourceLocation getScheduleKindLoc() { return KindLoc; }
+ /// \brief Get the first modifier location.
+ ///
+ SourceLocation getFirstScheduleModifierLoc() const {
+ return ModifiersLoc[FIRST];
+ }
+ /// \brief Get the second modifier location.
+ ///
+ SourceLocation getSecondScheduleModifierLoc() const {
+ return ModifiersLoc[SECOND];
+ }
+ /// \brief Get location of ','.
+ ///
+ SourceLocation getCommaLoc() { return CommaLoc; }
+ /// \brief Get chunk size.
+ ///
+ Expr *getChunkSize() { return dyn_cast_or_null<Expr>(ChunkSizes[CHUNK_SIZE]); }
+ /// \brief Get chunk size.
+ ///
+ Expr *getChunkSize() const {
+ return dyn_cast_or_null<Expr>(ChunkSizes[CHUNK_SIZE]);
+ }
+ /// \brief Get helper chunk size.
+ ///
+ Expr *getHelperChunkSize() {
+ return dyn_cast_or_null<Expr>(ChunkSizes[HELPER_CHUNK_SIZE]);
+ }
+ /// \brief Get helper chunk size.
+ ///
+ Expr *getHelperChunkSize() const {
+ return dyn_cast_or_null<Expr>(ChunkSizes[HELPER_CHUNK_SIZE]);
+ }
+
+ static bool classof(const OMPClause *T) {
+ return T->getClauseKind() == OMPC_schedule;
+ }
+
+ child_range children() {
+ return child_range(&ChunkSizes[CHUNK_SIZE], &ChunkSizes[CHUNK_SIZE] + 1);
+ }
+};
+
+/// \brief This represents 'ordered' clause in the '#pragma omp ...' directive.
+///
+/// \code
+/// #pragma omp for ordered (2)
+/// \endcode
+/// In this example directive '#pragma omp for' has 'ordered' clause with
+/// parameter 2.
+///
+class OMPOrderedClause : public OMPClause {
+ friend class OMPClauseReader;
+ /// \brief Location of '('.
+ SourceLocation LParenLoc;
+ /// \brief Number of for-loops.
+ Stmt *NumForLoops;
+
+ /// \brief Set the number of associated for-loops.
+ void setNumForLoops(Expr *Num) { NumForLoops = Num; }
+
+public:
+ /// \brief Build 'ordered' clause.
+ ///
+ /// \param Num Expression, possibly associated with this clause.
+ /// \param StartLoc Starting location of the clause.
+ /// \param LParenLoc Location of '('.
+ /// \param EndLoc Ending location of the clause.
+ ///
+ OMPOrderedClause(Expr *Num, SourceLocation StartLoc,
+ SourceLocation LParenLoc, SourceLocation EndLoc)
+ : OMPClause(OMPC_ordered, StartLoc, EndLoc), LParenLoc(LParenLoc),
+ NumForLoops(Num) {}
+
+ /// \brief Build an empty clause.
+ ///
+ explicit OMPOrderedClause()
+ : OMPClause(OMPC_ordered, SourceLocation(), SourceLocation()),
+ LParenLoc(SourceLocation()), NumForLoops(nullptr) {}
+
+ /// \brief Sets the location of '('.
+ void setLParenLoc(SourceLocation Loc) { LParenLoc = Loc; }
+ /// \brief Returns the location of '('.
+ SourceLocation getLParenLoc() const { return LParenLoc; }
+
+ /// \brief Return the number of associated for-loops.
+ Expr *getNumForLoops() const { return cast_or_null<Expr>(NumForLoops); }
+
+ static bool classof(const OMPClause *T) {
+ return T->getClauseKind() == OMPC_ordered;
+ }
+
+ child_range children() { return child_range(&NumForLoops, &NumForLoops + 1); }
+};
+
+/// \brief This represents 'nowait' clause in the '#pragma omp ...' directive.
+///
+/// \code
+/// #pragma omp for nowait
+/// \endcode
+/// In this example directive '#pragma omp for' has 'nowait' clause.
+///
+class OMPNowaitClause : public OMPClause {
+public:
+ /// \brief Build 'nowait' clause.
+ ///
+ /// \param StartLoc Starting location of the clause.
+ /// \param EndLoc Ending location of the clause.
+ ///
+ OMPNowaitClause(SourceLocation StartLoc, SourceLocation EndLoc)
+ : OMPClause(OMPC_nowait, StartLoc, EndLoc) {}
+
+ /// \brief Build an empty clause.
+ ///
+ OMPNowaitClause()
+ : OMPClause(OMPC_nowait, SourceLocation(), SourceLocation()) {}
+
+ static bool classof(const OMPClause *T) {
+ return T->getClauseKind() == OMPC_nowait;
+ }
+
+ child_range children() {
+ return child_range(child_iterator(), child_iterator());
+ }
+};
+
+/// \brief This represents 'untied' clause in the '#pragma omp ...' directive.
+///
+/// \code
+/// #pragma omp task untied
+/// \endcode
+/// In this example directive '#pragma omp task' has 'untied' clause.
+///
+class OMPUntiedClause : public OMPClause {
+public:
+ /// \brief Build 'untied' clause.
+ ///
+ /// \param StartLoc Starting location of the clause.
+ /// \param EndLoc Ending location of the clause.
+ ///
+ OMPUntiedClause(SourceLocation StartLoc, SourceLocation EndLoc)
+ : OMPClause(OMPC_untied, StartLoc, EndLoc) {}
+
+ /// \brief Build an empty clause.
+ ///
+ OMPUntiedClause()
+ : OMPClause(OMPC_untied, SourceLocation(), SourceLocation()) {}
+
+ static bool classof(const OMPClause *T) {
+ return T->getClauseKind() == OMPC_untied;
+ }
+
+ child_range children() {
+ return child_range(child_iterator(), child_iterator());
+ }
+};
+
+/// \brief This represents 'mergeable' clause in the '#pragma omp ...'
+/// directive.
+///
+/// \code
+/// #pragma omp task mergeable
+/// \endcode
+/// In this example directive '#pragma omp task' has 'mergeable' clause.
+///
+class OMPMergeableClause : public OMPClause {
+public:
+ /// \brief Build 'mergeable' clause.
+ ///
+ /// \param StartLoc Starting location of the clause.
+ /// \param EndLoc Ending location of the clause.
+ ///
+ OMPMergeableClause(SourceLocation StartLoc, SourceLocation EndLoc)
+ : OMPClause(OMPC_mergeable, StartLoc, EndLoc) {}
+
+ /// \brief Build an empty clause.
+ ///
+ OMPMergeableClause()
+ : OMPClause(OMPC_mergeable, SourceLocation(), SourceLocation()) {}
+
+ static bool classof(const OMPClause *T) {
+ return T->getClauseKind() == OMPC_mergeable;
+ }
+
+ child_range children() {
+ return child_range(child_iterator(), child_iterator());
+ }
+};
+
+/// \brief This represents 'read' clause in the '#pragma omp atomic' directive.
+///
+/// \code
+/// #pragma omp atomic read
+/// \endcode
+/// In this example directive '#pragma omp atomic' has 'read' clause.
+///
+class OMPReadClause : public OMPClause {
+public:
+ /// \brief Build 'read' clause.
+ ///
+ /// \param StartLoc Starting location of the clause.
+ /// \param EndLoc Ending location of the clause.
+ ///
+ OMPReadClause(SourceLocation StartLoc, SourceLocation EndLoc)
+ : OMPClause(OMPC_read, StartLoc, EndLoc) {}
+
+ /// \brief Build an empty clause.
+ ///
+ OMPReadClause() : OMPClause(OMPC_read, SourceLocation(), SourceLocation()) {}
+
+ static bool classof(const OMPClause *T) {
+ return T->getClauseKind() == OMPC_read;
+ }
+
+ child_range children() {
+ return child_range(child_iterator(), child_iterator());
+ }
+};
+
+/// \brief This represents 'write' clause in the '#pragma omp atomic' directive.
+///
+/// \code
+/// #pragma omp atomic write
+/// \endcode
+/// In this example directive '#pragma omp atomic' has 'write' clause.
+///
+class OMPWriteClause : public OMPClause {
+public:
+ /// \brief Build 'write' clause.
+ ///
+ /// \param StartLoc Starting location of the clause.
+ /// \param EndLoc Ending location of the clause.
+ ///
+ OMPWriteClause(SourceLocation StartLoc, SourceLocation EndLoc)
+ : OMPClause(OMPC_write, StartLoc, EndLoc) {}
+
+ /// \brief Build an empty clause.
+ ///
+ OMPWriteClause()
+ : OMPClause(OMPC_write, SourceLocation(), SourceLocation()) {}
+
+ static bool classof(const OMPClause *T) {
+ return T->getClauseKind() == OMPC_write;
+ }
+
+ child_range children() {
+ return child_range(child_iterator(), child_iterator());
+ }
+};
+
+/// \brief This represents 'update' clause in the '#pragma omp atomic'
+/// directive.
+///
+/// \code
+/// #pragma omp atomic update
+/// \endcode
+/// In this example directive '#pragma omp atomic' has 'update' clause.
+///
+class OMPUpdateClause : public OMPClause {
+public:
+ /// \brief Build 'update' clause.
+ ///
+ /// \param StartLoc Starting location of the clause.
+ /// \param EndLoc Ending location of the clause.
+ ///
+ OMPUpdateClause(SourceLocation StartLoc, SourceLocation EndLoc)
+ : OMPClause(OMPC_update, StartLoc, EndLoc) {}
+
+ /// \brief Build an empty clause.
+ ///
+ OMPUpdateClause()
+ : OMPClause(OMPC_update, SourceLocation(), SourceLocation()) {}
+
+ static bool classof(const OMPClause *T) {
+ return T->getClauseKind() == OMPC_update;
+ }
+
+ child_range children() {
+ return child_range(child_iterator(), child_iterator());
+ }
+};
+
+/// \brief This represents 'capture' clause in the '#pragma omp atomic'
+/// directive.
+///
+/// \code
+/// #pragma omp atomic capture
+/// \endcode
+/// In this example directive '#pragma omp atomic' has 'capture' clause.
+///
+class OMPCaptureClause : public OMPClause {
+public:
+ /// \brief Build 'capture' clause.
+ ///
+ /// \param StartLoc Starting location of the clause.
+ /// \param EndLoc Ending location of the clause.
+ ///
+ OMPCaptureClause(SourceLocation StartLoc, SourceLocation EndLoc)
+ : OMPClause(OMPC_capture, StartLoc, EndLoc) {}
+
+ /// \brief Build an empty clause.
+ ///
+ OMPCaptureClause()
+ : OMPClause(OMPC_capture, SourceLocation(), SourceLocation()) {}
+
+ static bool classof(const OMPClause *T) {
+ return T->getClauseKind() == OMPC_capture;
+ }
+
+ child_range children() {
+ return child_range(child_iterator(), child_iterator());
+ }
+};
+
+/// \brief This represents 'seq_cst' clause in the '#pragma omp atomic'
+/// directive.
+///
+/// \code
+/// #pragma omp atomic seq_cst
+/// \endcode
+/// In this example directive '#pragma omp atomic' has 'seq_cst' clause.
+///
+class OMPSeqCstClause : public OMPClause {
+public:
+ /// \brief Build 'seq_cst' clause.
+ ///
+ /// \param StartLoc Starting location of the clause.
+ /// \param EndLoc Ending location of the clause.
+ ///
+ OMPSeqCstClause(SourceLocation StartLoc, SourceLocation EndLoc)
+ : OMPClause(OMPC_seq_cst, StartLoc, EndLoc) {}
+
+ /// \brief Build an empty clause.
+ ///
+ OMPSeqCstClause()
+ : OMPClause(OMPC_seq_cst, SourceLocation(), SourceLocation()) {}
+
+ static bool classof(const OMPClause *T) {
+ return T->getClauseKind() == OMPC_seq_cst;
+ }
+
+ child_range children() {
+ return child_range(child_iterator(), child_iterator());
+ }
+};
+
+/// \brief This represents clause 'private' in the '#pragma omp ...' directives.
+///
+/// \code
+/// #pragma omp parallel private(a,b)
+/// \endcode
+/// In this example directive '#pragma omp parallel' has clause 'private'
+/// with the variables 'a' and 'b'.
+///
+class OMPPrivateClause final
+ : public OMPVarListClause<OMPPrivateClause>,
+ private llvm::TrailingObjects<OMPPrivateClause, Expr *> {
+ friend TrailingObjects;
+ friend OMPVarListClause;
+ friend class OMPClauseReader;
+ /// \brief Build clause with number of variables \a N.
+ ///
+ /// \param StartLoc Starting location of the clause.
+ /// \param LParenLoc Location of '('.
+ /// \param EndLoc Ending location of the clause.
+ /// \param N Number of the variables in the clause.
+ ///
+ OMPPrivateClause(SourceLocation StartLoc, SourceLocation LParenLoc,
+ SourceLocation EndLoc, unsigned N)
+ : OMPVarListClause<OMPPrivateClause>(OMPC_private, StartLoc, LParenLoc,
+ EndLoc, N) {}
+
+ /// \brief Build an empty clause.
+ ///
+ /// \param N Number of variables.
+ ///
+ explicit OMPPrivateClause(unsigned N)
+ : OMPVarListClause<OMPPrivateClause>(OMPC_private, SourceLocation(),
+ SourceLocation(), SourceLocation(),
+ N) {}
+
+ /// \brief Sets the list of references to private copies with initializers for
+ /// new private variables.
+ /// \param VL List of references.
+ void setPrivateCopies(ArrayRef<Expr *> VL);
+
+ /// \brief Gets the list of references to private copies with initializers for
+ /// new private variables.
+ MutableArrayRef<Expr *> getPrivateCopies() {
+ return MutableArrayRef<Expr *>(varlist_end(), varlist_size());
+ }
+ ArrayRef<const Expr *> getPrivateCopies() const {
+ return llvm::makeArrayRef(varlist_end(), varlist_size());
+ }
+
+public:
+ /// \brief Creates clause with a list of variables \a VL.
+ ///
+ /// \param C AST context.
+ /// \param StartLoc Starting location of the clause.
+ /// \param LParenLoc Location of '('.
+ /// \param EndLoc Ending location of the clause.
+ /// \param VL List of references to the variables.
+ /// \param PrivateVL List of references to private copies with initializers.
+ ///
+ static OMPPrivateClause *Create(const ASTContext &C, SourceLocation StartLoc,
+ SourceLocation LParenLoc,
+ SourceLocation EndLoc, ArrayRef<Expr *> VL,
+ ArrayRef<Expr *> PrivateVL);
+ /// \brief Creates an empty clause with the place for \a N variables.
+ ///
+ /// \param C AST context.
+ /// \param N The number of variables.
+ ///
+ static OMPPrivateClause *CreateEmpty(const ASTContext &C, unsigned N);
+
+ typedef MutableArrayRef<Expr *>::iterator private_copies_iterator;
+ typedef ArrayRef<const Expr *>::iterator private_copies_const_iterator;
+ typedef llvm::iterator_range<private_copies_iterator> private_copies_range;
+ typedef llvm::iterator_range<private_copies_const_iterator>
+ private_copies_const_range;
+
+ private_copies_range private_copies() {
+ return private_copies_range(getPrivateCopies().begin(),
+ getPrivateCopies().end());
+ }
+ private_copies_const_range private_copies() const {
+ return private_copies_const_range(getPrivateCopies().begin(),
+ getPrivateCopies().end());
+ }
+
+ child_range children() {
+ return child_range(reinterpret_cast<Stmt **>(varlist_begin()),
+ reinterpret_cast<Stmt **>(varlist_end()));
+ }
+
+ static bool classof(const OMPClause *T) {
+ return T->getClauseKind() == OMPC_private;
+ }
+};
+
+/// \brief This represents clause 'firstprivate' in the '#pragma omp ...'
+/// directives.
+///
+/// \code
+/// #pragma omp parallel firstprivate(a,b)
+/// \endcode
+/// In this example directive '#pragma omp parallel' has clause 'firstprivate'
+/// with the variables 'a' and 'b'.
+///
+class OMPFirstprivateClause final
+ : public OMPVarListClause<OMPFirstprivateClause>,
+ private llvm::TrailingObjects<OMPFirstprivateClause, Expr *> {
+ friend TrailingObjects;
+ friend OMPVarListClause;
+ friend class OMPClauseReader;
+
+ /// \brief Build clause with number of variables \a N.
+ ///
+ /// \param StartLoc Starting location of the clause.
+ /// \param LParenLoc Location of '('.
+ /// \param EndLoc Ending location of the clause.
+ /// \param N Number of the variables in the clause.
+ ///
+ OMPFirstprivateClause(SourceLocation StartLoc, SourceLocation LParenLoc,
+ SourceLocation EndLoc, unsigned N)
+ : OMPVarListClause<OMPFirstprivateClause>(OMPC_firstprivate, StartLoc,
+ LParenLoc, EndLoc, N) {}
+
+ /// \brief Build an empty clause.
+ ///
+ /// \param N Number of variables.
+ ///
+ explicit OMPFirstprivateClause(unsigned N)
+ : OMPVarListClause<OMPFirstprivateClause>(
+ OMPC_firstprivate, SourceLocation(), SourceLocation(),
+ SourceLocation(), N) {}
+ /// \brief Sets the list of references to private copies with initializers for
+ /// new private variables.
+ /// \param VL List of references.
+ void setPrivateCopies(ArrayRef<Expr *> VL);
+
+ /// \brief Gets the list of references to private copies with initializers for
+ /// new private variables.
+ MutableArrayRef<Expr *> getPrivateCopies() {
+ return MutableArrayRef<Expr *>(varlist_end(), varlist_size());
+ }
+ ArrayRef<const Expr *> getPrivateCopies() const {
+ return llvm::makeArrayRef(varlist_end(), varlist_size());
+ }
+
+ /// \brief Sets the list of references to initializer variables for new
+ /// private variables.
+ /// \param VL List of references.
+ void setInits(ArrayRef<Expr *> VL);
+
+ /// \brief Gets the list of references to initializer variables for new
+ /// private variables.
+ MutableArrayRef<Expr *> getInits() {
+ return MutableArrayRef<Expr *>(getPrivateCopies().end(), varlist_size());
+ }
+ ArrayRef<const Expr *> getInits() const {
+ return llvm::makeArrayRef(getPrivateCopies().end(), varlist_size());
+ }
+
+public:
+ /// \brief Creates clause with a list of variables \a VL.
+ ///
+ /// \param C AST context.
+ /// \param StartLoc Starting location of the clause.
+ /// \param LParenLoc Location of '('.
+ /// \param EndLoc Ending location of the clause.
+ /// \param VL List of references to the original variables.
+ /// \param PrivateVL List of references to private copies with initializers.
+ /// \param InitVL List of references to auto generated variables used for
+ /// initialization of a single array element. Used if firstprivate variable is
+ /// of array type.
+ ///
+ static OMPFirstprivateClause *
+ Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc,
+ SourceLocation EndLoc, ArrayRef<Expr *> VL, ArrayRef<Expr *> PrivateVL,
+ ArrayRef<Expr *> InitVL);
+ /// \brief Creates an empty clause with the place for \a N variables.
+ ///
+ /// \param C AST context.
+ /// \param N The number of variables.
+ ///
+ static OMPFirstprivateClause *CreateEmpty(const ASTContext &C, unsigned N);
+
+ typedef MutableArrayRef<Expr *>::iterator private_copies_iterator;
+ typedef ArrayRef<const Expr *>::iterator private_copies_const_iterator;
+ typedef llvm::iterator_range<private_copies_iterator> private_copies_range;
+ typedef llvm::iterator_range<private_copies_const_iterator>
+ private_copies_const_range;
+
+ private_copies_range private_copies() {
+ return private_copies_range(getPrivateCopies().begin(),
+ getPrivateCopies().end());
+ }
+ private_copies_const_range private_copies() const {
+ return private_copies_const_range(getPrivateCopies().begin(),
+ getPrivateCopies().end());
+ }
+
+ typedef MutableArrayRef<Expr *>::iterator inits_iterator;
+ typedef ArrayRef<const Expr *>::iterator inits_const_iterator;
+ typedef llvm::iterator_range<inits_iterator> inits_range;
+ typedef llvm::iterator_range<inits_const_iterator> inits_const_range;
+
+ inits_range inits() {
+ return inits_range(getInits().begin(), getInits().end());
+ }
+ inits_const_range inits() const {
+ return inits_const_range(getInits().begin(), getInits().end());
+ }
+
+ child_range children() {
+ return child_range(reinterpret_cast<Stmt **>(varlist_begin()),
+ reinterpret_cast<Stmt **>(varlist_end()));
+ }
+
+ static bool classof(const OMPClause *T) {
+ return T->getClauseKind() == OMPC_firstprivate;
+ }
+};
+
+/// \brief This represents clause 'lastprivate' in the '#pragma omp ...'
+/// directives.
+///
+/// \code
+/// #pragma omp simd lastprivate(a,b)
+/// \endcode
+/// In this example directive '#pragma omp simd' has clause 'lastprivate'
+/// with the variables 'a' and 'b'.
+class OMPLastprivateClause final
+ : public OMPVarListClause<OMPLastprivateClause>,
+ private llvm::TrailingObjects<OMPLastprivateClause, Expr *> {
+ // There are 4 additional tail-allocated arrays at the end of the class:
+ // 1. Contains list of pseudo variables with the default initialization for
+ // each non-firstprivate variables. Used in codegen for initialization of
+ // lastprivate copies.
+ // 2. List of helper expressions for proper generation of assignment operation
+ // required for lastprivate clause. This list represents private variables
+ // (for arrays, single array element).
+ // 3. List of helper expressions for proper generation of assignment operation
+ // required for lastprivate clause. This list represents original variables
+ // (for arrays, single array element).
+ // 4. List of helper expressions that represents assignment operation:
+ // \code
+ // DstExprs = SrcExprs;
+ // \endcode
+ // Required for proper codegen of final assignment performed by the
+ // lastprivate clause.
+ //
+ friend TrailingObjects;
+ friend OMPVarListClause;
+ friend class OMPClauseReader;
+
+ /// \brief Build clause with number of variables \a N.
+ ///
+ /// \param StartLoc Starting location of the clause.
+ /// \param LParenLoc Location of '('.
+ /// \param EndLoc Ending location of the clause.
+ /// \param N Number of the variables in the clause.
+ ///
+ OMPLastprivateClause(SourceLocation StartLoc, SourceLocation LParenLoc,
+ SourceLocation EndLoc, unsigned N)
+ : OMPVarListClause<OMPLastprivateClause>(OMPC_lastprivate, StartLoc,
+ LParenLoc, EndLoc, N) {}
+
+ /// \brief Build an empty clause.
+ ///
+ /// \param N Number of variables.
+ ///
+ explicit OMPLastprivateClause(unsigned N)
+ : OMPVarListClause<OMPLastprivateClause>(
+ OMPC_lastprivate, SourceLocation(), SourceLocation(),
+ SourceLocation(), N) {}
+
+ /// \brief Get the list of helper expressions for initialization of private
+ /// copies for lastprivate variables.
+ MutableArrayRef<Expr *> getPrivateCopies() {
+ return MutableArrayRef<Expr *>(varlist_end(), varlist_size());
+ }
+ ArrayRef<const Expr *> getPrivateCopies() const {
+ return llvm::makeArrayRef(varlist_end(), varlist_size());
+ }
+
+ /// \brief Set list of helper expressions, required for proper codegen of the
+ /// clause. These expressions represent private variables (for arrays, single
+ /// array element) in the final assignment statement performed by the
+ /// lastprivate clause.
+ void setSourceExprs(ArrayRef<Expr *> SrcExprs);
+
+ /// \brief Get the list of helper source expressions.
+ MutableArrayRef<Expr *> getSourceExprs() {
+ return MutableArrayRef<Expr *>(getPrivateCopies().end(), varlist_size());
+ }
+ ArrayRef<const Expr *> getSourceExprs() const {
+ return llvm::makeArrayRef(getPrivateCopies().end(), varlist_size());
+ }
+
+ /// \brief Set list of helper expressions, required for proper codegen of the
+ /// clause. These expressions represent original variables (for arrays, single
+ /// array element) in the final assignment statement performed by the
+ /// lastprivate clause.
+ void setDestinationExprs(ArrayRef<Expr *> DstExprs);
+
+ /// \brief Get the list of helper destination expressions.
+ MutableArrayRef<Expr *> getDestinationExprs() {
+ return MutableArrayRef<Expr *>(getSourceExprs().end(), varlist_size());
+ }
+ ArrayRef<const Expr *> getDestinationExprs() const {
+ return llvm::makeArrayRef(getSourceExprs().end(), varlist_size());
+ }
+
+ /// \brief Set list of helper assignment expressions, required for proper
+ /// codegen of the clause. These expressions are assignment expressions that
+ /// assign private copy of the variable to original variable.
+ void setAssignmentOps(ArrayRef<Expr *> AssignmentOps);
+
+ /// \brief Get the list of helper assignment expressions.
+ MutableArrayRef<Expr *> getAssignmentOps() {
+ return MutableArrayRef<Expr *>(getDestinationExprs().end(), varlist_size());
+ }
+ ArrayRef<const Expr *> getAssignmentOps() const {
+ return llvm::makeArrayRef(getDestinationExprs().end(), varlist_size());
+ }
+
+public:
+ /// \brief Creates clause with a list of variables \a VL.
+ ///
+ /// \param C AST context.
+ /// \param StartLoc Starting location of the clause.
+ /// \param LParenLoc Location of '('.
+ /// \param EndLoc Ending location of the clause.
+ /// \param VL List of references to the variables.
+ /// \param SrcExprs List of helper expressions for proper generation of
+ /// assignment operation required for lastprivate clause. This list represents
+ /// private variables (for arrays, single array element).
+ /// \param DstExprs List of helper expressions for proper generation of
+ /// assignment operation required for lastprivate clause. This list represents
+ /// original variables (for arrays, single array element).
+ /// \param AssignmentOps List of helper expressions that represents assignment
+ /// operation:
+ /// \code
+ /// DstExprs = SrcExprs;
+ /// \endcode
+ /// Required for proper codegen of final assignment performed by the
+ /// lastprivate clause.
+ ///
+ ///
+ static OMPLastprivateClause *
+ Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc,
+ SourceLocation EndLoc, ArrayRef<Expr *> VL, ArrayRef<Expr *> SrcExprs,
+ ArrayRef<Expr *> DstExprs, ArrayRef<Expr *> AssignmentOps);
+ /// \brief Creates an empty clause with the place for \a N variables.
+ ///
+ /// \param C AST context.
+ /// \param N The number of variables.
+ ///
+ static OMPLastprivateClause *CreateEmpty(const ASTContext &C, unsigned N);
+
+ typedef MutableArrayRef<Expr *>::iterator helper_expr_iterator;
+ typedef ArrayRef<const Expr *>::iterator helper_expr_const_iterator;
+ typedef llvm::iterator_range<helper_expr_iterator> helper_expr_range;
+ typedef llvm::iterator_range<helper_expr_const_iterator>
+ helper_expr_const_range;
+
+ /// \brief Set list of helper expressions, required for generation of private
+ /// copies of original lastprivate variables.
+ void setPrivateCopies(ArrayRef<Expr *> PrivateCopies);
+
+ helper_expr_const_range private_copies() const {
+ return helper_expr_const_range(getPrivateCopies().begin(),
+ getPrivateCopies().end());
+ }
+ helper_expr_range private_copies() {
+ return helper_expr_range(getPrivateCopies().begin(),
+ getPrivateCopies().end());
+ }
+ helper_expr_const_range source_exprs() const {
+ return helper_expr_const_range(getSourceExprs().begin(),
+ getSourceExprs().end());
+ }
+ helper_expr_range source_exprs() {
+ return helper_expr_range(getSourceExprs().begin(), getSourceExprs().end());
+ }
+ helper_expr_const_range destination_exprs() const {
+ return helper_expr_const_range(getDestinationExprs().begin(),
+ getDestinationExprs().end());
+ }
+ helper_expr_range destination_exprs() {
+ return helper_expr_range(getDestinationExprs().begin(),
+ getDestinationExprs().end());
+ }
+ helper_expr_const_range assignment_ops() const {
+ return helper_expr_const_range(getAssignmentOps().begin(),
+ getAssignmentOps().end());
+ }
+ helper_expr_range assignment_ops() {
+ return helper_expr_range(getAssignmentOps().begin(),
+ getAssignmentOps().end());
+ }
+
+ child_range children() {
+ return child_range(reinterpret_cast<Stmt **>(varlist_begin()),
+ reinterpret_cast<Stmt **>(varlist_end()));
+ }
+
+ static bool classof(const OMPClause *T) {
+ return T->getClauseKind() == OMPC_lastprivate;
+ }
+};
+
+/// \brief This represents clause 'shared' in the '#pragma omp ...' directives.
+///
+/// \code
+/// #pragma omp parallel shared(a,b)
+/// \endcode
+/// In this example directive '#pragma omp parallel' has clause 'shared'
+/// with the variables 'a' and 'b'.
+///
+class OMPSharedClause final
+ : public OMPVarListClause<OMPSharedClause>,
+ private llvm::TrailingObjects<OMPSharedClause, Expr *> {
+ friend TrailingObjects;
+ friend OMPVarListClause;
+ /// \brief Build clause with number of variables \a N.
+ ///
+ /// \param StartLoc Starting location of the clause.
+ /// \param LParenLoc Location of '('.
+ /// \param EndLoc Ending location of the clause.
+ /// \param N Number of the variables in the clause.
+ ///
+ OMPSharedClause(SourceLocation StartLoc, SourceLocation LParenLoc,
+ SourceLocation EndLoc, unsigned N)
+ : OMPVarListClause<OMPSharedClause>(OMPC_shared, StartLoc, LParenLoc,
+ EndLoc, N) {}
+
+ /// \brief Build an empty clause.
+ ///
+ /// \param N Number of variables.
+ ///
+ explicit OMPSharedClause(unsigned N)
+ : OMPVarListClause<OMPSharedClause>(OMPC_shared, SourceLocation(),
+ SourceLocation(), SourceLocation(),
+ N) {}
+
+public:
+ /// \brief Creates clause with a list of variables \a VL.
+ ///
+ /// \param C AST context.
+ /// \param StartLoc Starting location of the clause.
+ /// \param LParenLoc Location of '('.
+ /// \param EndLoc Ending location of the clause.
+ /// \param VL List of references to the variables.
+ ///
+ static OMPSharedClause *Create(const ASTContext &C, SourceLocation StartLoc,
+ SourceLocation LParenLoc,
+ SourceLocation EndLoc, ArrayRef<Expr *> VL);
+ /// \brief Creates an empty clause with \a N variables.
+ ///
+ /// \param C AST context.
+ /// \param N The number of variables.
+ ///
+ static OMPSharedClause *CreateEmpty(const ASTContext &C, unsigned N);
+
+ child_range children() {
+ return child_range(reinterpret_cast<Stmt **>(varlist_begin()),
+ reinterpret_cast<Stmt **>(varlist_end()));
+ }
+
+ static bool classof(const OMPClause *T) {
+ return T->getClauseKind() == OMPC_shared;
+ }
+};
+
+/// \brief This represents clause 'reduction' in the '#pragma omp ...'
+/// directives.
+///
+/// \code
+/// #pragma omp parallel reduction(+:a,b)
+/// \endcode
+/// In this example directive '#pragma omp parallel' has clause 'reduction'
+/// with operator '+' and the variables 'a' and 'b'.
+///
+class OMPReductionClause final
+ : public OMPVarListClause<OMPReductionClause>,
+ private llvm::TrailingObjects<OMPReductionClause, Expr *> {
+ friend TrailingObjects;
+ friend OMPVarListClause;
+ friend class OMPClauseReader;
+ /// \brief Location of ':'.
+ SourceLocation ColonLoc;
+ /// \brief Nested name specifier for C++.
+ NestedNameSpecifierLoc QualifierLoc;
+ /// \brief Name of custom operator.
+ DeclarationNameInfo NameInfo;
+
+ /// \brief Build clause with number of variables \a N.
+ ///
+ /// \param StartLoc Starting location of the clause.
+ /// \param LParenLoc Location of '('.
+ /// \param EndLoc Ending location of the clause.
+ /// \param ColonLoc Location of ':'.
+ /// \param N Number of the variables in the clause.
+ /// \param QualifierLoc The nested-name qualifier with location information
+ /// \param NameInfo The full name info for reduction identifier.
+ ///
+ OMPReductionClause(SourceLocation StartLoc, SourceLocation LParenLoc,
+ SourceLocation ColonLoc, SourceLocation EndLoc, unsigned N,
+ NestedNameSpecifierLoc QualifierLoc,
+ const DeclarationNameInfo &NameInfo)
+ : OMPVarListClause<OMPReductionClause>(OMPC_reduction, StartLoc,
+ LParenLoc, EndLoc, N),
+ ColonLoc(ColonLoc), QualifierLoc(QualifierLoc), NameInfo(NameInfo) {}
+
+ /// \brief Build an empty clause.
+ ///
+ /// \param N Number of variables.
+ ///
+ explicit OMPReductionClause(unsigned N)
+ : OMPVarListClause<OMPReductionClause>(OMPC_reduction, SourceLocation(),
+ SourceLocation(), SourceLocation(),
+ N),
+ ColonLoc(), QualifierLoc(), NameInfo() {}
+
+ /// \brief Sets location of ':' symbol in clause.
+ void setColonLoc(SourceLocation CL) { ColonLoc = CL; }
+ /// \brief Sets the name info for specified reduction identifier.
+ void setNameInfo(DeclarationNameInfo DNI) { NameInfo = DNI; }
+ /// \brief Sets the nested name specifier.
+ void setQualifierLoc(NestedNameSpecifierLoc NSL) { QualifierLoc = NSL; }
+
+ /// \brief Set list of helper expressions, required for proper codegen of the
+ /// clause. These expressions represent private copy of the reduction
+ /// variable.
+ void setPrivates(ArrayRef<Expr *> Privates);
+
+ /// \brief Get the list of helper privates.
+ MutableArrayRef<Expr *> getPrivates() {
+ return MutableArrayRef<Expr *>(varlist_end(), varlist_size());
+ }
+ ArrayRef<const Expr *> getPrivates() const {
+ return llvm::makeArrayRef(varlist_end(), varlist_size());
+ }
+
+ /// \brief Set list of helper expressions, required for proper codegen of the
+ /// clause. These expressions represent LHS expression in the final
+ /// reduction expression performed by the reduction clause.
+ void setLHSExprs(ArrayRef<Expr *> LHSExprs);
+
+ /// \brief Get the list of helper LHS expressions.
+ MutableArrayRef<Expr *> getLHSExprs() {
+ return MutableArrayRef<Expr *>(getPrivates().end(), varlist_size());
+ }
+ ArrayRef<const Expr *> getLHSExprs() const {
+ return llvm::makeArrayRef(getPrivates().end(), varlist_size());
+ }
+
+ /// \brief Set list of helper expressions, required for proper codegen of the
+ /// clause. These expressions represent RHS expression in the final
+ /// reduction expression performed by the reduction clause.
+ /// Also, variables in these expressions are used for proper initialization of
+ /// reduction copies.
+ void setRHSExprs(ArrayRef<Expr *> RHSExprs);
+
+ /// \brief Get the list of helper destination expressions.
+ MutableArrayRef<Expr *> getRHSExprs() {
+ return MutableArrayRef<Expr *>(getLHSExprs().end(), varlist_size());
+ }
+ ArrayRef<const Expr *> getRHSExprs() const {
+ return llvm::makeArrayRef(getLHSExprs().end(), varlist_size());
+ }
+
+ /// \brief Set list of helper reduction expressions, required for proper
+ /// codegen of the clause. These expressions are binary expressions or
+ /// operator/custom reduction call that calculates new value from source
+ /// helper expressions to destination helper expressions.
+ void setReductionOps(ArrayRef<Expr *> ReductionOps);
+
+ /// \brief Get the list of helper reduction expressions.
+ MutableArrayRef<Expr *> getReductionOps() {
+ return MutableArrayRef<Expr *>(getRHSExprs().end(), varlist_size());
+ }
+ ArrayRef<const Expr *> getReductionOps() const {
+ return llvm::makeArrayRef(getRHSExprs().end(), varlist_size());
+ }
+
+public:
+ /// \brief Creates clause with a list of variables \a VL.
+ ///
+ /// \param StartLoc Starting location of the clause.
+ /// \param LParenLoc Location of '('.
+ /// \param ColonLoc Location of ':'.
+ /// \param EndLoc Ending location of the clause.
+ /// \param VL The variables in the clause.
+ /// \param QualifierLoc The nested-name qualifier with location information
+ /// \param NameInfo The full name info for reduction identifier.
+ /// \param Privates List of helper expressions for proper generation of
+ /// private copies.
+ /// \param LHSExprs List of helper expressions for proper generation of
+ /// assignment operation required for copyprivate clause. This list represents
+ /// LHSs of the reduction expressions.
+ /// \param RHSExprs List of helper expressions for proper generation of
+ /// assignment operation required for copyprivate clause. This list represents
+ /// RHSs of the reduction expressions.
+ /// Also, variables in these expressions are used for proper initialization of
+ /// reduction copies.
+ /// \param ReductionOps List of helper expressions that represents reduction
+ /// expressions:
+ /// \code
+ /// LHSExprs binop RHSExprs;
+ /// operator binop(LHSExpr, RHSExpr);
+ /// <CutomReduction>(LHSExpr, RHSExpr);
+ /// \endcode
+ /// Required for proper codegen of final reduction operation performed by the
+ /// reduction clause.
+ ///
+ static OMPReductionClause *
+ Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc,
+ SourceLocation ColonLoc, SourceLocation EndLoc, ArrayRef<Expr *> VL,
+ NestedNameSpecifierLoc QualifierLoc,
+ const DeclarationNameInfo &NameInfo, ArrayRef<Expr *> Privates,
+ ArrayRef<Expr *> LHSExprs, ArrayRef<Expr *> RHSExprs,
+ ArrayRef<Expr *> ReductionOps);
+ /// \brief Creates an empty clause with the place for \a N variables.
+ ///
+ /// \param C AST context.
+ /// \param N The number of variables.
+ ///
+ static OMPReductionClause *CreateEmpty(const ASTContext &C, unsigned N);
+
+ /// \brief Gets location of ':' symbol in clause.
+ SourceLocation getColonLoc() const { return ColonLoc; }
+ /// \brief Gets the name info for specified reduction identifier.
+ const DeclarationNameInfo &getNameInfo() const { return NameInfo; }
+ /// \brief Gets the nested name specifier.
+ NestedNameSpecifierLoc getQualifierLoc() const { return QualifierLoc; }
+
+ typedef MutableArrayRef<Expr *>::iterator helper_expr_iterator;
+ typedef ArrayRef<const Expr *>::iterator helper_expr_const_iterator;
+ typedef llvm::iterator_range<helper_expr_iterator> helper_expr_range;
+ typedef llvm::iterator_range<helper_expr_const_iterator>
+ helper_expr_const_range;
+
+ helper_expr_const_range privates() const {
+ return helper_expr_const_range(getPrivates().begin(), getPrivates().end());
+ }
+ helper_expr_range privates() {
+ return helper_expr_range(getPrivates().begin(), getPrivates().end());
+ }
+ helper_expr_const_range lhs_exprs() const {
+ return helper_expr_const_range(getLHSExprs().begin(), getLHSExprs().end());
+ }
+ helper_expr_range lhs_exprs() {
+ return helper_expr_range(getLHSExprs().begin(), getLHSExprs().end());
+ }
+ helper_expr_const_range rhs_exprs() const {
+ return helper_expr_const_range(getRHSExprs().begin(), getRHSExprs().end());
+ }
+ helper_expr_range rhs_exprs() {
+ return helper_expr_range(getRHSExprs().begin(), getRHSExprs().end());
+ }
+ helper_expr_const_range reduction_ops() const {
+ return helper_expr_const_range(getReductionOps().begin(),
+ getReductionOps().end());
+ }
+ helper_expr_range reduction_ops() {
+ return helper_expr_range(getReductionOps().begin(),
+ getReductionOps().end());
+ }
+
+ child_range children() {
+ return child_range(reinterpret_cast<Stmt **>(varlist_begin()),
+ reinterpret_cast<Stmt **>(varlist_end()));
+ }
+
+ static bool classof(const OMPClause *T) {
+ return T->getClauseKind() == OMPC_reduction;
+ }
+};
+
+/// \brief This represents clause 'linear' in the '#pragma omp ...'
+/// directives.
+///
+/// \code
+/// #pragma omp simd linear(a,b : 2)
+/// \endcode
+/// In this example directive '#pragma omp simd' has clause 'linear'
+/// with variables 'a', 'b' and linear step '2'.
+///
+class OMPLinearClause final
+ : public OMPVarListClause<OMPLinearClause>,
+ private llvm::TrailingObjects<OMPLinearClause, Expr *> {
+ friend TrailingObjects;
+ friend OMPVarListClause;
+ friend class OMPClauseReader;
+ /// \brief Modifier of 'linear' clause.
+ OpenMPLinearClauseKind Modifier;
+ /// \brief Location of linear modifier if any.
+ SourceLocation ModifierLoc;
+ /// \brief Location of ':'.
+ SourceLocation ColonLoc;
+
+ /// \brief Sets the linear step for clause.
+ void setStep(Expr *Step) { *(getFinals().end()) = Step; }
+
+ /// \brief Sets the expression to calculate linear step for clause.
+ void setCalcStep(Expr *CalcStep) { *(getFinals().end() + 1) = CalcStep; }
+
+ /// \brief Build 'linear' clause with given number of variables \a NumVars.
+ ///
+ /// \param StartLoc Starting location of the clause.
+ /// \param LParenLoc Location of '('.
+ /// \param ColonLoc Location of ':'.
+ /// \param EndLoc Ending location of the clause.
+ /// \param NumVars Number of variables.
+ ///
+ OMPLinearClause(SourceLocation StartLoc, SourceLocation LParenLoc,
+ OpenMPLinearClauseKind Modifier, SourceLocation ModifierLoc,
+ SourceLocation ColonLoc, SourceLocation EndLoc,
+ unsigned NumVars)
+ : OMPVarListClause<OMPLinearClause>(OMPC_linear, StartLoc, LParenLoc,
+ EndLoc, NumVars),
+ Modifier(Modifier), ModifierLoc(ModifierLoc), ColonLoc(ColonLoc) {}
+
+ /// \brief Build an empty clause.
+ ///
+ /// \param NumVars Number of variables.
+ ///
+ explicit OMPLinearClause(unsigned NumVars)
+ : OMPVarListClause<OMPLinearClause>(OMPC_linear, SourceLocation(),
+ SourceLocation(), SourceLocation(),
+ NumVars),
+ Modifier(OMPC_LINEAR_val), ModifierLoc(), ColonLoc() {}
+
+ /// \brief Gets the list of initial values for linear variables.
+ ///
+ /// There are NumVars expressions with initial values allocated after the
+ /// varlist, they are followed by NumVars update expressions (used to update
+ /// the linear variable's value on current iteration) and they are followed by
+ /// NumVars final expressions (used to calculate the linear variable's
+ /// value after the loop body). After these lists, there are 2 helper
+ /// expressions - linear step and a helper to calculate it before the
+ /// loop body (used when the linear step is not constant):
+ ///
+ /// { Vars[] /* in OMPVarListClause */; Privates[]; Inits[]; Updates[];
+ /// Finals[]; Step; CalcStep; }
+ ///
+ MutableArrayRef<Expr *> getPrivates() {
+ return MutableArrayRef<Expr *>(varlist_end(), varlist_size());
+ }
+ ArrayRef<const Expr *> getPrivates() const {
+ return llvm::makeArrayRef(varlist_end(), varlist_size());
+ }
+
+ MutableArrayRef<Expr *> getInits() {
+ return MutableArrayRef<Expr *>(getPrivates().end(), varlist_size());
+ }
+ ArrayRef<const Expr *> getInits() const {
+ return llvm::makeArrayRef(getPrivates().end(), varlist_size());
+ }
+
+ /// \brief Sets the list of update expressions for linear variables.
+ MutableArrayRef<Expr *> getUpdates() {
+ return MutableArrayRef<Expr *>(getInits().end(), varlist_size());
+ }
+ ArrayRef<const Expr *> getUpdates() const {
+ return llvm::makeArrayRef(getInits().end(), varlist_size());
+ }
+
+ /// \brief Sets the list of final update expressions for linear variables.
+ MutableArrayRef<Expr *> getFinals() {
+ return MutableArrayRef<Expr *>(getUpdates().end(), varlist_size());
+ }
+ ArrayRef<const Expr *> getFinals() const {
+ return llvm::makeArrayRef(getUpdates().end(), varlist_size());
+ }
+
+ /// \brief Sets the list of the copies of original linear variables.
+ /// \param PL List of expressions.
+ void setPrivates(ArrayRef<Expr *> PL);
+
+ /// \brief Sets the list of the initial values for linear variables.
+ /// \param IL List of expressions.
+ void setInits(ArrayRef<Expr *> IL);
+
+public:
+ /// \brief Creates clause with a list of variables \a VL and a linear step
+ /// \a Step.
+ ///
+ /// \param C AST Context.
+ /// \param StartLoc Starting location of the clause.
+ /// \param LParenLoc Location of '('.
+ /// \param Modifier Modifier of 'linear' clause.
+ /// \param ModifierLoc Modifier location.
+ /// \param ColonLoc Location of ':'.
+ /// \param EndLoc Ending location of the clause.
+ /// \param VL List of references to the variables.
+ /// \param PL List of private copies of original variables.
+ /// \param IL List of initial values for the variables.
+ /// \param Step Linear step.
+ /// \param CalcStep Calculation of the linear step.
+ static OMPLinearClause *
+ Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc,
+ OpenMPLinearClauseKind Modifier, SourceLocation ModifierLoc,
+ SourceLocation ColonLoc, SourceLocation EndLoc, ArrayRef<Expr *> VL,
+ ArrayRef<Expr *> PL, ArrayRef<Expr *> IL, Expr *Step, Expr *CalcStep);
+
+ /// \brief Creates an empty clause with the place for \a NumVars variables.
+ ///
+ /// \param C AST context.
+ /// \param NumVars Number of variables.
+ ///
+ static OMPLinearClause *CreateEmpty(const ASTContext &C, unsigned NumVars);
+
+ /// \brief Set modifier.
+ void setModifier(OpenMPLinearClauseKind Kind) { Modifier = Kind; }
+ /// \brief Return modifier.
+ OpenMPLinearClauseKind getModifier() const { return Modifier; }
+
+ /// \brief Set modifier location.
+ void setModifierLoc(SourceLocation Loc) { ModifierLoc = Loc; }
+ /// \brief Return modifier location.
+ SourceLocation getModifierLoc() const { return ModifierLoc; }
+
+ /// \brief Sets the location of ':'.
+ void setColonLoc(SourceLocation Loc) { ColonLoc = Loc; }
+ /// \brief Returns the location of ':'.
+ SourceLocation getColonLoc() const { return ColonLoc; }
+
+ /// \brief Returns linear step.
+ Expr *getStep() { return *(getFinals().end()); }
+ /// \brief Returns linear step.
+ const Expr *getStep() const { return *(getFinals().end()); }
+ /// \brief Returns expression to calculate linear step.
+ Expr *getCalcStep() { return *(getFinals().end() + 1); }
+ /// \brief Returns expression to calculate linear step.
+ const Expr *getCalcStep() const { return *(getFinals().end() + 1); }
+
+ /// \brief Sets the list of update expressions for linear variables.
+ /// \param UL List of expressions.
+ void setUpdates(ArrayRef<Expr *> UL);
+
+ /// \brief Sets the list of final update expressions for linear variables.
+ /// \param FL List of expressions.
+ void setFinals(ArrayRef<Expr *> FL);
+
+ typedef MutableArrayRef<Expr *>::iterator privates_iterator;
+ typedef ArrayRef<const Expr *>::iterator privates_const_iterator;
+ typedef llvm::iterator_range<privates_iterator> privates_range;
+ typedef llvm::iterator_range<privates_const_iterator> privates_const_range;
+
+ privates_range privates() {
+ return privates_range(getPrivates().begin(), getPrivates().end());
+ }
+ privates_const_range privates() const {
+ return privates_const_range(getPrivates().begin(), getPrivates().end());
+ }
+
+ typedef MutableArrayRef<Expr *>::iterator inits_iterator;
+ typedef ArrayRef<const Expr *>::iterator inits_const_iterator;
+ typedef llvm::iterator_range<inits_iterator> inits_range;
+ typedef llvm::iterator_range<inits_const_iterator> inits_const_range;
+
+ inits_range inits() {
+ return inits_range(getInits().begin(), getInits().end());
+ }
+ inits_const_range inits() const {
+ return inits_const_range(getInits().begin(), getInits().end());
+ }
+
+ typedef MutableArrayRef<Expr *>::iterator updates_iterator;
+ typedef ArrayRef<const Expr *>::iterator updates_const_iterator;
+ typedef llvm::iterator_range<updates_iterator> updates_range;
+ typedef llvm::iterator_range<updates_const_iterator> updates_const_range;
+
+ updates_range updates() {
+ return updates_range(getUpdates().begin(), getUpdates().end());
+ }
+ updates_const_range updates() const {
+ return updates_const_range(getUpdates().begin(), getUpdates().end());
+ }
+
+ typedef MutableArrayRef<Expr *>::iterator finals_iterator;
+ typedef ArrayRef<const Expr *>::iterator finals_const_iterator;
+ typedef llvm::iterator_range<finals_iterator> finals_range;
+ typedef llvm::iterator_range<finals_const_iterator> finals_const_range;
+
+ finals_range finals() {
+ return finals_range(getFinals().begin(), getFinals().end());
+ }
+ finals_const_range finals() const {
+ return finals_const_range(getFinals().begin(), getFinals().end());
+ }
+
+ child_range children() {
+ return child_range(reinterpret_cast<Stmt **>(varlist_begin()),
+ reinterpret_cast<Stmt **>(varlist_end()));
+ }
+
+ static bool classof(const OMPClause *T) {
+ return T->getClauseKind() == OMPC_linear;
+ }
+};
+
+/// \brief This represents clause 'aligned' in the '#pragma omp ...'
+/// directives.
+///
+/// \code
+/// #pragma omp simd aligned(a,b : 8)
+/// \endcode
+/// In this example directive '#pragma omp simd' has clause 'aligned'
+/// with variables 'a', 'b' and alignment '8'.
+///
+class OMPAlignedClause final
+ : public OMPVarListClause<OMPAlignedClause>,
+ private llvm::TrailingObjects<OMPAlignedClause, Expr *> {
+ friend TrailingObjects;
+ friend OMPVarListClause;
+ friend class OMPClauseReader;
+ /// \brief Location of ':'.
+ SourceLocation ColonLoc;
+
+ /// \brief Sets the alignment for clause.
+ void setAlignment(Expr *A) { *varlist_end() = A; }
+
+ /// \brief Build 'aligned' clause with given number of variables \a NumVars.
+ ///
+ /// \param StartLoc Starting location of the clause.
+ /// \param LParenLoc Location of '('.
+ /// \param ColonLoc Location of ':'.
+ /// \param EndLoc Ending location of the clause.
+ /// \param NumVars Number of variables.
+ ///
+ OMPAlignedClause(SourceLocation StartLoc, SourceLocation LParenLoc,
+ SourceLocation ColonLoc, SourceLocation EndLoc,
+ unsigned NumVars)
+ : OMPVarListClause<OMPAlignedClause>(OMPC_aligned, StartLoc, LParenLoc,
+ EndLoc, NumVars),
+ ColonLoc(ColonLoc) {}
+
+ /// \brief Build an empty clause.
+ ///
+ /// \param NumVars Number of variables.
+ ///
+ explicit OMPAlignedClause(unsigned NumVars)
+ : OMPVarListClause<OMPAlignedClause>(OMPC_aligned, SourceLocation(),
+ SourceLocation(), SourceLocation(),
+ NumVars),
+ ColonLoc(SourceLocation()) {}
+
+public:
+ /// \brief Creates clause with a list of variables \a VL and alignment \a A.
+ ///
+ /// \param C AST Context.
+ /// \param StartLoc Starting location of the clause.
+ /// \param LParenLoc Location of '('.
+ /// \param ColonLoc Location of ':'.
+ /// \param EndLoc Ending location of the clause.
+ /// \param VL List of references to the variables.
+ /// \param A Alignment.
+ static OMPAlignedClause *Create(const ASTContext &C, SourceLocation StartLoc,
+ SourceLocation LParenLoc,
+ SourceLocation ColonLoc,
+ SourceLocation EndLoc, ArrayRef<Expr *> VL,
+ Expr *A);
+
+ /// \brief Creates an empty clause with the place for \a NumVars variables.
+ ///
+ /// \param C AST context.
+ /// \param NumVars Number of variables.
+ ///
+ static OMPAlignedClause *CreateEmpty(const ASTContext &C, unsigned NumVars);
+
+ /// \brief Sets the location of ':'.
+ void setColonLoc(SourceLocation Loc) { ColonLoc = Loc; }
+ /// \brief Returns the location of ':'.
+ SourceLocation getColonLoc() const { return ColonLoc; }
+
+ /// \brief Returns alignment.
+ Expr *getAlignment() { return *varlist_end(); }
+ /// \brief Returns alignment.
+ const Expr *getAlignment() const { return *varlist_end(); }
+
+ child_range children() {
+ return child_range(reinterpret_cast<Stmt **>(varlist_begin()),
+ reinterpret_cast<Stmt **>(varlist_end()));
+ }
+
+ static bool classof(const OMPClause *T) {
+ return T->getClauseKind() == OMPC_aligned;
+ }
+};
+
+/// \brief This represents clause 'copyin' in the '#pragma omp ...' directives.
+///
+/// \code
+/// #pragma omp parallel copyin(a,b)
+/// \endcode
+/// In this example directive '#pragma omp parallel' has clause 'copyin'
+/// with the variables 'a' and 'b'.
+///
+class OMPCopyinClause final
+ : public OMPVarListClause<OMPCopyinClause>,
+ private llvm::TrailingObjects<OMPCopyinClause, Expr *> {
+ // Class has 3 additional tail allocated arrays:
+ // 1. List of helper expressions for proper generation of assignment operation
+ // required for copyin clause. This list represents sources.
+ // 2. List of helper expressions for proper generation of assignment operation
+ // required for copyin clause. This list represents destinations.
+ // 3. List of helper expressions that represents assignment operation:
+ // \code
+ // DstExprs = SrcExprs;
+ // \endcode
+ // Required for proper codegen of propagation of master's thread values of
+ // threadprivate variables to local instances of that variables in other
+ // implicit threads.
+
+ friend TrailingObjects;
+ friend OMPVarListClause;
+ friend class OMPClauseReader;
+ /// \brief Build clause with number of variables \a N.
+ ///
+ /// \param StartLoc Starting location of the clause.
+ /// \param LParenLoc Location of '('.
+ /// \param EndLoc Ending location of the clause.
+ /// \param N Number of the variables in the clause.
+ ///
+ OMPCopyinClause(SourceLocation StartLoc, SourceLocation LParenLoc,
+ SourceLocation EndLoc, unsigned N)
+ : OMPVarListClause<OMPCopyinClause>(OMPC_copyin, StartLoc, LParenLoc,
+ EndLoc, N) {}
+
+ /// \brief Build an empty clause.
+ ///
+ /// \param N Number of variables.
+ ///
+ explicit OMPCopyinClause(unsigned N)
+ : OMPVarListClause<OMPCopyinClause>(OMPC_copyin, SourceLocation(),
+ SourceLocation(), SourceLocation(),
+ N) {}
+
+ /// \brief Set list of helper expressions, required for proper codegen of the
+ /// clause. These expressions represent source expression in the final
+ /// assignment statement performed by the copyin clause.
+ void setSourceExprs(ArrayRef<Expr *> SrcExprs);
+
+ /// \brief Get the list of helper source expressions.
+ MutableArrayRef<Expr *> getSourceExprs() {
+ return MutableArrayRef<Expr *>(varlist_end(), varlist_size());
+ }
+ ArrayRef<const Expr *> getSourceExprs() const {
+ return llvm::makeArrayRef(varlist_end(), varlist_size());
+ }
+
+ /// \brief Set list of helper expressions, required for proper codegen of the
+ /// clause. These expressions represent destination expression in the final
+ /// assignment statement performed by the copyin clause.
+ void setDestinationExprs(ArrayRef<Expr *> DstExprs);
+
+ /// \brief Get the list of helper destination expressions.
+ MutableArrayRef<Expr *> getDestinationExprs() {
+ return MutableArrayRef<Expr *>(getSourceExprs().end(), varlist_size());
+ }
+ ArrayRef<const Expr *> getDestinationExprs() const {
+ return llvm::makeArrayRef(getSourceExprs().end(), varlist_size());
+ }
+
+ /// \brief Set list of helper assignment expressions, required for proper
+ /// codegen of the clause. These expressions are assignment expressions that
+ /// assign source helper expressions to destination helper expressions
+ /// correspondingly.
+ void setAssignmentOps(ArrayRef<Expr *> AssignmentOps);
+
+ /// \brief Get the list of helper assignment expressions.
+ MutableArrayRef<Expr *> getAssignmentOps() {
+ return MutableArrayRef<Expr *>(getDestinationExprs().end(), varlist_size());
+ }
+ ArrayRef<const Expr *> getAssignmentOps() const {
+ return llvm::makeArrayRef(getDestinationExprs().end(), varlist_size());
+ }
+
+public:
+ /// \brief Creates clause with a list of variables \a VL.
+ ///
+ /// \param C AST context.
+ /// \param StartLoc Starting location of the clause.
+ /// \param LParenLoc Location of '('.
+ /// \param EndLoc Ending location of the clause.
+ /// \param VL List of references to the variables.
+ /// \param SrcExprs List of helper expressions for proper generation of
+ /// assignment operation required for copyin clause. This list represents
+ /// sources.
+ /// \param DstExprs List of helper expressions for proper generation of
+ /// assignment operation required for copyin clause. This list represents
+ /// destinations.
+ /// \param AssignmentOps List of helper expressions that represents assignment
+ /// operation:
+ /// \code
+ /// DstExprs = SrcExprs;
+ /// \endcode
+ /// Required for proper codegen of propagation of master's thread values of
+ /// threadprivate variables to local instances of that variables in other
+ /// implicit threads.
+ ///
+ static OMPCopyinClause *
+ Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc,
+ SourceLocation EndLoc, ArrayRef<Expr *> VL, ArrayRef<Expr *> SrcExprs,
+ ArrayRef<Expr *> DstExprs, ArrayRef<Expr *> AssignmentOps);
+ /// \brief Creates an empty clause with \a N variables.
+ ///
+ /// \param C AST context.
+ /// \param N The number of variables.
+ ///
+ static OMPCopyinClause *CreateEmpty(const ASTContext &C, unsigned N);
+
+ typedef MutableArrayRef<Expr *>::iterator helper_expr_iterator;
+ typedef ArrayRef<const Expr *>::iterator helper_expr_const_iterator;
+ typedef llvm::iterator_range<helper_expr_iterator> helper_expr_range;
+ typedef llvm::iterator_range<helper_expr_const_iterator>
+ helper_expr_const_range;
+
+ helper_expr_const_range source_exprs() const {
+ return helper_expr_const_range(getSourceExprs().begin(),
+ getSourceExprs().end());
+ }
+ helper_expr_range source_exprs() {
+ return helper_expr_range(getSourceExprs().begin(), getSourceExprs().end());
+ }
+ helper_expr_const_range destination_exprs() const {
+ return helper_expr_const_range(getDestinationExprs().begin(),
+ getDestinationExprs().end());
+ }
+ helper_expr_range destination_exprs() {
+ return helper_expr_range(getDestinationExprs().begin(),
+ getDestinationExprs().end());
+ }
+ helper_expr_const_range assignment_ops() const {
+ return helper_expr_const_range(getAssignmentOps().begin(),
+ getAssignmentOps().end());
+ }
+ helper_expr_range assignment_ops() {
+ return helper_expr_range(getAssignmentOps().begin(),
+ getAssignmentOps().end());
+ }
+
+ child_range children() {
+ return child_range(reinterpret_cast<Stmt **>(varlist_begin()),
+ reinterpret_cast<Stmt **>(varlist_end()));
+ }
+
+ static bool classof(const OMPClause *T) {
+ return T->getClauseKind() == OMPC_copyin;
+ }
+};
+
+/// \brief This represents clause 'copyprivate' in the '#pragma omp ...'
+/// directives.
+///
+/// \code
+/// #pragma omp single copyprivate(a,b)
+/// \endcode
+/// In this example directive '#pragma omp single' has clause 'copyprivate'
+/// with the variables 'a' and 'b'.
+///
+class OMPCopyprivateClause final
+ : public OMPVarListClause<OMPCopyprivateClause>,
+ private llvm::TrailingObjects<OMPCopyprivateClause, Expr *> {
+ friend TrailingObjects;
+ friend OMPVarListClause;
+ friend class OMPClauseReader;
+ /// \brief Build clause with number of variables \a N.
+ ///
+ /// \param StartLoc Starting location of the clause.
+ /// \param LParenLoc Location of '('.
+ /// \param EndLoc Ending location of the clause.
+ /// \param N Number of the variables in the clause.
+ ///
+ OMPCopyprivateClause(SourceLocation StartLoc, SourceLocation LParenLoc,
+ SourceLocation EndLoc, unsigned N)
+ : OMPVarListClause<OMPCopyprivateClause>(OMPC_copyprivate, StartLoc,
+ LParenLoc, EndLoc, N) {}
+
+ /// \brief Build an empty clause.
+ ///
+ /// \param N Number of variables.
+ ///
+ explicit OMPCopyprivateClause(unsigned N)
+ : OMPVarListClause<OMPCopyprivateClause>(
+ OMPC_copyprivate, SourceLocation(), SourceLocation(),
+ SourceLocation(), N) {}
+
+ /// \brief Set list of helper expressions, required for proper codegen of the
+ /// clause. These expressions represent source expression in the final
+ /// assignment statement performed by the copyprivate clause.
+ void setSourceExprs(ArrayRef<Expr *> SrcExprs);
+
+ /// \brief Get the list of helper source expressions.
+ MutableArrayRef<Expr *> getSourceExprs() {
+ return MutableArrayRef<Expr *>(varlist_end(), varlist_size());
+ }
+ ArrayRef<const Expr *> getSourceExprs() const {
+ return llvm::makeArrayRef(varlist_end(), varlist_size());
+ }
+
+ /// \brief Set list of helper expressions, required for proper codegen of the
+ /// clause. These expressions represent destination expression in the final
+ /// assignment statement performed by the copyprivate clause.
+ void setDestinationExprs(ArrayRef<Expr *> DstExprs);
+
+ /// \brief Get the list of helper destination expressions.
+ MutableArrayRef<Expr *> getDestinationExprs() {
+ return MutableArrayRef<Expr *>(getSourceExprs().end(), varlist_size());
+ }
+ ArrayRef<const Expr *> getDestinationExprs() const {
+ return llvm::makeArrayRef(getSourceExprs().end(), varlist_size());
+ }
+
+ /// \brief Set list of helper assignment expressions, required for proper
+ /// codegen of the clause. These expressions are assignment expressions that
+ /// assign source helper expressions to destination helper expressions
+ /// correspondingly.
+ void setAssignmentOps(ArrayRef<Expr *> AssignmentOps);
+
+ /// \brief Get the list of helper assignment expressions.
+ MutableArrayRef<Expr *> getAssignmentOps() {
+ return MutableArrayRef<Expr *>(getDestinationExprs().end(), varlist_size());
+ }
+ ArrayRef<const Expr *> getAssignmentOps() const {
+ return llvm::makeArrayRef(getDestinationExprs().end(), varlist_size());
+ }
+
+public:
+ /// \brief Creates clause with a list of variables \a VL.
+ ///
+ /// \param C AST context.
+ /// \param StartLoc Starting location of the clause.
+ /// \param LParenLoc Location of '('.
+ /// \param EndLoc Ending location of the clause.
+ /// \param VL List of references to the variables.
+ /// \param SrcExprs List of helper expressions for proper generation of
+ /// assignment operation required for copyprivate clause. This list represents
+ /// sources.
+ /// \param DstExprs List of helper expressions for proper generation of
+ /// assignment operation required for copyprivate clause. This list represents
+ /// destinations.
+ /// \param AssignmentOps List of helper expressions that represents assignment
+ /// operation:
+ /// \code
+ /// DstExprs = SrcExprs;
+ /// \endcode
+ /// Required for proper codegen of final assignment performed by the
+ /// copyprivate clause.
+ ///
+ static OMPCopyprivateClause *
+ Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc,
+ SourceLocation EndLoc, ArrayRef<Expr *> VL, ArrayRef<Expr *> SrcExprs,
+ ArrayRef<Expr *> DstExprs, ArrayRef<Expr *> AssignmentOps);
+ /// \brief Creates an empty clause with \a N variables.
+ ///
+ /// \param C AST context.
+ /// \param N The number of variables.
+ ///
+ static OMPCopyprivateClause *CreateEmpty(const ASTContext &C, unsigned N);
+
+ typedef MutableArrayRef<Expr *>::iterator helper_expr_iterator;
+ typedef ArrayRef<const Expr *>::iterator helper_expr_const_iterator;
+ typedef llvm::iterator_range<helper_expr_iterator> helper_expr_range;
+ typedef llvm::iterator_range<helper_expr_const_iterator>
+ helper_expr_const_range;
+
+ helper_expr_const_range source_exprs() const {
+ return helper_expr_const_range(getSourceExprs().begin(),
+ getSourceExprs().end());
+ }
+ helper_expr_range source_exprs() {
+ return helper_expr_range(getSourceExprs().begin(), getSourceExprs().end());
+ }
+ helper_expr_const_range destination_exprs() const {
+ return helper_expr_const_range(getDestinationExprs().begin(),
+ getDestinationExprs().end());
+ }
+ helper_expr_range destination_exprs() {
+ return helper_expr_range(getDestinationExprs().begin(),
+ getDestinationExprs().end());
+ }
+ helper_expr_const_range assignment_ops() const {
+ return helper_expr_const_range(getAssignmentOps().begin(),
+ getAssignmentOps().end());
+ }
+ helper_expr_range assignment_ops() {
+ return helper_expr_range(getAssignmentOps().begin(),
+ getAssignmentOps().end());
+ }
+
+ child_range children() {
+ return child_range(reinterpret_cast<Stmt **>(varlist_begin()),
+ reinterpret_cast<Stmt **>(varlist_end()));
+ }
+
+ static bool classof(const OMPClause *T) {
+ return T->getClauseKind() == OMPC_copyprivate;
+ }
+};
+
+/// \brief This represents implicit clause 'flush' for the '#pragma omp flush'
+/// directive.
+/// This clause does not exist by itself, it can be only as a part of 'omp
+/// flush' directive. This clause is introduced to keep the original structure
+/// of \a OMPExecutableDirective class and its derivatives and to use the
+/// existing infrastructure of clauses with the list of variables.
+///
+/// \code
+/// #pragma omp flush(a,b)
+/// \endcode
+/// In this example directive '#pragma omp flush' has implicit clause 'flush'
+/// with the variables 'a' and 'b'.
+///
+class OMPFlushClause final
+ : public OMPVarListClause<OMPFlushClause>,
+ private llvm::TrailingObjects<OMPFlushClause, Expr *> {
+ friend TrailingObjects;
+ friend OMPVarListClause;
+ /// \brief Build clause with number of variables \a N.
+ ///
+ /// \param StartLoc Starting location of the clause.
+ /// \param LParenLoc Location of '('.
+ /// \param EndLoc Ending location of the clause.
+ /// \param N Number of the variables in the clause.
+ ///
+ OMPFlushClause(SourceLocation StartLoc, SourceLocation LParenLoc,
+ SourceLocation EndLoc, unsigned N)
+ : OMPVarListClause<OMPFlushClause>(OMPC_flush, StartLoc, LParenLoc,
+ EndLoc, N) {}
+
+ /// \brief Build an empty clause.
+ ///
+ /// \param N Number of variables.
+ ///
+ explicit OMPFlushClause(unsigned N)
+ : OMPVarListClause<OMPFlushClause>(OMPC_flush, SourceLocation(),
+ SourceLocation(), SourceLocation(),
+ N) {}
+
+public:
+ /// \brief Creates clause with a list of variables \a VL.
+ ///
+ /// \param C AST context.
+ /// \param StartLoc Starting location of the clause.
+ /// \param LParenLoc Location of '('.
+ /// \param EndLoc Ending location of the clause.
+ /// \param VL List of references to the variables.
+ ///
+ static OMPFlushClause *Create(const ASTContext &C, SourceLocation StartLoc,
+ SourceLocation LParenLoc, SourceLocation EndLoc,
+ ArrayRef<Expr *> VL);
+ /// \brief Creates an empty clause with \a N variables.
+ ///
+ /// \param C AST context.
+ /// \param N The number of variables.
+ ///
+ static OMPFlushClause *CreateEmpty(const ASTContext &C, unsigned N);
+
+ child_range children() {
+ return child_range(reinterpret_cast<Stmt **>(varlist_begin()),
+ reinterpret_cast<Stmt **>(varlist_end()));
+ }
+
+ static bool classof(const OMPClause *T) {
+ return T->getClauseKind() == OMPC_flush;
+ }
+};
+
+/// \brief This represents implicit clause 'depend' for the '#pragma omp task'
+/// directive.
+///
+/// \code
+/// #pragma omp task depend(in:a,b)
+/// \endcode
+/// In this example directive '#pragma omp task' with clause 'depend' with the
+/// variables 'a' and 'b' with dependency 'in'.
+///
+class OMPDependClause final
+ : public OMPVarListClause<OMPDependClause>,
+ private llvm::TrailingObjects<OMPDependClause, Expr *> {
+ friend TrailingObjects;
+ friend OMPVarListClause;
+ friend class OMPClauseReader;
+ /// \brief Dependency type (one of in, out, inout).
+ OpenMPDependClauseKind DepKind;
+ /// \brief Dependency type location.
+ SourceLocation DepLoc;
+ /// \brief Colon location.
+ SourceLocation ColonLoc;
+ /// \brief Build clause with number of variables \a N.
+ ///
+ /// \param StartLoc Starting location of the clause.
+ /// \param LParenLoc Location of '('.
+ /// \param EndLoc Ending location of the clause.
+ /// \param N Number of the variables in the clause.
+ ///
+ OMPDependClause(SourceLocation StartLoc, SourceLocation LParenLoc,
+ SourceLocation EndLoc, unsigned N)
+ : OMPVarListClause<OMPDependClause>(OMPC_depend, StartLoc, LParenLoc,
+ EndLoc, N),
+ DepKind(OMPC_DEPEND_unknown) {}
+
+ /// \brief Build an empty clause.
+ ///
+ /// \param N Number of variables.
+ ///
+ explicit OMPDependClause(unsigned N)
+ : OMPVarListClause<OMPDependClause>(OMPC_depend, SourceLocation(),
+ SourceLocation(), SourceLocation(),
+ N),
+ DepKind(OMPC_DEPEND_unknown) {}
+ /// \brief Set dependency kind.
+ void setDependencyKind(OpenMPDependClauseKind K) { DepKind = K; }
+
+ /// \brief Set dependency kind and its location.
+ void setDependencyLoc(SourceLocation Loc) { DepLoc = Loc; }
+
+ /// \brief Set colon location.
+ void setColonLoc(SourceLocation Loc) { ColonLoc = Loc; }
+
+public:
+ /// \brief Creates clause with a list of variables \a VL.
+ ///
+ /// \param C AST context.
+ /// \param StartLoc Starting location of the clause.
+ /// \param LParenLoc Location of '('.
+ /// \param EndLoc Ending location of the clause.
+ /// \param DepKind Dependency type.
+ /// \param DepLoc Location of the dependency type.
+ /// \param ColonLoc Colon location.
+ /// \param VL List of references to the variables.
+ ///
+ static OMPDependClause *
+ Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc,
+ SourceLocation EndLoc, OpenMPDependClauseKind DepKind,
+ SourceLocation DepLoc, SourceLocation ColonLoc, ArrayRef<Expr *> VL);
+ /// \brief Creates an empty clause with \a N variables.
+ ///
+ /// \param C AST context.
+ /// \param N The number of variables.
+ ///
+ static OMPDependClause *CreateEmpty(const ASTContext &C, unsigned N);
+
+ /// \brief Get dependency type.
+ OpenMPDependClauseKind getDependencyKind() const { return DepKind; }
+ /// \brief Get dependency type location.
+ SourceLocation getDependencyLoc() const { return DepLoc; }
+ /// \brief Get colon location.
+ SourceLocation getColonLoc() const { return ColonLoc; }
+
+ child_range children() {
+ return child_range(reinterpret_cast<Stmt **>(varlist_begin()),
+ reinterpret_cast<Stmt **>(varlist_end()));
+ }
+
+ static bool classof(const OMPClause *T) {
+ return T->getClauseKind() == OMPC_depend;
+ }
+};
+
+/// \brief This represents 'device' clause in the '#pragma omp ...'
+/// directive.
+///
+/// \code
+/// #pragma omp target device(a)
+/// \endcode
+/// In this example directive '#pragma omp target' has clause 'device'
+/// with single expression 'a'.
+///
+class OMPDeviceClause : public OMPClause {
+ friend class OMPClauseReader;
+ /// \brief Location of '('.
+ SourceLocation LParenLoc;
+ /// \brief Device number.
+ Stmt *Device;
+ /// \brief Set the device number.
+ ///
+ /// \param E Device number.
+ ///
+ void setDevice(Expr *E) { Device = E; }
+
+public:
+ /// \brief Build 'device' clause.
+ ///
+ /// \param E Expression associated with this clause.
+ /// \param StartLoc Starting location of the clause.
+ /// \param LParenLoc Location of '('.
+ /// \param EndLoc Ending location of the clause.
+ ///
+ OMPDeviceClause(Expr *E, SourceLocation StartLoc, SourceLocation LParenLoc,
+ SourceLocation EndLoc)
+ : OMPClause(OMPC_device, StartLoc, EndLoc), LParenLoc(LParenLoc),
+ Device(E) {}
+
+ /// \brief Build an empty clause.
+ ///
+ OMPDeviceClause()
+ : OMPClause(OMPC_device, SourceLocation(), SourceLocation()),
+ LParenLoc(SourceLocation()), Device(nullptr) {}
+ /// \brief Sets the location of '('.
+ void setLParenLoc(SourceLocation Loc) { LParenLoc = Loc; }
+ /// \brief Returns the location of '('.
+ SourceLocation getLParenLoc() const { return LParenLoc; }
+ /// \brief Return device number.
+ Expr *getDevice() { return cast<Expr>(Device); }
+ /// \brief Return device number.
+ Expr *getDevice() const { return cast<Expr>(Device); }
+
+ static bool classof(const OMPClause *T) {
+ return T->getClauseKind() == OMPC_device;
+ }
+
+ child_range children() { return child_range(&Device, &Device + 1); }
+};
+
+/// \brief This represents 'threads' clause in the '#pragma omp ...' directive.
+///
+/// \code
+/// #pragma omp ordered threads
+/// \endcode
+/// In this example directive '#pragma omp ordered' has simple 'threads' clause.
+///
+class OMPThreadsClause : public OMPClause {
+public:
+ /// \brief Build 'threads' clause.
+ ///
+ /// \param StartLoc Starting location of the clause.
+ /// \param EndLoc Ending location of the clause.
+ ///
+ OMPThreadsClause(SourceLocation StartLoc, SourceLocation EndLoc)
+ : OMPClause(OMPC_threads, StartLoc, EndLoc) {}
+
+ /// \brief Build an empty clause.
+ ///
+ OMPThreadsClause()
+ : OMPClause(OMPC_threads, SourceLocation(), SourceLocation()) {}
+
+ static bool classof(const OMPClause *T) {
+ return T->getClauseKind() == OMPC_threads;
+ }
+
+ child_range children() {
+ return child_range(child_iterator(), child_iterator());
+ }
+};
+
+/// \brief This represents 'simd' clause in the '#pragma omp ...' directive.
+///
+/// \code
+/// #pragma omp ordered simd
+/// \endcode
+/// In this example directive '#pragma omp ordered' has simple 'simd' clause.
+///
+class OMPSIMDClause : public OMPClause {
+public:
+ /// \brief Build 'simd' clause.
+ ///
+ /// \param StartLoc Starting location of the clause.
+ /// \param EndLoc Ending location of the clause.
+ ///
+ OMPSIMDClause(SourceLocation StartLoc, SourceLocation EndLoc)
+ : OMPClause(OMPC_simd, StartLoc, EndLoc) {}
+
+ /// \brief Build an empty clause.
+ ///
+ OMPSIMDClause() : OMPClause(OMPC_simd, SourceLocation(), SourceLocation()) {}
+
+ static bool classof(const OMPClause *T) {
+ return T->getClauseKind() == OMPC_simd;
+ }
+
+ child_range children() {
+ return child_range(child_iterator(), child_iterator());
+ }
+};
+
+/// \brief This represents clause 'map' in the '#pragma omp ...'
+/// directives.
+///
+/// \code
+/// #pragma omp target map(a,b)
+/// \endcode
+/// In this example directive '#pragma omp target' has clause 'map'
+/// with the variables 'a' and 'b'.
+///
+class OMPMapClause final : public OMPVarListClause<OMPMapClause>,
+ private llvm::TrailingObjects<OMPMapClause, Expr *> {
+ friend TrailingObjects;
+ friend OMPVarListClause;
+ friend class OMPClauseReader;
+
+ /// \brief Map type modifier for the 'map' clause.
+ OpenMPMapClauseKind MapTypeModifier;
+ /// \brief Map type for the 'map' clause.
+ OpenMPMapClauseKind MapType;
+ /// \brief Location of the map type.
+ SourceLocation MapLoc;
+ /// \brief Colon location.
+ SourceLocation ColonLoc;
+
+ /// \brief Set type modifier for the clause.
+ ///
+ /// \param T Type Modifier for the clause.
+ ///
+ void setMapTypeModifier(OpenMPMapClauseKind T) { MapTypeModifier = T; }
+
+ /// \brief Set type for the clause.
+ ///
+ /// \param T Type for the clause.
+ ///
+ void setMapType(OpenMPMapClauseKind T) { MapType = T; }
+
+ /// \brief Set type location.
+ ///
+ /// \param TLoc Type location.
+ ///
+ void setMapLoc(SourceLocation TLoc) { MapLoc = TLoc; }
+
+ /// \brief Set colon location.
+ void setColonLoc(SourceLocation Loc) { ColonLoc = Loc; }
+
+ /// \brief Build clause with number of variables \a N.
+ ///
+ /// \param MapTypeModifier Map type modifier.
+ /// \param MapType Map type.
+ /// \param MapLoc Location of the map type.
+ /// \param StartLoc Starting location of the clause.
+ /// \param EndLoc Ending location of the clause.
+ /// \param N Number of the variables in the clause.
+ ///
+ explicit OMPMapClause(OpenMPMapClauseKind MapTypeModifier,
+ OpenMPMapClauseKind MapType, SourceLocation MapLoc,
+ SourceLocation StartLoc, SourceLocation LParenLoc,
+ SourceLocation EndLoc, unsigned N)
+ : OMPVarListClause<OMPMapClause>(OMPC_map, StartLoc, LParenLoc, EndLoc, N),
+ MapTypeModifier(MapTypeModifier), MapType(MapType), MapLoc(MapLoc) {}
+
+ /// \brief Build an empty clause.
+ ///
+ /// \param N Number of variables.
+ ///
+ explicit OMPMapClause(unsigned N)
+ : OMPVarListClause<OMPMapClause>(OMPC_map, SourceLocation(),
+ SourceLocation(), SourceLocation(), N),
+ MapTypeModifier(OMPC_MAP_unknown), MapType(OMPC_MAP_unknown), MapLoc() {}
+
+public:
+ /// \brief Creates clause with a list of variables \a VL.
+ ///
+ /// \param C AST context.
+ /// \param StartLoc Starting location of the clause.
+ /// \param EndLoc Ending location of the clause.
+ /// \param VL List of references to the variables.
+ /// \param TypeModifier Map type modifier.
+ /// \param Type Map type.
+ /// \param TypeLoc Location of the map type.
+ ///
+ static OMPMapClause *Create(const ASTContext &C, SourceLocation StartLoc,
+ SourceLocation LParenLoc,
+ SourceLocation EndLoc, ArrayRef<Expr *> VL,
+ OpenMPMapClauseKind TypeModifier,
+ OpenMPMapClauseKind Type, SourceLocation TypeLoc);
+ /// \brief Creates an empty clause with the place for \a N variables.
+ ///
+ /// \param C AST context.
+ /// \param N The number of variables.
+ ///
+ static OMPMapClause *CreateEmpty(const ASTContext &C, unsigned N);
+
+ /// \brief Fetches mapping kind for the clause.
+ OpenMPMapClauseKind getMapType() const LLVM_READONLY { return MapType; }
+
+ /// \brief Fetches the map type modifier for the clause.
+ OpenMPMapClauseKind getMapTypeModifier() const LLVM_READONLY {
+ return MapTypeModifier;
+ }
+
+ /// \brief Fetches location of clause mapping kind.
+ SourceLocation getMapLoc() const LLVM_READONLY { return MapLoc; }
+
+ /// \brief Get colon location.
+ SourceLocation getColonLoc() const { return ColonLoc; }
+
+ static bool classof(const OMPClause *T) {
+ return T->getClauseKind() == OMPC_map;
+ }
+
+ child_range children() {
+ return child_range(
+ reinterpret_cast<Stmt **>(varlist_begin()),
+ reinterpret_cast<Stmt **>(varlist_end()));
+ }
+};
+
+/// \brief This represents 'num_teams' clause in the '#pragma omp ...'
+/// directive.
+///
+/// \code
+/// #pragma omp teams num_teams(n)
+/// \endcode
+/// In this example directive '#pragma omp teams' has clause 'num_teams'
+/// with single expression 'n'.
+///
+class OMPNumTeamsClause : public OMPClause {
+ friend class OMPClauseReader;
+ /// \brief Location of '('.
+ SourceLocation LParenLoc;
+ /// \brief NumTeams number.
+ Stmt *NumTeams;
+ /// \brief Set the NumTeams number.
+ ///
+ /// \param E NumTeams number.
+ ///
+ void setNumTeams(Expr *E) { NumTeams = E; }
+
+public:
+ /// \brief Build 'num_teams' clause.
+ ///
+ /// \param E Expression associated with this clause.
+ /// \param StartLoc Starting location of the clause.
+ /// \param LParenLoc Location of '('.
+ /// \param EndLoc Ending location of the clause.
+ ///
+ OMPNumTeamsClause(Expr *E, SourceLocation StartLoc, SourceLocation LParenLoc,
+ SourceLocation EndLoc)
+ : OMPClause(OMPC_num_teams, StartLoc, EndLoc), LParenLoc(LParenLoc),
+ NumTeams(E) {}
+
+ /// \brief Build an empty clause.
+ ///
+ OMPNumTeamsClause()
+ : OMPClause(OMPC_num_teams, SourceLocation(), SourceLocation()),
+ LParenLoc(SourceLocation()), NumTeams(nullptr) {}
+ /// \brief Sets the location of '('.
+ void setLParenLoc(SourceLocation Loc) { LParenLoc = Loc; }
+ /// \brief Returns the location of '('.
+ SourceLocation getLParenLoc() const { return LParenLoc; }
+ /// \brief Return NumTeams number.
+ Expr *getNumTeams() { return cast<Expr>(NumTeams); }
+ /// \brief Return NumTeams number.
+ Expr *getNumTeams() const { return cast<Expr>(NumTeams); }
+
+ static bool classof(const OMPClause *T) {
+ return T->getClauseKind() == OMPC_num_teams;
+ }
+
+ child_range children() { return child_range(&NumTeams, &NumTeams + 1); }
+};
+
+/// \brief This represents 'thread_limit' clause in the '#pragma omp ...'
+/// directive.
+///
+/// \code
+/// #pragma omp teams thread_limit(n)
+/// \endcode
+/// In this example directive '#pragma omp teams' has clause 'thread_limit'
+/// with single expression 'n'.
+///
+class OMPThreadLimitClause : public OMPClause {
+ friend class OMPClauseReader;
+ /// \brief Location of '('.
+ SourceLocation LParenLoc;
+ /// \brief ThreadLimit number.
+ Stmt *ThreadLimit;
+ /// \brief Set the ThreadLimit number.
+ ///
+ /// \param E ThreadLimit number.
+ ///
+ void setThreadLimit(Expr *E) { ThreadLimit = E; }
+
+public:
+ /// \brief Build 'thread_limit' clause.
+ ///
+ /// \param E Expression associated with this clause.
+ /// \param StartLoc Starting location of the clause.
+ /// \param LParenLoc Location of '('.
+ /// \param EndLoc Ending location of the clause.
+ ///
+ OMPThreadLimitClause(Expr *E, SourceLocation StartLoc,
+ SourceLocation LParenLoc, SourceLocation EndLoc)
+ : OMPClause(OMPC_thread_limit, StartLoc, EndLoc), LParenLoc(LParenLoc),
+ ThreadLimit(E) {}
+
+ /// \brief Build an empty clause.
+ ///
+ OMPThreadLimitClause()
+ : OMPClause(OMPC_thread_limit, SourceLocation(), SourceLocation()),
+ LParenLoc(SourceLocation()), ThreadLimit(nullptr) {}
+ /// \brief Sets the location of '('.
+ void setLParenLoc(SourceLocation Loc) { LParenLoc = Loc; }
+ /// \brief Returns the location of '('.
+ SourceLocation getLParenLoc() const { return LParenLoc; }
+ /// \brief Return ThreadLimit number.
+ Expr *getThreadLimit() { return cast<Expr>(ThreadLimit); }
+ /// \brief Return ThreadLimit number.
+ Expr *getThreadLimit() const { return cast<Expr>(ThreadLimit); }
+
+ static bool classof(const OMPClause *T) {
+ return T->getClauseKind() == OMPC_thread_limit;
+ }
+
+ child_range children() { return child_range(&ThreadLimit, &ThreadLimit + 1); }
+};
+
+/// \brief This represents 'priority' clause in the '#pragma omp ...'
+/// directive.
+///
+/// \code
+/// #pragma omp task priority(n)
+/// \endcode
+/// In this example directive '#pragma omp teams' has clause 'priority' with
+/// single expression 'n'.
+///
+class OMPPriorityClause : public OMPClause {
+ friend class OMPClauseReader;
+ /// \brief Location of '('.
+ SourceLocation LParenLoc;
+ /// \brief Priority number.
+ Stmt *Priority;
+ /// \brief Set the Priority number.
+ ///
+ /// \param E Priority number.
+ ///
+ void setPriority(Expr *E) { Priority = E; }
+
+public:
+ /// \brief Build 'priority' clause.
+ ///
+ /// \param E Expression associated with this clause.
+ /// \param StartLoc Starting location of the clause.
+ /// \param LParenLoc Location of '('.
+ /// \param EndLoc Ending location of the clause.
+ ///
+ OMPPriorityClause(Expr *E, SourceLocation StartLoc, SourceLocation LParenLoc,
+ SourceLocation EndLoc)
+ : OMPClause(OMPC_priority, StartLoc, EndLoc), LParenLoc(LParenLoc),
+ Priority(E) {}
+
+ /// \brief Build an empty clause.
+ ///
+ OMPPriorityClause()
+ : OMPClause(OMPC_priority, SourceLocation(), SourceLocation()),
+ LParenLoc(SourceLocation()), Priority(nullptr) {}
+ /// \brief Sets the location of '('.
+ void setLParenLoc(SourceLocation Loc) { LParenLoc = Loc; }
+ /// \brief Returns the location of '('.
+ SourceLocation getLParenLoc() const { return LParenLoc; }
+ /// \brief Return Priority number.
+ Expr *getPriority() { return cast<Expr>(Priority); }
+ /// \brief Return Priority number.
+ Expr *getPriority() const { return cast<Expr>(Priority); }
+
+ static bool classof(const OMPClause *T) {
+ return T->getClauseKind() == OMPC_priority;
+ }
+
+ child_range children() { return child_range(&Priority, &Priority + 1); }
+};
+
+/// \brief This represents 'grainsize' clause in the '#pragma omp ...'
+/// directive.
+///
+/// \code
+/// #pragma omp taskloop grainsize(4)
+/// \endcode
+/// In this example directive '#pragma omp taskloop' has clause 'grainsize'
+/// with single expression '4'.
+///
+class OMPGrainsizeClause : public OMPClause {
+ friend class OMPClauseReader;
+ /// \brief Location of '('.
+ SourceLocation LParenLoc;
+ /// \brief Safe iteration space distance.
+ Stmt *Grainsize;
+
+ /// \brief Set safelen.
+ void setGrainsize(Expr *Size) { Grainsize = Size; }
+
+public:
+ /// \brief Build 'grainsize' clause.
+ ///
+ /// \param Size Expression associated with this clause.
+ /// \param StartLoc Starting location of the clause.
+ /// \param EndLoc Ending location of the clause.
+ ///
+ OMPGrainsizeClause(Expr *Size, SourceLocation StartLoc,
+ SourceLocation LParenLoc, SourceLocation EndLoc)
+ : OMPClause(OMPC_grainsize, StartLoc, EndLoc), LParenLoc(LParenLoc),
+ Grainsize(Size) {}
+
+ /// \brief Build an empty clause.
+ ///
+ explicit OMPGrainsizeClause()
+ : OMPClause(OMPC_grainsize, SourceLocation(), SourceLocation()),
+ LParenLoc(SourceLocation()), Grainsize(nullptr) {}
+
+ /// \brief Sets the location of '('.
+ void setLParenLoc(SourceLocation Loc) { LParenLoc = Loc; }
+ /// \brief Returns the location of '('.
+ SourceLocation getLParenLoc() const { return LParenLoc; }
+
+ /// \brief Return safe iteration space distance.
+ Expr *getGrainsize() const { return cast_or_null<Expr>(Grainsize); }
+
+ static bool classof(const OMPClause *T) {
+ return T->getClauseKind() == OMPC_grainsize;
+ }
+
+ child_range children() { return child_range(&Grainsize, &Grainsize + 1); }
+};
+
+/// \brief This represents 'nogroup' clause in the '#pragma omp ...' directive.
+///
+/// \code
+/// #pragma omp taskloop nogroup
+/// \endcode
+/// In this example directive '#pragma omp taskloop' has 'nogroup' clause.
+///
+class OMPNogroupClause : public OMPClause {
+public:
+ /// \brief Build 'nogroup' clause.
+ ///
+ /// \param StartLoc Starting location of the clause.
+ /// \param EndLoc Ending location of the clause.
+ ///
+ OMPNogroupClause(SourceLocation StartLoc, SourceLocation EndLoc)
+ : OMPClause(OMPC_nogroup, StartLoc, EndLoc) {}
+
+ /// \brief Build an empty clause.
+ ///
+ OMPNogroupClause()
+ : OMPClause(OMPC_nogroup, SourceLocation(), SourceLocation()) {}
+
+ static bool classof(const OMPClause *T) {
+ return T->getClauseKind() == OMPC_nogroup;
+ }
+
+ child_range children() {
+ return child_range(child_iterator(), child_iterator());
+ }
+};
+
+/// \brief This represents 'num_tasks' clause in the '#pragma omp ...'
+/// directive.
+///
+/// \code
+/// #pragma omp taskloop num_tasks(4)
+/// \endcode
+/// In this example directive '#pragma omp taskloop' has clause 'num_tasks'
+/// with single expression '4'.
+///
+class OMPNumTasksClause : public OMPClause {
+ friend class OMPClauseReader;
+ /// \brief Location of '('.
+ SourceLocation LParenLoc;
+ /// \brief Safe iteration space distance.
+ Stmt *NumTasks;
+
+ /// \brief Set safelen.
+ void setNumTasks(Expr *Size) { NumTasks = Size; }
+
+public:
+ /// \brief Build 'num_tasks' clause.
+ ///
+ /// \param Size Expression associated with this clause.
+ /// \param StartLoc Starting location of the clause.
+ /// \param EndLoc Ending location of the clause.
+ ///
+ OMPNumTasksClause(Expr *Size, SourceLocation StartLoc,
+ SourceLocation LParenLoc, SourceLocation EndLoc)
+ : OMPClause(OMPC_num_tasks, StartLoc, EndLoc), LParenLoc(LParenLoc),
+ NumTasks(Size) {}
+
+ /// \brief Build an empty clause.
+ ///
+ explicit OMPNumTasksClause()
+ : OMPClause(OMPC_num_tasks, SourceLocation(), SourceLocation()),
+ LParenLoc(SourceLocation()), NumTasks(nullptr) {}
+
+ /// \brief Sets the location of '('.
+ void setLParenLoc(SourceLocation Loc) { LParenLoc = Loc; }
+ /// \brief Returns the location of '('.
+ SourceLocation getLParenLoc() const { return LParenLoc; }
+
+ /// \brief Return safe iteration space distance.
+ Expr *getNumTasks() const { return cast_or_null<Expr>(NumTasks); }
+
+ static bool classof(const OMPClause *T) {
+ return T->getClauseKind() == OMPC_num_tasks;
+ }
+
+ child_range children() { return child_range(&NumTasks, &NumTasks + 1); }
+};
+
+/// \brief This represents 'hint' clause in the '#pragma omp ...' directive.
+///
+/// \code
+/// #pragma omp critical (name) hint(6)
+/// \endcode
+/// In this example directive '#pragma omp critical' has name 'name' and clause
+/// 'hint' with argument '6'.
+///
+class OMPHintClause : public OMPClause {
+ friend class OMPClauseReader;
+ /// \brief Location of '('.
+ SourceLocation LParenLoc;
+ /// \brief Hint expression of the 'hint' clause.
+ Stmt *Hint;
+
+ /// \brief Set hint expression.
+ ///
+ void setHint(Expr *H) { Hint = H; }
+
+public:
+ /// \brief Build 'hint' clause with expression \a Hint.
+ ///
+ /// \param Hint Hint expression.
+ /// \param StartLoc Starting location of the clause.
+ /// \param LParenLoc Location of '('.
+ /// \param EndLoc Ending location of the clause.
+ ///
+ OMPHintClause(Expr *Hint, SourceLocation StartLoc, SourceLocation LParenLoc,
+ SourceLocation EndLoc)
+ : OMPClause(OMPC_hint, StartLoc, EndLoc), LParenLoc(LParenLoc),
+ Hint(Hint) {}
+
+ /// \brief Build an empty clause.
+ ///
+ OMPHintClause()
+ : OMPClause(OMPC_hint, SourceLocation(), SourceLocation()),
+ LParenLoc(SourceLocation()), Hint(nullptr) {}
+
+ /// \brief Sets the location of '('.
+ void setLParenLoc(SourceLocation Loc) { LParenLoc = Loc; }
+ /// \brief Returns the location of '('.
+ SourceLocation getLParenLoc() const { return LParenLoc; }
+
+ /// \brief Returns number of threads.
+ Expr *getHint() const { return cast_or_null<Expr>(Hint); }
+
+ static bool classof(const OMPClause *T) {
+ return T->getClauseKind() == OMPC_hint;
+ }
+
+ child_range children() { return child_range(&Hint, &Hint + 1); }
+};
+
+} // end namespace clang
+
+#endif // LLVM_CLANG_AST_OPENMPCLAUSE_H
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..2235c10
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/AST/OperationKinds.h
@@ -0,0 +1,356 @@
+//===- 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_OPERATIONKINDS_H
+#define LLVM_CLANG_AST_OPERATIONKINDS_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. A conversion
+ /// from any pointer type to a C pointer type is a bitcast unless
+ /// it's actually BaseToDerived or DerivedToBase. A conversion to a
+ /// block pointer or ObjC pointer type is a bitcast only if the
+ /// operand has the same type kind; otherwise, it's one of the
+ /// specialized casts below.
+ ///
+ /// 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_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_ReinterpretMemberPointer - Reinterpret a member pointer as a
+ /// different kind of member pointer. C++ forbids this from
+ /// crossing between function and object types, but otherwise does
+ /// not restrict it. However, the only operation that is permitted
+ /// on a "punned" member pointer is casting it back to the original
+ /// type, which is required to be a lossless operation (although
+ /// many ABIs do not guarantee this on all possible intermediate types).
+ CK_ReinterpretMemberPointer,
+
+ /// 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_CPointerToObjCPointerCast - Casting a C pointer kind to an
+ /// Objective-C pointer.
+ CK_CPointerToObjCPointerCast,
+
+ /// CK_BlockPointerToObjCPointerCast - Casting a block pointer to an
+ /// ObjC pointer.
+ CK_BlockPointerToObjCPointerCast,
+
+ /// CK_AnyPointerToBlockPointerCast - Casting any non-block pointer
+ /// to a block pointer. Block-to-block casts are bitcasts.
+ 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,
+
+ /// \brief [ARC] Produces a retainable object pointer so that it may
+ /// be consumed, e.g. by being passed to a consuming parameter.
+ /// Calls objc_retain.
+ CK_ARCProduceObject,
+
+ /// \brief [ARC] Consumes a retainable object pointer that has just
+ /// been produced, e.g. as the return value of a retaining call.
+ /// Enters a cleanup to call objc_release at some indefinite time.
+ CK_ARCConsumeObject,
+
+ /// \brief [ARC] Reclaim a retainable object pointer object that may
+ /// have been produced and autoreleased as part of a function return
+ /// sequence.
+ CK_ARCReclaimReturnedObject,
+
+ /// \brief [ARC] Causes a value of block type to be copied to the
+ /// heap, if it is not already there. A number of other operations
+ /// in ARC cause blocks to be copied; this is for cases where that
+ /// would not otherwise be guaranteed, such as when casting to a
+ /// non-block pointer type.
+ CK_ARCExtendBlockObject,
+
+ /// \brief Converts from _Atomic(T) to T.
+ CK_AtomicToNonAtomic,
+ /// \brief Converts from T to _Atomic(T).
+ CK_NonAtomicToAtomic,
+
+ /// \brief Causes a block literal to by copied to the heap and then
+ /// autoreleased.
+ ///
+ /// This particular cast kind is used for the conversion from a C++11
+ /// lambda expression to a block pointer.
+ CK_CopyAndAutoreleaseBlockObject,
+
+ // Convert a builtin function to a function pointer; only allowed in the
+ // callee of a call expression.
+ CK_BuiltinFnToFnPtr,
+
+ // Convert a zero value for OpenCL event_t initialization.
+ CK_ZeroToOCLEvent,
+
+ // Convert a pointer to a different address space.
+ CK_AddressSpaceConversion
+};
+
+static const CastKind CK_Invalid = static_cast<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.
+ UO_Coawait // [C++ Coroutines] co_await operator
+};
+
+/// \brief The kind of bridging performed by the Objective-C bridge cast.
+enum ObjCBridgeCastKind {
+ /// \brief Bridging via __bridge, which does nothing but reinterpret
+ /// the bits.
+ OBC_Bridge,
+ /// \brief Bridging via __bridge_transfer, which transfers ownership of an
+ /// Objective-C pointer into ARC.
+ OBC_BridgeTransfer,
+ /// \brief Bridging via __bridge_retain, which makes an ARC object available
+ /// as a +1 C pointer.
+ OBC_BridgeRetained
+};
+
+}
+
+#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..8945c41
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/AST/ParentMap.h
@@ -0,0 +1,67 @@
+//===--- 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_AST_PARENTMAP_H
+#define LLVM_CLANG_AST_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);
+
+ /// Manually sets the parent of \p S to \p Parent.
+ ///
+ /// If \p S is already in the map, this method will update the mapping.
+ void setParent(const Stmt *S, const Stmt *Parent);
+
+ Stmt *getParent(Stmt*) const;
+ Stmt *getParentIgnoreParens(Stmt *) const;
+ Stmt *getParentIgnoreParenCasts(Stmt *) const;
+ Stmt *getParentIgnoreParenImpCasts(Stmt *) const;
+ Stmt *getOuterParenParent(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) != nullptr;
+ }
+
+ 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..8ab3f617
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/AST/PrettyPrinter.h
@@ -0,0 +1,175 @@
+//===--- 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_PRETTYPRINTER_H
+#define LLVM_CLANG_AST_PRETTYPRINTER_H
+
+#include "clang/Basic/LLVM.h"
+#include "clang/Basic/LangOptions.h"
+
+namespace clang {
+
+class LangOptions;
+class SourceManager;
+class Stmt;
+class TagDecl;
+
+class PrinterHelper {
+public:
+ virtual ~PrinterHelper();
+ virtual bool handledStmt(Stmt* E, 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)
+ : LangOpts(LO), Indentation(2), SuppressSpecifiers(false),
+ SuppressTagKeyword(false), SuppressTag(false), SuppressScope(false),
+ SuppressUnwrittenScope(false), SuppressInitializers(false),
+ ConstantArraySizeAsWritten(false), AnonymousTagLocations(true),
+ SuppressStrongLifetime(false), SuppressLifetimeQualifiers(false),
+ Bool(LO.Bool), TerseOutput(false), PolishForDeclaration(false),
+ Half(LO.Half), MSWChar(LO.MicrosoftExt && !LO.WChar),
+ IncludeNewlines(true), MSVCFormatting(false) { }
+
+ /// \brief What language we're printing.
+ LangOptions LangOpts;
+
+ /// \brief The number of spaces to use to indent each line.
+ unsigned Indentation : 8;
+
+ /// \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 tag keyword.
+ ///
+ /// This is used when printing the inner type of elaborated types,
+ /// (as the tag keyword is part of the elaborated type):
+ ///
+ /// \code
+ /// struct Geometry::Point;
+ /// \endcode
+ bool SuppressTagKeyword : 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 Suppress printing parts of scope specifiers that don't need
+ /// to be written, e.g., for inline or anonymous namespaces.
+ bool SuppressUnwrittenScope : 1;
+
+ /// \brief Suppress printing of variable initializers.
+ ///
+ /// This flag is used when printing the loop variable in a for-range
+ /// statement. For example, given:
+ ///
+ /// \code
+ /// for (auto x : coll)
+ /// \endcode
+ ///
+ /// SuppressInitializers will be true when printing "auto x", so that the
+ /// internal initializer constructed for x will not be printed.
+ bool SuppressInitializers : 1;
+
+ /// \brief Whether we should print the sizes of constant array expressions
+ /// as written in the sources.
+ ///
+ /// This flag determines whether array 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;
+
+ /// \brief When true, suppress printing of the __strong lifetime qualifier in
+ /// ARC.
+ unsigned SuppressStrongLifetime : 1;
+
+ /// \brief When true, suppress printing of lifetime qualifier in
+ /// ARC.
+ unsigned SuppressLifetimeQualifiers : 1;
+
+ /// \brief Whether we can use 'bool' rather than '_Bool', even if the language
+ /// doesn't actually have 'bool' (because, e.g., it is defined as a macro).
+ unsigned Bool : 1;
+
+ /// \brief Provide a 'terse' output.
+ ///
+ /// For example, in this mode we don't print function bodies, class members,
+ /// declarations inside namespaces etc. Effectively, this should print
+ /// only the requested declaration.
+ unsigned TerseOutput : 1;
+
+ /// \brief When true, do certain refinement needed for producing proper
+ /// declaration tag; such as, do not print attributes attached to the declaration.
+ ///
+ unsigned PolishForDeclaration : 1;
+
+ /// \brief When true, print the half-precision floating-point type as 'half'
+ /// instead of '__fp16'
+ unsigned Half : 1;
+
+ /// \brief When true, print the built-in wchar_t type as __wchar_t. For use in
+ /// Microsoft mode when wchar_t is not available.
+ unsigned MSWChar : 1;
+
+ /// \brief When true, include newlines after statements like "break", etc.
+ unsigned IncludeNewlines : 1;
+
+ /// \brief Use whitespace and punctuation like MSVC does. In particular, this
+ /// prints anonymous namespaces as `anonymous namespace' and does not insert
+ /// spaces after template arguments.
+ bool MSVCFormatting : 1;
+};
+
+} // end namespace clang
+
+#endif
diff --git a/contrib/llvm/tools/clang/include/clang/AST/RawCommentList.h b/contrib/llvm/tools/clang/include/clang/AST/RawCommentList.h
new file mode 100644
index 0000000..2e005dd
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/AST/RawCommentList.h
@@ -0,0 +1,203 @@
+//===--- RawCommentList.h - Classes for processing raw comments -*- 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_AST_RAWCOMMENTLIST_H
+#define LLVM_CLANG_AST_RAWCOMMENTLIST_H
+
+#include "clang/Basic/CommentOptions.h"
+#include "clang/Basic/SourceManager.h"
+#include "llvm/ADT/ArrayRef.h"
+
+namespace clang {
+
+class ASTContext;
+class ASTReader;
+class Decl;
+class Preprocessor;
+
+namespace comments {
+ class FullComment;
+} // end namespace comments
+
+class RawComment {
+public:
+ enum CommentKind {
+ RCK_Invalid, ///< Invalid comment
+ RCK_OrdinaryBCPL, ///< Any normal BCPL comments
+ RCK_OrdinaryC, ///< Any normal C comment
+ RCK_BCPLSlash, ///< \code /// stuff \endcode
+ RCK_BCPLExcl, ///< \code //! stuff \endcode
+ RCK_JavaDoc, ///< \code /** stuff */ \endcode
+ RCK_Qt, ///< \code /*! stuff */ \endcode, also used by HeaderDoc
+ RCK_Merged ///< Two or more documentation comments merged together
+ };
+
+ RawComment() : Kind(RCK_Invalid), IsAlmostTrailingComment(false) { }
+
+ RawComment(const SourceManager &SourceMgr, SourceRange SR,
+ bool Merged, bool ParseAllComments);
+
+ CommentKind getKind() const LLVM_READONLY {
+ return (CommentKind) Kind;
+ }
+
+ bool isInvalid() const LLVM_READONLY {
+ return Kind == RCK_Invalid;
+ }
+
+ bool isMerged() const LLVM_READONLY {
+ return Kind == RCK_Merged;
+ }
+
+ /// Is this comment attached to any declaration?
+ bool isAttached() const LLVM_READONLY {
+ return IsAttached;
+ }
+
+ void setAttached() {
+ IsAttached = true;
+ }
+
+ /// Returns true if it is a comment that should be put after a member:
+ /// \code ///< stuff \endcode
+ /// \code //!< stuff \endcode
+ /// \code /**< stuff */ \endcode
+ /// \code /*!< stuff */ \endcode
+ bool isTrailingComment() const LLVM_READONLY {
+ assert(isDocumentation());
+ return IsTrailingComment;
+ }
+
+ /// Returns true if it is a probable typo:
+ /// \code //< stuff \endcode
+ /// \code /*< stuff */ \endcode
+ bool isAlmostTrailingComment() const LLVM_READONLY {
+ return IsAlmostTrailingComment;
+ }
+
+ /// Returns true if this comment is not a documentation comment.
+ bool isOrdinary() const LLVM_READONLY {
+ return ((Kind == RCK_OrdinaryBCPL) || (Kind == RCK_OrdinaryC)) &&
+ !ParseAllComments;
+ }
+
+ /// Returns true if this comment any kind of a documentation comment.
+ bool isDocumentation() const LLVM_READONLY {
+ return !isInvalid() && !isOrdinary();
+ }
+
+ /// Returns whether we are parsing all comments.
+ bool isParseAllComments() const LLVM_READONLY {
+ return ParseAllComments;
+ }
+
+ /// Returns raw comment text with comment markers.
+ StringRef getRawText(const SourceManager &SourceMgr) const {
+ if (RawTextValid)
+ return RawText;
+
+ RawText = getRawTextSlow(SourceMgr);
+ RawTextValid = true;
+ return RawText;
+ }
+
+ SourceRange getSourceRange() const LLVM_READONLY { return Range; }
+ SourceLocation getLocStart() const LLVM_READONLY { return Range.getBegin(); }
+ SourceLocation getLocEnd() const LLVM_READONLY { return Range.getEnd(); }
+
+ const char *getBriefText(const ASTContext &Context) const {
+ if (BriefTextValid)
+ return BriefText;
+
+ return extractBriefText(Context);
+ }
+
+ /// Parse the comment, assuming it is attached to decl \c D.
+ comments::FullComment *parse(const ASTContext &Context,
+ const Preprocessor *PP, const Decl *D) const;
+
+private:
+ SourceRange Range;
+
+ mutable StringRef RawText;
+ mutable const char *BriefText;
+
+ mutable bool RawTextValid : 1; ///< True if RawText is valid
+ mutable bool BriefTextValid : 1; ///< True if BriefText is valid
+
+ unsigned Kind : 3;
+
+ /// True if comment is attached to a declaration in ASTContext.
+ bool IsAttached : 1;
+
+ bool IsTrailingComment : 1;
+ bool IsAlmostTrailingComment : 1;
+
+ /// When true, ordinary comments starting with "//" and "/*" will be
+ /// considered as documentation comments.
+ bool ParseAllComments : 1;
+
+ /// \brief Constructor for AST deserialization.
+ RawComment(SourceRange SR, CommentKind K, bool IsTrailingComment,
+ bool IsAlmostTrailingComment,
+ bool ParseAllComments) :
+ Range(SR), RawTextValid(false), BriefTextValid(false), Kind(K),
+ IsAttached(false), IsTrailingComment(IsTrailingComment),
+ IsAlmostTrailingComment(IsAlmostTrailingComment),
+ ParseAllComments(ParseAllComments)
+ { }
+
+ StringRef getRawTextSlow(const SourceManager &SourceMgr) const;
+
+ const char *extractBriefText(const ASTContext &Context) const;
+
+ friend class ASTReader;
+};
+
+/// \brief Compare comments' source locations.
+template<>
+class BeforeThanCompare<RawComment> {
+ const SourceManager &SM;
+
+public:
+ explicit BeforeThanCompare(const SourceManager &SM) : SM(SM) { }
+
+ bool operator()(const RawComment &LHS, const RawComment &RHS) {
+ return SM.isBeforeInTranslationUnit(LHS.getLocStart(), RHS.getLocStart());
+ }
+
+ bool operator()(const RawComment *LHS, const RawComment *RHS) {
+ return operator()(*LHS, *RHS);
+ }
+};
+
+/// \brief This class represents all comments included in the translation unit,
+/// sorted in order of appearance in the translation unit.
+class RawCommentList {
+public:
+ RawCommentList(SourceManager &SourceMgr) : SourceMgr(SourceMgr) {}
+
+ void addComment(const RawComment &RC, llvm::BumpPtrAllocator &Allocator);
+
+ ArrayRef<RawComment *> getComments() const {
+ return Comments;
+ }
+
+private:
+ SourceManager &SourceMgr;
+ std::vector<RawComment *> Comments;
+
+ void addDeserializedComments(ArrayRef<RawComment *> DeserializedComments);
+
+ friend class ASTReader;
+};
+
+} // 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..667f235
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/AST/RecordLayout.h
@@ -0,0 +1,315 @@
+//===--- 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_RECORDLAYOUT_H
+#define LLVM_CLANG_AST_RECORDLAYOUT_H
+
+#include "clang/AST/CharUnits.h"
+#include "clang/AST/DeclCXX.h"
+#include "llvm/ADT/DenseMap.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 {
+public:
+ struct VBaseInfo {
+ /// The offset to this virtual base in the complete-object layout
+ /// of this class.
+ CharUnits VBaseOffset;
+
+ private:
+ /// Whether this virtual base requires a vtordisp field in the
+ /// Microsoft ABI. These fields are required for certain operations
+ /// in constructors and destructors.
+ bool HasVtorDisp;
+
+ public:
+ bool hasVtorDisp() const { return HasVtorDisp; }
+
+ VBaseInfo() : HasVtorDisp(false) {}
+
+ VBaseInfo(CharUnits VBaseOffset, bool hasVtorDisp) :
+ VBaseOffset(VBaseOffset), HasVtorDisp(hasVtorDisp) {}
+ };
+
+ typedef llvm::DenseMap<const CXXRecordDecl *, VBaseInfo>
+ VBaseOffsetsMapTy;
+
+private:
+ /// Size - Size of record in characters.
+ CharUnits Size;
+
+ /// DataSize - Size of record in characters without tail padding.
+ CharUnits DataSize;
+
+ // Alignment - Alignment of record in characters.
+ CharUnits Alignment;
+
+ /// RequiredAlignment - The required alignment of the object. In the MS-ABI
+ /// the __declspec(align()) trumps #pramga pack and must always be obeyed.
+ CharUnits RequiredAlignment;
+
+ /// FieldOffsets - Array of field offsets in bits.
+ uint64_t *FieldOffsets;
+
+ // 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;
+
+ /// NonVirtualAlignment - The non-virtual alignment (in chars) of an object,
+ /// which is the alignment of the object without virtual bases.
+ CharUnits NonVirtualAlignment;
+
+ /// 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;
+
+ /// VBPtrOffset - Virtual base table offset (Microsoft-only).
+ CharUnits VBPtrOffset;
+
+ /// HasOwnVFPtr - Does this class provide a virtual function table
+ /// (vtable in Itanium, vftbl in Microsoft) that is independent from
+ /// its base classes?
+ bool HasOwnVFPtr : 1;
+
+ /// HasVFPtr - Does this class have a vftable that could be extended by
+ /// a derived class. The class may have inherited this pointer from
+ /// a primary base class.
+ bool HasExtendableVFPtr : 1;
+
+ /// HasZeroSizedSubObject - True if this class contains a zero sized member
+ /// or base or a base with a zero sized member or base. Only used for
+ /// MS-ABI.
+ bool HasZeroSizedSubObject : 1;
+
+ /// \brief True if this class is zero sized or first base is zero sized or
+ /// has this property. Only used for MS-ABI.
+ bool LeadsWithZeroSizedBase : 1;
+
+ /// PrimaryBase - The primary base info for this record.
+ llvm::PointerIntPair<const CXXRecordDecl *, 1, bool> PrimaryBase;
+
+ /// BaseSharingVBPtr - The base we share vbptr with.
+ const CXXRecordDecl *BaseSharingVBPtr;
+
+ /// 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.
+ VBaseOffsetsMapTy 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 requiredAlignment,
+ 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 requiredAlignment,
+ bool hasOwnVFPtr, bool hasExtendableVFPtr,
+ CharUnits vbptroffset,
+ CharUnits datasize,
+ const uint64_t *fieldoffsets, unsigned fieldcount,
+ CharUnits nonvirtualsize, CharUnits nonvirtualalignment,
+ CharUnits SizeOfLargestEmptySubobject,
+ const CXXRecordDecl *PrimaryBase,
+ bool IsPrimaryBaseVirtual,
+ const CXXRecordDecl *BaseSharingVBPtr,
+ bool HasZeroSizedSubObject,
+ bool LeadsWithZeroSizedBase,
+ const BaseOffsetsMapTy& BaseOffsets,
+ const VBaseOffsetsMapTy& VBaseOffsets);
+
+ ~ASTRecordLayout() = default;
+
+ void Destroy(ASTContext &Ctx);
+
+ ASTRecordLayout(const ASTRecordLayout &) = delete;
+ void operator=(const ASTRecordLayout &) = delete;
+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 getNonVirtualAlignment() const {
+ assert(CXXInfo && "Record layout does not have C++ specific info!");
+
+ return CXXInfo->NonVirtualAlignment;
+ }
+
+ /// 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].VBaseOffset;
+ }
+
+ CharUnits getSizeOfLargestEmptySubobject() const {
+ assert(CXXInfo && "Record layout does not have C++ specific info!");
+ return CXXInfo->SizeOfLargestEmptySubobject;
+ }
+
+ /// hasOwnVFPtr - Does this class provide its own virtual-function
+ /// table pointer, rather than inheriting one from a primary base
+ /// class? If so, it is at offset zero.
+ ///
+ /// This implies that the ABI has no primary base class, meaning
+ /// that it has no base classes that are suitable under the conditions
+ /// of the ABI.
+ bool hasOwnVFPtr() const {
+ assert(CXXInfo && "Record layout does not have C++ specific info!");
+ return CXXInfo->HasOwnVFPtr;
+ }
+
+ /// hasVFPtr - Does this class have a virtual function table pointer
+ /// that can be extended by a derived class? This is synonymous with
+ /// this class having a VFPtr at offset zero.
+ bool hasExtendableVFPtr() const {
+ assert(CXXInfo && "Record layout does not have C++ specific info!");
+ return CXXInfo->HasExtendableVFPtr;
+ }
+
+ /// hasOwnVBPtr - Does this class provide its own virtual-base
+ /// table pointer, rather than inheriting one from a primary base
+ /// class?
+ ///
+ /// This implies that the ABI has no primary base class, meaning
+ /// that it has no base classes that are suitable under the conditions
+ /// of the ABI.
+ bool hasOwnVBPtr() const {
+ assert(CXXInfo && "Record layout does not have C++ specific info!");
+ return hasVBPtr() && !CXXInfo->BaseSharingVBPtr;
+ }
+
+ /// hasVBPtr - Does this class have a virtual function table pointer.
+ bool hasVBPtr() const {
+ assert(CXXInfo && "Record layout does not have C++ specific info!");
+ return !CXXInfo->VBPtrOffset.isNegative();
+ }
+
+ CharUnits getRequiredAlignment() const {
+ return RequiredAlignment;
+ }
+
+ bool hasZeroSizedSubObject() const {
+ return CXXInfo && CXXInfo->HasZeroSizedSubObject;
+ }
+
+ bool leadsWithZeroSizedBase() const {
+ assert(CXXInfo && "Record layout does not have C++ specific info!");
+ return CXXInfo->LeadsWithZeroSizedBase;
+ }
+
+ /// getVBPtrOffset - Get the offset for virtual base table pointer.
+ /// This is only meaningful with the Microsoft ABI.
+ CharUnits getVBPtrOffset() const {
+ assert(CXXInfo && "Record layout does not have C++ specific info!");
+ return CXXInfo->VBPtrOffset;
+ }
+
+ const CXXRecordDecl *getBaseSharingVBPtr() const {
+ assert(CXXInfo && "Record layout does not have C++ specific info!");
+ return CXXInfo->BaseSharingVBPtr;
+ }
+
+ const VBaseOffsetsMapTy &getVBaseOffsetsMap() const {
+ assert(CXXInfo && "Record layout does not have C++ specific info!");
+ return CXXInfo->VBaseOffsets;
+ }
+};
+
+} // 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..e6f7583
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/AST/RecursiveASTVisitor.h
@@ -0,0 +1,2805 @@
+//===--- 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 <type_traits>
+
+#include "clang/AST/Attr.h"
+#include "clang/AST/Decl.h"
+#include "clang/AST/DeclCXX.h"
+#include "clang/AST/DeclFriend.h"
+#include "clang/AST/DeclObjC.h"
+#include "clang/AST/DeclOpenMP.h"
+#include "clang/AST/DeclTemplate.h"
+#include "clang/AST/Expr.h"
+#include "clang/AST/ExprCXX.h"
+#include "clang/AST/ExprObjC.h"
+#include "clang/AST/ExprOpenMP.h"
+#include "clang/AST/NestedNameSpecifier.h"
+#include "clang/AST/Stmt.h"
+#include "clang/AST/StmtCXX.h"
+#include "clang/AST/StmtObjC.h"
+#include "clang/AST/StmtOpenMP.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) OPERATOR(Coawait)
+
+// 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 NamespaceDecl, 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:
+ /// A queue used for performing data recursion over statements.
+ /// Parameters involving this type are used to implement data
+ /// recursion over Stmts and Exprs within this class, and should
+ /// typically not be explicitly specified by derived classes.
+ typedef SmallVectorImpl<Stmt *> DataRecursionQueue;
+
+ /// \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 Return whether this visitor should recurse into implicit
+ /// code, e.g., implicit constructors and destructors.
+ bool shouldVisitImplicitCode() const { return false; }
+
+ /// \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 nullptr).
+ bool TraverseStmt(Stmt *S, DataRecursionQueue *Queue = nullptr);
+
+ /// \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 an attribute, by dispatching to
+ /// Traverse*Attr() based on the argument's dynamic type.
+ ///
+ /// \returns false if the visitation was terminated early, true
+ /// otherwise (including when the argument is a Null type location).
+ bool TraverseAttr(Attr *At);
+
+ /// \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 C++ nested-name-specifier with location
+ /// information.
+ ///
+ /// \returns false if the visitation was terminated early, true otherwise.
+ bool TraverseNestedNameSpecifierLoc(NestedNameSpecifierLoc NNS);
+
+ /// \brief Recursively visit a name with its location information.
+ ///
+ /// \returns false if the visitation was terminated early, true otherwise.
+ bool TraverseDeclarationNameInfo(DeclarationNameInfo NameInfo);
+
+ /// \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);
+
+ /// \brief Recursively visit a lambda capture.
+ ///
+ /// \returns false if the visitation was terminated early, true otherwise.
+ bool TraverseLambdaCapture(LambdaExpr *LE, const LambdaCapture *C);
+
+ /// \brief Recursively visit the body of a lambda expression.
+ ///
+ /// This provides a hook for visitors that need more context when visiting
+ /// \c LE->getBody().
+ ///
+ /// \returns false if the visitation was terminated early, true otherwise.
+ bool TraverseLambdaBody(LambdaExpr *LE, DataRecursionQueue *Queue = nullptr);
+
+ /// \brief Recursively visit the syntactic or semantic form of an
+ /// initialization list.
+ ///
+ /// \returns false if the visitation was terminated early, true otherwise.
+ bool TraverseSynOrSemInitListExpr(InitListExpr *S,
+ DataRecursionQueue *Queue = nullptr);
+
+ // ---- Methods on Attrs ----
+
+ // \brief Visit an attribute.
+ bool VisitAttr(Attr *A) { return true; }
+
+// Declare Traverse* and empty Visit* for all Attr classes.
+#define ATTR_VISITOR_DECLS_ONLY
+#include "clang/AST/AttrVisitor.inc"
+#undef ATTR_VISITOR_DECLS_ONLY
+
+// ---- Methods on Stmts ----
+
+private:
+ template<typename T, typename U>
+ struct has_same_member_pointer_type : std::false_type {};
+ template<typename T, typename U, typename R, typename... P>
+ struct has_same_member_pointer_type<R (T::*)(P...), R (U::*)(P...)>
+ : std::true_type {};
+
+ // Traverse the given statement. If the most-derived traverse function takes a
+ // data recursion queue, pass it on; otherwise, discard it. Note that the
+ // first branch of this conditional must compile whether or not the derived
+ // class can take a queue, so if we're taking the second arm, make the first
+ // arm call our function rather than the derived class version.
+#define TRAVERSE_STMT_BASE(NAME, CLASS, VAR, QUEUE) \
+ (has_same_member_pointer_type<decltype( \
+ &RecursiveASTVisitor::Traverse##NAME), \
+ decltype(&Derived::Traverse##NAME)>::value \
+ ? static_cast<typename std::conditional< \
+ has_same_member_pointer_type< \
+ decltype(&RecursiveASTVisitor::Traverse##NAME), \
+ decltype(&Derived::Traverse##NAME)>::value, \
+ Derived &, RecursiveASTVisitor &>::type>(*this) \
+ .Traverse##NAME(static_cast<CLASS *>(VAR), QUEUE) \
+ : getDerived().Traverse##NAME(static_cast<CLASS *>(VAR)))
+
+// Try to traverse the given statement, or enqueue it if we're performing data
+// recursion in the middle of traversing another statement. Can only be called
+// from within a DEF_TRAVERSE_STMT body or similar context.
+#define TRY_TO_TRAVERSE_OR_ENQUEUE_STMT(S) \
+ do { \
+ if (!TRAVERSE_STMT_BASE(Stmt, Stmt, S, Queue)) \
+ return false; \
+ } while (0)
+
+public:
+// Declare Traverse*() for all concrete Stmt classes.
+#define ABSTRACT_STMT(STMT)
+#define STMT(CLASS, PARENT) \
+ bool Traverse##CLASS(CLASS *S, DataRecursionQueue *Queue = nullptr);
+#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, \
+ DataRecursionQueue *Queue = nullptr) { \
+ TRY_TO(WalkUpFromUnary##NAME(S)); \
+ TRY_TO_TRAVERSE_OR_ENQUEUE_STMT(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, DataRecursionQueue *Queue = nullptr) { \
+ TRY_TO(WalkUpFromBin##NAME(S)); \
+ TRY_TO_TRAVERSE_OR_ENQUEUE_STMT(S->getLHS()); \
+ TRY_TO_TRAVERSE_OR_ENQUEUE_STMT(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 TypeLoc 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);
+#define DEF_TRAVERSE_TMPL_INST(TMPLDECLKIND) \
+ bool TraverseTemplateInstantiations(TMPLDECLKIND##TemplateDecl *D);
+ DEF_TRAVERSE_TMPL_INST(Class)
+ DEF_TRAVERSE_TMPL_INST(Var)
+ DEF_TRAVERSE_TMPL_INST(Function)
+#undef DEF_TRAVERSE_TMPL_INST
+ 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);
+ bool TraverseOMPExecutableDirective(OMPExecutableDirective *S);
+ bool TraverseOMPLoopDirective(OMPLoopDirective *S);
+ bool TraverseOMPClause(OMPClause *C);
+#define OPENMP_CLAUSE(Name, Class) bool Visit##Class(Class *C);
+#include "clang/Basic/OpenMPKinds.def"
+ /// \brief Process clauses with list of variables.
+ template <typename T> bool VisitOMPClauseList(T *Node);
+
+ bool dataTraverseNode(Stmt *S, DataRecursionQueue *Queue);
+};
+
+template <typename Derived>
+bool RecursiveASTVisitor<Derived>::dataTraverseNode(Stmt *S,
+ DataRecursionQueue *Queue) {
+#define DISPATCH_STMT(NAME, CLASS, VAR) \
+ return TRAVERSE_STMT_BASE(NAME, CLASS, VAR, Queue);
+
+ // 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_STMT(Bin##NAME, BinaryOperator, S);
+
+ BINOP_LIST()
+#undef OPERATOR
+#undef BINOP_LIST
+
+#define OPERATOR(NAME) \
+ case BO_##NAME##Assign: \
+ DISPATCH_STMT(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_STMT(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_STMT(CLASS, CLASS, S);
+#include "clang/AST/StmtNodes.inc"
+ }
+
+ return true;
+}
+
+#undef DISPATCH_STMT
+
+template <typename Derived>
+bool RecursiveASTVisitor<Derived>::TraverseStmt(Stmt *S,
+ DataRecursionQueue *Queue) {
+ if (!S)
+ return true;
+
+ if (Queue) {
+ Queue->push_back(S);
+ return true;
+ }
+
+ SmallVector<Stmt *, 8> LocalQueue;
+ LocalQueue.push_back(S);
+
+ while (!LocalQueue.empty()) {
+ Stmt *CurrS = LocalQueue.pop_back_val();
+
+ size_t N = LocalQueue.size();
+ TRY_TO(dataTraverseNode(CurrS, &LocalQueue));
+ // Process new children in the order they were added.
+ std::reverse(LocalQueue.begin() + N, LocalQueue.end());
+ }
+
+ return true;
+}
+
+#define DISPATCH(NAME, CLASS, VAR) \
+ return getDerived().Traverse##NAME(static_cast<CLASS *>(VAR))
+
+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(TL.castAs<CLASS##TypeLoc>());
+#include "clang/AST/TypeLocNodes.def"
+ }
+
+ return true;
+}
+
+// Define the Traverse*Attr(Attr* A) methods
+#define VISITORCLASS RecursiveASTVisitor
+#include "clang/AST/AttrVisitor.inc"
+#undef VISITORCLASS
+
+template <typename Derived>
+bool RecursiveASTVisitor<Derived>::TraverseDecl(Decl *D) {
+ if (!D)
+ return true;
+
+ // As a syntax visitor, by default we want to ignore declarations for
+ // implicit declarations (ones not typed explicitly by the user).
+ if (!getDerived().shouldVisitImplicitCode() && D->isImplicit())
+ return true;
+
+ switch (D->getKind()) {
+#define ABSTRACT_DECL(DECL)
+#define DECL(CLASS, BASE) \
+ case Decl::CLASS: \
+ if (!getDerived().Traverse##CLASS##Decl(static_cast<CLASS##Decl *>(D))) \
+ return false; \
+ break;
+#include "clang/AST/DeclNodes.inc"
+ }
+
+ // Visit any attributes attached to this declaration.
+ for (auto *I : D->attrs()) {
+ if (!getDerived().TraverseAttr(I))
+ return false;
+ }
+ 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::NamespaceAlias:
+ case NestedNameSpecifier::Global:
+ case NestedNameSpecifier::Super:
+ return true;
+
+ case NestedNameSpecifier::TypeSpec:
+ case NestedNameSpecifier::TypeSpecWithTemplate:
+ TRY_TO(TraverseType(QualType(NNS->getAsType(), 0)));
+ }
+
+ return true;
+}
+
+template <typename Derived>
+bool RecursiveASTVisitor<Derived>::TraverseNestedNameSpecifierLoc(
+ NestedNameSpecifierLoc NNS) {
+ if (!NNS)
+ return true;
+
+ if (NestedNameSpecifierLoc Prefix = NNS.getPrefix())
+ TRY_TO(TraverseNestedNameSpecifierLoc(Prefix));
+
+ switch (NNS.getNestedNameSpecifier()->getKind()) {
+ case NestedNameSpecifier::Identifier:
+ case NestedNameSpecifier::Namespace:
+ case NestedNameSpecifier::NamespaceAlias:
+ case NestedNameSpecifier::Global:
+ case NestedNameSpecifier::Super:
+ return true;
+
+ case NestedNameSpecifier::TypeSpec:
+ case NestedNameSpecifier::TypeSpecWithTemplate:
+ TRY_TO(TraverseTypeLoc(NNS.getTypeLoc()));
+ break;
+ }
+
+ return true;
+}
+
+template <typename Derived>
+bool RecursiveASTVisitor<Derived>::TraverseDeclarationNameInfo(
+ DeclarationNameInfo NameInfo) {
+ switch (NameInfo.getName().getNameKind()) {
+ case DeclarationName::CXXConstructorName:
+ case DeclarationName::CXXDestructorName:
+ case DeclarationName::CXXConversionFunctionName:
+ if (TypeSourceInfo *TSInfo = NameInfo.getNamedTypeInfo())
+ TRY_TO(TraverseTypeLoc(TSInfo->getTypeLoc()));
+
+ break;
+
+ case DeclarationName::Identifier:
+ case DeclarationName::ObjCZeroArgSelector:
+ case DeclarationName::ObjCOneArgSelector:
+ case DeclarationName::ObjCMultiArgSelector:
+ case DeclarationName::CXXOperatorName:
+ case DeclarationName::CXXLiteralOperatorName:
+ case DeclarationName::CXXUsingDirective:
+ break;
+ }
+
+ 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:
+ case TemplateArgument::NullPtr:
+ 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:
+ case TemplateArgument::NullPtr:
+ return true;
+
+ case TemplateArgument::Type: {
+ // FIXME: how can TSI ever be NULL?
+ if (TypeSourceInfo *TSI = ArgLoc.getTypeSourceInfo())
+ return getDerived().TraverseTypeLoc(TSI->getTypeLoc());
+ else
+ return getDerived().TraverseType(Arg.getAsType());
+ }
+
+ case TemplateArgument::Template:
+ case TemplateArgument::TemplateExpansion:
+ if (ArgLoc.getTemplateQualifierLoc())
+ TRY_TO(getDerived().TraverseNestedNameSpecifierLoc(
+ ArgLoc.getTemplateQualifierLoc()));
+ 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) {
+ if (TypeSourceInfo *TInfo = Init->getTypeSourceInfo())
+ TRY_TO(TraverseTypeLoc(TInfo->getTypeLoc()));
+
+ if (Init->isWritten() || getDerived().shouldVisitImplicitCode())
+ TRY_TO(TraverseStmt(Init->getInit()));
+ return true;
+}
+
+template <typename Derived>
+bool
+RecursiveASTVisitor<Derived>::TraverseLambdaCapture(LambdaExpr *LE,
+ const LambdaCapture *C) {
+ if (LE->isInitCapture(C))
+ TRY_TO(TraverseDecl(C->getCapturedVar()));
+ return true;
+}
+
+template <typename Derived>
+bool RecursiveASTVisitor<Derived>::TraverseLambdaBody(
+ LambdaExpr *LE, DataRecursionQueue *Queue) {
+ TRY_TO_TRAVERSE_OR_ENQUEUE_STMT(LE->getBody());
+ 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(AdjustedType, { TRY_TO(TraverseType(T->getOriginalType())); })
+
+DEF_TRAVERSE_TYPE(DecayedType, { TRY_TO(TraverseType(T->getOriginalType())); })
+
+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->getReturnType())); })
+
+DEF_TRAVERSE_TYPE(FunctionProtoType, {
+ TRY_TO(TraverseType(T->getReturnType()));
+
+ for (const auto &A : T->param_types()) {
+ TRY_TO(TraverseType(A));
+ }
+
+ for (const auto &E : T->exceptions()) {
+ TRY_TO(TraverseType(E));
+ }
+
+ if (Expr *NE = T->getNoexceptExpr())
+ TRY_TO(TraverseStmt(NE));
+})
+
+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(UnaryTransformType, {
+ TRY_TO(TraverseType(T->getBaseType()));
+ TRY_TO(TraverseType(T->getUnderlyingType()));
+})
+
+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()));
+ for (auto typeArg : T->getTypeArgsAsWritten()) {
+ TRY_TO(TraverseType(typeArg));
+ }
+})
+
+DEF_TRAVERSE_TYPE(ObjCObjectPointerType,
+ { TRY_TO(TraverseType(T->getPointeeType())); })
+
+DEF_TRAVERSE_TYPE(AtomicType, { TRY_TO(TraverseType(T->getValueType())); })
+
+#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()));
+})
+
+DEF_TRAVERSE_TYPELOC(AdjustedType,
+ { TRY_TO(TraverseTypeLoc(TL.getOriginalLoc())); })
+
+DEF_TRAVERSE_TYPELOC(DecayedType,
+ { TRY_TO(TraverseTypeLoc(TL.getOriginalLoc())); })
+
+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.getReturnLoc())); })
+
+// FIXME: location of exception specifications (attributes?)
+DEF_TRAVERSE_TYPELOC(FunctionProtoType, {
+ TRY_TO(TraverseTypeLoc(TL.getReturnLoc()));
+
+ const FunctionProtoType *T = TL.getTypePtr();
+
+ for (unsigned I = 0, E = TL.getNumParams(); I != E; ++I) {
+ if (TL.getParam(I)) {
+ TRY_TO(TraverseDecl(TL.getParam(I)));
+ } else if (I < T->getNumParams()) {
+ TRY_TO(TraverseType(T->getParamType(I)));
+ }
+ }
+
+ for (const auto &E : T->exceptions()) {
+ TRY_TO(TraverseType(E));
+ }
+
+ if (Expr *NE = T->getNoexceptExpr())
+ TRY_TO(TraverseStmt(NE));
+})
+
+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(UnaryTransformType, {
+ TRY_TO(TraverseTypeLoc(TL.getUnderlyingTInfo()->getTypeLoc()));
+})
+
+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())); })
+
+DEF_TRAVERSE_TYPELOC(ElaboratedType, {
+ if (TL.getQualifierLoc()) {
+ TRY_TO(TraverseNestedNameSpecifierLoc(TL.getQualifierLoc()));
+ }
+ TRY_TO(TraverseTypeLoc(TL.getNamedTypeLoc()));
+})
+
+DEF_TRAVERSE_TYPELOC(DependentNameType, {
+ TRY_TO(TraverseNestedNameSpecifierLoc(TL.getQualifierLoc()));
+})
+
+DEF_TRAVERSE_TYPELOC(DependentTemplateSpecializationType, {
+ if (TL.getQualifierLoc()) {
+ TRY_TO(TraverseNestedNameSpecifierLoc(TL.getQualifierLoc()));
+ }
+
+ 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()));
+ for (unsigned i = 0, n = TL.getNumTypeArgs(); i != n; ++i)
+ TRY_TO(TraverseTypeLoc(TL.getTypeArgTInfo(i)->getTypeLoc()));
+})
+
+DEF_TRAVERSE_TYPELOC(ObjCObjectPointerType,
+ { TRY_TO(TraverseTypeLoc(TL.getPointeeLoc())); })
+
+DEF_TRAVERSE_TYPELOC(AtomicType, { TRY_TO(TraverseTypeLoc(TL.getValueLoc())); })
+
+#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 (auto *Child : DC->decls()) {
+ // BlockDecls and CapturedDecls are traversed through BlockExprs and
+ // CapturedStmts respectively.
+ if (!isa<BlockDecl>(Child) && !isa<CapturedDecl>(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, {
+ if (TypeSourceInfo *TInfo = D->getSignatureAsWritten())
+ TRY_TO(TraverseTypeLoc(TInfo->getTypeLoc()));
+ TRY_TO(TraverseStmt(D->getBody()));
+ for (const auto &I : D->captures()) {
+ if (I.hasCopyExpr()) {
+ TRY_TO(TraverseStmt(I.getCopyExpr()));
+ }
+ }
+ // 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(CapturedDecl, {
+ TRY_TO(TraverseStmt(D->getBody()));
+ // 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(EmptyDecl, {})
+
+DEF_TRAVERSE_DECL(FileScopeAsmDecl,
+ { TRY_TO(TraverseStmt(D->getAsmString())); })
+
+DEF_TRAVERSE_DECL(ImportDecl, {})
+
+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(ClassScopeFunctionSpecializationDecl, {
+ TRY_TO(TraverseDecl(D->getSpecialization()));
+
+ if (D->hasExplicitTemplateArgs()) {
+ const TemplateArgumentListInfo &args = D->templateArgs();
+ TRY_TO(TraverseTemplateArgumentLocsHelper(args.getArgumentArray(),
+ args.size()));
+ }
+})
+
+DEF_TRAVERSE_DECL(LinkageSpecDecl, {})
+
+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(ExternCContextDecl, {})
+
+DEF_TRAVERSE_DECL(NamespaceAliasDecl, {
+ TRY_TO(TraverseNestedNameSpecifierLoc(D->getQualifierLoc()));
+
+ // 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
+ if (ObjCTypeParamList *typeParamList = D->getTypeParamList()) {
+ for (auto typeParam : *typeParamList) {
+ TRY_TO(TraverseObjCTypeParamDecl(typeParam));
+ }
+ }
+})
+
+DEF_TRAVERSE_DECL(ObjCCategoryImplDecl, {// FIXME: implement
+ })
+
+DEF_TRAVERSE_DECL(ObjCImplementationDecl, {// FIXME: implement
+ })
+
+DEF_TRAVERSE_DECL(ObjCInterfaceDecl, {// FIXME: implement
+ if (ObjCTypeParamList *typeParamList = D->getTypeParamListAsWritten()) {
+ for (auto typeParam : *typeParamList) {
+ TRY_TO(TraverseObjCTypeParamDecl(typeParam));
+ }
+ }
+
+ if (TypeSourceInfo *superTInfo = D->getSuperClassTInfo()) {
+ TRY_TO(TraverseTypeLoc(superTInfo->getTypeLoc()));
+ }
+})
+
+DEF_TRAVERSE_DECL(ObjCProtocolDecl, {// FIXME: implement
+ })
+
+DEF_TRAVERSE_DECL(ObjCMethodDecl, {
+ if (D->getReturnTypeSourceInfo()) {
+ TRY_TO(TraverseTypeLoc(D->getReturnTypeSourceInfo()->getTypeLoc()));
+ }
+ for (ObjCMethodDecl::param_iterator I = D->param_begin(), E = D->param_end();
+ I != E; ++I) {
+ TRY_TO(TraverseDecl(*I));
+ }
+ if (D->isThisDeclarationADefinition()) {
+ TRY_TO(TraverseStmt(D->getBody()));
+ }
+ return true;
+})
+
+DEF_TRAVERSE_DECL(ObjCTypeParamDecl, {
+ if (D->hasExplicitBound()) {
+ TRY_TO(TraverseTypeLoc(D->getTypeSourceInfo()->getTypeLoc()));
+ // We shouldn't traverse D->getTypeForDecl(); it's a result of
+ // declaring the type alias, not something that was written in the
+ // source.
+ }
+})
+
+DEF_TRAVERSE_DECL(ObjCPropertyDecl, {
+ if (D->getTypeSourceInfo())
+ TRY_TO(TraverseTypeLoc(D->getTypeSourceInfo()->getTypeLoc()));
+ else
+ TRY_TO(TraverseType(D->getType()));
+ return true;
+})
+
+DEF_TRAVERSE_DECL(UsingDecl, {
+ TRY_TO(TraverseNestedNameSpecifierLoc(D->getQualifierLoc()));
+ TRY_TO(TraverseDeclarationNameInfo(D->getNameInfo()));
+})
+
+DEF_TRAVERSE_DECL(UsingDirectiveDecl, {
+ TRY_TO(TraverseNestedNameSpecifierLoc(D->getQualifierLoc()));
+})
+
+DEF_TRAVERSE_DECL(UsingShadowDecl, {})
+
+DEF_TRAVERSE_DECL(OMPThreadPrivateDecl, {
+ for (auto *I : D->varlists()) {
+ TRY_TO(TraverseStmt(I));
+ }
+})
+
+// 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;
+}
+
+template <typename Derived>
+bool RecursiveASTVisitor<Derived>::TraverseTemplateInstantiations(
+ ClassTemplateDecl *D) {
+ for (auto *SD : D->specializations()) {
+ for (auto *RD : SD->redecls()) {
+ // We don't want to visit injected-class-names in this traversal.
+ if (cast<CXXRecordDecl>(RD)->isInjectedClassName())
+ continue;
+
+ switch (
+ cast<ClassTemplateSpecializationDecl>(RD)->getSpecializationKind()) {
+ // Visit the implicit instantiations with the requested pattern.
+ case TSK_Undeclared:
+ case TSK_ImplicitInstantiation:
+ TRY_TO(TraverseDecl(RD));
+ 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;
+ }
+ }
+ }
+
+ return true;
+}
+
+template <typename Derived>
+bool RecursiveASTVisitor<Derived>::TraverseTemplateInstantiations(
+ VarTemplateDecl *D) {
+ for (auto *SD : D->specializations()) {
+ for (auto *RD : SD->redecls()) {
+ switch (
+ cast<VarTemplateSpecializationDecl>(RD)->getSpecializationKind()) {
+ case TSK_Undeclared:
+ case TSK_ImplicitInstantiation:
+ TRY_TO(TraverseDecl(RD));
+ break;
+
+ case TSK_ExplicitInstantiationDeclaration:
+ case TSK_ExplicitInstantiationDefinition:
+ case TSK_ExplicitSpecialization:
+ break;
+ }
+ }
+ }
+
+ return true;
+}
+
+// A helper method for traversing the instantiations of a
+// function while skipping its specializations.
+template <typename Derived>
+bool RecursiveASTVisitor<Derived>::TraverseTemplateInstantiations(
+ FunctionTemplateDecl *D) {
+ for (auto *FD : D->specializations()) {
+ for (auto *RD : FD->redecls()) {
+ switch (RD->getTemplateSpecializationKind()) {
+ case TSK_Undeclared:
+ case TSK_ImplicitInstantiation:
+ // We don't know what kind of FunctionDecl this is.
+ TRY_TO(TraverseDecl(RD));
+ break;
+
+ // FIXME: For now traverse explicit instantiations here. Change that
+ // once they are represented as dedicated nodes in the AST.
+ case TSK_ExplicitInstantiationDeclaration:
+ case TSK_ExplicitInstantiationDefinition:
+ TRY_TO(TraverseDecl(RD));
+ break;
+
+ case TSK_ExplicitSpecialization:
+ break;
+ }
+ }
+ }
+
+ return true;
+}
+
+// This macro unifies the traversal of class, variable and function
+// template declarations.
+#define DEF_TRAVERSE_TMPL_DECL(TMPLDECLKIND) \
+ DEF_TRAVERSE_DECL(TMPLDECLKIND##TemplateDecl, { \
+ TRY_TO(TraverseDecl(D->getTemplatedDecl())); \
+ TRY_TO(TraverseTemplateParameterListHelper(D->getTemplateParameters())); \
+ \
+ /* By default, we do not traverse the instantiations of \
+ class templates since they do not appear in the user code. The \
+ following code optionally traverses them. \
+ \
+ We only traverse the class instantiations when we see the canonical \
+ declaration of the template, to ensure we only visit them once. */ \
+ if (getDerived().shouldVisitTemplateInstantiations() && \
+ D == D->getCanonicalDecl()) \
+ TRY_TO(TraverseTemplateInstantiations(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. */ \
+ })
+
+DEF_TRAVERSE_TMPL_DECL(Class)
+DEF_TRAVERSE_TMPL_DECL(Var)
+DEF_TRAVERSE_TMPL_DECL(Function)
+
+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() && !D->defaultArgumentWasInherited()) {
+ TRY_TO(TraverseTemplateArgumentLoc(D->getDefaultArgument()));
+ }
+ TRY_TO(TraverseTemplateParameterListHelper(D->getTemplateParameters()));
+})
+
+DEF_TRAVERSE_DECL(BuiltinTemplateDecl, {
+ 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() && !D->defaultArgumentWasInherited())
+ 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(TypeAliasDecl, {
+ TRY_TO(TraverseTypeLoc(D->getTypeSourceInfo()->getTypeLoc()));
+ // We shouldn't traverse D->getTypeForDecl(); it's a result of
+ // declaring the type alias, not something that was written in the
+ // source.
+})
+
+DEF_TRAVERSE_DECL(TypeAliasTemplateDecl, {
+ TRY_TO(TraverseDecl(D->getTemplatedDecl()));
+ TRY_TO(TraverseTemplateParameterListHelper(D->getTemplateParameters()));
+})
+
+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(TraverseNestedNameSpecifierLoc(D->getQualifierLoc()));
+ // 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(TraverseNestedNameSpecifierLoc(D->getQualifierLoc()));
+ // 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(TraverseNestedNameSpecifierLoc(D->getQualifierLoc()));
+ return true;
+}
+
+template <typename Derived>
+bool RecursiveASTVisitor<Derived>::TraverseCXXRecordHelper(CXXRecordDecl *D) {
+ if (!TraverseRecordHelper(D))
+ return false;
+ if (D->isCompleteDefinition()) {
+ for (const auto &I : D->bases()) {
+ 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)); })
+
+#define DEF_TRAVERSE_TMPL_SPEC_DECL(TMPLDECLKIND) \
+ DEF_TRAVERSE_DECL(TMPLDECLKIND##TemplateSpecializationDecl, { \
+ /* For implicit instantiations ("set<int> x;"), we don't want to \
+ recurse at all, since the instatiated template 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 *TemplateSpecializationDecl \
+ (embedded in the DEF_TRAVERSE_DECL() macro) \
+ which contains the instantiated members of the template. */ \
+ return true; \
+ })
+
+DEF_TRAVERSE_TMPL_SPEC_DECL(Class)
+DEF_TRAVERSE_TMPL_SPEC_DECL(Var)
+
+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;
+}
+
+#define DEF_TRAVERSE_TMPL_PART_SPEC_DECL(TMPLDECLKIND, DECLKIND) \
+ DEF_TRAVERSE_DECL(TMPLDECLKIND##TemplatePartialSpecializationDecl, { \
+ /* 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()->getTemplateArgs(), \
+ D->getTemplateArgsAsWritten()->NumTemplateArgs)); \
+ \
+ /* Don't need the *TemplatePartialSpecializationHelper, even \
+ though that's our parent class -- we already visit all the \
+ template args here. */ \
+ TRY_TO(Traverse##DECLKIND##Helper(D)); \
+ \
+ /* Instantiations will have been visited with the primary template. */ \
+ })
+
+DEF_TRAVERSE_TMPL_PART_SPEC_DECL(Class, CXXRecord)
+DEF_TRAVERSE_TMPL_PART_SPEC_DECL(Var, Var)
+
+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(TraverseNestedNameSpecifierLoc(D->getQualifierLoc()));
+ TRY_TO(TraverseDeclarationNameInfo(D->getNameInfo()));
+})
+
+DEF_TRAVERSE_DECL(IndirectFieldDecl, {})
+
+template <typename Derived>
+bool RecursiveASTVisitor<Derived>::TraverseDeclaratorHelper(DeclaratorDecl *D) {
+ TRY_TO(TraverseNestedNameSpecifierLoc(D->getQualifierLoc()));
+ if (D->getTypeSourceInfo())
+ TRY_TO(TraverseTypeLoc(D->getTypeSourceInfo()->getTypeLoc()));
+ else
+ TRY_TO(TraverseType(D->getType()));
+ return true;
+}
+
+DEF_TRAVERSE_DECL(MSPropertyDecl, { TRY_TO(TraverseDeclaratorHelper(D)); })
+
+DEF_TRAVERSE_DECL(FieldDecl, {
+ TRY_TO(TraverseDeclaratorHelper(D));
+ if (D->isBitField())
+ TRY_TO(TraverseStmt(D->getBitWidth()));
+ else if (D->hasInClassInitializer())
+ TRY_TO(TraverseStmt(D->getInClassInitializer()));
+})
+
+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(TraverseNestedNameSpecifierLoc(D->getQualifierLoc()));
+ TRY_TO(TraverseDeclarationNameInfo(D->getNameInfo()));
+
+ // 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 ASTTemplateArgumentListInfo *TALI =
+ FTSI->TemplateArgumentsAsWritten) {
+ TRY_TO(TraverseTemplateArgumentLocsHelper(TALI->getTemplateArgs(),
+ TALI->NumTemplateArgs));
+ }
+ }
+ }
+
+ // 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.
+ if (TypeSourceInfo *TSI = D->getTypeSourceInfo()) {
+ TRY_TO(TraverseTypeLoc(TSI->getTypeLoc()));
+ } else if (getDerived().shouldVisitImplicitCode()) {
+ // Visit parameter variable declarations of the implicit function
+ // if the traverser is visiting implicit code. Parameter variable
+ // declarations do not have valid TypeSourceInfo, so to visit them
+ // we need to traverse the declarations explicitly.
+ for (FunctionDecl::param_const_iterator I = D->param_begin(),
+ E = D->param_end();
+ I != E; ++I)
+ TRY_TO(TraverseDecl(*I));
+ }
+
+ if (CXXConstructorDecl *Ctor = dyn_cast<CXXConstructorDecl>(D)) {
+ // Constructor initializers.
+ for (auto *I : Ctor->inits()) {
+ 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));
+ // Default params are taken care of when we traverse the ParmVarDecl.
+ if (!isa<ParmVarDecl>(D) &&
+ (!D->isCXXForRangeDecl() || getDerived().shouldVisitImplicitCode()))
+ 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));
+ if (D->hasDefaultArgument() && !D->defaultArgumentWasInherited())
+ 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, DataRecursionQueue *Queue) { \
+ TRY_TO(WalkUpFrom##STMT(S)); \
+ { CODE; } \
+ for (Stmt *SubStmt : S->children()) { \
+ TRY_TO_TRAVERSE_OR_ENQUEUE_STMT(SubStmt); \
+ } \
+ return true; \
+ }
+
+DEF_TRAVERSE_STMT(GCCAsmStmt, {
+ TRY_TO_TRAVERSE_OR_ENQUEUE_STMT(S->getAsmString());
+ for (unsigned I = 0, E = S->getNumInputs(); I < E; ++I) {
+ TRY_TO_TRAVERSE_OR_ENQUEUE_STMT(S->getInputConstraintLiteral(I));
+ }
+ for (unsigned I = 0, E = S->getNumOutputs(); I < E; ++I) {
+ TRY_TO_TRAVERSE_OR_ENQUEUE_STMT(S->getOutputConstraintLiteral(I));
+ }
+ for (unsigned I = 0, E = S->getNumClobbers(); I < E; ++I) {
+ TRY_TO_TRAVERSE_OR_ENQUEUE_STMT(S->getClobberStringLiteral(I));
+ }
+ // children() iterates over inputExpr and outputExpr.
+})
+
+DEF_TRAVERSE_STMT(
+ MSAsmStmt,
+ {// FIXME: MS Asm doesn't currently parse Constraints, Clobbers, etc. Once
+ // added this needs to be implemented.
+ })
+
+DEF_TRAVERSE_STMT(CXXCatchStmt, {
+ TRY_TO(TraverseDecl(S->getExceptionDecl()));
+ // children() iterates over the handler block.
+})
+
+DEF_TRAVERSE_STMT(DeclStmt, {
+ for (auto *I : S->decls()) {
+ 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(AttributedStmt, {})
+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(ObjCAutoreleasePoolStmt, {})
+DEF_TRAVERSE_STMT(CXXForRangeStmt, {
+ if (!getDerived().shouldVisitImplicitCode()) {
+ TRY_TO_TRAVERSE_OR_ENQUEUE_STMT(S->getLoopVarStmt());
+ TRY_TO_TRAVERSE_OR_ENQUEUE_STMT(S->getRangeInit());
+ TRY_TO_TRAVERSE_OR_ENQUEUE_STMT(S->getBody());
+ // Visit everything else only if shouldVisitImplicitCode().
+ return true;
+ }
+})
+DEF_TRAVERSE_STMT(MSDependentExistsStmt, {
+ TRY_TO(TraverseNestedNameSpecifierLoc(S->getQualifierLoc()));
+ TRY_TO(TraverseDeclarationNameInfo(S->getNameInfo()));
+})
+DEF_TRAVERSE_STMT(ReturnStmt, {})
+DEF_TRAVERSE_STMT(SwitchStmt, {})
+DEF_TRAVERSE_STMT(WhileStmt, {})
+
+DEF_TRAVERSE_STMT(CXXDependentScopeMemberExpr, {
+ TRY_TO(TraverseNestedNameSpecifierLoc(S->getQualifierLoc()));
+ TRY_TO(TraverseDeclarationNameInfo(S->getMemberNameInfo()));
+ if (S->hasExplicitTemplateArgs()) {
+ TRY_TO(TraverseTemplateArgumentLocsHelper(S->getTemplateArgs(),
+ S->getNumTemplateArgs()));
+ }
+})
+
+DEF_TRAVERSE_STMT(DeclRefExpr, {
+ TRY_TO(TraverseNestedNameSpecifierLoc(S->getQualifierLoc()));
+ TRY_TO(TraverseDeclarationNameInfo(S->getNameInfo()));
+ TRY_TO(TraverseTemplateArgumentLocsHelper(S->getTemplateArgs(),
+ S->getNumTemplateArgs()));
+})
+
+DEF_TRAVERSE_STMT(DependentScopeDeclRefExpr, {
+ TRY_TO(TraverseNestedNameSpecifierLoc(S->getQualifierLoc()));
+ TRY_TO(TraverseDeclarationNameInfo(S->getNameInfo()));
+ if (S->hasExplicitTemplateArgs()) {
+ TRY_TO(TraverseTemplateArgumentLocsHelper(S->getTemplateArgs(),
+ S->getNumTemplateArgs()));
+ }
+})
+
+DEF_TRAVERSE_STMT(MemberExpr, {
+ TRY_TO(TraverseNestedNameSpecifierLoc(S->getQualifierLoc()));
+ TRY_TO(TraverseDeclarationNameInfo(S->getMemberNameInfo()));
+ TRY_TO(TraverseTemplateArgumentLocsHelper(S->getTemplateArgs(),
+ S->getNumTemplateArgs()));
+})
+
+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()));
+})
+
+template <typename Derived>
+bool RecursiveASTVisitor<Derived>::TraverseSynOrSemInitListExpr(
+ InitListExpr *S, DataRecursionQueue *Queue) {
+ if (S) {
+ TRY_TO(WalkUpFromInitListExpr(S));
+ // All we need are the default actions. FIXME: use a helper function.
+ for (Stmt *SubStmt : S->children()) {
+ TRY_TO_TRAVERSE_OR_ENQUEUE_STMT(SubStmt);
+ }
+ }
+ return true;
+}
+
+// This method is called once for each pair of syntactic and semantic
+// InitListExpr, and it traverses the subtrees defined by the two forms. This
+// may cause some of the children to be visited twice, if they appear both in
+// the syntactic and the semantic form.
+//
+// There is no guarantee about which form \p S takes when this method is called.
+DEF_TRAVERSE_STMT(InitListExpr, {
+ TRY_TO(TraverseSynOrSemInitListExpr(
+ S->isSemanticForm() ? S->getSyntacticForm() : S, Queue));
+ TRY_TO(TraverseSynOrSemInitListExpr(
+ S->isSemanticForm() ? S : S->getSemanticForm(), Queue));
+ return true;
+})
+
+// GenericSelectionExpr is a special case because the types and expressions
+// are interleaved. We also need to watch out for null types (default
+// generic associations).
+DEF_TRAVERSE_STMT(GenericSelectionExpr, {
+ TRY_TO(TraverseStmt(S->getControllingExpr()));
+ for (unsigned i = 0; i != S->getNumAssocs(); ++i) {
+ if (TypeSourceInfo *TS = S->getAssocTypeSourceInfo(i))
+ TRY_TO(TraverseTypeLoc(TS->getTypeLoc()));
+ TRY_TO_TRAVERSE_OR_ENQUEUE_STMT(S->getAssocExpr(i));
+ }
+ return true;
+})
+
+// PseudoObjectExpr is a special case because of the weirdness with
+// syntactic expressions and opaque values.
+DEF_TRAVERSE_STMT(PseudoObjectExpr, {
+ TRY_TO_TRAVERSE_OR_ENQUEUE_STMT(S->getSyntacticForm());
+ for (PseudoObjectExpr::semantics_iterator i = S->semantics_begin(),
+ e = S->semantics_end();
+ i != e; ++i) {
+ Expr *sub = *i;
+ if (OpaqueValueExpr *OVE = dyn_cast<OpaqueValueExpr>(sub))
+ sub = OVE->getSourceExpr();
+ TRY_TO_TRAVERSE_OR_ENQUEUE_STMT(sub);
+ }
+ 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(UnaryExprOrTypeTraitExpr, {
+ // 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(MSPropertyRefExpr, {
+ TRY_TO(TraverseNestedNameSpecifierLoc(S->getQualifierLoc()));
+})
+
+DEF_TRAVERSE_STMT(MSPropertySubscriptExpr, {})
+
+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(TypeTraitExpr, {
+ for (unsigned I = 0, N = S->getNumArgs(); I != N; ++I)
+ TRY_TO(TraverseTypeLoc(S->getArg(I)->getTypeLoc()));
+})
+
+DEF_TRAVERSE_STMT(ArrayTypeTraitExpr, {
+ TRY_TO(TraverseTypeLoc(S->getQueriedTypeSourceInfo()->getTypeLoc()));
+})
+
+DEF_TRAVERSE_STMT(ExpressionTraitExpr,
+ { TRY_TO_TRAVERSE_OR_ENQUEUE_STMT(S->getQueriedExpression()); })
+
+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()));
+})
+
+// Walk only the visible parts of lambda expressions.
+DEF_TRAVERSE_STMT(LambdaExpr, {
+ for (LambdaExpr::capture_iterator C = S->explicit_capture_begin(),
+ CEnd = S->explicit_capture_end();
+ C != CEnd; ++C) {
+ TRY_TO(TraverseLambdaCapture(S, C));
+ }
+
+ TypeLoc TL = S->getCallOperator()->getTypeSourceInfo()->getTypeLoc();
+ FunctionProtoTypeLoc Proto = TL.castAs<FunctionProtoTypeLoc>();
+
+ if (S->hasExplicitParameters() && S->hasExplicitResultType()) {
+ // Visit the whole type.
+ TRY_TO(TraverseTypeLoc(TL));
+ } else {
+ if (S->hasExplicitParameters()) {
+ // Visit parameters.
+ for (unsigned I = 0, N = Proto.getNumParams(); I != N; ++I) {
+ TRY_TO(TraverseDecl(Proto.getParam(I)));
+ }
+ } else if (S->hasExplicitResultType()) {
+ TRY_TO(TraverseTypeLoc(Proto.getReturnLoc()));
+ }
+
+ auto *T = Proto.getTypePtr();
+ for (const auto &E : T->exceptions()) {
+ TRY_TO(TraverseType(E));
+ }
+
+ if (Expr *NE = T->getNoexceptExpr())
+ TRY_TO_TRAVERSE_OR_ENQUEUE_STMT(NE);
+ }
+
+ return TRAVERSE_STMT_BASE(LambdaBody, LambdaExpr, S, Queue);
+})
+
+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(OMPArraySectionExpr, {})
+DEF_TRAVERSE_STMT(BlockExpr, {
+ TRY_TO(TraverseDecl(S->getBlockDecl()));
+ return true; // no child statements to loop through.
+})
+DEF_TRAVERSE_STMT(ChooseExpr, {})
+DEF_TRAVERSE_STMT(CompoundLiteralExpr, {
+ TRY_TO(TraverseTypeLoc(S->getTypeSourceInfo()->getTypeLoc()));
+})
+DEF_TRAVERSE_STMT(CXXBindTemporaryExpr, {})
+DEF_TRAVERSE_STMT(CXXBoolLiteralExpr, {})
+DEF_TRAVERSE_STMT(CXXDefaultArgExpr, {})
+DEF_TRAVERSE_STMT(CXXDefaultInitExpr, {})
+DEF_TRAVERSE_STMT(CXXDeleteExpr, {})
+DEF_TRAVERSE_STMT(ExprWithCleanups, {})
+DEF_TRAVERSE_STMT(CXXNullPtrLiteralExpr, {})
+DEF_TRAVERSE_STMT(CXXStdInitializerListExpr, {})
+DEF_TRAVERSE_STMT(CXXPseudoDestructorExpr, {
+ TRY_TO(TraverseNestedNameSpecifierLoc(S->getQualifierLoc()));
+ 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(UserDefinedLiteral, {})
+DEF_TRAVERSE_STMT(DesignatedInitExpr, {})
+DEF_TRAVERSE_STMT(DesignatedInitUpdateExpr, {})
+DEF_TRAVERSE_STMT(ExtVectorElementExpr, {})
+DEF_TRAVERSE_STMT(GNUNullExpr, {})
+DEF_TRAVERSE_STMT(ImplicitValueInitExpr, {})
+DEF_TRAVERSE_STMT(NoInitExpr, {})
+DEF_TRAVERSE_STMT(ObjCBoolLiteralExpr, {})
+DEF_TRAVERSE_STMT(ObjCEncodeExpr, {
+ if (TypeSourceInfo *TInfo = S->getEncodedTypeSourceInfo())
+ TRY_TO(TraverseTypeLoc(TInfo->getTypeLoc()));
+})
+DEF_TRAVERSE_STMT(ObjCIsaExpr, {})
+DEF_TRAVERSE_STMT(ObjCIvarRefExpr, {})
+DEF_TRAVERSE_STMT(ObjCMessageExpr, {
+ if (TypeSourceInfo *TInfo = S->getClassReceiverTypeInfo())
+ TRY_TO(TraverseTypeLoc(TInfo->getTypeLoc()));
+})
+DEF_TRAVERSE_STMT(ObjCPropertyRefExpr, {})
+DEF_TRAVERSE_STMT(ObjCSubscriptRefExpr, {})
+DEF_TRAVERSE_STMT(ObjCProtocolExpr, {})
+DEF_TRAVERSE_STMT(ObjCSelectorExpr, {})
+DEF_TRAVERSE_STMT(ObjCIndirectCopyRestoreExpr, {})
+DEF_TRAVERSE_STMT(ObjCBridgedCastExpr, {
+ TRY_TO(TraverseTypeLoc(S->getTypeInfoAsWritten()->getTypeLoc()));
+})
+DEF_TRAVERSE_STMT(ParenExpr, {})
+DEF_TRAVERSE_STMT(ParenListExpr, {})
+DEF_TRAVERSE_STMT(PredefinedExpr, {})
+DEF_TRAVERSE_STMT(ShuffleVectorExpr, {})
+DEF_TRAVERSE_STMT(ConvertVectorExpr, {})
+DEF_TRAVERSE_STMT(StmtExpr, {})
+DEF_TRAVERSE_STMT(UnresolvedLookupExpr, {
+ TRY_TO(TraverseNestedNameSpecifierLoc(S->getQualifierLoc()));
+ if (S->hasExplicitTemplateArgs()) {
+ TRY_TO(TraverseTemplateArgumentLocsHelper(S->getTemplateArgs(),
+ S->getNumTemplateArgs()));
+ }
+})
+
+DEF_TRAVERSE_STMT(UnresolvedMemberExpr, {
+ TRY_TO(TraverseNestedNameSpecifierLoc(S->getQualifierLoc()));
+ if (S->hasExplicitTemplateArgs()) {
+ TRY_TO(TraverseTemplateArgumentLocsHelper(S->getTemplateArgs(),
+ S->getNumTemplateArgs()));
+ }
+})
+
+DEF_TRAVERSE_STMT(SEHTryStmt, {})
+DEF_TRAVERSE_STMT(SEHExceptStmt, {})
+DEF_TRAVERSE_STMT(SEHFinallyStmt, {})
+DEF_TRAVERSE_STMT(SEHLeaveStmt, {})
+DEF_TRAVERSE_STMT(CapturedStmt, { TRY_TO(TraverseDecl(S->getCapturedDecl())); })
+
+DEF_TRAVERSE_STMT(CXXOperatorCallExpr, {})
+DEF_TRAVERSE_STMT(OpaqueValueExpr, {})
+DEF_TRAVERSE_STMT(TypoExpr, {})
+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, {})
+DEF_TRAVERSE_STMT(SubstNonTypeTemplateParmExpr, {})
+DEF_TRAVERSE_STMT(FunctionParmPackExpr, {})
+DEF_TRAVERSE_STMT(MaterializeTemporaryExpr, {})
+DEF_TRAVERSE_STMT(CXXFoldExpr, {})
+DEF_TRAVERSE_STMT(AtomicExpr, {})
+
+// For coroutines expressions, traverse either the operand
+// as written or the implied calls, depending on what the
+// derived class requests.
+DEF_TRAVERSE_STMT(CoroutineBodyStmt, {
+ if (!getDerived().shouldVisitImplicitCode()) {
+ TRY_TO_TRAVERSE_OR_ENQUEUE_STMT(S->getBody());
+ return true;
+ }
+})
+DEF_TRAVERSE_STMT(CoreturnStmt, {
+ if (!getDerived().shouldVisitImplicitCode()) {
+ TRY_TO_TRAVERSE_OR_ENQUEUE_STMT(S->getOperand());
+ return true;
+ }
+})
+DEF_TRAVERSE_STMT(CoawaitExpr, {
+ if (!getDerived().shouldVisitImplicitCode()) {
+ TRY_TO_TRAVERSE_OR_ENQUEUE_STMT(S->getOperand());
+ return true;
+ }
+})
+DEF_TRAVERSE_STMT(CoyieldExpr, {
+ if (!getDerived().shouldVisitImplicitCode()) {
+ TRY_TO_TRAVERSE_OR_ENQUEUE_STMT(S->getOperand());
+ return true;
+ }
+})
+
+// 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, {})
+DEF_TRAVERSE_STMT(ObjCBoxedExpr, {})
+DEF_TRAVERSE_STMT(ObjCArrayLiteral, {})
+DEF_TRAVERSE_STMT(ObjCDictionaryLiteral, {})
+
+// Traverse OpenCL: AsType, Convert.
+DEF_TRAVERSE_STMT(AsTypeExpr, {})
+
+// OpenMP directives.
+template <typename Derived>
+bool RecursiveASTVisitor<Derived>::TraverseOMPExecutableDirective(
+ OMPExecutableDirective *S) {
+ for (auto *C : S->clauses()) {
+ TRY_TO(TraverseOMPClause(C));
+ }
+ return true;
+}
+
+template <typename Derived>
+bool
+RecursiveASTVisitor<Derived>::TraverseOMPLoopDirective(OMPLoopDirective *S) {
+ return TraverseOMPExecutableDirective(S);
+}
+
+DEF_TRAVERSE_STMT(OMPParallelDirective,
+ { TRY_TO(TraverseOMPExecutableDirective(S)); })
+
+DEF_TRAVERSE_STMT(OMPSimdDirective,
+ { TRY_TO(TraverseOMPExecutableDirective(S)); })
+
+DEF_TRAVERSE_STMT(OMPForDirective,
+ { TRY_TO(TraverseOMPExecutableDirective(S)); })
+
+DEF_TRAVERSE_STMT(OMPForSimdDirective,
+ { TRY_TO(TraverseOMPExecutableDirective(S)); })
+
+DEF_TRAVERSE_STMT(OMPSectionsDirective,
+ { TRY_TO(TraverseOMPExecutableDirective(S)); })
+
+DEF_TRAVERSE_STMT(OMPSectionDirective,
+ { TRY_TO(TraverseOMPExecutableDirective(S)); })
+
+DEF_TRAVERSE_STMT(OMPSingleDirective,
+ { TRY_TO(TraverseOMPExecutableDirective(S)); })
+
+DEF_TRAVERSE_STMT(OMPMasterDirective,
+ { TRY_TO(TraverseOMPExecutableDirective(S)); })
+
+DEF_TRAVERSE_STMT(OMPCriticalDirective, {
+ TRY_TO(TraverseDeclarationNameInfo(S->getDirectiveName()));
+ TRY_TO(TraverseOMPExecutableDirective(S));
+})
+
+DEF_TRAVERSE_STMT(OMPParallelForDirective,
+ { TRY_TO(TraverseOMPExecutableDirective(S)); })
+
+DEF_TRAVERSE_STMT(OMPParallelForSimdDirective,
+ { TRY_TO(TraverseOMPExecutableDirective(S)); })
+
+DEF_TRAVERSE_STMT(OMPParallelSectionsDirective,
+ { TRY_TO(TraverseOMPExecutableDirective(S)); })
+
+DEF_TRAVERSE_STMT(OMPTaskDirective,
+ { TRY_TO(TraverseOMPExecutableDirective(S)); })
+
+DEF_TRAVERSE_STMT(OMPTaskyieldDirective,
+ { TRY_TO(TraverseOMPExecutableDirective(S)); })
+
+DEF_TRAVERSE_STMT(OMPBarrierDirective,
+ { TRY_TO(TraverseOMPExecutableDirective(S)); })
+
+DEF_TRAVERSE_STMT(OMPTaskwaitDirective,
+ { TRY_TO(TraverseOMPExecutableDirective(S)); })
+
+DEF_TRAVERSE_STMT(OMPTaskgroupDirective,
+ { TRY_TO(TraverseOMPExecutableDirective(S)); })
+
+DEF_TRAVERSE_STMT(OMPCancellationPointDirective,
+ { TRY_TO(TraverseOMPExecutableDirective(S)); })
+
+DEF_TRAVERSE_STMT(OMPCancelDirective,
+ { TRY_TO(TraverseOMPExecutableDirective(S)); })
+
+DEF_TRAVERSE_STMT(OMPFlushDirective,
+ { TRY_TO(TraverseOMPExecutableDirective(S)); })
+
+DEF_TRAVERSE_STMT(OMPOrderedDirective,
+ { TRY_TO(TraverseOMPExecutableDirective(S)); })
+
+DEF_TRAVERSE_STMT(OMPAtomicDirective,
+ { TRY_TO(TraverseOMPExecutableDirective(S)); })
+
+DEF_TRAVERSE_STMT(OMPTargetDirective,
+ { TRY_TO(TraverseOMPExecutableDirective(S)); })
+
+DEF_TRAVERSE_STMT(OMPTargetDataDirective,
+ { TRY_TO(TraverseOMPExecutableDirective(S)); })
+
+DEF_TRAVERSE_STMT(OMPTeamsDirective,
+ { TRY_TO(TraverseOMPExecutableDirective(S)); })
+
+DEF_TRAVERSE_STMT(OMPTaskLoopDirective,
+ { TRY_TO(TraverseOMPExecutableDirective(S)); })
+
+DEF_TRAVERSE_STMT(OMPTaskLoopSimdDirective,
+ { TRY_TO(TraverseOMPExecutableDirective(S)); })
+
+DEF_TRAVERSE_STMT(OMPDistributeDirective,
+ { TRY_TO(TraverseOMPExecutableDirective(S)); })
+
+// OpenMP clauses.
+template <typename Derived>
+bool RecursiveASTVisitor<Derived>::TraverseOMPClause(OMPClause *C) {
+ if (!C)
+ return true;
+ switch (C->getClauseKind()) {
+#define OPENMP_CLAUSE(Name, Class) \
+ case OMPC_##Name: \
+ TRY_TO(Visit##Class(static_cast<Class *>(C))); \
+ break;
+#include "clang/Basic/OpenMPKinds.def"
+ case OMPC_threadprivate:
+ case OMPC_unknown:
+ break;
+ }
+ return true;
+}
+
+template <typename Derived>
+bool RecursiveASTVisitor<Derived>::VisitOMPIfClause(OMPIfClause *C) {
+ TRY_TO(TraverseStmt(C->getCondition()));
+ return true;
+}
+
+template <typename Derived>
+bool RecursiveASTVisitor<Derived>::VisitOMPFinalClause(OMPFinalClause *C) {
+ TRY_TO(TraverseStmt(C->getCondition()));
+ return true;
+}
+
+template <typename Derived>
+bool
+RecursiveASTVisitor<Derived>::VisitOMPNumThreadsClause(OMPNumThreadsClause *C) {
+ TRY_TO(TraverseStmt(C->getNumThreads()));
+ return true;
+}
+
+template <typename Derived>
+bool RecursiveASTVisitor<Derived>::VisitOMPSafelenClause(OMPSafelenClause *C) {
+ TRY_TO(TraverseStmt(C->getSafelen()));
+ return true;
+}
+
+template <typename Derived>
+bool RecursiveASTVisitor<Derived>::VisitOMPSimdlenClause(OMPSimdlenClause *C) {
+ TRY_TO(TraverseStmt(C->getSimdlen()));
+ return true;
+}
+
+template <typename Derived>
+bool
+RecursiveASTVisitor<Derived>::VisitOMPCollapseClause(OMPCollapseClause *C) {
+ TRY_TO(TraverseStmt(C->getNumForLoops()));
+ return true;
+}
+
+template <typename Derived>
+bool RecursiveASTVisitor<Derived>::VisitOMPDefaultClause(OMPDefaultClause *) {
+ return true;
+}
+
+template <typename Derived>
+bool RecursiveASTVisitor<Derived>::VisitOMPProcBindClause(OMPProcBindClause *) {
+ return true;
+}
+
+template <typename Derived>
+bool
+RecursiveASTVisitor<Derived>::VisitOMPScheduleClause(OMPScheduleClause *C) {
+ TRY_TO(TraverseStmt(C->getChunkSize()));
+ TRY_TO(TraverseStmt(C->getHelperChunkSize()));
+ return true;
+}
+
+template <typename Derived>
+bool RecursiveASTVisitor<Derived>::VisitOMPOrderedClause(OMPOrderedClause *C) {
+ TRY_TO(TraverseStmt(C->getNumForLoops()));
+ return true;
+}
+
+template <typename Derived>
+bool RecursiveASTVisitor<Derived>::VisitOMPNowaitClause(OMPNowaitClause *) {
+ return true;
+}
+
+template <typename Derived>
+bool RecursiveASTVisitor<Derived>::VisitOMPUntiedClause(OMPUntiedClause *) {
+ return true;
+}
+
+template <typename Derived>
+bool
+RecursiveASTVisitor<Derived>::VisitOMPMergeableClause(OMPMergeableClause *) {
+ return true;
+}
+
+template <typename Derived>
+bool RecursiveASTVisitor<Derived>::VisitOMPReadClause(OMPReadClause *) {
+ return true;
+}
+
+template <typename Derived>
+bool RecursiveASTVisitor<Derived>::VisitOMPWriteClause(OMPWriteClause *) {
+ return true;
+}
+
+template <typename Derived>
+bool RecursiveASTVisitor<Derived>::VisitOMPUpdateClause(OMPUpdateClause *) {
+ return true;
+}
+
+template <typename Derived>
+bool RecursiveASTVisitor<Derived>::VisitOMPCaptureClause(OMPCaptureClause *) {
+ return true;
+}
+
+template <typename Derived>
+bool RecursiveASTVisitor<Derived>::VisitOMPSeqCstClause(OMPSeqCstClause *) {
+ return true;
+}
+
+template <typename Derived>
+bool RecursiveASTVisitor<Derived>::VisitOMPThreadsClause(OMPThreadsClause *) {
+ return true;
+}
+
+template <typename Derived>
+bool RecursiveASTVisitor<Derived>::VisitOMPSIMDClause(OMPSIMDClause *) {
+ return true;
+}
+
+template <typename Derived>
+bool RecursiveASTVisitor<Derived>::VisitOMPNogroupClause(OMPNogroupClause *) {
+ return true;
+}
+
+template <typename Derived>
+template <typename T>
+bool RecursiveASTVisitor<Derived>::VisitOMPClauseList(T *Node) {
+ for (auto *E : Node->varlists()) {
+ TRY_TO(TraverseStmt(E));
+ }
+ return true;
+}
+
+template <typename Derived>
+bool RecursiveASTVisitor<Derived>::VisitOMPPrivateClause(OMPPrivateClause *C) {
+ TRY_TO(VisitOMPClauseList(C));
+ for (auto *E : C->private_copies()) {
+ TRY_TO(TraverseStmt(E));
+ }
+ return true;
+}
+
+template <typename Derived>
+bool RecursiveASTVisitor<Derived>::VisitOMPFirstprivateClause(
+ OMPFirstprivateClause *C) {
+ TRY_TO(VisitOMPClauseList(C));
+ for (auto *E : C->private_copies()) {
+ TRY_TO(TraverseStmt(E));
+ }
+ for (auto *E : C->inits()) {
+ TRY_TO(TraverseStmt(E));
+ }
+ return true;
+}
+
+template <typename Derived>
+bool RecursiveASTVisitor<Derived>::VisitOMPLastprivateClause(
+ OMPLastprivateClause *C) {
+ TRY_TO(VisitOMPClauseList(C));
+ for (auto *E : C->private_copies()) {
+ TRY_TO(TraverseStmt(E));
+ }
+ for (auto *E : C->source_exprs()) {
+ TRY_TO(TraverseStmt(E));
+ }
+ for (auto *E : C->destination_exprs()) {
+ TRY_TO(TraverseStmt(E));
+ }
+ for (auto *E : C->assignment_ops()) {
+ TRY_TO(TraverseStmt(E));
+ }
+ return true;
+}
+
+template <typename Derived>
+bool RecursiveASTVisitor<Derived>::VisitOMPSharedClause(OMPSharedClause *C) {
+ TRY_TO(VisitOMPClauseList(C));
+ return true;
+}
+
+template <typename Derived>
+bool RecursiveASTVisitor<Derived>::VisitOMPLinearClause(OMPLinearClause *C) {
+ TRY_TO(TraverseStmt(C->getStep()));
+ TRY_TO(TraverseStmt(C->getCalcStep()));
+ TRY_TO(VisitOMPClauseList(C));
+ for (auto *E : C->privates()) {
+ TRY_TO(TraverseStmt(E));
+ }
+ for (auto *E : C->inits()) {
+ TRY_TO(TraverseStmt(E));
+ }
+ for (auto *E : C->updates()) {
+ TRY_TO(TraverseStmt(E));
+ }
+ for (auto *E : C->finals()) {
+ TRY_TO(TraverseStmt(E));
+ }
+ return true;
+}
+
+template <typename Derived>
+bool RecursiveASTVisitor<Derived>::VisitOMPAlignedClause(OMPAlignedClause *C) {
+ TRY_TO(TraverseStmt(C->getAlignment()));
+ TRY_TO(VisitOMPClauseList(C));
+ return true;
+}
+
+template <typename Derived>
+bool RecursiveASTVisitor<Derived>::VisitOMPCopyinClause(OMPCopyinClause *C) {
+ TRY_TO(VisitOMPClauseList(C));
+ for (auto *E : C->source_exprs()) {
+ TRY_TO(TraverseStmt(E));
+ }
+ for (auto *E : C->destination_exprs()) {
+ TRY_TO(TraverseStmt(E));
+ }
+ for (auto *E : C->assignment_ops()) {
+ TRY_TO(TraverseStmt(E));
+ }
+ return true;
+}
+
+template <typename Derived>
+bool RecursiveASTVisitor<Derived>::VisitOMPCopyprivateClause(
+ OMPCopyprivateClause *C) {
+ TRY_TO(VisitOMPClauseList(C));
+ for (auto *E : C->source_exprs()) {
+ TRY_TO(TraverseStmt(E));
+ }
+ for (auto *E : C->destination_exprs()) {
+ TRY_TO(TraverseStmt(E));
+ }
+ for (auto *E : C->assignment_ops()) {
+ TRY_TO(TraverseStmt(E));
+ }
+ return true;
+}
+
+template <typename Derived>
+bool
+RecursiveASTVisitor<Derived>::VisitOMPReductionClause(OMPReductionClause *C) {
+ TRY_TO(TraverseNestedNameSpecifierLoc(C->getQualifierLoc()));
+ TRY_TO(TraverseDeclarationNameInfo(C->getNameInfo()));
+ TRY_TO(VisitOMPClauseList(C));
+ for (auto *E : C->privates()) {
+ TRY_TO(TraverseStmt(E));
+ }
+ for (auto *E : C->lhs_exprs()) {
+ TRY_TO(TraverseStmt(E));
+ }
+ for (auto *E : C->rhs_exprs()) {
+ TRY_TO(TraverseStmt(E));
+ }
+ for (auto *E : C->reduction_ops()) {
+ TRY_TO(TraverseStmt(E));
+ }
+ return true;
+}
+
+template <typename Derived>
+bool RecursiveASTVisitor<Derived>::VisitOMPFlushClause(OMPFlushClause *C) {
+ TRY_TO(VisitOMPClauseList(C));
+ return true;
+}
+
+template <typename Derived>
+bool RecursiveASTVisitor<Derived>::VisitOMPDependClause(OMPDependClause *C) {
+ TRY_TO(VisitOMPClauseList(C));
+ return true;
+}
+
+template <typename Derived>
+bool RecursiveASTVisitor<Derived>::VisitOMPDeviceClause(OMPDeviceClause *C) {
+ TRY_TO(TraverseStmt(C->getDevice()));
+ return true;
+}
+
+template <typename Derived>
+bool RecursiveASTVisitor<Derived>::VisitOMPMapClause(OMPMapClause *C) {
+ TRY_TO(VisitOMPClauseList(C));
+ return true;
+}
+
+template <typename Derived>
+bool RecursiveASTVisitor<Derived>::VisitOMPNumTeamsClause(
+ OMPNumTeamsClause *C) {
+ TRY_TO(TraverseStmt(C->getNumTeams()));
+ return true;
+}
+
+template <typename Derived>
+bool RecursiveASTVisitor<Derived>::VisitOMPThreadLimitClause(
+ OMPThreadLimitClause *C) {
+ TRY_TO(TraverseStmt(C->getThreadLimit()));
+ return true;
+}
+
+template <typename Derived>
+bool RecursiveASTVisitor<Derived>::VisitOMPPriorityClause(
+ OMPPriorityClause *C) {
+ TRY_TO(TraverseStmt(C->getPriority()));
+ return true;
+}
+
+template <typename Derived>
+bool RecursiveASTVisitor<Derived>::VisitOMPGrainsizeClause(
+ OMPGrainsizeClause *C) {
+ TRY_TO(TraverseStmt(C->getGrainsize()));
+ return true;
+}
+
+template <typename Derived>
+bool RecursiveASTVisitor<Derived>::VisitOMPNumTasksClause(
+ OMPNumTasksClause *C) {
+ TRY_TO(TraverseStmt(C->getNumTasks()));
+ return true;
+}
+
+template <typename Derived>
+bool RecursiveASTVisitor<Derived>::VisitOMPHintClause(OMPHintClause *C) {
+ TRY_TO(TraverseStmt(C->getHint()));
+ return true;
+}
+
+// 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_1UnaryExprOrTypeTraitExpr.html
+// http://clang.llvm.org/doxygen/classclang_1_1TypesCompatibleExpr.html
+// Every class that has getQualifier.
+
+#undef DEF_TRAVERSE_STMT
+#undef TRAVERSE_STMT
+#undef TRAVERSE_STMT_BASE
+
+#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..eaa22f8
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/AST/Redeclarable.h
@@ -0,0 +1,285 @@
+//===-- 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 "clang/AST/ExternalASTSource.h"
+#include "llvm/ADT/PointerIntPair.h"
+#include "llvm/Support/Casting.h"
+#include <iterator>
+
+namespace clang {
+class ASTContext;
+
+/// \brief Provides common interface for the Decls that can be redeclared.
+template<typename decl_type>
+class Redeclarable {
+protected:
+ class DeclLink {
+ /// A pointer to a known latest declaration, either statically known or
+ /// generationally updated as decls are added by an external source.
+ typedef LazyGenerationalUpdatePtr<const Decl*, Decl*,
+ &ExternalASTSource::CompleteRedeclChain>
+ KnownLatest;
+
+ /// We store a pointer to the ASTContext in the UninitializedLatest
+ /// pointer, but to avoid circular type dependencies when we steal the low
+ /// bits of this pointer, we use a raw void* here.
+ typedef const void *UninitializedLatest;
+
+ typedef Decl *Previous;
+
+ /// A pointer to either an uninitialized latest declaration (where either
+ /// we've not yet set the previous decl or there isn't one), or to a known
+ /// previous declaration.
+ typedef llvm::PointerUnion<Previous, UninitializedLatest> NotKnownLatest;
+
+ mutable llvm::PointerUnion<NotKnownLatest, KnownLatest> Next;
+
+ public:
+ enum PreviousTag { PreviousLink };
+ enum LatestTag { LatestLink };
+
+ DeclLink(LatestTag, const ASTContext &Ctx)
+ : Next(NotKnownLatest(reinterpret_cast<UninitializedLatest>(&Ctx))) {}
+ DeclLink(PreviousTag, decl_type *D)
+ : Next(NotKnownLatest(Previous(D))) {}
+
+ bool NextIsPrevious() const {
+ return Next.is<NotKnownLatest>() &&
+ // FIXME: 'template' is required on the next line due to an
+ // apparent clang bug.
+ Next.get<NotKnownLatest>().template is<Previous>();
+ }
+
+ bool NextIsLatest() const { return !NextIsPrevious(); }
+
+ decl_type *getNext(const decl_type *D) const {
+ if (Next.is<NotKnownLatest>()) {
+ NotKnownLatest NKL = Next.get<NotKnownLatest>();
+ if (NKL.is<Previous>())
+ return static_cast<decl_type*>(NKL.get<Previous>());
+
+ // Allocate the generational 'most recent' cache now, if needed.
+ Next = KnownLatest(*reinterpret_cast<const ASTContext *>(
+ NKL.get<UninitializedLatest>()),
+ const_cast<decl_type *>(D));
+ }
+
+ return static_cast<decl_type*>(Next.get<KnownLatest>().get(D));
+ }
+
+ void setPrevious(decl_type *D) {
+ assert(NextIsPrevious() && "decl became non-canonical unexpectedly");
+ Next = Previous(D);
+ }
+
+ void setLatest(decl_type *D) {
+ assert(NextIsLatest() && "decl became canonical unexpectedly");
+ if (Next.is<NotKnownLatest>()) {
+ NotKnownLatest NKL = Next.get<NotKnownLatest>();
+ Next = KnownLatest(*reinterpret_cast<const ASTContext *>(
+ NKL.get<UninitializedLatest>()),
+ D);
+ } else {
+ auto Latest = Next.get<KnownLatest>();
+ Latest.set(D);
+ Next = Latest;
+ }
+ }
+
+ void markIncomplete() { Next.get<KnownLatest>().markIncomplete(); }
+
+ Decl *getLatestNotUpdated() const {
+ assert(NextIsLatest() && "expected a canonical decl");
+ if (Next.is<NotKnownLatest>())
+ return nullptr;
+ return Next.get<KnownLatest>().getNotUpdated();
+ }
+ };
+
+ static DeclLink PreviousDeclLink(decl_type *D) {
+ return DeclLink(DeclLink::PreviousLink, D);
+ }
+
+ static DeclLink LatestDeclLink(const ASTContext &Ctx) {
+ return DeclLink(DeclLink::LatestLink, Ctx);
+ }
+
+ /// \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;
+ decl_type *First;
+
+ decl_type *getNextRedeclaration() const {
+ return RedeclLink.getNext(static_cast<const decl_type *>(this));
+ }
+
+public:
+ Redeclarable(const ASTContext &Ctx)
+ : RedeclLink(LatestDeclLink(Ctx)), First(static_cast<decl_type *>(this)) {}
+
+ /// \brief Return the previous declaration of this declaration or NULL if this
+ /// is the first declaration.
+ decl_type *getPreviousDecl() {
+ if (RedeclLink.NextIsPrevious())
+ return getNextRedeclaration();
+ return nullptr;
+ }
+ const decl_type *getPreviousDecl() const {
+ return const_cast<decl_type *>(
+ static_cast<const decl_type*>(this))->getPreviousDecl();
+ }
+
+ /// \brief Return the first declaration of this declaration or itself if this
+ /// is the only declaration.
+ decl_type *getFirstDecl() { return First; }
+
+ /// \brief Return the first declaration of this declaration or itself if this
+ /// is the only declaration.
+ const decl_type *getFirstDecl() const { return First; }
+
+ /// \brief True if this is the first declaration in its redeclaration chain.
+ bool isFirstDecl() const { return RedeclLink.NextIsLatest(); }
+
+ /// \brief Returns the most recent (re)declaration of this declaration.
+ decl_type *getMostRecentDecl() {
+ return getFirstDecl()->getNextRedeclaration();
+ }
+
+ /// \brief Returns the most recent (re)declaration of this declaration.
+ const decl_type *getMostRecentDecl() const {
+ return getFirstDecl()->getNextRedeclaration();
+ }
+
+ /// \brief Set the previous declaration. If PrevDecl is NULL, set this as the
+ /// first and only declaration.
+ void setPreviousDecl(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;
+ bool PassedFirst;
+
+ 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(nullptr) { }
+ explicit redecl_iterator(decl_type *C)
+ : Current(C), Starter(C), PassedFirst(false) { }
+
+ reference operator*() const { return Current; }
+ pointer operator->() const { return Current; }
+
+ redecl_iterator& operator++() {
+ assert(Current && "Advancing while iterator has reached end");
+ // Sanity check to avoid infinite loop on invalid redecl chain.
+ if (Current->isFirstDecl()) {
+ if (PassedFirst) {
+ assert(0 && "Passed first decl twice, invalid redecl chain!");
+ Current = nullptr;
+ return *this;
+ }
+ PassedFirst = true;
+ }
+
+ // Get either previous decl or latest decl.
+ decl_type *Next = Current->getNextRedeclaration();
+ Current = (Next != Starter) ? Next : nullptr;
+ 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;
+ }
+ };
+
+ typedef llvm::iterator_range<redecl_iterator> redecl_range;
+
+ /// \brief Returns an iterator range for all the redeclarations of the same
+ /// decl. It will iterate at least once (when this decl is the only one).
+ redecl_range redecls() const {
+ return redecl_range(redecl_iterator(const_cast<decl_type *>(
+ static_cast<const decl_type *>(this))),
+ redecl_iterator());
+ }
+
+ redecl_iterator redecls_begin() const { return redecls().begin(); }
+ redecl_iterator redecls_end() const { return redecls().end(); }
+
+ friend class ASTDeclReader;
+ friend class ASTDeclWriter;
+};
+
+/// \brief Get the primary declaration for a declaration from an AST file. That
+/// will be the first-loaded declaration.
+Decl *getPrimaryMergedDecl(Decl *D);
+
+/// \brief Provides common interface for the Decls that cannot be redeclared,
+/// but can be merged if the same declaration is brought in from multiple
+/// modules.
+template<typename decl_type>
+class Mergeable {
+public:
+ Mergeable() {}
+
+ /// \brief Return the first declaration of this declaration or itself if this
+ /// is the only declaration.
+ decl_type *getFirstDecl() {
+ decl_type *D = static_cast<decl_type*>(this);
+ if (!D->isFromASTFile())
+ return D;
+ return cast<decl_type>(getPrimaryMergedDecl(const_cast<decl_type*>(D)));
+ }
+
+ /// \brief Return the first declaration of this declaration or itself if this
+ /// is the only declaration.
+ const decl_type *getFirstDecl() const {
+ const decl_type *D = static_cast<const decl_type*>(this);
+ if (!D->isFromASTFile())
+ return D;
+ return cast<decl_type>(getPrimaryMergedDecl(const_cast<decl_type*>(D)));
+ }
+
+ /// \brief Returns true if this is the first declaration.
+ bool isFirstDecl() const { return getFirstDecl() == this; }
+};
+
+}
+
+#endif
diff --git a/contrib/llvm/tools/clang/include/clang/AST/SelectorLocationsKind.h b/contrib/llvm/tools/clang/include/clang/AST/SelectorLocationsKind.h
new file mode 100644
index 0000000..6d903f8
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/AST/SelectorLocationsKind.h
@@ -0,0 +1,83 @@
+//===--- SelectorLocationsKind.h - Kind of selector locations ---*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// Describes whether the identifier locations for a selector are "standard"
+// or not.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_AST_SELECTORLOCATIONSKIND_H
+#define LLVM_CLANG_AST_SELECTORLOCATIONSKIND_H
+
+#include "clang/Basic/LLVM.h"
+
+namespace clang {
+ class Selector;
+ class SourceLocation;
+ class Expr;
+ class ParmVarDecl;
+
+/// \brief Whether all locations of the selector identifiers are in a
+/// "standard" position.
+enum SelectorLocationsKind {
+ /// \brief Non-standard.
+ SelLoc_NonStandard = 0,
+
+ /// \brief For nullary selectors, immediately before the end:
+ /// "[foo release]" / "-(void)release;"
+ /// Or immediately before the arguments:
+ /// "[foo first:1 second:2]" / "-(id)first:(int)x second:(int)y;
+ SelLoc_StandardNoSpace = 1,
+
+ /// \brief For nullary selectors, immediately before the end:
+ /// "[foo release]" / "-(void)release;"
+ /// Or with a space between the arguments:
+ /// "[foo first: 1 second: 2]" / "-(id)first: (int)x second: (int)y;
+ SelLoc_StandardWithSpace = 2
+};
+
+/// \brief Returns true if all \p SelLocs are in a "standard" location.
+SelectorLocationsKind hasStandardSelectorLocs(Selector Sel,
+ ArrayRef<SourceLocation> SelLocs,
+ ArrayRef<Expr *> Args,
+ SourceLocation EndLoc);
+
+/// \brief Get the "standard" location of a selector identifier, e.g:
+/// For nullary selectors, immediately before ']': "[foo release]"
+///
+/// \param WithArgSpace if true the standard location is with a space apart
+/// before arguments: "[foo first: 1 second: 2]"
+/// If false: "[foo first:1 second:2]"
+SourceLocation getStandardSelectorLoc(unsigned Index,
+ Selector Sel,
+ bool WithArgSpace,
+ ArrayRef<Expr *> Args,
+ SourceLocation EndLoc);
+
+/// \brief Returns true if all \p SelLocs are in a "standard" location.
+SelectorLocationsKind hasStandardSelectorLocs(Selector Sel,
+ ArrayRef<SourceLocation> SelLocs,
+ ArrayRef<ParmVarDecl *> Args,
+ SourceLocation EndLoc);
+
+/// \brief Get the "standard" location of a selector identifier, e.g:
+/// For nullary selectors, immediately before ']': "[foo release]"
+///
+/// \param WithArgSpace if true the standard location is with a space apart
+/// before arguments: "-(id)first: (int)x second: (int)y;"
+/// If false: "-(id)first:(int)x second:(int)y;"
+SourceLocation getStandardSelectorLoc(unsigned Index,
+ Selector Sel,
+ bool WithArgSpace,
+ ArrayRef<ParmVarDecl *> Args,
+ SourceLocation EndLoc);
+
+} // end namespace clang
+
+#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..e48b7dc
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/AST/Stmt.h
@@ -0,0 +1,2196 @@
+//===--- 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 "clang/AST/DeclGroup.h"
+#include "clang/AST/StmtIterator.h"
+#include "clang/Basic/CapturedStmt.h"
+#include "clang/Basic/IdentifierTable.h"
+#include "clang/Basic/LLVM.h"
+#include "clang/Basic/SourceLocation.h"
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/PointerIntPair.h"
+#include "llvm/ADT/iterator.h"
+#include "llvm/Support/Compiler.h"
+#include "llvm/Support/ErrorHandling.h"
+#include <string>
+
+namespace llvm {
+ class FoldingSetNodeID;
+}
+
+namespace clang {
+ class ASTContext;
+ class Attr;
+ class CapturedDecl;
+ class Decl;
+ class Expr;
+ class IdentifierInfo;
+ class LabelDecl;
+ class ParmVarDecl;
+ class PrinterHelper;
+ struct PrintingPolicy;
+ class QualType;
+ class RecordDecl;
+ class SourceManager;
+ class StringLiteral;
+ class SwitchStmt;
+ class Token;
+ class VarDecl;
+
+//===----------------------------------------------------------------------===//
+// AST classes for statements.
+//===----------------------------------------------------------------------===//
+
+/// Stmt - This represents one statement.
+///
+class LLVM_ALIGNAS(LLVM_PTR_SIZE) 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) LLVM_NOEXCEPT {
+ llvm_unreachable("Stmts cannot be allocated with regular 'new'.");
+ }
+ void operator delete(void *data) LLVM_NOEXCEPT {
+ llvm_unreachable("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 ObjCArrayLiteral; // ctor
+ friend class ObjCDictionaryLiteral; // ctor
+ friend class ShuffleVectorExpr; // ctor
+ friend class ParenListExpr; // ctor
+ friend class CXXUnresolvedConstructExpr; // ctor
+ friend class CXXDependentScopeMemberExpr; // ctor
+ friend class OverloadExpr; // ctor
+ friend class PseudoObjectExpr; // ctor
+ friend class AtomicExpr; // ctor
+ unsigned : NumStmtBits;
+
+ unsigned ValueKind : 2;
+ unsigned ObjectKind : 2;
+ unsigned TypeDependent : 1;
+ unsigned ValueDependent : 1;
+ unsigned InstantiationDependent : 1;
+ unsigned ContainsUnexpandedParameterPack : 1;
+ };
+ enum { NumExprBits = 16 };
+
+ class CharacterLiteralBitfields {
+ friend class CharacterLiteral;
+ unsigned : NumExprBits;
+
+ unsigned Kind : 2;
+ };
+
+ enum APFloatSemantics {
+ IEEEhalf,
+ IEEEsingle,
+ IEEEdouble,
+ x87DoubleExtended,
+ IEEEquad,
+ PPCDoubleDouble
+ };
+
+ class FloatingLiteralBitfields {
+ friend class FloatingLiteral;
+ unsigned : NumExprBits;
+
+ unsigned Semantics : 3; // Provides semantics for APFloat construction
+ unsigned IsExact : 1;
+ };
+
+ class UnaryExprOrTypeTraitExprBitfields {
+ friend class UnaryExprOrTypeTraitExpr;
+ unsigned : NumExprBits;
+
+ unsigned Kind : 2;
+ unsigned IsType : 1; // true if operand is a type, false if an expression.
+ };
+
+ class DeclRefExprBitfields {
+ friend class DeclRefExpr;
+ friend class ASTStmtReader; // deserialization
+ unsigned : NumExprBits;
+
+ unsigned HasQualifier : 1;
+ unsigned HasTemplateKWAndArgsInfo : 1;
+ unsigned HasFoundDecl : 1;
+ unsigned HadMultipleCandidates : 1;
+ unsigned RefersToEnclosingVariableOrCapture : 1;
+ };
+
+ 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;
+ };
+
+ class ExprWithCleanupsBitfields {
+ friend class ExprWithCleanups;
+ friend class ASTStmtReader; // deserialization
+
+ unsigned : NumExprBits;
+
+ unsigned NumObjects : 32 - NumExprBits;
+ };
+
+ class PseudoObjectExprBitfields {
+ friend class PseudoObjectExpr;
+ friend class ASTStmtReader; // deserialization
+
+ unsigned : NumExprBits;
+
+ // These don't need to be particularly wide, because they're
+ // strictly limited by the forms of expressions we permit.
+ unsigned NumSubExprs : 8;
+ unsigned ResultIndex : 32 - 8 - NumExprBits;
+ };
+
+ class ObjCIndirectCopyRestoreExprBitfields {
+ friend class ObjCIndirectCopyRestoreExpr;
+ unsigned : NumExprBits;
+
+ unsigned ShouldCopy : 1;
+ };
+
+ class InitListExprBitfields {
+ friend class InitListExpr;
+
+ unsigned : NumExprBits;
+
+ /// Whether this initializer list originally had a GNU array-range
+ /// designator in it. This is a temporary marker used by CodeGen.
+ unsigned HadArrayRangeDesignator : 1;
+ };
+
+ class TypeTraitExprBitfields {
+ friend class TypeTraitExpr;
+ friend class ASTStmtReader;
+ friend class ASTStmtWriter;
+
+ unsigned : NumExprBits;
+
+ /// \brief The kind of type trait, which is a value of a TypeTrait enumerator.
+ unsigned Kind : 8;
+
+ /// \brief If this expression is not value-dependent, this indicates whether
+ /// the trait evaluated true or false.
+ unsigned Value : 1;
+
+ /// \brief The number of arguments to this type trait.
+ unsigned NumArgs : 32 - 8 - 1 - NumExprBits;
+ };
+
+ union {
+ StmtBitfields StmtBits;
+ CompoundStmtBitfields CompoundStmtBits;
+ ExprBitfields ExprBits;
+ CharacterLiteralBitfields CharacterLiteralBits;
+ FloatingLiteralBitfields FloatingLiteralBits;
+ UnaryExprOrTypeTraitExprBitfields UnaryExprOrTypeTraitExprBits;
+ DeclRefExprBitfields DeclRefExprBits;
+ CastExprBitfields CastExprBits;
+ CallExprBitfields CallExprBits;
+ ExprWithCleanupsBitfields ExprWithCleanupsBits;
+ PseudoObjectExprBitfields PseudoObjectExprBits;
+ ObjCIndirectCopyRestoreExprBitfields ObjCIndirectCopyRestoreExprBits;
+ InitListExprBitfields InitListExprBits;
+ TypeTraitExprBitfields TypeTraitExprBits;
+ };
+
+ friend class ASTStmtReader;
+ friend class ASTStmtWriter;
+
+public:
+ // Only allow allocation of Stmts using the allocator in ASTContext
+ // or by doing a placement new.
+ void* operator new(size_t bytes, const ASTContext& C,
+ unsigned alignment = 8);
+
+ void* operator new(size_t bytes, const ASTContext* C,
+ unsigned alignment = 8) {
+ return operator new(bytes, *C, alignment);
+ }
+
+ void *operator new(size_t bytes, void *mem) LLVM_NOEXCEPT { return mem; }
+
+ void operator delete(void *, const ASTContext &, unsigned) LLVM_NOEXCEPT {}
+ void operator delete(void *, const ASTContext *, unsigned) LLVM_NOEXCEPT {}
+ void operator delete(void *, size_t) LLVM_NOEXCEPT {}
+ void operator delete(void *, void *) LLVM_NOEXCEPT {}
+
+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:
+ /// Iterator 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).
+ struct ExprIterator
+ : llvm::iterator_adaptor_base<ExprIterator, Stmt **,
+ std::random_access_iterator_tag, Expr *> {
+ ExprIterator() : iterator_adaptor_base(nullptr) {}
+ ExprIterator(Stmt **I) : iterator_adaptor_base(I) {}
+
+ reference operator*() const {
+ assert((*I)->getStmtClass() >= firstExprConstant &&
+ (*I)->getStmtClass() <= lastExprConstant);
+ return *reinterpret_cast<Expr **>(I);
+ }
+ };
+
+ /// Const iterator for iterating over Stmt * arrays that contain only Expr *
+ struct ConstExprIterator
+ : llvm::iterator_adaptor_base<ConstExprIterator, const Stmt *const *,
+ std::random_access_iterator_tag,
+ const Expr *const> {
+ ConstExprIterator() : iterator_adaptor_base(nullptr) {}
+ ConstExprIterator(const Stmt *const *I) : iterator_adaptor_base(I) {}
+
+ reference operator*() const {
+ assert((*I)->getStmtClass() >= firstExprConstant &&
+ (*I)->getStmtClass() <= lastExprConstant);
+ return *reinterpret_cast<const Expr *const *>(I);
+ }
+ };
+
+private:
+ /// \brief Whether statistic collection is enabled.
+ static bool StatisticsEnabled;
+
+protected:
+ /// \brief Construct an empty statement.
+ explicit Stmt(StmtClass SC, EmptyShell) : Stmt(SC) {}
+
+public:
+ Stmt(StmtClass SC) {
+ static_assert(sizeof(*this) % llvm::AlignOf<void *>::Alignment == 0,
+ "Insufficient alignment!");
+ StmtBits.sClass = SC;
+ if (StatisticsEnabled) 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 LLVM_READONLY;
+ SourceLocation getLocStart() const LLVM_READONLY;
+ SourceLocation getLocEnd() const LLVM_READONLY;
+
+ // global temp stats (until we have a per-module visitor)
+ static void addStmtClass(const StmtClass s);
+ static void EnableStatistics();
+ static void PrintStats();
+
+ /// \brief Dumps the specified AST fragment and all subtrees to
+ /// \c llvm::errs().
+ void dump() const;
+ void dump(SourceManager &SM) const;
+ void dump(raw_ostream &OS, SourceManager &SM) const;
+ void dump(raw_ostream &OS) const;
+
+ /// dumpColor - same as dump(), but forces color highlighting.
+ void dumpColor() const;
+
+ /// dumpPretty/printPretty - These two methods do a "pretty print" of the AST
+ /// back to its original source language syntax.
+ void dumpPretty(const ASTContext &Context) const;
+ void printPretty(raw_ostream &OS, 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;
+
+ /// Skip past any implicit AST nodes which might surround this
+ /// statement, such as ExprWithCleanups or ImplicitCastExpr nodes.
+ Stmt *IgnoreImplicit();
+
+ /// \brief Skip no-op (attributed, compound) container stmts and skip captured
+ /// stmt at the top, if \a IgnoreCaptured is true.
+ Stmt *IgnoreContainers(bool IgnoreCaptured = false);
+
+ const Stmt *stripLabelLikeStatements() const;
+ Stmt *stripLabelLikeStatements() {
+ return const_cast<Stmt*>(
+ const_cast<const Stmt*>(this)->stripLabelLikeStatements());
+ }
+
+ /// 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 llvm::iterator_range<child_iterator> child_range;
+ typedef llvm::iterator_range<const_child_iterator> const_child_range;
+
+ child_range children();
+ const_child_range children() const {
+ auto Children = const_cast<Stmt *>(this)->children();
+ return const_child_range(Children.begin(), Children.end());
+ }
+
+ child_iterator child_begin() { return children().begin(); }
+ child_iterator child_end() { return children().end(); }
+
+ const_child_iterator child_begin() const { return children().begin(); }
+ const_child_iterator child_end() const { return children().end(); }
+
+ /// \brief Produce a unique representation of the given statement.
+ ///
+ /// \param ID once the profiling operation is complete, will contain
+ /// the unique representation of the given statement.
+ ///
+ /// \param Context the AST context in which the statement resides
+ ///
+ /// \param 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) const;
+};
+
+/// 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; }
+
+ SourceLocation getLocStart() const LLVM_READONLY { return StartLoc; }
+ SourceLocation getLocEnd() const LLVM_READONLY { return EndLoc; }
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == DeclStmtClass;
+ }
+
+ // 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;
+ typedef llvm::iterator_range<decl_iterator> decl_range;
+ typedef llvm::iterator_range<const_decl_iterator> decl_const_range;
+
+ decl_range decls() { return decl_range(decl_begin(), decl_end()); }
+ decl_const_range decls() const {
+ return decl_const_range(decl_begin(), decl_end());
+ }
+ 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(); }
+
+ typedef std::reverse_iterator<decl_iterator> reverse_decl_iterator;
+ reverse_decl_iterator decl_rbegin() {
+ return reverse_decl_iterator(decl_end());
+ }
+ reverse_decl_iterator decl_rend() {
+ return reverse_decl_iterator(decl_begin());
+ }
+};
+
+/// NullStmt - This is the null statement ";": C99 6.8.3p3.
+///
+class NullStmt : public Stmt {
+ SourceLocation SemiLoc;
+
+ /// \brief True if the null statement was preceded by an empty macro, e.g:
+ /// @code
+ /// #define CALL(x)
+ /// CALL(0);
+ /// @endcode
+ bool HasLeadingEmptyMacro;
+public:
+ NullStmt(SourceLocation L, bool hasLeadingEmptyMacro = false)
+ : Stmt(NullStmtClass), SemiLoc(L),
+ HasLeadingEmptyMacro(hasLeadingEmptyMacro) {}
+
+ /// \brief Build an empty null statement.
+ explicit NullStmt(EmptyShell Empty) : Stmt(NullStmtClass, Empty),
+ HasLeadingEmptyMacro(false) { }
+
+ SourceLocation getSemiLoc() const { return SemiLoc; }
+ void setSemiLoc(SourceLocation L) { SemiLoc = L; }
+
+ bool hasLeadingEmptyMacro() const { return HasLeadingEmptyMacro; }
+
+ SourceLocation getLocStart() const LLVM_READONLY { return SemiLoc; }
+ SourceLocation getLocEnd() const LLVM_READONLY { return SemiLoc; }
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == NullStmtClass;
+ }
+
+ child_range children() {
+ return child_range(child_iterator(), child_iterator());
+ }
+
+ friend class ASTStmtReader;
+ friend class ASTStmtWriter;
+};
+
+/// CompoundStmt - This represents a group of statements like { stmt stmt }.
+///
+class CompoundStmt : public Stmt {
+ Stmt** Body;
+ SourceLocation LBraceLoc, RBraceLoc;
+
+ friend class ASTStmtReader;
+
+public:
+ CompoundStmt(const ASTContext &C, ArrayRef<Stmt*> Stmts,
+ SourceLocation LB, SourceLocation RB);
+
+ // \brief Build an empty compound statement with a location.
+ explicit CompoundStmt(SourceLocation Loc)
+ : Stmt(CompoundStmtClass), Body(nullptr), LBraceLoc(Loc), RBraceLoc(Loc) {
+ CompoundStmtBits.NumStmts = 0;
+ }
+
+ // \brief Build an empty compound statement.
+ explicit CompoundStmt(EmptyShell Empty)
+ : Stmt(CompoundStmtClass, Empty), Body(nullptr) {
+ CompoundStmtBits.NumStmts = 0;
+ }
+
+ void setStmts(const ASTContext &C, ArrayRef<Stmt *> Stmts);
+
+ bool body_empty() const { return CompoundStmtBits.NumStmts == 0; }
+ unsigned size() const { return CompoundStmtBits.NumStmts; }
+
+ typedef Stmt** body_iterator;
+ typedef llvm::iterator_range<body_iterator> body_range;
+
+ body_range body() { return body_range(body_begin(), body_end()); }
+ body_iterator body_begin() { return Body; }
+ body_iterator body_end() { return Body + size(); }
+ Stmt *body_front() { return !body_empty() ? Body[0] : nullptr; }
+ Stmt *body_back() { return !body_empty() ? Body[size()-1] : nullptr; }
+
+ void setLastStmt(Stmt *S) {
+ assert(!body_empty() && "setLastStmt");
+ Body[size()-1] = S;
+ }
+
+ typedef Stmt* const * const_body_iterator;
+ typedef llvm::iterator_range<const_body_iterator> body_const_range;
+
+ body_const_range body() const {
+ return body_const_range(body_begin(), body_end());
+ }
+ const_body_iterator body_begin() const { return Body; }
+ const_body_iterator body_end() const { return Body + size(); }
+ const Stmt *body_front() const {
+ return !body_empty() ? Body[0] : nullptr;
+ }
+ const Stmt *body_back() const {
+ return !body_empty() ? Body[size() - 1] : nullptr;
+ }
+
+ 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());
+ }
+
+ SourceLocation getLocStart() const LLVM_READONLY { return LBraceLoc; }
+ SourceLocation getLocEnd() const LLVM_READONLY { return RBraceLoc; }
+
+ SourceLocation getLBracLoc() const { return LBraceLoc; }
+ SourceLocation getRBracLoc() const { return RBraceLoc; }
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == CompoundStmtClass;
+ }
+
+ // Iterators
+ child_range children() {
+ return child_range(Body, Body + CompoundStmtBits.NumStmts);
+ }
+
+ const_child_range children() const {
+ return const_child_range(child_iterator(Body),
+ child_iterator(Body + 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;
+ SourceLocation KeywordLoc;
+ SourceLocation ColonLoc;
+
+ SwitchCase(StmtClass SC, SourceLocation KWLoc, SourceLocation ColonLoc)
+ : Stmt(SC), NextSwitchCase(nullptr), KeywordLoc(KWLoc), ColonLoc(ColonLoc) {
+ }
+
+ SwitchCase(StmtClass SC, EmptyShell)
+ : Stmt(SC), NextSwitchCase(nullptr) {}
+
+public:
+ const SwitchCase *getNextSwitchCase() const { return NextSwitchCase; }
+
+ SwitchCase *getNextSwitchCase() { return NextSwitchCase; }
+
+ void setNextSwitchCase(SwitchCase *SC) { NextSwitchCase = SC; }
+
+ SourceLocation getKeywordLoc() const { return KeywordLoc; }
+ void setKeywordLoc(SourceLocation L) { KeywordLoc = L; }
+ SourceLocation getColonLoc() const { return ColonLoc; }
+ void setColonLoc(SourceLocation L) { ColonLoc = L; }
+
+ Stmt *getSubStmt();
+ const Stmt *getSubStmt() const {
+ return const_cast<SwitchCase*>(this)->getSubStmt();
+ }
+
+ SourceLocation getLocStart() const LLVM_READONLY { return KeywordLoc; }
+ SourceLocation getLocEnd() const LLVM_READONLY;
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == CaseStmtClass ||
+ T->getStmtClass() == DefaultStmtClass;
+ }
+};
+
+class CaseStmt : public SwitchCase {
+ SourceLocation EllipsisLoc;
+ enum { LHS, RHS, SUBSTMT, END_EXPR };
+ Stmt* SubExprs[END_EXPR]; // The expression for the RHS is Non-null for
+ // GNU "case 1 ... 4" extension
+public:
+ CaseStmt(Expr *lhs, Expr *rhs, SourceLocation caseLoc,
+ SourceLocation ellipsisLoc, SourceLocation colonLoc)
+ : SwitchCase(CaseStmtClass, caseLoc, colonLoc) {
+ SubExprs[SUBSTMT] = nullptr;
+ SubExprs[LHS] = reinterpret_cast<Stmt*>(lhs);
+ SubExprs[RHS] = reinterpret_cast<Stmt*>(rhs);
+ EllipsisLoc = ellipsisLoc;
+ }
+
+ /// \brief Build an empty switch case statement.
+ explicit CaseStmt(EmptyShell Empty) : SwitchCase(CaseStmtClass, Empty) { }
+
+ SourceLocation getCaseLoc() const { return KeywordLoc; }
+ void setCaseLoc(SourceLocation L) { KeywordLoc = 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); }
+
+ SourceLocation getLocStart() const LLVM_READONLY { return KeywordLoc; }
+ SourceLocation getLocEnd() const LLVM_READONLY {
+ // 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 CS->getSubStmt()->getLocEnd();
+ }
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == CaseStmtClass;
+ }
+
+ // Iterators
+ child_range children() {
+ return child_range(&SubExprs[0], &SubExprs[END_EXPR]);
+ }
+};
+
+class DefaultStmt : public SwitchCase {
+ Stmt* SubStmt;
+public:
+ DefaultStmt(SourceLocation DL, SourceLocation CL, Stmt *substmt) :
+ SwitchCase(DefaultStmtClass, DL, CL), SubStmt(substmt) {}
+
+ /// \brief Build an empty default statement.
+ explicit DefaultStmt(EmptyShell Empty)
+ : SwitchCase(DefaultStmtClass, Empty) { }
+
+ Stmt *getSubStmt() { return SubStmt; }
+ const Stmt *getSubStmt() const { return SubStmt; }
+ void setSubStmt(Stmt *S) { SubStmt = S; }
+
+ SourceLocation getDefaultLoc() const { return KeywordLoc; }
+ void setDefaultLoc(SourceLocation L) { KeywordLoc = L; }
+ SourceLocation getColonLoc() const { return ColonLoc; }
+ void setColonLoc(SourceLocation L) { ColonLoc = L; }
+
+ SourceLocation getLocStart() const LLVM_READONLY { return KeywordLoc; }
+ SourceLocation getLocEnd() const LLVM_READONLY { return SubStmt->getLocEnd();}
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == DefaultStmtClass;
+ }
+
+ // Iterators
+ child_range children() { return child_range(&SubStmt, &SubStmt+1); }
+};
+
+inline SourceLocation SwitchCase::getLocEnd() const {
+ if (const CaseStmt *CS = dyn_cast<CaseStmt>(this))
+ return CS->getLocEnd();
+ return cast<DefaultStmt>(this)->getLocEnd();
+}
+
+/// LabelStmt - Represents a label, which has a substatement. For example:
+/// foo: return;
+///
+class LabelStmt : public Stmt {
+ SourceLocation IdentLoc;
+ LabelDecl *TheDecl;
+ Stmt *SubStmt;
+
+public:
+ LabelStmt(SourceLocation IL, LabelDecl *D, Stmt *substmt)
+ : Stmt(LabelStmtClass), IdentLoc(IL), TheDecl(D), SubStmt(substmt) {
+ static_assert(sizeof(LabelStmt) ==
+ 2 * sizeof(SourceLocation) + 2 * sizeof(void *),
+ "LabelStmt too big");
+ }
+
+ // \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; }
+
+ SourceLocation getLocStart() const LLVM_READONLY { return IdentLoc; }
+ SourceLocation getLocEnd() const LLVM_READONLY { return SubStmt->getLocEnd();}
+
+ child_range children() { return child_range(&SubStmt, &SubStmt+1); }
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == LabelStmtClass;
+ }
+};
+
+
+/// \brief Represents an attribute applied to a statement.
+///
+/// Represents an attribute applied to a statement. For example:
+/// [[omp::for(...)]] for (...) { ... }
+///
+class AttributedStmt : public Stmt {
+ Stmt *SubStmt;
+ SourceLocation AttrLoc;
+ unsigned NumAttrs;
+
+ friend class ASTStmtReader;
+
+ AttributedStmt(SourceLocation Loc, ArrayRef<const Attr*> Attrs, Stmt *SubStmt)
+ : Stmt(AttributedStmtClass), SubStmt(SubStmt), AttrLoc(Loc),
+ NumAttrs(Attrs.size()) {
+ std::copy(Attrs.begin(), Attrs.end(), getAttrArrayPtr());
+ }
+
+ explicit AttributedStmt(EmptyShell Empty, unsigned NumAttrs)
+ : Stmt(AttributedStmtClass, Empty), NumAttrs(NumAttrs) {
+ std::fill_n(getAttrArrayPtr(), NumAttrs, nullptr);
+ }
+
+ const Attr *const *getAttrArrayPtr() const {
+ return reinterpret_cast<const Attr *const *>(this + 1);
+ }
+ const Attr **getAttrArrayPtr() {
+ return reinterpret_cast<const Attr **>(this + 1);
+ }
+
+public:
+ static AttributedStmt *Create(const ASTContext &C, SourceLocation Loc,
+ ArrayRef<const Attr*> Attrs, Stmt *SubStmt);
+ // \brief Build an empty attributed statement.
+ static AttributedStmt *CreateEmpty(const ASTContext &C, unsigned NumAttrs);
+
+ SourceLocation getAttrLoc() const { return AttrLoc; }
+ ArrayRef<const Attr*> getAttrs() const {
+ return llvm::makeArrayRef(getAttrArrayPtr(), NumAttrs);
+ }
+ Stmt *getSubStmt() { return SubStmt; }
+ const Stmt *getSubStmt() const { return SubStmt; }
+
+ SourceLocation getLocStart() const LLVM_READONLY { return AttrLoc; }
+ SourceLocation getLocEnd() const LLVM_READONLY { return SubStmt->getLocEnd();}
+
+ child_range children() { return child_range(&SubStmt, &SubStmt + 1); }
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == AttributedStmtClass;
+ }
+};
+
+
+/// 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(const ASTContext &C, SourceLocation IL, VarDecl *var, Expr *cond,
+ Stmt *then, SourceLocation EL = SourceLocation(),
+ Stmt *elsev = nullptr);
+
+ /// \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(const ASTContext &C, VarDecl *V);
+
+ /// If this IfStmt has a condition variable, return the faux DeclStmt
+ /// associated with the creation of that condition variable.
+ const DeclStmt *getConditionVariableDeclStmt() const {
+ return reinterpret_cast<DeclStmt*>(SubExprs[VAR]);
+ }
+
+ 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; }
+
+ SourceLocation getLocStart() const LLVM_READONLY { return IfLoc; }
+ SourceLocation getLocEnd() const LLVM_READONLY {
+ if (SubExprs[ELSE])
+ return SubExprs[ELSE]->getLocEnd();
+ else
+ return 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;
+ }
+};
+
+/// SwitchStmt - This represents a 'switch' stmt.
+///
+class SwitchStmt : public Stmt {
+ SourceLocation SwitchLoc;
+ enum { VAR, COND, BODY, END_EXPR };
+ Stmt* SubExprs[END_EXPR];
+ // This points to a linked list of case and default statements and, if the
+ // SwitchStmt is a switch on an enum value, records whether all the enum
+ // values were covered by CaseStmts. The coverage information value is meant
+ // to be a hint for possible clients.
+ llvm::PointerIntPair<SwitchCase *, 1, bool> FirstCase;
+
+public:
+ SwitchStmt(const 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(const ASTContext &C, VarDecl *V);
+
+ /// If this SwitchStmt has a condition variable, return the faux DeclStmt
+ /// associated with the creation of that condition variable.
+ const DeclStmt *getConditionVariableDeclStmt() const {
+ return reinterpret_cast<DeclStmt*>(SubExprs[VAR]);
+ }
+
+ const Expr *getCond() const { return reinterpret_cast<Expr*>(SubExprs[COND]);}
+ const Stmt *getBody() const { return SubExprs[BODY]; }
+ const SwitchCase *getSwitchCaseList() const { return FirstCase.getPointer(); }
+
+ 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.getPointer(); }
+
+ /// \brief Set the case list for this switch statement.
+ void setSwitchCaseList(SwitchCase *SC) { FirstCase.setPointer(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.getPointer());
+ FirstCase.setPointer(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() { FirstCase.setInt(true); }
+
+ /// Returns true if the SwitchStmt is a switch of an enum value and all cases
+ /// have been explicitly covered.
+ bool isAllEnumCasesCovered() const { return FirstCase.getInt(); }
+
+ SourceLocation getLocStart() const LLVM_READONLY { return SwitchLoc; }
+ SourceLocation getLocEnd() const LLVM_READONLY {
+ return SubExprs[BODY] ? SubExprs[BODY]->getLocEnd() : SubExprs[COND]->getLocEnd();
+ }
+
+ // Iterators
+ child_range children() {
+ return child_range(&SubExprs[0], &SubExprs[0]+END_EXPR);
+ }
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == SwitchStmtClass;
+ }
+};
+
+
+/// WhileStmt - This represents a 'while' stmt.
+///
+class WhileStmt : public Stmt {
+ SourceLocation WhileLoc;
+ enum { VAR, COND, BODY, END_EXPR };
+ Stmt* SubExprs[END_EXPR];
+public:
+ WhileStmt(const 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(const ASTContext &C, VarDecl *V);
+
+ /// If this WhileStmt has a condition variable, return the faux DeclStmt
+ /// associated with the creation of that condition variable.
+ const DeclStmt *getConditionVariableDeclStmt() const {
+ return reinterpret_cast<DeclStmt*>(SubExprs[VAR]);
+ }
+
+ 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; }
+
+ SourceLocation getLocStart() const LLVM_READONLY { return WhileLoc; }
+ SourceLocation getLocEnd() const LLVM_READONLY {
+ return SubExprs[BODY]->getLocEnd();
+ }
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == WhileStmtClass;
+ }
+
+ // Iterators
+ child_range children() {
+ return child_range(&SubExprs[0], &SubExprs[0]+END_EXPR);
+ }
+};
+
+/// DoStmt - This represents a 'do/while' stmt.
+///
+class DoStmt : public Stmt {
+ SourceLocation DoLoc;
+ enum { BODY, COND, END_EXPR };
+ Stmt* SubExprs[END_EXPR];
+ 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; }
+
+ SourceLocation getLocStart() const LLVM_READONLY { return DoLoc; }
+ SourceLocation getLocEnd() const LLVM_READONLY { return RParenLoc; }
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == DoStmtClass;
+ }
+
+ // 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 {
+ SourceLocation ForLoc;
+ enum { INIT, CONDVAR, COND, INC, BODY, END_EXPR };
+ Stmt* SubExprs[END_EXPR]; // SubExprs[INIT] is an expression or declstmt.
+ SourceLocation LParenLoc, RParenLoc;
+
+public:
+ ForStmt(const 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(const ASTContext &C, VarDecl *V);
+
+ /// If this ForStmt has a condition variable, return the faux DeclStmt
+ /// associated with the creation of that condition variable.
+ const DeclStmt *getConditionVariableDeclStmt() const {
+ return reinterpret_cast<DeclStmt*>(SubExprs[CONDVAR]);
+ }
+
+ 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; }
+
+ SourceLocation getLocStart() const LLVM_READONLY { return ForLoc; }
+ SourceLocation getLocEnd() const LLVM_READONLY {
+ return SubExprs[BODY]->getLocEnd();
+ }
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == ForStmtClass;
+ }
+
+ // 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; }
+
+ SourceLocation getLocStart() const LLVM_READONLY { return GotoLoc; }
+ SourceLocation getLocEnd() const LLVM_READONLY { return LabelLoc; }
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == GotoStmtClass;
+ }
+
+ // Iterators
+ child_range children() {
+ return child_range(child_iterator(), child_iterator());
+ }
+};
+
+/// 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();
+ }
+
+ SourceLocation getLocStart() const LLVM_READONLY { return GotoLoc; }
+ SourceLocation getLocEnd() const LLVM_READONLY { return Target->getLocEnd(); }
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == IndirectGotoStmtClass;
+ }
+
+ // 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; }
+
+ SourceLocation getLocStart() const LLVM_READONLY { return ContinueLoc; }
+ SourceLocation getLocEnd() const LLVM_READONLY { return ContinueLoc; }
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == ContinueStmtClass;
+ }
+
+ // Iterators
+ child_range children() {
+ return child_range(child_iterator(), child_iterator());
+ }
+};
+
+/// BreakStmt - This represents a break.
+///
+class BreakStmt : public Stmt {
+ SourceLocation BreakLoc;
+
+public:
+ BreakStmt(SourceLocation BL) : Stmt(BreakStmtClass), BreakLoc(BL) {
+ static_assert(sizeof(BreakStmt) == 2 * sizeof(SourceLocation),
+ "BreakStmt too large");
+ }
+
+ /// \brief Build an empty break statement.
+ explicit BreakStmt(EmptyShell Empty) : Stmt(BreakStmtClass, Empty) { }
+
+ SourceLocation getBreakLoc() const { return BreakLoc; }
+ void setBreakLoc(SourceLocation L) { BreakLoc = L; }
+
+ SourceLocation getLocStart() const LLVM_READONLY { return BreakLoc; }
+ SourceLocation getLocEnd() const LLVM_READONLY { return BreakLoc; }
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == BreakStmtClass;
+ }
+
+ // Iterators
+ child_range children() {
+ return child_range(child_iterator(), child_iterator());
+ }
+};
+
+
+/// 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 {
+ SourceLocation RetLoc;
+ Stmt *RetExpr;
+ const VarDecl *NRVOCandidate;
+
+public:
+ explicit ReturnStmt(SourceLocation RL) : ReturnStmt(RL, nullptr, nullptr) {}
+
+ ReturnStmt(SourceLocation RL, Expr *E, const VarDecl *NRVOCandidate)
+ : Stmt(ReturnStmtClass), RetLoc(RL), RetExpr((Stmt *)E),
+ 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; }
+
+ SourceLocation getLocStart() const LLVM_READONLY { return RetLoc; }
+ SourceLocation getLocEnd() const LLVM_READONLY {
+ return RetExpr ? RetExpr->getLocEnd() : RetLoc;
+ }
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == ReturnStmtClass;
+ }
+
+ // Iterators
+ child_range children() {
+ if (RetExpr) return child_range(&RetExpr, &RetExpr+1);
+ return child_range(child_iterator(), child_iterator());
+ }
+};
+
+/// AsmStmt is the base class for GCCAsmStmt and MSAsmStmt.
+///
+class AsmStmt : public Stmt {
+protected:
+ SourceLocation AsmLoc;
+ /// \brief True if the assembly statement does not have any input or output
+ /// operands.
+ bool IsSimple;
+
+ /// \brief If true, treat this inline assembly as having side effects.
+ /// This assembly statement should not be optimized, deleted or moved.
+ bool IsVolatile;
+
+ unsigned NumOutputs;
+ unsigned NumInputs;
+ unsigned NumClobbers;
+
+ Stmt **Exprs;
+
+ AsmStmt(StmtClass SC, SourceLocation asmloc, bool issimple, bool isvolatile,
+ unsigned numoutputs, unsigned numinputs, unsigned numclobbers) :
+ Stmt (SC), AsmLoc(asmloc), IsSimple(issimple), IsVolatile(isvolatile),
+ NumOutputs(numoutputs), NumInputs(numinputs), NumClobbers(numclobbers) { }
+
+ friend class ASTStmtReader;
+
+public:
+ /// \brief Build an empty inline-assembly statement.
+ explicit AsmStmt(StmtClass SC, EmptyShell Empty) :
+ Stmt(SC, Empty), Exprs(nullptr) { }
+
+ SourceLocation getAsmLoc() const { return AsmLoc; }
+ void setAsmLoc(SourceLocation L) { AsmLoc = L; }
+
+ bool isSimple() const { return IsSimple; }
+ void setSimple(bool V) { IsSimple = V; }
+
+ bool isVolatile() const { return IsVolatile; }
+ void setVolatile(bool V) { IsVolatile = V; }
+
+ SourceLocation getLocStart() const LLVM_READONLY { return SourceLocation(); }
+ SourceLocation getLocEnd() const LLVM_READONLY { return SourceLocation(); }
+
+ //===--- Asm String Analysis ---===//
+
+ /// Assemble final IR asm string.
+ std::string generateAsmString(const ASTContext &C) const;
+
+ //===--- Output operands ---===//
+
+ unsigned getNumOutputs() const { return NumOutputs; }
+
+ /// getOutputConstraint - Return the constraint string for the specified
+ /// output operand. All output constraints are known to be non-empty (either
+ /// '=' or '+').
+ StringRef getOutputConstraint(unsigned i) const;
+
+ /// 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] == '+';
+ }
+
+ const Expr *getOutputExpr(unsigned i) const;
+
+ /// getNumPlusOperands - Return the number of output operands that have a "+"
+ /// constraint.
+ unsigned getNumPlusOperands() const;
+
+ //===--- Input operands ---===//
+
+ unsigned getNumInputs() const { return NumInputs; }
+
+ /// getInputConstraint - Return the specified input constraint. Unlike output
+ /// constraints, these can be empty.
+ StringRef getInputConstraint(unsigned i) const;
+
+ const Expr *getInputExpr(unsigned i) const;
+
+ //===--- Other ---===//
+
+ unsigned getNumClobbers() const { return NumClobbers; }
+ StringRef getClobber(unsigned i) const;
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == GCCAsmStmtClass ||
+ T->getStmtClass() == MSAsmStmtClass;
+ }
+
+ // Input expr iterators.
+
+ typedef ExprIterator inputs_iterator;
+ typedef ConstExprIterator const_inputs_iterator;
+ typedef llvm::iterator_range<inputs_iterator> inputs_range;
+ typedef llvm::iterator_range<const_inputs_iterator> inputs_const_range;
+
+ inputs_iterator begin_inputs() {
+ return &Exprs[0] + NumOutputs;
+ }
+
+ inputs_iterator end_inputs() {
+ return &Exprs[0] + NumOutputs + NumInputs;
+ }
+
+ inputs_range inputs() { return inputs_range(begin_inputs(), end_inputs()); }
+
+ const_inputs_iterator begin_inputs() const {
+ return &Exprs[0] + NumOutputs;
+ }
+
+ const_inputs_iterator end_inputs() const {
+ return &Exprs[0] + NumOutputs + NumInputs;
+ }
+
+ inputs_const_range inputs() const {
+ return inputs_const_range(begin_inputs(), end_inputs());
+ }
+
+ // Output expr iterators.
+
+ typedef ExprIterator outputs_iterator;
+ typedef ConstExprIterator const_outputs_iterator;
+ typedef llvm::iterator_range<outputs_iterator> outputs_range;
+ typedef llvm::iterator_range<const_outputs_iterator> outputs_const_range;
+
+ outputs_iterator begin_outputs() {
+ return &Exprs[0];
+ }
+ outputs_iterator end_outputs() {
+ return &Exprs[0] + NumOutputs;
+ }
+ outputs_range outputs() {
+ return outputs_range(begin_outputs(), end_outputs());
+ }
+
+ const_outputs_iterator begin_outputs() const {
+ return &Exprs[0];
+ }
+ const_outputs_iterator end_outputs() const {
+ return &Exprs[0] + NumOutputs;
+ }
+ outputs_const_range outputs() const {
+ return outputs_const_range(begin_outputs(), end_outputs());
+ }
+
+ child_range children() {
+ return child_range(&Exprs[0], &Exprs[0] + NumOutputs + NumInputs);
+ }
+};
+
+/// This represents a GCC inline-assembly statement extension.
+///
+class GCCAsmStmt : public AsmStmt {
+ SourceLocation RParenLoc;
+ StringLiteral *AsmStr;
+
+ // FIXME: If we wanted to, we could allocate all of these in one big array.
+ StringLiteral **Constraints;
+ StringLiteral **Clobbers;
+ IdentifierInfo **Names;
+
+ friend class ASTStmtReader;
+
+public:
+ GCCAsmStmt(const ASTContext &C, SourceLocation asmloc, bool issimple,
+ bool isvolatile, 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 GCCAsmStmt(EmptyShell Empty) : AsmStmt(GCCAsmStmtClass, Empty),
+ Constraints(nullptr), Clobbers(nullptr), Names(nullptr) { }
+
+ SourceLocation getRParenLoc() const { return RParenLoc; }
+ void setRParenLoc(SourceLocation L) { RParenLoc = L; }
+
+ //===--- 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;
+
+ // Source range for operand references.
+ CharSourceRange Range;
+ public:
+ AsmStringPiece(const std::string &S) : MyKind(String), Str(S) {}
+ AsmStringPiece(unsigned OpNo, const std::string &S, SourceLocation Begin,
+ SourceLocation End)
+ : MyKind(Operand), Str(S), OperandNo(OpNo),
+ Range(CharSourceRange::getCharRange(Begin, End)) {
+ }
+
+ bool isString() const { return MyKind == String; }
+ bool isOperand() const { return MyKind == Operand; }
+
+ const std::string &getString() const {
+ return Str;
+ }
+
+ unsigned getOperandNo() const {
+ assert(isOperand());
+ return OperandNo;
+ }
+
+ CharSourceRange getRange() const {
+ assert(isOperand() && "Range is currently used only for Operands.");
+ return Range;
+ }
+
+ /// getModifier - Get the modifier for this operand, if present. This
+ /// returns '\0' if there was no modifier.
+ char getModifier() const;
+ };
+
+ /// 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(SmallVectorImpl<AsmStringPiece> &Pieces,
+ const ASTContext &C, unsigned &DiagOffs) const;
+
+ /// Assemble final IR asm string.
+ std::string generateAsmString(const ASTContext &C) const;
+
+ //===--- Output operands ---===//
+
+ IdentifierInfo *getOutputIdentifier(unsigned i) const {
+ return Names[i];
+ }
+
+ StringRef getOutputName(unsigned i) const {
+ if (IdentifierInfo *II = getOutputIdentifier(i))
+ return II->getName();
+
+ return StringRef();
+ }
+
+ 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<GCCAsmStmt*>(this)->getOutputExpr(i);
+ }
+
+ //===--- Input operands ---===//
+
+ IdentifierInfo *getInputIdentifier(unsigned i) const {
+ return Names[i + NumOutputs];
+ }
+
+ StringRef getInputName(unsigned i) const {
+ if (IdentifierInfo *II = getInputIdentifier(i))
+ return II->getName();
+
+ return StringRef();
+ }
+
+ 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);
+ void setInputExpr(unsigned i, Expr *E);
+
+ const Expr *getInputExpr(unsigned i) const {
+ return const_cast<GCCAsmStmt*>(this)->getInputExpr(i);
+ }
+
+private:
+ void setOutputsAndInputsAndClobbers(const ASTContext &C,
+ IdentifierInfo **Names,
+ StringLiteral **Constraints,
+ Stmt **Exprs,
+ unsigned NumOutputs,
+ unsigned NumInputs,
+ StringLiteral **Clobbers,
+ unsigned NumClobbers);
+public:
+
+ //===--- 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(StringRef SymbolicName) const;
+
+ StringRef getClobber(unsigned i) const;
+ StringLiteral *getClobberStringLiteral(unsigned i) { return Clobbers[i]; }
+ const StringLiteral *getClobberStringLiteral(unsigned i) const {
+ return Clobbers[i];
+ }
+
+ SourceLocation getLocStart() const LLVM_READONLY { return AsmLoc; }
+ SourceLocation getLocEnd() const LLVM_READONLY { return RParenLoc; }
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == GCCAsmStmtClass;
+ }
+};
+
+/// This represents a Microsoft inline-assembly statement extension.
+///
+class MSAsmStmt : public AsmStmt {
+ SourceLocation LBraceLoc, EndLoc;
+ StringRef AsmStr;
+
+ unsigned NumAsmToks;
+
+ Token *AsmToks;
+ StringRef *Constraints;
+ StringRef *Clobbers;
+
+ friend class ASTStmtReader;
+
+public:
+ MSAsmStmt(const ASTContext &C, SourceLocation asmloc,
+ SourceLocation lbraceloc, bool issimple, bool isvolatile,
+ ArrayRef<Token> asmtoks, unsigned numoutputs, unsigned numinputs,
+ ArrayRef<StringRef> constraints,
+ ArrayRef<Expr*> exprs, StringRef asmstr,
+ ArrayRef<StringRef> clobbers, SourceLocation endloc);
+
+ /// \brief Build an empty MS-style inline-assembly statement.
+ explicit MSAsmStmt(EmptyShell Empty) : AsmStmt(MSAsmStmtClass, Empty),
+ NumAsmToks(0), AsmToks(nullptr), Constraints(nullptr), Clobbers(nullptr) { }
+
+ SourceLocation getLBraceLoc() const { return LBraceLoc; }
+ void setLBraceLoc(SourceLocation L) { LBraceLoc = L; }
+ SourceLocation getEndLoc() const { return EndLoc; }
+ void setEndLoc(SourceLocation L) { EndLoc = L; }
+
+ bool hasBraces() const { return LBraceLoc.isValid(); }
+
+ unsigned getNumAsmToks() { return NumAsmToks; }
+ Token *getAsmToks() { return AsmToks; }
+
+ //===--- Asm String Analysis ---===//
+ StringRef getAsmString() const { return AsmStr; }
+
+ /// Assemble final IR asm string.
+ std::string generateAsmString(const ASTContext &C) const;
+
+ //===--- Output operands ---===//
+
+ StringRef getOutputConstraint(unsigned i) const {
+ assert(i < NumOutputs);
+ return Constraints[i];
+ }
+
+ Expr *getOutputExpr(unsigned i);
+
+ const Expr *getOutputExpr(unsigned i) const {
+ return const_cast<MSAsmStmt*>(this)->getOutputExpr(i);
+ }
+
+ //===--- Input operands ---===//
+
+ StringRef getInputConstraint(unsigned i) const {
+ assert(i < NumInputs);
+ return Constraints[i + NumOutputs];
+ }
+
+ Expr *getInputExpr(unsigned i);
+ void setInputExpr(unsigned i, Expr *E);
+
+ const Expr *getInputExpr(unsigned i) const {
+ return const_cast<MSAsmStmt*>(this)->getInputExpr(i);
+ }
+
+ //===--- Other ---===//
+
+ ArrayRef<StringRef> getAllConstraints() const {
+ return llvm::makeArrayRef(Constraints, NumInputs + NumOutputs);
+ }
+ ArrayRef<StringRef> getClobbers() const {
+ return llvm::makeArrayRef(Clobbers, NumClobbers);
+ }
+ ArrayRef<Expr*> getAllExprs() const {
+ return llvm::makeArrayRef(reinterpret_cast<Expr**>(Exprs),
+ NumInputs + NumOutputs);
+ }
+
+ StringRef getClobber(unsigned i) const { return getClobbers()[i]; }
+
+private:
+ void initialize(const ASTContext &C, StringRef AsmString,
+ ArrayRef<Token> AsmToks, ArrayRef<StringRef> Constraints,
+ ArrayRef<Expr*> Exprs, ArrayRef<StringRef> Clobbers);
+public:
+
+ SourceLocation getLocStart() const LLVM_READONLY { return AsmLoc; }
+ SourceLocation getLocEnd() const LLVM_READONLY { return EndLoc; }
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == MSAsmStmtClass;
+ }
+
+ child_range children() {
+ return child_range(&Exprs[0], &Exprs[NumInputs + NumOutputs]);
+ }
+};
+
+class SEHExceptStmt : public Stmt {
+ SourceLocation Loc;
+ Stmt *Children[2];
+
+ enum { FILTER_EXPR, BLOCK };
+
+ SEHExceptStmt(SourceLocation Loc,
+ Expr *FilterExpr,
+ Stmt *Block);
+
+ friend class ASTReader;
+ friend class ASTStmtReader;
+ explicit SEHExceptStmt(EmptyShell E) : Stmt(SEHExceptStmtClass, E) { }
+
+public:
+ static SEHExceptStmt* Create(const ASTContext &C,
+ SourceLocation ExceptLoc,
+ Expr *FilterExpr,
+ Stmt *Block);
+
+ SourceLocation getLocStart() const LLVM_READONLY { return getExceptLoc(); }
+ SourceLocation getLocEnd() const LLVM_READONLY { return getEndLoc(); }
+
+ SourceLocation getExceptLoc() const { return Loc; }
+ SourceLocation getEndLoc() const { return getBlock()->getLocEnd(); }
+
+ Expr *getFilterExpr() const {
+ return reinterpret_cast<Expr*>(Children[FILTER_EXPR]);
+ }
+
+ CompoundStmt *getBlock() const {
+ return cast<CompoundStmt>(Children[BLOCK]);
+ }
+
+ child_range children() {
+ return child_range(Children,Children+2);
+ }
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == SEHExceptStmtClass;
+ }
+
+};
+
+class SEHFinallyStmt : public Stmt {
+ SourceLocation Loc;
+ Stmt *Block;
+
+ SEHFinallyStmt(SourceLocation Loc,
+ Stmt *Block);
+
+ friend class ASTReader;
+ friend class ASTStmtReader;
+ explicit SEHFinallyStmt(EmptyShell E) : Stmt(SEHFinallyStmtClass, E) { }
+
+public:
+ static SEHFinallyStmt* Create(const ASTContext &C,
+ SourceLocation FinallyLoc,
+ Stmt *Block);
+
+ SourceLocation getLocStart() const LLVM_READONLY { return getFinallyLoc(); }
+ SourceLocation getLocEnd() const LLVM_READONLY { return getEndLoc(); }
+
+ SourceLocation getFinallyLoc() const { return Loc; }
+ SourceLocation getEndLoc() const { return Block->getLocEnd(); }
+
+ CompoundStmt *getBlock() const { return cast<CompoundStmt>(Block); }
+
+ child_range children() {
+ return child_range(&Block,&Block+1);
+ }
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == SEHFinallyStmtClass;
+ }
+
+};
+
+class SEHTryStmt : public Stmt {
+ bool IsCXXTry;
+ SourceLocation TryLoc;
+ Stmt *Children[2];
+
+ enum { TRY = 0, HANDLER = 1 };
+
+ SEHTryStmt(bool isCXXTry, // true if 'try' otherwise '__try'
+ SourceLocation TryLoc,
+ Stmt *TryBlock,
+ Stmt *Handler);
+
+ friend class ASTReader;
+ friend class ASTStmtReader;
+ explicit SEHTryStmt(EmptyShell E) : Stmt(SEHTryStmtClass, E) { }
+
+public:
+ static SEHTryStmt* Create(const ASTContext &C, bool isCXXTry,
+ SourceLocation TryLoc, Stmt *TryBlock,
+ Stmt *Handler);
+
+ SourceLocation getLocStart() const LLVM_READONLY { return getTryLoc(); }
+ SourceLocation getLocEnd() const LLVM_READONLY { return getEndLoc(); }
+
+ SourceLocation getTryLoc() const { return TryLoc; }
+ SourceLocation getEndLoc() const { return Children[HANDLER]->getLocEnd(); }
+
+ bool getIsCXXTry() const { return IsCXXTry; }
+
+ CompoundStmt* getTryBlock() const {
+ return cast<CompoundStmt>(Children[TRY]);
+ }
+
+ Stmt *getHandler() const { return Children[HANDLER]; }
+
+ /// Returns 0 if not defined
+ SEHExceptStmt *getExceptHandler() const;
+ SEHFinallyStmt *getFinallyHandler() const;
+
+ child_range children() {
+ return child_range(Children,Children+2);
+ }
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == SEHTryStmtClass;
+ }
+};
+
+/// Represents a __leave statement.
+///
+class SEHLeaveStmt : public Stmt {
+ SourceLocation LeaveLoc;
+public:
+ explicit SEHLeaveStmt(SourceLocation LL)
+ : Stmt(SEHLeaveStmtClass), LeaveLoc(LL) {}
+
+ /// \brief Build an empty __leave statement.
+ explicit SEHLeaveStmt(EmptyShell Empty) : Stmt(SEHLeaveStmtClass, Empty) { }
+
+ SourceLocation getLeaveLoc() const { return LeaveLoc; }
+ void setLeaveLoc(SourceLocation L) { LeaveLoc = L; }
+
+ SourceLocation getLocStart() const LLVM_READONLY { return LeaveLoc; }
+ SourceLocation getLocEnd() const LLVM_READONLY { return LeaveLoc; }
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == SEHLeaveStmtClass;
+ }
+
+ // Iterators
+ child_range children() {
+ return child_range(child_iterator(), child_iterator());
+ }
+};
+
+/// \brief This captures a statement into a function. For example, the following
+/// pragma annotated compound statement can be represented as a CapturedStmt,
+/// and this compound statement is the body of an anonymous outlined function.
+/// @code
+/// #pragma omp parallel
+/// {
+/// compute();
+/// }
+/// @endcode
+class CapturedStmt : public Stmt {
+public:
+ /// \brief The different capture forms: by 'this', by reference, capture for
+ /// variable-length array type etc.
+ enum VariableCaptureKind {
+ VCK_This,
+ VCK_ByRef,
+ VCK_ByCopy,
+ VCK_VLAType,
+ };
+
+ /// \brief Describes the capture of either a variable, or 'this', or
+ /// variable-length array type.
+ class Capture {
+ llvm::PointerIntPair<VarDecl *, 2, VariableCaptureKind> VarAndKind;
+ SourceLocation Loc;
+
+ public:
+ /// \brief Create a new capture.
+ ///
+ /// \param Loc The source location associated with this capture.
+ ///
+ /// \param Kind The kind of capture (this, ByRef, ...).
+ ///
+ /// \param Var The variable being captured, or null if capturing this.
+ ///
+ Capture(SourceLocation Loc, VariableCaptureKind Kind,
+ VarDecl *Var = nullptr);
+
+ /// \brief Determine the kind of capture.
+ VariableCaptureKind getCaptureKind() const;
+
+ /// \brief Retrieve the source location at which the variable or 'this' was
+ /// first used.
+ SourceLocation getLocation() const { return Loc; }
+
+ /// \brief Determine whether this capture handles the C++ 'this' pointer.
+ bool capturesThis() const { return getCaptureKind() == VCK_This; }
+
+ /// \brief Determine whether this capture handles a variable (by reference).
+ bool capturesVariable() const { return getCaptureKind() == VCK_ByRef; }
+
+ /// \brief Determine whether this capture handles a variable by copy.
+ bool capturesVariableByCopy() const {
+ return getCaptureKind() == VCK_ByCopy;
+ }
+
+ /// \brief Determine whether this capture handles a variable-length array
+ /// type.
+ bool capturesVariableArrayType() const {
+ return getCaptureKind() == VCK_VLAType;
+ }
+
+ /// \brief Retrieve the declaration of the variable being captured.
+ ///
+ /// This operation is only valid if this capture captures a variable.
+ VarDecl *getCapturedVar() const;
+
+ friend class ASTStmtReader;
+ };
+
+private:
+ /// \brief The number of variable captured, including 'this'.
+ unsigned NumCaptures;
+
+ /// \brief The pointer part is the implicit the outlined function and the
+ /// int part is the captured region kind, 'CR_Default' etc.
+ llvm::PointerIntPair<CapturedDecl *, 1, CapturedRegionKind> CapDeclAndKind;
+
+ /// \brief The record for captured variables, a RecordDecl or CXXRecordDecl.
+ RecordDecl *TheRecordDecl;
+
+ /// \brief Construct a captured statement.
+ CapturedStmt(Stmt *S, CapturedRegionKind Kind, ArrayRef<Capture> Captures,
+ ArrayRef<Expr *> CaptureInits, CapturedDecl *CD, RecordDecl *RD);
+
+ /// \brief Construct an empty captured statement.
+ CapturedStmt(EmptyShell Empty, unsigned NumCaptures);
+
+ Stmt **getStoredStmts() { return reinterpret_cast<Stmt **>(this + 1); }
+
+ Stmt *const *getStoredStmts() const {
+ return reinterpret_cast<Stmt *const *>(this + 1);
+ }
+
+ Capture *getStoredCaptures() const;
+
+ void setCapturedStmt(Stmt *S) { getStoredStmts()[NumCaptures] = S; }
+
+public:
+ static CapturedStmt *Create(const ASTContext &Context, Stmt *S,
+ CapturedRegionKind Kind,
+ ArrayRef<Capture> Captures,
+ ArrayRef<Expr *> CaptureInits,
+ CapturedDecl *CD, RecordDecl *RD);
+
+ static CapturedStmt *CreateDeserialized(const ASTContext &Context,
+ unsigned NumCaptures);
+
+ /// \brief Retrieve the statement being captured.
+ Stmt *getCapturedStmt() { return getStoredStmts()[NumCaptures]; }
+ const Stmt *getCapturedStmt() const { return getStoredStmts()[NumCaptures]; }
+
+ /// \brief Retrieve the outlined function declaration.
+ CapturedDecl *getCapturedDecl();
+ const CapturedDecl *getCapturedDecl() const;
+
+ /// \brief Set the outlined function declaration.
+ void setCapturedDecl(CapturedDecl *D);
+
+ /// \brief Retrieve the captured region kind.
+ CapturedRegionKind getCapturedRegionKind() const;
+
+ /// \brief Set the captured region kind.
+ void setCapturedRegionKind(CapturedRegionKind Kind);
+
+ /// \brief Retrieve the record declaration for captured variables.
+ const RecordDecl *getCapturedRecordDecl() const { return TheRecordDecl; }
+
+ /// \brief Set the record declaration for captured variables.
+ void setCapturedRecordDecl(RecordDecl *D) {
+ assert(D && "null RecordDecl");
+ TheRecordDecl = D;
+ }
+
+ /// \brief True if this variable has been captured.
+ bool capturesVariable(const VarDecl *Var) const;
+
+ /// \brief An iterator that walks over the captures.
+ typedef Capture *capture_iterator;
+ typedef const Capture *const_capture_iterator;
+ typedef llvm::iterator_range<capture_iterator> capture_range;
+ typedef llvm::iterator_range<const_capture_iterator> capture_const_range;
+
+ capture_range captures() {
+ return capture_range(capture_begin(), capture_end());
+ }
+ capture_const_range captures() const {
+ return capture_const_range(capture_begin(), capture_end());
+ }
+
+ /// \brief Retrieve an iterator pointing to the first capture.
+ capture_iterator capture_begin() { return getStoredCaptures(); }
+ const_capture_iterator capture_begin() const { return getStoredCaptures(); }
+
+ /// \brief Retrieve an iterator pointing past the end of the sequence of
+ /// captures.
+ capture_iterator capture_end() const {
+ return getStoredCaptures() + NumCaptures;
+ }
+
+ /// \brief Retrieve the number of captures, including 'this'.
+ unsigned capture_size() const { return NumCaptures; }
+
+ /// \brief Iterator that walks over the capture initialization arguments.
+ typedef Expr **capture_init_iterator;
+ typedef llvm::iterator_range<capture_init_iterator> capture_init_range;
+
+ /// \brief Const iterator that walks over the capture initialization
+ /// arguments.
+ typedef Expr *const *const_capture_init_iterator;
+ typedef llvm::iterator_range<const_capture_init_iterator>
+ const_capture_init_range;
+
+ capture_init_range capture_inits() {
+ return capture_init_range(capture_init_begin(), capture_init_end());
+ }
+
+ const_capture_init_range capture_inits() const {
+ return const_capture_init_range(capture_init_begin(), capture_init_end());
+ }
+
+ /// \brief Retrieve the first initialization argument.
+ capture_init_iterator capture_init_begin() {
+ return reinterpret_cast<Expr **>(getStoredStmts());
+ }
+
+ const_capture_init_iterator capture_init_begin() const {
+ return reinterpret_cast<Expr *const *>(getStoredStmts());
+ }
+
+ /// \brief Retrieve the iterator pointing one past the last initialization
+ /// argument.
+ capture_init_iterator capture_init_end() {
+ return capture_init_begin() + NumCaptures;
+ }
+
+ const_capture_init_iterator capture_init_end() const {
+ return capture_init_begin() + NumCaptures;
+ }
+
+ SourceLocation getLocStart() const LLVM_READONLY {
+ return getCapturedStmt()->getLocStart();
+ }
+ SourceLocation getLocEnd() const LLVM_READONLY {
+ return getCapturedStmt()->getLocEnd();
+ }
+ SourceRange getSourceRange() const LLVM_READONLY {
+ return getCapturedStmt()->getSourceRange();
+ }
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == CapturedStmtClass;
+ }
+
+ child_range children();
+
+ friend class ASTStmtReader;
+};
+
+} // 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..1ca73e2
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/AST/StmtCXX.h
@@ -0,0 +1,417 @@
+//===--- 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/DeclarationName.h"
+#include "clang/AST/Expr.h"
+#include "clang/AST/NestedNameSpecifier.h"
+#include "clang/AST/Stmt.h"
+#include "llvm/Support/Compiler.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(nullptr), HandlerBlock(nullptr) {}
+
+ SourceLocation getLocStart() const LLVM_READONLY { return CatchLoc; }
+ SourceLocation getLocEnd() const LLVM_READONLY {
+ return 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;
+ }
+
+ 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, ArrayRef<Stmt*> handlers);
+
+ 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(const ASTContext &C, SourceLocation tryLoc,
+ Stmt *tryBlock, ArrayRef<Stmt*> handlers);
+
+ static CXXTryStmt *Create(const ASTContext &C, EmptyShell Empty,
+ unsigned numHandlers);
+
+ SourceLocation getLocStart() const LLVM_READONLY { return getTryLoc(); }
+ SourceLocation getLocEnd() const LLVM_READONLY { return getEndLoc(); }
+
+ SourceLocation getTryLoc() const { return TryLoc; }
+ SourceLocation getEndLoc() const {
+ return getStmts()[NumHandlers]->getLocEnd();
+ }
+
+ CompoundStmt *getTryBlock() {
+ return cast<CompoundStmt>(getStmts()[0]);
+ }
+ const CompoundStmt *getTryBlock() const {
+ return cast<CompoundStmt>(getStmts()[0]);
+ }
+
+ unsigned getNumHandlers() const { return NumHandlers; }
+ CXXCatchStmt *getHandler(unsigned i) {
+ return cast<CXXCatchStmt>(getStmts()[i + 1]);
+ }
+ const CXXCatchStmt *getHandler(unsigned i) const {
+ return cast<CXXCatchStmt>(getStmts()[i + 1]);
+ }
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == CXXTryStmtClass;
+ }
+
+ child_range children() {
+ return child_range(getStmts(), getStmts() + getNumHandlers() + 1);
+ }
+
+ friend class ASTStmtReader;
+};
+
+/// CXXForRangeStmt - This represents C++0x [stmt.ranged]'s ranged for
+/// statement, represented as 'for (range-declarator : range-expression)'.
+///
+/// This is stored in a partially-desugared form to allow full semantic
+/// analysis of the constituent components. The original syntactic components
+/// can be extracted using getLoopVariable and getRangeInit.
+class CXXForRangeStmt : public Stmt {
+ SourceLocation ForLoc;
+ enum { RANGE, BEGINEND, COND, INC, LOOPVAR, BODY, END };
+ // SubExprs[RANGE] is an expression or declstmt.
+ // SubExprs[COND] and SubExprs[INC] are expressions.
+ Stmt *SubExprs[END];
+ SourceLocation CoawaitLoc;
+ SourceLocation ColonLoc;
+ SourceLocation RParenLoc;
+
+ friend class ASTStmtReader;
+public:
+ CXXForRangeStmt(DeclStmt *Range, DeclStmt *BeginEnd,
+ Expr *Cond, Expr *Inc, DeclStmt *LoopVar, Stmt *Body,
+ SourceLocation FL, SourceLocation CAL, SourceLocation CL,
+ SourceLocation RPL);
+ CXXForRangeStmt(EmptyShell Empty) : Stmt(CXXForRangeStmtClass, Empty) { }
+
+
+ VarDecl *getLoopVariable();
+ Expr *getRangeInit();
+
+ const VarDecl *getLoopVariable() const;
+ const Expr *getRangeInit() const;
+
+
+ DeclStmt *getRangeStmt() { return cast<DeclStmt>(SubExprs[RANGE]); }
+ DeclStmt *getBeginEndStmt() {
+ return cast_or_null<DeclStmt>(SubExprs[BEGINEND]);
+ }
+ Expr *getCond() { return cast_or_null<Expr>(SubExprs[COND]); }
+ Expr *getInc() { return cast_or_null<Expr>(SubExprs[INC]); }
+ DeclStmt *getLoopVarStmt() { return cast<DeclStmt>(SubExprs[LOOPVAR]); }
+ Stmt *getBody() { return SubExprs[BODY]; }
+
+ const DeclStmt *getRangeStmt() const {
+ return cast<DeclStmt>(SubExprs[RANGE]);
+ }
+ const DeclStmt *getBeginEndStmt() const {
+ return cast_or_null<DeclStmt>(SubExprs[BEGINEND]);
+ }
+ const Expr *getCond() const {
+ return cast_or_null<Expr>(SubExprs[COND]);
+ }
+ const Expr *getInc() const {
+ return cast_or_null<Expr>(SubExprs[INC]);
+ }
+ const DeclStmt *getLoopVarStmt() const {
+ return cast<DeclStmt>(SubExprs[LOOPVAR]);
+ }
+ const Stmt *getBody() const { return SubExprs[BODY]; }
+
+ void setRangeInit(Expr *E) { SubExprs[RANGE] = reinterpret_cast<Stmt*>(E); }
+ void setRangeStmt(Stmt *S) { SubExprs[RANGE] = S; }
+ void setBeginEndStmt(Stmt *S) { SubExprs[BEGINEND] = S; }
+ void setCond(Expr *E) { SubExprs[COND] = reinterpret_cast<Stmt*>(E); }
+ void setInc(Expr *E) { SubExprs[INC] = reinterpret_cast<Stmt*>(E); }
+ void setLoopVarStmt(Stmt *S) { SubExprs[LOOPVAR] = S; }
+ void setBody(Stmt *S) { SubExprs[BODY] = S; }
+
+ SourceLocation getForLoc() const { return ForLoc; }
+ SourceLocation getCoawaitLoc() const { return CoawaitLoc; }
+ SourceLocation getColonLoc() const { return ColonLoc; }
+ SourceLocation getRParenLoc() const { return RParenLoc; }
+
+ SourceLocation getLocStart() const LLVM_READONLY { return ForLoc; }
+ SourceLocation getLocEnd() const LLVM_READONLY {
+ return SubExprs[BODY]->getLocEnd();
+ }
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == CXXForRangeStmtClass;
+ }
+
+ // Iterators
+ child_range children() {
+ return child_range(&SubExprs[0], &SubExprs[END]);
+ }
+};
+
+/// \brief Representation of a Microsoft __if_exists or __if_not_exists
+/// statement with a dependent name.
+///
+/// The __if_exists statement can be used to include a sequence of statements
+/// in the program only when a particular dependent name does not exist. For
+/// example:
+///
+/// \code
+/// template<typename T>
+/// void call_foo(T &t) {
+/// __if_exists (T::foo) {
+/// t.foo(); // okay: only called when T::foo exists.
+/// }
+/// }
+/// \endcode
+///
+/// Similarly, the __if_not_exists statement can be used to include the
+/// statements when a particular name does not exist.
+///
+/// Note that this statement only captures __if_exists and __if_not_exists
+/// statements whose name is dependent. All non-dependent cases are handled
+/// directly in the parser, so that they don't introduce a new scope. Clang
+/// introduces scopes in the dependent case to keep names inside the compound
+/// statement from leaking out into the surround statements, which would
+/// compromise the template instantiation model. This behavior differs from
+/// Visual C++ (which never introduces a scope), but is a fairly reasonable
+/// approximation of the VC++ behavior.
+class MSDependentExistsStmt : public Stmt {
+ SourceLocation KeywordLoc;
+ bool IsIfExists;
+ NestedNameSpecifierLoc QualifierLoc;
+ DeclarationNameInfo NameInfo;
+ Stmt *SubStmt;
+
+ friend class ASTReader;
+ friend class ASTStmtReader;
+
+public:
+ MSDependentExistsStmt(SourceLocation KeywordLoc, bool IsIfExists,
+ NestedNameSpecifierLoc QualifierLoc,
+ DeclarationNameInfo NameInfo,
+ CompoundStmt *SubStmt)
+ : Stmt(MSDependentExistsStmtClass),
+ KeywordLoc(KeywordLoc), IsIfExists(IsIfExists),
+ QualifierLoc(QualifierLoc), NameInfo(NameInfo),
+ SubStmt(reinterpret_cast<Stmt *>(SubStmt)) { }
+
+ /// \brief Retrieve the location of the __if_exists or __if_not_exists
+ /// keyword.
+ SourceLocation getKeywordLoc() const { return KeywordLoc; }
+
+ /// \brief Determine whether this is an __if_exists statement.
+ bool isIfExists() const { return IsIfExists; }
+
+ /// \brief Determine whether this is an __if_exists statement.
+ bool isIfNotExists() const { return !IsIfExists; }
+
+ /// \brief Retrieve the nested-name-specifier that qualifies this name, if
+ /// any.
+ NestedNameSpecifierLoc getQualifierLoc() const { return QualifierLoc; }
+
+ /// \brief Retrieve the name of the entity we're testing for, along with
+ /// location information
+ DeclarationNameInfo getNameInfo() const { return NameInfo; }
+
+ /// \brief Retrieve the compound statement that will be included in the
+ /// program only if the existence of the symbol matches the initial keyword.
+ CompoundStmt *getSubStmt() const {
+ return reinterpret_cast<CompoundStmt *>(SubStmt);
+ }
+
+ SourceLocation getLocStart() const LLVM_READONLY { return KeywordLoc; }
+ SourceLocation getLocEnd() const LLVM_READONLY { return SubStmt->getLocEnd();}
+
+ child_range children() {
+ return child_range(&SubStmt, &SubStmt+1);
+ }
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == MSDependentExistsStmtClass;
+ }
+};
+
+/// \brief Represents the body of a coroutine. This wraps the normal function
+/// body and holds the additional semantic context required to set up and tear
+/// down the coroutine frame.
+class CoroutineBodyStmt : public Stmt {
+ enum SubStmt {
+ Body, ///< The body of the coroutine.
+ Promise, ///< The promise statement.
+ InitSuspend, ///< The initial suspend statement, run before the body.
+ FinalSuspend, ///< The final suspend statement, run after the body.
+ OnException, ///< Handler for exceptions thrown in the body.
+ OnFallthrough, ///< Handler for control flow falling off the body.
+ ReturnValue, ///< Return value for thunk function.
+ FirstParamMove ///< First offset for move construction of parameter copies.
+ };
+ Stmt *SubStmts[SubStmt::FirstParamMove];
+
+ friend class ASTStmtReader;
+public:
+ CoroutineBodyStmt(Stmt *Body, Stmt *Promise, Stmt *InitSuspend,
+ Stmt *FinalSuspend, Stmt *OnException, Stmt *OnFallthrough,
+ Expr *ReturnValue, ArrayRef<Expr *> ParamMoves)
+ : Stmt(CoroutineBodyStmtClass) {
+ SubStmts[CoroutineBodyStmt::Body] = Body;
+ SubStmts[CoroutineBodyStmt::Promise] = Promise;
+ SubStmts[CoroutineBodyStmt::InitSuspend] = InitSuspend;
+ SubStmts[CoroutineBodyStmt::FinalSuspend] = FinalSuspend;
+ SubStmts[CoroutineBodyStmt::OnException] = OnException;
+ SubStmts[CoroutineBodyStmt::OnFallthrough] = OnFallthrough;
+ SubStmts[CoroutineBodyStmt::ReturnValue] = ReturnValue;
+ // FIXME: Tail-allocate space for parameter move expressions and store them.
+ assert(ParamMoves.empty() && "not implemented yet");
+ }
+
+ /// \brief Retrieve the body of the coroutine as written. This will be either
+ /// a CompoundStmt or a TryStmt.
+ Stmt *getBody() const {
+ return SubStmts[SubStmt::Body];
+ }
+
+ Stmt *getPromiseDeclStmt() const { return SubStmts[SubStmt::Promise]; }
+ VarDecl *getPromiseDecl() const {
+ return cast<VarDecl>(cast<DeclStmt>(getPromiseDeclStmt())->getSingleDecl());
+ }
+
+ Stmt *getInitSuspendStmt() const { return SubStmts[SubStmt::InitSuspend]; }
+ Stmt *getFinalSuspendStmt() const { return SubStmts[SubStmt::FinalSuspend]; }
+
+ Stmt *getExceptionHandler() const { return SubStmts[SubStmt::OnException]; }
+ Stmt *getFallthroughHandler() const {
+ return SubStmts[SubStmt::OnFallthrough];
+ }
+
+ Expr *getReturnValueInit() const {
+ return cast<Expr>(SubStmts[SubStmt::ReturnValue]);
+ }
+
+ SourceLocation getLocStart() const LLVM_READONLY {
+ return getBody()->getLocStart();
+ }
+ SourceLocation getLocEnd() const LLVM_READONLY {
+ return getBody()->getLocEnd();
+ }
+
+ child_range children() {
+ return child_range(SubStmts, SubStmts + SubStmt::FirstParamMove);
+ }
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == CoroutineBodyStmtClass;
+ }
+};
+
+/// \brief Represents a 'co_return' statement in the C++ Coroutines TS.
+///
+/// This statament models the initialization of the coroutine promise
+/// (encapsulating the eventual notional return value) from an expression
+/// (or braced-init-list), followed by termination of the coroutine.
+///
+/// This initialization is modeled by the evaluation of the operand
+/// followed by a call to one of:
+/// <promise>.return_value(<operand>)
+/// <promise>.return_void()
+/// which we name the "promise call".
+class CoreturnStmt : public Stmt {
+ SourceLocation CoreturnLoc;
+
+ enum SubStmt { Operand, PromiseCall, Count };
+ Stmt *SubStmts[SubStmt::Count];
+
+ friend class ASTStmtReader;
+public:
+ CoreturnStmt(SourceLocation CoreturnLoc, Stmt *Operand, Stmt *PromiseCall)
+ : Stmt(CoreturnStmtClass), CoreturnLoc(CoreturnLoc) {
+ SubStmts[SubStmt::Operand] = Operand;
+ SubStmts[SubStmt::PromiseCall] = PromiseCall;
+ }
+
+ SourceLocation getKeywordLoc() const { return CoreturnLoc; }
+
+ /// \brief Retrieve the operand of the 'co_return' statement. Will be nullptr
+ /// if none was specified.
+ Expr *getOperand() const { return static_cast<Expr*>(SubStmts[Operand]); }
+
+ /// \brief Retrieve the promise call that results from this 'co_return'
+ /// statement. Will be nullptr if either the coroutine has not yet been
+ /// finalized or the coroutine has no eventual return type.
+ Expr *getPromiseCall() const {
+ return static_cast<Expr*>(SubStmts[PromiseCall]);
+ }
+
+ SourceLocation getLocStart() const LLVM_READONLY { return CoreturnLoc; }
+ SourceLocation getLocEnd() const LLVM_READONLY {
+ return getOperand()->getLocEnd();
+ }
+
+ child_range children() {
+ return child_range(SubStmts, SubStmts + SubStmt::Count);
+ }
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == CoreturnStmtClass;
+ }
+};
+
+} // 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..ab636a5
--- /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_STMTGRAPHTRAITS_H
+#define LLVM_CLANG_AST_STMTGRAPHTRAITS_H
+
+#include "clang/AST/Stmt.h"
+#include "llvm/ADT/DepthFirstIterator.h"
+#include "llvm/ADT/GraphTraits.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..81f8ad43
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/AST/StmtIterator.h
@@ -0,0 +1,144 @@
+//===--- 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_STMTITERATOR_H
+#define LLVM_CLANG_AST_STMTITERATOR_H
+
+#include "llvm/Support/Compiler.h"
+#include "llvm/Support/DataTypes.h"
+#include <cassert>
+#include <cstddef>
+#include <iterator>
+#include <utility>
+
+namespace clang {
+
+class Stmt;
+class Decl;
+class VariableArrayType;
+
+class StmtIteratorBase {
+protected:
+ enum { StmtMode = 0x0, SizeOfTypeVAMode = 0x1, DeclGroupMode = 0x2,
+ Flags = 0x3 };
+
+ union {
+ Stmt **stmt;
+ Decl **DGI;
+ };
+ uintptr_t RawVAPtr;
+ Decl **DGE;
+
+ bool inDeclGroup() const {
+ return (RawVAPtr & Flags) == DeclGroupMode;
+ }
+
+ bool inSizeOfTypeVA() const {
+ return (RawVAPtr & Flags) == SizeOfTypeVAMode;
+ }
+
+ bool inStmt() const {
+ return (RawVAPtr & Flags) == StmtMode;
+ }
+
+ const VariableArrayType *getVAPtr() const {
+ return reinterpret_cast<const VariableArrayType*>(RawVAPtr & ~Flags);
+ }
+
+ void setVAPtr(const VariableArrayType *P) {
+ assert (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), RawVAPtr(0) {}
+ StmtIteratorBase(const VariableArrayType *t);
+ StmtIteratorBase(Decl **dgi, Decl **dge);
+ StmtIteratorBase() : stmt(nullptr), 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(const VariableArrayType *t) : StmtIteratorBase(t) {}
+
+ DERIVED& operator++() {
+ if (inStmt())
+ ++stmt;
+ else if (getVAPtr())
+ NextVA();
+ else
+ NextDecl();
+
+ 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 && DGI == RHS.DGI && RawVAPtr == RHS.RawVAPtr;
+ }
+
+ bool operator!=(const DERIVED& RHS) const {
+ return stmt != RHS.stmt || DGI != RHS.DGI || RawVAPtr != RHS.RawVAPtr;
+ }
+
+ REFERENCE operator*() const {
+ return 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) {}
+};
+
+struct ConstStmtIterator : public StmtIteratorImpl<ConstStmtIterator,
+ const Stmt*> {
+ explicit ConstStmtIterator() :
+ StmtIteratorImpl<ConstStmtIterator,const Stmt*>() {}
+
+ ConstStmtIterator(const StmtIterator& RHS) :
+ StmtIteratorImpl<ConstStmtIterator,const Stmt*>(RHS) {}
+};
+
+} // 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..68fe3ef
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/AST/StmtObjC.h
@@ -0,0 +1,375 @@
+//===--- 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.
+//
+//===----------------------------------------------------------------------===//
+
+/// \file
+/// \brief 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"
+#include "llvm/Support/Compiler.h"
+
+namespace clang {
+
+/// \brief Represents Objective-C's collection statement.
+///
+/// This is 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; }
+
+ SourceLocation getLocStart() const LLVM_READONLY { return ForLoc; }
+ SourceLocation getLocEnd() const LLVM_READONLY {
+ return SubExprs[BODY]->getLocEnd();
+ }
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == ObjCForCollectionStmtClass;
+ }
+
+ // Iterators
+ child_range children() {
+ return child_range(&SubExprs[0], &SubExprs[END_EXPR]);
+ }
+};
+
+/// \brief 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; }
+
+ SourceLocation getLocStart() const LLVM_READONLY { return AtCatchLoc; }
+ SourceLocation getLocEnd() const LLVM_READONLY { return Body->getLocEnd(); }
+
+ bool hasEllipsis() const { return getCatchParamDecl() == nullptr; }
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == ObjCAtCatchStmtClass;
+ }
+
+ child_range children() { return child_range(&Body, &Body + 1); }
+};
+
+/// \brief Represents Objective-C's \@finally statement
+class ObjCAtFinallyStmt : public Stmt {
+ SourceLocation AtFinallyLoc;
+ Stmt *AtFinallyStmt;
+
+public:
+ ObjCAtFinallyStmt(SourceLocation atFinallyLoc, Stmt *atFinallyStmt)
+ : Stmt(ObjCAtFinallyStmtClass), AtFinallyLoc(atFinallyLoc),
+ AtFinallyStmt(atFinallyStmt) {}
+
+ explicit ObjCAtFinallyStmt(EmptyShell Empty) :
+ Stmt(ObjCAtFinallyStmtClass, Empty) { }
+
+ const Stmt *getFinallyBody() const { return AtFinallyStmt; }
+ Stmt *getFinallyBody() { return AtFinallyStmt; }
+ void setFinallyBody(Stmt *S) { AtFinallyStmt = S; }
+
+ SourceLocation getLocStart() const LLVM_READONLY { return AtFinallyLoc; }
+ SourceLocation getLocEnd() const LLVM_READONLY {
+ return AtFinallyStmt->getLocEnd();
+ }
+
+ SourceLocation getAtFinallyLoc() const { return AtFinallyLoc; }
+ void setAtFinallyLoc(SourceLocation Loc) { AtFinallyLoc = Loc; }
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == ObjCAtFinallyStmtClass;
+ }
+
+ child_range children() {
+ return child_range(&AtFinallyStmt, &AtFinallyStmt+1);
+ }
+};
+
+/// \brief Represents Objective-C's \@try ... \@catch ... \@finally statement.
+class ObjCAtTryStmt : public Stmt {
+private:
+ // The location of the @ in the \@try.
+ 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(const ASTContext &Context,
+ SourceLocation atTryLoc, Stmt *atTryStmt,
+ Stmt **CatchStmts, unsigned NumCatchStmts,
+ Stmt *atFinallyStmt);
+ static ObjCAtTryStmt *CreateEmpty(const 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;
+ }
+
+ /// \brief Retrieve the \@finally statement, if any.
+ const ObjCAtFinallyStmt *getFinallyStmt() const {
+ if (!HasFinally)
+ return nullptr;
+
+ return cast_or_null<ObjCAtFinallyStmt>(getStmts()[1 + NumCatchStmts]);
+ }
+ ObjCAtFinallyStmt *getFinallyStmt() {
+ if (!HasFinally)
+ return nullptr;
+
+ 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;
+ }
+
+ SourceLocation getLocStart() const LLVM_READONLY { return AtTryLoc; }
+ SourceLocation getLocEnd() const LLVM_READONLY;
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == ObjCAtTryStmtClass;
+ }
+
+ child_range children() {
+ return child_range(getStmts(),
+ getStmts() + 1 + NumCatchStmts + HasFinally);
+ }
+};
+
+/// \brief Represents Objective-C's \@synchronized statement.
+///
+/// Example:
+/// \code
+/// @synchronized (sem) {
+/// do-something;
+/// }
+/// \endcode
+class ObjCAtSynchronizedStmt : public Stmt {
+private:
+ SourceLocation AtSynchronizedLoc;
+ enum { SYNC_EXPR, SYNC_BODY, END_EXPR };
+ Stmt* SubStmts[END_EXPR];
+
+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; }
+
+ SourceLocation getLocStart() const LLVM_READONLY { return AtSynchronizedLoc; }
+ SourceLocation getLocEnd() const LLVM_READONLY {
+ return getSynchBody()->getLocEnd();
+ }
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == ObjCAtSynchronizedStmtClass;
+ }
+
+ child_range children() {
+ return child_range(&SubStmts[0], &SubStmts[0]+END_EXPR);
+ }
+};
+
+/// \brief Represents Objective-C's \@throw statement.
+class ObjCAtThrowStmt : public Stmt {
+ SourceLocation AtThrowLoc;
+ Stmt *Throw;
+
+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; }
+
+ SourceLocation getLocStart() const LLVM_READONLY { return AtThrowLoc; }
+ SourceLocation getLocEnd() const LLVM_READONLY {
+ return Throw ? Throw->getLocEnd() : AtThrowLoc;
+ }
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == ObjCAtThrowStmtClass;
+ }
+
+ child_range children() { return child_range(&Throw, &Throw+1); }
+};
+
+/// \brief Represents Objective-C's \@autoreleasepool Statement
+class ObjCAutoreleasePoolStmt : public Stmt {
+ SourceLocation AtLoc;
+ Stmt *SubStmt;
+
+public:
+ ObjCAutoreleasePoolStmt(SourceLocation atLoc, Stmt *subStmt)
+ : Stmt(ObjCAutoreleasePoolStmtClass), AtLoc(atLoc), SubStmt(subStmt) {}
+
+ explicit ObjCAutoreleasePoolStmt(EmptyShell Empty) :
+ Stmt(ObjCAutoreleasePoolStmtClass, Empty) { }
+
+ const Stmt *getSubStmt() const { return SubStmt; }
+ Stmt *getSubStmt() { return SubStmt; }
+ void setSubStmt(Stmt *S) { SubStmt = S; }
+
+ SourceLocation getLocStart() const LLVM_READONLY { return AtLoc; }
+ SourceLocation getLocEnd() const LLVM_READONLY { return SubStmt->getLocEnd();}
+
+ SourceLocation getAtLoc() const { return AtLoc; }
+ void setAtLoc(SourceLocation Loc) { AtLoc = Loc; }
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == ObjCAutoreleasePoolStmtClass;
+ }
+
+ child_range children() { return child_range(&SubStmt, &SubStmt + 1); }
+};
+
+} // end namespace clang
+
+#endif
diff --git a/contrib/llvm/tools/clang/include/clang/AST/StmtOpenMP.h b/contrib/llvm/tools/clang/include/clang/AST/StmtOpenMP.h
new file mode 100644
index 0000000..1ba859c
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/AST/StmtOpenMP.h
@@ -0,0 +1,2422 @@
+//===- StmtOpenMP.h - Classes for OpenMP directives ------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+/// \file
+/// \brief This file defines OpenMP AST classes for executable directives and
+/// clauses.
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_AST_STMTOPENMP_H
+#define LLVM_CLANG_AST_STMTOPENMP_H
+
+#include "clang/AST/Expr.h"
+#include "clang/AST/OpenMPClause.h"
+#include "clang/AST/Stmt.h"
+#include "clang/Basic/OpenMPKinds.h"
+#include "clang/Basic/SourceLocation.h"
+
+namespace clang {
+
+//===----------------------------------------------------------------------===//
+// AST classes for directives.
+//===----------------------------------------------------------------------===//
+
+/// \brief This is a basic class for representing single OpenMP executable
+/// directive.
+///
+class OMPExecutableDirective : public Stmt {
+ friend class ASTStmtReader;
+ /// \brief Kind of the directive.
+ OpenMPDirectiveKind Kind;
+ /// \brief Starting location of the directive (directive keyword).
+ SourceLocation StartLoc;
+ /// \brief Ending location of the directive.
+ SourceLocation EndLoc;
+ /// \brief Numbers of clauses.
+ const unsigned NumClauses;
+ /// \brief Number of child expressions/stmts.
+ const unsigned NumChildren;
+ /// \brief Offset from this to the start of clauses.
+ /// There are NumClauses pointers to clauses, they are followed by
+ /// NumChildren pointers to child stmts/exprs (if the directive type
+ /// requires an associated stmt, then it has to be the first of them).
+ const unsigned ClausesOffset;
+
+ /// \brief Get the clauses storage.
+ MutableArrayRef<OMPClause *> getClauses() {
+ OMPClause **ClauseStorage = reinterpret_cast<OMPClause **>(
+ reinterpret_cast<char *>(this) + ClausesOffset);
+ return MutableArrayRef<OMPClause *>(ClauseStorage, NumClauses);
+ }
+
+protected:
+ /// \brief Build instance of directive of class \a K.
+ ///
+ /// \param SC Statement class.
+ /// \param K Kind of OpenMP directive.
+ /// \param StartLoc Starting location of the directive (directive keyword).
+ /// \param EndLoc Ending location of the directive.
+ ///
+ template <typename T>
+ OMPExecutableDirective(const T *, StmtClass SC, OpenMPDirectiveKind K,
+ SourceLocation StartLoc, SourceLocation EndLoc,
+ unsigned NumClauses, unsigned NumChildren)
+ : Stmt(SC), Kind(K), StartLoc(std::move(StartLoc)),
+ EndLoc(std::move(EndLoc)), NumClauses(NumClauses),
+ NumChildren(NumChildren),
+ ClausesOffset(llvm::RoundUpToAlignment(sizeof(T),
+ llvm::alignOf<OMPClause *>())) {}
+
+ /// \brief Sets the list of variables for this clause.
+ ///
+ /// \param Clauses The list of clauses for the directive.
+ ///
+ void setClauses(ArrayRef<OMPClause *> Clauses);
+
+ /// \brief Set the associated statement for the directive.
+ ///
+ /// /param S Associated statement.
+ ///
+ void setAssociatedStmt(Stmt *S) {
+ assert(hasAssociatedStmt() && "no associated statement.");
+ *child_begin() = S;
+ }
+
+public:
+ /// \brief Iterates over a filtered subrange of clauses applied to a
+ /// directive.
+ ///
+ /// This iterator visits only clauses of type SpecificClause.
+ template <typename SpecificClause>
+ class specific_clause_iterator
+ : public llvm::iterator_adaptor_base<
+ specific_clause_iterator<SpecificClause>,
+ ArrayRef<OMPClause *>::const_iterator, std::forward_iterator_tag,
+ const SpecificClause *, ptrdiff_t, const SpecificClause *,
+ const SpecificClause *> {
+ ArrayRef<OMPClause *>::const_iterator End;
+
+ void SkipToNextClause() {
+ while (this->I != End && !isa<SpecificClause>(*this->I))
+ ++this->I;
+ }
+
+ public:
+ explicit specific_clause_iterator(ArrayRef<OMPClause *> Clauses)
+ : specific_clause_iterator::iterator_adaptor_base(Clauses.begin()),
+ End(Clauses.end()) {
+ SkipToNextClause();
+ }
+
+ const SpecificClause *operator*() const {
+ return cast<SpecificClause>(*this->I);
+ }
+ const SpecificClause *operator->() const { return **this; }
+
+ specific_clause_iterator &operator++() {
+ ++this->I;
+ SkipToNextClause();
+ return *this;
+ }
+ };
+
+ template <typename SpecificClause>
+ static llvm::iterator_range<specific_clause_iterator<SpecificClause>>
+ getClausesOfKind(ArrayRef<OMPClause *> Clauses) {
+ return {specific_clause_iterator<SpecificClause>(Clauses),
+ specific_clause_iterator<SpecificClause>(
+ llvm::makeArrayRef(Clauses.end(), 0))};
+ }
+
+ template <typename SpecificClause>
+ llvm::iterator_range<specific_clause_iterator<SpecificClause>>
+ getClausesOfKind() const {
+ return getClausesOfKind<SpecificClause>(clauses());
+ }
+
+ /// Gets a single clause of the specified kind associated with the
+ /// current directive iff there is only one clause of this kind (and assertion
+ /// is fired if there is more than one clause is associated with the
+ /// directive). Returns nullptr if no clause of this kind is associated with
+ /// the directive.
+ template <typename SpecificClause>
+ const SpecificClause *getSingleClause() const {
+ auto Clauses = getClausesOfKind<SpecificClause>();
+
+ if (Clauses.begin() != Clauses.end()) {
+ assert(std::next(Clauses.begin()) == Clauses.end() &&
+ "There are at least 2 clauses of the specified kind");
+ return *Clauses.begin();
+ }
+ return nullptr;
+ }
+
+ /// Returns true if the current directive has one or more clauses of a
+ /// specific kind.
+ template <typename SpecificClause>
+ bool hasClausesOfKind() const {
+ auto Clauses = getClausesOfKind<SpecificClause>();
+ return Clauses.begin() != Clauses.end();
+ }
+
+ /// \brief Returns starting location of directive kind.
+ SourceLocation getLocStart() const { return StartLoc; }
+ /// \brief Returns ending location of directive.
+ SourceLocation getLocEnd() const { return EndLoc; }
+
+ /// \brief Set starting location of directive kind.
+ ///
+ /// \param Loc New starting location of directive.
+ ///
+ void setLocStart(SourceLocation Loc) { StartLoc = Loc; }
+ /// \brief Set ending location of directive.
+ ///
+ /// \param Loc New ending location of directive.
+ ///
+ void setLocEnd(SourceLocation Loc) { EndLoc = Loc; }
+
+ /// \brief Get number of clauses.
+ unsigned getNumClauses() const { return NumClauses; }
+
+ /// \brief Returns specified clause.
+ ///
+ /// \param i Number of clause.
+ ///
+ OMPClause *getClause(unsigned i) const { return clauses()[i]; }
+
+ /// \brief Returns true if directive has associated statement.
+ bool hasAssociatedStmt() const { return NumChildren > 0; }
+
+ /// \brief Returns statement associated with the directive.
+ Stmt *getAssociatedStmt() const {
+ assert(hasAssociatedStmt() && "no associated statement.");
+ return const_cast<Stmt *>(*child_begin());
+ }
+
+ OpenMPDirectiveKind getDirectiveKind() const { return Kind; }
+
+ static bool classof(const Stmt *S) {
+ return S->getStmtClass() >= firstOMPExecutableDirectiveConstant &&
+ S->getStmtClass() <= lastOMPExecutableDirectiveConstant;
+ }
+
+ child_range children() {
+ if (!hasAssociatedStmt())
+ return child_range(child_iterator(), child_iterator());
+ Stmt **ChildStorage = reinterpret_cast<Stmt **>(getClauses().end());
+ return child_range(ChildStorage, ChildStorage + NumChildren);
+ }
+
+ ArrayRef<OMPClause *> clauses() { return getClauses(); }
+
+ ArrayRef<OMPClause *> clauses() const {
+ return const_cast<OMPExecutableDirective *>(this)->getClauses();
+ }
+};
+
+/// \brief This represents '#pragma omp parallel' directive.
+///
+/// \code
+/// #pragma omp parallel private(a,b) reduction(+: c,d)
+/// \endcode
+/// In this example directive '#pragma omp parallel' has clauses 'private'
+/// with the variables 'a' and 'b' and 'reduction' with operator '+' and
+/// variables 'c' and 'd'.
+///
+class OMPParallelDirective : public OMPExecutableDirective {
+ friend class ASTStmtReader;
+ /// \brief true if the construct has inner cancel directive.
+ bool HasCancel;
+
+ /// \brief Build directive with the given start and end location.
+ ///
+ /// \param StartLoc Starting location of the directive (directive keyword).
+ /// \param EndLoc Ending Location of the directive.
+ ///
+ OMPParallelDirective(SourceLocation StartLoc, SourceLocation EndLoc,
+ unsigned NumClauses)
+ : OMPExecutableDirective(this, OMPParallelDirectiveClass, OMPD_parallel,
+ StartLoc, EndLoc, NumClauses, 1),
+ HasCancel(false) {}
+
+ /// \brief Build an empty directive.
+ ///
+ /// \param NumClauses Number of clauses.
+ ///
+ explicit OMPParallelDirective(unsigned NumClauses)
+ : OMPExecutableDirective(this, OMPParallelDirectiveClass, OMPD_parallel,
+ SourceLocation(), SourceLocation(), NumClauses,
+ 1),
+ HasCancel(false) {}
+
+ /// \brief Set cancel state.
+ void setHasCancel(bool Has) { HasCancel = Has; }
+
+public:
+ /// \brief Creates directive with a list of \a Clauses.
+ ///
+ /// \param C AST context.
+ /// \param StartLoc Starting location of the directive kind.
+ /// \param EndLoc Ending Location of the directive.
+ /// \param Clauses List of clauses.
+ /// \param AssociatedStmt Statement associated with the directive.
+ /// \param HasCancel true if this directive has inner cancel directive.
+ ///
+ static OMPParallelDirective *
+ Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
+ ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt, bool HasCancel);
+
+ /// \brief Creates an empty directive with the place for \a N clauses.
+ ///
+ /// \param C AST context.
+ /// \param NumClauses Number of clauses.
+ ///
+ static OMPParallelDirective *CreateEmpty(const ASTContext &C,
+ unsigned NumClauses, EmptyShell);
+
+ /// \brief Return true if current directive has inner cancel directive.
+ bool hasCancel() const { return HasCancel; }
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == OMPParallelDirectiveClass;
+ }
+};
+
+/// \brief This is a common base class for loop directives ('omp simd', 'omp
+/// for', 'omp for simd' etc.). It is responsible for the loop code generation.
+///
+class OMPLoopDirective : public OMPExecutableDirective {
+ friend class ASTStmtReader;
+ /// \brief Number of collapsed loops as specified by 'collapse' clause.
+ unsigned CollapsedNum;
+
+ /// \brief Offsets to the stored exprs.
+ /// This enumeration contains offsets to all the pointers to children
+ /// expressions stored in OMPLoopDirective.
+ /// The first 9 children are nesessary for all the loop directives, and
+ /// the next 7 are specific to the worksharing ones.
+ /// After the fixed children, three arrays of length CollapsedNum are
+ /// allocated: loop counters, their updates and final values.
+ ///
+ enum {
+ AssociatedStmtOffset = 0,
+ IterationVariableOffset = 1,
+ LastIterationOffset = 2,
+ CalcLastIterationOffset = 3,
+ PreConditionOffset = 4,
+ CondOffset = 5,
+ InitOffset = 6,
+ IncOffset = 7,
+ // The '...End' enumerators do not correspond to child expressions - they
+ // specify the offset to the end (and start of the following counters/
+ // updates/finals arrays).
+ DefaultEnd = 8,
+ // The following 7 exprs are used by worksharing loops only.
+ IsLastIterVariableOffset = 8,
+ LowerBoundVariableOffset = 9,
+ UpperBoundVariableOffset = 10,
+ StrideVariableOffset = 11,
+ EnsureUpperBoundOffset = 12,
+ NextLowerBoundOffset = 13,
+ NextUpperBoundOffset = 14,
+ // Offset to the end (and start of the following counters/updates/finals
+ // arrays) for worksharing loop directives.
+ WorksharingEnd = 15,
+ };
+
+ /// \brief Get the counters storage.
+ MutableArrayRef<Expr *> getCounters() {
+ Expr **Storage = reinterpret_cast<Expr **>(
+ &(*(std::next(child_begin(), getArraysOffset(getDirectiveKind())))));
+ return MutableArrayRef<Expr *>(Storage, CollapsedNum);
+ }
+
+ /// \brief Get the private counters storage.
+ MutableArrayRef<Expr *> getPrivateCounters() {
+ Expr **Storage = reinterpret_cast<Expr **>(&*std::next(
+ child_begin(), getArraysOffset(getDirectiveKind()) + CollapsedNum));
+ return MutableArrayRef<Expr *>(Storage, CollapsedNum);
+ }
+
+ /// \brief Get the updates storage.
+ MutableArrayRef<Expr *> getInits() {
+ Expr **Storage = reinterpret_cast<Expr **>(
+ &*std::next(child_begin(),
+ getArraysOffset(getDirectiveKind()) + 2 * CollapsedNum));
+ return MutableArrayRef<Expr *>(Storage, CollapsedNum);
+ }
+
+ /// \brief Get the updates storage.
+ MutableArrayRef<Expr *> getUpdates() {
+ Expr **Storage = reinterpret_cast<Expr **>(
+ &*std::next(child_begin(),
+ getArraysOffset(getDirectiveKind()) + 3 * CollapsedNum));
+ return MutableArrayRef<Expr *>(Storage, CollapsedNum);
+ }
+
+ /// \brief Get the final counter updates storage.
+ MutableArrayRef<Expr *> getFinals() {
+ Expr **Storage = reinterpret_cast<Expr **>(
+ &*std::next(child_begin(),
+ getArraysOffset(getDirectiveKind()) + 4 * CollapsedNum));
+ return MutableArrayRef<Expr *>(Storage, CollapsedNum);
+ }
+
+protected:
+ /// \brief Build instance of loop directive of class \a Kind.
+ ///
+ /// \param SC Statement class.
+ /// \param Kind Kind of OpenMP directive.
+ /// \param StartLoc Starting location of the directive (directive keyword).
+ /// \param EndLoc Ending location of the directive.
+ /// \param CollapsedNum Number of collapsed loops from 'collapse' clause.
+ /// \param NumClauses Number of clauses.
+ /// \param NumSpecialChildren Number of additional directive-specific stmts.
+ ///
+ template <typename T>
+ OMPLoopDirective(const T *That, StmtClass SC, OpenMPDirectiveKind Kind,
+ SourceLocation StartLoc, SourceLocation EndLoc,
+ unsigned CollapsedNum, unsigned NumClauses,
+ unsigned NumSpecialChildren = 0)
+ : OMPExecutableDirective(That, SC, Kind, StartLoc, EndLoc, NumClauses,
+ numLoopChildren(CollapsedNum, Kind) +
+ NumSpecialChildren),
+ CollapsedNum(CollapsedNum) {}
+
+ /// \brief Offset to the start of children expression arrays.
+ static unsigned getArraysOffset(OpenMPDirectiveKind Kind) {
+ return (isOpenMPWorksharingDirective(Kind) ||
+ isOpenMPTaskLoopDirective(Kind) ||
+ isOpenMPDistributeDirective(Kind))
+ ? WorksharingEnd
+ : DefaultEnd;
+ }
+
+ /// \brief Children number.
+ static unsigned numLoopChildren(unsigned CollapsedNum,
+ OpenMPDirectiveKind Kind) {
+ return getArraysOffset(Kind) + 5 * CollapsedNum; // Counters,
+ // PrivateCounters, Inits,
+ // Updates and Finals
+ }
+
+ void setIterationVariable(Expr *IV) {
+ *std::next(child_begin(), IterationVariableOffset) = IV;
+ }
+ void setLastIteration(Expr *LI) {
+ *std::next(child_begin(), LastIterationOffset) = LI;
+ }
+ void setCalcLastIteration(Expr *CLI) {
+ *std::next(child_begin(), CalcLastIterationOffset) = CLI;
+ }
+ void setPreCond(Expr *PC) {
+ *std::next(child_begin(), PreConditionOffset) = PC;
+ }
+ void setCond(Expr *Cond) {
+ *std::next(child_begin(), CondOffset) = Cond;
+ }
+ void setInit(Expr *Init) { *std::next(child_begin(), InitOffset) = Init; }
+ void setInc(Expr *Inc) { *std::next(child_begin(), IncOffset) = Inc; }
+ void setIsLastIterVariable(Expr *IL) {
+ assert((isOpenMPWorksharingDirective(getDirectiveKind()) ||
+ isOpenMPTaskLoopDirective(getDirectiveKind()) ||
+ isOpenMPDistributeDirective(getDirectiveKind())) &&
+ "expected worksharing loop directive");
+ *std::next(child_begin(), IsLastIterVariableOffset) = IL;
+ }
+ void setLowerBoundVariable(Expr *LB) {
+ assert((isOpenMPWorksharingDirective(getDirectiveKind()) ||
+ isOpenMPTaskLoopDirective(getDirectiveKind()) ||
+ isOpenMPDistributeDirective(getDirectiveKind())) &&
+ "expected worksharing loop directive");
+ *std::next(child_begin(), LowerBoundVariableOffset) = LB;
+ }
+ void setUpperBoundVariable(Expr *UB) {
+ assert((isOpenMPWorksharingDirective(getDirectiveKind()) ||
+ isOpenMPTaskLoopDirective(getDirectiveKind()) ||
+ isOpenMPDistributeDirective(getDirectiveKind())) &&
+ "expected worksharing loop directive");
+ *std::next(child_begin(), UpperBoundVariableOffset) = UB;
+ }
+ void setStrideVariable(Expr *ST) {
+ assert((isOpenMPWorksharingDirective(getDirectiveKind()) ||
+ isOpenMPTaskLoopDirective(getDirectiveKind()) ||
+ isOpenMPDistributeDirective(getDirectiveKind())) &&
+ "expected worksharing loop directive");
+ *std::next(child_begin(), StrideVariableOffset) = ST;
+ }
+ void setEnsureUpperBound(Expr *EUB) {
+ assert((isOpenMPWorksharingDirective(getDirectiveKind()) ||
+ isOpenMPTaskLoopDirective(getDirectiveKind()) ||
+ isOpenMPDistributeDirective(getDirectiveKind())) &&
+ "expected worksharing loop directive");
+ *std::next(child_begin(), EnsureUpperBoundOffset) = EUB;
+ }
+ void setNextLowerBound(Expr *NLB) {
+ assert((isOpenMPWorksharingDirective(getDirectiveKind()) ||
+ isOpenMPTaskLoopDirective(getDirectiveKind()) ||
+ isOpenMPDistributeDirective(getDirectiveKind())) &&
+ "expected worksharing loop directive");
+ *std::next(child_begin(), NextLowerBoundOffset) = NLB;
+ }
+ void setNextUpperBound(Expr *NUB) {
+ assert((isOpenMPWorksharingDirective(getDirectiveKind()) ||
+ isOpenMPTaskLoopDirective(getDirectiveKind()) ||
+ isOpenMPDistributeDirective(getDirectiveKind())) &&
+ "expected worksharing loop directive");
+ *std::next(child_begin(), NextUpperBoundOffset) = NUB;
+ }
+ void setCounters(ArrayRef<Expr *> A);
+ void setPrivateCounters(ArrayRef<Expr *> A);
+ void setInits(ArrayRef<Expr *> A);
+ void setUpdates(ArrayRef<Expr *> A);
+ void setFinals(ArrayRef<Expr *> A);
+
+public:
+ /// \brief The expressions built for the OpenMP loop CodeGen for the
+ /// whole collapsed loop nest.
+ struct HelperExprs {
+ /// \brief Loop iteration variable.
+ Expr *IterationVarRef;
+ /// \brief Loop last iteration number.
+ Expr *LastIteration;
+ /// \brief Loop number of iterations.
+ Expr *NumIterations;
+ /// \brief Calculation of last iteration.
+ Expr *CalcLastIteration;
+ /// \brief Loop pre-condition.
+ Expr *PreCond;
+ /// \brief Loop condition.
+ Expr *Cond;
+ /// \brief Loop iteration variable init.
+ Expr *Init;
+ /// \brief Loop increment.
+ Expr *Inc;
+ /// \brief IsLastIteration - local flag variable passed to runtime.
+ Expr *IL;
+ /// \brief LowerBound - local variable passed to runtime.
+ Expr *LB;
+ /// \brief UpperBound - local variable passed to runtime.
+ Expr *UB;
+ /// \brief Stride - local variable passed to runtime.
+ Expr *ST;
+ /// \brief EnsureUpperBound -- expression LB = min(LB, NumIterations).
+ Expr *EUB;
+ /// \brief Update of LowerBound for statically sheduled 'omp for' loops.
+ Expr *NLB;
+ /// \brief Update of UpperBound for statically sheduled 'omp for' loops.
+ Expr *NUB;
+ /// \brief Counters Loop counters.
+ SmallVector<Expr *, 4> Counters;
+ /// \brief PrivateCounters Loop counters.
+ SmallVector<Expr *, 4> PrivateCounters;
+ /// \brief Expressions for loop counters inits for CodeGen.
+ SmallVector<Expr *, 4> Inits;
+ /// \brief Expressions for loop counters update for CodeGen.
+ SmallVector<Expr *, 4> Updates;
+ /// \brief Final loop counter values for GodeGen.
+ SmallVector<Expr *, 4> Finals;
+
+ /// \brief Check if all the expressions are built (does not check the
+ /// worksharing ones).
+ bool builtAll() {
+ return IterationVarRef != nullptr && LastIteration != nullptr &&
+ NumIterations != nullptr && PreCond != nullptr &&
+ Cond != nullptr && Init != nullptr && Inc != nullptr;
+ }
+
+ /// \brief Initialize all the fields to null.
+ /// \param Size Number of elements in the counters/finals/updates arrays.
+ void clear(unsigned Size) {
+ IterationVarRef = nullptr;
+ LastIteration = nullptr;
+ CalcLastIteration = nullptr;
+ PreCond = nullptr;
+ Cond = nullptr;
+ Init = nullptr;
+ Inc = nullptr;
+ IL = nullptr;
+ LB = nullptr;
+ UB = nullptr;
+ ST = nullptr;
+ EUB = nullptr;
+ NLB = nullptr;
+ NUB = nullptr;
+ Counters.resize(Size);
+ PrivateCounters.resize(Size);
+ Inits.resize(Size);
+ Updates.resize(Size);
+ Finals.resize(Size);
+ for (unsigned i = 0; i < Size; ++i) {
+ Counters[i] = nullptr;
+ PrivateCounters[i] = nullptr;
+ Inits[i] = nullptr;
+ Updates[i] = nullptr;
+ Finals[i] = nullptr;
+ }
+ }
+ };
+
+ /// \brief Get number of collapsed loops.
+ unsigned getCollapsedNumber() const { return CollapsedNum; }
+
+ Expr *getIterationVariable() const {
+ return const_cast<Expr *>(reinterpret_cast<const Expr *>(
+ *std::next(child_begin(), IterationVariableOffset)));
+ }
+ Expr *getLastIteration() const {
+ return const_cast<Expr *>(reinterpret_cast<const Expr *>(
+ *std::next(child_begin(), LastIterationOffset)));
+ }
+ Expr *getCalcLastIteration() const {
+ return const_cast<Expr *>(reinterpret_cast<const Expr *>(
+ *std::next(child_begin(), CalcLastIterationOffset)));
+ }
+ Expr *getPreCond() const {
+ return const_cast<Expr *>(reinterpret_cast<const Expr *>(
+ *std::next(child_begin(), PreConditionOffset)));
+ }
+ Expr *getCond() const {
+ return const_cast<Expr *>(
+ reinterpret_cast<const Expr *>(*std::next(child_begin(), CondOffset)));
+ }
+ Expr *getInit() const {
+ return const_cast<Expr *>(
+ reinterpret_cast<const Expr *>(*std::next(child_begin(), InitOffset)));
+ }
+ Expr *getInc() const {
+ return const_cast<Expr *>(
+ reinterpret_cast<const Expr *>(*std::next(child_begin(), IncOffset)));
+ }
+ Expr *getIsLastIterVariable() const {
+ assert((isOpenMPWorksharingDirective(getDirectiveKind()) ||
+ isOpenMPTaskLoopDirective(getDirectiveKind())) &&
+ "expected worksharing loop directive");
+ return const_cast<Expr *>(reinterpret_cast<const Expr *>(
+ *std::next(child_begin(), IsLastIterVariableOffset)));
+ }
+ Expr *getLowerBoundVariable() const {
+ assert((isOpenMPWorksharingDirective(getDirectiveKind()) ||
+ isOpenMPTaskLoopDirective(getDirectiveKind())) &&
+ "expected worksharing loop directive");
+ return const_cast<Expr *>(reinterpret_cast<const Expr *>(
+ *std::next(child_begin(), LowerBoundVariableOffset)));
+ }
+ Expr *getUpperBoundVariable() const {
+ assert((isOpenMPWorksharingDirective(getDirectiveKind()) ||
+ isOpenMPTaskLoopDirective(getDirectiveKind())) &&
+ "expected worksharing loop directive");
+ return const_cast<Expr *>(reinterpret_cast<const Expr *>(
+ *std::next(child_begin(), UpperBoundVariableOffset)));
+ }
+ Expr *getStrideVariable() const {
+ assert((isOpenMPWorksharingDirective(getDirectiveKind()) ||
+ isOpenMPTaskLoopDirective(getDirectiveKind())) &&
+ "expected worksharing loop directive");
+ return const_cast<Expr *>(reinterpret_cast<const Expr *>(
+ *std::next(child_begin(), StrideVariableOffset)));
+ }
+ Expr *getEnsureUpperBound() const {
+ assert((isOpenMPWorksharingDirective(getDirectiveKind()) ||
+ isOpenMPTaskLoopDirective(getDirectiveKind())) &&
+ "expected worksharing loop directive");
+ return const_cast<Expr *>(reinterpret_cast<const Expr *>(
+ *std::next(child_begin(), EnsureUpperBoundOffset)));
+ }
+ Expr *getNextLowerBound() const {
+ assert((isOpenMPWorksharingDirective(getDirectiveKind()) ||
+ isOpenMPTaskLoopDirective(getDirectiveKind())) &&
+ "expected worksharing loop directive");
+ return const_cast<Expr *>(reinterpret_cast<const Expr *>(
+ *std::next(child_begin(), NextLowerBoundOffset)));
+ }
+ Expr *getNextUpperBound() const {
+ assert((isOpenMPWorksharingDirective(getDirectiveKind()) ||
+ isOpenMPTaskLoopDirective(getDirectiveKind())) &&
+ "expected worksharing loop directive");
+ return const_cast<Expr *>(reinterpret_cast<const Expr *>(
+ *std::next(child_begin(), NextUpperBoundOffset)));
+ }
+ const Stmt *getBody() const {
+ // This relies on the loop form is already checked by Sema.
+ Stmt *Body = getAssociatedStmt()->IgnoreContainers(true);
+ Body = cast<ForStmt>(Body)->getBody();
+ for (unsigned Cnt = 1; Cnt < CollapsedNum; ++Cnt) {
+ Body = Body->IgnoreContainers();
+ Body = cast<ForStmt>(Body)->getBody();
+ }
+ return Body;
+ }
+
+ ArrayRef<Expr *> counters() { return getCounters(); }
+
+ ArrayRef<Expr *> counters() const {
+ return const_cast<OMPLoopDirective *>(this)->getCounters();
+ }
+
+ ArrayRef<Expr *> private_counters() { return getPrivateCounters(); }
+
+ ArrayRef<Expr *> private_counters() const {
+ return const_cast<OMPLoopDirective *>(this)->getPrivateCounters();
+ }
+
+ ArrayRef<Expr *> inits() { return getInits(); }
+
+ ArrayRef<Expr *> inits() const {
+ return const_cast<OMPLoopDirective *>(this)->getInits();
+ }
+
+ ArrayRef<Expr *> updates() { return getUpdates(); }
+
+ ArrayRef<Expr *> updates() const {
+ return const_cast<OMPLoopDirective *>(this)->getUpdates();
+ }
+
+ ArrayRef<Expr *> finals() { return getFinals(); }
+
+ ArrayRef<Expr *> finals() const {
+ return const_cast<OMPLoopDirective *>(this)->getFinals();
+ }
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == OMPSimdDirectiveClass ||
+ T->getStmtClass() == OMPForDirectiveClass ||
+ T->getStmtClass() == OMPForSimdDirectiveClass ||
+ T->getStmtClass() == OMPParallelForDirectiveClass ||
+ T->getStmtClass() == OMPParallelForSimdDirectiveClass ||
+ T->getStmtClass() == OMPTaskLoopDirectiveClass ||
+ T->getStmtClass() == OMPTaskLoopSimdDirectiveClass ||
+ T->getStmtClass() == OMPDistributeDirectiveClass;
+ }
+};
+
+/// \brief This represents '#pragma omp simd' directive.
+///
+/// \code
+/// #pragma omp simd private(a,b) linear(i,j:s) reduction(+:c,d)
+/// \endcode
+/// In this example directive '#pragma omp simd' has clauses 'private'
+/// with the variables 'a' and 'b', 'linear' with variables 'i', 'j' and
+/// linear step 's', 'reduction' with operator '+' and variables 'c' and 'd'.
+///
+class OMPSimdDirective : public OMPLoopDirective {
+ friend class ASTStmtReader;
+ /// \brief Build directive with the given start and end location.
+ ///
+ /// \param StartLoc Starting location of the directive kind.
+ /// \param EndLoc Ending location of the directive.
+ /// \param CollapsedNum Number of collapsed nested loops.
+ /// \param NumClauses Number of clauses.
+ ///
+ OMPSimdDirective(SourceLocation StartLoc, SourceLocation EndLoc,
+ unsigned CollapsedNum, unsigned NumClauses)
+ : OMPLoopDirective(this, OMPSimdDirectiveClass, OMPD_simd, StartLoc,
+ EndLoc, CollapsedNum, NumClauses) {}
+
+ /// \brief Build an empty directive.
+ ///
+ /// \param CollapsedNum Number of collapsed nested loops.
+ /// \param NumClauses Number of clauses.
+ ///
+ explicit OMPSimdDirective(unsigned CollapsedNum, unsigned NumClauses)
+ : OMPLoopDirective(this, OMPSimdDirectiveClass, OMPD_simd,
+ SourceLocation(), SourceLocation(), CollapsedNum,
+ NumClauses) {}
+
+public:
+ /// \brief Creates directive with a list of \a Clauses.
+ ///
+ /// \param C AST context.
+ /// \param StartLoc Starting location of the directive kind.
+ /// \param EndLoc Ending Location of the directive.
+ /// \param CollapsedNum Number of collapsed loops.
+ /// \param Clauses List of clauses.
+ /// \param AssociatedStmt Statement, associated with the directive.
+ /// \param Exprs Helper expressions for CodeGen.
+ ///
+ static OMPSimdDirective *Create(const ASTContext &C, SourceLocation StartLoc,
+ SourceLocation EndLoc, unsigned CollapsedNum,
+ ArrayRef<OMPClause *> Clauses,
+ Stmt *AssociatedStmt,
+ const HelperExprs &Exprs);
+
+ /// \brief Creates an empty directive with the place
+ /// for \a NumClauses clauses.
+ ///
+ /// \param C AST context.
+ /// \param CollapsedNum Number of collapsed nested loops.
+ /// \param NumClauses Number of clauses.
+ ///
+ static OMPSimdDirective *CreateEmpty(const ASTContext &C, unsigned NumClauses,
+ unsigned CollapsedNum, EmptyShell);
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == OMPSimdDirectiveClass;
+ }
+};
+
+/// \brief This represents '#pragma omp for' directive.
+///
+/// \code
+/// #pragma omp for private(a,b) reduction(+:c,d)
+/// \endcode
+/// In this example directive '#pragma omp for' has clauses 'private' with the
+/// variables 'a' and 'b' and 'reduction' with operator '+' and variables 'c'
+/// and 'd'.
+///
+class OMPForDirective : public OMPLoopDirective {
+ friend class ASTStmtReader;
+
+ /// \brief true if current directive has inner cancel directive.
+ bool HasCancel;
+
+ /// \brief Build directive with the given start and end location.
+ ///
+ /// \param StartLoc Starting location of the directive kind.
+ /// \param EndLoc Ending location of the directive.
+ /// \param CollapsedNum Number of collapsed nested loops.
+ /// \param NumClauses Number of clauses.
+ ///
+ OMPForDirective(SourceLocation StartLoc, SourceLocation EndLoc,
+ unsigned CollapsedNum, unsigned NumClauses)
+ : OMPLoopDirective(this, OMPForDirectiveClass, OMPD_for, StartLoc, EndLoc,
+ CollapsedNum, NumClauses),
+ HasCancel(false) {}
+
+ /// \brief Build an empty directive.
+ ///
+ /// \param CollapsedNum Number of collapsed nested loops.
+ /// \param NumClauses Number of clauses.
+ ///
+ explicit OMPForDirective(unsigned CollapsedNum, unsigned NumClauses)
+ : OMPLoopDirective(this, OMPForDirectiveClass, OMPD_for, SourceLocation(),
+ SourceLocation(), CollapsedNum, NumClauses),
+ HasCancel(false) {}
+
+ /// \brief Set cancel state.
+ void setHasCancel(bool Has) { HasCancel = Has; }
+
+public:
+ /// \brief Creates directive with a list of \a Clauses.
+ ///
+ /// \param C AST context.
+ /// \param StartLoc Starting location of the directive kind.
+ /// \param EndLoc Ending Location of the directive.
+ /// \param CollapsedNum Number of collapsed loops.
+ /// \param Clauses List of clauses.
+ /// \param AssociatedStmt Statement, associated with the directive.
+ /// \param Exprs Helper expressions for CodeGen.
+ /// \param HasCancel true if current directive has inner cancel directive.
+ ///
+ static OMPForDirective *Create(const ASTContext &C, SourceLocation StartLoc,
+ SourceLocation EndLoc, unsigned CollapsedNum,
+ ArrayRef<OMPClause *> Clauses,
+ Stmt *AssociatedStmt, const HelperExprs &Exprs,
+ bool HasCancel);
+
+ /// \brief Creates an empty directive with the place
+ /// for \a NumClauses clauses.
+ ///
+ /// \param C AST context.
+ /// \param CollapsedNum Number of collapsed nested loops.
+ /// \param NumClauses Number of clauses.
+ ///
+ static OMPForDirective *CreateEmpty(const ASTContext &C, unsigned NumClauses,
+ unsigned CollapsedNum, EmptyShell);
+
+ /// \brief Return true if current directive has inner cancel directive.
+ bool hasCancel() const { return HasCancel; }
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == OMPForDirectiveClass;
+ }
+};
+
+/// \brief This represents '#pragma omp for simd' directive.
+///
+/// \code
+/// #pragma omp for simd private(a,b) linear(i,j:s) reduction(+:c,d)
+/// \endcode
+/// In this example directive '#pragma omp for simd' has clauses 'private'
+/// with the variables 'a' and 'b', 'linear' with variables 'i', 'j' and
+/// linear step 's', 'reduction' with operator '+' and variables 'c' and 'd'.
+///
+class OMPForSimdDirective : public OMPLoopDirective {
+ friend class ASTStmtReader;
+ /// \brief Build directive with the given start and end location.
+ ///
+ /// \param StartLoc Starting location of the directive kind.
+ /// \param EndLoc Ending location of the directive.
+ /// \param CollapsedNum Number of collapsed nested loops.
+ /// \param NumClauses Number of clauses.
+ ///
+ OMPForSimdDirective(SourceLocation StartLoc, SourceLocation EndLoc,
+ unsigned CollapsedNum, unsigned NumClauses)
+ : OMPLoopDirective(this, OMPForSimdDirectiveClass, OMPD_for_simd,
+ StartLoc, EndLoc, CollapsedNum, NumClauses) {}
+
+ /// \brief Build an empty directive.
+ ///
+ /// \param CollapsedNum Number of collapsed nested loops.
+ /// \param NumClauses Number of clauses.
+ ///
+ explicit OMPForSimdDirective(unsigned CollapsedNum, unsigned NumClauses)
+ : OMPLoopDirective(this, OMPForSimdDirectiveClass, OMPD_for_simd,
+ SourceLocation(), SourceLocation(), CollapsedNum,
+ NumClauses) {}
+
+public:
+ /// \brief Creates directive with a list of \a Clauses.
+ ///
+ /// \param C AST context.
+ /// \param StartLoc Starting location of the directive kind.
+ /// \param EndLoc Ending Location of the directive.
+ /// \param CollapsedNum Number of collapsed loops.
+ /// \param Clauses List of clauses.
+ /// \param AssociatedStmt Statement, associated with the directive.
+ /// \param Exprs Helper expressions for CodeGen.
+ ///
+ static OMPForSimdDirective *
+ Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
+ unsigned CollapsedNum, ArrayRef<OMPClause *> Clauses,
+ Stmt *AssociatedStmt, const HelperExprs &Exprs);
+
+ /// \brief Creates an empty directive with the place
+ /// for \a NumClauses clauses.
+ ///
+ /// \param C AST context.
+ /// \param CollapsedNum Number of collapsed nested loops.
+ /// \param NumClauses Number of clauses.
+ ///
+ static OMPForSimdDirective *CreateEmpty(const ASTContext &C,
+ unsigned NumClauses,
+ unsigned CollapsedNum, EmptyShell);
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == OMPForSimdDirectiveClass;
+ }
+};
+
+/// \brief This represents '#pragma omp sections' directive.
+///
+/// \code
+/// #pragma omp sections private(a,b) reduction(+:c,d)
+/// \endcode
+/// In this example directive '#pragma omp sections' has clauses 'private' with
+/// the variables 'a' and 'b' and 'reduction' with operator '+' and variables
+/// 'c' and 'd'.
+///
+class OMPSectionsDirective : public OMPExecutableDirective {
+ friend class ASTStmtReader;
+
+ /// \brief true if current directive has inner cancel directive.
+ bool HasCancel;
+
+ /// \brief Build directive with the given start and end location.
+ ///
+ /// \param StartLoc Starting location of the directive kind.
+ /// \param EndLoc Ending location of the directive.
+ /// \param NumClauses Number of clauses.
+ ///
+ OMPSectionsDirective(SourceLocation StartLoc, SourceLocation EndLoc,
+ unsigned NumClauses)
+ : OMPExecutableDirective(this, OMPSectionsDirectiveClass, OMPD_sections,
+ StartLoc, EndLoc, NumClauses, 1),
+ HasCancel(false) {}
+
+ /// \brief Build an empty directive.
+ ///
+ /// \param NumClauses Number of clauses.
+ ///
+ explicit OMPSectionsDirective(unsigned NumClauses)
+ : OMPExecutableDirective(this, OMPSectionsDirectiveClass, OMPD_sections,
+ SourceLocation(), SourceLocation(), NumClauses,
+ 1),
+ HasCancel(false) {}
+
+ /// \brief Set cancel state.
+ void setHasCancel(bool Has) { HasCancel = Has; }
+
+public:
+ /// \brief Creates directive with a list of \a Clauses.
+ ///
+ /// \param C AST context.
+ /// \param StartLoc Starting location of the directive kind.
+ /// \param EndLoc Ending Location of the directive.
+ /// \param Clauses List of clauses.
+ /// \param AssociatedStmt Statement, associated with the directive.
+ /// \param HasCancel true if current directive has inner directive.
+ ///
+ static OMPSectionsDirective *
+ Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
+ ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt, bool HasCancel);
+
+ /// \brief Creates an empty directive with the place for \a NumClauses
+ /// clauses.
+ ///
+ /// \param C AST context.
+ /// \param NumClauses Number of clauses.
+ ///
+ static OMPSectionsDirective *CreateEmpty(const ASTContext &C,
+ unsigned NumClauses, EmptyShell);
+
+ /// \brief Return true if current directive has inner cancel directive.
+ bool hasCancel() const { return HasCancel; }
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == OMPSectionsDirectiveClass;
+ }
+};
+
+/// \brief This represents '#pragma omp section' directive.
+///
+/// \code
+/// #pragma omp section
+/// \endcode
+///
+class OMPSectionDirective : public OMPExecutableDirective {
+ friend class ASTStmtReader;
+
+ /// \brief true if current directive has inner cancel directive.
+ bool HasCancel;
+
+ /// \brief Build directive with the given start and end location.
+ ///
+ /// \param StartLoc Starting location of the directive kind.
+ /// \param EndLoc Ending location of the directive.
+ ///
+ OMPSectionDirective(SourceLocation StartLoc, SourceLocation EndLoc)
+ : OMPExecutableDirective(this, OMPSectionDirectiveClass, OMPD_section,
+ StartLoc, EndLoc, 0, 1),
+ HasCancel(false) {}
+
+ /// \brief Build an empty directive.
+ ///
+ explicit OMPSectionDirective()
+ : OMPExecutableDirective(this, OMPSectionDirectiveClass, OMPD_section,
+ SourceLocation(), SourceLocation(), 0, 1),
+ HasCancel(false) {}
+
+public:
+ /// \brief Creates directive.
+ ///
+ /// \param C AST context.
+ /// \param StartLoc Starting location of the directive kind.
+ /// \param EndLoc Ending Location of the directive.
+ /// \param AssociatedStmt Statement, associated with the directive.
+ /// \param HasCancel true if current directive has inner directive.
+ ///
+ static OMPSectionDirective *Create(const ASTContext &C,
+ SourceLocation StartLoc,
+ SourceLocation EndLoc,
+ Stmt *AssociatedStmt, bool HasCancel);
+
+ /// \brief Creates an empty directive.
+ ///
+ /// \param C AST context.
+ ///
+ static OMPSectionDirective *CreateEmpty(const ASTContext &C, EmptyShell);
+
+ /// \brief Set cancel state.
+ void setHasCancel(bool Has) { HasCancel = Has; }
+
+ /// \brief Return true if current directive has inner cancel directive.
+ bool hasCancel() const { return HasCancel; }
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == OMPSectionDirectiveClass;
+ }
+};
+
+/// \brief This represents '#pragma omp single' directive.
+///
+/// \code
+/// #pragma omp single private(a,b) copyprivate(c,d)
+/// \endcode
+/// In this example directive '#pragma omp single' has clauses 'private' with
+/// the variables 'a' and 'b' and 'copyprivate' with variables 'c' and 'd'.
+///
+class OMPSingleDirective : public OMPExecutableDirective {
+ friend class ASTStmtReader;
+ /// \brief Build directive with the given start and end location.
+ ///
+ /// \param StartLoc Starting location of the directive kind.
+ /// \param EndLoc Ending location of the directive.
+ /// \param NumClauses Number of clauses.
+ ///
+ OMPSingleDirective(SourceLocation StartLoc, SourceLocation EndLoc,
+ unsigned NumClauses)
+ : OMPExecutableDirective(this, OMPSingleDirectiveClass, OMPD_single,
+ StartLoc, EndLoc, NumClauses, 1) {}
+
+ /// \brief Build an empty directive.
+ ///
+ /// \param NumClauses Number of clauses.
+ ///
+ explicit OMPSingleDirective(unsigned NumClauses)
+ : OMPExecutableDirective(this, OMPSingleDirectiveClass, OMPD_single,
+ SourceLocation(), SourceLocation(), NumClauses,
+ 1) {}
+
+public:
+ /// \brief Creates directive with a list of \a Clauses.
+ ///
+ /// \param C AST context.
+ /// \param StartLoc Starting location of the directive kind.
+ /// \param EndLoc Ending Location of the directive.
+ /// \param Clauses List of clauses.
+ /// \param AssociatedStmt Statement, associated with the directive.
+ ///
+ static OMPSingleDirective *
+ Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
+ ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt);
+
+ /// \brief Creates an empty directive with the place for \a NumClauses
+ /// clauses.
+ ///
+ /// \param C AST context.
+ /// \param NumClauses Number of clauses.
+ ///
+ static OMPSingleDirective *CreateEmpty(const ASTContext &C,
+ unsigned NumClauses, EmptyShell);
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == OMPSingleDirectiveClass;
+ }
+};
+
+/// \brief This represents '#pragma omp master' directive.
+///
+/// \code
+/// #pragma omp master
+/// \endcode
+///
+class OMPMasterDirective : public OMPExecutableDirective {
+ friend class ASTStmtReader;
+ /// \brief Build directive with the given start and end location.
+ ///
+ /// \param StartLoc Starting location of the directive kind.
+ /// \param EndLoc Ending location of the directive.
+ ///
+ OMPMasterDirective(SourceLocation StartLoc, SourceLocation EndLoc)
+ : OMPExecutableDirective(this, OMPMasterDirectiveClass, OMPD_master,
+ StartLoc, EndLoc, 0, 1) {}
+
+ /// \brief Build an empty directive.
+ ///
+ explicit OMPMasterDirective()
+ : OMPExecutableDirective(this, OMPMasterDirectiveClass, OMPD_master,
+ SourceLocation(), SourceLocation(), 0, 1) {}
+
+public:
+ /// \brief Creates directive.
+ ///
+ /// \param C AST context.
+ /// \param StartLoc Starting location of the directive kind.
+ /// \param EndLoc Ending Location of the directive.
+ /// \param AssociatedStmt Statement, associated with the directive.
+ ///
+ static OMPMasterDirective *Create(const ASTContext &C,
+ SourceLocation StartLoc,
+ SourceLocation EndLoc,
+ Stmt *AssociatedStmt);
+
+ /// \brief Creates an empty directive.
+ ///
+ /// \param C AST context.
+ ///
+ static OMPMasterDirective *CreateEmpty(const ASTContext &C, EmptyShell);
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == OMPMasterDirectiveClass;
+ }
+};
+
+/// \brief This represents '#pragma omp critical' directive.
+///
+/// \code
+/// #pragma omp critical
+/// \endcode
+///
+class OMPCriticalDirective : public OMPExecutableDirective {
+ friend class ASTStmtReader;
+ /// \brief Name of the directive.
+ DeclarationNameInfo DirName;
+ /// \brief Build directive with the given start and end location.
+ ///
+ /// \param Name Name of the directive.
+ /// \param StartLoc Starting location of the directive kind.
+ /// \param EndLoc Ending location of the directive.
+ /// \param NumClauses Number of clauses.
+ ///
+ OMPCriticalDirective(const DeclarationNameInfo &Name, SourceLocation StartLoc,
+ SourceLocation EndLoc, unsigned NumClauses)
+ : OMPExecutableDirective(this, OMPCriticalDirectiveClass, OMPD_critical,
+ StartLoc, EndLoc, NumClauses, 1),
+ DirName(Name) {}
+
+ /// \brief Build an empty directive.
+ ///
+ /// \param NumClauses Number of clauses.
+ ///
+ explicit OMPCriticalDirective(unsigned NumClauses)
+ : OMPExecutableDirective(this, OMPCriticalDirectiveClass, OMPD_critical,
+ SourceLocation(), SourceLocation(), NumClauses,
+ 1),
+ DirName() {}
+
+ /// \brief Set name of the directive.
+ ///
+ /// \param Name Name of the directive.
+ ///
+ void setDirectiveName(const DeclarationNameInfo &Name) { DirName = Name; }
+
+public:
+ /// \brief Creates directive.
+ ///
+ /// \param C AST context.
+ /// \param Name Name of the directive.
+ /// \param StartLoc Starting location of the directive kind.
+ /// \param EndLoc Ending Location of the directive.
+ /// \param Clauses List of clauses.
+ /// \param AssociatedStmt Statement, associated with the directive.
+ ///
+ static OMPCriticalDirective *
+ Create(const ASTContext &C, const DeclarationNameInfo &Name,
+ SourceLocation StartLoc, SourceLocation EndLoc,
+ ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt);
+
+ /// \brief Creates an empty directive.
+ ///
+ /// \param C AST context.
+ /// \param NumClauses Number of clauses.
+ ///
+ static OMPCriticalDirective *CreateEmpty(const ASTContext &C,
+ unsigned NumClauses, EmptyShell);
+
+ /// \brief Return name of the directive.
+ ///
+ DeclarationNameInfo getDirectiveName() const { return DirName; }
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == OMPCriticalDirectiveClass;
+ }
+};
+
+/// \brief This represents '#pragma omp parallel for' directive.
+///
+/// \code
+/// #pragma omp parallel for private(a,b) reduction(+:c,d)
+/// \endcode
+/// In this example directive '#pragma omp parallel for' has clauses 'private'
+/// with the variables 'a' and 'b' and 'reduction' with operator '+' and
+/// variables 'c' and 'd'.
+///
+class OMPParallelForDirective : public OMPLoopDirective {
+ friend class ASTStmtReader;
+
+ /// \brief true if current region has inner cancel directive.
+ bool HasCancel;
+
+ /// \brief Build directive with the given start and end location.
+ ///
+ /// \param StartLoc Starting location of the directive kind.
+ /// \param EndLoc Ending location of the directive.
+ /// \param CollapsedNum Number of collapsed nested loops.
+ /// \param NumClauses Number of clauses.
+ ///
+ OMPParallelForDirective(SourceLocation StartLoc, SourceLocation EndLoc,
+ unsigned CollapsedNum, unsigned NumClauses)
+ : OMPLoopDirective(this, OMPParallelForDirectiveClass, OMPD_parallel_for,
+ StartLoc, EndLoc, CollapsedNum, NumClauses),
+ HasCancel(false) {}
+
+ /// \brief Build an empty directive.
+ ///
+ /// \param CollapsedNum Number of collapsed nested loops.
+ /// \param NumClauses Number of clauses.
+ ///
+ explicit OMPParallelForDirective(unsigned CollapsedNum, unsigned NumClauses)
+ : OMPLoopDirective(this, OMPParallelForDirectiveClass, OMPD_parallel_for,
+ SourceLocation(), SourceLocation(), CollapsedNum,
+ NumClauses),
+ HasCancel(false) {}
+
+ /// \brief Set cancel state.
+ void setHasCancel(bool Has) { HasCancel = Has; }
+
+public:
+ /// \brief Creates directive with a list of \a Clauses.
+ ///
+ /// \param C AST context.
+ /// \param StartLoc Starting location of the directive kind.
+ /// \param EndLoc Ending Location of the directive.
+ /// \param CollapsedNum Number of collapsed loops.
+ /// \param Clauses List of clauses.
+ /// \param AssociatedStmt Statement, associated with the directive.
+ /// \param Exprs Helper expressions for CodeGen.
+ /// \param HasCancel true if current directive has inner cancel directive.
+ ///
+ static OMPParallelForDirective *
+ Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
+ unsigned CollapsedNum, ArrayRef<OMPClause *> Clauses,
+ Stmt *AssociatedStmt, const HelperExprs &Exprs, bool HasCancel);
+
+ /// \brief Creates an empty directive with the place
+ /// for \a NumClauses clauses.
+ ///
+ /// \param C AST context.
+ /// \param CollapsedNum Number of collapsed nested loops.
+ /// \param NumClauses Number of clauses.
+ ///
+ static OMPParallelForDirective *CreateEmpty(const ASTContext &C,
+ unsigned NumClauses,
+ unsigned CollapsedNum,
+ EmptyShell);
+
+ /// \brief Return true if current directive has inner cancel directive.
+ bool hasCancel() const { return HasCancel; }
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == OMPParallelForDirectiveClass;
+ }
+};
+
+/// \brief This represents '#pragma omp parallel for simd' directive.
+///
+/// \code
+/// #pragma omp parallel for simd private(a,b) linear(i,j:s) reduction(+:c,d)
+/// \endcode
+/// In this example directive '#pragma omp parallel for simd' has clauses
+/// 'private' with the variables 'a' and 'b', 'linear' with variables 'i', 'j'
+/// and linear step 's', 'reduction' with operator '+' and variables 'c' and
+/// 'd'.
+///
+class OMPParallelForSimdDirective : public OMPLoopDirective {
+ friend class ASTStmtReader;
+ /// \brief Build directive with the given start and end location.
+ ///
+ /// \param StartLoc Starting location of the directive kind.
+ /// \param EndLoc Ending location of the directive.
+ /// \param CollapsedNum Number of collapsed nested loops.
+ /// \param NumClauses Number of clauses.
+ ///
+ OMPParallelForSimdDirective(SourceLocation StartLoc, SourceLocation EndLoc,
+ unsigned CollapsedNum, unsigned NumClauses)
+ : OMPLoopDirective(this, OMPParallelForSimdDirectiveClass,
+ OMPD_parallel_for_simd, StartLoc, EndLoc, CollapsedNum,
+ NumClauses) {}
+
+ /// \brief Build an empty directive.
+ ///
+ /// \param CollapsedNum Number of collapsed nested loops.
+ /// \param NumClauses Number of clauses.
+ ///
+ explicit OMPParallelForSimdDirective(unsigned CollapsedNum,
+ unsigned NumClauses)
+ : OMPLoopDirective(this, OMPParallelForSimdDirectiveClass,
+ OMPD_parallel_for_simd, SourceLocation(),
+ SourceLocation(), CollapsedNum, NumClauses) {}
+
+public:
+ /// \brief Creates directive with a list of \a Clauses.
+ ///
+ /// \param C AST context.
+ /// \param StartLoc Starting location of the directive kind.
+ /// \param EndLoc Ending Location of the directive.
+ /// \param CollapsedNum Number of collapsed loops.
+ /// \param Clauses List of clauses.
+ /// \param AssociatedStmt Statement, associated with the directive.
+ /// \param Exprs Helper expressions for CodeGen.
+ ///
+ static OMPParallelForSimdDirective *
+ Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
+ unsigned CollapsedNum, ArrayRef<OMPClause *> Clauses,
+ Stmt *AssociatedStmt, const HelperExprs &Exprs);
+
+ /// \brief Creates an empty directive with the place
+ /// for \a NumClauses clauses.
+ ///
+ /// \param C AST context.
+ /// \param CollapsedNum Number of collapsed nested loops.
+ /// \param NumClauses Number of clauses.
+ ///
+ static OMPParallelForSimdDirective *CreateEmpty(const ASTContext &C,
+ unsigned NumClauses,
+ unsigned CollapsedNum,
+ EmptyShell);
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == OMPParallelForSimdDirectiveClass;
+ }
+};
+
+/// \brief This represents '#pragma omp parallel sections' directive.
+///
+/// \code
+/// #pragma omp parallel sections private(a,b) reduction(+:c,d)
+/// \endcode
+/// In this example directive '#pragma omp parallel sections' has clauses
+/// 'private' with the variables 'a' and 'b' and 'reduction' with operator '+'
+/// and variables 'c' and 'd'.
+///
+class OMPParallelSectionsDirective : public OMPExecutableDirective {
+ friend class ASTStmtReader;
+
+ /// \brief true if current directive has inner cancel directive.
+ bool HasCancel;
+
+ /// \brief Build directive with the given start and end location.
+ ///
+ /// \param StartLoc Starting location of the directive kind.
+ /// \param EndLoc Ending location of the directive.
+ /// \param NumClauses Number of clauses.
+ ///
+ OMPParallelSectionsDirective(SourceLocation StartLoc, SourceLocation EndLoc,
+ unsigned NumClauses)
+ : OMPExecutableDirective(this, OMPParallelSectionsDirectiveClass,
+ OMPD_parallel_sections, StartLoc, EndLoc,
+ NumClauses, 1),
+ HasCancel(false) {}
+
+ /// \brief Build an empty directive.
+ ///
+ /// \param NumClauses Number of clauses.
+ ///
+ explicit OMPParallelSectionsDirective(unsigned NumClauses)
+ : OMPExecutableDirective(this, OMPParallelSectionsDirectiveClass,
+ OMPD_parallel_sections, SourceLocation(),
+ SourceLocation(), NumClauses, 1),
+ HasCancel(false) {}
+
+ /// \brief Set cancel state.
+ void setHasCancel(bool Has) { HasCancel = Has; }
+
+public:
+ /// \brief Creates directive with a list of \a Clauses.
+ ///
+ /// \param C AST context.
+ /// \param StartLoc Starting location of the directive kind.
+ /// \param EndLoc Ending Location of the directive.
+ /// \param Clauses List of clauses.
+ /// \param AssociatedStmt Statement, associated with the directive.
+ /// \param HasCancel true if current directive has inner cancel directive.
+ ///
+ static OMPParallelSectionsDirective *
+ Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
+ ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt, bool HasCancel);
+
+ /// \brief Creates an empty directive with the place for \a NumClauses
+ /// clauses.
+ ///
+ /// \param C AST context.
+ /// \param NumClauses Number of clauses.
+ ///
+ static OMPParallelSectionsDirective *
+ CreateEmpty(const ASTContext &C, unsigned NumClauses, EmptyShell);
+
+ /// \brief Return true if current directive has inner cancel directive.
+ bool hasCancel() const { return HasCancel; }
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == OMPParallelSectionsDirectiveClass;
+ }
+};
+
+/// \brief This represents '#pragma omp task' directive.
+///
+/// \code
+/// #pragma omp task private(a,b) final(d)
+/// \endcode
+/// In this example directive '#pragma omp task' has clauses 'private' with the
+/// variables 'a' and 'b' and 'final' with condition 'd'.
+///
+class OMPTaskDirective : public OMPExecutableDirective {
+ friend class ASTStmtReader;
+ /// \brief true if this directive has inner cancel directive.
+ bool HasCancel;
+
+ /// \brief Build directive with the given start and end location.
+ ///
+ /// \param StartLoc Starting location of the directive kind.
+ /// \param EndLoc Ending location of the directive.
+ /// \param NumClauses Number of clauses.
+ ///
+ OMPTaskDirective(SourceLocation StartLoc, SourceLocation EndLoc,
+ unsigned NumClauses)
+ : OMPExecutableDirective(this, OMPTaskDirectiveClass, OMPD_task, StartLoc,
+ EndLoc, NumClauses, 1),
+ HasCancel(false) {}
+
+ /// \brief Build an empty directive.
+ ///
+ /// \param NumClauses Number of clauses.
+ ///
+ explicit OMPTaskDirective(unsigned NumClauses)
+ : OMPExecutableDirective(this, OMPTaskDirectiveClass, OMPD_task,
+ SourceLocation(), SourceLocation(), NumClauses,
+ 1),
+ HasCancel(false) {}
+
+ /// \brief Set cancel state.
+ void setHasCancel(bool Has) { HasCancel = Has; }
+
+public:
+ /// \brief Creates directive with a list of \a Clauses.
+ ///
+ /// \param C AST context.
+ /// \param StartLoc Starting location of the directive kind.
+ /// \param EndLoc Ending Location of the directive.
+ /// \param Clauses List of clauses.
+ /// \param AssociatedStmt Statement, associated with the directive.
+ /// \param HasCancel true, if current directive has inner cancel directive.
+ ///
+ static OMPTaskDirective *Create(const ASTContext &C, SourceLocation StartLoc,
+ SourceLocation EndLoc,
+ ArrayRef<OMPClause *> Clauses,
+ Stmt *AssociatedStmt, bool HasCancel);
+
+ /// \brief Creates an empty directive with the place for \a NumClauses
+ /// clauses.
+ ///
+ /// \param C AST context.
+ /// \param NumClauses Number of clauses.
+ ///
+ static OMPTaskDirective *CreateEmpty(const ASTContext &C, unsigned NumClauses,
+ EmptyShell);
+
+ /// \brief Return true if current directive has inner cancel directive.
+ bool hasCancel() const { return HasCancel; }
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == OMPTaskDirectiveClass;
+ }
+};
+
+/// \brief This represents '#pragma omp taskyield' directive.
+///
+/// \code
+/// #pragma omp taskyield
+/// \endcode
+///
+class OMPTaskyieldDirective : public OMPExecutableDirective {
+ friend class ASTStmtReader;
+ /// \brief Build directive with the given start and end location.
+ ///
+ /// \param StartLoc Starting location of the directive kind.
+ /// \param EndLoc Ending location of the directive.
+ ///
+ OMPTaskyieldDirective(SourceLocation StartLoc, SourceLocation EndLoc)
+ : OMPExecutableDirective(this, OMPTaskyieldDirectiveClass, OMPD_taskyield,
+ StartLoc, EndLoc, 0, 0) {}
+
+ /// \brief Build an empty directive.
+ ///
+ explicit OMPTaskyieldDirective()
+ : OMPExecutableDirective(this, OMPTaskyieldDirectiveClass, OMPD_taskyield,
+ SourceLocation(), SourceLocation(), 0, 0) {}
+
+public:
+ /// \brief Creates directive.
+ ///
+ /// \param C AST context.
+ /// \param StartLoc Starting location of the directive kind.
+ /// \param EndLoc Ending Location of the directive.
+ ///
+ static OMPTaskyieldDirective *
+ Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc);
+
+ /// \brief Creates an empty directive.
+ ///
+ /// \param C AST context.
+ ///
+ static OMPTaskyieldDirective *CreateEmpty(const ASTContext &C, EmptyShell);
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == OMPTaskyieldDirectiveClass;
+ }
+};
+
+/// \brief This represents '#pragma omp barrier' directive.
+///
+/// \code
+/// #pragma omp barrier
+/// \endcode
+///
+class OMPBarrierDirective : public OMPExecutableDirective {
+ friend class ASTStmtReader;
+ /// \brief Build directive with the given start and end location.
+ ///
+ /// \param StartLoc Starting location of the directive kind.
+ /// \param EndLoc Ending location of the directive.
+ ///
+ OMPBarrierDirective(SourceLocation StartLoc, SourceLocation EndLoc)
+ : OMPExecutableDirective(this, OMPBarrierDirectiveClass, OMPD_barrier,
+ StartLoc, EndLoc, 0, 0) {}
+
+ /// \brief Build an empty directive.
+ ///
+ explicit OMPBarrierDirective()
+ : OMPExecutableDirective(this, OMPBarrierDirectiveClass, OMPD_barrier,
+ SourceLocation(), SourceLocation(), 0, 0) {}
+
+public:
+ /// \brief Creates directive.
+ ///
+ /// \param C AST context.
+ /// \param StartLoc Starting location of the directive kind.
+ /// \param EndLoc Ending Location of the directive.
+ ///
+ static OMPBarrierDirective *
+ Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc);
+
+ /// \brief Creates an empty directive.
+ ///
+ /// \param C AST context.
+ ///
+ static OMPBarrierDirective *CreateEmpty(const ASTContext &C, EmptyShell);
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == OMPBarrierDirectiveClass;
+ }
+};
+
+/// \brief This represents '#pragma omp taskwait' directive.
+///
+/// \code
+/// #pragma omp taskwait
+/// \endcode
+///
+class OMPTaskwaitDirective : public OMPExecutableDirective {
+ friend class ASTStmtReader;
+ /// \brief Build directive with the given start and end location.
+ ///
+ /// \param StartLoc Starting location of the directive kind.
+ /// \param EndLoc Ending location of the directive.
+ ///
+ OMPTaskwaitDirective(SourceLocation StartLoc, SourceLocation EndLoc)
+ : OMPExecutableDirective(this, OMPTaskwaitDirectiveClass, OMPD_taskwait,
+ StartLoc, EndLoc, 0, 0) {}
+
+ /// \brief Build an empty directive.
+ ///
+ explicit OMPTaskwaitDirective()
+ : OMPExecutableDirective(this, OMPTaskwaitDirectiveClass, OMPD_taskwait,
+ SourceLocation(), SourceLocation(), 0, 0) {}
+
+public:
+ /// \brief Creates directive.
+ ///
+ /// \param C AST context.
+ /// \param StartLoc Starting location of the directive kind.
+ /// \param EndLoc Ending Location of the directive.
+ ///
+ static OMPTaskwaitDirective *
+ Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc);
+
+ /// \brief Creates an empty directive.
+ ///
+ /// \param C AST context.
+ ///
+ static OMPTaskwaitDirective *CreateEmpty(const ASTContext &C, EmptyShell);
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == OMPTaskwaitDirectiveClass;
+ }
+};
+
+/// \brief This represents '#pragma omp taskgroup' directive.
+///
+/// \code
+/// #pragma omp taskgroup
+/// \endcode
+///
+class OMPTaskgroupDirective : public OMPExecutableDirective {
+ friend class ASTStmtReader;
+ /// \brief Build directive with the given start and end location.
+ ///
+ /// \param StartLoc Starting location of the directive kind.
+ /// \param EndLoc Ending location of the directive.
+ ///
+ OMPTaskgroupDirective(SourceLocation StartLoc, SourceLocation EndLoc)
+ : OMPExecutableDirective(this, OMPTaskgroupDirectiveClass, OMPD_taskgroup,
+ StartLoc, EndLoc, 0, 1) {}
+
+ /// \brief Build an empty directive.
+ ///
+ explicit OMPTaskgroupDirective()
+ : OMPExecutableDirective(this, OMPTaskgroupDirectiveClass, OMPD_taskgroup,
+ SourceLocation(), SourceLocation(), 0, 1) {}
+
+public:
+ /// \brief Creates directive.
+ ///
+ /// \param C AST context.
+ /// \param StartLoc Starting location of the directive kind.
+ /// \param EndLoc Ending Location of the directive.
+ /// \param AssociatedStmt Statement, associated with the directive.
+ ///
+ static OMPTaskgroupDirective *Create(const ASTContext &C,
+ SourceLocation StartLoc,
+ SourceLocation EndLoc,
+ Stmt *AssociatedStmt);
+
+ /// \brief Creates an empty directive.
+ ///
+ /// \param C AST context.
+ ///
+ static OMPTaskgroupDirective *CreateEmpty(const ASTContext &C, EmptyShell);
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == OMPTaskgroupDirectiveClass;
+ }
+};
+
+/// \brief This represents '#pragma omp flush' directive.
+///
+/// \code
+/// #pragma omp flush(a,b)
+/// \endcode
+/// In this example directive '#pragma omp flush' has 2 arguments- variables 'a'
+/// and 'b'.
+/// 'omp flush' directive does not have clauses but have an optional list of
+/// variables to flush. This list of variables is stored within some fake clause
+/// FlushClause.
+class OMPFlushDirective : public OMPExecutableDirective {
+ friend class ASTStmtReader;
+ /// \brief Build directive with the given start and end location.
+ ///
+ /// \param StartLoc Starting location of the directive kind.
+ /// \param EndLoc Ending location of the directive.
+ /// \param NumClauses Number of clauses.
+ ///
+ OMPFlushDirective(SourceLocation StartLoc, SourceLocation EndLoc,
+ unsigned NumClauses)
+ : OMPExecutableDirective(this, OMPFlushDirectiveClass, OMPD_flush,
+ StartLoc, EndLoc, NumClauses, 0) {}
+
+ /// \brief Build an empty directive.
+ ///
+ /// \param NumClauses Number of clauses.
+ ///
+ explicit OMPFlushDirective(unsigned NumClauses)
+ : OMPExecutableDirective(this, OMPFlushDirectiveClass, OMPD_flush,
+ SourceLocation(), SourceLocation(), NumClauses,
+ 0) {}
+
+public:
+ /// \brief Creates directive with a list of \a Clauses.
+ ///
+ /// \param C AST context.
+ /// \param StartLoc Starting location of the directive kind.
+ /// \param EndLoc Ending Location of the directive.
+ /// \param Clauses List of clauses (only single OMPFlushClause clause is
+ /// allowed).
+ ///
+ static OMPFlushDirective *Create(const ASTContext &C, SourceLocation StartLoc,
+ SourceLocation EndLoc,
+ ArrayRef<OMPClause *> Clauses);
+
+ /// \brief Creates an empty directive with the place for \a NumClauses
+ /// clauses.
+ ///
+ /// \param C AST context.
+ /// \param NumClauses Number of clauses.
+ ///
+ static OMPFlushDirective *CreateEmpty(const ASTContext &C,
+ unsigned NumClauses, EmptyShell);
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == OMPFlushDirectiveClass;
+ }
+};
+
+/// \brief This represents '#pragma omp ordered' directive.
+///
+/// \code
+/// #pragma omp ordered
+/// \endcode
+///
+class OMPOrderedDirective : public OMPExecutableDirective {
+ friend class ASTStmtReader;
+ /// \brief Build directive with the given start and end location.
+ ///
+ /// \param StartLoc Starting location of the directive kind.
+ /// \param EndLoc Ending location of the directive.
+ /// \param NumClauses Number of clauses.
+ ///
+ OMPOrderedDirective(SourceLocation StartLoc, SourceLocation EndLoc,
+ unsigned NumClauses)
+ : OMPExecutableDirective(this, OMPOrderedDirectiveClass, OMPD_ordered,
+ StartLoc, EndLoc, NumClauses, 1) {}
+
+ /// \brief Build an empty directive.
+ ///
+ /// \param NumClauses Number of clauses.
+ ///
+ explicit OMPOrderedDirective(unsigned NumClauses)
+ : OMPExecutableDirective(this, OMPOrderedDirectiveClass, OMPD_ordered,
+ SourceLocation(), SourceLocation(), NumClauses,
+ 1) {}
+
+public:
+ /// \brief Creates directive.
+ ///
+ /// \param C AST context.
+ /// \param StartLoc Starting location of the directive kind.
+ /// \param EndLoc Ending Location of the directive.
+ /// \param Clauses List of clauses.
+ /// \param AssociatedStmt Statement, associated with the directive.
+ ///
+ static OMPOrderedDirective *
+ Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
+ ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt);
+
+ /// \brief Creates an empty directive.
+ ///
+ /// \param C AST context.
+ /// \param NumClauses Number of clauses.
+ ///
+ static OMPOrderedDirective *CreateEmpty(const ASTContext &C,
+ unsigned NumClauses, EmptyShell);
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == OMPOrderedDirectiveClass;
+ }
+};
+
+/// \brief This represents '#pragma omp atomic' directive.
+///
+/// \code
+/// #pragma omp atomic capture
+/// \endcode
+/// In this example directive '#pragma omp atomic' has clause 'capture'.
+///
+class OMPAtomicDirective : public OMPExecutableDirective {
+ friend class ASTStmtReader;
+ /// \brief Used for 'atomic update' or 'atomic capture' constructs. They may
+ /// have atomic expressions of forms
+ /// \code
+ /// x = x binop expr;
+ /// x = expr binop x;
+ /// \endcode
+ /// This field is true for the first form of the expression and false for the
+ /// second. Required for correct codegen of non-associative operations (like
+ /// << or >>).
+ bool IsXLHSInRHSPart;
+ /// \brief Used for 'atomic update' or 'atomic capture' constructs. They may
+ /// have atomic expressions of forms
+ /// \code
+ /// v = x; <update x>;
+ /// <update x>; v = x;
+ /// \endcode
+ /// This field is true for the first(postfix) form of the expression and false
+ /// otherwise.
+ bool IsPostfixUpdate;
+
+ /// \brief Build directive with the given start and end location.
+ ///
+ /// \param StartLoc Starting location of the directive kind.
+ /// \param EndLoc Ending location of the directive.
+ /// \param NumClauses Number of clauses.
+ ///
+ OMPAtomicDirective(SourceLocation StartLoc, SourceLocation EndLoc,
+ unsigned NumClauses)
+ : OMPExecutableDirective(this, OMPAtomicDirectiveClass, OMPD_atomic,
+ StartLoc, EndLoc, NumClauses, 5),
+ IsXLHSInRHSPart(false), IsPostfixUpdate(false) {}
+
+ /// \brief Build an empty directive.
+ ///
+ /// \param NumClauses Number of clauses.
+ ///
+ explicit OMPAtomicDirective(unsigned NumClauses)
+ : OMPExecutableDirective(this, OMPAtomicDirectiveClass, OMPD_atomic,
+ SourceLocation(), SourceLocation(), NumClauses,
+ 5),
+ IsXLHSInRHSPart(false), IsPostfixUpdate(false) {}
+
+ /// \brief Set 'x' part of the associated expression/statement.
+ void setX(Expr *X) { *std::next(child_begin()) = X; }
+ /// \brief Set helper expression of the form
+ /// 'OpaqueValueExpr(x) binop OpaqueValueExpr(expr)' or
+ /// 'OpaqueValueExpr(expr) binop OpaqueValueExpr(x)'.
+ void setUpdateExpr(Expr *UE) { *std::next(child_begin(), 2) = UE; }
+ /// \brief Set 'v' part of the associated expression/statement.
+ void setV(Expr *V) { *std::next(child_begin(), 3) = V; }
+ /// \brief Set 'expr' part of the associated expression/statement.
+ void setExpr(Expr *E) { *std::next(child_begin(), 4) = E; }
+
+public:
+ /// \brief Creates directive with a list of \a Clauses and 'x', 'v' and 'expr'
+ /// parts of the atomic construct (see Section 2.12.6, atomic Construct, for
+ /// detailed description of 'x', 'v' and 'expr').
+ ///
+ /// \param C AST context.
+ /// \param StartLoc Starting location of the directive kind.
+ /// \param EndLoc Ending Location of the directive.
+ /// \param Clauses List of clauses.
+ /// \param AssociatedStmt Statement, associated with the directive.
+ /// \param X 'x' part of the associated expression/statement.
+ /// \param V 'v' part of the associated expression/statement.
+ /// \param E 'expr' part of the associated expression/statement.
+ /// \param UE Helper expression of the form
+ /// 'OpaqueValueExpr(x) binop OpaqueValueExpr(expr)' or
+ /// 'OpaqueValueExpr(expr) binop OpaqueValueExpr(x)'.
+ /// \param IsXLHSInRHSPart true if \a UE has the first form and false if the
+ /// second.
+ /// \param IsPostfixUpdate true if original value of 'x' must be stored in
+ /// 'v', not an updated one.
+ static OMPAtomicDirective *
+ Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
+ ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt, Expr *X, Expr *V,
+ Expr *E, Expr *UE, bool IsXLHSInRHSPart, bool IsPostfixUpdate);
+
+ /// \brief Creates an empty directive with the place for \a NumClauses
+ /// clauses.
+ ///
+ /// \param C AST context.
+ /// \param NumClauses Number of clauses.
+ ///
+ static OMPAtomicDirective *CreateEmpty(const ASTContext &C,
+ unsigned NumClauses, EmptyShell);
+
+ /// \brief Get 'x' part of the associated expression/statement.
+ Expr *getX() { return cast_or_null<Expr>(*std::next(child_begin())); }
+ const Expr *getX() const {
+ return cast_or_null<Expr>(*std::next(child_begin()));
+ }
+ /// \brief Get helper expression of the form
+ /// 'OpaqueValueExpr(x) binop OpaqueValueExpr(expr)' or
+ /// 'OpaqueValueExpr(expr) binop OpaqueValueExpr(x)'.
+ Expr *getUpdateExpr() {
+ return cast_or_null<Expr>(*std::next(child_begin(), 2));
+ }
+ const Expr *getUpdateExpr() const {
+ return cast_or_null<Expr>(*std::next(child_begin(), 2));
+ }
+ /// \brief Return true if helper update expression has form
+ /// 'OpaqueValueExpr(x) binop OpaqueValueExpr(expr)' and false if it has form
+ /// 'OpaqueValueExpr(expr) binop OpaqueValueExpr(x)'.
+ bool isXLHSInRHSPart() const { return IsXLHSInRHSPart; }
+ /// \brief Return true if 'v' expression must be updated to original value of
+ /// 'x', false if 'v' must be updated to the new value of 'x'.
+ bool isPostfixUpdate() const { return IsPostfixUpdate; }
+ /// \brief Get 'v' part of the associated expression/statement.
+ Expr *getV() { return cast_or_null<Expr>(*std::next(child_begin(), 3)); }
+ const Expr *getV() const {
+ return cast_or_null<Expr>(*std::next(child_begin(), 3));
+ }
+ /// \brief Get 'expr' part of the associated expression/statement.
+ Expr *getExpr() { return cast_or_null<Expr>(*std::next(child_begin(), 4)); }
+ const Expr *getExpr() const {
+ return cast_or_null<Expr>(*std::next(child_begin(), 4));
+ }
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == OMPAtomicDirectiveClass;
+ }
+};
+
+/// \brief This represents '#pragma omp target' directive.
+///
+/// \code
+/// #pragma omp target if(a)
+/// \endcode
+/// In this example directive '#pragma omp target' has clause 'if' with
+/// condition 'a'.
+///
+class OMPTargetDirective : public OMPExecutableDirective {
+ friend class ASTStmtReader;
+ /// \brief Build directive with the given start and end location.
+ ///
+ /// \param StartLoc Starting location of the directive kind.
+ /// \param EndLoc Ending location of the directive.
+ /// \param NumClauses Number of clauses.
+ ///
+ OMPTargetDirective(SourceLocation StartLoc, SourceLocation EndLoc,
+ unsigned NumClauses)
+ : OMPExecutableDirective(this, OMPTargetDirectiveClass, OMPD_target,
+ StartLoc, EndLoc, NumClauses, 1) {}
+
+ /// \brief Build an empty directive.
+ ///
+ /// \param NumClauses Number of clauses.
+ ///
+ explicit OMPTargetDirective(unsigned NumClauses)
+ : OMPExecutableDirective(this, OMPTargetDirectiveClass, OMPD_target,
+ SourceLocation(), SourceLocation(), NumClauses,
+ 1) {}
+
+public:
+ /// \brief Creates directive with a list of \a Clauses.
+ ///
+ /// \param C AST context.
+ /// \param StartLoc Starting location of the directive kind.
+ /// \param EndLoc Ending Location of the directive.
+ /// \param Clauses List of clauses.
+ /// \param AssociatedStmt Statement, associated with the directive.
+ ///
+ static OMPTargetDirective *
+ Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
+ ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt);
+
+ /// \brief Creates an empty directive with the place for \a NumClauses
+ /// clauses.
+ ///
+ /// \param C AST context.
+ /// \param NumClauses Number of clauses.
+ ///
+ static OMPTargetDirective *CreateEmpty(const ASTContext &C,
+ unsigned NumClauses, EmptyShell);
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == OMPTargetDirectiveClass;
+ }
+};
+
+/// \brief This represents '#pragma omp target data' directive.
+///
+/// \code
+/// #pragma omp target data device(0) if(a) map(b[:])
+/// \endcode
+/// In this example directive '#pragma omp target data' has clauses 'device'
+/// with the value '0', 'if' with condition 'a' and 'map' with array
+/// section 'b[:]'.
+///
+class OMPTargetDataDirective : public OMPExecutableDirective {
+ friend class ASTStmtReader;
+ /// \brief Build directive with the given start and end location.
+ ///
+ /// \param StartLoc Starting location of the directive kind.
+ /// \param EndLoc Ending Location of the directive.
+ /// \param NumClauses The number of clauses.
+ ///
+ OMPTargetDataDirective(SourceLocation StartLoc, SourceLocation EndLoc,
+ unsigned NumClauses)
+ : OMPExecutableDirective(this, OMPTargetDataDirectiveClass,
+ OMPD_target_data, StartLoc, EndLoc, NumClauses,
+ 1) {}
+
+ /// \brief Build an empty directive.
+ ///
+ /// \param NumClauses Number of clauses.
+ ///
+ explicit OMPTargetDataDirective(unsigned NumClauses)
+ : OMPExecutableDirective(this, OMPTargetDataDirectiveClass,
+ OMPD_target_data, SourceLocation(),
+ SourceLocation(), NumClauses, 1) {}
+
+public:
+ /// \brief Creates directive with a list of \a Clauses.
+ ///
+ /// \param C AST context.
+ /// \param StartLoc Starting location of the directive kind.
+ /// \param EndLoc Ending Location of the directive.
+ /// \param Clauses List of clauses.
+ /// \param AssociatedStmt Statement, associated with the directive.
+ ///
+ static OMPTargetDataDirective *
+ Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
+ ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt);
+
+ /// \brief Creates an empty directive with the place for \a N clauses.
+ ///
+ /// \param C AST context.
+ /// \param N The number of clauses.
+ ///
+ static OMPTargetDataDirective *CreateEmpty(const ASTContext &C, unsigned N,
+ EmptyShell);
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == OMPTargetDataDirectiveClass;
+ }
+};
+
+/// \brief This represents '#pragma omp teams' directive.
+///
+/// \code
+/// #pragma omp teams if(a)
+/// \endcode
+/// In this example directive '#pragma omp teams' has clause 'if' with
+/// condition 'a'.
+///
+class OMPTeamsDirective : public OMPExecutableDirective {
+ friend class ASTStmtReader;
+ /// \brief Build directive with the given start and end location.
+ ///
+ /// \param StartLoc Starting location of the directive kind.
+ /// \param EndLoc Ending location of the directive.
+ /// \param NumClauses Number of clauses.
+ ///
+ OMPTeamsDirective(SourceLocation StartLoc, SourceLocation EndLoc,
+ unsigned NumClauses)
+ : OMPExecutableDirective(this, OMPTeamsDirectiveClass, OMPD_teams,
+ StartLoc, EndLoc, NumClauses, 1) {}
+
+ /// \brief Build an empty directive.
+ ///
+ /// \param NumClauses Number of clauses.
+ ///
+ explicit OMPTeamsDirective(unsigned NumClauses)
+ : OMPExecutableDirective(this, OMPTeamsDirectiveClass, OMPD_teams,
+ SourceLocation(), SourceLocation(), NumClauses,
+ 1) {}
+
+public:
+ /// \brief Creates directive with a list of \a Clauses.
+ ///
+ /// \param C AST context.
+ /// \param StartLoc Starting location of the directive kind.
+ /// \param EndLoc Ending Location of the directive.
+ /// \param Clauses List of clauses.
+ /// \param AssociatedStmt Statement, associated with the directive.
+ ///
+ static OMPTeamsDirective *Create(const ASTContext &C, SourceLocation StartLoc,
+ SourceLocation EndLoc,
+ ArrayRef<OMPClause *> Clauses,
+ Stmt *AssociatedStmt);
+
+ /// \brief Creates an empty directive with the place for \a NumClauses
+ /// clauses.
+ ///
+ /// \param C AST context.
+ /// \param NumClauses Number of clauses.
+ ///
+ static OMPTeamsDirective *CreateEmpty(const ASTContext &C,
+ unsigned NumClauses, EmptyShell);
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == OMPTeamsDirectiveClass;
+ }
+};
+
+/// \brief This represents '#pragma omp cancellation point' directive.
+///
+/// \code
+/// #pragma omp cancellation point for
+/// \endcode
+///
+/// In this example a cancellation point is created for innermost 'for' region.
+class OMPCancellationPointDirective : public OMPExecutableDirective {
+ friend class ASTStmtReader;
+ OpenMPDirectiveKind CancelRegion;
+ /// \brief Build directive with the given start and end location.
+ ///
+ /// \param StartLoc Starting location of the directive kind.
+ /// \param EndLoc Ending location of the directive.
+ ///
+ OMPCancellationPointDirective(SourceLocation StartLoc, SourceLocation EndLoc)
+ : OMPExecutableDirective(this, OMPCancellationPointDirectiveClass,
+ OMPD_cancellation_point, StartLoc, EndLoc, 0, 0),
+ CancelRegion(OMPD_unknown) {}
+
+ /// \brief Build an empty directive.
+ ///
+ explicit OMPCancellationPointDirective()
+ : OMPExecutableDirective(this, OMPCancellationPointDirectiveClass,
+ OMPD_cancellation_point, SourceLocation(),
+ SourceLocation(), 0, 0),
+ CancelRegion(OMPD_unknown) {}
+
+ /// \brief Set cancel region for current cancellation point.
+ /// \param CR Cancellation region.
+ void setCancelRegion(OpenMPDirectiveKind CR) { CancelRegion = CR; }
+
+public:
+ /// \brief Creates directive.
+ ///
+ /// \param C AST context.
+ /// \param StartLoc Starting location of the directive kind.
+ /// \param EndLoc Ending Location of the directive.
+ ///
+ static OMPCancellationPointDirective *
+ Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
+ OpenMPDirectiveKind CancelRegion);
+
+ /// \brief Creates an empty directive.
+ ///
+ /// \param C AST context.
+ ///
+ static OMPCancellationPointDirective *CreateEmpty(const ASTContext &C,
+ EmptyShell);
+
+ /// \brief Get cancellation region for the current cancellation point.
+ OpenMPDirectiveKind getCancelRegion() const { return CancelRegion; }
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == OMPCancellationPointDirectiveClass;
+ }
+};
+
+/// \brief This represents '#pragma omp cancel' directive.
+///
+/// \code
+/// #pragma omp cancel for
+/// \endcode
+///
+/// In this example a cancel is created for innermost 'for' region.
+class OMPCancelDirective : public OMPExecutableDirective {
+ friend class ASTStmtReader;
+ OpenMPDirectiveKind CancelRegion;
+ /// \brief Build directive with the given start and end location.
+ ///
+ /// \param StartLoc Starting location of the directive kind.
+ /// \param EndLoc Ending location of the directive.
+ /// \param NumClauses Number of clauses.
+ ///
+ OMPCancelDirective(SourceLocation StartLoc, SourceLocation EndLoc,
+ unsigned NumClauses)
+ : OMPExecutableDirective(this, OMPCancelDirectiveClass, OMPD_cancel,
+ StartLoc, EndLoc, NumClauses, 0),
+ CancelRegion(OMPD_unknown) {}
+
+ /// \brief Build an empty directive.
+ ///
+ /// \param NumClauses Number of clauses.
+ explicit OMPCancelDirective(unsigned NumClauses)
+ : OMPExecutableDirective(this, OMPCancelDirectiveClass, OMPD_cancel,
+ SourceLocation(), SourceLocation(), NumClauses,
+ 0),
+ CancelRegion(OMPD_unknown) {}
+
+ /// \brief Set cancel region for current cancellation point.
+ /// \param CR Cancellation region.
+ void setCancelRegion(OpenMPDirectiveKind CR) { CancelRegion = CR; }
+
+public:
+ /// \brief Creates directive.
+ ///
+ /// \param C AST context.
+ /// \param StartLoc Starting location of the directive kind.
+ /// \param EndLoc Ending Location of the directive.
+ /// \param Clauses List of clauses.
+ ///
+ static OMPCancelDirective *
+ Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
+ ArrayRef<OMPClause *> Clauses, OpenMPDirectiveKind CancelRegion);
+
+ /// \brief Creates an empty directive.
+ ///
+ /// \param C AST context.
+ /// \param NumClauses Number of clauses.
+ ///
+ static OMPCancelDirective *CreateEmpty(const ASTContext &C,
+ unsigned NumClauses, EmptyShell);
+
+ /// \brief Get cancellation region for the current cancellation point.
+ OpenMPDirectiveKind getCancelRegion() const { return CancelRegion; }
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == OMPCancelDirectiveClass;
+ }
+};
+
+/// \brief This represents '#pragma omp taskloop' directive.
+///
+/// \code
+/// #pragma omp taskloop private(a,b) grainsize(val) num_tasks(num)
+/// \endcode
+/// In this example directive '#pragma omp taskloop' has clauses 'private'
+/// with the variables 'a' and 'b', 'grainsize' with expression 'val' and
+/// 'num_tasks' with expression 'num'.
+///
+class OMPTaskLoopDirective : public OMPLoopDirective {
+ friend class ASTStmtReader;
+ /// \brief Build directive with the given start and end location.
+ ///
+ /// \param StartLoc Starting location of the directive kind.
+ /// \param EndLoc Ending location of the directive.
+ /// \param CollapsedNum Number of collapsed nested loops.
+ /// \param NumClauses Number of clauses.
+ ///
+ OMPTaskLoopDirective(SourceLocation StartLoc, SourceLocation EndLoc,
+ unsigned CollapsedNum, unsigned NumClauses)
+ : OMPLoopDirective(this, OMPTaskLoopDirectiveClass, OMPD_taskloop,
+ StartLoc, EndLoc, CollapsedNum, NumClauses) {}
+
+ /// \brief Build an empty directive.
+ ///
+ /// \param CollapsedNum Number of collapsed nested loops.
+ /// \param NumClauses Number of clauses.
+ ///
+ explicit OMPTaskLoopDirective(unsigned CollapsedNum, unsigned NumClauses)
+ : OMPLoopDirective(this, OMPTaskLoopDirectiveClass, OMPD_taskloop,
+ SourceLocation(), SourceLocation(), CollapsedNum,
+ NumClauses) {}
+
+public:
+ /// \brief Creates directive with a list of \a Clauses.
+ ///
+ /// \param C AST context.
+ /// \param StartLoc Starting location of the directive kind.
+ /// \param EndLoc Ending Location of the directive.
+ /// \param CollapsedNum Number of collapsed loops.
+ /// \param Clauses List of clauses.
+ /// \param AssociatedStmt Statement, associated with the directive.
+ /// \param Exprs Helper expressions for CodeGen.
+ ///
+ static OMPTaskLoopDirective *
+ Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
+ unsigned CollapsedNum, ArrayRef<OMPClause *> Clauses,
+ Stmt *AssociatedStmt, const HelperExprs &Exprs);
+
+ /// \brief Creates an empty directive with the place
+ /// for \a NumClauses clauses.
+ ///
+ /// \param C AST context.
+ /// \param CollapsedNum Number of collapsed nested loops.
+ /// \param NumClauses Number of clauses.
+ ///
+ static OMPTaskLoopDirective *CreateEmpty(const ASTContext &C,
+ unsigned NumClauses,
+ unsigned CollapsedNum, EmptyShell);
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == OMPTaskLoopDirectiveClass;
+ }
+};
+
+/// \brief This represents '#pragma omp taskloop simd' directive.
+///
+/// \code
+/// #pragma omp taskloop simd private(a,b) grainsize(val) num_tasks(num)
+/// \endcode
+/// In this example directive '#pragma omp taskloop simd' has clauses 'private'
+/// with the variables 'a' and 'b', 'grainsize' with expression 'val' and
+/// 'num_tasks' with expression 'num'.
+///
+class OMPTaskLoopSimdDirective : public OMPLoopDirective {
+ friend class ASTStmtReader;
+ /// \brief Build directive with the given start and end location.
+ ///
+ /// \param StartLoc Starting location of the directive kind.
+ /// \param EndLoc Ending location of the directive.
+ /// \param CollapsedNum Number of collapsed nested loops.
+ /// \param NumClauses Number of clauses.
+ ///
+ OMPTaskLoopSimdDirective(SourceLocation StartLoc, SourceLocation EndLoc,
+ unsigned CollapsedNum, unsigned NumClauses)
+ : OMPLoopDirective(this, OMPTaskLoopSimdDirectiveClass,
+ OMPD_taskloop_simd, StartLoc, EndLoc, CollapsedNum,
+ NumClauses) {}
+
+ /// \brief Build an empty directive.
+ ///
+ /// \param CollapsedNum Number of collapsed nested loops.
+ /// \param NumClauses Number of clauses.
+ ///
+ explicit OMPTaskLoopSimdDirective(unsigned CollapsedNum, unsigned NumClauses)
+ : OMPLoopDirective(this, OMPTaskLoopSimdDirectiveClass,
+ OMPD_taskloop_simd, SourceLocation(), SourceLocation(),
+ CollapsedNum, NumClauses) {}
+
+public:
+ /// \brief Creates directive with a list of \a Clauses.
+ ///
+ /// \param C AST context.
+ /// \param StartLoc Starting location of the directive kind.
+ /// \param EndLoc Ending Location of the directive.
+ /// \param CollapsedNum Number of collapsed loops.
+ /// \param Clauses List of clauses.
+ /// \param AssociatedStmt Statement, associated with the directive.
+ /// \param Exprs Helper expressions for CodeGen.
+ ///
+ static OMPTaskLoopSimdDirective *
+ Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
+ unsigned CollapsedNum, ArrayRef<OMPClause *> Clauses,
+ Stmt *AssociatedStmt, const HelperExprs &Exprs);
+
+ /// \brief Creates an empty directive with the place
+ /// for \a NumClauses clauses.
+ ///
+ /// \param C AST context.
+ /// \param CollapsedNum Number of collapsed nested loops.
+ /// \param NumClauses Number of clauses.
+ ///
+ static OMPTaskLoopSimdDirective *CreateEmpty(const ASTContext &C,
+ unsigned NumClauses,
+ unsigned CollapsedNum,
+ EmptyShell);
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == OMPTaskLoopSimdDirectiveClass;
+ }
+};
+
+/// \brief This represents '#pragma omp distribute' directive.
+///
+/// \code
+/// #pragma omp distribute private(a,b)
+/// \endcode
+/// In this example directive '#pragma omp distribute' has clauses 'private'
+/// with the variables 'a' and 'b'
+///
+class OMPDistributeDirective : public OMPLoopDirective {
+ friend class ASTStmtReader;
+
+ /// \brief Build directive with the given start and end location.
+ ///
+ /// \param StartLoc Starting location of the directive kind.
+ /// \param EndLoc Ending location of the directive.
+ /// \param CollapsedNum Number of collapsed nested loops.
+ /// \param NumClauses Number of clauses.
+ ///
+ OMPDistributeDirective(SourceLocation StartLoc, SourceLocation EndLoc,
+ unsigned CollapsedNum, unsigned NumClauses)
+ : OMPLoopDirective(this, OMPDistributeDirectiveClass, OMPD_distribute,
+ StartLoc, EndLoc, CollapsedNum, NumClauses)
+ {}
+
+ /// \brief Build an empty directive.
+ ///
+ /// \param CollapsedNum Number of collapsed nested loops.
+ /// \param NumClauses Number of clauses.
+ ///
+ explicit OMPDistributeDirective(unsigned CollapsedNum, unsigned NumClauses)
+ : OMPLoopDirective(this, OMPDistributeDirectiveClass, OMPD_distribute,
+ SourceLocation(), SourceLocation(), CollapsedNum,
+ NumClauses)
+ {}
+
+public:
+ /// \brief Creates directive with a list of \a Clauses.
+ ///
+ /// \param C AST context.
+ /// \param StartLoc Starting location of the directive kind.
+ /// \param EndLoc Ending Location of the directive.
+ /// \param CollapsedNum Number of collapsed loops.
+ /// \param Clauses List of clauses.
+ /// \param AssociatedStmt Statement, associated with the directive.
+ /// \param Exprs Helper expressions for CodeGen.
+ ///
+ static OMPDistributeDirective *
+ Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
+ unsigned CollapsedNum, ArrayRef<OMPClause *> Clauses,
+ Stmt *AssociatedStmt, const HelperExprs &Exprs);
+
+ /// \brief Creates an empty directive with the place
+ /// for \a NumClauses clauses.
+ ///
+ /// \param C AST context.
+ /// \param CollapsedNum Number of collapsed nested loops.
+ /// \param NumClauses Number of clauses.
+ ///
+ static OMPDistributeDirective *CreateEmpty(const ASTContext &C,
+ unsigned NumClauses,
+ unsigned CollapsedNum, EmptyShell);
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == OMPDistributeDirectiveClass;
+ }
+};
+
+} // 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..df4a2d8
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/AST/StmtVisitor.h
@@ -0,0 +1,227 @@
+//===--- 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 and ConstStmtVisitor interfaces.
+//
+//===----------------------------------------------------------------------===//
+
+#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/ExprOpenMP.h"
+#include "clang/AST/StmtCXX.h"
+#include "clang/AST/StmtObjC.h"
+#include "clang/AST/StmtOpenMP.h"
+
+namespace clang {
+
+template <typename T> struct make_ptr { typedef T *type; };
+template <typename T> struct make_const_ptr { typedef const T *type; };
+
+/// StmtVisitorBase - This class implements a simple visitor for Stmt
+/// subclasses. Since Expr derives from Stmt, this also includes support for
+/// visiting Exprs.
+template<template <typename> class Ptr, typename ImplClass, typename RetTy=void>
+class StmtVisitorBase {
+public:
+
+#define PTR(CLASS) typename Ptr<CLASS>::type
+#define DISPATCH(NAME, CLASS) \
+ return static_cast<ImplClass*>(this)->Visit ## NAME(static_cast<PTR(CLASS)>(S))
+
+ RetTy Visit(PTR(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 (PTR(BinaryOperator) BinOp = dyn_cast<BinaryOperator>(S)) {
+ switch (BinOp->getOpcode()) {
+ 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 (PTR(UnaryOperator) UnOp = dyn_cast<UnaryOperator>(S)) {
+ switch (UnOp->getOpcode()) {
+ 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);
+ case UO_Coawait: DISPATCH(UnaryCoawait, UnaryOperator);
+ }
+ }
+
+ // Top switch stmt: dispatch to VisitFooStmt for each FooStmt.
+ switch (S->getStmtClass()) {
+ default: llvm_unreachable("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(PTR(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(PTR(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(PTR(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(PTR(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) UNARYOP_FALLBACK(Coawait)
+#undef UNARYOP_FALLBACK
+
+ // Base case, ignore it. :)
+ RetTy VisitStmt(PTR(Stmt) Node) { return RetTy(); }
+
+#undef PTR
+#undef DISPATCH
+};
+
+/// StmtVisitor - This class implements a simple visitor for Stmt subclasses.
+/// Since Expr derives from Stmt, this also includes support for visiting Exprs.
+///
+/// This class does not preserve constness of Stmt pointers (see also
+/// ConstStmtVisitor).
+template<typename ImplClass, typename RetTy=void>
+class StmtVisitor
+ : public StmtVisitorBase<make_ptr, ImplClass, RetTy> {};
+
+/// ConstStmtVisitor - This class implements a simple visitor for Stmt
+/// subclasses. Since Expr derives from Stmt, this also includes support for
+/// visiting Exprs.
+///
+/// This class preserves constness of Stmt pointers (see also StmtVisitor).
+template<typename ImplClass, typename RetTy=void>
+class ConstStmtVisitor
+ : public StmtVisitorBase<make_const_ptr, ImplClass, RetTy> {};
+
+/// \brief This class implements a simple visitor for OMPClause
+/// subclasses.
+template<class ImplClass, template <typename> class Ptr, typename RetTy>
+class OMPClauseVisitorBase {
+public:
+#define PTR(CLASS) typename Ptr<CLASS>::type
+#define DISPATCH(CLASS) \
+ return static_cast<ImplClass*>(this)->Visit##CLASS(static_cast<PTR(CLASS)>(S))
+
+#define OPENMP_CLAUSE(Name, Class) \
+ RetTy Visit ## Class (PTR(Class) S) { DISPATCH(Class); }
+#include "clang/Basic/OpenMPKinds.def"
+
+ RetTy Visit(PTR(OMPClause) S) {
+ // Top switch clause: visit each OMPClause.
+ switch (S->getClauseKind()) {
+ default: llvm_unreachable("Unknown clause kind!");
+#define OPENMP_CLAUSE(Name, Class) \
+ case OMPC_ ## Name : return Visit ## Class(static_cast<PTR(Class)>(S));
+#include "clang/Basic/OpenMPKinds.def"
+ }
+ }
+ // Base case, ignore it. :)
+ RetTy VisitOMPClause(PTR(OMPClause) Node) { return RetTy(); }
+#undef PTR
+#undef DISPATCH
+};
+
+template<class ImplClass, typename RetTy = void>
+class OMPClauseVisitor :
+ public OMPClauseVisitorBase <ImplClass, make_ptr, RetTy> {};
+template<class ImplClass, typename RetTy = void>
+class ConstOMPClauseVisitor :
+ public OMPClauseVisitorBase <ImplClass, make_const_ptr, RetTy> {};
+
+} // 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..f87171a
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/AST/TemplateBase.h
@@ -0,0 +1,661 @@
+//===-- 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 "clang/AST/TemplateName.h"
+#include "clang/AST/Type.h"
+#include "llvm/ADT/APSInt.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/iterator_range.h"
+#include "llvm/Support/Compiler.h"
+#include "llvm/Support/ErrorHandling.h"
+#include "llvm/Support/TrailingObjects.h"
+
+namespace llvm {
+ class FoldingSetNodeID;
+}
+
+namespace clang {
+
+class DiagnosticBuilder;
+class Expr;
+struct PrintingPolicy;
+class TypeSourceInfo;
+class ValueDecl;
+
+/// \brief Represents a template argument.
+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.
+ Type,
+ /// The template argument is a declaration that was provided for a pointer,
+ /// reference, or pointer to member non-type template parameter.
+ Declaration,
+ /// The template argument is a null pointer or null pointer to member that
+ /// was provided for a non-type template parameter.
+ NullPtr,
+ /// 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 an expression, and we've not resolved it to one
+ /// of the other forms yet, either because it's dependent or because we're
+ /// representing a non-canonical template argument (for instance, in a
+ /// TemplateSpecializationType). Also used to represent a non-dependent
+ /// __uuidof expression (a Microsoft extension).
+ 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.
+
+ struct DA {
+ unsigned Kind;
+ void *QT;
+ ValueDecl *D;
+ };
+ struct I {
+ unsigned Kind;
+ // We store a decomposed APSInt with the data allocated by ASTContext if
+ // BitWidth > 64. The memory may be shared between multiple
+ // TemplateArgument instances.
+ unsigned BitWidth : 31;
+ unsigned IsUnsigned : 1;
+ union {
+ uint64_t VAL; ///< Used to store the <= 64 bits integer value.
+ const uint64_t *pVal; ///< Used to store the >64 bits integer value.
+ };
+ void *Type;
+ };
+ struct A {
+ unsigned Kind;
+ unsigned NumArgs;
+ const TemplateArgument *Args;
+ };
+ struct TA {
+ unsigned Kind;
+ unsigned NumExpansions;
+ void *Name;
+ };
+ struct TV {
+ unsigned Kind;
+ uintptr_t V;
+ };
+ union {
+ struct DA DeclArg;
+ struct I Integer;
+ struct A Args;
+ struct TA TemplateArg;
+ struct TV TypeOrValue;
+ };
+
+ TemplateArgument(TemplateName, bool) = delete;
+
+public:
+ /// \brief Construct an empty, invalid template argument.
+ TemplateArgument() {
+ TypeOrValue.Kind = Null;
+ TypeOrValue.V = 0;
+ }
+
+ /// \brief Construct a template type argument.
+ TemplateArgument(QualType T, bool isNullPtr = false) {
+ TypeOrValue.Kind = isNullPtr ? NullPtr : Type;
+ TypeOrValue.V = 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(ValueDecl *D, QualType QT) {
+ assert(D && "Expected decl");
+ DeclArg.Kind = Declaration;
+ DeclArg.QT = QT.getAsOpaquePtr();
+ DeclArg.D = D;
+ }
+
+ /// \brief Construct an integral constant template argument. The memory to
+ /// store the value is allocated with Ctx.
+ TemplateArgument(ASTContext &Ctx, const llvm::APSInt &Value, QualType Type);
+
+ /// \brief Construct an integral constant template argument with the same
+ /// value as Other but a different type.
+ TemplateArgument(const TemplateArgument &Other, QualType Type) {
+ Integer = Other.Integer;
+ 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) {
+ TemplateArg.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, Optional<unsigned> NumExpansions) {
+ TemplateArg.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) {
+ TypeOrValue.Kind = Expression;
+ TypeOrValue.V = 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.
+ explicit TemplateArgument(ArrayRef<TemplateArgument> Args) {
+ this->Args.Kind = Pack;
+ this->Args.Args = Args.data();
+ this->Args.NumArgs = Args.size();
+ }
+
+ static TemplateArgument getEmptyPack() { return TemplateArgument(None); }
+
+ /// \brief Create a new template argument pack by copying the given set of
+ /// template arguments.
+ static TemplateArgument CreatePackCopy(ASTContext &Context,
+ ArrayRef<TemplateArgument> Args);
+
+ /// \brief Return the kind of stored template argument.
+ ArgKind getKind() const { return (ArgKind)TypeOrValue.Kind; }
+
+ /// \brief Determine whether this template argument has no value.
+ bool isNull() const { return getKind() == Null; }
+
+ /// \brief Whether this template argument is dependent on a template
+ /// parameter such that its result can change from one instantiation to
+ /// another.
+ bool isDependent() const;
+
+ /// \brief Whether this template argument is dependent on a template
+ /// parameter.
+ bool isInstantiationDependent() 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 type for a type template argument.
+ QualType getAsType() const {
+ assert(getKind() == Type && "Unexpected kind");
+ return QualType::getFromOpaquePtr(reinterpret_cast<void*>(TypeOrValue.V));
+ }
+
+ /// \brief Retrieve the declaration for a declaration non-type
+ /// template argument.
+ ValueDecl *getAsDecl() const {
+ assert(getKind() == Declaration && "Unexpected kind");
+ return DeclArg.D;
+ }
+
+ QualType getParamTypeForDecl() const {
+ assert(getKind() == Declaration && "Unexpected kind");
+ return QualType::getFromOpaquePtr(DeclArg.QT);
+ }
+
+ /// \brief Retrieve the type for null non-type template argument.
+ QualType getNullPtrType() const {
+ assert(getKind() == NullPtr && "Unexpected kind");
+ return QualType::getFromOpaquePtr(reinterpret_cast<void*>(TypeOrValue.V));
+ }
+
+ /// \brief Retrieve the template name for a template name argument.
+ TemplateName getAsTemplate() const {
+ assert(getKind() == Template && "Unexpected kind");
+ 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 {
+ assert((getKind() == Template || getKind() == TemplateExpansion) &&
+ "Unexpected kind");
+
+ return TemplateName::getFromVoidPointer(TemplateArg.Name);
+ }
+
+ /// \brief Retrieve the number of expansions that a template template argument
+ /// expansion will produce, if known.
+ Optional<unsigned> getNumTemplateExpansions() const;
+
+ /// \brief Retrieve the template argument as an integral value.
+ // FIXME: Provide a way to read the integral data without copying the value.
+ llvm::APSInt getAsIntegral() const {
+ assert(getKind() == Integral && "Unexpected kind");
+ using namespace llvm;
+ if (Integer.BitWidth <= 64)
+ return APSInt(APInt(Integer.BitWidth, Integer.VAL), Integer.IsUnsigned);
+
+ unsigned NumWords = APInt::getNumWords(Integer.BitWidth);
+ return APSInt(APInt(Integer.BitWidth, makeArrayRef(Integer.pVal, NumWords)),
+ Integer.IsUnsigned);
+ }
+
+ /// \brief Retrieve the type of the integral value.
+ QualType getIntegralType() const {
+ assert(getKind() == Integral && "Unexpected kind");
+ return QualType::getFromOpaquePtr(Integer.Type);
+ }
+
+ void setIntegralType(QualType T) {
+ assert(getKind() == Integral && "Unexpected kind");
+ Integer.Type = T.getAsOpaquePtr();
+ }
+
+ /// \brief Retrieve the template argument as an expression.
+ Expr *getAsExpr() const {
+ assert(getKind() == Expression && "Unexpected kind");
+ return reinterpret_cast<Expr *>(TypeOrValue.V);
+ }
+
+ /// \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(getKind() == Pack);
+ return Args.Args;
+ }
+
+ /// \brief Iterator referencing one past the last argument of a template
+ /// argument pack.
+ pack_iterator pack_end() const {
+ assert(getKind() == Pack);
+ return Args.Args + Args.NumArgs;
+ }
+
+ /// \brief Iterator range referencing all of the elements of a template
+ /// argument pack.
+ llvm::iterator_range<pack_iterator> pack_elements() const {
+ return llvm::make_range(pack_begin(), pack_end());
+ }
+
+ /// \brief The number of template arguments in the given template argument
+ /// pack.
+ unsigned pack_size() const {
+ assert(getKind() == Pack);
+ return Args.NumArgs;
+ }
+
+ /// \brief Return the array of arguments in this template argument pack.
+ ArrayRef<TemplateArgument> getPackAsArray() const {
+ assert(getKind() == Pack);
+ return llvm::makeArrayRef(Args.Args, Args.NumArgs);
+ }
+
+ /// \brief 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.
+ TemplateArgument getPackExpansionPattern() const;
+
+ /// \brief Print this template argument to the given output stream.
+ void print(const PrintingPolicy &Policy, 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:
+
+ struct T {
+ // FIXME: We'd like to just use the qualifier in the TemplateName,
+ // but template arguments get canonicalized too quickly.
+ NestedNameSpecifier *Qualifier;
+ void *QualifierLocData;
+ unsigned TemplateNameLoc;
+ unsigned EllipsisLoc;
+ };
+
+ union {
+ struct T Template;
+ Expr *Expression;
+ TypeSourceInfo *Declarator;
+ };
+
+public:
+ TemplateArgumentLocInfo();
+
+ TemplateArgumentLocInfo(TypeSourceInfo *TInfo) : Declarator(TInfo) {}
+
+ TemplateArgumentLocInfo(Expr *E) : Expression(E) {}
+
+ TemplateArgumentLocInfo(NestedNameSpecifierLoc QualifierLoc,
+ SourceLocation TemplateNameLoc,
+ SourceLocation EllipsisLoc)
+ {
+ Template.Qualifier = QualifierLoc.getNestedNameSpecifier();
+ Template.QualifierLocData = QualifierLoc.getOpaqueData();
+ Template.TemplateNameLoc = TemplateNameLoc.getRawEncoding();
+ Template.EllipsisLoc = EllipsisLoc.getRawEncoding();
+ }
+
+ TypeSourceInfo *getAsTypeSourceInfo() const {
+ return Declarator;
+ }
+
+ Expr *getAsExpr() const {
+ return Expression;
+ }
+
+ NestedNameSpecifierLoc getTemplateQualifierLoc() const {
+ return NestedNameSpecifierLoc(Template.Qualifier,
+ Template.QualifierLocData);
+ }
+
+ 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,
+ NestedNameSpecifierLoc QualifierLoc,
+ SourceLocation TemplateNameLoc,
+ SourceLocation EllipsisLoc = SourceLocation())
+ : Argument(Argument), LocInfo(QualifierLoc, 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 LLVM_READONLY;
+
+ 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();
+ }
+
+ Expr *getSourceNullPtrExpression() const {
+ assert(Argument.getKind() == TemplateArgument::NullPtr);
+ return LocInfo.getAsExpr();
+ }
+
+ Expr *getSourceIntegralExpression() const {
+ assert(Argument.getKind() == TemplateArgument::Integral);
+ return LocInfo.getAsExpr();
+ }
+
+ NestedNameSpecifierLoc getTemplateQualifierLoc() const {
+ assert(Argument.getKind() == TemplateArgument::Template ||
+ Argument.getKind() == TemplateArgument::TemplateExpansion);
+ return LocInfo.getTemplateQualifierLoc();
+ }
+
+ 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();
+ }
+};
+
+/// A convenient class for passing around template argument
+/// information. Designed to be passed by reference.
+class TemplateArgumentListInfo {
+ SmallVector<TemplateArgumentLoc, 8> Arguments;
+ SourceLocation LAngleLoc;
+ SourceLocation RAngleLoc;
+
+ // This can leak if used in an AST node, use ASTTemplateArgumentListInfo
+ // instead.
+ void *operator new(size_t bytes, ASTContext &C) = delete;
+
+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();
+ }
+
+ llvm::ArrayRef<TemplateArgumentLoc> arguments() const {
+ return Arguments;
+ }
+
+ const TemplateArgumentLoc &operator[](unsigned I) const {
+ return Arguments[I];
+ }
+
+ TemplateArgumentLoc &operator[](unsigned I) {
+ return Arguments[I];
+ }
+
+ void addArgument(const TemplateArgumentLoc &Loc) {
+ Arguments.push_back(Loc);
+ }
+};
+
+/// \brief Represents an explicit template argument list in C++, e.g.,
+/// the "<int>" in "sort<int>".
+/// This is safe to be used inside an AST node, in contrast with
+/// TemplateArgumentListInfo.
+struct ASTTemplateArgumentListInfo final
+ : private llvm::TrailingObjects<ASTTemplateArgumentListInfo,
+ TemplateArgumentLoc> {
+private:
+ friend TrailingObjects;
+
+ ASTTemplateArgumentListInfo(const TemplateArgumentListInfo &List);
+
+public:
+ /// \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.
+ unsigned NumTemplateArgs;
+
+ /// \brief Retrieve the template arguments
+ const TemplateArgumentLoc *getTemplateArgs() const {
+ return getTrailingObjects<TemplateArgumentLoc>();
+ }
+
+ const TemplateArgumentLoc &operator[](unsigned I) const {
+ return getTemplateArgs()[I];
+ }
+
+ static const ASTTemplateArgumentListInfo *
+ Create(ASTContext &C, const TemplateArgumentListInfo &List);
+};
+
+/// \brief Represents an explicit template argument list in C++, e.g.,
+/// the "<int>" in "sort<int>".
+///
+/// It is intended to be used as a trailing object on AST nodes, and
+/// as such, doesn't contain the array of TemplateArgumentLoc itself,
+/// but expects the containing object to also provide storage for
+/// that.
+struct LLVM_ALIGNAS(LLVM_PTR_SIZE) ASTTemplateKWAndArgsInfo {
+ /// \brief The source location of the left angle bracket ('<').
+ SourceLocation LAngleLoc;
+
+ /// \brief The source location of the right angle bracket ('>').
+ SourceLocation RAngleLoc;
+
+ /// \brief The source location of the template keyword; this is used
+ /// as part of the representation of qualified identifiers, such as
+ /// S<T>::template apply<T>. Will be empty if this expression does
+ /// not have a template keyword.
+ SourceLocation TemplateKWLoc;
+
+ /// \brief The number of template arguments in TemplateArgs.
+ unsigned NumTemplateArgs;
+
+ void initializeFrom(SourceLocation TemplateKWLoc,
+ const TemplateArgumentListInfo &List,
+ TemplateArgumentLoc *OutArgArray);
+ void initializeFrom(SourceLocation TemplateKWLoc,
+ const TemplateArgumentListInfo &List,
+ TemplateArgumentLoc *OutArgArray, bool &Dependent,
+ bool &InstantiationDependent,
+ bool &ContainsUnexpandedParameterPack);
+ void initializeFrom(SourceLocation TemplateKWLoc);
+
+ void copyInto(const TemplateArgumentLoc *ArgArray,
+ TemplateArgumentListInfo &List) const;
+};
+
+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..3e10d2f
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/AST/TemplateName.h
@@ -0,0 +1,533 @@
+//===--- 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 "clang/Basic/LLVM.h"
+#include "llvm/ADT/FoldingSet.h"
+#include "llvm/ADT/PointerUnion.h"
+
+namespace clang {
+
+class ASTContext;
+class DependentTemplateName;
+class DiagnosticBuilder;
+class IdentifierInfo;
+class NamedDecl;
+class NestedNameSpecifier;
+enum OverloadedOperatorKind : int;
+class OverloadedTemplateStorage;
+struct PrintingPolicy;
+class QualifiedTemplateName;
+class SubstTemplateTemplateParmPackStorage;
+class SubstTemplateTemplateParmStorage;
+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:
+ enum Kind {
+ Overloaded,
+ SubstTemplateTemplateParm,
+ SubstTemplateTemplateParmPack
+ };
+
+ struct BitsTag {
+ /// \brief A Kind.
+ unsigned Kind : 2;
+
+ /// \brief The number of stored templates or template arguments,
+ /// depending on which subclass we have.
+ unsigned Size : 30;
+ };
+
+ union {
+ struct BitsTag Bits;
+ void *PointerAlignment;
+ };
+
+ UncommonTemplateNameStorage(Kind kind, unsigned size) {
+ Bits.Kind = kind;
+ Bits.Size = size;
+ }
+
+public:
+ unsigned size() const { return Bits.Size; }
+
+ OverloadedTemplateStorage *getAsOverloadedStorage() {
+ return Bits.Kind == Overloaded
+ ? reinterpret_cast<OverloadedTemplateStorage *>(this)
+ : nullptr;
+ }
+
+ SubstTemplateTemplateParmStorage *getAsSubstTemplateTemplateParm() {
+ return Bits.Kind == SubstTemplateTemplateParm
+ ? reinterpret_cast<SubstTemplateTemplateParmStorage *>(this)
+ : nullptr;
+ }
+
+ SubstTemplateTemplateParmPackStorage *getAsSubstTemplateTemplateParmPack() {
+ return Bits.Kind == SubstTemplateTemplateParmPack
+ ? reinterpret_cast<SubstTemplateTemplateParmPackStorage *>(this)
+ : nullptr;
+ }
+};
+
+/// \brief A structure for storing the information associated with an
+/// overloaded template name.
+class OverloadedTemplateStorage : public UncommonTemplateNameStorage {
+ friend class ASTContext;
+
+ OverloadedTemplateStorage(unsigned size)
+ : UncommonTemplateNameStorage(Overloaded, size) { }
+
+ 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
+{
+ TemplateTemplateParmDecl *Parameter;
+ const TemplateArgument *Arguments;
+
+public:
+ SubstTemplateTemplateParmPackStorage(TemplateTemplateParmDecl *Parameter,
+ unsigned Size,
+ const TemplateArgument *Arguments)
+ : UncommonTemplateNameStorage(SubstTemplateTemplateParmPack, Size),
+ 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, ASTContext &Context);
+
+ 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);
+
+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 that has been substituted
+ /// for some other template name.
+ SubstTemplateTemplateParm,
+ /// \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);
+ explicit TemplateName(OverloadedTemplateStorage *Storage);
+ explicit TemplateName(SubstTemplateTemplateParmStorage *Storage);
+ explicit TemplateName(SubstTemplateTemplateParmPackStorage *Storage);
+ explicit TemplateName(QualifiedTemplateName *Qual);
+ explicit TemplateName(DependentTemplateName *Dep);
+
+ /// \brief Determine whether this template name is NULL.
+ bool isNull() const;
+
+ // \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;
+
+ /// \brief Retrieve the substituted template template parameter, if
+ /// known.
+ ///
+ /// \returns The storage for the substituted template template parameter,
+ /// if known. Otherwise, returns NULL.
+ SubstTemplateTemplateParmStorage *getAsSubstTemplateTemplateParm() const;
+
+ /// \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;
+
+ /// \brief Retrieve the underlying qualified template name
+ /// structure, if any.
+ QualifiedTemplateName *getAsQualifiedTemplateName() const;
+
+ /// \brief Retrieve the underlying dependent template name
+ /// structure, if any.
+ DependentTemplateName *getAsDependentTemplateName() const;
+
+ TemplateName getUnderlying() const;
+
+ /// \brief Determines whether this is a dependent template name.
+ bool isDependent() const;
+
+ /// \brief Determines whether this is a template name that somehow
+ /// depends on a template parameter.
+ bool isInstantiationDependent() 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(raw_ostream &OS, const PrintingPolicy &Policy,
+ bool SuppressNNS = false) const;
+
+ /// \brief Debugging aid that dumps the template name.
+ void dump(raw_ostream &OS) 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 A structure for storing the information associated with a
+/// substituted template template parameter.
+class SubstTemplateTemplateParmStorage
+ : public UncommonTemplateNameStorage, public llvm::FoldingSetNode {
+ friend class ASTContext;
+
+ TemplateTemplateParmDecl *Parameter;
+ TemplateName Replacement;
+
+ SubstTemplateTemplateParmStorage(TemplateTemplateParmDecl *parameter,
+ TemplateName replacement)
+ : UncommonTemplateNameStorage(SubstTemplateTemplateParm, 0),
+ Parameter(parameter), Replacement(replacement) {}
+
+public:
+ TemplateTemplateParmDecl *getParameter() const { return Parameter; }
+ TemplateName getReplacement() const { return Replacement; }
+
+ void Profile(llvm::FoldingSetNodeID &ID);
+
+ static void Profile(llvm::FoldingSetNodeID &ID,
+ TemplateTemplateParmDecl *parameter,
+ TemplateName replacement);
+};
+
+inline TemplateName TemplateName::getUnderlying() const {
+ if (SubstTemplateTemplateParmStorage *subst
+ = getAsSubstTemplateTemplateParm())
+ return subst->getReplacement().getUnderlying();
+ return *this;
+}
+
+/// \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..0c08130
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/AST/Type.h
@@ -0,0 +1,5683 @@
+//===--- 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.
+//
+//===----------------------------------------------------------------------===//
+/// \file
+/// \brief C Language Family Type Representation
+///
+/// This file defines the clang::Type interface and subclasses, used to
+/// represent types for languages in the C family.
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_AST_TYPE_H
+#define LLVM_CLANG_AST_TYPE_H
+
+#include "clang/AST/NestedNameSpecifier.h"
+#include "clang/AST/TemplateName.h"
+#include "clang/Basic/AddressSpaces.h"
+#include "clang/Basic/Diagnostic.h"
+#include "clang/Basic/ExceptionSpecificationType.h"
+#include "clang/Basic/LLVM.h"
+#include "clang/Basic/Linkage.h"
+#include "clang/Basic/PartialDiagnostic.h"
+#include "clang/Basic/Specifiers.h"
+#include "clang/Basic/Visibility.h"
+#include "llvm/ADT/APInt.h"
+#include "llvm/ADT/FoldingSet.h"
+#include "llvm/ADT/Optional.h"
+#include "llvm/ADT/PointerIntPair.h"
+#include "llvm/ADT/PointerUnion.h"
+#include "llvm/ADT/Twine.h"
+#include "llvm/ADT/iterator_range.h"
+#include "llvm/Support/ErrorHandling.h"
+
+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 TypedefNameDecl;
+ class TemplateDecl;
+ class TemplateTypeParmDecl;
+ class NonTypeTemplateParmDecl;
+ class TemplateTemplateParmDecl;
+ class TagDecl;
+ class RecordDecl;
+ class CXXRecordDecl;
+ class EnumDecl;
+ class FieldDecl;
+ class FunctionDecl;
+ 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"
+
+/// 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 ObjCLifetime {
+ /// There is no lifetime qualification on this type.
+ OCL_None,
+
+ /// This object can be modified without requiring retains or
+ /// releases.
+ OCL_ExplicitNone,
+
+ /// Assigning into this object requires the old value to be
+ /// released and the new value to be retained. The timing of the
+ /// release of the old value is inexact: it may be moved to
+ /// immediately after the last known point where the value is
+ /// live.
+ OCL_Strong,
+
+ /// Reading or writing from this object requires a barrier call.
+ OCL_Weak,
+
+ /// Assigning into this object requires a lifetime extension.
+ OCL_Autoreleasing
+ };
+
+ 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) {}
+
+ /// Returns the common set of qualifiers while removing them from
+ /// the given sets.
+ static Qualifiers removeCommonQualifiers(Qualifiers &L, Qualifiers &R) {
+ // If both are only CVR-qualified, bit operations are sufficient.
+ if (!(L.Mask & ~CVRMask) && !(R.Mask & ~CVRMask)) {
+ Qualifiers Q;
+ Q.Mask = L.Mask & R.Mask;
+ L.Mask &= ~Q.Mask;
+ R.Mask &= ~Q.Mask;
+ return Q;
+ }
+
+ Qualifiers Q;
+ unsigned CommonCRV = L.getCVRQualifiers() & R.getCVRQualifiers();
+ Q.addCVRQualifiers(CommonCRV);
+ L.removeCVRQualifiers(CommonCRV);
+ R.removeCVRQualifiers(CommonCRV);
+
+ if (L.getObjCGCAttr() == R.getObjCGCAttr()) {
+ Q.setObjCGCAttr(L.getObjCGCAttr());
+ L.removeObjCGCAttr();
+ R.removeObjCGCAttr();
+ }
+
+ if (L.getObjCLifetime() == R.getObjCLifetime()) {
+ Q.setObjCLifetime(L.getObjCLifetime());
+ L.removeObjCLifetime();
+ R.removeObjCLifetime();
+ }
+
+ if (L.getAddressSpace() == R.getAddressSpace()) {
+ Q.setAddressSpace(L.getAddressSpace());
+ L.removeAddressSpace();
+ R.removeAddressSpace();
+ }
+ return Q;
+ }
+
+ 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);
+ }
+ Qualifiers withoutObjCGCAttr() const {
+ Qualifiers qs = *this;
+ qs.removeObjCGCAttr();
+ return qs;
+ }
+ Qualifiers withoutObjCLifetime() const {
+ Qualifiers qs = *this;
+ qs.removeObjCLifetime();
+ return qs;
+ }
+
+ bool hasObjCLifetime() const { return Mask & LifetimeMask; }
+ ObjCLifetime getObjCLifetime() const {
+ return ObjCLifetime((Mask & LifetimeMask) >> LifetimeShift);
+ }
+ void setObjCLifetime(ObjCLifetime type) {
+ Mask = (Mask & ~LifetimeMask) | (type << LifetimeShift);
+ }
+ void removeObjCLifetime() { setObjCLifetime(OCL_None); }
+ void addObjCLifetime(ObjCLifetime type) {
+ assert(type);
+ assert(!hasObjCLifetime());
+ Mask |= (type << LifetimeShift);
+ }
+
+ /// True if the lifetime is neither None or ExplicitNone.
+ bool hasNonTrivialObjCLifetime() const {
+ ObjCLifetime lifetime = getObjCLifetime();
+ return (lifetime > OCL_ExplicitNone);
+ }
+
+ /// True if the lifetime is either strong or weak.
+ bool hasStrongOrWeakObjCLifetime() const {
+ ObjCLifetime lifetime = getObjCLifetime();
+ return (lifetime == OCL_Strong || lifetime == OCL_Weak);
+ }
+
+ 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;
+ }
+
+ /// 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;
+ }
+
+ /// Return true if the set contains any qualifiers.
+ bool hasQualifiers() const { return Mask; }
+ bool empty() const { return !Mask; }
+
+ /// 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());
+ if (Q.hasObjCLifetime())
+ addObjCLifetime(Q.getObjCLifetime());
+ }
+ }
+
+ /// \brief Remove the qualifiers from the given set from this set.
+ void removeQualifiers(Qualifiers Q) {
+ // If the other set doesn't have any non-boolean qualifiers, just
+ // bit-and the inverse in.
+ if (!(Q.Mask & ~CVRMask))
+ Mask &= ~Q.Mask;
+ else {
+ Mask &= ~(Q.Mask & CVRMask);
+ if (getObjCGCAttr() == Q.getObjCGCAttr())
+ removeObjCGCAttr();
+ if (getObjCLifetime() == Q.getObjCLifetime())
+ removeObjCLifetime();
+ if (getAddressSpace() == Q.getAddressSpace())
+ removeAddressSpace();
+ }
+ }
+
+ /// 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());
+ assert(getObjCLifetime() == qs.getObjCLifetime() ||
+ !hasObjCLifetime() || !qs.hasObjCLifetime());
+ Mask |= qs.Mask;
+ }
+
+ /// Returns true if this address space is a superset of the other one.
+ /// OpenCL v2.0 defines conversion rules (OpenCLC v2.0 s6.5.5) and notion of
+ /// overlapping address spaces.
+ /// CL1.1 or CL1.2:
+ /// every address space is a superset of itself.
+ /// CL2.0 adds:
+ /// __generic is a superset of any address space except for __constant.
+ bool isAddressSpaceSupersetOf(Qualifiers other) const {
+ return
+ // Address spaces must match exactly.
+ getAddressSpace() == other.getAddressSpace() ||
+ // Otherwise in OpenCLC v2.0 s6.5.5: every address space except
+ // for __constant can be used as __generic.
+ (getAddressSpace() == LangAS::opencl_generic &&
+ other.getAddressSpace() != LangAS::opencl_constant);
+ }
+
+ /// 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 {
+ return isAddressSpaceSupersetOf(other) &&
+ // ObjC GC qualifiers can match, be added, or be removed, but can't
+ // be changed.
+ (getObjCGCAttr() == other.getObjCGCAttr() || !hasObjCGCAttr() ||
+ !other.hasObjCGCAttr()) &&
+ // ObjC lifetime qualifiers must match exactly.
+ getObjCLifetime() == other.getObjCLifetime() &&
+ // CVR qualifiers may subset.
+ (((Mask & CVRMask) | (other.Mask & CVRMask)) == (Mask & CVRMask));
+ }
+
+ /// \brief Determines if these qualifiers compatibly include another set of
+ /// qualifiers from the narrow perspective of Objective-C ARC lifetime.
+ ///
+ /// One set of Objective-C lifetime qualifiers compatibly includes the other
+ /// if the lifetime qualifiers match, or if both are non-__weak and the
+ /// including set also contains the 'const' qualifier, or both are non-__weak
+ /// and one is None (which can only happen in non-ARC modes).
+ bool compatiblyIncludesObjCLifetime(Qualifiers other) const {
+ if (getObjCLifetime() == other.getObjCLifetime())
+ return true;
+
+ if (getObjCLifetime() == OCL_Weak || other.getObjCLifetime() == OCL_Weak)
+ return false;
+
+ if (getObjCLifetime() == OCL_None || other.getObjCLifetime() == OCL_None)
+ return true;
+
+ return hasConst();
+ }
+
+ /// \brief Determine whether this set of qualifiers is a strict superset of
+ /// another set of qualifiers, not considering qualifier compatibility.
+ bool isStrictSupersetOf(Qualifiers Other) const;
+
+ bool operator==(Qualifiers Other) const { return Mask == Other.Mask; }
+ bool operator!=(Qualifiers Other) const { return Mask != Other.Mask; }
+
+ explicit 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) {
+ removeQualifiers(R);
+ 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;
+
+ bool isEmptyWhenPrinted(const PrintingPolicy &Policy) const;
+ void print(raw_ostream &OS, const PrintingPolicy &Policy,
+ bool appendSpaceIfNonEmpty = false) const;
+
+ void Profile(llvm::FoldingSetNodeID &ID) const {
+ ID.AddInteger(Mask);
+ }
+
+private:
+
+ // bits: |0 1 2|3 .. 4|5 .. 7|8 ... 31|
+ // |C R V|GCAttr|Lifetime|AddressSpace|
+ uint32_t Mask;
+
+ static const uint32_t GCAttrMask = 0x18;
+ static const uint32_t GCAttrShift = 3;
+ static const uint32_t LifetimeMask = 0xE0;
+ static const uint32_t LifetimeShift = 5;
+ static const uint32_t AddressSpaceMask = ~(CVRMask|GCAttrMask|LifetimeMask);
+ static const uint32_t AddressSpaceShift = 8;
+};
+
+/// A std::pair-like structure for storing a qualified type split
+/// into its local qualifiers and its locally-unqualified type.
+struct SplitQualType {
+ /// The locally-unqualified type.
+ const Type *Ty;
+
+ /// The local qualifiers.
+ Qualifiers Quals;
+
+ SplitQualType() : Ty(nullptr), Quals() {}
+ SplitQualType(const Type *ty, Qualifiers qs) : Ty(ty), Quals(qs) {}
+
+ SplitQualType getSingleStepDesugaredType() const; // end of this file
+
+ // Make std::tie work.
+ std::pair<const Type *,Qualifiers> asPair() const {
+ return std::pair<const Type *, Qualifiers>(Ty, Quals);
+ }
+
+ friend bool operator==(SplitQualType a, SplitQualType b) {
+ return a.Ty == b.Ty && a.Quals == b.Quals;
+ }
+ friend bool operator!=(SplitQualType a, SplitQualType b) {
+ return a.Ty != b.Ty || a.Quals != b.Quals;
+ }
+};
+
+/// The kind of type we are substituting Objective-C type arguments into.
+///
+/// The kind of substitution affects the replacement of type parameters when
+/// no concrete type information is provided, e.g., when dealing with an
+/// unspecialized type.
+enum class ObjCSubstitutionContext {
+ /// An ordinary type.
+ Ordinary,
+ /// The result type of a method or function.
+ Result,
+ /// The parameter type of a method or function.
+ Parameter,
+ /// The type of a property.
+ Property,
+ /// The superclass of a type.
+ Superclass,
+};
+
+/// A (possibly-)qualified type.
+///
+/// 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 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;
+
+ /// Retrieves a pointer to the name of the base type.
+ const IdentifierInfo *getBaseTypeIdentifier() 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;
+
+ /// 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);
+ }
+
+ /// \brief Determine whether this is a Plain Old Data (POD) type (C++ 3.9p10).
+ bool isPODType(ASTContext &Context) const;
+
+ /// Return true if this is a POD type according to the rules of the C++98
+ /// standard, regardless of the current compilation's language.
+ bool isCXX98PODType(ASTContext &Context) const;
+
+ /// Return true if this is a POD type according to the more relaxed rules
+ /// of the C++11 standard, regardless of the current compilation's language.
+ /// (C++0x [basic.types]p9)
+ bool isCXX11PODType(ASTContext &Context) const;
+
+ /// Return true if this is a trivial type per (C++0x [basic.types]p9)
+ bool isTrivialType(ASTContext &Context) const;
+
+ /// Return true if this is a trivially copyable type (C++0x [basic.types]p9)
+ bool isTriviallyCopyableType(ASTContext &Context) const;
+
+ // Don't promise in the API that anything besides 'const' can be
+ // easily added.
+
+ /// Add the `const` type qualifier to this QualType.
+ void addConst() {
+ addFastQualifiers(Qualifiers::Const);
+ }
+ QualType withConst() const {
+ return withFastQualifiers(Qualifiers::Const);
+ }
+
+ /// Add the `volatile` type qualifier to this QualType.
+ void addVolatile() {
+ addFastQualifiers(Qualifiers::Volatile);
+ }
+ QualType withVolatile() const {
+ return withFastQualifiers(Qualifiers::Volatile);
+ }
+
+ /// Add the `restrict` qualifier to this QualType.
+ void addRestrict() {
+ addFastQualifiers(Qualifiers::Restrict);
+ }
+ QualType withRestrict() const {
+ return withFastQualifiers(Qualifiers::Restrict);
+ }
+
+ QualType withCVRQualifiers(unsigned CVR) const {
+ return withFastQualifiers(CVR);
+ }
+
+ 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 sugar for an array
+ /// type. To strip qualifiers even from within a sugared array type, use
+ /// ASTContext::getUnqualifiedArrayType.
+ inline QualType getUnqualifiedType() const;
+
+ /// 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 sugar for an array
+ /// type. To strip qualifiers even from within a sugared array type, use
+ /// ASTContext::getUnqualifiedArrayType.
+ inline SplitQualType getSplitUnqualifiedType() const;
+
+ /// \brief Determine whether this type is more qualified than the other
+ /// given type, requiring exact equality for non-CVR qualifiers.
+ bool isMoreQualifiedThan(QualType Other) const;
+
+ /// \brief Determine whether this type is at least as qualified as the other
+ /// given type, requiring exact equality for non-CVR qualifiers.
+ 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(const ASTContext &Context) const;
+
+ /// 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);
+ }
+
+ /// \brief Return the specified type with one level of "sugar" removed from
+ /// the type.
+ ///
+ /// This routine takes off the first typedef, typeof, etc. If the outer level
+ /// of the type is already concrete, it returns it unmodified.
+ QualType getSingleStepDesugaredType(const ASTContext &Context) const {
+ return getSingleStepDesugaredTypeImpl(*this, Context);
+ }
+
+ /// Returns the specified type after dropping any
+ /// outer-level parentheses.
+ QualType IgnoreParens() const {
+ if (isa<ParenType>(*this))
+ return QualType::IgnoreParens(*this);
+ return *this;
+ }
+
+ /// 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.Ty, split.Quals);
+ }
+ static std::string getAsString(const Type *ty, Qualifiers qs);
+
+ std::string getAsString(const PrintingPolicy &Policy) const;
+
+ void print(raw_ostream &OS, const PrintingPolicy &Policy,
+ const Twine &PlaceHolder = Twine()) const {
+ print(split(), OS, Policy, PlaceHolder);
+ }
+ static void print(SplitQualType split, raw_ostream &OS,
+ const PrintingPolicy &policy, const Twine &PlaceHolder) {
+ return print(split.Ty, split.Quals, OS, policy, PlaceHolder);
+ }
+ static void print(const Type *ty, Qualifiers qs,
+ raw_ostream &OS, const PrintingPolicy &policy,
+ const Twine &PlaceHolder);
+
+ 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.Ty, split.Quals, out, policy);
+ }
+ static void getAsStringInternal(const Type *ty, Qualifiers qs,
+ std::string &out,
+ const PrintingPolicy &policy);
+
+ class StreamedQualTypeHelper {
+ const QualType &T;
+ const PrintingPolicy &Policy;
+ const Twine &PlaceHolder;
+ public:
+ StreamedQualTypeHelper(const QualType &T, const PrintingPolicy &Policy,
+ const Twine &PlaceHolder)
+ : T(T), Policy(Policy), PlaceHolder(PlaceHolder) { }
+
+ friend raw_ostream &operator<<(raw_ostream &OS,
+ const StreamedQualTypeHelper &SQT) {
+ SQT.T.print(OS, SQT.Policy, SQT.PlaceHolder);
+ return OS;
+ }
+ };
+
+ StreamedQualTypeHelper stream(const PrintingPolicy &Policy,
+ const Twine &PlaceHolder = Twine()) const {
+ return StreamedQualTypeHelper(*this, Policy, PlaceHolder);
+ }
+
+ void dump(const char *s) const;
+ void dump() const;
+
+ void Profile(llvm::FoldingSetNodeID &ID) const {
+ ID.AddPointer(getAsOpaquePtr());
+ }
+
+ /// Return the address space of this type.
+ inline unsigned getAddressSpace() const;
+
+ /// Returns gc attribute of this type.
+ inline Qualifiers::GC getObjCGCAttr() const;
+
+ /// true when Type is objc's weak.
+ bool isObjCGCWeak() const {
+ return getObjCGCAttr() == Qualifiers::Weak;
+ }
+
+ /// true when Type is objc's strong.
+ bool isObjCGCStrong() const {
+ return getObjCGCAttr() == Qualifiers::Strong;
+ }
+
+ /// Returns lifetime attribute of this type.
+ Qualifiers::ObjCLifetime getObjCLifetime() const {
+ return getQualifiers().getObjCLifetime();
+ }
+
+ bool hasNonTrivialObjCLifetime() const {
+ return getQualifiers().hasNonTrivialObjCLifetime();
+ }
+
+ bool hasStrongOrWeakObjCLifetime() const {
+ return getQualifiers().hasStrongOrWeakObjCLifetime();
+ }
+
+ enum DestructionKind {
+ DK_none,
+ DK_cxx_destructor,
+ DK_objc_strong_lifetime,
+ DK_objc_weak_lifetime
+ };
+
+ /// Returns a nonzero value 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);
+ }
+
+ /// Determine whether expressions of the given type are forbidden
+ /// from being lvalues in C.
+ ///
+ /// The expression types that are forbidden to be lvalues 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.
+ bool isCForbiddenLValueType() const;
+
+ /// Substitute type arguments for the Objective-C type parameters used in the
+ /// subject type.
+ ///
+ /// \param ctx ASTContext in which the type exists.
+ ///
+ /// \param typeArgs The type arguments that will be substituted for the
+ /// Objective-C type parameters in the subject type, which are generally
+ /// computed via \c Type::getObjCSubstitutions. If empty, the type
+ /// parameters will be replaced with their bounds or id/Class, as appropriate
+ /// for the context.
+ ///
+ /// \param context The context in which the subject type was written.
+ ///
+ /// \returns the resulting type.
+ QualType substObjCTypeArgs(ASTContext &ctx,
+ ArrayRef<QualType> typeArgs,
+ ObjCSubstitutionContext context) const;
+
+ /// Substitute type arguments from an object type for the Objective-C type
+ /// parameters used in the subject type.
+ ///
+ /// This operation combines the computation of type arguments for
+ /// substitution (\c Type::getObjCSubstitutions) with the actual process of
+ /// substitution (\c QualType::substObjCTypeArgs) for the convenience of
+ /// callers that need to perform a single substitution in isolation.
+ ///
+ /// \param objectType The type of the object whose member type we're
+ /// substituting into. For example, this might be the receiver of a message
+ /// or the base of a property access.
+ ///
+ /// \param dc The declaration context from which the subject type was
+ /// retrieved, which indicates (for example) which type parameters should
+ /// be substituted.
+ ///
+ /// \param context The context in which the subject type was written.
+ ///
+ /// \returns the subject type after replacing all of the Objective-C type
+ /// parameters with their corresponding arguments.
+ QualType substObjCMemberType(QualType objectType,
+ const DeclContext *dc,
+ ObjCSubstitutionContext context) const;
+
+ /// Strip Objective-C "__kindof" types from the given type.
+ QualType stripObjCKindOfType(const ASTContext &ctx) const;
+
+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 getSingleStepDesugaredTypeImpl(QualType type,
+ const ASTContext &C);
+ 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< ::clang::QualType> {
+ typedef const ::clang::Type *SimpleType;
+ static SimpleType getSimplifiedValue(::clang::QualType Val) {
+ return Val.getTypePtr();
+ }
+};
+
+// 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;
+};
+
+/// 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.
+
+ /// 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 hasObjCLifetime() const { return Quals.hasObjCLifetime(); }
+ Qualifiers::ObjCLifetime getObjCLifetime() const {
+ return Quals.getObjCLifetime();
+ }
+
+ 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);
+ }
+};
+
+/// The kind of C++11 ref-qualifier associated with a function type.
+/// This 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
+};
+
+/// Which keyword(s) were used to create an AutoType.
+enum class AutoTypeKeyword {
+ /// \brief auto
+ Auto,
+ /// \brief decltype(auto)
+ DecltypeAuto,
+ /// \brief __auto_type (GNU extension)
+ GNUAutoType
+};
+
+/// 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 &) = delete;
+ void operator=(const Type &) = delete;
+
+ /// 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;
+
+ /// Whether this type is a dependent type (C++ [temp.dep.type]).
+ unsigned Dependent : 1;
+
+ /// Whether this type somehow involves a template parameter, even
+ /// if the resolution of the type does not depend on a template parameter.
+ unsigned InstantiationDependent : 1;
+
+ /// 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++11 variadic templates).
+ unsigned ContainsUnexpandedParameterPack : 1;
+
+ /// \brief True if the cache (i.e. the bitfields here starting with
+ /// 'Cache') is valid.
+ mutable unsigned CacheValid : 1;
+
+ /// \brief Linkage of this type.
+ mutable unsigned CachedLinkage : 3;
+
+ /// \brief Whether this type involves and local or unnamed types.
+ mutable unsigned CachedLocalOrUnnamed : 1;
+
+ /// \brief Whether this type comes from an AST file.
+ mutable unsigned FromAST : 1;
+
+ bool isCacheValid() const {
+ return CacheValid;
+ }
+ 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 = 18 };
+
+protected:
+ // These classes allow subclasses to somewhat cleanly pack bitfields
+ // into Type.
+
+ class ArrayTypeBitfields {
+ friend class ArrayType;
+
+ unsigned : NumTypeBits;
+
+ /// CVR qualifiers from declarations like
+ /// 'int X[static restrict 4]'. For function parameters only.
+ unsigned IndexTypeQuals : 3;
+
+ /// 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;
+ friend class FunctionProtoType;
+
+ unsigned : NumTypeBits;
+
+ /// Extra information which affects how the function is called, like
+ /// regparm and the calling convention.
+ unsigned ExtInfo : 9;
+
+ /// 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;
+
+ /// The number of type arguments stored directly on this object type.
+ unsigned NumTypeArgs : 7;
+
+ /// The number of protocols stored directly on this object type.
+ unsigned NumProtocols : 6;
+
+ /// Whether this is a "kindof" type.
+ unsigned IsKindOf : 1;
+ };
+ static_assert(NumTypeBits + 7 + 6 + 1 <= 32, "Does not fit in an unsigned");
+
+ 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;
+
+ /// The kind of vector, either a generic vector type or some
+ /// target-specific vector type such as for AltiVec or Neon.
+ unsigned VecKind : 3;
+
+ /// The number of elements in the vector.
+ unsigned NumElements : 29 - NumTypeBits;
+
+ enum { MaxNumElements = (1 << (29 - NumTypeBits)) - 1 };
+ };
+
+ class AttributedTypeBitfields {
+ friend class AttributedType;
+
+ unsigned : NumTypeBits;
+
+ /// An AttributedType::Kind
+ unsigned AttrKind : 32 - NumTypeBits;
+ };
+
+ class AutoTypeBitfields {
+ friend class AutoType;
+
+ unsigned : NumTypeBits;
+
+ /// Was this placeholder type spelled as 'auto', 'decltype(auto)',
+ /// or '__auto_type'? AutoTypeKeyword value.
+ unsigned Keyword : 2;
+ };
+
+ union {
+ TypeBitfields TypeBits;
+ ArrayTypeBitfields ArrayTypeBits;
+ AttributedTypeBitfields AttributedTypeBits;
+ AutoTypeBitfields AutoTypeBits;
+ 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 InstantiationDependent, bool VariablyModified,
+ bool ContainsUnexpandedParameterPack)
+ : ExtQualsTypeCommonBase(this,
+ canon.isNull() ? QualType(this_(), 0) : canon) {
+ TypeBits.TC = tc;
+ TypeBits.Dependent = Dependent;
+ TypeBits.InstantiationDependent = Dependent || InstantiationDependent;
+ TypeBits.VariablyModified = VariablyModified;
+ TypeBits.ContainsUnexpandedParameterPack = ContainsUnexpandedParameterPack;
+ TypeBits.CacheValid = false;
+ TypeBits.CachedLocalOrUnnamed = false;
+ TypeBits.CachedLinkage = NoLinkage;
+ TypeBits.FromAST = false;
+ }
+ friend class ASTContext;
+
+ void setDependent(bool D = true) {
+ TypeBits.Dependent = D;
+ if (D)
+ TypeBits.InstantiationDependent = true;
+ }
+ void setInstantiationDependent(bool D = true) {
+ TypeBits.InstantiationDependent = 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);
+ }
+
+ /// Pull a single level of sugar off of this locally-unqualified type.
+ /// Users should generally prefer SplitQualType::getSingleStepDesugaredType()
+ /// or QualType::getSingleStepDesugaredType(const ASTContext&).
+ QualType getLocallyUnqualifiedSingleStepDesugaredType() const;
+
+ /// Types are partitioned into 3 broad categories (C99 6.2.5p1):
+ /// object types, function types, and incomplete types.
+
+ /// 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.
+ ///
+ /// \brief Def If non-null, and the type refers to some kind of declaration
+ /// that can be completed (such as a C struct, C++ class, or Objective-C
+ /// class), will be set to the declaration.
+ bool isIncompleteType(NamedDecl **Def = nullptr) const;
+
+ /// 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();
+ }
+
+ /// Return true if this is a literal type
+ /// (C++11 [basic.types]p10)
+ bool isLiteralType(const ASTContext &Ctx) const;
+
+ /// Test if this type is a standard-layout type.
+ /// (C++0x [basic.type]p9)
+ bool isStandardLayoutType() const;
+
+ /// Helper methods to distinguish type categories. All type predicates
+ /// operate on the canonical type, ignoring typedefs and qualifiers.
+
+ /// Returns true if the type is a builtin type.
+ bool isBuiltinType() const;
+
+ /// Test for a particular builtin type.
+ bool isSpecificBuiltinType(unsigned K) const;
+
+ /// 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;
+ const BuiltinType *getAsPlaceholderType() const;
+
+ /// Test for a specific placeholder type.
+ bool isSpecificPlaceholderType(unsigned K) const;
+
+ /// Test for a placeholder type other than Overload; see
+ /// BuiltinType::isNonOverloadPlaceholderType.
+ bool isNonOverloadPlaceholderType() 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 isChar16Type() const;
+ bool isChar32Type() const;
+ bool isAnyCharacterType() const;
+ bool isIntegralType(ASTContext &Ctx) const;
+
+ /// Determine whether this type is an integral or enumeration type.
+ bool isIntegralOrEnumerationType() const;
+ /// 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 isHalfType() const; // OpenCL 6.1.1.1, NEON (IEEE 754-2008 half)
+ 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 isScalarType() const; // C99 6.2.5p21 (arithmetic + pointers)
+ bool isAggregateType() const;
+ bool isFundamentalType() const;
+ bool isCompoundType() 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 isObjCBoxableRecordType() const;
+ bool isInterfaceType() 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 ObjC object
+ bool isObjCRetainableType() const; // ObjC object or block pointer
+ bool isObjCLifetimeType() const; // (array of)* retainable type
+ bool isObjCIndirectLifetimeType() const; // (pointer to)* lifetime type
+ bool isObjCNSObjectType() const; // __attribute__((NSObject))
+ bool isObjCIndependentClassType() const; // __attribute__((objc_independent_class))
+ // 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 isObjCInertUnsafeUnretainedType() const;
+
+ /// Whether the type is Objective-C 'id' or a __kindof type of an
+ /// object type, e.g., __kindof NSView * or __kindof id
+ /// <NSCopying>.
+ ///
+ /// \param bound Will be set to the bound on non-id subtype types,
+ /// which will be (possibly specialized) Objective-C class type, or
+ /// null for 'id.
+ bool isObjCIdOrObjectKindOfType(const ASTContext &ctx,
+ const ObjCObjectType *&bound) const;
+
+ bool isObjCClassType() const; // Class
+
+ /// Whether the type is Objective-C 'Class' or a __kindof type of an
+ /// Class type, e.g., __kindof Class <NSCopying>.
+ ///
+ /// Unlike \c isObjCIdOrObjectKindOfType, there is no relevant bound
+ /// here because Objective-C's type system cannot express "a class
+ /// object for a subclass of NSFoo".
+ bool isObjCClassOrClassKindOfType() const;
+
+ bool isBlockCompatibleObjCPointerType(ASTContext &ctx) const;
+ bool isObjCSelType() const; // Class
+ bool isObjCBuiltinType() const; // 'id' or 'Class'
+ bool isObjCARCBridgableType() const;
+ bool isCARCBridgableType() const;
+ bool isTemplateTypeParmType() const; // C++ template type parameter
+ bool isNullPtrType() const; // C++0x nullptr_t
+ bool isAtomicType() const; // C11 _Atomic()
+
+ bool isImage1dT() const; // OpenCL image1d_t
+ bool isImage1dArrayT() const; // OpenCL image1d_array_t
+ bool isImage1dBufferT() const; // OpenCL image1d_buffer_t
+ bool isImage2dT() const; // OpenCL image2d_t
+ bool isImage2dArrayT() const; // OpenCL image2d_array_t
+ bool isImage2dDepthT() const; // OpenCL image_2d_depth_t
+ bool isImage2dArrayDepthT() const; // OpenCL image_2d_array_depth_t
+ bool isImage2dMSAAT() const; // OpenCL image_2d_msaa_t
+ bool isImage2dArrayMSAAT() const; // OpenCL image_2d_array_msaa_t
+ bool isImage2dMSAATDepth() const; // OpenCL image_2d_msaa_depth_t
+ bool isImage2dArrayMSAATDepth() const; // OpenCL image_2d_array_msaa_depth_t
+ bool isImage3dT() const; // OpenCL image3d_t
+
+ bool isImageType() const; // Any OpenCL image type
+
+ bool isSamplerT() const; // OpenCL sampler_t
+ bool isEventT() const; // OpenCL event_t
+ bool isClkEventT() const; // OpenCL clk_event_t
+ bool isQueueT() const; // OpenCL queue_t
+ bool isNDRangeT() const; // OpenCL ndrange_t
+ bool isReserveIDT() const; // OpenCL reserve_id_t
+
+ bool isOpenCLSpecificType() const; // Any OpenCL specific type
+
+ /// Determines if this type, which must satisfy
+ /// isObjCLifetimeType(), is implicitly __unsafe_unretained rather
+ /// than implicitly __strong.
+ bool isObjCARCImplicitlyUnretainedType() const;
+
+ /// Return the implicit lifetime for this type, which must not be dependent.
+ Qualifiers::ObjCLifetime getObjCARCImplicitLifetime() const;
+
+ enum ScalarTypeKind {
+ STK_CPointer,
+ STK_BlockPointer,
+ STK_ObjCObjectPointer,
+ STK_MemberPointer,
+ STK_Bool,
+ STK_Integral,
+ STK_Floating,
+ STK_IntegralComplex,
+ STK_FloatingComplex
+ };
+ /// Given that this is a scalar type, classify it.
+ ScalarTypeKind getScalarTypeKind() const;
+
+ /// 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 Determine whether this type is an instantiation-dependent type,
+ /// meaning that the type involves a template parameter (even if the
+ /// definition does not actually depend on the type substituted for that
+ /// template parameter).
+ bool isInstantiationDependentType() const {
+ return TypeBits.InstantiationDependent;
+ }
+
+ /// \brief Determine whether this type is an undeduced type, meaning that
+ /// it somehow involves a C++11 'auto' type which has not yet been deduced.
+ bool isUndeducedType() const;
+
+ /// \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;
+
+ bool canDecayToPointerType() const;
+
+ /// 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;
+
+ /// 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.
+ const ObjCObjectType *getAsObjCInterfaceType() const;
+ // 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 ObjCObjectPointerType *getAsObjCQualifiedClassType() const;
+ const ObjCObjectType *getAsObjCQualifiedInterfaceType() 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 Retrieves the TagDecl that this type refers to, either
+ /// because the type is a TagType or because it is the injected-class-name
+ /// type of a class template or class template partial specialization.
+ TagDecl *getAsTagDecl() const;
+
+ /// If this is a pointer or reference to a RecordType, return the
+ /// CXXRecordDecl that that type refers to.
+ ///
+ /// If this is not a pointer or reference, or the type being pointed to does
+ /// not refer to a CXXRecordDecl, returns NULL.
+ const CXXRecordDecl *getPointeeCXXRecordDecl() const;
+
+ /// 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;
+
+ /// Get the base element type of this type, potentially discarding type
+ /// qualifiers. This should never be used when type qualifiers
+ /// are meaningful.
+ const Type *getBaseElementTypeUnsafe() const;
+
+ /// If this is an array type, return the element type of the array,
+ /// potentially with type qualifiers missing.
+ /// This should never be used when type qualifiers are meaningful.
+ const Type *getArrayElementTypeNoTypeQual() const;
+
+ /// If this is a pointer, ObjC object pointer, or block
+ /// pointer, this returns the respective pointee.
+ QualType getPointeeType() const;
+
+ /// 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
+
+ /// Return true if this is an integer type that is
+ /// signed, according to C99 6.2.5p4 [char, signed char, short, int, long..],
+ /// or an enum decl which has a signed representation.
+ bool isSignedIntegerType() const;
+
+ /// Return true if this is an integer type that is
+ /// unsigned, according to C99 6.2.5p6 [which returns true for _Bool],
+ /// or an enum decl which has an unsigned representation.
+ bool isUnsignedIntegerType() const;
+
+ /// Determines whether this is an integer type that is signed or an
+ /// enumeration types whose underlying type is a signed integer type.
+ bool isSignedIntegerOrEnumerationType() const;
+
+ /// Determines whether this is an integer type that is unsigned or an
+ /// enumeration types whose underlying type is a unsigned integer type.
+ bool isUnsignedIntegerOrEnumerationType() const;
+
+ /// 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;
+
+ /// Returns true if this type can be represented by some
+ /// set of type specifiers.
+ bool isSpecifierType() const;
+
+ /// Determine the linkage of this type.
+ Linkage getLinkage() const;
+
+ /// Determine the visibility of this type.
+ Visibility getVisibility() const {
+ return getLinkageAndVisibility().getVisibility();
+ }
+
+ /// Return true if the visibility was explicitly set is the code.
+ bool isVisibilityExplicit() const {
+ return getLinkageAndVisibility().isVisibilityExplicit();
+ }
+
+ /// Determine the linkage and visibility of this type.
+ LinkageInfo getLinkageAndVisibility() const;
+
+ /// True if the computed linkage is valid. Used for consistency
+ /// checking. Should always return true.
+ bool isLinkageValid() const;
+
+ /// Determine the nullability of the given type.
+ ///
+ /// Note that nullability is only captured as sugar within the type
+ /// system, not as part of the canonical type, so nullability will
+ /// be lost by canonicalization and desugaring.
+ Optional<NullabilityKind> getNullability(const ASTContext &context) const;
+
+ /// Determine whether the given type can have a nullability
+ /// specifier applied to it, i.e., if it is any kind of pointer type
+ /// or a dependent type that could instantiate to any kind of
+ /// pointer type.
+ bool canHaveNullability() const;
+
+ /// Retrieve the set of substitutions required when accessing a member
+ /// of the Objective-C receiver type that is declared in the given context.
+ ///
+ /// \c *this is the type of the object we're operating on, e.g., the
+ /// receiver for a message send or the base of a property access, and is
+ /// expected to be of some object or object pointer type.
+ ///
+ /// \param dc The declaration context for which we are building up a
+ /// substitution mapping, which should be an Objective-C class, extension,
+ /// category, or method within.
+ ///
+ /// \returns an array of type arguments that can be substituted for
+ /// the type parameters of the given declaration context in any type described
+ /// within that context, or an empty optional to indicate that no
+ /// substitution is required.
+ Optional<ArrayRef<QualType>>
+ getObjCSubstitutions(const DeclContext *dc) const;
+
+ /// Determines if this is an ObjC interface type that may accept type
+ /// parameters.
+ bool acceptsObjCTypeParams() const;
+
+ const char *getTypeClassName() const;
+
+ QualType getCanonicalTypeInternal() const {
+ return CanonicalType;
+ }
+ CanQualType getCanonicalTypeUnqualified() const; // in CanonicalType.h
+ void dump() const;
+
+ friend class ASTReader;
+ friend class ASTWriter;
+};
+
+/// \brief This will check for a TypedefType by removing any existing sugar
+/// until it reaches a TypedefType or a non-sugared type.
+template <> const TypedefType *Type::getAs() const;
+
+/// \brief This will check for a TemplateSpecializationType by removing any
+/// existing sugar until it reaches a TemplateSpecializationType or a
+/// non-sugared type.
+template <> const TemplateSpecializationType *Type::getAs() const;
+
+/// \brief This will check for an AttributedType by removing any existing sugar
+/// until it reaches an AttributedType or a non-sugared type.
+template <> const AttributedType *Type::getAs() const;
+
+// 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"
+
+
+/// 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 {
+#define BUILTIN_TYPE(Id, SingletonId) Id,
+#define LAST_BUILTIN_TYPE(Id) LastKind = Id
+#include "clang/AST/BuiltinTypes.def"
+ };
+
+public:
+ BuiltinType(Kind K)
+ : Type(Builtin, QualType(), /*Dependent=*/(K == Dependent),
+ /*InstantiationDependent=*/(K == Dependent),
+ /*VariablyModified=*/false,
+ /*Unexpanded paramter pack=*/false) {
+ BuiltinTypeBits.Kind = K;
+ }
+
+ Kind getKind() const { return static_cast<Kind>(BuiltinTypeBits.Kind); }
+ StringRef getName(const PrintingPolicy &Policy) const;
+ const char *getNameAsCString(const PrintingPolicy &Policy) const {
+ // The StringRef is null-terminated.
+ StringRef str = getName(Policy);
+ assert(!str.empty() && str.data()[str.size()] == '\0');
+ return str.data();
+ }
+
+ 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() >= Half && getKind() <= LongDouble;
+ }
+
+ /// Determines whether the given kind corresponds to a placeholder type.
+ static bool isPlaceholderTypeKind(Kind K) {
+ return K >= Overload;
+ }
+
+ /// Determines whether this type is a placeholder type, i.e. a type
+ /// which cannot appear in arbitrary positions in a fully-formed
+ /// expression.
+ bool isPlaceholderType() const {
+ return isPlaceholderTypeKind(getKind());
+ }
+
+ /// Determines whether this type is a placeholder type other than
+ /// Overload. Most placeholder types require only syntactic
+ /// information about their context in order to be resolved (e.g.
+ /// whether it is a call expression), which means they can (and
+ /// should) be resolved in an earlier "phase" of analysis.
+ /// Overload expressions sometimes pick up further information
+ /// from their context, like whether the context expects a
+ /// specific function-pointer type, and so frequently need
+ /// special treatment.
+ bool isNonOverloadPlaceholderType() const {
+ return getKind() > Overload;
+ }
+
+ static bool classof(const Type *T) { return T->getTypeClass() == Builtin; }
+};
+
+/// Complex values, per C99 6.2.5p11. 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->isInstantiationDependentType(),
+ 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; }
+};
+
+/// 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->isInstantiationDependentType(),
+ 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; }
+};
+
+/// 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->isInstantiationDependentType(),
+ Pointee->isVariablyModifiedType(),
+ Pointee->containsUnexpandedParameterPack()),
+ PointeeType(Pointee) {
+ }
+ friend class ASTContext; // ASTContext creates these.
+
+public:
+
+ QualType getPointeeType() const { return PointeeType; }
+
+ /// Returns true if address spaces of pointers overlap.
+ /// OpenCL v2.0 defines conversion rules for pointers to different
+ /// address spaces (OpenCLC v2.0 s6.5.5) and notion of overlapping
+ /// address spaces.
+ /// CL1.1 or CL1.2:
+ /// address spaces overlap iff they are they same.
+ /// CL2.0 adds:
+ /// __generic overlaps with any address space except for __constant.
+ bool isAddressSpaceOverlapping(const PointerType &other) const {
+ Qualifiers thisQuals = PointeeType.getQualifiers();
+ Qualifiers otherQuals = other.getPointeeType().getQualifiers();
+ // Address spaces overlap if at least one of them is a superset of another
+ return thisQuals.isAddressSpaceSupersetOf(otherQuals) ||
+ otherQuals.isAddressSpaceSupersetOf(thisQuals);
+ }
+
+ 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; }
+};
+
+/// Represents a type which was implicitly adjusted by the semantic
+/// engine for arbitrary reasons. For example, array and function types can
+/// decay, and function types can have their calling conventions adjusted.
+class AdjustedType : public Type, public llvm::FoldingSetNode {
+ QualType OriginalTy;
+ QualType AdjustedTy;
+
+protected:
+ AdjustedType(TypeClass TC, QualType OriginalTy, QualType AdjustedTy,
+ QualType CanonicalPtr)
+ : Type(TC, CanonicalPtr, OriginalTy->isDependentType(),
+ OriginalTy->isInstantiationDependentType(),
+ OriginalTy->isVariablyModifiedType(),
+ OriginalTy->containsUnexpandedParameterPack()),
+ OriginalTy(OriginalTy), AdjustedTy(AdjustedTy) {}
+
+ friend class ASTContext; // ASTContext creates these.
+
+public:
+ QualType getOriginalType() const { return OriginalTy; }
+ QualType getAdjustedType() const { return AdjustedTy; }
+
+ bool isSugared() const { return true; }
+ QualType desugar() const { return AdjustedTy; }
+
+ void Profile(llvm::FoldingSetNodeID &ID) {
+ Profile(ID, OriginalTy, AdjustedTy);
+ }
+ static void Profile(llvm::FoldingSetNodeID &ID, QualType Orig, QualType New) {
+ ID.AddPointer(Orig.getAsOpaquePtr());
+ ID.AddPointer(New.getAsOpaquePtr());
+ }
+
+ static bool classof(const Type *T) {
+ return T->getTypeClass() == Adjusted || T->getTypeClass() == Decayed;
+ }
+};
+
+/// Represents a pointer type decayed from an array or function type.
+class DecayedType : public AdjustedType {
+
+ DecayedType(QualType OriginalType, QualType DecayedPtr, QualType CanonicalPtr)
+ : AdjustedType(Decayed, OriginalType, DecayedPtr, CanonicalPtr) {
+ assert(isa<PointerType>(getAdjustedType()));
+ }
+
+ friend class ASTContext; // ASTContext creates these.
+
+public:
+ QualType getDecayedType() const { return getAdjustedType(); }
+
+ QualType getPointeeType() const {
+ return cast<PointerType>(getDecayedType())->getPointeeType();
+ }
+
+ static bool classof(const Type *T) { return T->getTypeClass() == Decayed; }
+};
+
+/// 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->isInstantiationDependentType(),
+ 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;
+ }
+};
+
+/// 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->isInstantiationDependentType(),
+ 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;
+ }
+};
+
+/// An lvalue reference type, per C++11 [dcl.ref].
+///
+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;
+ }
+};
+
+/// An rvalue reference type, per C++11 [dcl.ref].
+///
+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;
+ }
+};
+
+/// A pointer to member type per C++ 8.3.3 - Pointers to members.
+///
+/// This includes both pointers to data members and pointer to member functions.
+///
+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(),
+ (Cls->isInstantiationDependentType() ||
+ Pointee->isInstantiationDependentType()),
+ 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; }
+ CXXRecordDecl *getMostRecentCXXRecordDecl() const;
+
+ 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;
+ }
+};
+
+/// Represents an array type, per C99 6.7.5.2 - Array Declarators.
+///
+class ArrayType : public Type, public llvm::FoldingSetNode {
+public:
+ /// 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:
+ /// 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,
+ et->isInstantiationDependentType() || 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;
+ }
+};
+
+/// 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;
+ }
+};
+
+/// Represents a C array 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;
+ }
+
+ 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);
+ }
+};
+
+/// Represents a C array with a specified size that 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 {
+ /// An assignment-expression. VLA's are only permitted within
+ /// a function block.
+ Stmt *SizeExpr;
+ /// The range spanned by 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;
+ }
+
+ friend class StmtIteratorBase;
+
+ void Profile(llvm::FoldingSetNodeID &ID) {
+ llvm_unreachable("Cannot unique VariableArrayTypes.");
+ }
+};
+
+/// 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;
+
+ /// The range spanned by 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;
+ }
+
+ 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);
+};
+
+/// Represents 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;
+ /// 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;
+ }
+
+ void Profile(llvm::FoldingSetNodeID &ID) {
+ Profile(ID, Context, getElementType(), getSizeExpr());
+ }
+
+ static void Profile(llvm::FoldingSetNodeID &ID, const ASTContext &Context,
+ QualType ElementType, Expr *SizeExpr);
+};
+
+
+/// Represents a 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:
+ /// 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; }
+ static bool isVectorSizeTooLarge(unsigned NumElements) {
+ return NumElements > VectorTypeBitfields::MaxNumElements;
+ }
+
+ 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;
+ }
+};
+
+/// 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;
+ }
+};
+
+/// 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:
+ /// 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 9,
+ // you'll need to adjust both the Bits field below and
+ // Type::FunctionTypeBitfields.
+
+ // | CC |noreturn|produces|regparm|
+ // |0 .. 3| 4 | 5 | 6 .. 8|
+ //
+ // regparm is either 0 (no regparm attribute) or the regparm value+1.
+ enum { CallConvMask = 0xF };
+ enum { NoReturnMask = 0x10 };
+ enum { ProducesResultMask = 0x20 };
+ enum { RegParmMask = ~(CallConvMask | NoReturnMask | ProducesResultMask),
+ RegParmOffset = 6 }; // Assumed to be the last field
+
+ uint16_t Bits;
+
+ ExtInfo(unsigned Bits) : Bits(static_cast<uint16_t>(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, bool hasRegParm, unsigned regParm, CallingConv cc,
+ bool producesResult) {
+ assert((!hasRegParm || regParm < 7) && "Invalid regparm value");
+ Bits = ((unsigned) cc) |
+ (noReturn ? NoReturnMask : 0) |
+ (producesResult ? ProducesResultMask : 0) |
+ (hasRegParm ? ((regParm + 1) << RegParmOffset) : 0);
+ }
+
+ // Constructor with all defaults. Use when for example creating a
+ // function known to use defaults.
+ ExtInfo() : Bits(CC_C) { }
+
+ // Constructor with just the calling convention, which is an important part
+ // of the canonical type.
+ ExtInfo(CallingConv CC) : Bits(CC) { }
+
+ bool getNoReturn() const { return Bits & NoReturnMask; }
+ bool getProducesResult() const { return Bits & ProducesResultMask; }
+ bool getHasRegParm() const { return (Bits >> RegParmOffset) != 0; }
+ unsigned getRegParm() const {
+ unsigned RegParm = Bits >> RegParmOffset;
+ if (RegParm > 0)
+ --RegParm;
+ return RegParm;
+ }
+ 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 withProducesResult(bool producesResult) const {
+ if (producesResult)
+ return ExtInfo(Bits | ProducesResultMask);
+ else
+ return ExtInfo(Bits & ~ProducesResultMask);
+ }
+
+ ExtInfo withRegParm(unsigned RegParm) const {
+ assert(RegParm < 7 && "Invalid regparm value");
+ return ExtInfo((Bits & ~RegParmMask) |
+ ((RegParm + 1) << 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,
+ QualType Canonical, bool Dependent,
+ bool InstantiationDependent,
+ bool VariablyModified, bool ContainsUnexpandedParameterPack,
+ ExtInfo Info)
+ : Type(tc, Canonical, Dependent, InstantiationDependent, VariablyModified,
+ ContainsUnexpandedParameterPack),
+ ResultType(res) {
+ FunctionTypeBits.ExtInfo = Info.Bits;
+ }
+ unsigned getTypeQuals() const { return FunctionTypeBits.TypeQuals; }
+
+public:
+ QualType getReturnType() const { return ResultType; }
+
+ bool getHasRegParm() const { return getExtInfo().getHasRegParm(); }
+ unsigned getRegParmType() const { return getExtInfo().getRegParm(); }
+ /// Determine whether this function type includes the GNU noreturn
+ /// attribute. The C++11 [[noreturn]] attribute does not affect the function
+ /// type.
+ bool getNoReturnAttr() const { return getExtInfo().getNoReturn(); }
+ CallingConv getCallConv() const { return getExtInfo().getCC(); }
+ ExtInfo getExtInfo() const { return ExtInfo(FunctionTypeBits.ExtInfo); }
+ bool isConst() const { return getTypeQuals() & Qualifiers::Const; }
+ bool isVolatile() const { return getTypeQuals() & Qualifiers::Volatile; }
+ bool isRestrict() const { return getTypeQuals() & Qualifiers::Restrict; }
+
+ /// \brief Determine the type of an expression that calls a function of
+ /// this type.
+ QualType getCallResultType(ASTContext &Context) const {
+ return getReturnType().getNonLValueExprType(Context);
+ }
+
+ static StringRef getNameForCallConv(CallingConv CC);
+
+ static bool classof(const Type *T) {
+ return T->getTypeClass() == FunctionNoProto ||
+ T->getTypeClass() == FunctionProto;
+ }
+};
+
+/// 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, Canonical,
+ /*Dependent=*/false, /*InstantiationDependent=*/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, getReturnType(), 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;
+ }
+};
+
+/// Represents a prototype with parameter type info, e.g.
+/// 'int foo(int)' or 'int foo(void)'. 'void' is represented as having no
+/// parameters, not as having a single void parameter. 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:
+ struct ExceptionSpecInfo {
+ ExceptionSpecInfo()
+ : Type(EST_None), NoexceptExpr(nullptr),
+ SourceDecl(nullptr), SourceTemplate(nullptr) {}
+
+ ExceptionSpecInfo(ExceptionSpecificationType EST)
+ : Type(EST), NoexceptExpr(nullptr), SourceDecl(nullptr),
+ SourceTemplate(nullptr) {}
+
+ /// The kind of exception specification this is.
+ ExceptionSpecificationType Type;
+ /// Explicitly-specified list of exception types.
+ ArrayRef<QualType> Exceptions;
+ /// Noexcept expression, if this is EST_ComputedNoexcept.
+ Expr *NoexceptExpr;
+ /// The function whose exception specification this is, for
+ /// EST_Unevaluated and EST_Uninstantiated.
+ FunctionDecl *SourceDecl;
+ /// The function template whose exception specification this is instantiated
+ /// from, for EST_Uninstantiated.
+ FunctionDecl *SourceTemplate;
+ };
+
+ /// Extra information about a function prototype.
+ struct ExtProtoInfo {
+ ExtProtoInfo()
+ : Variadic(false), HasTrailingReturn(false), TypeQuals(0),
+ RefQualifier(RQ_None), ConsumedParameters(nullptr) {}
+
+ ExtProtoInfo(CallingConv CC)
+ : ExtInfo(CC), Variadic(false), HasTrailingReturn(false), TypeQuals(0),
+ RefQualifier(RQ_None), ConsumedParameters(nullptr) {}
+
+ ExtProtoInfo withExceptionSpec(const ExceptionSpecInfo &O) {
+ ExtProtoInfo Result(*this);
+ Result.ExceptionSpec = O;
+ return Result;
+ }
+
+ FunctionType::ExtInfo ExtInfo;
+ bool Variadic : 1;
+ bool HasTrailingReturn : 1;
+ unsigned char TypeQuals;
+ RefQualifierKind RefQualifier;
+ ExceptionSpecInfo ExceptionSpec;
+ const bool *ConsumedParameters;
+ };
+
+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, ArrayRef<QualType> params,
+ QualType canonical, const ExtProtoInfo &epi);
+
+ /// The number of parameters this function has, not counting '...'.
+ unsigned NumParams : 15;
+
+ /// The number of types in the exception spec, if any.
+ unsigned NumExceptions : 9;
+
+ /// The type of exception specification this function has.
+ unsigned ExceptionSpecType : 4;
+
+ /// Whether this function has any consumed parameters.
+ unsigned HasAnyConsumedParams : 1;
+
+ /// Whether the function is variadic.
+ unsigned Variadic : 1;
+
+ /// Whether this function has a trailing return type.
+ unsigned HasTrailingReturn : 1;
+
+ // ParamInfo - There is an variable size array after the class in memory that
+ // holds the parameter types.
+
+ // Exceptions - There is another variable size array after ArgInfo that
+ // holds the exception types.
+
+ // NoexceptExpr - Instead of Exceptions, there may be a single Expr* pointing
+ // to the expression in the noexcept() specifier.
+
+ // ExceptionSpecDecl, ExceptionSpecTemplate - Instead of Exceptions, there may
+ // be a pair of FunctionDecl* pointing to the function which should be used to
+ // instantiate this function type's exception specification, and the function
+ // from which it should be instantiated.
+
+ // ConsumedParameters - A variable size array, following Exceptions
+ // and of length NumParams, holding flags indicating which parameters
+ // are consumed. This only appears if HasAnyConsumedParams is true.
+
+ friend class ASTContext; // ASTContext creates these.
+
+ const bool *getConsumedParamsBuffer() const {
+ assert(hasAnyConsumedParams());
+
+ // Find the end of the exceptions.
+ Expr *const *eh_end = reinterpret_cast<Expr *const *>(exception_end());
+ if (getExceptionSpecType() == EST_ComputedNoexcept)
+ eh_end += 1; // NoexceptExpr
+ // The memory layout of these types isn't handled here, so
+ // hopefully this is never called for them?
+ assert(getExceptionSpecType() != EST_Uninstantiated &&
+ getExceptionSpecType() != EST_Unevaluated);
+
+ return reinterpret_cast<const bool*>(eh_end);
+ }
+
+public:
+ unsigned getNumParams() const { return NumParams; }
+ QualType getParamType(unsigned i) const {
+ assert(i < NumParams && "invalid parameter index");
+ return param_type_begin()[i];
+ }
+ ArrayRef<QualType> getParamTypes() const {
+ return llvm::makeArrayRef(param_type_begin(), param_type_end());
+ }
+
+ ExtProtoInfo getExtProtoInfo() const {
+ ExtProtoInfo EPI;
+ EPI.ExtInfo = getExtInfo();
+ EPI.Variadic = isVariadic();
+ EPI.HasTrailingReturn = hasTrailingReturn();
+ EPI.ExceptionSpec.Type = getExceptionSpecType();
+ EPI.TypeQuals = static_cast<unsigned char>(getTypeQuals());
+ EPI.RefQualifier = getRefQualifier();
+ if (EPI.ExceptionSpec.Type == EST_Dynamic) {
+ EPI.ExceptionSpec.Exceptions = exceptions();
+ } else if (EPI.ExceptionSpec.Type == EST_ComputedNoexcept) {
+ EPI.ExceptionSpec.NoexceptExpr = getNoexceptExpr();
+ } else if (EPI.ExceptionSpec.Type == EST_Uninstantiated) {
+ EPI.ExceptionSpec.SourceDecl = getExceptionSpecDecl();
+ EPI.ExceptionSpec.SourceTemplate = getExceptionSpecTemplate();
+ } else if (EPI.ExceptionSpec.Type == EST_Unevaluated) {
+ EPI.ExceptionSpec.SourceDecl = getExceptionSpecDecl();
+ }
+ if (hasAnyConsumedParams())
+ EPI.ConsumedParameters = getConsumedParamsBuffer();
+ return EPI;
+ }
+
+ /// Get the kind of exception specification on this function.
+ ExceptionSpecificationType getExceptionSpecType() const {
+ return static_cast<ExceptionSpecificationType>(ExceptionSpecType);
+ }
+ /// Return whether this function has any kind of exception spec.
+ bool hasExceptionSpec() const {
+ return getExceptionSpecType() != EST_None;
+ }
+ /// Return whether this function has a dynamic (throw) exception spec.
+ bool hasDynamicExceptionSpec() const {
+ return isDynamicExceptionSpec(getExceptionSpecType());
+ }
+ /// Return whether this function has a noexcept exception spec.
+ bool hasNoexceptExceptionSpec() const {
+ return isNoexceptExceptionSpec(getExceptionSpecType());
+ }
+ /// Return whether this function has a dependent exception spec.
+ bool hasDependentExceptionSpec() const;
+ /// Result type of getNoexceptSpec().
+ enum NoexceptResult {
+ NR_NoNoexcept, ///< There is no noexcept specifier.
+ NR_BadNoexcept, ///< The noexcept specifier has a bad expression.
+ NR_Dependent, ///< The noexcept specifier is dependent.
+ NR_Throw, ///< The noexcept specifier evaluates to false.
+ NR_Nothrow ///< The noexcept specifier evaluates to true.
+ };
+ /// Get the meaning of the noexcept spec on this function, if any.
+ NoexceptResult getNoexceptSpec(const ASTContext &Ctx) const;
+ unsigned getNumExceptions() const { return NumExceptions; }
+ QualType getExceptionType(unsigned i) const {
+ assert(i < NumExceptions && "Invalid exception number!");
+ return exception_begin()[i];
+ }
+ Expr *getNoexceptExpr() const {
+ if (getExceptionSpecType() != EST_ComputedNoexcept)
+ return nullptr;
+ // NoexceptExpr sits where the arguments end.
+ return *reinterpret_cast<Expr *const *>(param_type_end());
+ }
+ /// \brief If this function type has an exception specification which hasn't
+ /// been determined yet (either because it has not been evaluated or because
+ /// it has not been instantiated), this is the function whose exception
+ /// specification is represented by this type.
+ FunctionDecl *getExceptionSpecDecl() const {
+ if (getExceptionSpecType() != EST_Uninstantiated &&
+ getExceptionSpecType() != EST_Unevaluated)
+ return nullptr;
+ return reinterpret_cast<FunctionDecl *const *>(param_type_end())[0];
+ }
+ /// \brief If this function type has an uninstantiated exception
+ /// specification, this is the function whose exception specification
+ /// should be instantiated to find the exception specification for
+ /// this type.
+ FunctionDecl *getExceptionSpecTemplate() const {
+ if (getExceptionSpecType() != EST_Uninstantiated)
+ return nullptr;
+ return reinterpret_cast<FunctionDecl *const *>(param_type_end())[1];
+ }
+ /// Determine whether this function type has a non-throwing exception
+ /// specification. If this depends on template arguments, returns
+ /// \c ResultIfDependent.
+ bool isNothrow(const ASTContext &Ctx, bool ResultIfDependent = false) const;
+
+ bool isVariadic() const { return Variadic; }
+
+ /// 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.
+ bool isTemplateVariadic() const;
+
+ bool hasTrailingReturn() const { return HasTrailingReturn; }
+
+ unsigned getTypeQuals() const { return FunctionType::getTypeQuals(); }
+
+
+ /// Retrieve the ref-qualifier associated with this function type.
+ RefQualifierKind getRefQualifier() const {
+ return static_cast<RefQualifierKind>(FunctionTypeBits.RefQualifier);
+ }
+
+ typedef const QualType *param_type_iterator;
+ typedef llvm::iterator_range<param_type_iterator> param_type_range;
+
+ param_type_range param_types() const {
+ return param_type_range(param_type_begin(), param_type_end());
+ }
+ param_type_iterator param_type_begin() const {
+ return reinterpret_cast<const QualType *>(this+1);
+ }
+ param_type_iterator param_type_end() const {
+ return param_type_begin() + NumParams;
+ }
+
+ typedef const QualType *exception_iterator;
+
+ ArrayRef<QualType> exceptions() const {
+ return llvm::makeArrayRef(exception_begin(), exception_end());
+ }
+ exception_iterator exception_begin() const {
+ // exceptions begin where arguments end
+ return param_type_end();
+ }
+ exception_iterator exception_end() const {
+ if (getExceptionSpecType() != EST_Dynamic)
+ return exception_begin();
+ return exception_begin() + NumExceptions;
+ }
+
+ bool hasAnyConsumedParams() const { return HasAnyConsumedParams; }
+ bool isParamConsumed(unsigned I) const {
+ assert(I < getNumParams() && "parameter index out of range");
+ if (hasAnyConsumedParams())
+ return getConsumedParamsBuffer()[I];
+ return false;
+ }
+
+ bool isSugared() const { return false; }
+ QualType desugar() const { return QualType(this, 0); }
+
+ void printExceptionSpecification(raw_ostream &OS,
+ const PrintingPolicy &Policy) const;
+
+ static bool classof(const Type *T) {
+ return T->getTypeClass() == FunctionProto;
+ }
+
+ void Profile(llvm::FoldingSetNodeID &ID, const ASTContext &Ctx);
+ static void Profile(llvm::FoldingSetNodeID &ID, QualType Result,
+ param_type_iterator ArgTys, unsigned NumArgs,
+ const ExtProtoInfo &EPI, const ASTContext &Context);
+};
+
+/// \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, 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;
+ }
+
+ void Profile(llvm::FoldingSetNodeID &ID) {
+ return Profile(ID, Decl);
+ }
+ static void Profile(llvm::FoldingSetNodeID &ID,
+ UnresolvedUsingTypenameDecl *D) {
+ ID.AddPointer(D);
+ }
+};
+
+
+class TypedefType : public Type {
+ TypedefNameDecl *Decl;
+protected:
+ TypedefType(TypeClass tc, const TypedefNameDecl *D, QualType can)
+ : Type(tc, can, can->isDependentType(),
+ can->isInstantiationDependentType(),
+ can->isVariablyModifiedType(),
+ /*ContainsUnexpandedParameterPack=*/false),
+ Decl(const_cast<TypedefNameDecl*>(D)) {
+ assert(!isa<TypedefType>(can) && "Invalid canonical type");
+ }
+ friend class ASTContext; // ASTContext creates these.
+public:
+
+ TypedefNameDecl *getDecl() const { return Decl; }
+
+ bool isSugared() const { return true; }
+ QualType desugar() const;
+
+ static bool classof(const Type *T) { return T->getTypeClass() == Typedef; }
+};
+
+/// Represents a `typeof` (or __typeof__) expression (a 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;
+
+ static bool classof(const Type *T) { return T->getTypeClass() == TypeOfExpr; }
+};
+
+/// \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) { }
+
+ void Profile(llvm::FoldingSetNodeID &ID) {
+ Profile(ID, Context, getUnderlyingExpr());
+ }
+
+ static void Profile(llvm::FoldingSetNodeID &ID, const ASTContext &Context,
+ Expr *E);
+};
+
+/// Represents `typeof(type)`, a GCC extension.
+class TypeOfType : public Type {
+ QualType TOType;
+ TypeOfType(QualType T, QualType can)
+ : Type(TypeOf, can, T->isDependentType(),
+ T->isInstantiationDependentType(),
+ 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; }
+};
+
+/// Represents the type `decltype(expr)` (C++11).
+class DecltypeType : public Type {
+ Expr *E;
+ 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;
+
+ /// \brief Returns whether this type directly provides sugar.
+ bool isSugared() const;
+
+ static bool classof(const Type *T) { return T->getTypeClass() == Decltype; }
+};
+
+/// \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);
+
+ void Profile(llvm::FoldingSetNodeID &ID) {
+ Profile(ID, Context, getUnderlyingExpr());
+ }
+
+ static void Profile(llvm::FoldingSetNodeID &ID, const ASTContext &Context,
+ Expr *E);
+};
+
+/// A unary type transform, which is a type constructed from another.
+class UnaryTransformType : public Type {
+public:
+ enum UTTKind {
+ EnumUnderlyingType
+ };
+
+private:
+ /// The untransformed type.
+ QualType BaseType;
+ /// The transformed type if not dependent, otherwise the same as BaseType.
+ QualType UnderlyingType;
+
+ UTTKind UKind;
+protected:
+ UnaryTransformType(QualType BaseTy, QualType UnderlyingTy, UTTKind UKind,
+ QualType CanonicalTy);
+ friend class ASTContext;
+public:
+ bool isSugared() const { return !isDependentType(); }
+ QualType desugar() const { return UnderlyingType; }
+
+ QualType getUnderlyingType() const { return UnderlyingType; }
+ QualType getBaseType() const { return BaseType; }
+
+ UTTKind getUTTKind() const { return UKind; }
+
+ static bool classof(const Type *T) {
+ return T->getTypeClass() == UnaryTransform;
+ }
+};
+
+class TagType : public Type {
+ /// Stores the TagDecl associated with this type. The decl may point to any
+ /// TagDecl that declares the entity.
+ TagDecl * decl;
+
+ friend class ASTReader;
+
+protected:
+ TagType(TypeClass TC, const TagDecl *D, QualType can);
+
+public:
+ TagDecl *getDecl() const;
+
+ /// 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;
+ }
+};
+
+/// 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 Type *T) { return T->getTypeClass() == Record; }
+};
+
+/// 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 Type *T) { return T->getTypeClass() == Enum; }
+};
+
+/// 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,
+ attr_objc_ownership,
+ attr_pcs,
+ attr_pcs_vfp,
+
+ FirstEnumOperandKind = attr_objc_gc,
+ LastEnumOperandKind = attr_pcs_vfp,
+
+ // No operand.
+ attr_noreturn,
+ attr_cdecl,
+ attr_fastcall,
+ attr_stdcall,
+ attr_thiscall,
+ attr_pascal,
+ attr_vectorcall,
+ attr_inteloclbicc,
+ attr_ms_abi,
+ attr_sysv_abi,
+ attr_ptr32,
+ attr_ptr64,
+ attr_sptr,
+ attr_uptr,
+ attr_nonnull,
+ attr_nullable,
+ attr_null_unspecified,
+ attr_objc_kindof,
+ attr_objc_inert_unsafe_unretained,
+ };
+
+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->isInstantiationDependentType(),
+ 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(); }
+
+ /// Does this attribute behave like a type qualifier?
+ ///
+ /// A type qualifier adjusts a type to provide specialized rules for
+ /// a specific object, like the standard const and volatile qualifiers.
+ /// This includes attributes controlling things like nullability,
+ /// address spaces, and ARC ownership. The value of the object is still
+ /// largely described by the modified type.
+ ///
+ /// In contrast, many type attributes "rewrite" their modified type to
+ /// produce a fundamentally different type, not necessarily related in any
+ /// formalizable way to the original type. For example, calling convention
+ /// and vector attributes are not simple type qualifiers.
+ ///
+ /// Type qualifiers are often, but not always, reflected in the canonical
+ /// type.
+ bool isQualifier() const;
+
+ bool isMSTypeSpec() const;
+
+ bool isCallingConv() const;
+
+ llvm::Optional<NullabilityKind> getImmediateNullability() const;
+
+ /// Retrieve the attribute kind corresponding to the given
+ /// nullability kind.
+ static Kind getNullabilityAttrKind(NullabilityKind kind) {
+ switch (kind) {
+ case NullabilityKind::NonNull:
+ return attr_nonnull;
+
+ case NullabilityKind::Nullable:
+ return attr_nullable;
+
+ case NullabilityKind::Unspecified:
+ return attr_null_unspecified;
+ }
+ llvm_unreachable("Unknown nullability kind.");
+ }
+
+ /// Strip off the top-level nullability annotation on the given
+ /// type, if it's there.
+ ///
+ /// \param T The type to strip. If the type is exactly an
+ /// AttributedType specifying nullability (without looking through
+ /// type sugar), the nullability is returned and this type changed
+ /// to the underlying modified type.
+ ///
+ /// \returns the top-level nullability, if present.
+ static Optional<NullabilityKind> stripOuterNullability(QualType &T);
+
+ 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;
+ }
+};
+
+class TemplateTypeParmType : public Type, public llvm::FoldingSetNode {
+ // Helper data collector for canonical types.
+ struct CanonicalTTPTInfo {
+ unsigned Depth : 15;
+ unsigned ParameterPack : 1;
+ unsigned Index : 16;
+ };
+
+ union {
+ // Info for the canonical type.
+ CanonicalTTPTInfo CanTTPTInfo;
+ // Info for the non-canonical type.
+ TemplateTypeParmDecl *TTPDecl;
+ };
+
+ /// Build a non-canonical type.
+ TemplateTypeParmType(TemplateTypeParmDecl *TTPDecl, QualType Canon)
+ : Type(TemplateTypeParm, Canon, /*Dependent=*/true,
+ /*InstantiationDependent=*/true,
+ /*VariablyModified=*/false,
+ Canon->containsUnexpandedParameterPack()),
+ TTPDecl(TTPDecl) { }
+
+ /// Build the canonical type.
+ TemplateTypeParmType(unsigned D, unsigned I, bool PP)
+ : Type(TemplateTypeParm, QualType(this, 0),
+ /*Dependent=*/true,
+ /*InstantiationDependent=*/true,
+ /*VariablyModified=*/false, PP) {
+ CanTTPTInfo.Depth = D;
+ CanTTPTInfo.Index = I;
+ CanTTPTInfo.ParameterPack = PP;
+ }
+
+ friend class ASTContext; // ASTContext creates these
+
+ const CanonicalTTPTInfo& getCanTTPTInfo() const {
+ QualType Can = getCanonicalTypeInternal();
+ return Can->castAs<TemplateTypeParmType>()->CanTTPTInfo;
+ }
+
+public:
+ unsigned getDepth() const { return getCanTTPTInfo().Depth; }
+ unsigned getIndex() const { return getCanTTPTInfo().Index; }
+ bool isParameterPack() const { return getCanTTPTInfo().ParameterPack; }
+
+ TemplateTypeParmDecl *getDecl() const {
+ return isCanonicalUnqualified() ? nullptr : TTPDecl;
+ }
+
+ IdentifierInfo *getIdentifier() const;
+
+ bool isSugared() const { return false; }
+ QualType desugar() const { return QualType(this, 0); }
+
+ void Profile(llvm::FoldingSetNodeID &ID) {
+ Profile(ID, getDepth(), getIndex(), isParameterPack(), getDecl());
+ }
+
+ static void Profile(llvm::FoldingSetNodeID &ID, unsigned Depth,
+ unsigned Index, bool ParameterPack,
+ TemplateTypeParmDecl *TTPDecl) {
+ ID.AddInteger(Depth);
+ ID.AddInteger(Index);
+ ID.AddBoolean(ParameterPack);
+ ID.AddPointer(TTPDecl);
+ }
+
+ static bool classof(const Type *T) {
+ return T->getTypeClass() == TemplateTypeParm;
+ }
+};
+
+/// \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->isInstantiationDependentType(),
+ Canon->isVariablyModifiedType(),
+ Canon->containsUnexpandedParameterPack()),
+ Replaced(Param) { }
+
+ friend class ASTContext;
+
+public:
+ /// 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;
+ }
+};
+
+/// \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 *getIdentifier() const { return Replaced->getIdentifier(); }
+
+ /// 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;
+ }
+};
+
+/// \brief Represents a C++11 auto or C++14 decltype(auto) type.
+///
+/// These types are usually a placeholder for a deduced type. However, before
+/// the initializer is attached, or if the initializer is type-dependent, there
+/// is no deduced type and an auto type is canonical. In the latter case, it is
+/// also a dependent type.
+class AutoType : public Type, public llvm::FoldingSetNode {
+ AutoType(QualType DeducedType, AutoTypeKeyword Keyword, bool IsDependent)
+ : Type(Auto, DeducedType.isNull() ? QualType(this, 0) : DeducedType,
+ /*Dependent=*/IsDependent, /*InstantiationDependent=*/IsDependent,
+ /*VariablyModified=*/false,
+ /*ContainsParameterPack=*/DeducedType.isNull()
+ ? false : DeducedType->containsUnexpandedParameterPack()) {
+ assert((DeducedType.isNull() || !IsDependent) &&
+ "auto deduced to dependent type");
+ AutoTypeBits.Keyword = (unsigned)Keyword;
+ }
+
+ friend class ASTContext; // ASTContext creates these
+
+public:
+ bool isDecltypeAuto() const {
+ return getKeyword() == AutoTypeKeyword::DecltypeAuto;
+ }
+ AutoTypeKeyword getKeyword() const {
+ return (AutoTypeKeyword)AutoTypeBits.Keyword;
+ }
+
+ bool isSugared() const { return !isCanonicalUnqualified(); }
+ QualType desugar() const { return getCanonicalTypeInternal(); }
+
+ /// \brief Get the type deduced for this auto type, or null if it's either
+ /// not been deduced or was deduced to a dependent type.
+ QualType getDeducedType() const {
+ return !isCanonicalUnqualified() ? getCanonicalTypeInternal() : QualType();
+ }
+ bool isDeduced() const {
+ return !isCanonicalUnqualified() || isDependentType();
+ }
+
+ void Profile(llvm::FoldingSetNodeID &ID) {
+ Profile(ID, getDeducedType(), getKeyword(), isDependentType());
+ }
+
+ static void Profile(llvm::FoldingSetNodeID &ID, QualType Deduced,
+ AutoTypeKeyword Keyword, bool IsDependent) {
+ ID.AddPointer(Deduced.getAsOpaquePtr());
+ ID.AddInteger((unsigned)Keyword);
+ ID.AddBoolean(IsDependent);
+ }
+
+ static bool classof(const Type *T) {
+ return T->getTypeClass() == Auto;
+ }
+};
+
+/// \brief Represents a type template specialization; the template
+/// must be a class template, a type alias template, or a template
+/// template parameter. A template which cannot be resolved to one of
+/// these, e.g. because it is written with a dependent scope
+/// specifier, is instead represented as a
+/// @c DependentTemplateSpecializationType.
+///
+/// A non-dependent template specialization type is always "sugar",
+/// typically for a \c RecordType. 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>>
+///
+/// Template specializations are dependent if either the template or
+/// any of the template arguments are dependent, in which case the
+/// type may also be canonical.
+///
+/// Instances of this type are allocated with a trailing array of
+/// TemplateArguments, followed by a QualType representing the
+/// non-canonical aliased type when the template is a type alias
+/// template.
+class LLVM_ALIGNAS(/*alignof(uint64_t)*/ 8) TemplateSpecializationType
+ : public Type,
+ public llvm::FoldingSetNode {
+ /// The name of the template being specialized. This is
+ /// either a TemplateName::Template (in which case it is a
+ /// ClassTemplateDecl*, a TemplateTemplateParmDecl*, or a
+ /// TypeAliasTemplateDecl*), a
+ /// TemplateName::SubstTemplateTemplateParmPack, or a
+ /// TemplateName::SubstTemplateTemplateParm (in which case the
+ /// replacement must, recursively, be one of these).
+ TemplateName Template;
+
+ /// The number of template arguments named in this class template
+ /// specialization.
+ unsigned NumArgs : 31;
+
+ /// Whether this template specialization type is a substituted type alias.
+ bool TypeAlias : 1;
+
+ TemplateSpecializationType(TemplateName T,
+ const TemplateArgument *Args,
+ unsigned NumArgs, QualType Canon,
+ QualType Aliased);
+
+ friend class ASTContext; // ASTContext creates these
+
+public:
+ /// Determine whether any of the given template arguments are dependent.
+ static bool anyDependentTemplateArguments(const TemplateArgumentLoc *Args,
+ unsigned NumArgs,
+ bool &InstantiationDependent);
+
+ static bool anyDependentTemplateArguments(const TemplateArgumentListInfo &,
+ bool &InstantiationDependent);
+
+ /// \brief Print a template argument list, including the '<' and '>'
+ /// enclosing the template arguments.
+ static void PrintTemplateArgumentList(raw_ostream &OS,
+ const TemplateArgument *Args,
+ unsigned NumArgs,
+ const PrintingPolicy &Policy,
+ bool SkipBrackets = false);
+
+ static void PrintTemplateArgumentList(raw_ostream &OS,
+ const TemplateArgumentLoc *Args,
+ unsigned NumArgs,
+ const PrintingPolicy &Policy);
+
+ static void PrintTemplateArgumentList(raw_ostream &OS,
+ 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());
+ }
+
+ /// \brief Determine if this template specialization type is for a type alias
+ /// template that has been substituted.
+ ///
+ /// Nearly every template specialization type whose template is an alias
+ /// template will be substituted. However, this is not the case when
+ /// the specialization contains a pack expansion but the template alias
+ /// does not have a corresponding parameter pack, e.g.,
+ ///
+ /// \code
+ /// template<typename T, typename U, typename V> struct S;
+ /// template<typename T, typename U> using A = S<T, int, U>;
+ /// template<typename... Ts> struct X {
+ /// typedef A<Ts...> type; // not a type alias
+ /// };
+ /// \endcode
+ bool isTypeAlias() const { return TypeAlias; }
+
+ /// Get the aliased type, if this is a specialization of a type alias
+ /// template.
+ QualType getAliasedType() const {
+ assert(isTypeAlias() && "not a type alias template specialization");
+ return *reinterpret_cast<const QualType*>(end());
+ }
+
+ typedef const TemplateArgument * iterator;
+
+ iterator begin() const { return getArgs(); }
+ iterator end() const; // defined inline in TemplateBase.h
+
+ /// Retrieve the name of the template that we are specializing.
+ TemplateName getTemplateName() const { return Template; }
+
+ /// Retrieve the template arguments.
+ const TemplateArgument *getArgs() const {
+ return reinterpret_cast<const TemplateArgument *>(this + 1);
+ }
+
+ /// Retrieve the number of template arguments.
+ unsigned getNumArgs() const { return NumArgs; }
+
+ /// Retrieve a specific template argument as a type.
+ /// \pre \c isArgType(Arg)
+ const TemplateArgument &getArg(unsigned Idx) const; // in TemplateBase.h
+
+ bool isSugared() const {
+ return !isDependentType() || isCurrentInstantiation() || isTypeAlias();
+ }
+ QualType desugar() const { return getCanonicalTypeInternal(); }
+
+ void Profile(llvm::FoldingSetNodeID &ID, const ASTContext &Ctx) {
+ Profile(ID, Template, getArgs(), NumArgs, Ctx);
+ if (isTypeAlias())
+ getAliasedType().Profile(ID);
+ }
+
+ 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;
+ }
+};
+
+/// 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,
+ /*InstantiationDependent=*/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;
+ }
+};
+
+/// \brief The kind of a tag type.
+enum TagTypeKind {
+ /// \brief The "struct" keyword.
+ TTK_Struct,
+ /// \brief The "__interface" keyword.
+ TTK_Interface,
+ /// \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 "__interface" keyword introduces the elaborated-type-specifier.
+ ETK_Interface,
+ /// \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 InstantiationDependent, bool VariablyModified,
+ bool ContainsUnexpandedParameterPack)
+ : Type(tc, Canonical, Dependent, InstantiationDependent, VariablyModified,
+ ContainsUnexpandedParameterPack) {
+ TypeWithKeywordBits.Keyword = Keyword;
+ }
+
+public:
+ ElaboratedTypeKeyword getKeyword() const {
+ return static_cast<ElaboratedTypeKeyword>(TypeWithKeywordBits.Keyword);
+ }
+
+ /// Converts a type specifier (DeclSpec::TST) into an elaborated type keyword.
+ static ElaboratedTypeKeyword getKeywordForTypeSpec(unsigned TypeSpec);
+
+ /// 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);
+
+ /// Converts a TagTypeKind into an elaborated type keyword.
+ static ElaboratedTypeKeyword getKeywordForTagTypeKind(TagTypeKind Tag);
+
+ /// 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 StringRef getKeywordName(ElaboratedTypeKeyword Keyword);
+
+ static StringRef 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 {
+
+ /// The nested name specifier containing the qualifier.
+ NestedNameSpecifier *NNS;
+
+ /// 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->isInstantiationDependentType(),
+ NamedType->isVariablyModifiedType(),
+ NamedType->containsUnexpandedParameterPack()),
+ NNS(NNS), NamedType(NamedType) {
+ assert(!(Keyword == ETK_None && NNS == nullptr) &&
+ "ElaboratedType cannot have elaborated type keyword "
+ "and name qualifier both null.");
+ }
+
+ friend class ASTContext; // ASTContext creates these
+
+public:
+ ~ElaboratedType();
+
+ /// Retrieve the qualification on this type.
+ NestedNameSpecifier *getQualifier() const { return NNS; }
+
+ /// Retrieve the type named by the qualified-id.
+ QualType getNamedType() const { return NamedType; }
+
+ /// Remove a single level of sugar.
+ QualType desugar() const { return getNamedType(); }
+
+ /// 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;
+ }
+};
+
+/// \brief Represents a qualified type name for which the type name is
+/// dependent.
+///
+/// DependentNameType represents a class of dependent types that involve a
+/// possibly dependent nested-name-specifier (e.g., "T::") followed by a
+/// 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).
+/// Typically the nested-name-specifier is dependent, but in MSVC compatibility
+/// mode, this type is used with non-dependent names to delay name lookup until
+/// instantiation.
+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,
+ /*InstantiationDependent=*/true,
+ /*VariablyModified=*/false,
+ NNS->containsUnexpandedParameterPack()),
+ NNS(NNS), Name(Name) {}
+
+ friend class ASTContext; // ASTContext creates these
+
+public:
+ /// Retrieve the qualification on this type.
+ NestedNameSpecifier *getQualifier() const { return NNS; }
+
+ /// 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;
+ }
+};
+
+/// Represents a template specialization type whose template cannot be
+/// resolved, e.g.
+/// A<T>::template B<T>
+class LLVM_ALIGNAS(/*alignof(uint64_t)*/ 8) DependentTemplateSpecializationType
+ : public TypeWithKeyword,
+ public llvm::FoldingSetNode {
+
+ /// The nested name specifier containing the qualifier.
+ NestedNameSpecifier *NNS;
+
+ /// 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;
+ }
+};
+
+/// \brief Represents a pack expansion of types.
+///
+/// Pack expansions are part of C++11 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,
+ Optional<unsigned> NumExpansions)
+ : Type(PackExpansion, Canon, /*Dependent=*/Pattern->isDependentType(),
+ /*InstantiationDependent=*/true,
+ /*VariablyModified=*/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.
+ Optional<unsigned> getNumExpansions() const {
+ if (NumExpansions)
+ return NumExpansions - 1;
+
+ return None;
+ }
+
+ bool isSugared() const { return !Pattern->isDependentType(); }
+ QualType desugar() const { return isSugared() ? Pattern : QualType(this, 0); }
+
+ void Profile(llvm::FoldingSetNodeID &ID) {
+ Profile(ID, getPattern(), getNumExpansions());
+ }
+
+ static void Profile(llvm::FoldingSetNodeID &ID, QualType Pattern,
+ Optional<unsigned> NumExpansions) {
+ ID.AddPointer(Pattern.getAsOpaquePtr());
+ ID.AddBoolean(NumExpansions.hasValue());
+ if (NumExpansions)
+ ID.AddInteger(*NumExpansions);
+ }
+
+ static bool classof(const Type *T) {
+ return T->getTypeClass() == PackExpansion;
+ }
+};
+
+/// Represents a class type in Objective C.
+///
+/// Every Objective C type is a combination of a base type, a set of
+/// type arguments (optional, for parameterized classes) and a list of
+/// protocols.
+///
+/// Given the following declarations:
+/// \code
+/// \@class C<T>;
+/// \@protocol P;
+/// \endcode
+///
+/// 'C' is an ObjCInterfaceType C. It is sugar for an ObjCObjectType
+/// with base C and no protocols.
+///
+/// 'C<P>' is an unspecialized ObjCObjectType with base C and protocol list [P].
+/// 'C<C*>' is a specialized ObjCObjectType with type arguments 'C*' and no
+/// protocol list.
+/// 'C<C*><P>' is a specialized ObjCObjectType with base C, type arguments 'C*',
+/// and protocol list [P].
+///
+/// 'id' is a TypedefType which is sugar for an ObjCObjectPointerType whose
+/// pointee is an ObjCObjectType with base BuiltinType::ObjCIdType
+/// and no protocols.
+///
+/// 'id<P>' is an ObjCObjectPointerType whose pointee is an ObjCObjectType
+/// 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.NumTypeArgs - the number of type arguments stored
+ // after the ObjCObjectPointerType node.
+ // ObjCObjectType.NumProtocols - the number of protocols stored
+ // after the type arguments of 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;
+
+ /// Cached superclass type.
+ mutable llvm::PointerIntPair<const ObjCObjectType *, 1, bool>
+ CachedSuperClassType;
+
+ ObjCProtocolDecl * const *getProtocolStorage() const {
+ return const_cast<ObjCObjectType*>(this)->getProtocolStorage();
+ }
+
+ QualType *getTypeArgStorage();
+ const QualType *getTypeArgStorage() const {
+ return const_cast<ObjCObjectType *>(this)->getTypeArgStorage();
+ }
+
+ ObjCProtocolDecl **getProtocolStorage();
+
+protected:
+ ObjCObjectType(QualType Canonical, QualType Base,
+ ArrayRef<QualType> typeArgs,
+ ArrayRef<ObjCProtocolDecl *> protocols,
+ bool isKindOf);
+
+ enum Nonce_ObjCInterface { Nonce_ObjCInterface };
+ ObjCObjectType(enum Nonce_ObjCInterface)
+ : Type(ObjCInterface, QualType(), false, false, false, false),
+ BaseType(QualType(this_(), 0)) {
+ ObjCObjectTypeBits.NumProtocols = 0;
+ ObjCObjectTypeBits.NumTypeArgs = 0;
+ ObjCObjectTypeBits.IsKindOf = 0;
+ }
+
+ void computeSuperClassTypeSlow() const;
+
+public:
+ /// 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 ObjCObjectPointerType)
+ /// - 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;
+
+ /// Determine whether this object type is "specialized", meaning
+ /// that it has type arguments.
+ bool isSpecialized() const;
+
+ /// Determine whether this object type was written with type arguments.
+ bool isSpecializedAsWritten() const {
+ return ObjCObjectTypeBits.NumTypeArgs > 0;
+ }
+
+ /// Determine whether this object type is "unspecialized", meaning
+ /// that it has no type arguments.
+ bool isUnspecialized() const { return !isSpecialized(); }
+
+ /// Determine whether this object type is "unspecialized" as
+ /// written, meaning that it has no type arguments.
+ bool isUnspecializedAsWritten() const { return !isSpecializedAsWritten(); }
+
+ /// Retrieve the type arguments of this object type (semantically).
+ ArrayRef<QualType> getTypeArgs() const;
+
+ /// Retrieve the type arguments of this object type as they were
+ /// written.
+ ArrayRef<QualType> getTypeArgsAsWritten() const {
+ return llvm::makeArrayRef(getTypeArgStorage(),
+ ObjCObjectTypeBits.NumTypeArgs);
+ }
+
+ typedef ObjCProtocolDecl * const *qual_iterator;
+ typedef llvm::iterator_range<qual_iterator> qual_range;
+
+ qual_range quals() const { return qual_range(qual_begin(), qual_end()); }
+ qual_iterator qual_begin() const { return getProtocolStorage(); }
+ qual_iterator qual_end() const { return qual_begin() + getNumProtocols(); }
+
+ bool qual_empty() const { return getNumProtocols() == 0; }
+
+ /// Return the number of qualifying protocols in this interface type,
+ /// or 0 if there are none.
+ unsigned getNumProtocols() const { return ObjCObjectTypeBits.NumProtocols; }
+
+ /// Fetch a protocol by index.
+ ObjCProtocolDecl *getProtocol(unsigned I) const {
+ assert(I < getNumProtocols() && "Out-of-range protocol access");
+ return qual_begin()[I];
+ }
+
+ /// Retrieve all of the protocol qualifiers.
+ ArrayRef<ObjCProtocolDecl *> getProtocols() const {
+ return ArrayRef<ObjCProtocolDecl *>(qual_begin(), getNumProtocols());
+ }
+
+ /// Whether this is a "__kindof" type as written.
+ bool isKindOfTypeAsWritten() const { return ObjCObjectTypeBits.IsKindOf; }
+
+ /// Whether this ia a "__kindof" type (semantically).
+ bool isKindOfType() const;
+
+ /// Retrieve the type of the superclass of this object type.
+ ///
+ /// This operation substitutes any type arguments into the
+ /// superclass of the current class type, potentially producing a
+ /// specialization of the superclass type. Produces a null type if
+ /// there is no superclass.
+ QualType getSuperClassType() const {
+ if (!CachedSuperClassType.getInt())
+ computeSuperClassTypeSlow();
+
+ assert(CachedSuperClassType.getInt() && "Superclass not set?");
+ return QualType(CachedSuperClassType.getPointer(), 0);
+ }
+
+ /// Strip off the Objective-C "kindof" type and (with it) any
+ /// protocol qualifiers.
+ QualType stripObjCKindOfTypeAndQuals(const ASTContext &ctx) const;
+
+ 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;
+ }
+};
+
+/// 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,
+ ArrayRef<QualType> typeArgs,
+ ArrayRef<ObjCProtocolDecl *> protocols,
+ bool isKindOf)
+ : ObjCObjectType(Canonical, Base, typeArgs, protocols, isKindOf) {}
+
+public:
+ void Profile(llvm::FoldingSetNodeID &ID);
+ static void Profile(llvm::FoldingSetNodeID &ID,
+ QualType Base,
+ ArrayRef<QualType> typeArgs,
+ ArrayRef<ObjCProtocolDecl *> protocols,
+ bool isKindOf);
+};
+
+inline QualType *ObjCObjectType::getTypeArgStorage() {
+ return reinterpret_cast<QualType *>(static_cast<ObjCObjectTypeImpl*>(this)+1);
+}
+
+inline ObjCProtocolDecl **ObjCObjectType::getProtocolStorage() {
+ return reinterpret_cast<ObjCProtocolDecl**>(
+ getTypeArgStorage() + ObjCObjectTypeBits.NumTypeArgs);
+}
+
+/// 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 {
+ mutable ObjCInterfaceDecl *Decl;
+
+ ObjCInterfaceType(const ObjCInterfaceDecl *D)
+ : ObjCObjectType(Nonce_ObjCInterface),
+ Decl(const_cast<ObjCInterfaceDecl*>(D)) {}
+ friend class ASTContext; // ASTContext creates these.
+ friend class ASTReader;
+ friend class ObjCInterfaceDecl;
+
+public:
+ /// 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;
+ }
+
+ // 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 {
+ QualType baseType = getBaseType();
+ while (const ObjCObjectType *ObjT = baseType->getAs<ObjCObjectType>()) {
+ if (const ObjCInterfaceType *T = dyn_cast<ObjCInterfaceType>(ObjT))
+ return T->getDecl();
+
+ baseType = ObjT->getBaseType();
+ }
+
+ return nullptr;
+}
+
+/// Represents 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,
+ Pointee->isDependentType(),
+ Pointee->isInstantiationDependentType(),
+ Pointee->isVariablyModifiedType(),
+ Pointee->containsUnexpandedParameterPack()),
+ PointeeType(Pointee) {}
+ friend class ASTContext; // ASTContext creates these.
+
+public:
+ /// Gets the type pointed to by this ObjC pointer.
+ /// The result will always be an ObjCObjectType or sugar thereof.
+ QualType getPointeeType() const { return PointeeType; }
+
+ /// Gets the type pointed to by this ObjC pointer. 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:
+ /// \code
+ /// \@class A; \@protocol P; \@protocol Q;
+ /// typedef A<P> AP;
+ /// typedef A A1;
+ /// typedef A1<P> A1P;
+ /// typedef A1P<Q> A1PQ;
+ /// \endcode
+ /// 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>();
+ }
+
+ /// 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;
+
+ /// 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();
+ }
+
+ /// 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();
+ }
+
+ /// 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();
+ }
+
+ /// True if this is equivalent to the 'id' or 'Class' type,
+ bool isObjCIdOrClassType() const {
+ return getObjectType()->isObjCUnqualifiedIdOrClass();
+ }
+
+ /// True if this is equivalent to 'id<P>' for some non-empty set of
+ /// protocols.
+ bool isObjCQualifiedIdType() const {
+ return getObjectType()->isObjCQualifiedId();
+ }
+
+ /// True if this is equivalent to 'Class<P>' for some non-empty set of
+ /// protocols.
+ bool isObjCQualifiedClassType() const {
+ return getObjectType()->isObjCQualifiedClass();
+ }
+
+ /// Whether this is a "__kindof" type.
+ bool isKindOfType() const { return getObjectType()->isKindOfType(); }
+
+ /// Whether this type is specialized, meaning that it has type arguments.
+ bool isSpecialized() const { return getObjectType()->isSpecialized(); }
+
+ /// Whether this type is specialized, meaning that it has type arguments.
+ bool isSpecializedAsWritten() const {
+ return getObjectType()->isSpecializedAsWritten();
+ }
+
+ /// Whether this type is unspecialized, meaning that is has no type arguments.
+ bool isUnspecialized() const { return getObjectType()->isUnspecialized(); }
+
+ /// Determine whether this object type is "unspecialized" as
+ /// written, meaning that it has no type arguments.
+ bool isUnspecializedAsWritten() const { return !isSpecializedAsWritten(); }
+
+ /// Retrieve the type arguments for this type.
+ ArrayRef<QualType> getTypeArgs() const {
+ return getObjectType()->getTypeArgs();
+ }
+
+ /// Retrieve the type arguments for this type.
+ ArrayRef<QualType> getTypeArgsAsWritten() const {
+ return getObjectType()->getTypeArgsAsWritten();
+ }
+
+ /// 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;
+ typedef llvm::iterator_range<qual_iterator> qual_range;
+
+ qual_range quals() const { return qual_range(qual_begin(), qual_end()); }
+ 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(); }
+
+ /// Return the number of qualifying protocols on the object type.
+ unsigned getNumProtocols() const {
+ return getObjectType()->getNumProtocols();
+ }
+
+ /// 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); }
+
+ /// Retrieve the type of the superclass of this object pointer type.
+ ///
+ /// This operation substitutes any type arguments into the
+ /// superclass of the current class type, potentially producing a
+ /// pointer to a specialization of the superclass type. Produces a
+ /// null type if there is no superclass.
+ QualType getSuperClassType() const;
+
+ /// Strip off the Objective-C "kindof" type and (with it) any
+ /// protocol qualifiers.
+ const ObjCObjectPointerType *stripObjCKindOfTypeAndQuals(
+ const ASTContext &ctx) const;
+
+ 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;
+ }
+};
+
+class AtomicType : public Type, public llvm::FoldingSetNode {
+ QualType ValueType;
+
+ AtomicType(QualType ValTy, QualType Canonical)
+ : Type(Atomic, Canonical, ValTy->isDependentType(),
+ ValTy->isInstantiationDependentType(),
+ ValTy->isVariablyModifiedType(),
+ ValTy->containsUnexpandedParameterPack()),
+ ValueType(ValTy) {}
+ friend class ASTContext; // ASTContext creates these.
+
+ public:
+ /// Gets the type contained by this atomic type, i.e.
+ /// the type returned by performing an atomic load of this atomic type.
+ QualType getValueType() const { return ValueType; }
+
+ bool isSugared() const { return false; }
+ QualType desugar() const { return QualType(this, 0); }
+
+ void Profile(llvm::FoldingSetNodeID &ID) {
+ Profile(ID, getValueType());
+ }
+ static void Profile(llvm::FoldingSetNodeID &ID, QualType T) {
+ ID.AddPointer(T.getAsOpaquePtr());
+ }
+ static bool classof(const Type *T) {
+ return T->getTypeClass() == Atomic;
+ }
+};
+
+/// 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 SplitQualType SplitQualType::getSingleStepDesugaredType() const {
+ SplitQualType desugar =
+ Ty->getLocallyUnqualifiedSingleStepDesugaredType().split();
+ desugar.Quals.addConsistentQualifiers(Quals);
+ return desugar;
+}
+
+inline const Type *QualType::getTypePtr() const {
+ return getCommonPtr()->BaseType;
+}
+
+inline const Type *QualType::getTypePtrOrNull() const {
+ return (isNull() ? nullptr : 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).Ty, 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);
+}
+
+/// Return the address space of this type.
+inline unsigned QualType::getAddressSpace() const {
+ return getQualifiers().getAddressSpace();
+}
+
+/// 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);
+}
+
+/// 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));
+}
+
+/// 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());
+}
+
+/// 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 QualType::isCForbiddenLValueType() const {
+ return ((getTypePtr()->isVoidType() && !hasQualifiers()) ||
+ getTypePtr()->isFunctionType());
+}
+
+/// Tests whether the type is categorized as a fundamental type.
+///
+/// \returns True for types specified in C++0x [basic.fundamental].
+inline bool Type::isFundamentalType() const {
+ return isVoidType() ||
+ // FIXME: It's really annoying that we don't have an
+ // 'isArithmeticType()' which agrees with the standard definition.
+ (isArithmeticType() && !isEnumeralType());
+}
+
+/// Tests whether the type is categorized as a compound type.
+///
+/// \returns True for types specified in C++0x [basic.compound].
+inline bool Type::isCompoundType() const {
+ // C++0x [basic.compound]p1:
+ // Compound types can be constructed in the following ways:
+ // -- arrays of objects of a given type [...];
+ return isArrayType() ||
+ // -- functions, which have parameters of given types [...];
+ isFunctionType() ||
+ // -- pointers to void or objects or functions [...];
+ isPointerType() ||
+ // -- references to objects or functions of a given type. [...]
+ isReferenceType() ||
+ // -- classes containing a sequence of objects of various types, [...];
+ isRecordType() ||
+ // -- unions, which are classes capable of containing objects of different
+ // types at different times;
+ isUnionType() ||
+ // -- enumerations, which comprise a set of named constant values. [...];
+ isEnumeralType() ||
+ // -- pointers to non-static class members, [...].
+ isMemberPointerType();
+}
+
+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::isAtomicType() const {
+ return isa<AtomicType>(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::isImage1dT() const {
+ return isSpecificBuiltinType(BuiltinType::OCLImage1d);
+}
+
+inline bool Type::isImage1dArrayT() const {
+ return isSpecificBuiltinType(BuiltinType::OCLImage1dArray);
+}
+
+inline bool Type::isImage1dBufferT() const {
+ return isSpecificBuiltinType(BuiltinType::OCLImage1dBuffer);
+}
+
+inline bool Type::isImage2dT() const {
+ return isSpecificBuiltinType(BuiltinType::OCLImage2d);
+}
+
+inline bool Type::isImage2dArrayT() const {
+ return isSpecificBuiltinType(BuiltinType::OCLImage2dArray);
+}
+
+inline bool Type::isImage2dDepthT() const {
+ return isSpecificBuiltinType(BuiltinType::OCLImage2dDepth);
+}
+
+inline bool Type::isImage2dArrayDepthT() const {
+ return isSpecificBuiltinType(BuiltinType::OCLImage2dArrayDepth);
+}
+
+inline bool Type::isImage2dMSAAT() const {
+ return isSpecificBuiltinType(BuiltinType::OCLImage2dMSAA);
+}
+
+inline bool Type::isImage2dArrayMSAAT() const {
+ return isSpecificBuiltinType(BuiltinType::OCLImage2dArrayMSAA);
+}
+
+inline bool Type::isImage2dMSAATDepth() const {
+ return isSpecificBuiltinType(BuiltinType::OCLImage2dMSAADepth);
+}
+
+inline bool Type::isImage2dArrayMSAATDepth() const {
+ return isSpecificBuiltinType(BuiltinType::OCLImage2dArrayMSAADepth);
+}
+
+inline bool Type::isImage3dT() const {
+ return isSpecificBuiltinType(BuiltinType::OCLImage3d);
+}
+
+inline bool Type::isSamplerT() const {
+ return isSpecificBuiltinType(BuiltinType::OCLSampler);
+}
+
+inline bool Type::isEventT() const {
+ return isSpecificBuiltinType(BuiltinType::OCLEvent);
+}
+
+inline bool Type::isClkEventT() const {
+ return isSpecificBuiltinType(BuiltinType::OCLClkEvent);
+}
+
+inline bool Type::isQueueT() const {
+ return isSpecificBuiltinType(BuiltinType::OCLQueue);
+}
+
+inline bool Type::isNDRangeT() const {
+ return isSpecificBuiltinType(BuiltinType::OCLNDRange);
+}
+
+inline bool Type::isReserveIDT() const {
+ return isSpecificBuiltinType(BuiltinType::OCLReserveID);
+}
+
+inline bool Type::isImageType() const {
+ return isImage3dT() || isImage2dT() || isImage2dArrayT() ||
+ isImage2dDepthT() || isImage2dArrayDepthT() || isImage2dMSAAT() ||
+ isImage2dArrayMSAAT() || isImage2dMSAATDepth() ||
+ isImage2dArrayMSAATDepth() || isImage1dT() || isImage1dArrayT() ||
+ isImage1dBufferT();
+}
+
+inline bool Type::isOpenCLSpecificType() const {
+ return isSamplerT() || isEventT() || isImageType() || isClkEventT() ||
+ isQueueT() || isNDRangeT() || isReserveIDT();
+}
+
+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 = dyn_cast<BuiltinType>(this))
+ return BT->isPlaceholderType();
+ return false;
+}
+
+inline const BuiltinType *Type::getAsPlaceholderType() const {
+ if (const BuiltinType *BT = dyn_cast<BuiltinType>(this))
+ if (BT->isPlaceholderType())
+ return BT;
+ return nullptr;
+}
+
+inline bool Type::isSpecificPlaceholderType(unsigned K) const {
+ assert(BuiltinType::isPlaceholderTypeKind((BuiltinType::Kind) K));
+ if (const BuiltinType *BT = dyn_cast<BuiltinType>(this))
+ return (BT->getKind() == (BuiltinType::Kind) K);
+ return false;
+}
+
+inline bool Type::isNonOverloadPlaceholderType() const {
+ if (const BuiltinType *BT = dyn_cast<BuiltinType>(this))
+ return BT->isNonOverloadPlaceholderType();
+ return false;
+}
+
+inline bool Type::isVoidType() const {
+ if (const BuiltinType *BT = dyn_cast<BuiltinType>(CanonicalType))
+ return BT->getKind() == BuiltinType::Void;
+ return false;
+}
+
+inline bool Type::isHalfType() const {
+ if (const BuiltinType *BT = dyn_cast<BuiltinType>(CanonicalType))
+ return BT->getKind() == BuiltinType::Half;
+ // FIXME: Should we allow complex __fp16? Probably not.
+ return false;
+}
+
+inline bool Type::isNullPtrType() const {
+ if (const BuiltinType *BT = getAs<BuiltinType>())
+ return BT->getKind() == BuiltinType::NullPtr;
+ return false;
+}
+
+extern bool IsEnumDeclComplete(EnumDecl *);
+extern bool IsEnumDeclScoped(EnumDecl *);
+
+inline 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 IsEnumDeclComplete(ET->getDecl()) &&
+ !IsEnumDeclScoped(ET->getDecl());
+ }
+ return false;
+}
+
+inline 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 IsEnumDeclComplete(ET->getDecl());
+ return isa<PointerType>(CanonicalType) ||
+ isa<BlockPointerType>(CanonicalType) ||
+ isa<MemberPointerType>(CanonicalType) ||
+ isa<ComplexType>(CanonicalType) ||
+ isa<ObjCObjectPointerType>(CanonicalType);
+}
+
+inline 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 IsEnumDeclComplete(ET->getDecl());
+
+ return false;
+}
+
+inline bool Type::isBooleanType() const {
+ if (const BuiltinType *BT = dyn_cast<BuiltinType>(CanonicalType))
+ return BT->getKind() == BuiltinType::Bool;
+ return false;
+}
+
+inline bool Type::isUndeducedType() const {
+ const AutoType *AT = getContainedAutoType();
+ return AT && !AT->isDeduced();
+}
+
+/// \brief Determines whether this is a type for which one can define
+/// an overloaded operator.
+inline bool Type::isOverloadableType() const {
+ return isDependentType() || isRecordType() || isEnumeralType();
+}
+
+/// \brief Determines whether this type can decay to a pointer type.
+inline bool Type::canDecayToPointerType() const {
+ return isFunctionType() || isArrayType();
+}
+
+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()),
+ DiagnosticsEngine::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()),
+ DiagnosticsEngine::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 = (std::is_same<T, ArrayType>::value ||
+ std::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 nullptr;
+
+ // 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 nullptr;
+
+ // 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;
+
+ if (const T *ty = dyn_cast<T>(this)) return ty;
+ assert(isa<T>(CanonicalType));
+ 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..26feda5
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/AST/TypeLoc.h
@@ -0,0 +1,2039 @@
+//===--- 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.
+//
+//===----------------------------------------------------------------------===//
+///
+/// \file
+/// \brief Defines the clang::TypeLoc interface and its subclasses.
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_AST_TYPELOC_H
+#define LLVM_CLANG_AST_TYPELOC_H
+
+#include "clang/AST/Decl.h"
+#include "clang/AST/TemplateBase.h"
+#include "clang/AST/Type.h"
+#include "clang/Basic/Specifiers.h"
+#include "llvm/Support/Compiler.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 castAs()/getAs()
+/// 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:
+ /// \brief Convert to the specified TypeLoc type, asserting that this TypeLoc
+ /// is of the desired type.
+ ///
+ /// \pre T::isKind(*this)
+ template<typename T>
+ T castAs() const {
+ assert(T::isKind(*this));
+ T t;
+ TypeLoc& tl = t;
+ tl = *this;
+ return t;
+ }
+
+ /// \brief Convert to the specified TypeLoc type, returning a null TypeLoc if
+ /// this TypeLoc is not of the desired type.
+ template<typename T>
+ T getAs() const {
+ if (!T::isKind(*this))
+ return T();
+ T t;
+ TypeLoc& tl = t;
+ tl = *this;
+ return t;
+ }
+
+ /// 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(nullptr), Data(nullptr) { }
+ 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; }
+ explicit 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 Returns the alignment of type source info data block for
+ /// the given type.
+ static unsigned getLocalAlignmentForType(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 LLVM_READONLY {
+ return SourceRange(getBeginLoc(), getEndLoc());
+ }
+ SourceLocation getLocStart() const LLVM_READONLY { return getBeginLoc(); }
+ SourceLocation getLocEnd() const LLVM_READONLY { return 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;
+
+ /// \brief Find a type with the location of an explicit type qualifier.
+ ///
+ /// The result, if non-null, will be one of:
+ /// QualifiedTypeLoc
+ /// AtomicTypeLoc
+ /// AttributedTypeLoc, for those type attributes that behave as qualifiers
+ TypeLoc findExplicitQualifierLoc() const;
+
+ /// \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) {
+ assert(getType() == Other.getType());
+ copy(Other);
+ }
+
+ /// \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) {
+ assert(getType() == Other.getType());
+ assert(getFullDataSize() == Size);
+ copy(Other);
+ }
+
+ /// Copies the other type loc into this one.
+ void copy(TypeLoc other);
+
+ 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);
+ }
+
+ /// Find the location of the nullability specifier (__nonnull,
+ /// __nullable, or __null_unspecifier), if there is one.
+ SourceLocation findNullabilityLoc() const;
+
+private:
+ static bool isKind(const TypeLoc&) {
+ return true;
+ }
+
+ 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 {
+ // TODO: is this alignment already sufficient?
+ 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();
+ }
+
+private:
+ friend class TypeLoc;
+ static bool isKind(const TypeLoc &TL) {
+ return !TL.getType().hasLocalQualifiers();
+ }
+};
+
+/// \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 {
+ unsigned align =
+ TypeLoc::getLocalAlignmentForType(QualType(getTypePtr(), 0));
+ uintptr_t dataInt = reinterpret_cast<uintptr_t>(Data);
+ dataInt = llvm::RoundUpToAlignment(dataInt, align);
+ return UnqualTypeLoc(getTypePtr(), reinterpret_cast<void*>(dataInt));
+ }
+
+ /// Initializes the local data of this type source info block to
+ /// provide no information.
+ void initializeLocal(ASTContext &Context, SourceLocation Loc) {
+ // do nothing
+ }
+
+ void copyLocal(TypeLoc other) {
+ // 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 alignment of the type source info data block that is
+ /// specific to this type.
+ unsigned getLocalDataAlignment() const {
+ // We don't preserve any location information.
+ return 1;
+ }
+
+private:
+ friend class TypeLoc;
+ static bool isKind(const TypeLoc &TL) {
+ return TL.getType().hasLocalQualifiers();
+ }
+};
+
+inline UnqualTypeLoc TypeLoc::getUnqualifiedLoc() const {
+ if (QualifiedTypeLoc Loc = getAs<QualifiedTypeLoc>())
+ return Loc.getUnqualifiedLoc();
+ return castAs<UnqualTypeLoc>();
+}
+
+/// 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.
+///
+/// \tparam Base a class from which to derive
+/// \tparam Derived the class deriving from this one
+/// \tparam TypeClass the concrete Type subclass associated with this
+/// location type
+/// \tparam LocalData the structure type of local location data for
+/// this type
+///
+/// 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);
+ }
+
+ friend class TypeLoc;
+ static bool isKind(const TypeLoc &TL) {
+ return !TL.getType().hasLocalQualifiers() &&
+ Derived::classofType(TL.getTypePtr());
+ }
+
+ static bool classofType(const Type *Ty) {
+ return TypeClass::classof(Ty);
+ }
+
+public:
+ unsigned getLocalDataAlignment() const {
+ return std::max(llvm::alignOf<LocalData>(),
+ asDerived()->getExtraLocalDataAlignment());
+ }
+ unsigned getLocalDataSize() const {
+ unsigned size = sizeof(LocalData);
+ unsigned extraAlign = asDerived()->getExtraLocalDataAlignment();
+ size = llvm::RoundUpToAlignment(size, extraAlign);
+ size += asDerived()->getExtraLocalDataSize();
+ return size;
+ }
+
+ void copyLocal(Derived other) {
+ // Some subclasses have no data to copy.
+ if (asDerived()->getLocalDataSize() == 0) return;
+
+ // Copy the fixed-sized local data.
+ memcpy(getLocalData(), other.getLocalData(), sizeof(LocalData));
+
+ // Copy the variable-sized local data. We need to do this
+ // separately because the padding in the source and the padding in
+ // the destination might be different.
+ memcpy(getExtraLocalData(), other.getExtraLocalData(),
+ asDerived()->getExtraLocalDataSize());
+ }
+
+ TypeLoc getNextTypeLoc() const {
+ return getNextTypeLoc(asDerived()->getInnerType());
+ }
+
+ const TypeClass *getTypePtr() const {
+ return cast<TypeClass>(Base::getTypePtr());
+ }
+
+protected:
+ unsigned getExtraLocalDataSize() const {
+ return 0;
+ }
+
+ unsigned getExtraLocalDataAlignment() const {
+ return 1;
+ }
+
+ 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 {
+ unsigned size = sizeof(LocalData);
+ unsigned extraAlign = asDerived()->getExtraLocalDataAlignment();
+ size = llvm::RoundUpToAlignment(size, extraAlign);
+ return reinterpret_cast<char*>(Base::Data) + size;
+ }
+
+ void *getNonLocalData() const {
+ uintptr_t data = reinterpret_cast<uintptr_t>(Base::Data);
+ data += asDerived()->getLocalDataSize();
+ data = llvm::RoundUpToAlignment(data, getNextTypeAlign());
+ return reinterpret_cast<void*>(data);
+ }
+
+ 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();
+ }
+
+ unsigned getNextTypeAlign() const {
+ return getNextTypeAlign(asDerived()->getInnerType());
+ }
+
+ unsigned getNextTypeAlign(HasNoInnerType _) const {
+ return 1;
+ }
+
+ unsigned getNextTypeAlign(QualType T) const {
+ return TypeLoc::getLocalAlignmentForType(T);
+ }
+
+ 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 {
+ friend class TypeLoc;
+ static bool classofType(const Type *Ty) {
+ return TypeClass::classof(Ty);
+ }
+
+ static bool isKind(const TypeLoc &TL) {
+ return !TL.getType().hasLocalQualifiers() &&
+ Derived::classofType(TL.getTypePtr());
+ }
+ static bool isKind(const UnqualTypeLoc &TL) {
+ return Derived::classofType(TL.getTypePtr());
+ }
+
+public:
+ 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),
+ LocalDataAlignment = llvm::AlignOf<TypeSpecLocInfo>::Alignment };
+
+ 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);
+ }
+
+private:
+ friend class TypeLoc;
+ static bool isKind(const TypeLoc &TL);
+};
+
+
+struct BuiltinLocInfo {
+ SourceLocation BuiltinLoc;
+};
+
+/// \brief Wrapper for source info for builtin types.
+class BuiltinTypeLoc : public ConcreteTypeLoc<UnqualTypeLoc,
+ BuiltinTypeLoc,
+ BuiltinType,
+ BuiltinLocInfo> {
+public:
+ 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;
+ }
+
+ unsigned getExtraLocalDataAlignment() const {
+ return needsExtraLocalData() ? llvm::alignOf<WrittenBuiltinSpecs>() : 1;
+ }
+
+ 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:
+ TypedefNameDecl *getTypedefNameDecl() const {
+ return getTypePtr()->getDecl();
+ }
+};
+
+/// \brief Wrapper for source info for injected class names of class
+/// templates.
+class InjectedClassNameTypeLoc :
+ public InheritingConcreteTypeLoc<TypeSpecTypeLoc,
+ InjectedClassNameTypeLoc,
+ InjectedClassNameType> {
+public:
+ CXXRecordDecl *getDecl() const {
+ return getTypePtr()->getDecl();
+ }
+};
+
+/// \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 True if the tag was defined in this type specifier.
+ bool isDefinition() const {
+ TagDecl *D = getDecl();
+ return D->isCompleteDefinition() &&
+ (D->getIdentifier() == nullptr || D->getLocation() == getNameLoc());
+ }
+};
+
+/// \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> {
+public:
+ TemplateTypeParmDecl *getDecl() const { return getTypePtr()->getDecl(); }
+};
+
+/// \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();
+ }
+
+ bool isQualifier() const {
+ return getTypePtr()->isQualifier();
+ }
+
+ /// 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(nullptr);
+ } else if (hasAttrEnumOperand()) {
+ setAttrOperandParensRange(SourceRange(loc));
+ setAttrEnumOperandLoc(loc);
+ }
+ }
+
+ QualType getInnerType() const {
+ return getTypePtr()->getModifiedType();
+ }
+};
+
+
+struct ObjCObjectTypeLocInfo {
+ SourceLocation TypeArgsLAngleLoc;
+ SourceLocation TypeArgsRAngleLoc;
+ SourceLocation ProtocolLAngleLoc;
+ SourceLocation ProtocolRAngleLoc;
+ 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,
+ ObjCObjectTypeLocInfo> {
+ // TypeSourceInfo*'s are stored after Info, one for each type argument.
+ TypeSourceInfo **getTypeArgLocArray() const {
+ return (TypeSourceInfo**)this->getExtraLocalData();
+ }
+
+ // SourceLocations are stored after the type argument information, one for
+ // each Protocol.
+ SourceLocation *getProtocolLocArray() const {
+ return (SourceLocation*)(getTypeArgLocArray() + getNumTypeArgs());
+ }
+
+public:
+ SourceLocation getTypeArgsLAngleLoc() const {
+ return this->getLocalData()->TypeArgsLAngleLoc;
+ }
+ void setTypeArgsLAngleLoc(SourceLocation Loc) {
+ this->getLocalData()->TypeArgsLAngleLoc = Loc;
+ }
+
+ SourceLocation getTypeArgsRAngleLoc() const {
+ return this->getLocalData()->TypeArgsRAngleLoc;
+ }
+ void setTypeArgsRAngleLoc(SourceLocation Loc) {
+ this->getLocalData()->TypeArgsRAngleLoc = Loc;
+ }
+
+ unsigned getNumTypeArgs() const {
+ return this->getTypePtr()->getTypeArgsAsWritten().size();
+ }
+
+ TypeSourceInfo *getTypeArgTInfo(unsigned i) const {
+ assert(i < getNumTypeArgs() && "Index is out of bounds!");
+ return getTypeArgLocArray()[i];
+ }
+
+ void setTypeArgTInfo(unsigned i, TypeSourceInfo *TInfo) {
+ assert(i < getNumTypeArgs() && "Index is out of bounds!");
+ getTypeArgLocArray()[i] = TInfo;
+ }
+
+ SourceLocation getProtocolLAngleLoc() const {
+ return this->getLocalData()->ProtocolLAngleLoc;
+ }
+ void setProtocolLAngleLoc(SourceLocation Loc) {
+ this->getLocalData()->ProtocolLAngleLoc = Loc;
+ }
+
+ SourceLocation getProtocolRAngleLoc() const {
+ return this->getLocalData()->ProtocolRAngleLoc;
+ }
+ void setProtocolRAngleLoc(SourceLocation Loc) {
+ this->getLocalData()->ProtocolRAngleLoc = 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);
+ }
+
+
+ ArrayRef<SourceLocation> getProtocolLocs() const {
+ return llvm::makeArrayRef(getProtocolLocArray(), getNumProtocols());
+ }
+
+ bool hasBaseTypeAsWritten() const {
+ return getLocalData()->HasBaseTypeAsWritten;
+ }
+
+ void setHasBaseTypeAsWritten(bool HasBaseType) {
+ getLocalData()->HasBaseTypeAsWritten = HasBaseType;
+ }
+
+ TypeLoc getBaseLoc() const {
+ return getInnerTypeLoc();
+ }
+
+ SourceRange getLocalSourceRange() const {
+ SourceLocation start = getTypeArgsLAngleLoc();
+ if (start.isInvalid())
+ start = getProtocolLAngleLoc();
+ SourceLocation end = getProtocolRAngleLoc();
+ if (end.isInvalid())
+ end = getTypeArgsRAngleLoc();
+ return SourceRange(start, end);
+ }
+
+ void initializeLocal(ASTContext &Context, SourceLocation Loc);
+
+ unsigned getExtraLocalDataSize() const {
+ return this->getNumTypeArgs() * sizeof(TypeSourceInfo *)
+ + this->getNumProtocols() * sizeof(SourceLocation);
+ }
+
+ unsigned getExtraLocalDataAlignment() const {
+ assert(llvm::alignOf<ObjCObjectTypeLoc>()
+ >= llvm::alignOf<TypeSourceInfo *>() &&
+ "not enough alignment for tail-allocated data");
+ return llvm::alignOf<TypeSourceInfo *>();
+ }
+
+ QualType getInnerType() const {
+ return getTypePtr()->getBaseType();
+ }
+};
+
+
+struct ObjCInterfaceLocInfo {
+ SourceLocation NameLoc;
+ SourceLocation NameEndLoc;
+};
+
+/// \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(), getNameEndLoc());
+ }
+
+ SourceLocation getNameEndLoc() const {
+ return getLocalData()->NameEndLoc;
+ }
+
+ void setNameEndLoc(SourceLocation Loc) {
+ getLocalData()->NameEndLoc = Loc;
+ }
+
+ void initializeLocal(ASTContext &Context, SourceLocation Loc) {
+ setNameLoc(Loc);
+ setNameEndLoc(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();
+ }
+};
+
+inline TypeLoc TypeLoc::IgnoreParens() const {
+ if (ParenTypeLoc::isKind(*this))
+ return IgnoreParensImpl(*this);
+ return *this;
+}
+
+
+struct AdjustedLocInfo { }; // Nothing.
+
+class AdjustedTypeLoc : public ConcreteTypeLoc<UnqualTypeLoc, AdjustedTypeLoc,
+ AdjustedType, AdjustedLocInfo> {
+public:
+ TypeLoc getOriginalLoc() const {
+ return getInnerTypeLoc();
+ }
+
+ void initializeLocal(ASTContext &Context, SourceLocation Loc) {
+ // do nothing
+ }
+
+ QualType getInnerType() const {
+ // The inner type is the undecayed type, since that's what we have source
+ // location information for.
+ return getTypePtr()->getOriginalType();
+ }
+
+ SourceRange getLocalSourceRange() const {
+ return SourceRange();
+ }
+
+ unsigned getLocalDataSize() const {
+ // sizeof(AdjustedLocInfo) is 1, but we don't need its address to be unique
+ // anyway. TypeLocBuilder can't handle data sizes of 1.
+ return 0; // No data.
+ }
+};
+
+/// \brief Wrapper for source info for pointers decayed from arrays and
+/// functions.
+class DecayedTypeLoc : public InheritingConcreteTypeLoc<
+ AdjustedTypeLoc, DecayedTypeLoc, DecayedType> {
+};
+
+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);
+ }
+};
+
+struct MemberPointerLocInfo : public PointerLikeLocInfo {
+ TypeSourceInfo *ClassTInfo;
+};
+
+/// \brief Wrapper for source info for member pointers.
+class MemberPointerTypeLoc : public PointerLikeTypeLoc<MemberPointerTypeLoc,
+ MemberPointerType,
+ MemberPointerLocInfo> {
+public:
+ SourceLocation getStarLoc() const {
+ return getSigilLoc();
+ }
+ void setStarLoc(SourceLocation Loc) {
+ setSigilLoc(Loc);
+ }
+
+ const Type *getClass() const {
+ return getTypePtr()->getClass();
+ }
+ TypeSourceInfo *getClassTInfo() const {
+ return getLocalData()->ClassTInfo;
+ }
+ void setClassTInfo(TypeSourceInfo* TI) {
+ getLocalData()->ClassTInfo = TI;
+ }
+
+ void initializeLocal(ASTContext &Context, SourceLocation Loc) {
+ setSigilLoc(Loc);
+ setClassTInfo(nullptr);
+ }
+
+ SourceRange getLocalSourceRange() const {
+ if (TypeSourceInfo *TI = getClassTInfo())
+ return SourceRange(TI->getTypeLoc().getBeginLoc(), getStarLoc());
+ else
+ return SourceRange(getStarLoc());
+ }
+};
+
+/// 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 LocalRangeBegin;
+ SourceLocation LParenLoc;
+ SourceLocation RParenLoc;
+ SourceLocation LocalRangeEnd;
+};
+
+/// \brief Wrapper for source info for functions.
+class FunctionTypeLoc : public ConcreteTypeLoc<UnqualTypeLoc,
+ FunctionTypeLoc,
+ FunctionType,
+ FunctionLocInfo> {
+public:
+ SourceLocation getLocalRangeBegin() const {
+ return getLocalData()->LocalRangeBegin;
+ }
+ void setLocalRangeBegin(SourceLocation L) {
+ getLocalData()->LocalRangeBegin = L;
+ }
+
+ SourceLocation getLocalRangeEnd() const {
+ return getLocalData()->LocalRangeEnd;
+ }
+ void setLocalRangeEnd(SourceLocation L) {
+ getLocalData()->LocalRangeEnd = L;
+ }
+
+ 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());
+ }
+
+ ArrayRef<ParmVarDecl *> getParams() const {
+ return llvm::makeArrayRef(getParmArray(), getNumParams());
+ }
+
+ // ParmVarDecls* are stored after Info, one for each parameter.
+ ParmVarDecl **getParmArray() const {
+ return (ParmVarDecl**) getExtraLocalData();
+ }
+
+ unsigned getNumParams() const {
+ if (isa<FunctionNoProtoType>(getTypePtr()))
+ return 0;
+ return cast<FunctionProtoType>(getTypePtr())->getNumParams();
+ }
+ ParmVarDecl *getParam(unsigned i) const { return getParmArray()[i]; }
+ void setParam(unsigned i, ParmVarDecl *VD) { getParmArray()[i] = VD; }
+
+ TypeLoc getReturnLoc() const {
+ return getInnerTypeLoc();
+ }
+
+ SourceRange getLocalSourceRange() const {
+ return SourceRange(getLocalRangeBegin(), getLocalRangeEnd());
+ }
+
+ void initializeLocal(ASTContext &Context, SourceLocation Loc) {
+ setLocalRangeBegin(Loc);
+ setLParenLoc(Loc);
+ setRParenLoc(Loc);
+ setLocalRangeEnd(Loc);
+ for (unsigned i = 0, e = getNumParams(); i != e; ++i)
+ setParam(i, nullptr);
+ }
+
+ /// \brief Returns the size of the type source info data block that is
+ /// specific to this type.
+ unsigned getExtraLocalDataSize() const {
+ return getNumParams() * sizeof(ParmVarDecl *);
+ }
+
+ unsigned getExtraLocalDataAlignment() const {
+ return llvm::alignOf<ParmVarDecl*>();
+ }
+
+ QualType getInnerType() const { return getTypePtr()->getReturnType(); }
+};
+
+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(nullptr);
+ }
+
+ 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 TemplateKWLoc;
+ SourceLocation LAngleLoc;
+ SourceLocation RAngleLoc;
+};
+
+class TemplateSpecializationTypeLoc :
+ public ConcreteTypeLoc<UnqualTypeLoc,
+ TemplateSpecializationTypeLoc,
+ TemplateSpecializationType,
+ TemplateSpecializationLocInfo> {
+public:
+ SourceLocation getTemplateKeywordLoc() const {
+ return getLocalData()->TemplateKWLoc;
+ }
+ void setTemplateKeywordLoc(SourceLocation Loc) {
+ getLocalData()->TemplateKWLoc = Loc;
+ }
+
+ 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 {
+ if (getTemplateKeywordLoc().isValid())
+ return SourceRange(getTemplateKeywordLoc(), getRAngleLoc());
+ else
+ return SourceRange(getTemplateNameLoc(), getRAngleLoc());
+ }
+
+ void initializeLocal(ASTContext &Context, SourceLocation Loc) {
+ setTemplateKeywordLoc(Loc);
+ setTemplateNameLoc(Loc);
+ setLAngleLoc(Loc);
+ setRAngleLoc(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);
+ }
+
+ unsigned getExtraLocalDataAlignment() const {
+ return llvm::alignOf<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;
+ }
+
+ void initializeLocal(ASTContext &Context, SourceLocation Loc);
+};
+
+// FIXME: location of the 'decltype' and parens.
+class DecltypeTypeLoc : public InheritingConcreteTypeLoc<TypeSpecTypeLoc,
+ DecltypeTypeLoc,
+ DecltypeType> {
+public:
+ Expr *getUnderlyingExpr() const { return getTypePtr()->getUnderlyingExpr(); }
+};
+
+struct UnaryTransformTypeLocInfo {
+ // FIXME: While there's only one unary transform right now, future ones may
+ // need different representations
+ SourceLocation KWLoc, LParenLoc, RParenLoc;
+ TypeSourceInfo *UnderlyingTInfo;
+};
+
+class UnaryTransformTypeLoc : public ConcreteTypeLoc<UnqualTypeLoc,
+ UnaryTransformTypeLoc,
+ UnaryTransformType,
+ UnaryTransformTypeLocInfo> {
+public:
+ SourceLocation getKWLoc() const { return getLocalData()->KWLoc; }
+ void setKWLoc(SourceLocation Loc) { getLocalData()->KWLoc = Loc; }
+
+ 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; }
+
+ TypeSourceInfo* getUnderlyingTInfo() const {
+ return getLocalData()->UnderlyingTInfo;
+ }
+ void setUnderlyingTInfo(TypeSourceInfo *TInfo) {
+ getLocalData()->UnderlyingTInfo = TInfo;
+ }
+
+ SourceRange getLocalSourceRange() const {
+ return SourceRange(getKWLoc(), getRParenLoc());
+ }
+
+ SourceRange getParensRange() const {
+ return SourceRange(getLParenLoc(), getRParenLoc());
+ }
+ void setParensRange(SourceRange Range) {
+ setLParenLoc(Range.getBegin());
+ setRParenLoc(Range.getEnd());
+ }
+
+ void initializeLocal(ASTContext &Context, SourceLocation Loc) {
+ setKWLoc(Loc);
+ setRParenLoc(Loc);
+ setLParenLoc(Loc);
+ }
+};
+
+class AutoTypeLoc : public InheritingConcreteTypeLoc<TypeSpecTypeLoc,
+ AutoTypeLoc,
+ AutoType> {
+};
+
+struct ElaboratedLocInfo {
+ SourceLocation ElaboratedKWLoc;
+ /// \brief Data associated with the nested-name-specifier location.
+ void *QualifierData;
+};
+
+class ElaboratedTypeLoc : public ConcreteTypeLoc<UnqualTypeLoc,
+ ElaboratedTypeLoc,
+ ElaboratedType,
+ ElaboratedLocInfo> {
+public:
+ SourceLocation getElaboratedKeywordLoc() const {
+ return this->getLocalData()->ElaboratedKWLoc;
+ }
+ void setElaboratedKeywordLoc(SourceLocation Loc) {
+ this->getLocalData()->ElaboratedKWLoc = Loc;
+ }
+
+ NestedNameSpecifierLoc getQualifierLoc() const {
+ return NestedNameSpecifierLoc(getTypePtr()->getQualifier(),
+ getLocalData()->QualifierData);
+ }
+
+ void setQualifierLoc(NestedNameSpecifierLoc QualifierLoc) {
+ assert(QualifierLoc.getNestedNameSpecifier()
+ == getTypePtr()->getQualifier() &&
+ "Inconsistent nested-name-specifier pointer");
+ getLocalData()->QualifierData = QualifierLoc.getOpaqueData();
+ }
+
+ SourceRange getLocalSourceRange() const {
+ if (getElaboratedKeywordLoc().isValid())
+ if (getQualifierLoc())
+ return SourceRange(getElaboratedKeywordLoc(),
+ getQualifierLoc().getEndLoc());
+ else
+ return SourceRange(getElaboratedKeywordLoc());
+ else
+ return getQualifierLoc().getSourceRange();
+ }
+
+ void initializeLocal(ASTContext &Context, SourceLocation 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 getElaboratedKeywordLoc() const {
+ return this->getLocalData()->ElaboratedKWLoc;
+ }
+ void setElaboratedKeywordLoc(SourceLocation Loc) {
+ this->getLocalData()->ElaboratedKWLoc = Loc;
+ }
+
+ NestedNameSpecifierLoc getQualifierLoc() const {
+ return NestedNameSpecifierLoc(getTypePtr()->getQualifier(),
+ getLocalData()->QualifierData);
+ }
+
+ void setQualifierLoc(NestedNameSpecifierLoc QualifierLoc) {
+ assert(QualifierLoc.getNestedNameSpecifier()
+ == getTypePtr()->getQualifier() &&
+ "Inconsistent nested-name-specifier pointer");
+ getLocalData()->QualifierData = QualifierLoc.getOpaqueData();
+ }
+
+ SourceLocation getNameLoc() const {
+ return this->getLocalData()->NameLoc;
+ }
+ void setNameLoc(SourceLocation Loc) {
+ this->getLocalData()->NameLoc = Loc;
+ }
+
+ SourceRange getLocalSourceRange() const {
+ if (getElaboratedKeywordLoc().isValid())
+ return SourceRange(getElaboratedKeywordLoc(), getNameLoc());
+ else
+ return SourceRange(getQualifierLoc().getBeginLoc(), getNameLoc());
+ }
+
+ void copy(DependentNameTypeLoc Loc) {
+ unsigned size = getFullDataSize();
+ assert(size == Loc.getFullDataSize());
+ memcpy(Data, Loc.Data, size);
+ }
+
+ void initializeLocal(ASTContext &Context, SourceLocation Loc);
+};
+
+struct DependentTemplateSpecializationLocInfo : DependentNameLocInfo {
+ SourceLocation TemplateKWLoc;
+ SourceLocation LAngleLoc;
+ SourceLocation RAngleLoc;
+ // followed by a TemplateArgumentLocInfo[]
+};
+
+class DependentTemplateSpecializationTypeLoc :
+ public ConcreteTypeLoc<UnqualTypeLoc,
+ DependentTemplateSpecializationTypeLoc,
+ DependentTemplateSpecializationType,
+ DependentTemplateSpecializationLocInfo> {
+public:
+ SourceLocation getElaboratedKeywordLoc() const {
+ return this->getLocalData()->ElaboratedKWLoc;
+ }
+ void setElaboratedKeywordLoc(SourceLocation Loc) {
+ this->getLocalData()->ElaboratedKWLoc = Loc;
+ }
+
+ NestedNameSpecifierLoc getQualifierLoc() const {
+ if (!getLocalData()->QualifierData)
+ return NestedNameSpecifierLoc();
+
+ return NestedNameSpecifierLoc(getTypePtr()->getQualifier(),
+ getLocalData()->QualifierData);
+ }
+
+ void setQualifierLoc(NestedNameSpecifierLoc QualifierLoc) {
+ if (!QualifierLoc) {
+ // Even if we have a nested-name-specifier in the dependent
+ // template specialization type, we won't record the nested-name-specifier
+ // location information when this type-source location information is
+ // part of a nested-name-specifier.
+ getLocalData()->QualifierData = nullptr;
+ return;
+ }
+
+ assert(QualifierLoc.getNestedNameSpecifier()
+ == getTypePtr()->getQualifier() &&
+ "Inconsistent nested-name-specifier pointer");
+ getLocalData()->QualifierData = QualifierLoc.getOpaqueData();
+ }
+
+ SourceLocation getTemplateKeywordLoc() const {
+ return getLocalData()->TemplateKWLoc;
+ }
+ void setTemplateKeywordLoc(SourceLocation Loc) {
+ getLocalData()->TemplateKWLoc = Loc;
+ }
+
+ SourceLocation getTemplateNameLoc() const {
+ return this->getLocalData()->NameLoc;
+ }
+ void setTemplateNameLoc(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 (getElaboratedKeywordLoc().isValid())
+ return SourceRange(getElaboratedKeywordLoc(), getRAngleLoc());
+ else if (getQualifierLoc())
+ return SourceRange(getQualifierLoc().getBeginLoc(), getRAngleLoc());
+ else if (getTemplateKeywordLoc().isValid())
+ return SourceRange(getTemplateKeywordLoc(), getRAngleLoc());
+ else
+ return SourceRange(getTemplateNameLoc(), getRAngleLoc());
+ }
+
+ void copy(DependentTemplateSpecializationTypeLoc Loc) {
+ unsigned size = getFullDataSize();
+ assert(size == Loc.getFullDataSize());
+ memcpy(Data, Loc.Data, size);
+ }
+
+ void initializeLocal(ASTContext &Context, SourceLocation Loc);
+
+ unsigned getExtraLocalDataSize() const {
+ return getNumArgs() * sizeof(TemplateArgumentLocInfo);
+ }
+
+ unsigned getExtraLocalDataAlignment() const {
+ return llvm::alignOf<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();
+ }
+};
+
+struct AtomicTypeLocInfo {
+ SourceLocation KWLoc, LParenLoc, RParenLoc;
+};
+
+class AtomicTypeLoc : public ConcreteTypeLoc<UnqualTypeLoc, AtomicTypeLoc,
+ AtomicType, AtomicTypeLocInfo> {
+public:
+ TypeLoc getValueLoc() const {
+ return this->getInnerTypeLoc();
+ }
+
+ SourceRange getLocalSourceRange() const {
+ return SourceRange(getKWLoc(), getRParenLoc());
+ }
+
+ SourceLocation getKWLoc() const {
+ return this->getLocalData()->KWLoc;
+ }
+ void setKWLoc(SourceLocation Loc) {
+ this->getLocalData()->KWLoc = 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());
+ }
+
+ void initializeLocal(ASTContext &Context, SourceLocation Loc) {
+ setKWLoc(Loc);
+ setLParenLoc(Loc);
+ setRParenLoc(Loc);
+ }
+
+ QualType getInnerType() const {
+ return this->getTypePtr()->getValueType();
+ }
+};
+
+
+}
+
+#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..db5775a
--- /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(TyLoc.castAs<CLASSNAME>())
+
+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..2549f0b
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/AST/TypeNodes.def
@@ -0,0 +1,129 @@
+//===-- 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 five 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_TYPE(Adjusted, Type)
+NON_CANONICAL_TYPE(Decayed, AdjustedType)
+NON_CANONICAL_UNLESS_DEPENDENT_TYPE(TypeOfExpr, Type)
+NON_CANONICAL_UNLESS_DEPENDENT_TYPE(TypeOf, Type)
+NON_CANONICAL_UNLESS_DEPENDENT_TYPE(Decltype, Type)
+NON_CANONICAL_UNLESS_DEPENDENT_TYPE(UnaryTransform, 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)
+TYPE(Auto, Type)
+DEPENDENT_TYPE(InjectedClassName, Type)
+DEPENDENT_TYPE(DependentName, Type)
+DEPENDENT_TYPE(DependentTemplateSpecialization, Type)
+NON_CANONICAL_UNLESS_DEPENDENT_TYPE(PackExpansion, Type)
+TYPE(ObjCObject, Type)
+TYPE(ObjCInterface, ObjCObjectType)
+TYPE(ObjCObjectPointer, Type)
+TYPE(Atomic, Type)
+
+#ifdef LAST_TYPE
+LAST_TYPE(Atomic)
+#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..392e544
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/AST/TypeOrdering.h
@@ -0,0 +1,79 @@
+//===-------------- 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.
+//
+//===----------------------------------------------------------------------===//
+///
+/// \file
+/// \brief Allows QualTypes to be sorted and hence used in maps and sets.
+///
+/// Defines clang::QualTypeOrdering, a total ordering on clang::QualType,
+/// and hence enables QualType values to be sorted and to be used in
+/// std::maps, std::sets, llvm::DenseMaps, and llvm::DenseSets.
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_AST_TYPEORDERING_H
+#define LLVM_CLANG_AST_TYPEORDERING_H
+
+#include "clang/AST/CanonicalType.h"
+#include "clang/AST/Type.h"
+#include <functional>
+
+namespace clang {
+
+/// \brief 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..11e5a47
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/AST/TypeVisitor.h
@@ -0,0 +1,95 @@
+//===--- 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))
+
+/// \brief An operation on a type.
+///
+/// \tparam ImplClass Class implementing the operation. Must be inherited from
+/// TypeVisitor.
+/// \tparam RetTy %Type of result produced by the operation.
+///
+/// The class implements polymorphic operation on an object of type derived
+/// from Type. The operation is performed by calling method Visit. It then
+/// dispatches the call to function \c VisitFooType, if actual argument type
+/// is \c FooType.
+///
+/// The class implements static polymorphism using Curiously Recurring
+/// Template Pattern. It is designed to be a base class for some concrete
+/// class:
+///
+/// \code
+/// class SomeVisitor : public TypeVisitor<SomeVisitor,sometype> { ... };
+/// ...
+/// Type *atype = ...
+/// ...
+/// SomeVisitor avisitor;
+/// sometype result = avisitor.Visit(atype);
+/// \endcode
+///
+/// Actual treatment is made by methods of the derived class, TypeVisitor only
+/// dispatches call to the appropriate method. If the implementation class
+/// \c ImplClass provides specific action for some type, say
+/// \c ConstantArrayType, it should define method
+/// <tt>VisitConstantArrayType(const ConstantArrayType*)</tt>. Otherwise
+/// \c TypeVisitor dispatches call to the method that handles parent type. In
+/// this example handlers are tried in the sequence:
+///
+/// \li <tt>ImplClass::VisitConstantArrayType(const ConstantArrayType*)</tt>
+/// \li <tt>ImplClass::VisitArrayType(const ArrayType*)</tt>
+/// \li <tt>ImplClass::VisitType(const Type*)</tt>
+/// \li <tt>TypeVisitor::VisitType(const Type*)</tt>
+///
+/// The first function of this sequence that is defined will handle object of
+/// type \c ConstantArrayType.
+template<typename ImplClass, typename RetTy=void>
+class TypeVisitor {
+public:
+
+ /// \brief Performs the operation associated with this visitor object.
+ RetTy Visit(const Type *T) {
+ // Top switch stmt: dispatch to VisitFooType for each FooType.
+ switch (T->getTypeClass()) {
+#define ABSTRACT_TYPE(CLASS, PARENT)
+#define TYPE(CLASS, PARENT) case Type::CLASS: DISPATCH(CLASS##Type);
+#include "clang/AST/TypeNodes.def"
+ }
+ llvm_unreachable("Unknown type class!");
+ }
+
+ // 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"
+
+ /// \brief Method called if \c ImpClass doesn't provide specific handler
+ /// for some type class.
+ 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..26ee1cf
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/AST/UnresolvedSet.h
@@ -0,0 +1,140 @@
+//===-- 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 "clang/AST/DeclAccessPair.h"
+#include "clang/Basic/LLVM.h"
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/iterator.h"
+
+namespace clang {
+
+/// The iterator over UnresolvedSets. Serves as both the const and
+/// non-const iterator.
+class UnresolvedSetIterator : public llvm::iterator_adaptor_base<
+ UnresolvedSetIterator, DeclAccessPair *,
+ std::random_access_iterator_tag, NamedDecl *,
+ std::ptrdiff_t, NamedDecl *, NamedDecl *> {
+ friend class UnresolvedSetImpl;
+ friend class ASTUnresolvedSet;
+ friend class OverloadExpr;
+
+ explicit UnresolvedSetIterator(DeclAccessPair *Iter)
+ : iterator_adaptor_base(Iter) {}
+ explicit UnresolvedSetIterator(const DeclAccessPair *Iter)
+ : iterator_adaptor_base(const_cast<DeclAccessPair *>(Iter)) {}
+
+public:
+ UnresolvedSetIterator() {}
+
+ NamedDecl *getDecl() const { return I->getDecl(); }
+ void setDecl(NamedDecl *ND) const { return I->setDecl(ND); }
+ AccessSpecifier getAccess() const { return I->getAccess(); }
+ void setAccess(AccessSpecifier AS) { I->setAccess(AS); }
+ const DeclAccessPair &getPair() const { return *I; }
+
+ NamedDecl *operator*() const { return getDecl(); }
+ NamedDecl *operator->() const { return **this; }
+};
+
+/// \brief A set of unresolved declarations.
+class UnresolvedSetImpl {
+ typedef SmallVectorImpl<DeclAccessPair> 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.I->setDecl(New); }
+
+ void replace(iterator I, NamedDecl *New, AccessSpecifier AS) {
+ I.I->set(New, AS);
+ }
+
+ void erase(unsigned I) { decls()[I] = decls().pop_back_val(); }
+
+ void erase(iterator I) { *I.I = decls().pop_back_val(); }
+
+ void setAccess(iterator I, AccessSpecifier AS) { I.I->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.I, E.I); }
+
+ 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);
+ }
+};
+
+/// \brief A set of unresolved declarations.
+template <unsigned InlineCapacity> class UnresolvedSet :
+ public UnresolvedSetImpl {
+ SmallVector<DeclAccessPair, InlineCapacity> Decls;
+};
+
+
+} // namespace clang
+
+#endif
diff --git a/contrib/llvm/tools/clang/include/clang/AST/VTTBuilder.h b/contrib/llvm/tools/clang/include/clang/AST/VTTBuilder.h
new file mode 100644
index 0000000..727bf51
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/AST/VTTBuilder.h
@@ -0,0 +1,162 @@
+//===--- VTTBuilder.h - C++ VTT layout builder --------------------*- C++ -*-=//
+//
+// 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 generation of the layout of virtual table
+// tables (VTT).
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_AST_VTTBUILDER_H
+#define LLVM_CLANG_AST_VTTBUILDER_H
+
+#include "clang/AST/BaseSubobject.h"
+#include "clang/AST/CXXInheritance.h"
+#include "clang/AST/GlobalDecl.h"
+#include "clang/AST/RecordLayout.h"
+#include "clang/Basic/ABI.h"
+#include "llvm/ADT/SetVector.h"
+#include <utility>
+
+namespace clang {
+
+class VTTVTable {
+ llvm::PointerIntPair<const CXXRecordDecl *, 1, bool> BaseAndIsVirtual;
+ CharUnits BaseOffset;
+
+public:
+ VTTVTable() {}
+ VTTVTable(const CXXRecordDecl *Base, CharUnits BaseOffset, bool BaseIsVirtual)
+ : BaseAndIsVirtual(Base, BaseIsVirtual), BaseOffset(BaseOffset) {}
+ VTTVTable(BaseSubobject Base, bool BaseIsVirtual)
+ : BaseAndIsVirtual(Base.getBase(), BaseIsVirtual),
+ BaseOffset(Base.getBaseOffset()) {}
+
+ const CXXRecordDecl *getBase() const {
+ return BaseAndIsVirtual.getPointer();
+ }
+
+ CharUnits getBaseOffset() const {
+ return BaseOffset;
+ }
+
+ bool isVirtual() const {
+ return BaseAndIsVirtual.getInt();
+ }
+
+ BaseSubobject getBaseSubobject() const {
+ return BaseSubobject(getBase(), getBaseOffset());
+ }
+};
+
+struct VTTComponent {
+ uint64_t VTableIndex;
+ BaseSubobject VTableBase;
+
+ VTTComponent() {}
+ VTTComponent(uint64_t VTableIndex, BaseSubobject VTableBase)
+ : VTableIndex(VTableIndex), VTableBase(VTableBase) {}
+};
+
+/// \brief Class for building VTT layout information.
+class VTTBuilder {
+
+ ASTContext &Ctx;
+
+ /// \brief The most derived class for which we're building this vtable.
+ const CXXRecordDecl *MostDerivedClass;
+
+ typedef SmallVector<VTTVTable, 64> VTTVTablesVectorTy;
+
+ /// \brief The VTT vtables.
+ VTTVTablesVectorTy VTTVTables;
+
+ typedef SmallVector<VTTComponent, 64> VTTComponentsVectorTy;
+
+ /// \brief The VTT components.
+ VTTComponentsVectorTy VTTComponents;
+
+ /// \brief 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;
+
+ /// \brief The sub-VTT indices for the bases of the most derived class.
+ llvm::DenseMap<BaseSubobject, uint64_t> SubVTTIndicies;
+
+ /// \brief The secondary virtual pointer indices of all subobjects of
+ /// the most derived class.
+ llvm::DenseMap<BaseSubobject, uint64_t> SecondaryVirtualPointerIndices;
+
+ /// \brief Whether the VTT builder should generate LLVM IR for the VTT.
+ bool GenerateDefinition;
+
+ /// \brief Add a vtable pointer to the VTT currently being built.
+ void AddVTablePointer(BaseSubobject Base, uint64_t VTableIndex,
+ const CXXRecordDecl *VTableClass);
+
+ /// \brief Lay out the secondary VTTs of the given base subobject.
+ void LayoutSecondaryVTTs(BaseSubobject Base);
+
+ /// \brief 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.
+ void LayoutSecondaryVirtualPointers(BaseSubobject Base,
+ bool BaseIsMorallyVirtual,
+ uint64_t VTableIndex,
+ const CXXRecordDecl *VTableClass,
+ VisitedVirtualBasesSetTy &VBases);
+
+ /// \brief Lay out the secondary virtual pointers for the given base
+ /// subobject.
+ void LayoutSecondaryVirtualPointers(BaseSubobject Base,
+ uint64_t VTableIndex);
+
+ /// \brief Lay out the VTTs for the virtual base classes of the given
+ /// record declaration.
+ void LayoutVirtualVTTs(const CXXRecordDecl *RD,
+ VisitedVirtualBasesSetTy &VBases);
+
+ /// \brief 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(ASTContext &Ctx, const CXXRecordDecl *MostDerivedClass,
+ bool GenerateDefinition);
+
+ // \brief Returns a reference to the VTT components.
+ const VTTComponentsVectorTy &getVTTComponents() const {
+ return VTTComponents;
+ }
+
+ // \brief Returns a reference to the VTT vtables.
+ const VTTVTablesVectorTy &getVTTVTables() const {
+ return VTTVTables;
+ }
+
+ /// \brief Returns a reference to the sub-VTT indices.
+ const llvm::DenseMap<BaseSubobject, uint64_t> &getSubVTTIndicies() const {
+ return SubVTTIndicies;
+ }
+
+ /// \brief Returns a reference to the secondary virtual pointer indices.
+ const llvm::DenseMap<BaseSubobject, uint64_t> &
+ getSecondaryVirtualPointerIndices() const {
+ return SecondaryVirtualPointerIndices;
+ }
+
+};
+
+}
+
+#endif
diff --git a/contrib/llvm/tools/clang/include/clang/AST/VTableBuilder.h b/contrib/llvm/tools/clang/include/clang/AST/VTableBuilder.h
new file mode 100644
index 0000000..481fd11
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/AST/VTableBuilder.h
@@ -0,0 +1,566 @@
+//===--- VTableBuilder.h - C++ vtable layout builder --------------*- C++ -*-=//
+//
+// 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 generation of the layout of virtual tables.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_AST_VTABLEBUILDER_H
+#define LLVM_CLANG_AST_VTABLEBUILDER_H
+
+#include "clang/AST/BaseSubobject.h"
+#include "clang/AST/CXXInheritance.h"
+#include "clang/AST/GlobalDecl.h"
+#include "clang/AST/RecordLayout.h"
+#include "clang/Basic/ABI.h"
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/SetVector.h"
+#include <memory>
+#include <utility>
+
+namespace clang {
+ class CXXRecordDecl;
+
+/// \brief Represents a single component in a vtable.
+class VTableComponent {
+public:
+ enum Kind {
+ CK_VCallOffset,
+ CK_VBaseOffset,
+ CK_OffsetToTop,
+ CK_RTTI,
+ CK_FunctionPointer,
+
+ /// \brief A pointer to the complete destructor.
+ CK_CompleteDtorPointer,
+
+ /// \brief A pointer to the deleting destructor.
+ CK_DeletingDtorPointer,
+
+ /// \brief An entry that is never used.
+ ///
+ /// 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
+ };
+
+ VTableComponent() = default;
+
+ static VTableComponent MakeVCallOffset(CharUnits Offset) {
+ return VTableComponent(CK_VCallOffset, Offset);
+ }
+
+ static VTableComponent MakeVBaseOffset(CharUnits Offset) {
+ return VTableComponent(CK_VBaseOffset, Offset);
+ }
+
+ static VTableComponent MakeOffsetToTop(CharUnits 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);
+ }
+
+ /// \brief Get the kind of this vtable component.
+ Kind getKind() const {
+ return (Kind)(Value & 0x7);
+ }
+
+ CharUnits getVCallOffset() const {
+ assert(getKind() == CK_VCallOffset && "Invalid component kind!");
+
+ return getOffset();
+ }
+
+ CharUnits getVBaseOffset() const {
+ assert(getKind() == CK_VBaseOffset && "Invalid component kind!");
+
+ return getOffset();
+ }
+
+ CharUnits getOffsetToTop() const {
+ assert(getKind() == CK_OffsetToTop && "Invalid component kind!");
+
+ return getOffset();
+ }
+
+ const CXXRecordDecl *getRTTIDecl() const {
+ assert(isRTTIKind() && "Invalid component kind!");
+ return reinterpret_cast<CXXRecordDecl *>(getPointer());
+ }
+
+ const CXXMethodDecl *getFunctionDecl() const {
+ assert(isFunctionPointerKind() && "Invalid component kind!");
+ if (isDestructorKind())
+ return getDestructorDecl();
+ return reinterpret_cast<CXXMethodDecl *>(getPointer());
+ }
+
+ const CXXDestructorDecl *getDestructorDecl() const {
+ assert(isDestructorKind() && "Invalid component kind!");
+ return reinterpret_cast<CXXDestructorDecl *>(getPointer());
+ }
+
+ const CXXMethodDecl *getUnusedFunctionDecl() const {
+ assert(getKind() == CK_UnusedFunctionPointer && "Invalid component kind!");
+ return reinterpret_cast<CXXMethodDecl *>(getPointer());
+ }
+
+ bool isDestructorKind() const { return isDestructorKind(getKind()); }
+
+ bool isUsedFunctionPointerKind() const {
+ return isUsedFunctionPointerKind(getKind());
+ }
+
+ bool isFunctionPointerKind() const {
+ return isFunctionPointerKind(getKind());
+ }
+
+ bool isRTTIKind() const { return isRTTIKind(getKind()); }
+
+private:
+ static bool isFunctionPointerKind(Kind ComponentKind) {
+ return isUsedFunctionPointerKind(ComponentKind) ||
+ ComponentKind == CK_UnusedFunctionPointer;
+ }
+ static bool isUsedFunctionPointerKind(Kind ComponentKind) {
+ return ComponentKind == CK_FunctionPointer ||
+ isDestructorKind(ComponentKind);
+ }
+ static bool isDestructorKind(Kind ComponentKind) {
+ return ComponentKind == CK_CompleteDtorPointer ||
+ ComponentKind == CK_DeletingDtorPointer;
+ }
+ static bool isRTTIKind(Kind ComponentKind) {
+ return ComponentKind == CK_RTTI;
+ }
+
+ VTableComponent(Kind ComponentKind, CharUnits Offset) {
+ assert((ComponentKind == CK_VCallOffset ||
+ ComponentKind == CK_VBaseOffset ||
+ ComponentKind == CK_OffsetToTop) && "Invalid component kind!");
+ assert(Offset.getQuantity() < (1LL << 56) && "Offset is too big!");
+ assert(Offset.getQuantity() >= -(1LL << 56) && "Offset is too small!");
+
+ Value = (uint64_t(Offset.getQuantity()) << 3) | ComponentKind;
+ }
+
+ VTableComponent(Kind ComponentKind, uintptr_t Ptr) {
+ assert((isRTTIKind(ComponentKind) || isFunctionPointerKind(ComponentKind)) &&
+ "Invalid component kind!");
+
+ assert((Ptr & 7) == 0 && "Pointer not sufficiently aligned!");
+
+ Value = Ptr | ComponentKind;
+ }
+
+ CharUnits getOffset() const {
+ assert((getKind() == CK_VCallOffset || getKind() == CK_VBaseOffset ||
+ getKind() == CK_OffsetToTop) && "Invalid component kind!");
+
+ return CharUnits::fromQuantity(Value >> 3);
+ }
+
+ uintptr_t getPointer() const {
+ assert((getKind() == CK_RTTI || isFunctionPointerKind()) &&
+ "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 bits 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;
+};
+
+class VTableLayout {
+public:
+ typedef std::pair<uint64_t, ThunkInfo> VTableThunkTy;
+
+ typedef const VTableComponent *vtable_component_iterator;
+ typedef const VTableThunkTy *vtable_thunk_iterator;
+ typedef llvm::iterator_range<vtable_component_iterator>
+ vtable_component_range;
+
+ typedef llvm::DenseMap<BaseSubobject, uint64_t> AddressPointsMapTy;
+
+private:
+ uint64_t NumVTableComponents;
+ std::unique_ptr<VTableComponent[]> VTableComponents;
+
+ /// \brief Contains thunks needed by vtables, sorted by indices.
+ uint64_t NumVTableThunks;
+ std::unique_ptr<VTableThunkTy[]> VTableThunks;
+
+ /// \brief Address points for all vtables.
+ AddressPointsMapTy AddressPoints;
+
+ bool IsMicrosoftABI;
+
+public:
+ VTableLayout(uint64_t NumVTableComponents,
+ const VTableComponent *VTableComponents,
+ uint64_t NumVTableThunks,
+ const VTableThunkTy *VTableThunks,
+ const AddressPointsMapTy &AddressPoints,
+ bool IsMicrosoftABI);
+ ~VTableLayout();
+
+ uint64_t getNumVTableComponents() const {
+ return NumVTableComponents;
+ }
+
+ vtable_component_range vtable_components() const {
+ return vtable_component_range(vtable_component_begin(),
+ vtable_component_end());
+ }
+
+ vtable_component_iterator vtable_component_begin() const {
+ return VTableComponents.get();
+ }
+
+ vtable_component_iterator vtable_component_end() const {
+ return VTableComponents.get() + NumVTableComponents;
+ }
+
+ uint64_t getNumVTableThunks() const { return NumVTableThunks; }
+
+ vtable_thunk_iterator vtable_thunk_begin() const {
+ return VTableThunks.get();
+ }
+
+ vtable_thunk_iterator vtable_thunk_end() const {
+ return VTableThunks.get() + NumVTableThunks;
+ }
+
+ uint64_t getAddressPoint(BaseSubobject Base) const {
+ assert(AddressPoints.count(Base) &&
+ "Did not find address point!");
+
+ uint64_t AddressPoint = AddressPoints.lookup(Base);
+ assert(AddressPoint != 0 || IsMicrosoftABI);
+ (void)IsMicrosoftABI;
+
+ return AddressPoint;
+ }
+
+ const AddressPointsMapTy &getAddressPoints() const {
+ return AddressPoints;
+ }
+};
+
+class VTableContextBase {
+public:
+ typedef SmallVector<ThunkInfo, 1> ThunkInfoVectorTy;
+
+ bool isMicrosoft() const { return IsMicrosoftABI; }
+
+ virtual ~VTableContextBase() {}
+
+protected:
+ typedef llvm::DenseMap<const CXXMethodDecl *, ThunkInfoVectorTy> ThunksMapTy;
+
+ /// \brief Contains all thunks that a given method decl will need.
+ ThunksMapTy Thunks;
+
+ /// Compute and store all vtable related information (vtable layout, vbase
+ /// offset offsets, thunks etc) for the given record decl.
+ virtual void computeVTableRelatedInformation(const CXXRecordDecl *RD) = 0;
+
+ VTableContextBase(bool MS) : IsMicrosoftABI(MS) {}
+
+public:
+ virtual const ThunkInfoVectorTy *getThunkInfo(GlobalDecl GD) {
+ const CXXMethodDecl *MD = cast<CXXMethodDecl>(GD.getDecl()->getCanonicalDecl());
+ computeVTableRelatedInformation(MD->getParent());
+
+ // This assumes that all the destructors present in the vtable
+ // use exactly the same set of thunks.
+ ThunksMapTy::const_iterator I = Thunks.find(MD);
+ if (I == Thunks.end()) {
+ // We did not find a thunk for this method.
+ return nullptr;
+ }
+
+ return &I->second;
+ }
+
+ bool IsMicrosoftABI;
+};
+
+class ItaniumVTableContext : public VTableContextBase {
+private:
+
+ /// \brief 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 llvm::DenseMap<const CXXRecordDecl *, const VTableLayout *>
+ VTableLayoutMapTy;
+ VTableLayoutMapTy VTableLayouts;
+
+ typedef std::pair<const CXXRecordDecl *,
+ const CXXRecordDecl *> ClassPairTy;
+
+ /// \brief vtable offsets for offsets of virtual bases of a class.
+ ///
+ /// Contains the vtable offset (relative to the address point) in chars
+ /// where the offsets for virtual bases of a class are stored.
+ typedef llvm::DenseMap<ClassPairTy, CharUnits>
+ VirtualBaseClassOffsetOffsetsMapTy;
+ VirtualBaseClassOffsetOffsetsMapTy VirtualBaseClassOffsetOffsets;
+
+ void computeVTableRelatedInformation(const CXXRecordDecl *RD) override;
+
+public:
+ ItaniumVTableContext(ASTContext &Context);
+ ~ItaniumVTableContext() override;
+
+ const VTableLayout &getVTableLayout(const CXXRecordDecl *RD) {
+ computeVTableRelatedInformation(RD);
+ assert(VTableLayouts.count(RD) && "No layout for this record decl!");
+
+ return *VTableLayouts[RD];
+ }
+
+ VTableLayout *
+ createConstructionVTableLayout(const CXXRecordDecl *MostDerivedClass,
+ CharUnits MostDerivedClassOffset,
+ bool MostDerivedClassIsVirtual,
+ const CXXRecordDecl *LayoutClass);
+
+ /// \brief Locate a virtual function in the vtable.
+ ///
+ /// 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);
+
+ /// Return the offset in chars (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 unambiguous base.
+ CharUnits getVirtualBaseOffsetOffset(const CXXRecordDecl *RD,
+ const CXXRecordDecl *VBase);
+
+ static bool classof(const VTableContextBase *VT) {
+ return !VT->isMicrosoft();
+ }
+};
+
+/// Holds information about the inheritance path to a virtual base or function
+/// table pointer. A record may contain as many vfptrs or vbptrs as there are
+/// base subobjects.
+struct VPtrInfo {
+ typedef SmallVector<const CXXRecordDecl *, 1> BasePath;
+
+ VPtrInfo(const CXXRecordDecl *RD)
+ : ReusingBase(RD), BaseWithVPtr(RD), NextBaseToMangle(RD) {}
+
+ /// The vtable will hold all of the virtual bases or virtual methods of
+ /// ReusingBase. This may or may not be the same class as VPtrSubobject.Base.
+ /// A derived class will reuse the vptr of the first non-virtual base
+ /// subobject that has one.
+ const CXXRecordDecl *ReusingBase;
+
+ /// BaseWithVPtr is at this offset from its containing complete object or
+ /// virtual base.
+ CharUnits NonVirtualOffset;
+
+ /// The vptr is stored inside this subobject.
+ const CXXRecordDecl *BaseWithVPtr;
+
+ /// The bases from the inheritance path that got used to mangle the vbtable
+ /// name. This is not really a full path like a CXXBasePath. It holds the
+ /// subset of records that need to be mangled into the vbtable symbol name in
+ /// order to get a unique name.
+ BasePath MangledPath;
+
+ /// The next base to push onto the mangled path if this path is ambiguous in a
+ /// derived class. If it's null, then it's already been pushed onto the path.
+ const CXXRecordDecl *NextBaseToMangle;
+
+ /// The set of possibly indirect vbases that contain this vbtable. When a
+ /// derived class indirectly inherits from the same vbase twice, we only keep
+ /// vtables and their paths from the first instance.
+ BasePath ContainingVBases;
+
+ /// This holds the base classes path from the complete type to the first base
+ /// with the given vfptr offset, in the base-to-derived order. Only used for
+ /// vftables.
+ BasePath PathToBaseWithVPtr;
+
+ /// Static offset from the top of the most derived class to this vfptr,
+ /// including any virtual base offset. Only used for vftables.
+ CharUnits FullOffsetInMDC;
+
+ /// The vptr is stored inside the non-virtual component of this virtual base.
+ const CXXRecordDecl *getVBaseWithVPtr() const {
+ return ContainingVBases.empty() ? nullptr : ContainingVBases.front();
+ }
+};
+
+typedef SmallVector<VPtrInfo *, 2> VPtrInfoVector;
+
+/// All virtual base related information about a given record decl. Includes
+/// information on all virtual base tables and the path components that are used
+/// to mangle them.
+struct VirtualBaseInfo {
+ ~VirtualBaseInfo() { llvm::DeleteContainerPointers(VBPtrPaths); }
+
+ /// A map from virtual base to vbtable index for doing a conversion from the
+ /// the derived class to the a base.
+ llvm::DenseMap<const CXXRecordDecl *, unsigned> VBTableIndices;
+
+ /// Information on all virtual base tables used when this record is the most
+ /// derived class.
+ VPtrInfoVector VBPtrPaths;
+};
+
+class MicrosoftVTableContext : public VTableContextBase {
+public:
+ struct MethodVFTableLocation {
+ /// If nonzero, holds the vbtable index of the virtual base with the vfptr.
+ uint64_t VBTableIndex;
+
+ /// If nonnull, holds the last vbase which contains the vfptr that the
+ /// method definition is adjusted to.
+ const CXXRecordDecl *VBase;
+
+ /// This is the offset of the vfptr from the start of the last vbase, or the
+ /// complete type if there are no virtual bases.
+ CharUnits VFPtrOffset;
+
+ /// Method's index in the vftable.
+ uint64_t Index;
+
+ MethodVFTableLocation()
+ : VBTableIndex(0), VBase(nullptr), VFPtrOffset(CharUnits::Zero()),
+ Index(0) {}
+
+ MethodVFTableLocation(uint64_t VBTableIndex, const CXXRecordDecl *VBase,
+ CharUnits VFPtrOffset, uint64_t Index)
+ : VBTableIndex(VBTableIndex), VBase(VBase),
+ VFPtrOffset(VFPtrOffset), Index(Index) {}
+
+ bool operator<(const MethodVFTableLocation &other) const {
+ if (VBTableIndex != other.VBTableIndex) {
+ assert(VBase != other.VBase);
+ return VBTableIndex < other.VBTableIndex;
+ }
+ return std::tie(VFPtrOffset, Index) <
+ std::tie(other.VFPtrOffset, other.Index);
+ }
+ };
+
+private:
+ ASTContext &Context;
+
+ typedef llvm::DenseMap<GlobalDecl, MethodVFTableLocation>
+ MethodVFTableLocationsTy;
+ MethodVFTableLocationsTy MethodVFTableLocations;
+
+ typedef llvm::DenseMap<const CXXRecordDecl *, VPtrInfoVector *>
+ VFPtrLocationsMapTy;
+ VFPtrLocationsMapTy VFPtrLocations;
+
+ typedef std::pair<const CXXRecordDecl *, CharUnits> VFTableIdTy;
+ typedef llvm::DenseMap<VFTableIdTy, const VTableLayout *> VFTableLayoutMapTy;
+ VFTableLayoutMapTy VFTableLayouts;
+
+ llvm::DenseMap<const CXXRecordDecl *, VirtualBaseInfo *> VBaseInfo;
+
+ void enumerateVFPtrs(const CXXRecordDecl *ForClass, VPtrInfoVector &Result);
+
+ void computeVTableRelatedInformation(const CXXRecordDecl *RD) override;
+
+ void dumpMethodLocations(const CXXRecordDecl *RD,
+ const MethodVFTableLocationsTy &NewMethods,
+ raw_ostream &);
+
+ const VirtualBaseInfo *
+ computeVBTableRelatedInformation(const CXXRecordDecl *RD);
+
+ void computeVTablePaths(bool ForVBTables, const CXXRecordDecl *RD,
+ VPtrInfoVector &Paths);
+
+public:
+ MicrosoftVTableContext(ASTContext &Context)
+ : VTableContextBase(/*MS=*/true), Context(Context) {}
+
+ ~MicrosoftVTableContext() override;
+
+ const VPtrInfoVector &getVFPtrOffsets(const CXXRecordDecl *RD);
+
+ const VTableLayout &getVFTableLayout(const CXXRecordDecl *RD,
+ CharUnits VFPtrOffset);
+
+ const MethodVFTableLocation &getMethodVFTableLocation(GlobalDecl GD);
+
+ const ThunkInfoVectorTy *getThunkInfo(GlobalDecl GD) override {
+ // Complete destructors don't have a slot in a vftable, so no thunks needed.
+ if (isa<CXXDestructorDecl>(GD.getDecl()) &&
+ GD.getDtorType() == Dtor_Complete)
+ return nullptr;
+ return VTableContextBase::getThunkInfo(GD);
+ }
+
+ /// \brief Returns the index of VBase in the vbtable of Derived.
+ /// VBase must be a morally virtual base of Derived.
+ /// The vbtable is an array of i32 offsets. The first entry is a self entry,
+ /// and the rest are offsets from the vbptr to virtual bases.
+ unsigned getVBTableIndex(const CXXRecordDecl *Derived,
+ const CXXRecordDecl *VBase);
+
+ const VPtrInfoVector &enumerateVBTables(const CXXRecordDecl *RD);
+
+ static bool classof(const VTableContextBase *VT) { return VT->isMicrosoft(); }
+};
+
+} // namespace clang
+
+#endif
diff --git a/contrib/llvm/tools/clang/include/clang/ASTMatchers/ASTMatchFinder.h b/contrib/llvm/tools/clang/include/clang/ASTMatchers/ASTMatchFinder.h
new file mode 100644
index 0000000..92ec92c
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/ASTMatchers/ASTMatchFinder.h
@@ -0,0 +1,294 @@
+//===--- ASTMatchFinder.h - Structural query framework ----------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// Provides a way to construct an ASTConsumer that runs given matchers
+// over the AST and invokes a given callback on every match.
+//
+// The general idea is to construct a matcher expression that describes a
+// subtree match on the AST. Next, a callback that is executed every time the
+// expression matches is registered, and the matcher is run over the AST of
+// some code. Matched subexpressions can be bound to string IDs and easily
+// be accessed from the registered callback. The callback can than use the
+// AST nodes that the subexpressions matched on to output information about
+// the match or construct changes that can be applied to the code.
+//
+// Example:
+// class HandleMatch : public MatchFinder::MatchCallback {
+// public:
+// virtual void Run(const MatchFinder::MatchResult &Result) {
+// const CXXRecordDecl *Class =
+// Result.Nodes.GetDeclAs<CXXRecordDecl>("id");
+// ...
+// }
+// };
+//
+// int main(int argc, char **argv) {
+// ClangTool Tool(argc, argv);
+// MatchFinder finder;
+// finder.AddMatcher(Id("id", record(hasName("::a_namespace::AClass"))),
+// new HandleMatch);
+// return Tool.Run(newFrontendActionFactory(&finder));
+// }
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_ASTMATCHERS_ASTMATCHFINDER_H
+#define LLVM_CLANG_ASTMATCHERS_ASTMATCHFINDER_H
+
+#include "clang/ASTMatchers/ASTMatchers.h"
+#include "llvm/ADT/SmallPtrSet.h"
+#include "llvm/ADT/StringMap.h"
+#include "llvm/Support/Timer.h"
+
+namespace clang {
+
+namespace ast_matchers {
+
+/// \brief A class to allow finding matches over the Clang AST.
+///
+/// After creation, you can add multiple matchers to the MatchFinder via
+/// calls to addMatcher(...).
+///
+/// Once all matchers are added, newASTConsumer() returns an ASTConsumer
+/// that will trigger the callbacks specified via addMatcher(...) when a match
+/// is found.
+///
+/// The order of matches is guaranteed to be equivalent to doing a pre-order
+/// traversal on the AST, and applying the matchers in the order in which they
+/// were added to the MatchFinder.
+///
+/// See ASTMatchers.h for more information about how to create matchers.
+///
+/// Not intended to be subclassed.
+class MatchFinder {
+public:
+ /// \brief Contains all information for a given match.
+ ///
+ /// Every time a match is found, the MatchFinder will invoke the registered
+ /// MatchCallback with a MatchResult containing information about the match.
+ struct MatchResult {
+ MatchResult(const BoundNodes &Nodes, clang::ASTContext *Context);
+
+ /// \brief Contains the nodes bound on the current match.
+ ///
+ /// This allows user code to easily extract matched AST nodes.
+ const BoundNodes Nodes;
+
+ /// \brief Utilities for interpreting the matched AST structures.
+ /// @{
+ clang::ASTContext * const Context;
+ clang::SourceManager * const SourceManager;
+ /// @}
+ };
+
+ /// \brief Called when the Match registered for it was successfully found
+ /// in the AST.
+ class MatchCallback {
+ public:
+ virtual ~MatchCallback();
+
+ /// \brief Called on every match by the \c MatchFinder.
+ virtual void run(const MatchResult &Result) = 0;
+
+ /// \brief Called at the start of each translation unit.
+ ///
+ /// Optionally override to do per translation unit tasks.
+ virtual void onStartOfTranslationUnit() {}
+
+ /// \brief Called at the end of each translation unit.
+ ///
+ /// Optionally override to do per translation unit tasks.
+ virtual void onEndOfTranslationUnit() {}
+
+ /// \brief An id used to group the matchers.
+ ///
+ /// This id is used, for example, for the profiling output.
+ /// It defaults to "<unknown>".
+ virtual StringRef getID() const;
+ };
+
+ /// \brief Called when parsing is finished. Intended for testing only.
+ class ParsingDoneTestCallback {
+ public:
+ virtual ~ParsingDoneTestCallback();
+ virtual void run() = 0;
+ };
+
+ struct MatchFinderOptions {
+ struct Profiling {
+ Profiling(llvm::StringMap<llvm::TimeRecord> &Records)
+ : Records(Records) {}
+
+ /// \brief Per bucket timing information.
+ llvm::StringMap<llvm::TimeRecord> &Records;
+ };
+
+ /// \brief Enables per-check timers.
+ ///
+ /// It prints a report after match.
+ llvm::Optional<Profiling> CheckProfiling;
+ };
+
+ MatchFinder(MatchFinderOptions Options = MatchFinderOptions());
+ ~MatchFinder();
+
+ /// \brief Adds a matcher to execute when running over the AST.
+ ///
+ /// Calls 'Action' with the BoundNodes on every match.
+ /// Adding more than one 'NodeMatch' allows finding different matches in a
+ /// single pass over the AST.
+ ///
+ /// Does not take ownership of 'Action'.
+ /// @{
+ void addMatcher(const DeclarationMatcher &NodeMatch,
+ MatchCallback *Action);
+ void addMatcher(const TypeMatcher &NodeMatch,
+ MatchCallback *Action);
+ void addMatcher(const StatementMatcher &NodeMatch,
+ MatchCallback *Action);
+ void addMatcher(const NestedNameSpecifierMatcher &NodeMatch,
+ MatchCallback *Action);
+ void addMatcher(const NestedNameSpecifierLocMatcher &NodeMatch,
+ MatchCallback *Action);
+ void addMatcher(const TypeLocMatcher &NodeMatch,
+ MatchCallback *Action);
+ /// @}
+
+ /// \brief Adds a matcher to execute when running over the AST.
+ ///
+ /// This is similar to \c addMatcher(), but it uses the dynamic interface. It
+ /// is more flexible, but the lost type information enables a caller to pass
+ /// a matcher that cannot match anything.
+ ///
+ /// \returns \c true if the matcher is a valid top-level matcher, \c false
+ /// otherwise.
+ bool addDynamicMatcher(const internal::DynTypedMatcher &NodeMatch,
+ MatchCallback *Action);
+
+ /// \brief Creates a clang ASTConsumer that finds all matches.
+ std::unique_ptr<clang::ASTConsumer> newASTConsumer();
+
+ /// \brief Calls the registered callbacks on all matches on the given \p Node.
+ ///
+ /// Note that there can be multiple matches on a single node, for
+ /// example when using decl(forEachDescendant(stmt())).
+ ///
+ /// @{
+ template <typename T> void match(const T &Node, ASTContext &Context) {
+ match(clang::ast_type_traits::DynTypedNode::create(Node), Context);
+ }
+ void match(const clang::ast_type_traits::DynTypedNode &Node,
+ ASTContext &Context);
+ /// @}
+
+ /// \brief Finds all matches in the given AST.
+ void matchAST(ASTContext &Context);
+
+ /// \brief Registers a callback to notify the end of parsing.
+ ///
+ /// The provided closure is called after parsing is done, before the AST is
+ /// traversed. Useful for benchmarking.
+ /// Each call to FindAll(...) will call the closure once.
+ void registerTestCallbackAfterParsing(ParsingDoneTestCallback *ParsingDone);
+
+ /// \brief For each \c Matcher<> a \c MatchCallback that will be called
+ /// when it matches.
+ struct MatchersByType {
+ std::vector<std::pair<internal::DynTypedMatcher, MatchCallback *>>
+ DeclOrStmt;
+ std::vector<std::pair<TypeMatcher, MatchCallback *>> Type;
+ std::vector<std::pair<NestedNameSpecifierMatcher, MatchCallback *>>
+ NestedNameSpecifier;
+ std::vector<std::pair<NestedNameSpecifierLocMatcher, MatchCallback *>>
+ NestedNameSpecifierLoc;
+ std::vector<std::pair<TypeLocMatcher, MatchCallback *>> TypeLoc;
+ /// \brief All the callbacks in one container to simplify iteration.
+ llvm::SmallPtrSet<MatchCallback *, 16> AllCallbacks;
+ };
+
+private:
+ MatchersByType Matchers;
+
+ MatchFinderOptions Options;
+
+ /// \brief Called when parsing is done.
+ ParsingDoneTestCallback *ParsingDone;
+};
+
+/// \brief Returns the results of matching \p Matcher on \p Node.
+///
+/// Collects the \c BoundNodes of all callback invocations when matching
+/// \p Matcher on \p Node and returns the collected results.
+///
+/// Multiple results occur when using matchers like \c forEachDescendant,
+/// which generate a result for each sub-match.
+///
+/// \see selectFirst
+/// @{
+template <typename MatcherT, typename NodeT>
+SmallVector<BoundNodes, 1>
+match(MatcherT Matcher, const NodeT &Node, ASTContext &Context);
+
+template <typename MatcherT>
+SmallVector<BoundNodes, 1>
+match(MatcherT Matcher, const ast_type_traits::DynTypedNode &Node,
+ ASTContext &Context);
+/// @}
+
+/// \brief Returns the first result of type \c NodeT bound to \p BoundTo.
+///
+/// Returns \c NULL if there is no match, or if the matching node cannot be
+/// casted to \c NodeT.
+///
+/// This is useful in combanation with \c match():
+/// \code
+/// const Decl *D = selectFirst<Decl>("id", match(Matcher.bind("id"),
+/// Node, Context));
+/// \endcode
+template <typename NodeT>
+const NodeT *
+selectFirst(StringRef BoundTo, const SmallVectorImpl<BoundNodes> &Results) {
+ for (const BoundNodes &N : Results) {
+ if (const NodeT *Node = N.getNodeAs<NodeT>(BoundTo))
+ return Node;
+ }
+ return nullptr;
+}
+
+namespace internal {
+class CollectMatchesCallback : public MatchFinder::MatchCallback {
+public:
+ void run(const MatchFinder::MatchResult &Result) override {
+ Nodes.push_back(Result.Nodes);
+ }
+ SmallVector<BoundNodes, 1> Nodes;
+};
+}
+
+template <typename MatcherT>
+SmallVector<BoundNodes, 1>
+match(MatcherT Matcher, const ast_type_traits::DynTypedNode &Node,
+ ASTContext &Context) {
+ internal::CollectMatchesCallback Callback;
+ MatchFinder Finder;
+ Finder.addMatcher(Matcher, &Callback);
+ Finder.match(Node, Context);
+ return std::move(Callback.Nodes);
+}
+
+template <typename MatcherT, typename NodeT>
+SmallVector<BoundNodes, 1>
+match(MatcherT Matcher, const NodeT &Node, ASTContext &Context) {
+ return match(Matcher, ast_type_traits::DynTypedNode::create(Node), Context);
+}
+
+} // end namespace ast_matchers
+} // end namespace clang
+
+#endif
diff --git a/contrib/llvm/tools/clang/include/clang/ASTMatchers/ASTMatchers.h b/contrib/llvm/tools/clang/include/clang/ASTMatchers/ASTMatchers.h
new file mode 100644
index 0000000..e6ba877
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/ASTMatchers/ASTMatchers.h
@@ -0,0 +1,4671 @@
+//===--- ASTMatchers.h - Structural query framework -------------*- 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 matchers to be used together with the MatchFinder to
+// match AST nodes.
+//
+// Matchers are created by generator functions, which can be combined in
+// a functional in-language DSL to express queries over the C++ AST.
+//
+// For example, to match a class with a certain name, one would call:
+// cxxRecordDecl(hasName("MyClass"))
+// which returns a matcher that can be used to find all AST nodes that declare
+// a class named 'MyClass'.
+//
+// For more complicated match expressions we're often interested in accessing
+// multiple parts of the matched AST nodes once a match is found. In that case,
+// use the id(...) matcher around the match expressions that match the nodes
+// you want to access.
+//
+// For example, when we're interested in child classes of a certain class, we
+// would write:
+// cxxRecordDecl(hasName("MyClass"), hasChild(id("child", recordDecl())))
+// When the match is found via the MatchFinder, a user provided callback will
+// be called with a BoundNodes instance that contains a mapping from the
+// strings that we provided for the id(...) calls to the nodes that were
+// matched.
+// In the given example, each time our matcher finds a match we get a callback
+// where "child" is bound to the RecordDecl node of the matching child
+// class declaration.
+//
+// See ASTMatchersInternal.h for a more in-depth explanation of the
+// implementation details of the matcher framework.
+//
+// See ASTMatchFinder.h for how to use the generated matchers to run over
+// an AST.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_ASTMATCHERS_ASTMATCHERS_H
+#define LLVM_CLANG_ASTMATCHERS_ASTMATCHERS_H
+
+#include "clang/AST/ASTContext.h"
+#include "clang/AST/DeclFriend.h"
+#include "clang/AST/DeclObjC.h"
+#include "clang/AST/DeclTemplate.h"
+#include "clang/ASTMatchers/ASTMatchersInternal.h"
+#include "clang/ASTMatchers/ASTMatchersMacros.h"
+#include "llvm/ADT/Twine.h"
+#include "llvm/Support/Regex.h"
+#include <iterator>
+
+namespace clang {
+namespace ast_matchers {
+
+/// \brief Maps string IDs to AST nodes matched by parts of a matcher.
+///
+/// The bound nodes are generated by calling \c bind("id") on the node matchers
+/// of the nodes we want to access later.
+///
+/// The instances of BoundNodes are created by \c MatchFinder when the user's
+/// callbacks are executed every time a match is found.
+class BoundNodes {
+public:
+ /// \brief Returns the AST node bound to \c ID.
+ ///
+ /// Returns NULL if there was no node bound to \c ID or if there is a node but
+ /// it cannot be converted to the specified type.
+ template <typename T>
+ const T *getNodeAs(StringRef ID) const {
+ return MyBoundNodes.getNodeAs<T>(ID);
+ }
+
+ /// \brief Deprecated. Please use \c getNodeAs instead.
+ /// @{
+ template <typename T>
+ const T *getDeclAs(StringRef ID) const {
+ return getNodeAs<T>(ID);
+ }
+ template <typename T>
+ const T *getStmtAs(StringRef ID) const {
+ return getNodeAs<T>(ID);
+ }
+ /// @}
+
+ /// \brief Type of mapping from binding identifiers to bound nodes. This type
+ /// is an associative container with a key type of \c std::string and a value
+ /// type of \c clang::ast_type_traits::DynTypedNode
+ typedef internal::BoundNodesMap::IDToNodeMap IDToNodeMap;
+
+ /// \brief Retrieve mapping from binding identifiers to bound nodes.
+ const IDToNodeMap &getMap() const {
+ return MyBoundNodes.getMap();
+ }
+
+private:
+ /// \brief Create BoundNodes from a pre-filled map of bindings.
+ BoundNodes(internal::BoundNodesMap &MyBoundNodes)
+ : MyBoundNodes(MyBoundNodes) {}
+
+ internal::BoundNodesMap MyBoundNodes;
+
+ friend class internal::BoundNodesTreeBuilder;
+};
+
+/// \brief If the provided matcher matches a node, binds the node to \c ID.
+///
+/// FIXME: Do we want to support this now that we have bind()?
+template <typename T>
+internal::Matcher<T> id(StringRef ID,
+ const internal::BindableMatcher<T> &InnerMatcher) {
+ return InnerMatcher.bind(ID);
+}
+
+/// \brief Types of matchers for the top-level classes in the AST class
+/// hierarchy.
+/// @{
+typedef internal::Matcher<Decl> DeclarationMatcher;
+typedef internal::Matcher<Stmt> StatementMatcher;
+typedef internal::Matcher<QualType> TypeMatcher;
+typedef internal::Matcher<TypeLoc> TypeLocMatcher;
+typedef internal::Matcher<NestedNameSpecifier> NestedNameSpecifierMatcher;
+typedef internal::Matcher<NestedNameSpecifierLoc> NestedNameSpecifierLocMatcher;
+/// @}
+
+/// \brief Matches any node.
+///
+/// Useful when another matcher requires a child matcher, but there's no
+/// additional constraint. This will often be used with an explicit conversion
+/// to an \c internal::Matcher<> type such as \c TypeMatcher.
+///
+/// Example: \c DeclarationMatcher(anything()) matches all declarations, e.g.,
+/// \code
+/// "int* p" and "void f()" in
+/// int* p;
+/// void f();
+/// \endcode
+///
+/// Usable as: Any Matcher
+inline internal::TrueMatcher anything() { return internal::TrueMatcher(); }
+
+/// \brief Matches the top declaration context.
+///
+/// Given
+/// \code
+/// int X;
+/// namespace NS {
+/// int Y;
+/// } // namespace NS
+/// \endcode
+/// decl(hasDeclContext(translationUnitDecl()))
+/// matches "int X", but not "int Y".
+const internal::VariadicDynCastAllOfMatcher<Decl, TranslationUnitDecl>
+ translationUnitDecl;
+
+/// \brief Matches typedef declarations.
+///
+/// Given
+/// \code
+/// typedef int X;
+/// \endcode
+/// typedefDecl()
+/// matches "typedef int X"
+const internal::VariadicDynCastAllOfMatcher<Decl, TypedefDecl> typedefDecl;
+
+/// \brief Matches AST nodes that were expanded within the main-file.
+///
+/// Example matches X but not Y
+/// (matcher = cxxRecordDecl(isExpansionInMainFile())
+/// \code
+/// #include <Y.h>
+/// class X {};
+/// \endcode
+/// Y.h:
+/// \code
+/// class Y {};
+/// \endcode
+///
+/// Usable as: Matcher<Decl>, Matcher<Stmt>, Matcher<TypeLoc>
+AST_POLYMORPHIC_MATCHER(isExpansionInMainFile,
+ AST_POLYMORPHIC_SUPPORTED_TYPES(Decl, Stmt, TypeLoc)) {
+ auto &SourceManager = Finder->getASTContext().getSourceManager();
+ return SourceManager.isInMainFile(
+ SourceManager.getExpansionLoc(Node.getLocStart()));
+}
+
+/// \brief Matches AST nodes that were expanded within system-header-files.
+///
+/// Example matches Y but not X
+/// (matcher = cxxRecordDecl(isExpansionInSystemHeader())
+/// \code
+/// #include <SystemHeader.h>
+/// class X {};
+/// \endcode
+/// SystemHeader.h:
+/// \code
+/// class Y {};
+/// \endcode
+///
+/// Usable as: Matcher<Decl>, Matcher<Stmt>, Matcher<TypeLoc>
+AST_POLYMORPHIC_MATCHER(isExpansionInSystemHeader,
+ AST_POLYMORPHIC_SUPPORTED_TYPES(Decl, Stmt, TypeLoc)) {
+ auto &SourceManager = Finder->getASTContext().getSourceManager();
+ auto ExpansionLoc = SourceManager.getExpansionLoc(Node.getLocStart());
+ if (ExpansionLoc.isInvalid()) {
+ return false;
+ }
+ return SourceManager.isInSystemHeader(ExpansionLoc);
+}
+
+/// \brief Matches AST nodes that were expanded within files whose name is
+/// partially matching a given regex.
+///
+/// Example matches Y but not X
+/// (matcher = cxxRecordDecl(isExpansionInFileMatching("AST.*"))
+/// \code
+/// #include "ASTMatcher.h"
+/// class X {};
+/// \endcode
+/// ASTMatcher.h:
+/// \code
+/// class Y {};
+/// \endcode
+///
+/// Usable as: Matcher<Decl>, Matcher<Stmt>, Matcher<TypeLoc>
+AST_POLYMORPHIC_MATCHER_P(isExpansionInFileMatching,
+ AST_POLYMORPHIC_SUPPORTED_TYPES(Decl, Stmt, TypeLoc),
+ std::string, RegExp) {
+ auto &SourceManager = Finder->getASTContext().getSourceManager();
+ auto ExpansionLoc = SourceManager.getExpansionLoc(Node.getLocStart());
+ if (ExpansionLoc.isInvalid()) {
+ return false;
+ }
+ auto FileEntry =
+ SourceManager.getFileEntryForID(SourceManager.getFileID(ExpansionLoc));
+ if (!FileEntry) {
+ return false;
+ }
+
+ auto Filename = FileEntry->getName();
+ llvm::Regex RE(RegExp);
+ return RE.match(Filename);
+}
+
+/// \brief Matches declarations.
+///
+/// Examples matches \c X, \c C, and the friend declaration inside \c C;
+/// \code
+/// void X();
+/// class C {
+/// friend X;
+/// };
+/// \endcode
+const internal::VariadicAllOfMatcher<Decl> decl;
+
+/// \brief Matches a declaration of a linkage specification.
+///
+/// Given
+/// \code
+/// extern "C" {}
+/// \endcode
+/// linkageSpecDecl()
+/// matches "extern "C" {}"
+const internal::VariadicDynCastAllOfMatcher<Decl, LinkageSpecDecl>
+ linkageSpecDecl;
+
+/// \brief Matches a declaration of anything that could have a name.
+///
+/// Example matches \c X, \c S, the anonymous union type, \c i, and \c U;
+/// \code
+/// typedef int X;
+/// struct S {
+/// union {
+/// int i;
+/// } U;
+/// };
+/// \endcode
+const internal::VariadicDynCastAllOfMatcher<Decl, NamedDecl> namedDecl;
+
+/// \brief Matches a declaration of a namespace.
+///
+/// Given
+/// \code
+/// namespace {}
+/// namespace test {}
+/// \endcode
+/// namespaceDecl()
+/// matches "namespace {}" and "namespace test {}"
+const internal::VariadicDynCastAllOfMatcher<Decl, NamespaceDecl> namespaceDecl;
+
+/// \brief Matches a declaration of a namespace alias.
+///
+/// Given
+/// \code
+/// namespace test {}
+/// namespace alias = ::test;
+/// \endcode
+/// namespaceAliasDecl()
+/// matches "namespace alias" but not "namespace test"
+const internal::VariadicDynCastAllOfMatcher<Decl, NamespaceAliasDecl>
+ namespaceAliasDecl;
+
+/// \brief Matches class, struct, and union declarations.
+///
+/// Example matches \c X, \c Z, \c U, and \c S
+/// \code
+/// class X;
+/// template<class T> class Z {};
+/// struct S {};
+/// union U {};
+/// \endcode
+const internal::VariadicDynCastAllOfMatcher<
+ Decl,
+ RecordDecl> recordDecl;
+
+/// \brief Matches C++ class declarations.
+///
+/// Example matches \c X, \c Z
+/// \code
+/// class X;
+/// template<class T> class Z {};
+/// \endcode
+const internal::VariadicDynCastAllOfMatcher<
+ Decl,
+ CXXRecordDecl> cxxRecordDecl;
+
+/// \brief Matches C++ class template declarations.
+///
+/// Example matches \c Z
+/// \code
+/// template<class T> class Z {};
+/// \endcode
+const internal::VariadicDynCastAllOfMatcher<
+ Decl,
+ ClassTemplateDecl> classTemplateDecl;
+
+/// \brief Matches C++ class template specializations.
+///
+/// Given
+/// \code
+/// template<typename T> class A {};
+/// template<> class A<double> {};
+/// A<int> a;
+/// \endcode
+/// classTemplateSpecializationDecl()
+/// matches the specializations \c A<int> and \c A<double>
+const internal::VariadicDynCastAllOfMatcher<
+ Decl,
+ ClassTemplateSpecializationDecl> classTemplateSpecializationDecl;
+
+/// \brief Matches declarator declarations (field, variable, function
+/// and non-type template parameter declarations).
+///
+/// Given
+/// \code
+/// class X { int y; };
+/// \endcode
+/// declaratorDecl()
+/// matches \c int y.
+const internal::VariadicDynCastAllOfMatcher<Decl, DeclaratorDecl>
+ declaratorDecl;
+
+/// \brief Matches parameter variable declarations.
+///
+/// Given
+/// \code
+/// void f(int x);
+/// \endcode
+/// parmVarDecl()
+/// matches \c int x.
+const internal::VariadicDynCastAllOfMatcher<Decl, ParmVarDecl> parmVarDecl;
+
+/// \brief Matches C++ access specifier declarations.
+///
+/// Given
+/// \code
+/// class C {
+/// public:
+/// int a;
+/// };
+/// \endcode
+/// accessSpecDecl()
+/// matches 'public:'
+const internal::VariadicDynCastAllOfMatcher<
+ Decl,
+ AccessSpecDecl> accessSpecDecl;
+
+/// \brief Matches constructor initializers.
+///
+/// Examples matches \c i(42).
+/// \code
+/// class C {
+/// C() : i(42) {}
+/// int i;
+/// };
+/// \endcode
+const internal::VariadicAllOfMatcher<CXXCtorInitializer> cxxCtorInitializer;
+
+/// \brief Matches template arguments.
+///
+/// Given
+/// \code
+/// template <typename T> struct C {};
+/// C<int> c;
+/// \endcode
+/// templateArgument()
+/// matches 'int' in C<int>.
+const internal::VariadicAllOfMatcher<TemplateArgument> templateArgument;
+
+/// \brief Matches non-type template parameter declarations.
+///
+/// Given
+/// \code
+/// template <typename T, int N> struct C {};
+/// \endcode
+/// nonTypeTemplateParmDecl()
+/// matches 'N', but not 'T'.
+const internal::VariadicDynCastAllOfMatcher<
+ Decl,
+ NonTypeTemplateParmDecl> nonTypeTemplateParmDecl;
+
+/// \brief Matches template type parameter declarations.
+///
+/// Given
+/// \code
+/// template <typename T, int N> struct C {};
+/// \endcode
+/// templateTypeParmDecl()
+/// matches 'T', but not 'N'.
+const internal::VariadicDynCastAllOfMatcher<
+ Decl,
+ TemplateTypeParmDecl> templateTypeParmDecl;
+
+/// \brief Matches public C++ declarations.
+///
+/// Given
+/// \code
+/// class C {
+/// public: int a;
+/// protected: int b;
+/// private: int c;
+/// };
+/// \endcode
+/// fieldDecl(isPublic())
+/// matches 'int a;'
+AST_MATCHER(Decl, isPublic) {
+ return Node.getAccess() == AS_public;
+}
+
+/// \brief Matches protected C++ declarations.
+///
+/// Given
+/// \code
+/// class C {
+/// public: int a;
+/// protected: int b;
+/// private: int c;
+/// };
+/// \endcode
+/// fieldDecl(isProtected())
+/// matches 'int b;'
+AST_MATCHER(Decl, isProtected) {
+ return Node.getAccess() == AS_protected;
+}
+
+/// \brief Matches private C++ declarations.
+///
+/// Given
+/// \code
+/// class C {
+/// public: int a;
+/// protected: int b;
+/// private: int c;
+/// };
+/// \endcode
+/// fieldDecl(isPrivate())
+/// matches 'int c;'
+AST_MATCHER(Decl, isPrivate) {
+ return Node.getAccess() == AS_private;
+}
+
+/// \brief Matches a declaration that has been implicitly added
+/// by the compiler (eg. implicit default/copy constructors).
+AST_MATCHER(Decl, isImplicit) {
+ return Node.isImplicit();
+}
+
+/// \brief Matches classTemplateSpecializations that have at least one
+/// TemplateArgument matching the given InnerMatcher.
+///
+/// Given
+/// \code
+/// template<typename T> class A {};
+/// template<> class A<double> {};
+/// A<int> a;
+/// \endcode
+/// classTemplateSpecializationDecl(hasAnyTemplateArgument(
+/// refersToType(asString("int"))))
+/// matches the specialization \c A<int>
+AST_POLYMORPHIC_MATCHER_P(
+ hasAnyTemplateArgument,
+ AST_POLYMORPHIC_SUPPORTED_TYPES(ClassTemplateSpecializationDecl,
+ TemplateSpecializationType),
+ internal::Matcher<TemplateArgument>, InnerMatcher) {
+ ArrayRef<TemplateArgument> List =
+ internal::getTemplateSpecializationArgs(Node);
+ return matchesFirstInRange(InnerMatcher, List.begin(), List.end(), Finder,
+ Builder);
+}
+
+/// \brief Matches expressions that match InnerMatcher after any implicit casts
+/// are stripped off.
+///
+/// Parentheses and explicit casts are not discarded.
+/// Given
+/// \code
+/// int arr[5];
+/// int a = 0;
+/// char b = 0;
+/// const int c = a;
+/// int *d = arr;
+/// long e = (long) 0l;
+/// \endcode
+/// The matchers
+/// \code
+/// varDecl(hasInitializer(ignoringImpCasts(integerLiteral())))
+/// varDecl(hasInitializer(ignoringImpCasts(declRefExpr())))
+/// \endcode
+/// would match the declarations for a, b, c, and d, but not e.
+/// While
+/// \code
+/// varDecl(hasInitializer(integerLiteral()))
+/// varDecl(hasInitializer(declRefExpr()))
+/// \endcode
+/// only match the declarations for b, c, and d.
+AST_MATCHER_P(Expr, ignoringImpCasts,
+ internal::Matcher<Expr>, InnerMatcher) {
+ return InnerMatcher.matches(*Node.IgnoreImpCasts(), Finder, Builder);
+}
+
+/// \brief Matches expressions that match InnerMatcher after parentheses and
+/// casts are stripped off.
+///
+/// Implicit and non-C Style casts are also discarded.
+/// Given
+/// \code
+/// int a = 0;
+/// char b = (0);
+/// void* c = reinterpret_cast<char*>(0);
+/// char d = char(0);
+/// \endcode
+/// The matcher
+/// varDecl(hasInitializer(ignoringParenCasts(integerLiteral())))
+/// would match the declarations for a, b, c, and d.
+/// while
+/// varDecl(hasInitializer(integerLiteral()))
+/// only match the declaration for a.
+AST_MATCHER_P(Expr, ignoringParenCasts, internal::Matcher<Expr>, InnerMatcher) {
+ return InnerMatcher.matches(*Node.IgnoreParenCasts(), Finder, Builder);
+}
+
+/// \brief Matches expressions that match InnerMatcher after implicit casts and
+/// parentheses are stripped off.
+///
+/// Explicit casts are not discarded.
+/// Given
+/// \code
+/// int arr[5];
+/// int a = 0;
+/// char b = (0);
+/// const int c = a;
+/// int *d = (arr);
+/// long e = ((long) 0l);
+/// \endcode
+/// The matchers
+/// varDecl(hasInitializer(ignoringParenImpCasts(integerLiteral())))
+/// varDecl(hasInitializer(ignoringParenImpCasts(declRefExpr())))
+/// would match the declarations for a, b, c, and d, but not e.
+/// while
+/// varDecl(hasInitializer(integerLiteral()))
+/// varDecl(hasInitializer(declRefExpr()))
+/// would only match the declaration for a.
+AST_MATCHER_P(Expr, ignoringParenImpCasts,
+ internal::Matcher<Expr>, InnerMatcher) {
+ return InnerMatcher.matches(*Node.IgnoreParenImpCasts(), Finder, Builder);
+}
+
+/// \brief Matches classTemplateSpecializations where the n'th TemplateArgument
+/// matches the given InnerMatcher.
+///
+/// Given
+/// \code
+/// template<typename T, typename U> class A {};
+/// A<bool, int> b;
+/// A<int, bool> c;
+/// \endcode
+/// classTemplateSpecializationDecl(hasTemplateArgument(
+/// 1, refersToType(asString("int"))))
+/// matches the specialization \c A<bool, int>
+AST_POLYMORPHIC_MATCHER_P2(
+ hasTemplateArgument,
+ AST_POLYMORPHIC_SUPPORTED_TYPES(ClassTemplateSpecializationDecl,
+ TemplateSpecializationType),
+ unsigned, N, internal::Matcher<TemplateArgument>, InnerMatcher) {
+ ArrayRef<TemplateArgument> List =
+ internal::getTemplateSpecializationArgs(Node);
+ if (List.size() <= N)
+ return false;
+ return InnerMatcher.matches(List[N], Finder, Builder);
+}
+
+/// \brief Matches if the number of template arguments equals \p N.
+///
+/// Given
+/// \code
+/// template<typename T> struct C {};
+/// C<int> c;
+/// \endcode
+/// classTemplateSpecializationDecl(templateArgumentCountIs(1))
+/// matches C<int>.
+AST_POLYMORPHIC_MATCHER_P(
+ templateArgumentCountIs,
+ AST_POLYMORPHIC_SUPPORTED_TYPES(ClassTemplateSpecializationDecl,
+ TemplateSpecializationType),
+ unsigned, N) {
+ return internal::getTemplateSpecializationArgs(Node).size() == N;
+}
+
+/// \brief Matches a TemplateArgument that refers to a certain type.
+///
+/// Given
+/// \code
+/// struct X {};
+/// template<typename T> struct A {};
+/// A<X> a;
+/// \endcode
+/// classTemplateSpecializationDecl(hasAnyTemplateArgument(
+/// refersToType(class(hasName("X")))))
+/// matches the specialization \c A<X>
+AST_MATCHER_P(TemplateArgument, refersToType,
+ internal::Matcher<QualType>, InnerMatcher) {
+ if (Node.getKind() != TemplateArgument::Type)
+ return false;
+ return InnerMatcher.matches(Node.getAsType(), Finder, Builder);
+}
+
+/// \brief Matches a canonical TemplateArgument that refers to a certain
+/// declaration.
+///
+/// Given
+/// \code
+/// template<typename T> struct A {};
+/// struct B { B* next; };
+/// A<&B::next> a;
+/// \endcode
+/// classTemplateSpecializationDecl(hasAnyTemplateArgument(
+/// refersToDeclaration(fieldDecl(hasName("next"))))
+/// matches the specialization \c A<&B::next> with \c fieldDecl(...) matching
+/// \c B::next
+AST_MATCHER_P(TemplateArgument, refersToDeclaration,
+ internal::Matcher<Decl>, InnerMatcher) {
+ if (Node.getKind() == TemplateArgument::Declaration)
+ return InnerMatcher.matches(*Node.getAsDecl(), Finder, Builder);
+ return false;
+}
+
+/// \brief Matches a sugar TemplateArgument that refers to a certain expression.
+///
+/// Given
+/// \code
+/// template<typename T> struct A {};
+/// struct B { B* next; };
+/// A<&B::next> a;
+/// \endcode
+/// templateSpecializationType(hasAnyTemplateArgument(
+/// isExpr(hasDescendant(declRefExpr(to(fieldDecl(hasName("next"))))))))
+/// matches the specialization \c A<&B::next> with \c fieldDecl(...) matching
+/// \c B::next
+AST_MATCHER_P(TemplateArgument, isExpr, internal::Matcher<Expr>, InnerMatcher) {
+ if (Node.getKind() == TemplateArgument::Expression)
+ return InnerMatcher.matches(*Node.getAsExpr(), Finder, Builder);
+ return false;
+}
+
+/// \brief Matches a TemplateArgument that is an integral value.
+///
+/// Given
+/// \code
+/// template<int T> struct A {};
+/// C<42> c;
+/// \endcode
+/// classTemplateSpecializationDecl(
+/// hasAnyTemplateArgument(isIntegral()))
+/// matches the implicit instantiation of C in C<42>
+/// with isIntegral() matching 42.
+AST_MATCHER(TemplateArgument, isIntegral) {
+ return Node.getKind() == TemplateArgument::Integral;
+}
+
+/// \brief Matches a TemplateArgument that referes to an integral type.
+///
+/// Given
+/// \code
+/// template<int T> struct A {};
+/// C<42> c;
+/// \endcode
+/// classTemplateSpecializationDecl(
+/// hasAnyTemplateArgument(refersToIntegralType(asString("int"))))
+/// matches the implicit instantiation of C in C<42>.
+AST_MATCHER_P(TemplateArgument, refersToIntegralType,
+ internal::Matcher<QualType>, InnerMatcher) {
+ if (Node.getKind() != TemplateArgument::Integral)
+ return false;
+ return InnerMatcher.matches(Node.getIntegralType(), Finder, Builder);
+}
+
+/// \brief Matches a TemplateArgument of integral type with a given value.
+///
+/// Note that 'Value' is a string as the template argument's value is
+/// an arbitrary precision integer. 'Value' must be euqal to the canonical
+/// representation of that integral value in base 10.
+///
+/// Given
+/// \code
+/// template<int T> struct A {};
+/// C<42> c;
+/// \endcode
+/// classTemplateSpecializationDecl(
+/// hasAnyTemplateArgument(equalsIntegralValue("42")))
+/// matches the implicit instantiation of C in C<42>.
+AST_MATCHER_P(TemplateArgument, equalsIntegralValue,
+ std::string, Value) {
+ if (Node.getKind() != TemplateArgument::Integral)
+ return false;
+ return Node.getAsIntegral().toString(10) == Value;
+}
+
+/// \brief Matches any value declaration.
+///
+/// Example matches A, B, C and F
+/// \code
+/// enum X { A, B, C };
+/// void F();
+/// \endcode
+const internal::VariadicDynCastAllOfMatcher<Decl, ValueDecl> valueDecl;
+
+/// \brief Matches C++ constructor declarations.
+///
+/// Example matches Foo::Foo() and Foo::Foo(int)
+/// \code
+/// class Foo {
+/// public:
+/// Foo();
+/// Foo(int);
+/// int DoSomething();
+/// };
+/// \endcode
+const internal::VariadicDynCastAllOfMatcher<
+ Decl,
+ CXXConstructorDecl> cxxConstructorDecl;
+
+/// \brief Matches explicit C++ destructor declarations.
+///
+/// Example matches Foo::~Foo()
+/// \code
+/// class Foo {
+/// public:
+/// virtual ~Foo();
+/// };
+/// \endcode
+const internal::VariadicDynCastAllOfMatcher<
+ Decl,
+ CXXDestructorDecl> cxxDestructorDecl;
+
+/// \brief Matches enum declarations.
+///
+/// Example matches X
+/// \code
+/// enum X {
+/// A, B, C
+/// };
+/// \endcode
+const internal::VariadicDynCastAllOfMatcher<Decl, EnumDecl> enumDecl;
+
+/// \brief Matches enum constants.
+///
+/// Example matches A, B, C
+/// \code
+/// enum X {
+/// A, B, C
+/// };
+/// \endcode
+const internal::VariadicDynCastAllOfMatcher<
+ Decl,
+ EnumConstantDecl> enumConstantDecl;
+
+/// \brief Matches method declarations.
+///
+/// Example matches y
+/// \code
+/// class X { void y(); };
+/// \endcode
+const internal::VariadicDynCastAllOfMatcher<Decl, CXXMethodDecl> cxxMethodDecl;
+
+/// \brief Matches conversion operator declarations.
+///
+/// Example matches the operator.
+/// \code
+/// class X { operator int() const; };
+/// \endcode
+const internal::VariadicDynCastAllOfMatcher<Decl, CXXConversionDecl>
+ cxxConversionDecl;
+
+/// \brief Matches variable declarations.
+///
+/// Note: this does not match declarations of member variables, which are
+/// "field" declarations in Clang parlance.
+///
+/// Example matches a
+/// \code
+/// int a;
+/// \endcode
+const internal::VariadicDynCastAllOfMatcher<Decl, VarDecl> varDecl;
+
+/// \brief Matches field declarations.
+///
+/// Given
+/// \code
+/// class X { int m; };
+/// \endcode
+/// fieldDecl()
+/// matches 'm'.
+const internal::VariadicDynCastAllOfMatcher<Decl, FieldDecl> fieldDecl;
+
+/// \brief Matches function declarations.
+///
+/// Example matches f
+/// \code
+/// void f();
+/// \endcode
+const internal::VariadicDynCastAllOfMatcher<Decl, FunctionDecl> functionDecl;
+
+/// \brief Matches C++ function template declarations.
+///
+/// Example matches f
+/// \code
+/// template<class T> void f(T t) {}
+/// \endcode
+const internal::VariadicDynCastAllOfMatcher<
+ Decl,
+ FunctionTemplateDecl> functionTemplateDecl;
+
+/// \brief Matches friend declarations.
+///
+/// Given
+/// \code
+/// class X { friend void foo(); };
+/// \endcode
+/// friendDecl()
+/// matches 'friend void foo()'.
+const internal::VariadicDynCastAllOfMatcher<Decl, FriendDecl> friendDecl;
+
+/// \brief Matches statements.
+///
+/// Given
+/// \code
+/// { ++a; }
+/// \endcode
+/// stmt()
+/// matches both the compound statement '{ ++a; }' and '++a'.
+const internal::VariadicAllOfMatcher<Stmt> stmt;
+
+/// \brief Matches declaration statements.
+///
+/// Given
+/// \code
+/// int a;
+/// \endcode
+/// declStmt()
+/// matches 'int a'.
+const internal::VariadicDynCastAllOfMatcher<
+ Stmt,
+ DeclStmt> declStmt;
+
+/// \brief Matches member expressions.
+///
+/// Given
+/// \code
+/// class Y {
+/// void x() { this->x(); x(); Y y; y.x(); a; this->b; Y::b; }
+/// int a; static int b;
+/// };
+/// \endcode
+/// memberExpr()
+/// matches this->x, x, y.x, a, this->b
+const internal::VariadicDynCastAllOfMatcher<Stmt, MemberExpr> memberExpr;
+
+/// \brief Matches call expressions.
+///
+/// Example matches x.y() and y()
+/// \code
+/// X x;
+/// x.y();
+/// y();
+/// \endcode
+const internal::VariadicDynCastAllOfMatcher<Stmt, CallExpr> callExpr;
+
+/// \brief Matches lambda expressions.
+///
+/// Example matches [&](){return 5;}
+/// \code
+/// [&](){return 5;}
+/// \endcode
+const internal::VariadicDynCastAllOfMatcher<Stmt, LambdaExpr> lambdaExpr;
+
+/// \brief Matches member call expressions.
+///
+/// Example matches x.y()
+/// \code
+/// X x;
+/// x.y();
+/// \endcode
+const internal::VariadicDynCastAllOfMatcher<
+ Stmt,
+ CXXMemberCallExpr> cxxMemberCallExpr;
+
+/// \brief Matches ObjectiveC Message invocation expressions.
+///
+/// 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". This matcher should match both message sends.
+/// \code
+/// [[NSString alloc] initWithString:@"Hello"]
+/// \endcode
+const internal::VariadicDynCastAllOfMatcher<
+ Stmt,
+ ObjCMessageExpr> objcMessageExpr;
+
+/// \brief Matches Objective-C interface declarations.
+///
+/// Example matches Foo
+/// \code
+/// @interface Foo
+/// @end
+/// \endcode
+const internal::VariadicDynCastAllOfMatcher<
+ Decl,
+ ObjCInterfaceDecl> objcInterfaceDecl;
+
+/// \brief Matches expressions that introduce cleanups to be run at the end
+/// of the sub-expression's evaluation.
+///
+/// Example matches std::string()
+/// \code
+/// const std::string str = std::string();
+/// \endcode
+const internal::VariadicDynCastAllOfMatcher<
+ Stmt,
+ ExprWithCleanups> exprWithCleanups;
+
+/// \brief Matches init list expressions.
+///
+/// Given
+/// \code
+/// int a[] = { 1, 2 };
+/// struct B { int x, y; };
+/// B b = { 5, 6 };
+/// \endcode
+/// initListExpr()
+/// matches "{ 1, 2 }" and "{ 5, 6 }"
+const internal::VariadicDynCastAllOfMatcher<Stmt, InitListExpr> initListExpr;
+
+/// \brief Matches substitutions of non-type template parameters.
+///
+/// Given
+/// \code
+/// template <int N>
+/// struct A { static const int n = N; };
+/// struct B : public A<42> {};
+/// \endcode
+/// substNonTypeTemplateParmExpr()
+/// matches "N" in the right-hand side of "static const int n = N;"
+const internal::VariadicDynCastAllOfMatcher<
+ Stmt,
+ SubstNonTypeTemplateParmExpr> substNonTypeTemplateParmExpr;
+
+/// \brief Matches using declarations.
+///
+/// Given
+/// \code
+/// namespace X { int x; }
+/// using X::x;
+/// \endcode
+/// usingDecl()
+/// matches \code using X::x \endcode
+const internal::VariadicDynCastAllOfMatcher<Decl, UsingDecl> usingDecl;
+
+/// \brief Matches using namespace declarations.
+///
+/// Given
+/// \code
+/// namespace X { int x; }
+/// using namespace X;
+/// \endcode
+/// usingDirectiveDecl()
+/// matches \code using namespace X \endcode
+const internal::VariadicDynCastAllOfMatcher<
+ Decl,
+ UsingDirectiveDecl> usingDirectiveDecl;
+
+/// \brief Matches unresolved using value declarations.
+///
+/// Given
+/// \code
+/// template<typename X>
+/// class C : private X {
+/// using X::x;
+/// };
+/// \endcode
+/// unresolvedUsingValueDecl()
+/// matches \code using X::x \endcode
+const internal::VariadicDynCastAllOfMatcher<
+ Decl,
+ UnresolvedUsingValueDecl> unresolvedUsingValueDecl;
+
+/// \brief Matches unresolved using value declarations that involve the
+/// typename.
+///
+/// Given
+/// \code
+/// template <typename T>
+/// struct Base { typedef T Foo; };
+///
+/// template<typename T>
+/// struct S : private Base<T> {
+/// using typename Base<T>::Foo;
+/// };
+/// \endcode
+/// unresolvedUsingTypenameDecl()
+/// matches \code using Base<T>::Foo \endcode
+const internal::VariadicDynCastAllOfMatcher<
+ Decl,
+ UnresolvedUsingTypenameDecl> unresolvedUsingTypenameDecl;
+
+/// \brief Matches constructor call expressions (including implicit ones).
+///
+/// Example matches string(ptr, n) and ptr within arguments of f
+/// (matcher = cxxConstructExpr())
+/// \code
+/// void f(const string &a, const string &b);
+/// char *ptr;
+/// int n;
+/// f(string(ptr, n), ptr);
+/// \endcode
+const internal::VariadicDynCastAllOfMatcher<
+ Stmt,
+ CXXConstructExpr> cxxConstructExpr;
+
+/// \brief Matches unresolved constructor call expressions.
+///
+/// Example matches T(t) in return statement of f
+/// (matcher = cxxUnresolvedConstructExpr())
+/// \code
+/// template <typename T>
+/// void f(const T& t) { return T(t); }
+/// \endcode
+const internal::VariadicDynCastAllOfMatcher<
+ Stmt,
+ CXXUnresolvedConstructExpr> cxxUnresolvedConstructExpr;
+
+/// \brief Matches implicit and explicit this expressions.
+///
+/// Example matches the implicit this expression in "return i".
+/// (matcher = cxxThisExpr())
+/// \code
+/// struct foo {
+/// int i;
+/// int f() { return i; }
+/// };
+/// \endcode
+const internal::VariadicDynCastAllOfMatcher<Stmt, CXXThisExpr> cxxThisExpr;
+
+/// \brief Matches nodes where temporaries are created.
+///
+/// Example matches FunctionTakesString(GetStringByValue())
+/// (matcher = cxxBindTemporaryExpr())
+/// \code
+/// FunctionTakesString(GetStringByValue());
+/// FunctionTakesStringByPointer(GetStringPointer());
+/// \endcode
+const internal::VariadicDynCastAllOfMatcher<
+ Stmt,
+ CXXBindTemporaryExpr> cxxBindTemporaryExpr;
+
+/// \brief Matches nodes where temporaries are materialized.
+///
+/// Example: Given
+/// \code
+/// struct T {void func()};
+/// T f();
+/// void g(T);
+/// \endcode
+/// materializeTemporaryExpr() matches 'f()' in these statements
+/// \code
+/// T u(f());
+/// g(f());
+/// \endcode
+/// but does not match
+/// \code
+/// f();
+/// f().func();
+/// \endcode
+const internal::VariadicDynCastAllOfMatcher<
+ Stmt,
+ MaterializeTemporaryExpr> materializeTemporaryExpr;
+
+/// \brief Matches new expressions.
+///
+/// Given
+/// \code
+/// new X;
+/// \endcode
+/// cxxNewExpr()
+/// matches 'new X'.
+const internal::VariadicDynCastAllOfMatcher<Stmt, CXXNewExpr> cxxNewExpr;
+
+/// \brief Matches delete expressions.
+///
+/// Given
+/// \code
+/// delete X;
+/// \endcode
+/// cxxDeleteExpr()
+/// matches 'delete X'.
+const internal::VariadicDynCastAllOfMatcher<Stmt, CXXDeleteExpr> cxxDeleteExpr;
+
+/// \brief Matches array subscript expressions.
+///
+/// Given
+/// \code
+/// int i = a[1];
+/// \endcode
+/// arraySubscriptExpr()
+/// matches "a[1]"
+const internal::VariadicDynCastAllOfMatcher<
+ Stmt,
+ ArraySubscriptExpr> arraySubscriptExpr;
+
+/// \brief Matches the value of a default argument at the call site.
+///
+/// Example matches the CXXDefaultArgExpr placeholder inserted for the
+/// default value of the second parameter in the call expression f(42)
+/// (matcher = cxxDefaultArgExpr())
+/// \code
+/// void f(int x, int y = 0);
+/// f(42);
+/// \endcode
+const internal::VariadicDynCastAllOfMatcher<
+ Stmt,
+ CXXDefaultArgExpr> cxxDefaultArgExpr;
+
+/// \brief Matches overloaded operator calls.
+///
+/// Note that if an operator isn't overloaded, it won't match. Instead, use
+/// binaryOperator matcher.
+/// Currently it does not match operators such as new delete.
+/// FIXME: figure out why these do not match?
+///
+/// Example matches both operator<<((o << b), c) and operator<<(o, b)
+/// (matcher = cxxOperatorCallExpr())
+/// \code
+/// ostream &operator<< (ostream &out, int i) { };
+/// ostream &o; int b = 1, c = 1;
+/// o << b << c;
+/// \endcode
+const internal::VariadicDynCastAllOfMatcher<
+ Stmt,
+ CXXOperatorCallExpr> cxxOperatorCallExpr;
+
+/// \brief Matches expressions.
+///
+/// Example matches x()
+/// \code
+/// void f() { x(); }
+/// \endcode
+const internal::VariadicDynCastAllOfMatcher<Stmt, Expr> expr;
+
+/// \brief Matches expressions that refer to declarations.
+///
+/// Example matches x in if (x)
+/// \code
+/// bool x;
+/// if (x) {}
+/// \endcode
+const internal::VariadicDynCastAllOfMatcher<Stmt, DeclRefExpr> declRefExpr;
+
+/// \brief Matches if statements.
+///
+/// Example matches 'if (x) {}'
+/// \code
+/// if (x) {}
+/// \endcode
+const internal::VariadicDynCastAllOfMatcher<Stmt, IfStmt> ifStmt;
+
+/// \brief Matches for statements.
+///
+/// Example matches 'for (;;) {}'
+/// \code
+/// for (;;) {}
+/// int i[] = {1, 2, 3}; for (auto a : i);
+/// \endcode
+const internal::VariadicDynCastAllOfMatcher<Stmt, ForStmt> forStmt;
+
+/// \brief Matches the increment statement of a for loop.
+///
+/// Example:
+/// forStmt(hasIncrement(unaryOperator(hasOperatorName("++"))))
+/// matches '++x' in
+/// \code
+/// for (x; x < N; ++x) { }
+/// \endcode
+AST_MATCHER_P(ForStmt, hasIncrement, internal::Matcher<Stmt>,
+ InnerMatcher) {
+ const Stmt *const Increment = Node.getInc();
+ return (Increment != nullptr &&
+ InnerMatcher.matches(*Increment, Finder, Builder));
+}
+
+/// \brief Matches the initialization statement of a for loop.
+///
+/// Example:
+/// forStmt(hasLoopInit(declStmt()))
+/// matches 'int x = 0' in
+/// \code
+/// for (int x = 0; x < N; ++x) { }
+/// \endcode
+AST_MATCHER_P(ForStmt, hasLoopInit, internal::Matcher<Stmt>,
+ InnerMatcher) {
+ const Stmt *const Init = Node.getInit();
+ return (Init != nullptr && InnerMatcher.matches(*Init, Finder, Builder));
+}
+
+/// \brief Matches range-based for statements.
+///
+/// cxxForRangeStmt() matches 'for (auto a : i)'
+/// \code
+/// int i[] = {1, 2, 3}; for (auto a : i);
+/// for(int j = 0; j < 5; ++j);
+/// \endcode
+const internal::VariadicDynCastAllOfMatcher<
+ Stmt,
+ CXXForRangeStmt> cxxForRangeStmt;
+
+/// \brief Matches the initialization statement of a for loop.
+///
+/// Example:
+/// forStmt(hasLoopVariable(anything()))
+/// matches 'int x' in
+/// \code
+/// for (int x : a) { }
+/// \endcode
+AST_MATCHER_P(CXXForRangeStmt, hasLoopVariable, internal::Matcher<VarDecl>,
+ InnerMatcher) {
+ const VarDecl *const Var = Node.getLoopVariable();
+ return (Var != nullptr && InnerMatcher.matches(*Var, Finder, Builder));
+}
+
+/// \brief Matches the range initialization statement of a for loop.
+///
+/// Example:
+/// forStmt(hasRangeInit(anything()))
+/// matches 'a' in
+/// \code
+/// for (int x : a) { }
+/// \endcode
+AST_MATCHER_P(CXXForRangeStmt, hasRangeInit, internal::Matcher<Expr>,
+ InnerMatcher) {
+ const Expr *const Init = Node.getRangeInit();
+ return (Init != nullptr && InnerMatcher.matches(*Init, Finder, Builder));
+}
+
+/// \brief Matches while statements.
+///
+/// Given
+/// \code
+/// while (true) {}
+/// \endcode
+/// whileStmt()
+/// matches 'while (true) {}'.
+const internal::VariadicDynCastAllOfMatcher<Stmt, WhileStmt> whileStmt;
+
+/// \brief Matches do statements.
+///
+/// Given
+/// \code
+/// do {} while (true);
+/// \endcode
+/// doStmt()
+/// matches 'do {} while(true)'
+const internal::VariadicDynCastAllOfMatcher<Stmt, DoStmt> doStmt;
+
+/// \brief Matches break statements.
+///
+/// Given
+/// \code
+/// while (true) { break; }
+/// \endcode
+/// breakStmt()
+/// matches 'break'
+const internal::VariadicDynCastAllOfMatcher<Stmt, BreakStmt> breakStmt;
+
+/// \brief Matches continue statements.
+///
+/// Given
+/// \code
+/// while (true) { continue; }
+/// \endcode
+/// continueStmt()
+/// matches 'continue'
+const internal::VariadicDynCastAllOfMatcher<Stmt, ContinueStmt> continueStmt;
+
+/// \brief Matches return statements.
+///
+/// Given
+/// \code
+/// return 1;
+/// \endcode
+/// returnStmt()
+/// matches 'return 1'
+const internal::VariadicDynCastAllOfMatcher<Stmt, ReturnStmt> returnStmt;
+
+/// \brief Matches goto statements.
+///
+/// Given
+/// \code
+/// goto FOO;
+/// FOO: bar();
+/// \endcode
+/// gotoStmt()
+/// matches 'goto FOO'
+const internal::VariadicDynCastAllOfMatcher<Stmt, GotoStmt> gotoStmt;
+
+/// \brief Matches label statements.
+///
+/// Given
+/// \code
+/// goto FOO;
+/// FOO: bar();
+/// \endcode
+/// labelStmt()
+/// matches 'FOO:'
+const internal::VariadicDynCastAllOfMatcher<Stmt, LabelStmt> labelStmt;
+
+/// \brief Matches switch statements.
+///
+/// Given
+/// \code
+/// switch(a) { case 42: break; default: break; }
+/// \endcode
+/// switchStmt()
+/// matches 'switch(a)'.
+const internal::VariadicDynCastAllOfMatcher<Stmt, SwitchStmt> switchStmt;
+
+/// \brief Matches case and default statements inside switch statements.
+///
+/// Given
+/// \code
+/// switch(a) { case 42: break; default: break; }
+/// \endcode
+/// switchCase()
+/// matches 'case 42: break;' and 'default: break;'.
+const internal::VariadicDynCastAllOfMatcher<Stmt, SwitchCase> switchCase;
+
+/// \brief Matches case statements inside switch statements.
+///
+/// Given
+/// \code
+/// switch(a) { case 42: break; default: break; }
+/// \endcode
+/// caseStmt()
+/// matches 'case 42: break;'.
+const internal::VariadicDynCastAllOfMatcher<Stmt, CaseStmt> caseStmt;
+
+/// \brief Matches default statements inside switch statements.
+///
+/// Given
+/// \code
+/// switch(a) { case 42: break; default: break; }
+/// \endcode
+/// defaultStmt()
+/// matches 'default: break;'.
+const internal::VariadicDynCastAllOfMatcher<Stmt, DefaultStmt> defaultStmt;
+
+/// \brief Matches compound statements.
+///
+/// Example matches '{}' and '{{}}'in 'for (;;) {{}}'
+/// \code
+/// for (;;) {{}}
+/// \endcode
+const internal::VariadicDynCastAllOfMatcher<Stmt, CompoundStmt> compoundStmt;
+
+/// \brief Matches catch statements.
+///
+/// \code
+/// try {} catch(int i) {}
+/// \endcode
+/// cxxCatchStmt()
+/// matches 'catch(int i)'
+const internal::VariadicDynCastAllOfMatcher<Stmt, CXXCatchStmt> cxxCatchStmt;
+
+/// \brief Matches try statements.
+///
+/// \code
+/// try {} catch(int i) {}
+/// \endcode
+/// cxxTryStmt()
+/// matches 'try {}'
+const internal::VariadicDynCastAllOfMatcher<Stmt, CXXTryStmt> cxxTryStmt;
+
+/// \brief Matches throw expressions.
+///
+/// \code
+/// try { throw 5; } catch(int i) {}
+/// \endcode
+/// cxxThrowExpr()
+/// matches 'throw 5'
+const internal::VariadicDynCastAllOfMatcher<Stmt, CXXThrowExpr> cxxThrowExpr;
+
+/// \brief Matches null statements.
+///
+/// \code
+/// foo();;
+/// \endcode
+/// nullStmt()
+/// matches the second ';'
+const internal::VariadicDynCastAllOfMatcher<Stmt, NullStmt> nullStmt;
+
+/// \brief Matches asm statements.
+///
+/// \code
+/// int i = 100;
+/// __asm("mov al, 2");
+/// \endcode
+/// asmStmt()
+/// matches '__asm("mov al, 2")'
+const internal::VariadicDynCastAllOfMatcher<Stmt, AsmStmt> asmStmt;
+
+/// \brief Matches bool literals.
+///
+/// Example matches true
+/// \code
+/// true
+/// \endcode
+const internal::VariadicDynCastAllOfMatcher<
+ Stmt,
+ CXXBoolLiteralExpr> cxxBoolLiteral;
+
+/// \brief Matches string literals (also matches wide string literals).
+///
+/// Example matches "abcd", L"abcd"
+/// \code
+/// char *s = "abcd"; wchar_t *ws = L"abcd"
+/// \endcode
+const internal::VariadicDynCastAllOfMatcher<
+ Stmt,
+ StringLiteral> stringLiteral;
+
+/// \brief Matches character literals (also matches wchar_t).
+///
+/// Not matching Hex-encoded chars (e.g. 0x1234, which is a IntegerLiteral),
+/// though.
+///
+/// Example matches 'a', L'a'
+/// \code
+/// char ch = 'a'; wchar_t chw = L'a';
+/// \endcode
+const internal::VariadicDynCastAllOfMatcher<
+ Stmt,
+ CharacterLiteral> characterLiteral;
+
+/// \brief Matches integer literals of all sizes / encodings, e.g.
+/// 1, 1L, 0x1 and 1U.
+///
+/// Does not match character-encoded integers such as L'a'.
+const internal::VariadicDynCastAllOfMatcher<
+ Stmt,
+ IntegerLiteral> integerLiteral;
+
+/// \brief Matches float literals of all sizes / encodings, e.g.
+/// 1.0, 1.0f, 1.0L and 1e10.
+///
+/// Does not match implicit conversions such as
+/// \code
+/// float a = 10;
+/// \endcode
+const internal::VariadicDynCastAllOfMatcher<
+ Stmt,
+ FloatingLiteral> floatLiteral;
+
+/// \brief Matches user defined literal operator call.
+///
+/// Example match: "foo"_suffix
+const internal::VariadicDynCastAllOfMatcher<
+ Stmt,
+ UserDefinedLiteral> userDefinedLiteral;
+
+/// \brief Matches compound (i.e. non-scalar) literals
+///
+/// Example match: {1}, (1, 2)
+/// \code
+/// int array[4] = {1}; vector int myvec = (vector int)(1, 2);
+/// \endcode
+const internal::VariadicDynCastAllOfMatcher<
+ Stmt,
+ CompoundLiteralExpr> compoundLiteralExpr;
+
+/// \brief Matches nullptr literal.
+const internal::VariadicDynCastAllOfMatcher<
+ Stmt,
+ CXXNullPtrLiteralExpr> cxxNullPtrLiteralExpr;
+
+/// \brief Matches GNU __null expression.
+const internal::VariadicDynCastAllOfMatcher<
+ Stmt,
+ GNUNullExpr> gnuNullExpr;
+
+/// \brief Matches binary operator expressions.
+///
+/// Example matches a || b
+/// \code
+/// !(a || b)
+/// \endcode
+const internal::VariadicDynCastAllOfMatcher<
+ Stmt,
+ BinaryOperator> binaryOperator;
+
+/// \brief Matches unary operator expressions.
+///
+/// Example matches !a
+/// \code
+/// !a || b
+/// \endcode
+const internal::VariadicDynCastAllOfMatcher<
+ Stmt,
+ UnaryOperator> unaryOperator;
+
+/// \brief Matches conditional operator expressions.
+///
+/// Example matches a ? b : c
+/// \code
+/// (a ? b : c) + 42
+/// \endcode
+const internal::VariadicDynCastAllOfMatcher<
+ Stmt,
+ ConditionalOperator> conditionalOperator;
+
+/// \brief Matches a C++ static_assert declaration.
+///
+/// Example:
+/// staticAssertExpr()
+/// matches
+/// static_assert(sizeof(S) == sizeof(int))
+/// in
+/// \code
+/// struct S {
+/// int x;
+/// };
+/// static_assert(sizeof(S) == sizeof(int));
+/// \endcode
+const internal::VariadicDynCastAllOfMatcher<
+ Decl,
+ StaticAssertDecl> staticAssertDecl;
+
+/// \brief Matches a reinterpret_cast expression.
+///
+/// Either the source expression or the destination type can be matched
+/// using has(), but hasDestinationType() is more specific and can be
+/// more readable.
+///
+/// Example matches reinterpret_cast<char*>(&p) in
+/// \code
+/// void* p = reinterpret_cast<char*>(&p);
+/// \endcode
+const internal::VariadicDynCastAllOfMatcher<
+ Stmt,
+ CXXReinterpretCastExpr> cxxReinterpretCastExpr;
+
+/// \brief Matches a C++ static_cast expression.
+///
+/// \see hasDestinationType
+/// \see reinterpretCast
+///
+/// Example:
+/// cxxStaticCastExpr()
+/// matches
+/// static_cast<long>(8)
+/// in
+/// \code
+/// long eight(static_cast<long>(8));
+/// \endcode
+const internal::VariadicDynCastAllOfMatcher<
+ Stmt,
+ CXXStaticCastExpr> cxxStaticCastExpr;
+
+/// \brief Matches a dynamic_cast expression.
+///
+/// Example:
+/// cxxDynamicCastExpr()
+/// matches
+/// dynamic_cast<D*>(&b);
+/// in
+/// \code
+/// struct B { virtual ~B() {} }; struct D : B {};
+/// B b;
+/// D* p = dynamic_cast<D*>(&b);
+/// \endcode
+const internal::VariadicDynCastAllOfMatcher<
+ Stmt,
+ CXXDynamicCastExpr> cxxDynamicCastExpr;
+
+/// \brief Matches a const_cast expression.
+///
+/// Example: Matches const_cast<int*>(&r) in
+/// \code
+/// int n = 42;
+/// const int &r(n);
+/// int* p = const_cast<int*>(&r);
+/// \endcode
+const internal::VariadicDynCastAllOfMatcher<
+ Stmt,
+ CXXConstCastExpr> cxxConstCastExpr;
+
+/// \brief Matches a C-style cast expression.
+///
+/// Example: Matches (int*) 2.2f in
+/// \code
+/// int i = (int) 2.2f;
+/// \endcode
+const internal::VariadicDynCastAllOfMatcher<
+ Stmt,
+ CStyleCastExpr> cStyleCastExpr;
+
+/// \brief Matches explicit cast expressions.
+///
+/// Matches any cast expression written in user code, whether it be a
+/// C-style cast, a functional-style cast, or a keyword cast.
+///
+/// Does not match implicit conversions.
+///
+/// Note: the name "explicitCast" is chosen to match Clang's terminology, as
+/// Clang uses the term "cast" to apply to implicit conversions as well as to
+/// actual cast expressions.
+///
+/// \see hasDestinationType.
+///
+/// Example: matches all five of the casts in
+/// \code
+/// int((int)(reinterpret_cast<int>(static_cast<int>(const_cast<int>(42)))))
+/// \endcode
+/// but does not match the implicit conversion in
+/// \code
+/// long ell = 42;
+/// \endcode
+const internal::VariadicDynCastAllOfMatcher<
+ Stmt,
+ ExplicitCastExpr> explicitCastExpr;
+
+/// \brief Matches the implicit cast nodes of Clang's AST.
+///
+/// This matches many different places, including function call return value
+/// eliding, as well as any type conversions.
+const internal::VariadicDynCastAllOfMatcher<
+ Stmt,
+ ImplicitCastExpr> implicitCastExpr;
+
+/// \brief Matches any cast nodes of Clang's AST.
+///
+/// Example: castExpr() matches each of the following:
+/// \code
+/// (int) 3;
+/// const_cast<Expr *>(SubExpr);
+/// char c = 0;
+/// \endcode
+/// but does not match
+/// \code
+/// int i = (0);
+/// int k = 0;
+/// \endcode
+const internal::VariadicDynCastAllOfMatcher<Stmt, CastExpr> castExpr;
+
+/// \brief Matches functional cast expressions
+///
+/// Example: Matches Foo(bar);
+/// \code
+/// Foo f = bar;
+/// Foo g = (Foo) bar;
+/// Foo h = Foo(bar);
+/// \endcode
+const internal::VariadicDynCastAllOfMatcher<
+ Stmt,
+ CXXFunctionalCastExpr> cxxFunctionalCastExpr;
+
+/// \brief Matches functional cast expressions having N != 1 arguments
+///
+/// Example: Matches Foo(bar, bar)
+/// \code
+/// Foo h = Foo(bar, bar);
+/// \endcode
+const internal::VariadicDynCastAllOfMatcher<
+ Stmt,
+ CXXTemporaryObjectExpr> cxxTemporaryObjectExpr;
+
+/// \brief Matches \c QualTypes in the clang AST.
+const internal::VariadicAllOfMatcher<QualType> qualType;
+
+/// \brief Matches \c Types in the clang AST.
+const internal::VariadicAllOfMatcher<Type> type;
+
+/// \brief Matches \c TypeLocs in the clang AST.
+const internal::VariadicAllOfMatcher<TypeLoc> typeLoc;
+
+/// \brief Matches if any of the given matchers matches.
+///
+/// Unlike \c anyOf, \c eachOf will generate a match result for each
+/// matching submatcher.
+///
+/// For example, in:
+/// \code
+/// class A { int a; int b; };
+/// \endcode
+/// The matcher:
+/// \code
+/// cxxRecordDecl(eachOf(has(fieldDecl(hasName("a")).bind("v")),
+/// has(fieldDecl(hasName("b")).bind("v"))))
+/// \endcode
+/// will generate two results binding "v", the first of which binds
+/// the field declaration of \c a, the second the field declaration of
+/// \c b.
+///
+/// Usable as: Any Matcher
+const internal::VariadicOperatorMatcherFunc<2, UINT_MAX> eachOf = {
+ internal::DynTypedMatcher::VO_EachOf
+};
+
+/// \brief Matches if any of the given matchers matches.
+///
+/// Usable as: Any Matcher
+const internal::VariadicOperatorMatcherFunc<2, UINT_MAX> anyOf = {
+ internal::DynTypedMatcher::VO_AnyOf
+};
+
+/// \brief Matches if all given matchers match.
+///
+/// Usable as: Any Matcher
+const internal::VariadicOperatorMatcherFunc<2, UINT_MAX> allOf = {
+ internal::DynTypedMatcher::VO_AllOf
+};
+
+/// \brief Matches sizeof (C99), alignof (C++11) and vec_step (OpenCL)
+///
+/// Given
+/// \code
+/// Foo x = bar;
+/// int y = sizeof(x) + alignof(x);
+/// \endcode
+/// unaryExprOrTypeTraitExpr()
+/// matches \c sizeof(x) and \c alignof(x)
+const internal::VariadicDynCastAllOfMatcher<
+ Stmt,
+ UnaryExprOrTypeTraitExpr> unaryExprOrTypeTraitExpr;
+
+/// \brief Matches unary expressions that have a specific type of argument.
+///
+/// Given
+/// \code
+/// int a, c; float b; int s = sizeof(a) + sizeof(b) + alignof(c);
+/// \endcode
+/// unaryExprOrTypeTraitExpr(hasArgumentOfType(asString("int"))
+/// matches \c sizeof(a) and \c alignof(c)
+AST_MATCHER_P(UnaryExprOrTypeTraitExpr, hasArgumentOfType,
+ internal::Matcher<QualType>, InnerMatcher) {
+ const QualType ArgumentType = Node.getTypeOfArgument();
+ return InnerMatcher.matches(ArgumentType, Finder, Builder);
+}
+
+/// \brief Matches unary expressions of a certain kind.
+///
+/// Given
+/// \code
+/// int x;
+/// int s = sizeof(x) + alignof(x)
+/// \endcode
+/// unaryExprOrTypeTraitExpr(ofKind(UETT_SizeOf))
+/// matches \c sizeof(x)
+AST_MATCHER_P(UnaryExprOrTypeTraitExpr, ofKind, UnaryExprOrTypeTrait, Kind) {
+ return Node.getKind() == Kind;
+}
+
+/// \brief Same as unaryExprOrTypeTraitExpr, but only matching
+/// alignof.
+inline internal::Matcher<Stmt> alignOfExpr(
+ const internal::Matcher<UnaryExprOrTypeTraitExpr> &InnerMatcher) {
+ return stmt(unaryExprOrTypeTraitExpr(allOf(
+ ofKind(UETT_AlignOf), InnerMatcher)));
+}
+
+/// \brief Same as unaryExprOrTypeTraitExpr, but only matching
+/// sizeof.
+inline internal::Matcher<Stmt> sizeOfExpr(
+ const internal::Matcher<UnaryExprOrTypeTraitExpr> &InnerMatcher) {
+ return stmt(unaryExprOrTypeTraitExpr(
+ allOf(ofKind(UETT_SizeOf), InnerMatcher)));
+}
+
+/// \brief Matches NamedDecl nodes that have the specified name.
+///
+/// Supports specifying enclosing namespaces or classes by prefixing the name
+/// with '<enclosing>::'.
+/// Does not match typedefs of an underlying type with the given name.
+///
+/// Example matches X (Name == "X")
+/// \code
+/// class X;
+/// \endcode
+///
+/// Example matches X (Name is one of "::a::b::X", "a::b::X", "b::X", "X")
+/// \code
+/// namespace a { namespace b { class X; } }
+/// \endcode
+inline internal::Matcher<NamedDecl> hasName(const std::string &Name) {
+ return internal::Matcher<NamedDecl>(new internal::HasNameMatcher(Name));
+}
+
+/// \brief Matches NamedDecl nodes whose fully qualified names contain
+/// a substring matched by the given RegExp.
+///
+/// Supports specifying enclosing namespaces or classes by
+/// prefixing the name with '<enclosing>::'. Does not match typedefs
+/// of an underlying type with the given name.
+///
+/// Example matches X (regexp == "::X")
+/// \code
+/// class X;
+/// \endcode
+///
+/// Example matches X (regexp is one of "::X", "^foo::.*X", among others)
+/// \code
+/// namespace foo { namespace bar { class X; } }
+/// \endcode
+AST_MATCHER_P(NamedDecl, matchesName, std::string, RegExp) {
+ assert(!RegExp.empty());
+ std::string FullNameString = "::" + Node.getQualifiedNameAsString();
+ llvm::Regex RE(RegExp);
+ return RE.match(FullNameString);
+}
+
+/// \brief Matches overloaded operator names.
+///
+/// Matches overloaded operator names specified in strings without the
+/// "operator" prefix: e.g. "<<".
+///
+/// Given:
+/// \code
+/// class A { int operator*(); };
+/// const A &operator<<(const A &a, const A &b);
+/// A a;
+/// a << a; // <-- This matches
+/// \endcode
+///
+/// \c cxxOperatorCallExpr(hasOverloadedOperatorName("<<"))) matches the
+/// specified line and
+/// \c cxxRecordDecl(hasMethod(hasOverloadedOperatorName("*")))
+/// matches the declaration of \c A.
+///
+/// Usable as: Matcher<CXXOperatorCallExpr>, Matcher<FunctionDecl>
+inline internal::PolymorphicMatcherWithParam1<
+ internal::HasOverloadedOperatorNameMatcher, StringRef,
+ AST_POLYMORPHIC_SUPPORTED_TYPES(CXXOperatorCallExpr, FunctionDecl)>
+hasOverloadedOperatorName(StringRef Name) {
+ return internal::PolymorphicMatcherWithParam1<
+ internal::HasOverloadedOperatorNameMatcher, StringRef,
+ AST_POLYMORPHIC_SUPPORTED_TYPES(CXXOperatorCallExpr, FunctionDecl)>(Name);
+}
+
+/// \brief Matches C++ classes that are directly or indirectly derived from
+/// a class matching \c Base.
+///
+/// Note that a class is not considered to be derived from itself.
+///
+/// Example matches Y, Z, C (Base == hasName("X"))
+/// \code
+/// class X;
+/// class Y : public X {}; // directly derived
+/// class Z : public Y {}; // indirectly derived
+/// typedef X A;
+/// typedef A B;
+/// class C : public B {}; // derived from a typedef of X
+/// \endcode
+///
+/// In the following example, Bar matches isDerivedFrom(hasName("X")):
+/// \code
+/// class Foo;
+/// typedef Foo X;
+/// class Bar : public Foo {}; // derived from a type that X is a typedef of
+/// \endcode
+AST_MATCHER_P(CXXRecordDecl, isDerivedFrom,
+ internal::Matcher<NamedDecl>, Base) {
+ return Finder->classIsDerivedFrom(&Node, Base, Builder);
+}
+
+/// \brief Overloaded method as shortcut for \c isDerivedFrom(hasName(...)).
+AST_MATCHER_P_OVERLOAD(CXXRecordDecl, isDerivedFrom, std::string, BaseName, 1) {
+ assert(!BaseName.empty());
+ return isDerivedFrom(hasName(BaseName)).matches(Node, Finder, Builder);
+}
+
+/// \brief Similar to \c isDerivedFrom(), but also matches classes that directly
+/// match \c Base.
+AST_MATCHER_P_OVERLOAD(CXXRecordDecl, isSameOrDerivedFrom,
+ internal::Matcher<NamedDecl>, Base, 0) {
+ return Matcher<CXXRecordDecl>(anyOf(Base, isDerivedFrom(Base)))
+ .matches(Node, Finder, Builder);
+}
+
+/// \brief Overloaded method as shortcut for
+/// \c isSameOrDerivedFrom(hasName(...)).
+AST_MATCHER_P_OVERLOAD(CXXRecordDecl, isSameOrDerivedFrom, std::string,
+ BaseName, 1) {
+ assert(!BaseName.empty());
+ return isSameOrDerivedFrom(hasName(BaseName)).matches(Node, Finder, Builder);
+}
+
+/// \brief Matches the first method of a class or struct that satisfies \c
+/// InnerMatcher.
+///
+/// Given:
+/// \code
+/// class A { void func(); };
+/// class B { void member(); };
+/// \endcode
+///
+/// \c cxxRecordDecl(hasMethod(hasName("func"))) matches the declaration of
+/// \c A but not \c B.
+AST_MATCHER_P(CXXRecordDecl, hasMethod, internal::Matcher<CXXMethodDecl>,
+ InnerMatcher) {
+ return matchesFirstInPointerRange(InnerMatcher, Node.method_begin(),
+ Node.method_end(), Finder, Builder);
+}
+
+/// \brief Matches AST nodes that have child AST nodes that match the
+/// provided matcher.
+///
+/// Example matches X, Y
+/// (matcher = cxxRecordDecl(has(cxxRecordDecl(hasName("X")))
+/// \code
+/// class X {}; // Matches X, because X::X is a class of name X inside X.
+/// class Y { class X {}; };
+/// class Z { class Y { class X {}; }; }; // Does not match Z.
+/// \endcode
+///
+/// ChildT must be an AST base type.
+///
+/// Usable as: Any Matcher
+const internal::ArgumentAdaptingMatcherFunc<internal::HasMatcher>
+LLVM_ATTRIBUTE_UNUSED has = {};
+
+/// \brief Matches AST nodes that have descendant AST nodes that match the
+/// provided matcher.
+///
+/// Example matches X, Y, Z
+/// (matcher = cxxRecordDecl(hasDescendant(cxxRecordDecl(hasName("X")))))
+/// \code
+/// class X {}; // Matches X, because X::X is a class of name X inside X.
+/// class Y { class X {}; };
+/// class Z { class Y { class X {}; }; };
+/// \endcode
+///
+/// DescendantT must be an AST base type.
+///
+/// Usable as: Any Matcher
+const internal::ArgumentAdaptingMatcherFunc<internal::HasDescendantMatcher>
+LLVM_ATTRIBUTE_UNUSED hasDescendant = {};
+
+/// \brief Matches AST nodes that have child AST nodes that match the
+/// provided matcher.
+///
+/// Example matches X, Y
+/// (matcher = cxxRecordDecl(forEach(cxxRecordDecl(hasName("X")))
+/// \code
+/// class X {}; // Matches X, because X::X is a class of name X inside X.
+/// class Y { class X {}; };
+/// class Z { class Y { class X {}; }; }; // Does not match Z.
+/// \endcode
+///
+/// ChildT must be an AST base type.
+///
+/// As opposed to 'has', 'forEach' will cause a match for each result that
+/// matches instead of only on the first one.
+///
+/// Usable as: Any Matcher
+const internal::ArgumentAdaptingMatcherFunc<internal::ForEachMatcher>
+LLVM_ATTRIBUTE_UNUSED forEach = {};
+
+/// \brief Matches AST nodes that have descendant AST nodes that match the
+/// provided matcher.
+///
+/// Example matches X, A, B, C
+/// (matcher = cxxRecordDecl(forEachDescendant(cxxRecordDecl(hasName("X")))))
+/// \code
+/// class X {}; // Matches X, because X::X is a class of name X inside X.
+/// class A { class X {}; };
+/// class B { class C { class X {}; }; };
+/// \endcode
+///
+/// DescendantT must be an AST base type.
+///
+/// As opposed to 'hasDescendant', 'forEachDescendant' will cause a match for
+/// each result that matches instead of only on the first one.
+///
+/// Note: Recursively combined ForEachDescendant can cause many matches:
+/// cxxRecordDecl(forEachDescendant(cxxRecordDecl(
+/// forEachDescendant(cxxRecordDecl())
+/// )))
+/// will match 10 times (plus injected class name matches) on:
+/// \code
+/// class A { class B { class C { class D { class E {}; }; }; }; };
+/// \endcode
+///
+/// Usable as: Any Matcher
+const internal::ArgumentAdaptingMatcherFunc<internal::ForEachDescendantMatcher>
+LLVM_ATTRIBUTE_UNUSED forEachDescendant = {};
+
+/// \brief Matches if the node or any descendant matches.
+///
+/// Generates results for each match.
+///
+/// For example, in:
+/// \code
+/// class A { class B {}; class C {}; };
+/// \endcode
+/// The matcher:
+/// \code
+/// cxxRecordDecl(hasName("::A"),
+/// findAll(cxxRecordDecl(isDefinition()).bind("m")))
+/// \endcode
+/// will generate results for \c A, \c B and \c C.
+///
+/// Usable as: Any Matcher
+template <typename T>
+internal::Matcher<T> findAll(const internal::Matcher<T> &Matcher) {
+ return eachOf(Matcher, forEachDescendant(Matcher));
+}
+
+/// \brief Matches AST nodes that have a parent that matches the provided
+/// matcher.
+///
+/// Given
+/// \code
+/// void f() { for (;;) { int x = 42; if (true) { int x = 43; } } }
+/// \endcode
+/// \c compoundStmt(hasParent(ifStmt())) matches "{ int x = 43; }".
+///
+/// Usable as: Any Matcher
+const internal::ArgumentAdaptingMatcherFunc<
+ internal::HasParentMatcher,
+ internal::TypeList<Decl, NestedNameSpecifierLoc, Stmt, TypeLoc>,
+ internal::TypeList<Decl, NestedNameSpecifierLoc, Stmt, TypeLoc>>
+ LLVM_ATTRIBUTE_UNUSED hasParent = {};
+
+/// \brief Matches AST nodes that have an ancestor that matches the provided
+/// matcher.
+///
+/// Given
+/// \code
+/// void f() { if (true) { int x = 42; } }
+/// void g() { for (;;) { int x = 43; } }
+/// \endcode
+/// \c expr(integerLiteral(hasAncestor(ifStmt()))) matches \c 42, but not 43.
+///
+/// Usable as: Any Matcher
+const internal::ArgumentAdaptingMatcherFunc<
+ internal::HasAncestorMatcher,
+ internal::TypeList<Decl, NestedNameSpecifierLoc, Stmt, TypeLoc>,
+ internal::TypeList<Decl, NestedNameSpecifierLoc, Stmt, TypeLoc>>
+ LLVM_ATTRIBUTE_UNUSED hasAncestor = {};
+
+/// \brief Matches if the provided matcher does not match.
+///
+/// Example matches Y (matcher = cxxRecordDecl(unless(hasName("X"))))
+/// \code
+/// class X {};
+/// class Y {};
+/// \endcode
+///
+/// Usable as: Any Matcher
+const internal::VariadicOperatorMatcherFunc<1, 1> unless = {
+ internal::DynTypedMatcher::VO_UnaryNot
+};
+
+/// \brief Matches a node if the declaration associated with that node
+/// matches the given matcher.
+///
+/// The associated declaration is:
+/// - for type nodes, the declaration of the underlying type
+/// - for CallExpr, the declaration of the callee
+/// - for MemberExpr, the declaration of the referenced member
+/// - for CXXConstructExpr, the declaration of the constructor
+///
+/// Also usable as Matcher<T> for any T supporting the getDecl() member
+/// function. e.g. various subtypes of clang::Type and various expressions.
+///
+/// Usable as: Matcher<CallExpr>, Matcher<CXXConstructExpr>,
+/// Matcher<DeclRefExpr>, Matcher<EnumType>, Matcher<InjectedClassNameType>,
+/// Matcher<LabelStmt>, Matcher<MemberExpr>, Matcher<QualType>,
+/// Matcher<RecordType>, Matcher<TagType>,
+/// Matcher<TemplateSpecializationType>, Matcher<TemplateTypeParmType>,
+/// Matcher<TypedefType>, Matcher<UnresolvedUsingType>
+inline internal::PolymorphicMatcherWithParam1<
+ internal::HasDeclarationMatcher, internal::Matcher<Decl>,
+ void(internal::HasDeclarationSupportedTypes)>
+hasDeclaration(const internal::Matcher<Decl> &InnerMatcher) {
+ return internal::PolymorphicMatcherWithParam1<
+ internal::HasDeclarationMatcher, internal::Matcher<Decl>,
+ void(internal::HasDeclarationSupportedTypes)>(InnerMatcher);
+}
+
+/// \brief Matches on the implicit object argument of a member call expression.
+///
+/// Example matches y.x()
+/// (matcher = cxxMemberCallExpr(on(hasType(cxxRecordDecl(hasName("Y"))))))
+/// \code
+/// class Y { public: void x(); };
+/// void z() { Y y; y.x(); }",
+/// \endcode
+///
+/// FIXME: Overload to allow directly matching types?
+AST_MATCHER_P(CXXMemberCallExpr, on, internal::Matcher<Expr>,
+ InnerMatcher) {
+ const Expr *ExprNode = Node.getImplicitObjectArgument()
+ ->IgnoreParenImpCasts();
+ return (ExprNode != nullptr &&
+ InnerMatcher.matches(*ExprNode, Finder, Builder));
+}
+
+
+/// \brief Matches on the receiver of an ObjectiveC Message expression.
+///
+/// Example
+/// matcher = objCMessageExpr(hasRecieverType(asString("UIWebView *")));
+/// matches the [webView ...] message invocation.
+/// \code
+/// NSString *webViewJavaScript = ...
+/// UIWebView *webView = ...
+/// [webView stringByEvaluatingJavaScriptFromString:webViewJavascript];
+/// \endcode
+AST_MATCHER_P(ObjCMessageExpr, hasReceiverType, internal::Matcher<QualType>,
+ InnerMatcher) {
+ const QualType TypeDecl = Node.getReceiverType();
+ return InnerMatcher.matches(TypeDecl, Finder, Builder);
+}
+
+/// \brief Matches when BaseName == Selector.getAsString()
+///
+/// matcher = objCMessageExpr(hasSelector("loadHTMLString:baseURL:"));
+/// matches the outer message expr in the code below, but NOT the message
+/// invocation for self.bodyView.
+/// \code
+/// [self.bodyView loadHTMLString:html baseURL:NULL];
+/// \endcode
+AST_MATCHER_P(ObjCMessageExpr, hasSelector, std::string, BaseName) {
+ Selector Sel = Node.getSelector();
+ return BaseName.compare(Sel.getAsString()) == 0;
+}
+
+
+/// \brief Matches ObjC selectors whose name contains
+/// a substring matched by the given RegExp.
+/// matcher = objCMessageExpr(matchesSelector("loadHTMLString\:baseURL?"));
+/// matches the outer message expr in the code below, but NOT the message
+/// invocation for self.bodyView.
+/// \code
+/// [self.bodyView loadHTMLString:html baseURL:NULL];
+/// \endcode
+AST_MATCHER_P(ObjCMessageExpr, matchesSelector, std::string, RegExp) {
+ assert(!RegExp.empty());
+ std::string SelectorString = Node.getSelector().getAsString();
+ llvm::Regex RE(RegExp);
+ return RE.match(SelectorString);
+}
+
+/// \brief Matches when the selector is the empty selector
+///
+/// Matches only when the selector of the objCMessageExpr is NULL. This may
+/// represent an error condition in the tree!
+AST_MATCHER(ObjCMessageExpr, hasNullSelector) {
+ return Node.getSelector().isNull();
+}
+
+/// \brief Matches when the selector is a Unary Selector
+///
+/// matcher = objCMessageExpr(matchesSelector(hasUnarySelector());
+/// matches self.bodyView in the code below, but NOT the outer message
+/// invocation of "loadHTMLString:baseURL:".
+/// \code
+/// [self.bodyView loadHTMLString:html baseURL:NULL];
+/// \endcode
+AST_MATCHER(ObjCMessageExpr, hasUnarySelector) {
+ return Node.getSelector().isUnarySelector();
+}
+
+/// \brief Matches when the selector is a keyword selector
+///
+/// objCMessageExpr(hasKeywordSelector()) matches the generated setFrame
+/// message expression in
+///
+/// \code
+/// UIWebView *webView = ...;
+/// CGRect bodyFrame = webView.frame;
+/// bodyFrame.size.height = self.bodyContentHeight;
+/// webView.frame = bodyFrame;
+/// // ^---- matches here
+/// \endcode
+AST_MATCHER(ObjCMessageExpr, hasKeywordSelector) {
+ return Node.getSelector().isKeywordSelector();
+}
+
+/// \brief Matches when the selector has the specified number of arguments
+///
+/// matcher = objCMessageExpr(numSelectorArgs(0));
+/// matches self.bodyView in the code below
+///
+/// matcher = objCMessageExpr(numSelectorArgs(2));
+/// matches the invocation of "loadHTMLString:baseURL:" but not that
+/// of self.bodyView
+/// \code
+/// [self.bodyView loadHTMLString:html baseURL:NULL];
+/// \endcode
+AST_MATCHER_P(ObjCMessageExpr, numSelectorArgs, unsigned, N) {
+ return Node.getSelector().getNumArgs() == N;
+}
+
+/// \brief Matches if the call expression's callee expression matches.
+///
+/// Given
+/// \code
+/// class Y { void x() { this->x(); x(); Y y; y.x(); } };
+/// void f() { f(); }
+/// \endcode
+/// callExpr(callee(expr()))
+/// matches this->x(), x(), y.x(), f()
+/// with callee(...)
+/// matching this->x, x, y.x, f respectively
+///
+/// Note: Callee cannot take the more general internal::Matcher<Expr>
+/// because this introduces ambiguous overloads with calls to Callee taking a
+/// internal::Matcher<Decl>, as the matcher hierarchy is purely
+/// implemented in terms of implicit casts.
+AST_MATCHER_P(CallExpr, callee, internal::Matcher<Stmt>,
+ InnerMatcher) {
+ const Expr *ExprNode = Node.getCallee();
+ return (ExprNode != nullptr &&
+ InnerMatcher.matches(*ExprNode, Finder, Builder));
+}
+
+/// \brief Matches if the call expression's callee's declaration matches the
+/// given matcher.
+///
+/// Example matches y.x() (matcher = callExpr(callee(
+/// cxxMethodDecl(hasName("x")))))
+/// \code
+/// class Y { public: void x(); };
+/// void z() { Y y; y.x(); }
+/// \endcode
+AST_MATCHER_P_OVERLOAD(CallExpr, callee, internal::Matcher<Decl>, InnerMatcher,
+ 1) {
+ return callExpr(hasDeclaration(InnerMatcher)).matches(Node, Finder, Builder);
+}
+
+/// \brief Matches if the expression's or declaration's type matches a type
+/// matcher.
+///
+/// Example matches x (matcher = expr(hasType(cxxRecordDecl(hasName("X")))))
+/// and z (matcher = varDecl(hasType(cxxRecordDecl(hasName("X")))))
+/// \code
+/// class X {};
+/// void y(X &x) { x; X z; }
+/// \endcode
+AST_POLYMORPHIC_MATCHER_P_OVERLOAD(
+ hasType, AST_POLYMORPHIC_SUPPORTED_TYPES(Expr, ValueDecl),
+ internal::Matcher<QualType>, InnerMatcher, 0) {
+ return InnerMatcher.matches(Node.getType(), Finder, Builder);
+}
+
+/// \brief Overloaded to match the declaration of the expression's or value
+/// declaration's type.
+///
+/// In case of a value declaration (for example a variable declaration),
+/// this resolves one layer of indirection. For example, in the value
+/// declaration "X x;", cxxRecordDecl(hasName("X")) matches the declaration of
+/// X, while varDecl(hasType(cxxRecordDecl(hasName("X")))) matches the
+/// declaration of x.
+///
+/// Example matches x (matcher = expr(hasType(cxxRecordDecl(hasName("X")))))
+/// and z (matcher = varDecl(hasType(cxxRecordDecl(hasName("X")))))
+/// \code
+/// class X {};
+/// void y(X &x) { x; X z; }
+/// \endcode
+///
+/// Usable as: Matcher<Expr>, Matcher<ValueDecl>
+AST_POLYMORPHIC_MATCHER_P_OVERLOAD(hasType,
+ AST_POLYMORPHIC_SUPPORTED_TYPES(Expr,
+ ValueDecl),
+ internal::Matcher<Decl>, InnerMatcher, 1) {
+ return qualType(hasDeclaration(InnerMatcher))
+ .matches(Node.getType(), Finder, Builder);
+}
+
+/// \brief Matches if the type location of the declarator decl's type matches
+/// the inner matcher.
+///
+/// Given
+/// \code
+/// int x;
+/// \endcode
+/// declaratorDecl(hasTypeLoc(loc(asString("int"))))
+/// matches int x
+AST_MATCHER_P(DeclaratorDecl, hasTypeLoc, internal::Matcher<TypeLoc>, Inner) {
+ if (!Node.getTypeSourceInfo())
+ // This happens for example for implicit destructors.
+ return false;
+ return Inner.matches(Node.getTypeSourceInfo()->getTypeLoc(), Finder, Builder);
+}
+
+/// \brief Matches if the matched type is represented by the given string.
+///
+/// Given
+/// \code
+/// class Y { public: void x(); };
+/// void z() { Y* y; y->x(); }
+/// \endcode
+/// cxxMemberCallExpr(on(hasType(asString("class Y *"))))
+/// matches y->x()
+AST_MATCHER_P(QualType, asString, std::string, Name) {
+ return Name == Node.getAsString();
+}
+
+/// \brief Matches if the matched type is a pointer type and the pointee type
+/// matches the specified matcher.
+///
+/// Example matches y->x()
+/// (matcher = cxxMemberCallExpr(on(hasType(pointsTo
+/// cxxRecordDecl(hasName("Y")))))))
+/// \code
+/// class Y { public: void x(); };
+/// void z() { Y *y; y->x(); }
+/// \endcode
+AST_MATCHER_P(
+ QualType, pointsTo, internal::Matcher<QualType>,
+ InnerMatcher) {
+ return (!Node.isNull() && Node->isAnyPointerType() &&
+ InnerMatcher.matches(Node->getPointeeType(), Finder, Builder));
+}
+
+/// \brief Overloaded to match the pointee type's declaration.
+AST_MATCHER_P_OVERLOAD(QualType, pointsTo, internal::Matcher<Decl>,
+ InnerMatcher, 1) {
+ return pointsTo(qualType(hasDeclaration(InnerMatcher)))
+ .matches(Node, Finder, Builder);
+}
+
+/// \brief Matches if the matched type is a reference type and the referenced
+/// type matches the specified matcher.
+///
+/// Example matches X &x and const X &y
+/// (matcher = varDecl(hasType(references(cxxRecordDecl(hasName("X"))))))
+/// \code
+/// class X {
+/// void a(X b) {
+/// X &x = b;
+/// const X &y = b;
+/// }
+/// };
+/// \endcode
+AST_MATCHER_P(QualType, references, internal::Matcher<QualType>,
+ InnerMatcher) {
+ return (!Node.isNull() && Node->isReferenceType() &&
+ InnerMatcher.matches(Node->getPointeeType(), Finder, Builder));
+}
+
+/// \brief Matches QualTypes whose canonical type matches InnerMatcher.
+///
+/// Given:
+/// \code
+/// typedef int &int_ref;
+/// int a;
+/// int_ref b = a;
+/// \endcode
+///
+/// \c varDecl(hasType(qualType(referenceType()))))) will not match the
+/// declaration of b but \c
+/// varDecl(hasType(qualType(hasCanonicalType(referenceType())))))) does.
+AST_MATCHER_P(QualType, hasCanonicalType, internal::Matcher<QualType>,
+ InnerMatcher) {
+ if (Node.isNull())
+ return false;
+ return InnerMatcher.matches(Node.getCanonicalType(), Finder, Builder);
+}
+
+/// \brief Overloaded to match the referenced type's declaration.
+AST_MATCHER_P_OVERLOAD(QualType, references, internal::Matcher<Decl>,
+ InnerMatcher, 1) {
+ return references(qualType(hasDeclaration(InnerMatcher)))
+ .matches(Node, Finder, Builder);
+}
+
+AST_MATCHER_P(CXXMemberCallExpr, onImplicitObjectArgument,
+ internal::Matcher<Expr>, InnerMatcher) {
+ const Expr *ExprNode = Node.getImplicitObjectArgument();
+ return (ExprNode != nullptr &&
+ InnerMatcher.matches(*ExprNode, Finder, Builder));
+}
+
+/// \brief Matches if the expression's type either matches the specified
+/// matcher, or is a pointer to a type that matches the InnerMatcher.
+AST_MATCHER_P_OVERLOAD(CXXMemberCallExpr, thisPointerType,
+ internal::Matcher<QualType>, InnerMatcher, 0) {
+ return onImplicitObjectArgument(
+ anyOf(hasType(InnerMatcher), hasType(pointsTo(InnerMatcher))))
+ .matches(Node, Finder, Builder);
+}
+
+/// \brief Overloaded to match the type's declaration.
+AST_MATCHER_P_OVERLOAD(CXXMemberCallExpr, thisPointerType,
+ internal::Matcher<Decl>, InnerMatcher, 1) {
+ return onImplicitObjectArgument(
+ anyOf(hasType(InnerMatcher), hasType(pointsTo(InnerMatcher))))
+ .matches(Node, Finder, Builder);
+}
+
+/// \brief Matches a DeclRefExpr that refers to a declaration that matches the
+/// specified matcher.
+///
+/// Example matches x in if(x)
+/// (matcher = declRefExpr(to(varDecl(hasName("x")))))
+/// \code
+/// bool x;
+/// if (x) {}
+/// \endcode
+AST_MATCHER_P(DeclRefExpr, to, internal::Matcher<Decl>,
+ InnerMatcher) {
+ const Decl *DeclNode = Node.getDecl();
+ return (DeclNode != nullptr &&
+ InnerMatcher.matches(*DeclNode, Finder, Builder));
+}
+
+/// \brief Matches a \c DeclRefExpr that refers to a declaration through a
+/// specific using shadow declaration.
+///
+/// Given
+/// \code
+/// namespace a { void f() {} }
+/// using a::f;
+/// void g() {
+/// f(); // Matches this ..
+/// a::f(); // .. but not this.
+/// }
+/// \endcode
+/// declRefExpr(throughUsingDecl(anything()))
+/// matches \c f()
+AST_MATCHER_P(DeclRefExpr, throughUsingDecl,
+ internal::Matcher<UsingShadowDecl>, InnerMatcher) {
+ const NamedDecl *FoundDecl = Node.getFoundDecl();
+ if (const UsingShadowDecl *UsingDecl = dyn_cast<UsingShadowDecl>(FoundDecl))
+ return InnerMatcher.matches(*UsingDecl, Finder, Builder);
+ return false;
+}
+
+/// \brief Matches the Decl of a DeclStmt which has a single declaration.
+///
+/// Given
+/// \code
+/// int a, b;
+/// int c;
+/// \endcode
+/// declStmt(hasSingleDecl(anything()))
+/// matches 'int c;' but not 'int a, b;'.
+AST_MATCHER_P(DeclStmt, hasSingleDecl, internal::Matcher<Decl>, InnerMatcher) {
+ if (Node.isSingleDecl()) {
+ const Decl *FoundDecl = Node.getSingleDecl();
+ return InnerMatcher.matches(*FoundDecl, Finder, Builder);
+ }
+ return false;
+}
+
+/// \brief Matches a variable declaration that has an initializer expression
+/// that matches the given matcher.
+///
+/// Example matches x (matcher = varDecl(hasInitializer(callExpr())))
+/// \code
+/// bool y() { return true; }
+/// bool x = y();
+/// \endcode
+AST_MATCHER_P(
+ VarDecl, hasInitializer, internal::Matcher<Expr>,
+ InnerMatcher) {
+ const Expr *Initializer = Node.getAnyInitializer();
+ return (Initializer != nullptr &&
+ InnerMatcher.matches(*Initializer, Finder, Builder));
+}
+
+/// \brief Matches a variable declaration that has function scope and is a
+/// non-static local variable.
+///
+/// Example matches x (matcher = varDecl(hasLocalStorage())
+/// \code
+/// void f() {
+/// int x;
+/// static int y;
+/// }
+/// int z;
+/// \endcode
+AST_MATCHER(VarDecl, hasLocalStorage) {
+ return Node.hasLocalStorage();
+}
+
+/// \brief Matches a variable declaration that does not have local storage.
+///
+/// Example matches y and z (matcher = varDecl(hasGlobalStorage())
+/// \code
+/// void f() {
+/// int x;
+/// static int y;
+/// }
+/// int z;
+/// \endcode
+AST_MATCHER(VarDecl, hasGlobalStorage) {
+ return Node.hasGlobalStorage();
+}
+
+/// \brief Matches a variable declaration that has automatic storage duration.
+///
+/// Example matches x, but not y, z, or a.
+/// (matcher = varDecl(hasAutomaticStorageDuration())
+/// \code
+/// void f() {
+/// int x;
+/// static int y;
+/// thread_local int z;
+/// }
+/// int a;
+/// \endcode
+AST_MATCHER(VarDecl, hasAutomaticStorageDuration) {
+ return Node.getStorageDuration() == SD_Automatic;
+}
+
+/// \brief Matches a variable declaration that has static storage duration.
+///
+/// Example matches y and a, but not x or z.
+/// (matcher = varDecl(hasStaticStorageDuration())
+/// \code
+/// void f() {
+/// int x;
+/// static int y;
+/// thread_local int z;
+/// }
+/// int a;
+/// \endcode
+AST_MATCHER(VarDecl, hasStaticStorageDuration) {
+ return Node.getStorageDuration() == SD_Static;
+}
+
+/// \brief Matches a variable declaration that has thread storage duration.
+///
+/// Example matches z, but not x, z, or a.
+/// (matcher = varDecl(hasThreadStorageDuration())
+/// \code
+/// void f() {
+/// int x;
+/// static int y;
+/// thread_local int z;
+/// }
+/// int a;
+/// \endcode
+AST_MATCHER(VarDecl, hasThreadStorageDuration) {
+ return Node.getStorageDuration() == SD_Thread;
+}
+
+/// \brief Matches a variable declaration that is an exception variable from
+/// a C++ catch block, or an Objective-C \@catch statement.
+///
+/// Example matches x (matcher = varDecl(isExceptionVariable())
+/// \code
+/// void f(int y) {
+/// try {
+/// } catch (int x) {
+/// }
+/// }
+/// \endcode
+AST_MATCHER(VarDecl, isExceptionVariable) {
+ return Node.isExceptionVariable();
+}
+
+/// \brief Checks that a call expression or a constructor call expression has
+/// a specific number of arguments (including absent default arguments).
+///
+/// Example matches f(0, 0) (matcher = callExpr(argumentCountIs(2)))
+/// \code
+/// void f(int x, int y);
+/// f(0, 0);
+/// \endcode
+AST_POLYMORPHIC_MATCHER_P(argumentCountIs,
+ AST_POLYMORPHIC_SUPPORTED_TYPES(CallExpr,
+ CXXConstructExpr,
+ ObjCMessageExpr),
+ unsigned, N) {
+ return Node.getNumArgs() == N;
+}
+
+/// \brief Matches the n'th argument of a call expression or a constructor
+/// call expression.
+///
+/// Example matches y in x(y)
+/// (matcher = callExpr(hasArgument(0, declRefExpr())))
+/// \code
+/// void x(int) { int y; x(y); }
+/// \endcode
+AST_POLYMORPHIC_MATCHER_P2(hasArgument,
+ AST_POLYMORPHIC_SUPPORTED_TYPES(CallExpr,
+ CXXConstructExpr,
+ ObjCMessageExpr),
+ unsigned, N, internal::Matcher<Expr>, InnerMatcher) {
+ return (N < Node.getNumArgs() &&
+ InnerMatcher.matches(
+ *Node.getArg(N)->IgnoreParenImpCasts(), Finder, Builder));
+}
+
+/// \brief Matches declaration statements that contain a specific number of
+/// declarations.
+///
+/// Example: Given
+/// \code
+/// int a, b;
+/// int c;
+/// int d = 2, e;
+/// \endcode
+/// declCountIs(2)
+/// matches 'int a, b;' and 'int d = 2, e;', but not 'int c;'.
+AST_MATCHER_P(DeclStmt, declCountIs, unsigned, N) {
+ return std::distance(Node.decl_begin(), Node.decl_end()) == (ptrdiff_t)N;
+}
+
+/// \brief Matches the n'th declaration of a declaration statement.
+///
+/// Note that this does not work for global declarations because the AST
+/// breaks up multiple-declaration DeclStmt's into multiple single-declaration
+/// DeclStmt's.
+/// Example: Given non-global declarations
+/// \code
+/// int a, b = 0;
+/// int c;
+/// int d = 2, e;
+/// \endcode
+/// declStmt(containsDeclaration(
+/// 0, varDecl(hasInitializer(anything()))))
+/// matches only 'int d = 2, e;', and
+/// declStmt(containsDeclaration(1, varDecl()))
+/// \code
+/// matches 'int a, b = 0' as well as 'int d = 2, e;'
+/// but 'int c;' is not matched.
+/// \endcode
+AST_MATCHER_P2(DeclStmt, containsDeclaration, unsigned, N,
+ internal::Matcher<Decl>, InnerMatcher) {
+ const unsigned NumDecls = std::distance(Node.decl_begin(), Node.decl_end());
+ if (N >= NumDecls)
+ return false;
+ DeclStmt::const_decl_iterator Iterator = Node.decl_begin();
+ std::advance(Iterator, N);
+ return InnerMatcher.matches(**Iterator, Finder, Builder);
+}
+
+/// \brief Matches a C++ catch statement that has a catch-all handler.
+///
+/// Given
+/// \code
+/// try {
+/// // ...
+/// } catch (int) {
+/// // ...
+/// } catch (...) {
+/// // ...
+/// }
+/// /endcode
+/// cxxCatchStmt(isCatchAll()) matches catch(...) but not catch(int).
+AST_MATCHER(CXXCatchStmt, isCatchAll) {
+ return Node.getExceptionDecl() == nullptr;
+}
+
+/// \brief Matches a constructor initializer.
+///
+/// Given
+/// \code
+/// struct Foo {
+/// Foo() : foo_(1) { }
+/// int foo_;
+/// };
+/// \endcode
+/// cxxRecordDecl(has(cxxConstructorDecl(
+/// hasAnyConstructorInitializer(anything())
+/// )))
+/// record matches Foo, hasAnyConstructorInitializer matches foo_(1)
+AST_MATCHER_P(CXXConstructorDecl, hasAnyConstructorInitializer,
+ internal::Matcher<CXXCtorInitializer>, InnerMatcher) {
+ return matchesFirstInPointerRange(InnerMatcher, Node.init_begin(),
+ Node.init_end(), Finder, Builder);
+}
+
+/// \brief Matches the field declaration of a constructor initializer.
+///
+/// Given
+/// \code
+/// struct Foo {
+/// Foo() : foo_(1) { }
+/// int foo_;
+/// };
+/// \endcode
+/// cxxRecordDecl(has(cxxConstructorDecl(hasAnyConstructorInitializer(
+/// forField(hasName("foo_"))))))
+/// matches Foo
+/// with forField matching foo_
+AST_MATCHER_P(CXXCtorInitializer, forField,
+ internal::Matcher<FieldDecl>, InnerMatcher) {
+ const FieldDecl *NodeAsDecl = Node.getMember();
+ return (NodeAsDecl != nullptr &&
+ InnerMatcher.matches(*NodeAsDecl, Finder, Builder));
+}
+
+/// \brief Matches the initializer expression of a constructor initializer.
+///
+/// Given
+/// \code
+/// struct Foo {
+/// Foo() : foo_(1) { }
+/// int foo_;
+/// };
+/// \endcode
+/// cxxRecordDecl(has(cxxConstructorDecl(hasAnyConstructorInitializer(
+/// withInitializer(integerLiteral(equals(1)))))))
+/// matches Foo
+/// with withInitializer matching (1)
+AST_MATCHER_P(CXXCtorInitializer, withInitializer,
+ internal::Matcher<Expr>, InnerMatcher) {
+ const Expr* NodeAsExpr = Node.getInit();
+ return (NodeAsExpr != nullptr &&
+ InnerMatcher.matches(*NodeAsExpr, Finder, Builder));
+}
+
+/// \brief Matches a constructor initializer if it is explicitly written in
+/// code (as opposed to implicitly added by the compiler).
+///
+/// Given
+/// \code
+/// struct Foo {
+/// Foo() { }
+/// Foo(int) : foo_("A") { }
+/// string foo_;
+/// };
+/// \endcode
+/// cxxConstructorDecl(hasAnyConstructorInitializer(isWritten()))
+/// will match Foo(int), but not Foo()
+AST_MATCHER(CXXCtorInitializer, isWritten) {
+ return Node.isWritten();
+}
+
+/// \brief Matches a constructor initializer if it is initializing a base, as
+/// opposed to a member.
+///
+/// Given
+/// \code
+/// struct B {};
+/// struct D : B {
+/// int I;
+/// D(int i) : I(i) {}
+/// };
+/// struct E : B {
+/// E() : B() {}
+/// };
+/// \endcode
+/// cxxConstructorDecl(hasAnyConstructorInitializer(isBaseInitializer()))
+/// will match E(), but not match D(int).
+AST_MATCHER(CXXCtorInitializer, isBaseInitializer) {
+ return Node.isBaseInitializer();
+}
+
+/// \brief Matches a constructor initializer if it is initializing a member, as
+/// opposed to a base.
+///
+/// Given
+/// \code
+/// struct B {};
+/// struct D : B {
+/// int I;
+/// D(int i) : I(i) {}
+/// };
+/// struct E : B {
+/// E() : B() {}
+/// };
+/// \endcode
+/// cxxConstructorDecl(hasAnyConstructorInitializer(isMemberInitializer()))
+/// will match D(int), but not match E().
+AST_MATCHER(CXXCtorInitializer, isMemberInitializer) {
+ return Node.isMemberInitializer();
+}
+
+/// \brief Matches any argument of a call expression or a constructor call
+/// expression.
+///
+/// Given
+/// \code
+/// void x(int, int, int) { int y; x(1, y, 42); }
+/// \endcode
+/// callExpr(hasAnyArgument(declRefExpr()))
+/// matches x(1, y, 42)
+/// with hasAnyArgument(...)
+/// matching y
+///
+/// FIXME: Currently this will ignore parentheses and implicit casts on
+/// the argument before applying the inner matcher. We'll want to remove
+/// this to allow for greater control by the user once \c ignoreImplicit()
+/// has been implemented.
+AST_POLYMORPHIC_MATCHER_P(hasAnyArgument,
+ AST_POLYMORPHIC_SUPPORTED_TYPES(CallExpr,
+ CXXConstructExpr),
+ internal::Matcher<Expr>, InnerMatcher) {
+ for (const Expr *Arg : Node.arguments()) {
+ BoundNodesTreeBuilder Result(*Builder);
+ if (InnerMatcher.matches(*Arg->IgnoreParenImpCasts(), Finder, &Result)) {
+ *Builder = std::move(Result);
+ return true;
+ }
+ }
+ return false;
+}
+
+/// \brief Matches a constructor call expression which uses list initialization.
+AST_MATCHER(CXXConstructExpr, isListInitialization) {
+ return Node.isListInitialization();
+}
+
+/// \brief Matches the n'th parameter of a function declaration.
+///
+/// Given
+/// \code
+/// class X { void f(int x) {} };
+/// \endcode
+/// cxxMethodDecl(hasParameter(0, hasType(varDecl())))
+/// matches f(int x) {}
+/// with hasParameter(...)
+/// matching int x
+AST_MATCHER_P2(FunctionDecl, hasParameter,
+ unsigned, N, internal::Matcher<ParmVarDecl>,
+ InnerMatcher) {
+ return (N < Node.getNumParams() &&
+ InnerMatcher.matches(
+ *Node.getParamDecl(N), Finder, Builder));
+}
+
+/// \brief Matches any parameter of a function declaration.
+///
+/// Does not match the 'this' parameter of a method.
+///
+/// Given
+/// \code
+/// class X { void f(int x, int y, int z) {} };
+/// \endcode
+/// cxxMethodDecl(hasAnyParameter(hasName("y")))
+/// matches f(int x, int y, int z) {}
+/// with hasAnyParameter(...)
+/// matching int y
+AST_MATCHER_P(FunctionDecl, hasAnyParameter,
+ internal::Matcher<ParmVarDecl>, InnerMatcher) {
+ return matchesFirstInPointerRange(InnerMatcher, Node.param_begin(),
+ Node.param_end(), Finder, Builder);
+}
+
+/// \brief Matches \c FunctionDecls that have a specific parameter count.
+///
+/// Given
+/// \code
+/// void f(int i) {}
+/// void g(int i, int j) {}
+/// \endcode
+/// functionDecl(parameterCountIs(2))
+/// matches g(int i, int j) {}
+AST_MATCHER_P(FunctionDecl, parameterCountIs, unsigned, N) {
+ return Node.getNumParams() == N;
+}
+
+/// \brief Matches the return type of a function declaration.
+///
+/// Given:
+/// \code
+/// class X { int f() { return 1; } };
+/// \endcode
+/// cxxMethodDecl(returns(asString("int")))
+/// matches int f() { return 1; }
+AST_MATCHER_P(FunctionDecl, returns,
+ internal::Matcher<QualType>, InnerMatcher) {
+ return InnerMatcher.matches(Node.getReturnType(), Finder, Builder);
+}
+
+/// \brief Matches extern "C" function declarations.
+///
+/// Given:
+/// \code
+/// extern "C" void f() {}
+/// extern "C" { void g() {} }
+/// void h() {}
+/// \endcode
+/// functionDecl(isExternC())
+/// matches the declaration of f and g, but not the declaration h
+AST_MATCHER(FunctionDecl, isExternC) {
+ return Node.isExternC();
+}
+
+/// \brief Matches deleted function declarations.
+///
+/// Given:
+/// \code
+/// void Func();
+/// void DeletedFunc() = delete;
+/// \endcode
+/// functionDecl(isDeleted())
+/// matches the declaration of DeletedFunc, but not Func.
+AST_MATCHER(FunctionDecl, isDeleted) {
+ return Node.isDeleted();
+}
+
+/// \brief Matches functions that have a non-throwing exception specification.
+///
+/// Given:
+/// \code
+/// void f();
+/// void g() noexcept;
+/// void h() throw();
+/// void i() throw(int);
+/// void j() noexcept(false);
+/// \endcode
+/// functionDecl(isNoThrow())
+/// matches the declarations of g, and h, but not f, i or j.
+AST_MATCHER(FunctionDecl, isNoThrow) {
+ const auto *FnTy = Node.getType()->getAs<FunctionProtoType>();
+
+ // If the function does not have a prototype, then it is assumed to be a
+ // throwing function (as it would if the function did not have any exception
+ // specification).
+ if (!FnTy)
+ return false;
+
+ // Assume the best for any unresolved exception specification.
+ if (isUnresolvedExceptionSpec(FnTy->getExceptionSpecType()))
+ return true;
+
+ return FnTy->isNothrow(Node.getASTContext());
+}
+
+/// \brief Matches constexpr variable and function declarations.
+///
+/// Given:
+/// \code
+/// constexpr int foo = 42;
+/// constexpr int bar();
+/// \endcode
+/// varDecl(isConstexpr())
+/// matches the declaration of foo.
+/// functionDecl(isConstexpr())
+/// matches the declaration of bar.
+AST_POLYMORPHIC_MATCHER(isConstexpr,
+ AST_POLYMORPHIC_SUPPORTED_TYPES(VarDecl,
+ FunctionDecl)) {
+ return Node.isConstexpr();
+}
+
+/// \brief Matches the condition expression of an if statement, for loop,
+/// or conditional operator.
+///
+/// Example matches true (matcher = hasCondition(cxxBoolLiteral(equals(true))))
+/// \code
+/// if (true) {}
+/// \endcode
+AST_POLYMORPHIC_MATCHER_P(hasCondition,
+ AST_POLYMORPHIC_SUPPORTED_TYPES(IfStmt, ForStmt,
+ WhileStmt, DoStmt,
+ ConditionalOperator),
+ internal::Matcher<Expr>, InnerMatcher) {
+ const Expr *const Condition = Node.getCond();
+ return (Condition != nullptr &&
+ InnerMatcher.matches(*Condition, Finder, Builder));
+}
+
+/// \brief Matches the then-statement of an if statement.
+///
+/// Examples matches the if statement
+/// (matcher = ifStmt(hasThen(cxxBoolLiteral(equals(true)))))
+/// \code
+/// if (false) true; else false;
+/// \endcode
+AST_MATCHER_P(IfStmt, hasThen, internal::Matcher<Stmt>, InnerMatcher) {
+ const Stmt *const Then = Node.getThen();
+ return (Then != nullptr && InnerMatcher.matches(*Then, Finder, Builder));
+}
+
+/// \brief Matches the else-statement of an if statement.
+///
+/// Examples matches the if statement
+/// (matcher = ifStmt(hasElse(cxxBoolLiteral(equals(true)))))
+/// \code
+/// if (false) false; else true;
+/// \endcode
+AST_MATCHER_P(IfStmt, hasElse, internal::Matcher<Stmt>, InnerMatcher) {
+ const Stmt *const Else = Node.getElse();
+ return (Else != nullptr && InnerMatcher.matches(*Else, Finder, Builder));
+}
+
+/// \brief Matches if a node equals a previously bound node.
+///
+/// Matches a node if it equals the node previously bound to \p ID.
+///
+/// Given
+/// \code
+/// class X { int a; int b; };
+/// \endcode
+/// cxxRecordDecl(
+/// has(fieldDecl(hasName("a"), hasType(type().bind("t")))),
+/// has(fieldDecl(hasName("b"), hasType(type(equalsBoundNode("t"))))))
+/// matches the class \c X, as \c a and \c b have the same type.
+///
+/// Note that when multiple matches are involved via \c forEach* matchers,
+/// \c equalsBoundNodes acts as a filter.
+/// For example:
+/// compoundStmt(
+/// forEachDescendant(varDecl().bind("d")),
+/// forEachDescendant(declRefExpr(to(decl(equalsBoundNode("d"))))))
+/// will trigger a match for each combination of variable declaration
+/// and reference to that variable declaration within a compound statement.
+AST_POLYMORPHIC_MATCHER_P(equalsBoundNode,
+ AST_POLYMORPHIC_SUPPORTED_TYPES(Stmt, Decl, Type,
+ QualType),
+ std::string, ID) {
+ // FIXME: Figure out whether it makes sense to allow this
+ // on any other node types.
+ // For *Loc it probably does not make sense, as those seem
+ // unique. For NestedNameSepcifier it might make sense, as
+ // those also have pointer identity, but I'm not sure whether
+ // they're ever reused.
+ internal::NotEqualsBoundNodePredicate Predicate;
+ Predicate.ID = ID;
+ Predicate.Node = ast_type_traits::DynTypedNode::create(Node);
+ return Builder->removeBindings(Predicate);
+}
+
+/// \brief Matches the condition variable statement in an if statement.
+///
+/// Given
+/// \code
+/// if (A* a = GetAPointer()) {}
+/// \endcode
+/// hasConditionVariableStatement(...)
+/// matches 'A* a = GetAPointer()'.
+AST_MATCHER_P(IfStmt, hasConditionVariableStatement,
+ internal::Matcher<DeclStmt>, InnerMatcher) {
+ const DeclStmt* const DeclarationStatement =
+ Node.getConditionVariableDeclStmt();
+ return DeclarationStatement != nullptr &&
+ InnerMatcher.matches(*DeclarationStatement, Finder, Builder);
+}
+
+/// \brief Matches the index expression of an array subscript expression.
+///
+/// Given
+/// \code
+/// int i[5];
+/// void f() { i[1] = 42; }
+/// \endcode
+/// arraySubscriptExpression(hasIndex(integerLiteral()))
+/// matches \c i[1] with the \c integerLiteral() matching \c 1
+AST_MATCHER_P(ArraySubscriptExpr, hasIndex,
+ internal::Matcher<Expr>, InnerMatcher) {
+ if (const Expr* Expression = Node.getIdx())
+ return InnerMatcher.matches(*Expression, Finder, Builder);
+ return false;
+}
+
+/// \brief Matches the base expression of an array subscript expression.
+///
+/// Given
+/// \code
+/// int i[5];
+/// void f() { i[1] = 42; }
+/// \endcode
+/// arraySubscriptExpression(hasBase(implicitCastExpr(
+/// hasSourceExpression(declRefExpr()))))
+/// matches \c i[1] with the \c declRefExpr() matching \c i
+AST_MATCHER_P(ArraySubscriptExpr, hasBase,
+ internal::Matcher<Expr>, InnerMatcher) {
+ if (const Expr* Expression = Node.getBase())
+ return InnerMatcher.matches(*Expression, Finder, Builder);
+ return false;
+}
+
+/// \brief Matches a 'for', 'while', or 'do while' statement that has
+/// a given body.
+///
+/// Given
+/// \code
+/// for (;;) {}
+/// \endcode
+/// hasBody(compoundStmt())
+/// matches 'for (;;) {}'
+/// with compoundStmt()
+/// matching '{}'
+AST_POLYMORPHIC_MATCHER_P(hasBody,
+ AST_POLYMORPHIC_SUPPORTED_TYPES(DoStmt, ForStmt,
+ WhileStmt,
+ CXXForRangeStmt),
+ internal::Matcher<Stmt>, InnerMatcher) {
+ const Stmt *const Statement = Node.getBody();
+ return (Statement != nullptr &&
+ InnerMatcher.matches(*Statement, Finder, Builder));
+}
+
+/// \brief Matches compound statements where at least one substatement matches
+/// a given matcher.
+///
+/// Given
+/// \code
+/// { {}; 1+2; }
+/// \endcode
+/// hasAnySubstatement(compoundStmt())
+/// matches '{ {}; 1+2; }'
+/// with compoundStmt()
+/// matching '{}'
+AST_MATCHER_P(CompoundStmt, hasAnySubstatement,
+ internal::Matcher<Stmt>, InnerMatcher) {
+ return matchesFirstInPointerRange(InnerMatcher, Node.body_begin(),
+ Node.body_end(), Finder, Builder);
+}
+
+/// \brief Checks that a compound statement contains a specific number of
+/// child statements.
+///
+/// Example: Given
+/// \code
+/// { for (;;) {} }
+/// \endcode
+/// compoundStmt(statementCountIs(0)))
+/// matches '{}'
+/// but does not match the outer compound statement.
+AST_MATCHER_P(CompoundStmt, statementCountIs, unsigned, N) {
+ return Node.size() == N;
+}
+
+/// \brief Matches literals that are equal to the given value.
+///
+/// Example matches true (matcher = cxxBoolLiteral(equals(true)))
+/// \code
+/// true
+/// \endcode
+///
+/// Usable as: Matcher<CharacterLiteral>, Matcher<CXXBoolLiteral>,
+/// Matcher<FloatingLiteral>, Matcher<IntegerLiteral>
+template <typename ValueT>
+internal::PolymorphicMatcherWithParam1<internal::ValueEqualsMatcher, ValueT>
+equals(const ValueT &Value) {
+ return internal::PolymorphicMatcherWithParam1<
+ internal::ValueEqualsMatcher,
+ ValueT>(Value);
+}
+
+/// \brief Matches the operator Name of operator expressions (binary or
+/// unary).
+///
+/// Example matches a || b (matcher = binaryOperator(hasOperatorName("||")))
+/// \code
+/// !(a || b)
+/// \endcode
+AST_POLYMORPHIC_MATCHER_P(hasOperatorName,
+ AST_POLYMORPHIC_SUPPORTED_TYPES(BinaryOperator,
+ UnaryOperator),
+ std::string, Name) {
+ return Name == Node.getOpcodeStr(Node.getOpcode());
+}
+
+/// \brief Matches the left hand side of binary operator expressions.
+///
+/// Example matches a (matcher = binaryOperator(hasLHS()))
+/// \code
+/// a || b
+/// \endcode
+AST_POLYMORPHIC_MATCHER_P(hasLHS,
+ AST_POLYMORPHIC_SUPPORTED_TYPES(BinaryOperator,
+ ArraySubscriptExpr),
+ internal::Matcher<Expr>, InnerMatcher) {
+ const Expr *LeftHandSide = Node.getLHS();
+ return (LeftHandSide != nullptr &&
+ InnerMatcher.matches(*LeftHandSide, Finder, Builder));
+}
+
+/// \brief Matches the right hand side of binary operator expressions.
+///
+/// Example matches b (matcher = binaryOperator(hasRHS()))
+/// \code
+/// a || b
+/// \endcode
+AST_POLYMORPHIC_MATCHER_P(hasRHS,
+ AST_POLYMORPHIC_SUPPORTED_TYPES(BinaryOperator,
+ ArraySubscriptExpr),
+ internal::Matcher<Expr>, InnerMatcher) {
+ const Expr *RightHandSide = Node.getRHS();
+ return (RightHandSide != nullptr &&
+ InnerMatcher.matches(*RightHandSide, Finder, Builder));
+}
+
+/// \brief Matches if either the left hand side or the right hand side of a
+/// binary operator matches.
+inline internal::Matcher<BinaryOperator> hasEitherOperand(
+ const internal::Matcher<Expr> &InnerMatcher) {
+ return anyOf(hasLHS(InnerMatcher), hasRHS(InnerMatcher));
+}
+
+/// \brief Matches if the operand of a unary operator matches.
+///
+/// Example matches true (matcher = hasUnaryOperand(
+/// cxxBoolLiteral(equals(true))))
+/// \code
+/// !true
+/// \endcode
+AST_MATCHER_P(UnaryOperator, hasUnaryOperand,
+ internal::Matcher<Expr>, InnerMatcher) {
+ const Expr * const Operand = Node.getSubExpr();
+ return (Operand != nullptr &&
+ InnerMatcher.matches(*Operand, Finder, Builder));
+}
+
+/// \brief Matches if the cast's source expression matches the given matcher.
+///
+/// Example: matches "a string" (matcher =
+/// hasSourceExpression(cxxConstructExpr()))
+/// \code
+/// class URL { URL(string); };
+/// URL url = "a string";
+/// \endcode
+AST_MATCHER_P(CastExpr, hasSourceExpression,
+ internal::Matcher<Expr>, InnerMatcher) {
+ const Expr* const SubExpression = Node.getSubExpr();
+ return (SubExpression != nullptr &&
+ InnerMatcher.matches(*SubExpression, Finder, Builder));
+}
+
+/// \brief Matches casts whose destination type matches a given matcher.
+///
+/// (Note: Clang's AST refers to other conversions as "casts" too, and calls
+/// actual casts "explicit" casts.)
+AST_MATCHER_P(ExplicitCastExpr, hasDestinationType,
+ internal::Matcher<QualType>, InnerMatcher) {
+ const QualType NodeType = Node.getTypeAsWritten();
+ return InnerMatcher.matches(NodeType, Finder, Builder);
+}
+
+/// \brief Matches implicit casts whose destination type matches a given
+/// matcher.
+///
+/// FIXME: Unit test this matcher
+AST_MATCHER_P(ImplicitCastExpr, hasImplicitDestinationType,
+ internal::Matcher<QualType>, InnerMatcher) {
+ return InnerMatcher.matches(Node.getType(), Finder, Builder);
+}
+
+/// \brief Matches RecordDecl object that are spelled with "struct."
+///
+/// Example matches S, but not C or U.
+/// \code
+/// struct S {};
+/// class C {};
+/// union U {};
+/// \endcode
+AST_MATCHER(RecordDecl, isStruct) {
+ return Node.isStruct();
+}
+
+/// \brief Matches RecordDecl object that are spelled with "union."
+///
+/// Example matches U, but not C or S.
+/// \code
+/// struct S {};
+/// class C {};
+/// union U {};
+/// \endcode
+AST_MATCHER(RecordDecl, isUnion) {
+ return Node.isUnion();
+}
+
+/// \brief Matches RecordDecl object that are spelled with "class."
+///
+/// Example matches C, but not S or U.
+/// \code
+/// struct S {};
+/// class C {};
+/// union U {};
+/// \endcode
+AST_MATCHER(RecordDecl, isClass) {
+ return Node.isClass();
+}
+
+/// \brief Matches the true branch expression of a conditional operator.
+///
+/// Example matches a
+/// \code
+/// condition ? a : b
+/// \endcode
+AST_MATCHER_P(ConditionalOperator, hasTrueExpression,
+ internal::Matcher<Expr>, InnerMatcher) {
+ const Expr *Expression = Node.getTrueExpr();
+ return (Expression != nullptr &&
+ InnerMatcher.matches(*Expression, Finder, Builder));
+}
+
+/// \brief Matches the false branch expression of a conditional operator.
+///
+/// Example matches b
+/// \code
+/// condition ? a : b
+/// \endcode
+AST_MATCHER_P(ConditionalOperator, hasFalseExpression,
+ internal::Matcher<Expr>, InnerMatcher) {
+ const Expr *Expression = Node.getFalseExpr();
+ return (Expression != nullptr &&
+ InnerMatcher.matches(*Expression, Finder, Builder));
+}
+
+/// \brief Matches if a declaration has a body attached.
+///
+/// Example matches A, va, fa
+/// \code
+/// class A {};
+/// class B; // Doesn't match, as it has no body.
+/// int va;
+/// extern int vb; // Doesn't match, as it doesn't define the variable.
+/// void fa() {}
+/// void fb(); // Doesn't match, as it has no body.
+/// \endcode
+///
+/// Usable as: Matcher<TagDecl>, Matcher<VarDecl>, Matcher<FunctionDecl>
+AST_POLYMORPHIC_MATCHER(isDefinition,
+ AST_POLYMORPHIC_SUPPORTED_TYPES(TagDecl, VarDecl,
+ FunctionDecl)) {
+ return Node.isThisDeclarationADefinition();
+}
+
+/// \brief Matches if a function declaration is variadic.
+///
+/// Example matches f, but not g or h. The function i will not match, even when
+/// compiled in C mode.
+/// \code
+/// void f(...);
+/// void g(int);
+/// template <typename... Ts> void h(Ts...);
+/// void i();
+/// \endcode
+AST_MATCHER(FunctionDecl, isVariadic) {
+ return Node.isVariadic();
+}
+
+/// \brief Matches the class declaration that the given method declaration
+/// belongs to.
+///
+/// FIXME: Generalize this for other kinds of declarations.
+/// FIXME: What other kind of declarations would we need to generalize
+/// this to?
+///
+/// Example matches A() in the last line
+/// (matcher = cxxConstructExpr(hasDeclaration(cxxMethodDecl(
+/// ofClass(hasName("A"))))))
+/// \code
+/// class A {
+/// public:
+/// A();
+/// };
+/// A a = A();
+/// \endcode
+AST_MATCHER_P(CXXMethodDecl, ofClass,
+ internal::Matcher<CXXRecordDecl>, InnerMatcher) {
+ const CXXRecordDecl *Parent = Node.getParent();
+ return (Parent != nullptr &&
+ InnerMatcher.matches(*Parent, Finder, Builder));
+}
+
+/// \brief Matches if the given method declaration is virtual.
+///
+/// Given
+/// \code
+/// class A {
+/// public:
+/// virtual void x();
+/// };
+/// \endcode
+/// matches A::x
+AST_MATCHER(CXXMethodDecl, isVirtual) {
+ return Node.isVirtual();
+}
+
+/// \brief Matches if the given method or class declaration is final.
+///
+/// Given:
+/// \code
+/// class A final {};
+///
+/// struct B {
+/// virtual void f();
+/// };
+///
+/// struct C : B {
+/// void f() final;
+/// };
+/// \endcode
+/// matches A and C::f, but not B, C, or B::f
+AST_POLYMORPHIC_MATCHER(isFinal,
+ AST_POLYMORPHIC_SUPPORTED_TYPES(CXXRecordDecl,
+ CXXMethodDecl)) {
+ return Node.template hasAttr<FinalAttr>();
+}
+
+/// \brief Matches if the given method declaration is pure.
+///
+/// Given
+/// \code
+/// class A {
+/// public:
+/// virtual void x() = 0;
+/// };
+/// \endcode
+/// matches A::x
+AST_MATCHER(CXXMethodDecl, isPure) {
+ return Node.isPure();
+}
+
+/// \brief Matches if the given method declaration is const.
+///
+/// Given
+/// \code
+/// struct A {
+/// void foo() const;
+/// void bar();
+/// };
+/// \endcode
+///
+/// cxxMethodDecl(isConst()) matches A::foo() but not A::bar()
+AST_MATCHER(CXXMethodDecl, isConst) {
+ return Node.isConst();
+}
+
+/// \brief Matches if the given method declaration declares a copy assignment
+/// operator.
+///
+/// Given
+/// \code
+/// struct A {
+/// A &operator=(const A &);
+/// A &operator=(A &&);
+/// };
+/// \endcode
+///
+/// cxxMethodDecl(isCopyAssignmentOperator()) matches the first method but not
+/// the second one.
+AST_MATCHER(CXXMethodDecl, isCopyAssignmentOperator) {
+ return Node.isCopyAssignmentOperator();
+}
+
+/// \brief Matches if the given method declaration overrides another method.
+///
+/// Given
+/// \code
+/// class A {
+/// public:
+/// virtual void x();
+/// };
+/// class B : public A {
+/// public:
+/// virtual void x();
+/// };
+/// \endcode
+/// matches B::x
+AST_MATCHER(CXXMethodDecl, isOverride) {
+ return Node.size_overridden_methods() > 0 || Node.hasAttr<OverrideAttr>();
+}
+
+/// \brief Matches member expressions that are called with '->' as opposed
+/// to '.'.
+///
+/// Member calls on the implicit this pointer match as called with '->'.
+///
+/// Given
+/// \code
+/// class Y {
+/// void x() { this->x(); x(); Y y; y.x(); a; this->b; Y::b; }
+/// int a;
+/// static int b;
+/// };
+/// \endcode
+/// memberExpr(isArrow())
+/// matches this->x, x, y.x, a, this->b
+AST_MATCHER(MemberExpr, isArrow) {
+ return Node.isArrow();
+}
+
+/// \brief Matches QualType nodes that are of integer type.
+///
+/// Given
+/// \code
+/// void a(int);
+/// void b(long);
+/// void c(double);
+/// \endcode
+/// functionDecl(hasAnyParameter(hasType(isInteger())))
+/// matches "a(int)", "b(long)", but not "c(double)".
+AST_MATCHER(QualType, isInteger) {
+ return Node->isIntegerType();
+}
+
+/// \brief Matches QualType nodes that are of character type.
+///
+/// Given
+/// \code
+/// void a(char);
+/// void b(wchar_t);
+/// void c(double);
+/// \endcode
+/// functionDecl(hasAnyParameter(hasType(isAnyCharacter())))
+/// matches "a(char)", "b(wchar_t)", but not "c(double)".
+AST_MATCHER(QualType, isAnyCharacter) {
+ return Node->isAnyCharacterType();
+}
+
+/// \brief Matches QualType nodes that are const-qualified, i.e., that
+/// include "top-level" const.
+///
+/// Given
+/// \code
+/// void a(int);
+/// void b(int const);
+/// void c(const int);
+/// void d(const int*);
+/// void e(int const) {};
+/// \endcode
+/// functionDecl(hasAnyParameter(hasType(isConstQualified())))
+/// matches "void b(int const)", "void c(const int)" and
+/// "void e(int const) {}". It does not match d as there
+/// is no top-level const on the parameter type "const int *".
+AST_MATCHER(QualType, isConstQualified) {
+ return Node.isConstQualified();
+}
+
+/// \brief Matches QualType nodes that are volatile-qualified, i.e., that
+/// include "top-level" volatile.
+///
+/// Given
+/// \code
+/// void a(int);
+/// void b(int volatile);
+/// void c(volatile int);
+/// void d(volatile int*);
+/// void e(int volatile) {};
+/// \endcode
+/// functionDecl(hasAnyParameter(hasType(isVolatileQualified())))
+/// matches "void b(int volatile)", "void c(volatile int)" and
+/// "void e(int volatile) {}". It does not match d as there
+/// is no top-level volatile on the parameter type "volatile int *".
+AST_MATCHER(QualType, isVolatileQualified) {
+ return Node.isVolatileQualified();
+}
+
+/// \brief Matches QualType nodes that have local CV-qualifiers attached to
+/// the node, not hidden within a typedef.
+///
+/// Given
+/// \code
+/// typedef const int const_int;
+/// const_int i;
+/// int *const j;
+/// int *volatile k;
+/// int m;
+/// \endcode
+/// \c varDecl(hasType(hasLocalQualifiers())) matches only \c j and \c k.
+/// \c i is const-qualified but the qualifier is not local.
+AST_MATCHER(QualType, hasLocalQualifiers) {
+ return Node.hasLocalQualifiers();
+}
+
+/// \brief Matches a member expression where the member is matched by a
+/// given matcher.
+///
+/// Given
+/// \code
+/// struct { int first, second; } first, second;
+/// int i(second.first);
+/// int j(first.second);
+/// \endcode
+/// memberExpr(member(hasName("first")))
+/// matches second.first
+/// but not first.second (because the member name there is "second").
+AST_MATCHER_P(MemberExpr, member,
+ internal::Matcher<ValueDecl>, InnerMatcher) {
+ return InnerMatcher.matches(*Node.getMemberDecl(), Finder, Builder);
+}
+
+/// \brief Matches a member expression where the object expression is
+/// matched by a given matcher.
+///
+/// Given
+/// \code
+/// struct X { int m; };
+/// void f(X x) { x.m; m; }
+/// \endcode
+/// memberExpr(hasObjectExpression(hasType(cxxRecordDecl(hasName("X")))))))
+/// matches "x.m" and "m"
+/// with hasObjectExpression(...)
+/// matching "x" and the implicit object expression of "m" which has type X*.
+AST_MATCHER_P(MemberExpr, hasObjectExpression,
+ internal::Matcher<Expr>, InnerMatcher) {
+ return InnerMatcher.matches(*Node.getBase(), Finder, Builder);
+}
+
+/// \brief Matches any using shadow declaration.
+///
+/// Given
+/// \code
+/// namespace X { void b(); }
+/// using X::b;
+/// \endcode
+/// usingDecl(hasAnyUsingShadowDecl(hasName("b"))))
+/// matches \code using X::b \endcode
+AST_MATCHER_P(UsingDecl, hasAnyUsingShadowDecl,
+ internal::Matcher<UsingShadowDecl>, InnerMatcher) {
+ return matchesFirstInPointerRange(InnerMatcher, Node.shadow_begin(),
+ Node.shadow_end(), Finder, Builder);
+}
+
+/// \brief Matches a using shadow declaration where the target declaration is
+/// matched by the given matcher.
+///
+/// Given
+/// \code
+/// namespace X { int a; void b(); }
+/// using X::a;
+/// using X::b;
+/// \endcode
+/// usingDecl(hasAnyUsingShadowDecl(hasTargetDecl(functionDecl())))
+/// matches \code using X::b \endcode
+/// but not \code using X::a \endcode
+AST_MATCHER_P(UsingShadowDecl, hasTargetDecl,
+ internal::Matcher<NamedDecl>, InnerMatcher) {
+ return InnerMatcher.matches(*Node.getTargetDecl(), Finder, Builder);
+}
+
+/// \brief Matches template instantiations of function, class, or static
+/// member variable template instantiations.
+///
+/// Given
+/// \code
+/// template <typename T> class X {}; class A {}; X<A> x;
+/// \endcode
+/// or
+/// \code
+/// template <typename T> class X {}; class A {}; template class X<A>;
+/// \endcode
+/// cxxRecordDecl(hasName("::X"), isTemplateInstantiation())
+/// matches the template instantiation of X<A>.
+///
+/// But given
+/// \code
+/// template <typename T> class X {}; class A {};
+/// template <> class X<A> {}; X<A> x;
+/// \endcode
+/// cxxRecordDecl(hasName("::X"), isTemplateInstantiation())
+/// does not match, as X<A> is an explicit template specialization.
+///
+/// Usable as: Matcher<FunctionDecl>, Matcher<VarDecl>, Matcher<CXXRecordDecl>
+AST_POLYMORPHIC_MATCHER(isTemplateInstantiation,
+ AST_POLYMORPHIC_SUPPORTED_TYPES(FunctionDecl, VarDecl,
+ CXXRecordDecl)) {
+ return (Node.getTemplateSpecializationKind() == TSK_ImplicitInstantiation ||
+ Node.getTemplateSpecializationKind() ==
+ TSK_ExplicitInstantiationDefinition);
+}
+
+/// \brief Matches declarations that are template instantiations or are inside
+/// template instantiations.
+///
+/// Given
+/// \code
+/// template<typename T> void A(T t) { T i; }
+/// A(0);
+/// A(0U);
+/// \endcode
+/// functionDecl(isInstantiated())
+/// matches 'A(int) {...};' and 'A(unsigned) {...}'.
+AST_MATCHER_FUNCTION(internal::Matcher<Decl>, isInstantiated) {
+ auto IsInstantiation = decl(anyOf(cxxRecordDecl(isTemplateInstantiation()),
+ functionDecl(isTemplateInstantiation())));
+ return decl(anyOf(IsInstantiation, hasAncestor(IsInstantiation)));
+}
+
+/// \brief Matches statements inside of a template instantiation.
+///
+/// Given
+/// \code
+/// int j;
+/// template<typename T> void A(T t) { T i; j += 42;}
+/// A(0);
+/// A(0U);
+/// \endcode
+/// declStmt(isInTemplateInstantiation())
+/// matches 'int i;' and 'unsigned i'.
+/// unless(stmt(isInTemplateInstantiation()))
+/// will NOT match j += 42; as it's shared between the template definition and
+/// instantiation.
+AST_MATCHER_FUNCTION(internal::Matcher<Stmt>, isInTemplateInstantiation) {
+ return stmt(
+ hasAncestor(decl(anyOf(cxxRecordDecl(isTemplateInstantiation()),
+ functionDecl(isTemplateInstantiation())))));
+}
+
+/// \brief Matches explicit template specializations of function, class, or
+/// static member variable template instantiations.
+///
+/// Given
+/// \code
+/// template<typename T> void A(T t) { }
+/// template<> void A(int N) { }
+/// \endcode
+/// functionDecl(isExplicitTemplateSpecialization())
+/// matches the specialization A<int>().
+///
+/// Usable as: Matcher<FunctionDecl>, Matcher<VarDecl>, Matcher<CXXRecordDecl>
+AST_POLYMORPHIC_MATCHER(isExplicitTemplateSpecialization,
+ AST_POLYMORPHIC_SUPPORTED_TYPES(FunctionDecl, VarDecl,
+ CXXRecordDecl)) {
+ return (Node.getTemplateSpecializationKind() == TSK_ExplicitSpecialization);
+}
+
+/// \brief Matches \c TypeLocs for which the given inner
+/// QualType-matcher matches.
+AST_MATCHER_FUNCTION_P_OVERLOAD(internal::BindableMatcher<TypeLoc>, loc,
+ internal::Matcher<QualType>, InnerMatcher, 0) {
+ return internal::BindableMatcher<TypeLoc>(
+ new internal::TypeLocTypeMatcher(InnerMatcher));
+}
+
+/// \brief Matches type \c bool.
+///
+/// Given
+/// \code
+/// struct S { bool func(); };
+/// \endcode
+/// functionDecl(returns(booleanType()))
+/// matches "bool func();"
+AST_MATCHER(Type, booleanType) {
+ return Node.isBooleanType();
+}
+
+/// \brief Matches type \c void.
+///
+/// Given
+/// \code
+/// struct S { void func(); };
+/// \endcode
+/// functionDecl(returns(voidType()))
+/// matches "void func();"
+AST_MATCHER(Type, voidType) {
+ return Node.isVoidType();
+}
+
+/// \brief Matches builtin Types.
+///
+/// Given
+/// \code
+/// struct A {};
+/// A a;
+/// int b;
+/// float c;
+/// bool d;
+/// \endcode
+/// builtinType()
+/// matches "int b", "float c" and "bool d"
+AST_TYPE_MATCHER(BuiltinType, builtinType);
+
+/// \brief Matches all kinds of arrays.
+///
+/// Given
+/// \code
+/// int a[] = { 2, 3 };
+/// int b[4];
+/// void f() { int c[a[0]]; }
+/// \endcode
+/// arrayType()
+/// matches "int a[]", "int b[4]" and "int c[a[0]]";
+AST_TYPE_MATCHER(ArrayType, arrayType);
+
+/// \brief Matches C99 complex types.
+///
+/// Given
+/// \code
+/// _Complex float f;
+/// \endcode
+/// complexType()
+/// matches "_Complex float f"
+AST_TYPE_MATCHER(ComplexType, complexType);
+
+/// \brief Matches arrays and C99 complex types that have a specific element
+/// type.
+///
+/// Given
+/// \code
+/// struct A {};
+/// A a[7];
+/// int b[7];
+/// \endcode
+/// arrayType(hasElementType(builtinType()))
+/// matches "int b[7]"
+///
+/// Usable as: Matcher<ArrayType>, Matcher<ComplexType>
+AST_TYPELOC_TRAVERSE_MATCHER(hasElementType, getElement,
+ AST_POLYMORPHIC_SUPPORTED_TYPES(ArrayType,
+ ComplexType));
+
+/// \brief Matches C arrays with a specified constant size.
+///
+/// Given
+/// \code
+/// void() {
+/// int a[2];
+/// int b[] = { 2, 3 };
+/// int c[b[0]];
+/// }
+/// \endcode
+/// constantArrayType()
+/// matches "int a[2]"
+AST_TYPE_MATCHER(ConstantArrayType, constantArrayType);
+
+/// \brief Matches \c ConstantArrayType nodes that have the specified size.
+///
+/// Given
+/// \code
+/// int a[42];
+/// int b[2 * 21];
+/// int c[41], d[43];
+/// \endcode
+/// constantArrayType(hasSize(42))
+/// matches "int a[42]" and "int b[2 * 21]"
+AST_MATCHER_P(ConstantArrayType, hasSize, unsigned, N) {
+ return Node.getSize() == N;
+}
+
+/// \brief Matches C++ arrays whose size is a value-dependent expression.
+///
+/// Given
+/// \code
+/// template<typename T, int Size>
+/// class array {
+/// T data[Size];
+/// };
+/// \endcode
+/// dependentSizedArrayType
+/// matches "T data[Size]"
+AST_TYPE_MATCHER(DependentSizedArrayType, dependentSizedArrayType);
+
+/// \brief Matches C arrays with unspecified size.
+///
+/// Given
+/// \code
+/// int a[] = { 2, 3 };
+/// int b[42];
+/// void f(int c[]) { int d[a[0]]; };
+/// \endcode
+/// incompleteArrayType()
+/// matches "int a[]" and "int c[]"
+AST_TYPE_MATCHER(IncompleteArrayType, incompleteArrayType);
+
+/// \brief Matches C arrays with a specified size that is not an
+/// integer-constant-expression.
+///
+/// Given
+/// \code
+/// void f() {
+/// int a[] = { 2, 3 }
+/// int b[42];
+/// int c[a[0]];
+/// }
+/// \endcode
+/// variableArrayType()
+/// matches "int c[a[0]]"
+AST_TYPE_MATCHER(VariableArrayType, variableArrayType);
+
+/// \brief Matches \c VariableArrayType nodes that have a specific size
+/// expression.
+///
+/// Given
+/// \code
+/// void f(int b) {
+/// int a[b];
+/// }
+/// \endcode
+/// variableArrayType(hasSizeExpr(ignoringImpCasts(declRefExpr(to(
+/// varDecl(hasName("b")))))))
+/// matches "int a[b]"
+AST_MATCHER_P(VariableArrayType, hasSizeExpr,
+ internal::Matcher<Expr>, InnerMatcher) {
+ return InnerMatcher.matches(*Node.getSizeExpr(), Finder, Builder);
+}
+
+/// \brief Matches atomic types.
+///
+/// Given
+/// \code
+/// _Atomic(int) i;
+/// \endcode
+/// atomicType()
+/// matches "_Atomic(int) i"
+AST_TYPE_MATCHER(AtomicType, atomicType);
+
+/// \brief Matches atomic types with a specific value type.
+///
+/// Given
+/// \code
+/// _Atomic(int) i;
+/// _Atomic(float) f;
+/// \endcode
+/// atomicType(hasValueType(isInteger()))
+/// matches "_Atomic(int) i"
+///
+/// Usable as: Matcher<AtomicType>
+AST_TYPELOC_TRAVERSE_MATCHER(hasValueType, getValue,
+ AST_POLYMORPHIC_SUPPORTED_TYPES(AtomicType));
+
+/// \brief Matches types nodes representing C++11 auto types.
+///
+/// Given:
+/// \code
+/// auto n = 4;
+/// int v[] = { 2, 3 }
+/// for (auto i : v) { }
+/// \endcode
+/// autoType()
+/// matches "auto n" and "auto i"
+AST_TYPE_MATCHER(AutoType, autoType);
+
+/// \brief Matches \c AutoType nodes where the deduced type is a specific type.
+///
+/// Note: There is no \c TypeLoc for the deduced type and thus no
+/// \c getDeducedLoc() matcher.
+///
+/// Given
+/// \code
+/// auto a = 1;
+/// auto b = 2.0;
+/// \endcode
+/// autoType(hasDeducedType(isInteger()))
+/// matches "auto a"
+///
+/// Usable as: Matcher<AutoType>
+AST_TYPE_TRAVERSE_MATCHER(hasDeducedType, getDeducedType,
+ AST_POLYMORPHIC_SUPPORTED_TYPES(AutoType));
+
+/// \brief Matches \c FunctionType nodes.
+///
+/// Given
+/// \code
+/// int (*f)(int);
+/// void g();
+/// \endcode
+/// functionType()
+/// matches "int (*f)(int)" and the type of "g".
+AST_TYPE_MATCHER(FunctionType, functionType);
+
+/// \brief Matches \c ParenType nodes.
+///
+/// Given
+/// \code
+/// int (*ptr_to_array)[4];
+/// int *array_of_ptrs[4];
+/// \endcode
+///
+/// \c varDecl(hasType(pointsTo(parenType()))) matches \c ptr_to_array but not
+/// \c array_of_ptrs.
+AST_TYPE_MATCHER(ParenType, parenType);
+
+/// \brief Matches \c ParenType nodes where the inner type is a specific type.
+///
+/// Given
+/// \code
+/// int (*ptr_to_array)[4];
+/// int (*ptr_to_func)(int);
+/// \endcode
+///
+/// \c varDecl(hasType(pointsTo(parenType(innerType(functionType()))))) matches
+/// \c ptr_to_func but not \c ptr_to_array.
+///
+/// Usable as: Matcher<ParenType>
+AST_TYPE_TRAVERSE_MATCHER(innerType, getInnerType,
+ AST_POLYMORPHIC_SUPPORTED_TYPES(ParenType));
+
+/// \brief Matches block pointer types, i.e. types syntactically represented as
+/// "void (^)(int)".
+///
+/// The \c pointee is always required to be a \c FunctionType.
+AST_TYPE_MATCHER(BlockPointerType, blockPointerType);
+
+/// \brief Matches member pointer types.
+/// Given
+/// \code
+/// struct A { int i; }
+/// A::* ptr = A::i;
+/// \endcode
+/// memberPointerType()
+/// matches "A::* ptr"
+AST_TYPE_MATCHER(MemberPointerType, memberPointerType);
+
+/// \brief Matches pointer types, but does not match Objective-C object pointer
+/// types.
+///
+/// Given
+/// \code
+/// int *a;
+/// int &b = *a;
+/// int c = 5;
+///
+/// @interface Foo
+/// @end
+/// Foo *f;
+/// \endcode
+/// pointerType()
+/// matches "int *a", but does not match "Foo *f".
+AST_TYPE_MATCHER(PointerType, pointerType);
+
+/// \brief Matches an Objective-C object pointer type, which is different from
+/// a pointer type, despite being syntactically similar.
+///
+/// Given
+/// \code
+/// int *a;
+///
+/// @interface Foo
+/// @end
+/// Foo *f;
+/// \endcode
+/// pointerType()
+/// matches "Foo *f", but does not match "int *a".
+AST_TYPE_MATCHER(ObjCObjectPointerType, objcObjectPointerType);
+
+/// \brief Matches both lvalue and rvalue reference types.
+///
+/// Given
+/// \code
+/// int *a;
+/// int &b = *a;
+/// int &&c = 1;
+/// auto &d = b;
+/// auto &&e = c;
+/// auto &&f = 2;
+/// int g = 5;
+/// \endcode
+///
+/// \c referenceType() matches the types of \c b, \c c, \c d, \c e, and \c f.
+AST_TYPE_MATCHER(ReferenceType, referenceType);
+
+/// \brief Matches lvalue reference types.
+///
+/// Given:
+/// \code
+/// int *a;
+/// int &b = *a;
+/// int &&c = 1;
+/// auto &d = b;
+/// auto &&e = c;
+/// auto &&f = 2;
+/// int g = 5;
+/// \endcode
+///
+/// \c lValueReferenceType() matches the types of \c b, \c d, and \c e. \c e is
+/// matched since the type is deduced as int& by reference collapsing rules.
+AST_TYPE_MATCHER(LValueReferenceType, lValueReferenceType);
+
+/// \brief Matches rvalue reference types.
+///
+/// Given:
+/// \code
+/// int *a;
+/// int &b = *a;
+/// int &&c = 1;
+/// auto &d = b;
+/// auto &&e = c;
+/// auto &&f = 2;
+/// int g = 5;
+/// \endcode
+///
+/// \c rValueReferenceType() matches the types of \c c and \c f. \c e is not
+/// matched as it is deduced to int& by reference collapsing rules.
+AST_TYPE_MATCHER(RValueReferenceType, rValueReferenceType);
+
+/// \brief Narrows PointerType (and similar) matchers to those where the
+/// \c pointee matches a given matcher.
+///
+/// Given
+/// \code
+/// int *a;
+/// int const *b;
+/// float const *f;
+/// \endcode
+/// pointerType(pointee(isConstQualified(), isInteger()))
+/// matches "int const *b"
+///
+/// Usable as: Matcher<BlockPointerType>, Matcher<MemberPointerType>,
+/// Matcher<PointerType>, Matcher<ReferenceType>
+AST_TYPELOC_TRAVERSE_MATCHER(pointee, getPointee,
+ AST_POLYMORPHIC_SUPPORTED_TYPES(BlockPointerType,
+ MemberPointerType,
+ PointerType,
+ ReferenceType));
+
+/// \brief Matches typedef types.
+///
+/// Given
+/// \code
+/// typedef int X;
+/// \endcode
+/// typedefType()
+/// matches "typedef int X"
+AST_TYPE_MATCHER(TypedefType, typedefType);
+
+/// \brief Matches template specialization types.
+///
+/// Given
+/// \code
+/// template <typename T>
+/// class C { };
+///
+/// template class C<int>; // A
+/// C<char> var; // B
+/// \endcode
+///
+/// \c templateSpecializationType() matches the type of the explicit
+/// instantiation in \c A and the type of the variable declaration in \c B.
+AST_TYPE_MATCHER(TemplateSpecializationType, templateSpecializationType);
+
+/// \brief Matches types nodes representing unary type transformations.
+///
+/// Given:
+/// \code
+/// typedef __underlying_type(T) type;
+/// \endcode
+/// unaryTransformType()
+/// matches "__underlying_type(T)"
+AST_TYPE_MATCHER(UnaryTransformType, unaryTransformType);
+
+/// \brief Matches record types (e.g. structs, classes).
+///
+/// Given
+/// \code
+/// class C {};
+/// struct S {};
+///
+/// C c;
+/// S s;
+/// \endcode
+///
+/// \c recordType() matches the type of the variable declarations of both \c c
+/// and \c s.
+AST_TYPE_MATCHER(RecordType, recordType);
+
+/// \brief Matches types specified with an elaborated type keyword or with a
+/// qualified name.
+///
+/// Given
+/// \code
+/// namespace N {
+/// namespace M {
+/// class D {};
+/// }
+/// }
+/// class C {};
+///
+/// class C c;
+/// N::M::D d;
+/// \endcode
+///
+/// \c elaboratedType() matches the type of the variable declarations of both
+/// \c c and \c d.
+AST_TYPE_MATCHER(ElaboratedType, elaboratedType);
+
+/// \brief Matches ElaboratedTypes whose qualifier, a NestedNameSpecifier,
+/// matches \c InnerMatcher if the qualifier exists.
+///
+/// Given
+/// \code
+/// namespace N {
+/// namespace M {
+/// class D {};
+/// }
+/// }
+/// N::M::D d;
+/// \endcode
+///
+/// \c elaboratedType(hasQualifier(hasPrefix(specifiesNamespace(hasName("N"))))
+/// matches the type of the variable declaration of \c d.
+AST_MATCHER_P(ElaboratedType, hasQualifier,
+ internal::Matcher<NestedNameSpecifier>, InnerMatcher) {
+ if (const NestedNameSpecifier *Qualifier = Node.getQualifier())
+ return InnerMatcher.matches(*Qualifier, Finder, Builder);
+
+ return false;
+}
+
+/// \brief Matches ElaboratedTypes whose named type matches \c InnerMatcher.
+///
+/// Given
+/// \code
+/// namespace N {
+/// namespace M {
+/// class D {};
+/// }
+/// }
+/// N::M::D d;
+/// \endcode
+///
+/// \c elaboratedType(namesType(recordType(
+/// hasDeclaration(namedDecl(hasName("D")))))) matches the type of the variable
+/// declaration of \c d.
+AST_MATCHER_P(ElaboratedType, namesType, internal::Matcher<QualType>,
+ InnerMatcher) {
+ return InnerMatcher.matches(Node.getNamedType(), Finder, Builder);
+}
+
+/// \brief Matches types that represent the result of substituting a type for a
+/// template type parameter.
+///
+/// Given
+/// \code
+/// template <typename T>
+/// void F(T t) {
+/// int i = 1 + t;
+/// }
+/// \endcode
+///
+/// \c substTemplateTypeParmType() matches the type of 't' but not '1'
+AST_TYPE_MATCHER(SubstTemplateTypeParmType, substTemplateTypeParmType);
+
+/// \brief Matches template type parameter types.
+///
+/// Example matches T, but not int.
+/// (matcher = templateTypeParmType())
+/// \code
+/// template <typename T> void f(int i);
+/// \endcode
+AST_TYPE_MATCHER(TemplateTypeParmType, templateTypeParmType);
+
+/// \brief Matches injected class name types.
+///
+/// Example matches S s, but not S<T> s.
+/// (matcher = parmVarDecl(hasType(injectedClassNameType())))
+/// \code
+/// template <typename T> struct S {
+/// void f(S s);
+/// void g(S<T> s);
+/// };
+/// \endcode
+AST_TYPE_MATCHER(InjectedClassNameType, injectedClassNameType);
+
+/// \brief Matches decayed type
+/// Example matches i[] in declaration of f.
+/// (matcher = valueDecl(hasType(decayedType(hasDecayedType(pointerType())))))
+/// Example matches i[1].
+/// (matcher = expr(hasType(decayedType(hasDecayedType(pointerType())))))
+/// \code
+/// void f(int i[]) {
+/// i[1] = 0;
+/// }
+/// \endcode
+AST_TYPE_MATCHER(DecayedType, decayedType);
+
+/// \brief Matches the decayed type, whos decayed type matches \c InnerMatcher
+AST_MATCHER_P(DecayedType, hasDecayedType, internal::Matcher<QualType>,
+ InnerType) {
+ return InnerType.matches(Node.getDecayedType(), Finder, Builder);
+}
+
+/// \brief Matches declarations whose declaration context, interpreted as a
+/// Decl, matches \c InnerMatcher.
+///
+/// Given
+/// \code
+/// namespace N {
+/// namespace M {
+/// class D {};
+/// }
+/// }
+/// \endcode
+///
+/// \c cxxRcordDecl(hasDeclContext(namedDecl(hasName("M")))) matches the
+/// declaration of \c class \c D.
+AST_MATCHER_P(Decl, hasDeclContext, internal::Matcher<Decl>, InnerMatcher) {
+ const DeclContext *DC = Node.getDeclContext();
+ if (!DC) return false;
+ return InnerMatcher.matches(*Decl::castFromDeclContext(DC), Finder, Builder);
+}
+
+/// \brief Matches nested name specifiers.
+///
+/// Given
+/// \code
+/// namespace ns {
+/// struct A { static void f(); };
+/// void A::f() {}
+/// void g() { A::f(); }
+/// }
+/// ns::A a;
+/// \endcode
+/// nestedNameSpecifier()
+/// matches "ns::" and both "A::"
+const internal::VariadicAllOfMatcher<NestedNameSpecifier> nestedNameSpecifier;
+
+/// \brief Same as \c nestedNameSpecifier but matches \c NestedNameSpecifierLoc.
+const internal::VariadicAllOfMatcher<
+ NestedNameSpecifierLoc> nestedNameSpecifierLoc;
+
+/// \brief Matches \c NestedNameSpecifierLocs for which the given inner
+/// NestedNameSpecifier-matcher matches.
+AST_MATCHER_FUNCTION_P_OVERLOAD(
+ internal::BindableMatcher<NestedNameSpecifierLoc>, loc,
+ internal::Matcher<NestedNameSpecifier>, InnerMatcher, 1) {
+ return internal::BindableMatcher<NestedNameSpecifierLoc>(
+ new internal::LocMatcher<NestedNameSpecifierLoc, NestedNameSpecifier>(
+ InnerMatcher));
+}
+
+/// \brief Matches nested name specifiers that specify a type matching the
+/// given \c QualType matcher without qualifiers.
+///
+/// Given
+/// \code
+/// struct A { struct B { struct C {}; }; };
+/// A::B::C c;
+/// \endcode
+/// nestedNameSpecifier(specifiesType(
+/// hasDeclaration(cxxRecordDecl(hasName("A")))
+/// ))
+/// matches "A::"
+AST_MATCHER_P(NestedNameSpecifier, specifiesType,
+ internal::Matcher<QualType>, InnerMatcher) {
+ if (!Node.getAsType())
+ return false;
+ return InnerMatcher.matches(QualType(Node.getAsType(), 0), Finder, Builder);
+}
+
+/// \brief Matches nested name specifier locs that specify a type matching the
+/// given \c TypeLoc.
+///
+/// Given
+/// \code
+/// struct A { struct B { struct C {}; }; };
+/// A::B::C c;
+/// \endcode
+/// nestedNameSpecifierLoc(specifiesTypeLoc(loc(type(
+/// hasDeclaration(cxxRecordDecl(hasName("A")))))))
+/// matches "A::"
+AST_MATCHER_P(NestedNameSpecifierLoc, specifiesTypeLoc,
+ internal::Matcher<TypeLoc>, InnerMatcher) {
+ return Node && InnerMatcher.matches(Node.getTypeLoc(), Finder, Builder);
+}
+
+/// \brief Matches on the prefix of a \c NestedNameSpecifier.
+///
+/// Given
+/// \code
+/// struct A { struct B { struct C {}; }; };
+/// A::B::C c;
+/// \endcode
+/// nestedNameSpecifier(hasPrefix(specifiesType(asString("struct A")))) and
+/// matches "A::"
+AST_MATCHER_P_OVERLOAD(NestedNameSpecifier, hasPrefix,
+ internal::Matcher<NestedNameSpecifier>, InnerMatcher,
+ 0) {
+ const NestedNameSpecifier *NextNode = Node.getPrefix();
+ if (!NextNode)
+ return false;
+ return InnerMatcher.matches(*NextNode, Finder, Builder);
+}
+
+/// \brief Matches on the prefix of a \c NestedNameSpecifierLoc.
+///
+/// Given
+/// \code
+/// struct A { struct B { struct C {}; }; };
+/// A::B::C c;
+/// \endcode
+/// nestedNameSpecifierLoc(hasPrefix(loc(specifiesType(asString("struct A")))))
+/// matches "A::"
+AST_MATCHER_P_OVERLOAD(NestedNameSpecifierLoc, hasPrefix,
+ internal::Matcher<NestedNameSpecifierLoc>, InnerMatcher,
+ 1) {
+ NestedNameSpecifierLoc NextNode = Node.getPrefix();
+ if (!NextNode)
+ return false;
+ return InnerMatcher.matches(NextNode, Finder, Builder);
+}
+
+/// \brief Matches nested name specifiers that specify a namespace matching the
+/// given namespace matcher.
+///
+/// Given
+/// \code
+/// namespace ns { struct A {}; }
+/// ns::A a;
+/// \endcode
+/// nestedNameSpecifier(specifiesNamespace(hasName("ns")))
+/// matches "ns::"
+AST_MATCHER_P(NestedNameSpecifier, specifiesNamespace,
+ internal::Matcher<NamespaceDecl>, InnerMatcher) {
+ if (!Node.getAsNamespace())
+ return false;
+ return InnerMatcher.matches(*Node.getAsNamespace(), Finder, Builder);
+}
+
+/// \brief Overloads for the \c equalsNode matcher.
+/// FIXME: Implement for other node types.
+/// @{
+
+/// \brief Matches if a node equals another node.
+///
+/// \c Decl has pointer identity in the AST.
+AST_MATCHER_P_OVERLOAD(Decl, equalsNode, const Decl*, Other, 0) {
+ return &Node == Other;
+}
+/// \brief Matches if a node equals another node.
+///
+/// \c Stmt has pointer identity in the AST.
+AST_MATCHER_P_OVERLOAD(Stmt, equalsNode, const Stmt*, Other, 1) {
+ return &Node == Other;
+}
+/// \brief Matches if a node equals another node.
+///
+/// \c Type has pointer identity in the AST.
+AST_MATCHER_P_OVERLOAD(Type, equalsNode, const Type*, Other, 2) {
+ return &Node == Other;
+}
+
+/// @}
+
+/// \brief Matches each case or default statement belonging to the given switch
+/// statement. This matcher may produce multiple matches.
+///
+/// Given
+/// \code
+/// switch (1) { case 1: case 2: default: switch (2) { case 3: case 4: ; } }
+/// \endcode
+/// switchStmt(forEachSwitchCase(caseStmt().bind("c"))).bind("s")
+/// matches four times, with "c" binding each of "case 1:", "case 2:",
+/// "case 3:" and "case 4:", and "s" respectively binding "switch (1)",
+/// "switch (1)", "switch (2)" and "switch (2)".
+AST_MATCHER_P(SwitchStmt, forEachSwitchCase, internal::Matcher<SwitchCase>,
+ InnerMatcher) {
+ BoundNodesTreeBuilder Result;
+ // FIXME: getSwitchCaseList() does not necessarily guarantee a stable
+ // iteration order. We should use the more general iterating matchers once
+ // they are capable of expressing this matcher (for example, it should ignore
+ // case statements belonging to nested switch statements).
+ bool Matched = false;
+ for (const SwitchCase *SC = Node.getSwitchCaseList(); SC;
+ SC = SC->getNextSwitchCase()) {
+ BoundNodesTreeBuilder CaseBuilder(*Builder);
+ bool CaseMatched = InnerMatcher.matches(*SC, Finder, &CaseBuilder);
+ if (CaseMatched) {
+ Matched = true;
+ Result.addMatch(CaseBuilder);
+ }
+ }
+ *Builder = std::move(Result);
+ return Matched;
+}
+
+/// \brief Matches each constructor initializer in a constructor definition.
+///
+/// Given
+/// \code
+/// class A { A() : i(42), j(42) {} int i; int j; };
+/// \endcode
+/// cxxConstructorDecl(forEachConstructorInitializer(
+/// forField(decl().bind("x"))
+/// ))
+/// will trigger two matches, binding for 'i' and 'j' respectively.
+AST_MATCHER_P(CXXConstructorDecl, forEachConstructorInitializer,
+ internal::Matcher<CXXCtorInitializer>, InnerMatcher) {
+ BoundNodesTreeBuilder Result;
+ bool Matched = false;
+ for (const auto *I : Node.inits()) {
+ BoundNodesTreeBuilder InitBuilder(*Builder);
+ if (InnerMatcher.matches(*I, Finder, &InitBuilder)) {
+ Matched = true;
+ Result.addMatch(InitBuilder);
+ }
+ }
+ *Builder = std::move(Result);
+ return Matched;
+}
+
+/// \brief Matches constructor declarations that are copy constructors.
+///
+/// Given
+/// \code
+/// struct S {
+/// S(); // #1
+/// S(const S &); // #2
+/// S(S &&); // #3
+/// };
+/// \endcode
+/// cxxConstructorDecl(isCopyConstructor()) will match #2, but not #1 or #3.
+AST_MATCHER(CXXConstructorDecl, isCopyConstructor) {
+ return Node.isCopyConstructor();
+}
+
+/// \brief Matches constructor declarations that are move constructors.
+///
+/// Given
+/// \code
+/// struct S {
+/// S(); // #1
+/// S(const S &); // #2
+/// S(S &&); // #3
+/// };
+/// \endcode
+/// cxxConstructorDecl(isMoveConstructor()) will match #3, but not #1 or #2.
+AST_MATCHER(CXXConstructorDecl, isMoveConstructor) {
+ return Node.isMoveConstructor();
+}
+
+/// \brief Matches constructor declarations that are default constructors.
+///
+/// Given
+/// \code
+/// struct S {
+/// S(); // #1
+/// S(const S &); // #2
+/// S(S &&); // #3
+/// };
+/// \endcode
+/// cxxConstructorDecl(isDefaultConstructor()) will match #1, but not #2 or #3.
+AST_MATCHER(CXXConstructorDecl, isDefaultConstructor) {
+ return Node.isDefaultConstructor();
+}
+
+/// \brief Matches constructor and conversion declarations that are marked with
+/// the explicit keyword.
+///
+/// Given
+/// \code
+/// struct S {
+/// S(int); // #1
+/// explicit S(double); // #2
+/// operator int(); // #3
+/// explicit operator bool(); // #4
+/// };
+/// \endcode
+/// cxxConstructorDecl(isExplicit()) will match #2, but not #1.
+/// cxxConversionDecl(isExplicit()) will match #4, but not #3.
+AST_POLYMORPHIC_MATCHER(isExplicit,
+ AST_POLYMORPHIC_SUPPORTED_TYPES(CXXConstructorDecl,
+ CXXConversionDecl)) {
+ return Node.isExplicit();
+}
+
+/// \brief Matches function and namespace declarations that are marked with
+/// the inline keyword.
+///
+/// Given
+/// \code
+/// inline void f();
+/// void g();
+/// namespace n {
+/// inline namespace m {}
+/// }
+/// \endcode
+/// functionDecl(isInline()) will match ::f().
+/// namespaceDecl(isInline()) will match n::m.
+AST_POLYMORPHIC_MATCHER(isInline,
+ AST_POLYMORPHIC_SUPPORTED_TYPES(NamespaceDecl,
+ FunctionDecl)) {
+ // This is required because the spelling of the function used to determine
+ // whether inline is specified or not differs between the polymorphic types.
+ if (const auto *FD = dyn_cast<FunctionDecl>(&Node))
+ return FD->isInlineSpecified();
+ else if (const auto *NSD = dyn_cast<NamespaceDecl>(&Node))
+ return NSD->isInline();
+ llvm_unreachable("Not a valid polymorphic type");
+}
+
+/// \brief Matches anonymous namespace declarations.
+///
+/// Given
+/// \code
+/// namespace n {
+/// namespace {} // #1
+/// }
+/// \endcode
+/// namespaceDecl(isAnonymous()) will match #1 but not ::n.
+AST_MATCHER(NamespaceDecl, isAnonymous) {
+ return Node.isAnonymousNamespace();
+}
+
+/// \brief If the given case statement does not use the GNU case range
+/// extension, matches the constant given in the statement.
+///
+/// Given
+/// \code
+/// switch (1) { case 1: case 1+1: case 3 ... 4: ; }
+/// \endcode
+/// caseStmt(hasCaseConstant(integerLiteral()))
+/// matches "case 1:"
+AST_MATCHER_P(CaseStmt, hasCaseConstant, internal::Matcher<Expr>,
+ InnerMatcher) {
+ if (Node.getRHS())
+ return false;
+
+ return InnerMatcher.matches(*Node.getLHS(), Finder, Builder);
+}
+
+/// \brief Matches declaration that has a given attribute.
+///
+/// Given
+/// \code
+/// __attribute__((device)) void f() { ... }
+/// \endcode
+/// decl(hasAttr(clang::attr::CUDADevice)) matches the function declaration of
+/// f. If the matcher is use from clang-query, attr::Kind parameter should be
+/// passed as a quoted string. e.g., hasAttr("attr::CUDADevice").
+AST_MATCHER_P(Decl, hasAttr, attr::Kind, AttrKind) {
+ for (const auto *Attr : Node.attrs()) {
+ if (Attr->getKind() == AttrKind)
+ return true;
+ }
+ return false;
+}
+
+/// \brief Matches CUDA kernel call expression.
+///
+/// Example matches,
+/// \code
+/// kernel<<<i,j>>>();
+/// \endcode
+const internal::VariadicDynCastAllOfMatcher<
+ Stmt,
+ CUDAKernelCallExpr> cudaKernelCallExpr;
+
+} // end namespace ast_matchers
+} // end namespace clang
+
+#endif
diff --git a/contrib/llvm/tools/clang/include/clang/ASTMatchers/ASTMatchersInternal.h b/contrib/llvm/tools/clang/include/clang/ASTMatchers/ASTMatchersInternal.h
new file mode 100644
index 0000000..d499091
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/ASTMatchers/ASTMatchersInternal.h
@@ -0,0 +1,1591 @@
+//===--- ASTMatchersInternal.h - Structural query framework -----*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// Implements the base layer of the matcher framework.
+//
+// Matchers are methods that return a Matcher<T> which provides a method
+// Matches(...) which is a predicate on an AST node. The Matches method's
+// parameters define the context of the match, which allows matchers to recurse
+// or store the current node as bound to a specific string, so that it can be
+// retrieved later.
+//
+// In general, matchers have two parts:
+// 1. A function Matcher<T> MatcherName(<arguments>) which returns a Matcher<T>
+// based on the arguments and optionally on template type deduction based
+// on the arguments. Matcher<T>s form an implicit reverse hierarchy
+// to clang's AST class hierarchy, meaning that you can use a Matcher<Base>
+// everywhere a Matcher<Derived> is required.
+// 2. An implementation of a class derived from MatcherInterface<T>.
+//
+// The matcher functions are defined in ASTMatchers.h. To make it possible
+// to implement both the matcher function and the implementation of the matcher
+// interface in one place, ASTMatcherMacros.h defines macros that allow
+// implementing a matcher in a single place.
+//
+// This file contains the base classes needed to construct the actual matchers.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_ASTMATCHERS_ASTMATCHERSINTERNAL_H
+#define LLVM_CLANG_ASTMATCHERS_ASTMATCHERSINTERNAL_H
+
+#include "clang/AST/ASTTypeTraits.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/AST/ExprObjC.h"
+#include "clang/AST/Stmt.h"
+#include "clang/AST/StmtCXX.h"
+#include "clang/AST/StmtObjC.h"
+#include "clang/AST/Type.h"
+#include "llvm/ADT/Optional.h"
+#include "llvm/ADT/VariadicFunction.h"
+#include "llvm/Support/ManagedStatic.h"
+#include <map>
+#include <string>
+#include <vector>
+
+namespace clang {
+namespace ast_matchers {
+
+class BoundNodes;
+
+namespace internal {
+
+/// \brief Internal version of BoundNodes. Holds all the bound nodes.
+class BoundNodesMap {
+public:
+ /// \brief Adds \c Node to the map with key \c ID.
+ ///
+ /// The node's base type should be in NodeBaseType or it will be unaccessible.
+ void addNode(StringRef ID, const ast_type_traits::DynTypedNode& DynNode) {
+ NodeMap[ID] = DynNode;
+ }
+
+ /// \brief Returns the AST node bound to \c ID.
+ ///
+ /// Returns NULL if there was no node bound to \c ID or if there is a node but
+ /// it cannot be converted to the specified type.
+ template <typename T>
+ const T *getNodeAs(StringRef ID) const {
+ IDToNodeMap::const_iterator It = NodeMap.find(ID);
+ if (It == NodeMap.end()) {
+ return nullptr;
+ }
+ return It->second.get<T>();
+ }
+
+ ast_type_traits::DynTypedNode getNode(StringRef ID) const {
+ IDToNodeMap::const_iterator It = NodeMap.find(ID);
+ if (It == NodeMap.end()) {
+ return ast_type_traits::DynTypedNode();
+ }
+ return It->second;
+ }
+
+ /// \brief Imposes an order on BoundNodesMaps.
+ bool operator<(const BoundNodesMap &Other) const {
+ return NodeMap < Other.NodeMap;
+ }
+
+ /// \brief A map from IDs to the bound nodes.
+ ///
+ /// Note that we're using std::map here, as for memoization:
+ /// - we need a comparison operator
+ /// - we need an assignment operator
+ typedef std::map<std::string, ast_type_traits::DynTypedNode> IDToNodeMap;
+
+ const IDToNodeMap &getMap() const {
+ return NodeMap;
+ }
+
+ /// \brief Returns \c true if this \c BoundNodesMap can be compared, i.e. all
+ /// stored nodes have memoization data.
+ bool isComparable() const {
+ for (const auto &IDAndNode : NodeMap) {
+ if (!IDAndNode.second.getMemoizationData())
+ return false;
+ }
+ return true;
+ }
+
+private:
+ IDToNodeMap NodeMap;
+};
+
+/// \brief Creates BoundNodesTree objects.
+///
+/// The tree builder is used during the matching process to insert the bound
+/// nodes from the Id matcher.
+class BoundNodesTreeBuilder {
+public:
+ /// \brief A visitor interface to visit all BoundNodes results for a
+ /// BoundNodesTree.
+ class Visitor {
+ public:
+ virtual ~Visitor() {}
+
+ /// \brief Called multiple times during a single call to VisitMatches(...).
+ ///
+ /// 'BoundNodesView' contains the bound nodes for a single match.
+ virtual void visitMatch(const BoundNodes& BoundNodesView) = 0;
+ };
+
+ /// \brief Add a binding from an id to a node.
+ void setBinding(StringRef Id, const ast_type_traits::DynTypedNode &DynNode) {
+ if (Bindings.empty())
+ Bindings.emplace_back();
+ for (BoundNodesMap &Binding : Bindings)
+ Binding.addNode(Id, DynNode);
+ }
+
+ /// \brief Adds a branch in the tree.
+ void addMatch(const BoundNodesTreeBuilder &Bindings);
+
+ /// \brief Visits all matches that this BoundNodesTree represents.
+ ///
+ /// The ownership of 'ResultVisitor' remains at the caller.
+ void visitMatches(Visitor* ResultVisitor);
+
+ template <typename ExcludePredicate>
+ bool removeBindings(const ExcludePredicate &Predicate) {
+ Bindings.erase(std::remove_if(Bindings.begin(), Bindings.end(), Predicate),
+ Bindings.end());
+ return !Bindings.empty();
+ }
+
+ /// \brief Imposes an order on BoundNodesTreeBuilders.
+ bool operator<(const BoundNodesTreeBuilder &Other) const {
+ return Bindings < Other.Bindings;
+ }
+
+ /// \brief Returns \c true if this \c BoundNodesTreeBuilder can be compared,
+ /// i.e. all stored node maps have memoization data.
+ bool isComparable() const {
+ for (const BoundNodesMap &NodesMap : Bindings) {
+ if (!NodesMap.isComparable())
+ return false;
+ }
+ return true;
+ }
+
+private:
+ SmallVector<BoundNodesMap, 16> Bindings;
+};
+
+class ASTMatchFinder;
+
+/// \brief Generic interface for all matchers.
+///
+/// Used by the implementation of Matcher<T> and DynTypedMatcher.
+/// In general, implement MatcherInterface<T> or SingleNodeMatcherInterface<T>
+/// instead.
+class DynMatcherInterface
+ : public llvm::ThreadSafeRefCountedBase<DynMatcherInterface> {
+public:
+ virtual ~DynMatcherInterface() {}
+
+ /// \brief Returns true if \p DynNode can be matched.
+ ///
+ /// May bind \p DynNode to an ID via \p Builder, or recurse into
+ /// the AST via \p Finder.
+ virtual bool dynMatches(const ast_type_traits::DynTypedNode &DynNode,
+ ASTMatchFinder *Finder,
+ BoundNodesTreeBuilder *Builder) const = 0;
+};
+
+/// \brief Generic interface for matchers on an AST node of type T.
+///
+/// Implement this if your matcher may need to inspect the children or
+/// descendants of the node or bind matched nodes to names. If you are
+/// writing a simple matcher that only inspects properties of the
+/// current node and doesn't care about its children or descendants,
+/// implement SingleNodeMatcherInterface instead.
+template <typename T>
+class MatcherInterface : public DynMatcherInterface {
+public:
+ /// \brief Returns true if 'Node' can be matched.
+ ///
+ /// May bind 'Node' to an ID via 'Builder', or recurse into
+ /// the AST via 'Finder'.
+ virtual bool matches(const T &Node,
+ ASTMatchFinder *Finder,
+ BoundNodesTreeBuilder *Builder) const = 0;
+
+ bool dynMatches(const ast_type_traits::DynTypedNode &DynNode,
+ ASTMatchFinder *Finder,
+ BoundNodesTreeBuilder *Builder) const override {
+ return matches(DynNode.getUnchecked<T>(), Finder, Builder);
+ }
+};
+
+/// \brief Interface for matchers that only evaluate properties on a single
+/// node.
+template <typename T>
+class SingleNodeMatcherInterface : public MatcherInterface<T> {
+public:
+ /// \brief Returns true if the matcher matches the provided node.
+ ///
+ /// A subclass must implement this instead of Matches().
+ virtual bool matchesNode(const T &Node) const = 0;
+
+private:
+ /// Implements MatcherInterface::Matches.
+ bool matches(const T &Node,
+ ASTMatchFinder * /* Finder */,
+ BoundNodesTreeBuilder * /* Builder */) const override {
+ return matchesNode(Node);
+ }
+};
+
+template <typename> class Matcher;
+
+/// \brief Matcher that works on a \c DynTypedNode.
+///
+/// It is constructed from a \c Matcher<T> object and redirects most calls to
+/// underlying matcher.
+/// It checks whether the \c DynTypedNode is convertible into the type of the
+/// underlying matcher and then do the actual match on the actual node, or
+/// return false if it is not convertible.
+class DynTypedMatcher {
+public:
+ /// \brief Takes ownership of the provided implementation pointer.
+ template <typename T>
+ DynTypedMatcher(MatcherInterface<T> *Implementation)
+ : AllowBind(false),
+ SupportedKind(ast_type_traits::ASTNodeKind::getFromNodeKind<T>()),
+ RestrictKind(SupportedKind), Implementation(Implementation) {}
+
+ /// \brief Construct from a variadic function.
+ enum VariadicOperator {
+ /// \brief Matches nodes for which all provided matchers match.
+ VO_AllOf,
+ /// \brief Matches nodes for which at least one of the provided matchers
+ /// matches.
+ VO_AnyOf,
+ /// \brief Matches nodes for which at least one of the provided matchers
+ /// matches, but doesn't stop at the first match.
+ VO_EachOf,
+ /// \brief Matches nodes that do not match the provided matcher.
+ ///
+ /// Uses the variadic matcher interface, but fails if
+ /// InnerMatchers.size() != 1.
+ VO_UnaryNot
+ };
+ static DynTypedMatcher
+ constructVariadic(VariadicOperator Op,
+ ast_type_traits::ASTNodeKind SupportedKind,
+ std::vector<DynTypedMatcher> InnerMatchers);
+
+ /// \brief Get a "true" matcher for \p NodeKind.
+ ///
+ /// It only checks that the node is of the right kind.
+ static DynTypedMatcher trueMatcher(ast_type_traits::ASTNodeKind NodeKind);
+
+ void setAllowBind(bool AB) { AllowBind = AB; }
+
+ /// \brief Check whether this matcher could ever match a node of kind \p Kind.
+ /// \return \c false if this matcher will never match such a node. Otherwise,
+ /// return \c true.
+ bool canMatchNodesOfKind(ast_type_traits::ASTNodeKind Kind) const;
+
+ /// \brief Return a matcher that points to the same implementation, but
+ /// restricts the node types for \p Kind.
+ DynTypedMatcher dynCastTo(const ast_type_traits::ASTNodeKind Kind) const;
+
+ /// \brief Returns true if the matcher matches the given \c DynNode.
+ bool matches(const ast_type_traits::DynTypedNode &DynNode,
+ ASTMatchFinder *Finder, BoundNodesTreeBuilder *Builder) const;
+
+ /// \brief Same as matches(), but skips the kind check.
+ ///
+ /// It is faster, but the caller must ensure the node is valid for the
+ /// kind of this matcher.
+ bool matchesNoKindCheck(const ast_type_traits::DynTypedNode &DynNode,
+ ASTMatchFinder *Finder,
+ BoundNodesTreeBuilder *Builder) const;
+
+ /// \brief Bind the specified \p ID to the matcher.
+ /// \return A new matcher with the \p ID bound to it if this matcher supports
+ /// binding. Otherwise, returns an empty \c Optional<>.
+ llvm::Optional<DynTypedMatcher> tryBind(StringRef ID) const;
+
+ /// \brief Returns a unique \p ID for the matcher.
+ ///
+ /// Casting a Matcher<T> to Matcher<U> creates a matcher that has the
+ /// same \c Implementation pointer, but different \c RestrictKind. We need to
+ /// include both in the ID to make it unique.
+ ///
+ /// \c MatcherIDType supports operator< and provides strict weak ordering.
+ typedef std::pair<ast_type_traits::ASTNodeKind, uint64_t> MatcherIDType;
+ MatcherIDType getID() const {
+ /// FIXME: Document the requirements this imposes on matcher
+ /// implementations (no new() implementation_ during a Matches()).
+ return std::make_pair(RestrictKind,
+ reinterpret_cast<uint64_t>(Implementation.get()));
+ }
+
+ /// \brief Returns the type this matcher works on.
+ ///
+ /// \c matches() will always return false unless the node passed is of this
+ /// or a derived type.
+ ast_type_traits::ASTNodeKind getSupportedKind() const {
+ return SupportedKind;
+ }
+
+ /// \brief Returns \c true if the passed \c DynTypedMatcher can be converted
+ /// to a \c Matcher<T>.
+ ///
+ /// This method verifies that the underlying matcher in \c Other can process
+ /// nodes of types T.
+ template <typename T> bool canConvertTo() const {
+ return canConvertTo(ast_type_traits::ASTNodeKind::getFromNodeKind<T>());
+ }
+ bool canConvertTo(ast_type_traits::ASTNodeKind To) const;
+
+ /// \brief Construct a \c Matcher<T> interface around the dynamic matcher.
+ ///
+ /// This method asserts that \c canConvertTo() is \c true. Callers
+ /// should call \c canConvertTo() first to make sure that \c this is
+ /// compatible with T.
+ template <typename T> Matcher<T> convertTo() const {
+ assert(canConvertTo<T>());
+ return unconditionalConvertTo<T>();
+ }
+
+ /// \brief Same as \c convertTo(), but does not check that the underlying
+ /// matcher can handle a value of T.
+ ///
+ /// If it is not compatible, then this matcher will never match anything.
+ template <typename T> Matcher<T> unconditionalConvertTo() const;
+
+private:
+ DynTypedMatcher(ast_type_traits::ASTNodeKind SupportedKind,
+ ast_type_traits::ASTNodeKind RestrictKind,
+ IntrusiveRefCntPtr<DynMatcherInterface> Implementation)
+ : AllowBind(false),
+ SupportedKind(SupportedKind),
+ RestrictKind(RestrictKind),
+ Implementation(std::move(Implementation)) {}
+
+ bool AllowBind;
+ ast_type_traits::ASTNodeKind SupportedKind;
+ /// \brief A potentially stricter node kind.
+ ///
+ /// It allows to perform implicit and dynamic cast of matchers without
+ /// needing to change \c Implementation.
+ ast_type_traits::ASTNodeKind RestrictKind;
+ IntrusiveRefCntPtr<DynMatcherInterface> Implementation;
+};
+
+/// \brief Wrapper base class for a wrapping matcher.
+///
+/// This is just a container for a DynTypedMatcher that can be used as a base
+/// class for another matcher.
+template <typename T>
+class WrapperMatcherInterface : public MatcherInterface<T> {
+protected:
+ explicit WrapperMatcherInterface(DynTypedMatcher &&InnerMatcher)
+ : InnerMatcher(std::move(InnerMatcher)) {}
+
+ const DynTypedMatcher InnerMatcher;
+};
+
+/// \brief Wrapper of a MatcherInterface<T> *that allows copying.
+///
+/// A Matcher<Base> can be used anywhere a Matcher<Derived> is
+/// required. This establishes an is-a relationship which is reverse
+/// to the AST hierarchy. In other words, Matcher<T> is contravariant
+/// with respect to T. The relationship is built via a type conversion
+/// operator rather than a type hierarchy to be able to templatize the
+/// type hierarchy instead of spelling it out.
+template <typename T>
+class Matcher {
+public:
+ /// \brief Takes ownership of the provided implementation pointer.
+ explicit Matcher(MatcherInterface<T> *Implementation)
+ : Implementation(Implementation) {}
+
+ /// \brief Implicitly converts \c Other to a Matcher<T>.
+ ///
+ /// Requires \c T to be derived from \c From.
+ template <typename From>
+ Matcher(const Matcher<From> &Other,
+ typename std::enable_if<std::is_base_of<From, T>::value &&
+ !std::is_same<From, T>::value>::type * = 0)
+ : Implementation(restrictMatcher(Other.Implementation)) {
+ assert(Implementation.getSupportedKind().isSame(
+ ast_type_traits::ASTNodeKind::getFromNodeKind<T>()));
+ }
+
+ /// \brief Implicitly converts \c Matcher<Type> to \c Matcher<QualType>.
+ ///
+ /// The resulting matcher is not strict, i.e. ignores qualifiers.
+ template <typename TypeT>
+ Matcher(const Matcher<TypeT> &Other,
+ typename std::enable_if<
+ std::is_same<T, QualType>::value &&
+ std::is_same<TypeT, Type>::value>::type* = 0)
+ : Implementation(new TypeToQualType<TypeT>(Other)) {}
+
+ /// \brief Convert \c this into a \c Matcher<T> by applying dyn_cast<> to the
+ /// argument.
+ /// \c To must be a base class of \c T.
+ template <typename To>
+ Matcher<To> dynCastTo() const {
+ static_assert(std::is_base_of<To, T>::value, "Invalid dynCast call.");
+ return Matcher<To>(Implementation);
+ }
+
+ /// \brief Forwards the call to the underlying MatcherInterface<T> pointer.
+ bool matches(const T &Node,
+ ASTMatchFinder *Finder,
+ BoundNodesTreeBuilder *Builder) const {
+ return Implementation.matches(ast_type_traits::DynTypedNode::create(Node),
+ Finder, Builder);
+ }
+
+ /// \brief Returns an ID that uniquely identifies the matcher.
+ DynTypedMatcher::MatcherIDType getID() const {
+ return Implementation.getID();
+ }
+
+ /// \brief Extract the dynamic matcher.
+ ///
+ /// The returned matcher keeps the same restrictions as \c this and remembers
+ /// that it is meant to support nodes of type \c T.
+ operator DynTypedMatcher() const { return Implementation; }
+
+ /// \brief Allows the conversion of a \c Matcher<Type> to a \c
+ /// Matcher<QualType>.
+ ///
+ /// Depending on the constructor argument, the matcher is either strict, i.e.
+ /// does only matches in the absence of qualifiers, or not, i.e. simply
+ /// ignores any qualifiers.
+ template <typename TypeT>
+ class TypeToQualType : public WrapperMatcherInterface<QualType> {
+ public:
+ TypeToQualType(const Matcher<TypeT> &InnerMatcher)
+ : TypeToQualType::WrapperMatcherInterface(InnerMatcher) {}
+
+ bool matches(const QualType &Node, ASTMatchFinder *Finder,
+ BoundNodesTreeBuilder *Builder) const override {
+ if (Node.isNull())
+ return false;
+ return this->InnerMatcher.matches(
+ ast_type_traits::DynTypedNode::create(*Node), Finder, Builder);
+ }
+ };
+
+private:
+ // For Matcher<T> <=> Matcher<U> conversions.
+ template <typename U> friend class Matcher;
+ // For DynTypedMatcher::unconditionalConvertTo<T>.
+ friend class DynTypedMatcher;
+
+ static DynTypedMatcher restrictMatcher(const DynTypedMatcher &Other) {
+ return Other.dynCastTo(ast_type_traits::ASTNodeKind::getFromNodeKind<T>());
+ }
+
+ explicit Matcher(const DynTypedMatcher &Implementation)
+ : Implementation(restrictMatcher(Implementation)) {
+ assert(this->Implementation.getSupportedKind()
+ .isSame(ast_type_traits::ASTNodeKind::getFromNodeKind<T>()));
+ }
+
+ DynTypedMatcher Implementation;
+}; // class Matcher
+
+/// \brief A convenient helper for creating a Matcher<T> without specifying
+/// the template type argument.
+template <typename T>
+inline Matcher<T> makeMatcher(MatcherInterface<T> *Implementation) {
+ return Matcher<T>(Implementation);
+}
+
+/// \brief Specialization of the conversion functions for QualType.
+///
+/// This specialization provides the Matcher<Type>->Matcher<QualType>
+/// conversion that the static API does.
+template <>
+inline Matcher<QualType> DynTypedMatcher::convertTo<QualType>() const {
+ assert(canConvertTo<QualType>());
+ const ast_type_traits::ASTNodeKind SourceKind = getSupportedKind();
+ if (SourceKind.isSame(
+ ast_type_traits::ASTNodeKind::getFromNodeKind<Type>())) {
+ // We support implicit conversion from Matcher<Type> to Matcher<QualType>
+ return unconditionalConvertTo<Type>();
+ }
+ return unconditionalConvertTo<QualType>();
+}
+
+/// \brief Finds the first node in a range that matches the given matcher.
+template <typename MatcherT, typename IteratorT>
+bool matchesFirstInRange(const MatcherT &Matcher, IteratorT Start,
+ IteratorT End, ASTMatchFinder *Finder,
+ BoundNodesTreeBuilder *Builder) {
+ for (IteratorT I = Start; I != End; ++I) {
+ BoundNodesTreeBuilder Result(*Builder);
+ if (Matcher.matches(*I, Finder, &Result)) {
+ *Builder = std::move(Result);
+ return true;
+ }
+ }
+ return false;
+}
+
+/// \brief Finds the first node in a pointer range that matches the given
+/// matcher.
+template <typename MatcherT, typename IteratorT>
+bool matchesFirstInPointerRange(const MatcherT &Matcher, IteratorT Start,
+ IteratorT End, ASTMatchFinder *Finder,
+ BoundNodesTreeBuilder *Builder) {
+ for (IteratorT I = Start; I != End; ++I) {
+ BoundNodesTreeBuilder Result(*Builder);
+ if (Matcher.matches(**I, Finder, &Result)) {
+ *Builder = std::move(Result);
+ return true;
+ }
+ }
+ return false;
+}
+
+// Metafunction to determine if type T has a member called
+// getDecl.
+#if defined(_MSC_VER) && (_MSC_VER < 1900) && !defined(__clang__)
+// For old versions of MSVC, we use a weird nonstandard __if_exists
+// statement, since before MSVC2015, it was not standards-conformant
+// enough to compile the usual code below.
+template <typename T> struct has_getDecl {
+ __if_exists(T::getDecl) {
+ enum { value = 1 };
+ }
+ __if_not_exists(T::getDecl) {
+ enum { value = 0 };
+ }
+};
+#else
+// There is a default template inheriting from "false_type". Then, a
+// partial specialization inherits from "true_type". However, this
+// specialization will only exist when the call to getDecl() isn't an
+// error -- it vanishes by SFINAE when the member doesn't exist.
+template <typename> struct type_sink_to_void { typedef void type; };
+template <typename T, typename = void> struct has_getDecl : std::false_type {};
+template <typename T>
+struct has_getDecl<
+ T, typename type_sink_to_void<decltype(std::declval<T>().getDecl())>::type>
+ : std::true_type {};
+#endif
+
+/// \brief Matches overloaded operators with a specific name.
+///
+/// The type argument ArgT is not used by this matcher but is used by
+/// PolymorphicMatcherWithParam1 and should be StringRef.
+template <typename T, typename ArgT>
+class HasOverloadedOperatorNameMatcher : public SingleNodeMatcherInterface<T> {
+ static_assert(std::is_same<T, CXXOperatorCallExpr>::value ||
+ std::is_base_of<FunctionDecl, T>::value,
+ "unsupported class for matcher");
+ static_assert(std::is_same<ArgT, StringRef>::value,
+ "argument type must be StringRef");
+
+public:
+ explicit HasOverloadedOperatorNameMatcher(const StringRef Name)
+ : SingleNodeMatcherInterface<T>(), Name(Name) {}
+
+ bool matchesNode(const T &Node) const override {
+ return matchesSpecialized(Node);
+ }
+
+private:
+
+ /// \brief CXXOperatorCallExpr exist only for calls to overloaded operators
+ /// so this function returns true if the call is to an operator of the given
+ /// name.
+ bool matchesSpecialized(const CXXOperatorCallExpr &Node) const {
+ return getOperatorSpelling(Node.getOperator()) == Name;
+ }
+
+ /// \brief Returns true only if CXXMethodDecl represents an overloaded
+ /// operator and has the given operator name.
+ bool matchesSpecialized(const FunctionDecl &Node) const {
+ return Node.isOverloadedOperator() &&
+ getOperatorSpelling(Node.getOverloadedOperator()) == Name;
+ }
+
+ std::string Name;
+};
+
+/// \brief Matches named declarations with a specific name.
+///
+/// See \c hasName() in ASTMatchers.h for details.
+class HasNameMatcher : public SingleNodeMatcherInterface<NamedDecl> {
+ public:
+ explicit HasNameMatcher(StringRef Name);
+
+ bool matchesNode(const NamedDecl &Node) const override;
+
+ private:
+ /// \brief Unqualified match routine.
+ ///
+ /// It is much faster than the full match, but it only works for unqualified
+ /// matches.
+ bool matchesNodeUnqualified(const NamedDecl &Node) const;
+
+ /// \brief Full match routine
+ ///
+ /// It generates the fully qualified name of the declaration (which is
+ /// expensive) before trying to match.
+ /// It is slower but simple and works on all cases.
+ bool matchesNodeFull(const NamedDecl &Node) const;
+
+ const bool UseUnqualifiedMatch;
+ const std::string Name;
+};
+
+/// \brief Matches declarations for QualType and CallExpr.
+///
+/// Type argument DeclMatcherT is required by PolymorphicMatcherWithParam1 but
+/// not actually used.
+template <typename T, typename DeclMatcherT>
+class HasDeclarationMatcher : public WrapperMatcherInterface<T> {
+ static_assert(std::is_same<DeclMatcherT, Matcher<Decl>>::value,
+ "instantiated with wrong types");
+
+public:
+ explicit HasDeclarationMatcher(const Matcher<Decl> &InnerMatcher)
+ : HasDeclarationMatcher::WrapperMatcherInterface(InnerMatcher) {}
+
+ bool matches(const T &Node, ASTMatchFinder *Finder,
+ BoundNodesTreeBuilder *Builder) const override {
+ return matchesSpecialized(Node, Finder, Builder);
+ }
+
+private:
+ /// \brief If getDecl exists as a member of U, returns whether the inner
+ /// matcher matches Node.getDecl().
+ template <typename U>
+ bool matchesSpecialized(
+ const U &Node, ASTMatchFinder *Finder, BoundNodesTreeBuilder *Builder,
+ typename std::enable_if<has_getDecl<U>::value, int>::type = 0) const {
+ return matchesDecl(Node.getDecl(), Finder, Builder);
+ }
+
+ /// \brief Extracts the TagDecl of a QualType and returns whether the inner
+ /// matcher matches on it.
+ bool matchesSpecialized(const QualType &Node, ASTMatchFinder *Finder,
+ BoundNodesTreeBuilder *Builder) const {
+ if (Node.isNull())
+ return false;
+
+ if (auto *TD = Node->getAsTagDecl())
+ return matchesDecl(TD, Finder, Builder);
+ else if (auto *TT = Node->getAs<TypedefType>())
+ return matchesDecl(TT->getDecl(), Finder, Builder);
+ // Do not use getAs<TemplateTypeParmType> instead of the direct dyn_cast.
+ // Calling getAs will return the canonical type, but that type does not
+ // store a TemplateTypeParmDecl. We *need* the uncanonical type, if it is
+ // available, and using dyn_cast ensures that.
+ else if (auto *TTP = dyn_cast<TemplateTypeParmType>(Node.getTypePtr()))
+ return matchesDecl(TTP->getDecl(), Finder, Builder);
+ else if (auto *OCIT = Node->getAs<ObjCInterfaceType>())
+ return matchesDecl(OCIT->getDecl(), Finder, Builder);
+ else if (auto *UUT = Node->getAs<UnresolvedUsingType>())
+ return matchesDecl(UUT->getDecl(), Finder, Builder);
+ else if (auto *ICNT = Node->getAs<InjectedClassNameType>())
+ return matchesDecl(ICNT->getDecl(), Finder, Builder);
+ return false;
+ }
+
+ /// \brief Gets the TemplateDecl from a TemplateSpecializationType
+ /// and returns whether the inner matches on it.
+ bool matchesSpecialized(const TemplateSpecializationType &Node,
+ ASTMatchFinder *Finder,
+ BoundNodesTreeBuilder *Builder) const {
+ return matchesDecl(Node.getTemplateName().getAsTemplateDecl(),
+ Finder, Builder);
+ }
+
+ /// \brief Extracts the Decl of the callee of a CallExpr and returns whether
+ /// the inner matcher matches on it.
+ bool matchesSpecialized(const CallExpr &Node, ASTMatchFinder *Finder,
+ BoundNodesTreeBuilder *Builder) const {
+ return matchesDecl(Node.getCalleeDecl(), Finder, Builder);
+ }
+
+ /// \brief Extracts the Decl of the constructor call and returns whether the
+ /// inner matcher matches on it.
+ bool matchesSpecialized(const CXXConstructExpr &Node,
+ ASTMatchFinder *Finder,
+ BoundNodesTreeBuilder *Builder) const {
+ return matchesDecl(Node.getConstructor(), Finder, Builder);
+ }
+
+ /// \brief Extracts the \c ValueDecl a \c MemberExpr refers to and returns
+ /// whether the inner matcher matches on it.
+ bool matchesSpecialized(const MemberExpr &Node,
+ ASTMatchFinder *Finder,
+ BoundNodesTreeBuilder *Builder) const {
+ return matchesDecl(Node.getMemberDecl(), Finder, Builder);
+ }
+
+ /// \brief Returns whether the inner matcher \c Node. Returns false if \c Node
+ /// is \c NULL.
+ bool matchesDecl(const Decl *Node, ASTMatchFinder *Finder,
+ BoundNodesTreeBuilder *Builder) const {
+ return Node != nullptr &&
+ this->InnerMatcher.matches(
+ ast_type_traits::DynTypedNode::create(*Node), Finder, Builder);
+ }
+};
+
+/// \brief IsBaseType<T>::value is true if T is a "base" type in the AST
+/// node class hierarchies.
+template <typename T>
+struct IsBaseType {
+ static const bool value =
+ std::is_same<T, Decl>::value ||
+ std::is_same<T, Stmt>::value ||
+ std::is_same<T, QualType>::value ||
+ std::is_same<T, Type>::value ||
+ std::is_same<T, TypeLoc>::value ||
+ std::is_same<T, NestedNameSpecifier>::value ||
+ std::is_same<T, NestedNameSpecifierLoc>::value ||
+ std::is_same<T, CXXCtorInitializer>::value;
+};
+template <typename T>
+const bool IsBaseType<T>::value;
+
+/// \brief Interface that allows matchers to traverse the AST.
+/// FIXME: Find a better name.
+///
+/// This provides three entry methods for each base node type in the AST:
+/// - \c matchesChildOf:
+/// Matches a matcher on every child node of the given node. Returns true
+/// if at least one child node could be matched.
+/// - \c matchesDescendantOf:
+/// Matches a matcher on all descendant nodes of the given node. Returns true
+/// if at least one descendant matched.
+/// - \c matchesAncestorOf:
+/// Matches a matcher on all ancestors of the given node. Returns true if
+/// at least one ancestor matched.
+///
+/// FIXME: Currently we only allow Stmt and Decl nodes to start a traversal.
+/// In the future, we want to implement this for all nodes for which it makes
+/// sense. In the case of matchesAncestorOf, we'll want to implement it for
+/// all nodes, as all nodes have ancestors.
+class ASTMatchFinder {
+public:
+ /// \brief Defines how we descend a level in the AST when we pass
+ /// through expressions.
+ enum TraversalKind {
+ /// Will traverse any child nodes.
+ TK_AsIs,
+ /// Will not traverse implicit casts and parentheses.
+ TK_IgnoreImplicitCastsAndParentheses
+ };
+
+ /// \brief Defines how bindings are processed on recursive matches.
+ enum BindKind {
+ /// Stop at the first match and only bind the first match.
+ BK_First,
+ /// Create results for all combinations of bindings that match.
+ BK_All
+ };
+
+ /// \brief Defines which ancestors are considered for a match.
+ enum AncestorMatchMode {
+ /// All ancestors.
+ AMM_All,
+ /// Direct parent only.
+ AMM_ParentOnly
+ };
+
+ virtual ~ASTMatchFinder() {}
+
+ /// \brief Returns true if the given class is directly or indirectly derived
+ /// from a base type matching \c base.
+ ///
+ /// A class is considered to be also derived from itself.
+ virtual bool classIsDerivedFrom(const CXXRecordDecl *Declaration,
+ const Matcher<NamedDecl> &Base,
+ BoundNodesTreeBuilder *Builder) = 0;
+
+ template <typename T>
+ bool matchesChildOf(const T &Node,
+ const DynTypedMatcher &Matcher,
+ BoundNodesTreeBuilder *Builder,
+ TraversalKind Traverse,
+ BindKind Bind) {
+ static_assert(std::is_base_of<Decl, T>::value ||
+ std::is_base_of<Stmt, T>::value ||
+ std::is_base_of<NestedNameSpecifier, T>::value ||
+ std::is_base_of<NestedNameSpecifierLoc, T>::value ||
+ std::is_base_of<TypeLoc, T>::value ||
+ std::is_base_of<QualType, T>::value,
+ "unsupported type for recursive matching");
+ return matchesChildOf(ast_type_traits::DynTypedNode::create(Node),
+ Matcher, Builder, Traverse, Bind);
+ }
+
+ template <typename T>
+ bool matchesDescendantOf(const T &Node,
+ const DynTypedMatcher &Matcher,
+ BoundNodesTreeBuilder *Builder,
+ BindKind Bind) {
+ static_assert(std::is_base_of<Decl, T>::value ||
+ std::is_base_of<Stmt, T>::value ||
+ std::is_base_of<NestedNameSpecifier, T>::value ||
+ std::is_base_of<NestedNameSpecifierLoc, T>::value ||
+ std::is_base_of<TypeLoc, T>::value ||
+ std::is_base_of<QualType, T>::value,
+ "unsupported type for recursive matching");
+ return matchesDescendantOf(ast_type_traits::DynTypedNode::create(Node),
+ Matcher, Builder, Bind);
+ }
+
+ // FIXME: Implement support for BindKind.
+ template <typename T>
+ bool matchesAncestorOf(const T &Node,
+ const DynTypedMatcher &Matcher,
+ BoundNodesTreeBuilder *Builder,
+ AncestorMatchMode MatchMode) {
+ static_assert(std::is_base_of<Decl, T>::value ||
+ std::is_base_of<NestedNameSpecifierLoc, T>::value ||
+ std::is_base_of<Stmt, T>::value ||
+ std::is_base_of<TypeLoc, T>::value,
+ "type not allowed for recursive matching");
+ return matchesAncestorOf(ast_type_traits::DynTypedNode::create(Node),
+ Matcher, Builder, MatchMode);
+ }
+
+ virtual ASTContext &getASTContext() const = 0;
+
+protected:
+ virtual bool matchesChildOf(const ast_type_traits::DynTypedNode &Node,
+ const DynTypedMatcher &Matcher,
+ BoundNodesTreeBuilder *Builder,
+ TraversalKind Traverse,
+ BindKind Bind) = 0;
+
+ virtual bool matchesDescendantOf(const ast_type_traits::DynTypedNode &Node,
+ const DynTypedMatcher &Matcher,
+ BoundNodesTreeBuilder *Builder,
+ BindKind Bind) = 0;
+
+ virtual bool matchesAncestorOf(const ast_type_traits::DynTypedNode &Node,
+ const DynTypedMatcher &Matcher,
+ BoundNodesTreeBuilder *Builder,
+ AncestorMatchMode MatchMode) = 0;
+};
+
+/// \brief A type-list implementation.
+///
+/// A "linked list" of types, accessible by using the ::head and ::tail
+/// typedefs.
+template <typename... Ts> struct TypeList {}; // Empty sentinel type list.
+
+template <typename T1, typename... Ts> struct TypeList<T1, Ts...> {
+ /// \brief The first type on the list.
+ typedef T1 head;
+
+ /// \brief A sublist with the tail. ie everything but the head.
+ ///
+ /// This type is used to do recursion. TypeList<>/EmptyTypeList indicates the
+ /// end of the list.
+ typedef TypeList<Ts...> tail;
+};
+
+/// \brief The empty type list.
+typedef TypeList<> EmptyTypeList;
+
+/// \brief Helper meta-function to determine if some type \c T is present or
+/// a parent type in the list.
+template <typename AnyTypeList, typename T>
+struct TypeListContainsSuperOf {
+ static const bool value =
+ std::is_base_of<typename AnyTypeList::head, T>::value ||
+ TypeListContainsSuperOf<typename AnyTypeList::tail, T>::value;
+};
+template <typename T>
+struct TypeListContainsSuperOf<EmptyTypeList, T> {
+ static const bool value = false;
+};
+
+/// \brief A "type list" that contains all types.
+///
+/// Useful for matchers like \c anything and \c unless.
+typedef TypeList<Decl, Stmt, NestedNameSpecifier, NestedNameSpecifierLoc,
+ QualType, Type, TypeLoc, CXXCtorInitializer> AllNodeBaseTypes;
+
+/// \brief Helper meta-function to extract the argument out of a function of
+/// type void(Arg).
+///
+/// See AST_POLYMORPHIC_SUPPORTED_TYPES for details.
+template <class T> struct ExtractFunctionArgMeta;
+template <class T> struct ExtractFunctionArgMeta<void(T)> {
+ typedef T type;
+};
+
+/// \brief Default type lists for ArgumentAdaptingMatcher matchers.
+typedef AllNodeBaseTypes AdaptativeDefaultFromTypes;
+typedef TypeList<Decl, Stmt, NestedNameSpecifier, NestedNameSpecifierLoc,
+ TypeLoc, QualType> AdaptativeDefaultToTypes;
+
+/// \brief All types that are supported by HasDeclarationMatcher above.
+typedef TypeList<CallExpr, CXXConstructExpr, DeclRefExpr, EnumType,
+ InjectedClassNameType, LabelStmt, MemberExpr, QualType,
+ RecordType, TagType, TemplateSpecializationType,
+ TemplateTypeParmType, TypedefType,
+ UnresolvedUsingType> HasDeclarationSupportedTypes;
+
+/// \brief Converts a \c Matcher<T> to a matcher of desired type \c To by
+/// "adapting" a \c To into a \c T.
+///
+/// The \c ArgumentAdapterT argument specifies how the adaptation is done.
+///
+/// For example:
+/// \c ArgumentAdaptingMatcher<HasMatcher, T>(InnerMatcher);
+/// Given that \c InnerMatcher is of type \c Matcher<T>, this returns a matcher
+/// that is convertible into any matcher of type \c To by constructing
+/// \c HasMatcher<To, T>(InnerMatcher).
+///
+/// If a matcher does not need knowledge about the inner type, prefer to use
+/// PolymorphicMatcherWithParam1.
+template <template <typename ToArg, typename FromArg> class ArgumentAdapterT,
+ typename FromTypes = AdaptativeDefaultFromTypes,
+ typename ToTypes = AdaptativeDefaultToTypes>
+struct ArgumentAdaptingMatcherFunc {
+ template <typename T> class Adaptor {
+ public:
+ explicit Adaptor(const Matcher<T> &InnerMatcher)
+ : InnerMatcher(InnerMatcher) {}
+
+ typedef ToTypes ReturnTypes;
+
+ template <typename To> operator Matcher<To>() const {
+ return Matcher<To>(new ArgumentAdapterT<To, T>(InnerMatcher));
+ }
+
+ private:
+ const Matcher<T> InnerMatcher;
+ };
+
+ template <typename T>
+ static Adaptor<T> create(const Matcher<T> &InnerMatcher) {
+ return Adaptor<T>(InnerMatcher);
+ }
+
+ template <typename T>
+ Adaptor<T> operator()(const Matcher<T> &InnerMatcher) const {
+ return create(InnerMatcher);
+ }
+};
+
+/// \brief A PolymorphicMatcherWithParamN<MatcherT, P1, ..., PN> object can be
+/// created from N parameters p1, ..., pN (of type P1, ..., PN) and
+/// used as a Matcher<T> where a MatcherT<T, P1, ..., PN>(p1, ..., pN)
+/// can be constructed.
+///
+/// For example:
+/// - PolymorphicMatcherWithParam0<IsDefinitionMatcher>()
+/// creates an object that can be used as a Matcher<T> for any type T
+/// where an IsDefinitionMatcher<T>() can be constructed.
+/// - PolymorphicMatcherWithParam1<ValueEqualsMatcher, int>(42)
+/// creates an object that can be used as a Matcher<T> for any type T
+/// where a ValueEqualsMatcher<T, int>(42) can be constructed.
+template <template <typename T> class MatcherT,
+ typename ReturnTypesF = void(AllNodeBaseTypes)>
+class PolymorphicMatcherWithParam0 {
+public:
+ typedef typename ExtractFunctionArgMeta<ReturnTypesF>::type ReturnTypes;
+ template <typename T>
+ operator Matcher<T>() const {
+ static_assert(TypeListContainsSuperOf<ReturnTypes, T>::value,
+ "right polymorphic conversion");
+ return Matcher<T>(new MatcherT<T>());
+ }
+};
+
+template <template <typename T, typename P1> class MatcherT,
+ typename P1,
+ typename ReturnTypesF = void(AllNodeBaseTypes)>
+class PolymorphicMatcherWithParam1 {
+public:
+ explicit PolymorphicMatcherWithParam1(const P1 &Param1)
+ : Param1(Param1) {}
+
+ typedef typename ExtractFunctionArgMeta<ReturnTypesF>::type ReturnTypes;
+
+ template <typename T>
+ operator Matcher<T>() const {
+ static_assert(TypeListContainsSuperOf<ReturnTypes, T>::value,
+ "right polymorphic conversion");
+ return Matcher<T>(new MatcherT<T, P1>(Param1));
+ }
+
+private:
+ const P1 Param1;
+};
+
+template <template <typename T, typename P1, typename P2> class MatcherT,
+ typename P1, typename P2,
+ typename ReturnTypesF = void(AllNodeBaseTypes)>
+class PolymorphicMatcherWithParam2 {
+public:
+ PolymorphicMatcherWithParam2(const P1 &Param1, const P2 &Param2)
+ : Param1(Param1), Param2(Param2) {}
+
+ typedef typename ExtractFunctionArgMeta<ReturnTypesF>::type ReturnTypes;
+
+ template <typename T>
+ operator Matcher<T>() const {
+ static_assert(TypeListContainsSuperOf<ReturnTypes, T>::value,
+ "right polymorphic conversion");
+ return Matcher<T>(new MatcherT<T, P1, P2>(Param1, Param2));
+ }
+
+private:
+ const P1 Param1;
+ const P2 Param2;
+};
+
+/// \brief Matches any instance of the given NodeType.
+///
+/// This is useful when a matcher syntactically requires a child matcher,
+/// but the context doesn't care. See for example: anything().
+class TrueMatcher {
+ public:
+ typedef AllNodeBaseTypes ReturnTypes;
+
+ template <typename T>
+ operator Matcher<T>() const {
+ return DynTypedMatcher::trueMatcher(
+ ast_type_traits::ASTNodeKind::getFromNodeKind<T>())
+ .template unconditionalConvertTo<T>();
+ }
+};
+
+/// \brief A Matcher that allows binding the node it matches to an id.
+///
+/// BindableMatcher provides a \a bind() method that allows binding the
+/// matched node to an id if the match was successful.
+template <typename T>
+class BindableMatcher : public Matcher<T> {
+public:
+ explicit BindableMatcher(const Matcher<T> &M) : Matcher<T>(M) {}
+ explicit BindableMatcher(MatcherInterface<T> *Implementation)
+ : Matcher<T>(Implementation) {}
+
+ /// \brief Returns a matcher that will bind the matched node on a match.
+ ///
+ /// The returned matcher is equivalent to this matcher, but will
+ /// bind the matched node on a match.
+ Matcher<T> bind(StringRef ID) const {
+ return DynTypedMatcher(*this)
+ .tryBind(ID)
+ ->template unconditionalConvertTo<T>();
+ }
+
+ /// \brief Same as Matcher<T>'s conversion operator, but enables binding on
+ /// the returned matcher.
+ operator DynTypedMatcher() const {
+ DynTypedMatcher Result = static_cast<const Matcher<T>&>(*this);
+ Result.setAllowBind(true);
+ return Result;
+ }
+};
+
+/// \brief Matches nodes of type T that have child nodes of type ChildT for
+/// which a specified child matcher matches.
+///
+/// ChildT must be an AST base type.
+template <typename T, typename ChildT>
+class HasMatcher : public WrapperMatcherInterface<T> {
+ static_assert(IsBaseType<ChildT>::value,
+ "has only accepts base type matcher");
+
+public:
+ explicit HasMatcher(const Matcher<ChildT> &ChildMatcher)
+ : HasMatcher::WrapperMatcherInterface(ChildMatcher) {}
+
+ bool matches(const T &Node, ASTMatchFinder *Finder,
+ BoundNodesTreeBuilder *Builder) const override {
+ return Finder->matchesChildOf(
+ Node, this->InnerMatcher, Builder,
+ ASTMatchFinder::TK_IgnoreImplicitCastsAndParentheses,
+ ASTMatchFinder::BK_First);
+ }
+};
+
+/// \brief Matches nodes of type T that have child nodes of type ChildT for
+/// which a specified child matcher matches. ChildT must be an AST base
+/// type.
+/// As opposed to the HasMatcher, the ForEachMatcher will produce a match
+/// for each child that matches.
+template <typename T, typename ChildT>
+class ForEachMatcher : public WrapperMatcherInterface<T> {
+ static_assert(IsBaseType<ChildT>::value,
+ "for each only accepts base type matcher");
+
+ public:
+ explicit ForEachMatcher(const Matcher<ChildT> &ChildMatcher)
+ : ForEachMatcher::WrapperMatcherInterface(ChildMatcher) {}
+
+ bool matches(const T& Node, ASTMatchFinder* Finder,
+ BoundNodesTreeBuilder* Builder) const override {
+ return Finder->matchesChildOf(
+ Node, this->InnerMatcher, Builder,
+ ASTMatchFinder::TK_IgnoreImplicitCastsAndParentheses,
+ ASTMatchFinder::BK_All);
+ }
+};
+
+/// \brief VariadicOperatorMatcher related types.
+/// @{
+
+/// \brief Polymorphic matcher object that uses a \c
+/// DynTypedMatcher::VariadicOperator operator.
+///
+/// Input matchers can have any type (including other polymorphic matcher
+/// types), and the actual Matcher<T> is generated on demand with an implicit
+/// coversion operator.
+template <typename... Ps> class VariadicOperatorMatcher {
+public:
+ VariadicOperatorMatcher(DynTypedMatcher::VariadicOperator Op, Ps &&... Params)
+ : Op(Op), Params(std::forward<Ps>(Params)...) {}
+
+ template <typename T> operator Matcher<T>() const {
+ return DynTypedMatcher::constructVariadic(
+ Op, ast_type_traits::ASTNodeKind::getFromNodeKind<T>(),
+ getMatchers<T>(llvm::index_sequence_for<Ps...>()))
+ .template unconditionalConvertTo<T>();
+ }
+
+private:
+ // Helper method to unpack the tuple into a vector.
+ template <typename T, std::size_t... Is>
+ std::vector<DynTypedMatcher> getMatchers(llvm::index_sequence<Is...>) const {
+ return {Matcher<T>(std::get<Is>(Params))...};
+ }
+
+ const DynTypedMatcher::VariadicOperator Op;
+ std::tuple<Ps...> Params;
+};
+
+/// \brief Overloaded function object to generate VariadicOperatorMatcher
+/// objects from arbitrary matchers.
+template <unsigned MinCount, unsigned MaxCount>
+struct VariadicOperatorMatcherFunc {
+ DynTypedMatcher::VariadicOperator Op;
+
+ template <typename... Ms>
+ VariadicOperatorMatcher<Ms...> operator()(Ms &&... Ps) const {
+ static_assert(MinCount <= sizeof...(Ms) && sizeof...(Ms) <= MaxCount,
+ "invalid number of parameters for variadic matcher");
+ return VariadicOperatorMatcher<Ms...>(Op, std::forward<Ms>(Ps)...);
+ }
+};
+
+/// @}
+
+template <typename T>
+inline Matcher<T> DynTypedMatcher::unconditionalConvertTo() const {
+ return Matcher<T>(*this);
+}
+
+/// \brief Creates a Matcher<T> that matches if all inner matchers match.
+template<typename T>
+BindableMatcher<T> makeAllOfComposite(
+ ArrayRef<const Matcher<T> *> InnerMatchers) {
+ // For the size() == 0 case, we return a "true" matcher.
+ if (InnerMatchers.size() == 0) {
+ return BindableMatcher<T>(TrueMatcher());
+ }
+ // For the size() == 1 case, we simply return that one matcher.
+ // No need to wrap it in a variadic operation.
+ if (InnerMatchers.size() == 1) {
+ return BindableMatcher<T>(*InnerMatchers[0]);
+ }
+
+ typedef llvm::pointee_iterator<const Matcher<T> *const *> PI;
+ std::vector<DynTypedMatcher> DynMatchers(PI(InnerMatchers.begin()),
+ PI(InnerMatchers.end()));
+ return BindableMatcher<T>(
+ DynTypedMatcher::constructVariadic(
+ DynTypedMatcher::VO_AllOf,
+ ast_type_traits::ASTNodeKind::getFromNodeKind<T>(),
+ std::move(DynMatchers))
+ .template unconditionalConvertTo<T>());
+}
+
+/// \brief Creates a Matcher<T> that matches if
+/// T is dyn_cast'able into InnerT and all inner matchers match.
+///
+/// Returns BindableMatcher, as matchers that use dyn_cast have
+/// the same object both to match on and to run submatchers on,
+/// so there is no ambiguity with what gets bound.
+template<typename T, typename InnerT>
+BindableMatcher<T> makeDynCastAllOfComposite(
+ ArrayRef<const Matcher<InnerT> *> InnerMatchers) {
+ return BindableMatcher<T>(
+ makeAllOfComposite(InnerMatchers).template dynCastTo<T>());
+}
+
+/// \brief Matches nodes of type T that have at least one descendant node of
+/// type DescendantT for which the given inner matcher matches.
+///
+/// DescendantT must be an AST base type.
+template <typename T, typename DescendantT>
+class HasDescendantMatcher : public WrapperMatcherInterface<T> {
+ static_assert(IsBaseType<DescendantT>::value,
+ "has descendant only accepts base type matcher");
+
+public:
+ explicit HasDescendantMatcher(const Matcher<DescendantT> &DescendantMatcher)
+ : HasDescendantMatcher::WrapperMatcherInterface(DescendantMatcher) {}
+
+ bool matches(const T &Node, ASTMatchFinder *Finder,
+ BoundNodesTreeBuilder *Builder) const override {
+ return Finder->matchesDescendantOf(Node, this->InnerMatcher, Builder,
+ ASTMatchFinder::BK_First);
+ }
+};
+
+/// \brief Matches nodes of type \c T that have a parent node of type \c ParentT
+/// for which the given inner matcher matches.
+///
+/// \c ParentT must be an AST base type.
+template <typename T, typename ParentT>
+class HasParentMatcher : public WrapperMatcherInterface<T> {
+ static_assert(IsBaseType<ParentT>::value,
+ "has parent only accepts base type matcher");
+
+public:
+ explicit HasParentMatcher(const Matcher<ParentT> &ParentMatcher)
+ : HasParentMatcher::WrapperMatcherInterface(ParentMatcher) {}
+
+ bool matches(const T &Node, ASTMatchFinder *Finder,
+ BoundNodesTreeBuilder *Builder) const override {
+ return Finder->matchesAncestorOf(Node, this->InnerMatcher, Builder,
+ ASTMatchFinder::AMM_ParentOnly);
+ }
+};
+
+/// \brief Matches nodes of type \c T that have at least one ancestor node of
+/// type \c AncestorT for which the given inner matcher matches.
+///
+/// \c AncestorT must be an AST base type.
+template <typename T, typename AncestorT>
+class HasAncestorMatcher : public WrapperMatcherInterface<T> {
+ static_assert(IsBaseType<AncestorT>::value,
+ "has ancestor only accepts base type matcher");
+
+public:
+ explicit HasAncestorMatcher(const Matcher<AncestorT> &AncestorMatcher)
+ : HasAncestorMatcher::WrapperMatcherInterface(AncestorMatcher) {}
+
+ bool matches(const T &Node, ASTMatchFinder *Finder,
+ BoundNodesTreeBuilder *Builder) const override {
+ return Finder->matchesAncestorOf(Node, this->InnerMatcher, Builder,
+ ASTMatchFinder::AMM_All);
+ }
+};
+
+/// \brief Matches nodes of type T that have at least one descendant node of
+/// type DescendantT for which the given inner matcher matches.
+///
+/// DescendantT must be an AST base type.
+/// As opposed to HasDescendantMatcher, ForEachDescendantMatcher will match
+/// for each descendant node that matches instead of only for the first.
+template <typename T, typename DescendantT>
+class ForEachDescendantMatcher : public WrapperMatcherInterface<T> {
+ static_assert(IsBaseType<DescendantT>::value,
+ "for each descendant only accepts base type matcher");
+
+public:
+ explicit ForEachDescendantMatcher(
+ const Matcher<DescendantT> &DescendantMatcher)
+ : ForEachDescendantMatcher::WrapperMatcherInterface(DescendantMatcher) {}
+
+ bool matches(const T &Node, ASTMatchFinder *Finder,
+ BoundNodesTreeBuilder *Builder) const override {
+ return Finder->matchesDescendantOf(Node, this->InnerMatcher, Builder,
+ ASTMatchFinder::BK_All);
+ }
+};
+
+/// \brief Matches on nodes that have a getValue() method if getValue() equals
+/// the value the ValueEqualsMatcher was constructed with.
+template <typename T, typename ValueT>
+class ValueEqualsMatcher : public SingleNodeMatcherInterface<T> {
+ static_assert(std::is_base_of<CharacterLiteral, T>::value ||
+ std::is_base_of<CXXBoolLiteralExpr, T>::value ||
+ std::is_base_of<FloatingLiteral, T>::value ||
+ std::is_base_of<IntegerLiteral, T>::value,
+ "the node must have a getValue method");
+
+public:
+ explicit ValueEqualsMatcher(const ValueT &ExpectedValue)
+ : ExpectedValue(ExpectedValue) {}
+
+ bool matchesNode(const T &Node) const override {
+ return Node.getValue() == ExpectedValue;
+ }
+
+private:
+ const ValueT ExpectedValue;
+};
+
+/// \brief Template specializations to easily write matchers for floating point
+/// literals.
+template <>
+inline bool ValueEqualsMatcher<FloatingLiteral, double>::matchesNode(
+ const FloatingLiteral &Node) const {
+ if ((&Node.getSemantics()) == &llvm::APFloat::IEEEsingle)
+ return Node.getValue().convertToFloat() == ExpectedValue;
+ if ((&Node.getSemantics()) == &llvm::APFloat::IEEEdouble)
+ return Node.getValue().convertToDouble() == ExpectedValue;
+ return false;
+}
+template <>
+inline bool ValueEqualsMatcher<FloatingLiteral, float>::matchesNode(
+ const FloatingLiteral &Node) const {
+ if ((&Node.getSemantics()) == &llvm::APFloat::IEEEsingle)
+ return Node.getValue().convertToFloat() == ExpectedValue;
+ if ((&Node.getSemantics()) == &llvm::APFloat::IEEEdouble)
+ return Node.getValue().convertToDouble() == ExpectedValue;
+ return false;
+}
+template <>
+inline bool ValueEqualsMatcher<FloatingLiteral, llvm::APFloat>::matchesNode(
+ const FloatingLiteral &Node) const {
+ return ExpectedValue.compare(Node.getValue()) == llvm::APFloat::cmpEqual;
+}
+
+/// \brief A VariadicDynCastAllOfMatcher<SourceT, TargetT> object is a
+/// variadic functor that takes a number of Matcher<TargetT> and returns a
+/// Matcher<SourceT> that matches TargetT nodes that are matched by all of the
+/// given matchers, if SourceT can be dynamically casted into TargetT.
+///
+/// For example:
+/// const VariadicDynCastAllOfMatcher<
+/// Decl, CXXRecordDecl> record;
+/// Creates a functor record(...) that creates a Matcher<Decl> given
+/// a variable number of arguments of type Matcher<CXXRecordDecl>.
+/// The returned matcher matches if the given Decl can by dynamically
+/// casted to CXXRecordDecl and all given matchers match.
+template <typename SourceT, typename TargetT>
+class VariadicDynCastAllOfMatcher
+ : public llvm::VariadicFunction<
+ BindableMatcher<SourceT>, Matcher<TargetT>,
+ makeDynCastAllOfComposite<SourceT, TargetT> > {
+public:
+ VariadicDynCastAllOfMatcher() {}
+};
+
+/// \brief A \c VariadicAllOfMatcher<T> object is a variadic functor that takes
+/// a number of \c Matcher<T> and returns a \c Matcher<T> that matches \c T
+/// nodes that are matched by all of the given matchers.
+///
+/// For example:
+/// const VariadicAllOfMatcher<NestedNameSpecifier> nestedNameSpecifier;
+/// Creates a functor nestedNameSpecifier(...) that creates a
+/// \c Matcher<NestedNameSpecifier> given a variable number of arguments of type
+/// \c Matcher<NestedNameSpecifier>.
+/// The returned matcher matches if all given matchers match.
+template <typename T>
+class VariadicAllOfMatcher : public llvm::VariadicFunction<
+ BindableMatcher<T>, Matcher<T>,
+ makeAllOfComposite<T> > {
+public:
+ VariadicAllOfMatcher() {}
+};
+
+/// \brief Matches nodes of type \c TLoc for which the inner
+/// \c Matcher<T> matches.
+template <typename TLoc, typename T>
+class LocMatcher : public WrapperMatcherInterface<TLoc> {
+public:
+ explicit LocMatcher(const Matcher<T> &InnerMatcher)
+ : LocMatcher::WrapperMatcherInterface(InnerMatcher) {}
+
+ bool matches(const TLoc &Node, ASTMatchFinder *Finder,
+ BoundNodesTreeBuilder *Builder) const override {
+ if (!Node)
+ return false;
+ return this->InnerMatcher.matches(extract(Node), Finder, Builder);
+ }
+
+private:
+ static ast_type_traits::DynTypedNode
+ extract(const NestedNameSpecifierLoc &Loc) {
+ return ast_type_traits::DynTypedNode::create(*Loc.getNestedNameSpecifier());
+ }
+};
+
+/// \brief Matches \c TypeLocs based on an inner matcher matching a certain
+/// \c QualType.
+///
+/// Used to implement the \c loc() matcher.
+class TypeLocTypeMatcher : public WrapperMatcherInterface<TypeLoc> {
+public:
+ explicit TypeLocTypeMatcher(const Matcher<QualType> &InnerMatcher)
+ : TypeLocTypeMatcher::WrapperMatcherInterface(InnerMatcher) {}
+
+ bool matches(const TypeLoc &Node, ASTMatchFinder *Finder,
+ BoundNodesTreeBuilder *Builder) const override {
+ if (!Node)
+ return false;
+ return this->InnerMatcher.matches(
+ ast_type_traits::DynTypedNode::create(Node.getType()), Finder, Builder);
+ }
+};
+
+/// \brief Matches nodes of type \c T for which the inner matcher matches on a
+/// another node of type \c T that can be reached using a given traverse
+/// function.
+template <typename T>
+class TypeTraverseMatcher : public WrapperMatcherInterface<T> {
+public:
+ explicit TypeTraverseMatcher(const Matcher<QualType> &InnerMatcher,
+ QualType (T::*TraverseFunction)() const)
+ : TypeTraverseMatcher::WrapperMatcherInterface(InnerMatcher),
+ TraverseFunction(TraverseFunction) {}
+
+ bool matches(const T &Node, ASTMatchFinder *Finder,
+ BoundNodesTreeBuilder *Builder) const override {
+ QualType NextNode = (Node.*TraverseFunction)();
+ if (NextNode.isNull())
+ return false;
+ return this->InnerMatcher.matches(
+ ast_type_traits::DynTypedNode::create(NextNode), Finder, Builder);
+ }
+
+private:
+ QualType (T::*TraverseFunction)() const;
+};
+
+/// \brief Matches nodes of type \c T in a ..Loc hierarchy, for which the inner
+/// matcher matches on a another node of type \c T that can be reached using a
+/// given traverse function.
+template <typename T>
+class TypeLocTraverseMatcher : public WrapperMatcherInterface<T> {
+public:
+ explicit TypeLocTraverseMatcher(const Matcher<TypeLoc> &InnerMatcher,
+ TypeLoc (T::*TraverseFunction)() const)
+ : TypeLocTraverseMatcher::WrapperMatcherInterface(InnerMatcher),
+ TraverseFunction(TraverseFunction) {}
+
+ bool matches(const T &Node, ASTMatchFinder *Finder,
+ BoundNodesTreeBuilder *Builder) const override {
+ TypeLoc NextNode = (Node.*TraverseFunction)();
+ if (!NextNode)
+ return false;
+ return this->InnerMatcher.matches(
+ ast_type_traits::DynTypedNode::create(NextNode), Finder, Builder);
+ }
+
+private:
+ TypeLoc (T::*TraverseFunction)() const;
+};
+
+/// \brief Converts a \c Matcher<InnerT> to a \c Matcher<OuterT>, where
+/// \c OuterT is any type that is supported by \c Getter.
+///
+/// \code Getter<OuterT>::value() \endcode returns a
+/// \code InnerTBase (OuterT::*)() \endcode, which is used to adapt a \c OuterT
+/// object into a \c InnerT
+template <typename InnerTBase,
+ template <typename OuterT> class Getter,
+ template <typename OuterT> class MatcherImpl,
+ typename ReturnTypesF>
+class TypeTraversePolymorphicMatcher {
+private:
+ typedef TypeTraversePolymorphicMatcher<InnerTBase, Getter, MatcherImpl,
+ ReturnTypesF> Self;
+ static Self create(ArrayRef<const Matcher<InnerTBase> *> InnerMatchers);
+
+public:
+ typedef typename ExtractFunctionArgMeta<ReturnTypesF>::type ReturnTypes;
+
+ explicit TypeTraversePolymorphicMatcher(
+ ArrayRef<const Matcher<InnerTBase> *> InnerMatchers)
+ : InnerMatcher(makeAllOfComposite(InnerMatchers)) {}
+
+ template <typename OuterT> operator Matcher<OuterT>() const {
+ return Matcher<OuterT>(
+ new MatcherImpl<OuterT>(InnerMatcher, Getter<OuterT>::value()));
+ }
+
+ struct Func : public llvm::VariadicFunction<Self, Matcher<InnerTBase>,
+ &Self::create> {
+ Func() {}
+ };
+
+private:
+ const Matcher<InnerTBase> InnerMatcher;
+};
+
+/// \brief A simple memoizer of T(*)() functions.
+///
+/// It will call the passed 'Func' template parameter at most once.
+/// Used to support AST_MATCHER_FUNCTION() macro.
+template <typename Matcher, Matcher (*Func)()> class MemoizedMatcher {
+ struct Wrapper {
+ Wrapper() : M(Func()) {}
+ Matcher M;
+ };
+
+public:
+ static const Matcher &getInstance() {
+ static llvm::ManagedStatic<Wrapper> Instance;
+ return Instance->M;
+ }
+};
+
+// Define the create() method out of line to silence a GCC warning about
+// the struct "Func" having greater visibility than its base, which comes from
+// using the flag -fvisibility-inlines-hidden.
+template <typename InnerTBase, template <typename OuterT> class Getter,
+ template <typename OuterT> class MatcherImpl, typename ReturnTypesF>
+TypeTraversePolymorphicMatcher<InnerTBase, Getter, MatcherImpl, ReturnTypesF>
+TypeTraversePolymorphicMatcher<
+ InnerTBase, Getter, MatcherImpl,
+ ReturnTypesF>::create(ArrayRef<const Matcher<InnerTBase> *> InnerMatchers) {
+ return Self(InnerMatchers);
+}
+
+// FIXME: unify ClassTemplateSpecializationDecl and TemplateSpecializationType's
+// APIs for accessing the template argument list.
+inline ArrayRef<TemplateArgument>
+getTemplateSpecializationArgs(const ClassTemplateSpecializationDecl &D) {
+ return D.getTemplateArgs().asArray();
+}
+
+inline ArrayRef<TemplateArgument>
+getTemplateSpecializationArgs(const TemplateSpecializationType &T) {
+ return llvm::makeArrayRef(T.getArgs(), T.getNumArgs());
+}
+
+struct NotEqualsBoundNodePredicate {
+ bool operator()(const internal::BoundNodesMap &Nodes) const {
+ return Nodes.getNode(ID) != Node;
+ }
+ std::string ID;
+ ast_type_traits::DynTypedNode Node;
+};
+
+} // end namespace internal
+} // end namespace ast_matchers
+} // end namespace clang
+
+#endif
diff --git a/contrib/llvm/tools/clang/include/clang/ASTMatchers/ASTMatchersMacros.h b/contrib/llvm/tools/clang/include/clang/ASTMatchers/ASTMatchersMacros.h
new file mode 100644
index 0000000..8ad0c16
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/ASTMatchers/ASTMatchersMacros.h
@@ -0,0 +1,404 @@
+//===--- ASTMatchersMacros.h - Structural query framework -------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// Defines macros that enable us to define new matchers in a single place.
+// Since a matcher is a function which returns a Matcher<T> object, where
+// T is the type of the actual implementation of the matcher, the macros allow
+// us to write matchers like functions and take care of the definition of the
+// class boilerplate.
+//
+// Note that when you define a matcher with an AST_MATCHER* macro, only the
+// function which creates the matcher goes into the current namespace - the
+// class that implements the actual matcher, which gets returned by the
+// generator function, is put into the 'internal' namespace. This allows us
+// to only have the functions (which is all the user cares about) in the
+// 'ast_matchers' namespace and hide the boilerplate.
+//
+// To define a matcher in user code, put it into your own namespace. This would
+// help to prevent ODR violations in case a matcher with the same name is
+// defined in multiple translation units:
+//
+// namespace my_matchers {
+// AST_MATCHER_P(clang::MemberExpr, Member,
+// clang::ast_matchers::internal::Matcher<clang::ValueDecl>,
+// InnerMatcher) {
+// return InnerMatcher.matches(*Node.getMemberDecl(), Finder, Builder);
+// }
+// } // namespace my_matchers
+//
+// Alternatively, an unnamed namespace may be used:
+//
+// namespace clang {
+// namespace ast_matchers {
+// namespace {
+// AST_MATCHER_P(MemberExpr, Member,
+// internal::Matcher<ValueDecl>, InnerMatcher) {
+// return InnerMatcher.matches(*Node.getMemberDecl(), Finder, Builder);
+// }
+// } // namespace
+// } // namespace ast_matchers
+// } // namespace clang
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_ASTMATCHERS_ASTMATCHERSMACROS_H
+#define LLVM_CLANG_ASTMATCHERS_ASTMATCHERSMACROS_H
+
+/// \brief AST_MATCHER_FUNCTION(ReturnType, DefineMatcher) { ... }
+/// defines a zero parameter function named DefineMatcher() that returns a
+/// ReturnType object.
+#define AST_MATCHER_FUNCTION(ReturnType, DefineMatcher) \
+ inline ReturnType DefineMatcher##_getInstance(); \
+ inline ReturnType DefineMatcher() { \
+ return ::clang::ast_matchers::internal::MemoizedMatcher< \
+ ReturnType, DefineMatcher##_getInstance>::getInstance(); \
+ } \
+ inline ReturnType DefineMatcher##_getInstance()
+
+/// \brief AST_MATCHER_FUNCTION_P(ReturnType, DefineMatcher, ParamType, Param) {
+/// ... }
+/// defines a single-parameter function named DefineMatcher() that returns a
+/// ReturnType object.
+///
+/// The code between the curly braces has access to the following variables:
+///
+/// Param: the parameter passed to the function; its type
+/// is ParamType.
+///
+/// The code should return an instance of ReturnType.
+#define AST_MATCHER_FUNCTION_P(ReturnType, DefineMatcher, ParamType, Param) \
+ AST_MATCHER_FUNCTION_P_OVERLOAD(ReturnType, DefineMatcher, ParamType, Param, \
+ 0)
+#define AST_MATCHER_FUNCTION_P_OVERLOAD(ReturnType, DefineMatcher, ParamType, \
+ Param, OverloadId) \
+ inline ReturnType DefineMatcher(ParamType const &Param); \
+ typedef ReturnType (&DefineMatcher##_Type##OverloadId)(ParamType const &); \
+ inline ReturnType DefineMatcher(ParamType const &Param)
+
+/// \brief AST_MATCHER(Type, DefineMatcher) { ... }
+/// defines a zero parameter function named DefineMatcher() that returns a
+/// Matcher<Type> object.
+///
+/// The code between the curly braces has access to the following variables:
+///
+/// Node: the AST node being matched; its type is Type.
+/// Finder: an ASTMatchFinder*.
+/// Builder: a BoundNodesTreeBuilder*.
+///
+/// The code should return true if 'Node' matches.
+#define AST_MATCHER(Type, DefineMatcher) \
+ namespace internal { \
+ class matcher_##DefineMatcher##Matcher \
+ : public ::clang::ast_matchers::internal::MatcherInterface<Type> { \
+ public: \
+ explicit matcher_##DefineMatcher##Matcher() {} \
+ bool matches(const Type &Node, \
+ ::clang::ast_matchers::internal::ASTMatchFinder *Finder, \
+ ::clang::ast_matchers::internal::BoundNodesTreeBuilder \
+ *Builder) const override; \
+ }; \
+ } \
+ inline ::clang::ast_matchers::internal::Matcher<Type> DefineMatcher() { \
+ return ::clang::ast_matchers::internal::makeMatcher( \
+ new internal::matcher_##DefineMatcher##Matcher()); \
+ } \
+ inline bool internal::matcher_##DefineMatcher##Matcher::matches( \
+ const Type &Node, \
+ ::clang::ast_matchers::internal::ASTMatchFinder *Finder, \
+ ::clang::ast_matchers::internal::BoundNodesTreeBuilder *Builder) const
+
+/// \brief AST_MATCHER_P(Type, DefineMatcher, ParamType, Param) { ... }
+/// defines a single-parameter function named DefineMatcher() that returns a
+/// Matcher<Type> object.
+///
+/// The code between the curly braces has access to the following variables:
+///
+/// Node: the AST node being matched; its type is Type.
+/// Param: the parameter passed to the function; its type
+/// is ParamType.
+/// Finder: an ASTMatchFinder*.
+/// Builder: a BoundNodesTreeBuilder*.
+///
+/// The code should return true if 'Node' matches.
+#define AST_MATCHER_P(Type, DefineMatcher, ParamType, Param) \
+ AST_MATCHER_P_OVERLOAD(Type, DefineMatcher, ParamType, Param, 0)
+
+#define AST_MATCHER_P_OVERLOAD(Type, DefineMatcher, ParamType, Param, \
+ OverloadId) \
+ namespace internal { \
+ class matcher_##DefineMatcher##OverloadId##Matcher \
+ : public ::clang::ast_matchers::internal::MatcherInterface<Type> { \
+ public: \
+ explicit matcher_##DefineMatcher##OverloadId##Matcher( \
+ ParamType const &A##Param) \
+ : Param(A##Param) {} \
+ bool matches(const Type &Node, \
+ ::clang::ast_matchers::internal::ASTMatchFinder *Finder, \
+ ::clang::ast_matchers::internal::BoundNodesTreeBuilder \
+ *Builder) const override; \
+ \
+ private: \
+ ParamType const Param; \
+ }; \
+ } \
+ inline ::clang::ast_matchers::internal::Matcher<Type> DefineMatcher( \
+ ParamType const &Param) { \
+ return ::clang::ast_matchers::internal::makeMatcher( \
+ new internal::matcher_##DefineMatcher##OverloadId##Matcher(Param)); \
+ } \
+ typedef ::clang::ast_matchers::internal::Matcher<Type>( \
+ &DefineMatcher##_Type##OverloadId)(ParamType const &Param); \
+ inline bool internal::matcher_##DefineMatcher##OverloadId##Matcher::matches( \
+ const Type &Node, \
+ ::clang::ast_matchers::internal::ASTMatchFinder *Finder, \
+ ::clang::ast_matchers::internal::BoundNodesTreeBuilder *Builder) const
+
+/// \brief AST_MATCHER_P2(
+/// Type, DefineMatcher, ParamType1, Param1, ParamType2, Param2) { ... }
+/// defines a two-parameter function named DefineMatcher() that returns a
+/// Matcher<Type> object.
+///
+/// The code between the curly braces has access to the following variables:
+///
+/// Node: the AST node being matched; its type is Type.
+/// Param1, Param2: the parameters passed to the function; their types
+/// are ParamType1 and ParamType2.
+/// Finder: an ASTMatchFinder*.
+/// Builder: a BoundNodesTreeBuilder*.
+///
+/// The code should return true if 'Node' matches.
+#define AST_MATCHER_P2(Type, DefineMatcher, ParamType1, Param1, ParamType2, \
+ Param2) \
+ AST_MATCHER_P2_OVERLOAD(Type, DefineMatcher, ParamType1, Param1, ParamType2, \
+ Param2, 0)
+
+#define AST_MATCHER_P2_OVERLOAD(Type, DefineMatcher, ParamType1, Param1, \
+ ParamType2, Param2, OverloadId) \
+ namespace internal { \
+ class matcher_##DefineMatcher##OverloadId##Matcher \
+ : public ::clang::ast_matchers::internal::MatcherInterface<Type> { \
+ public: \
+ matcher_##DefineMatcher##OverloadId##Matcher(ParamType1 const &A##Param1, \
+ ParamType2 const &A##Param2) \
+ : Param1(A##Param1), Param2(A##Param2) {} \
+ bool matches(const Type &Node, \
+ ::clang::ast_matchers::internal::ASTMatchFinder *Finder, \
+ ::clang::ast_matchers::internal::BoundNodesTreeBuilder \
+ *Builder) const override; \
+ \
+ private: \
+ ParamType1 const Param1; \
+ ParamType2 const Param2; \
+ }; \
+ } \
+ inline ::clang::ast_matchers::internal::Matcher<Type> DefineMatcher( \
+ ParamType1 const &Param1, ParamType2 const &Param2) { \
+ return ::clang::ast_matchers::internal::makeMatcher( \
+ new internal::matcher_##DefineMatcher##OverloadId##Matcher(Param1, \
+ Param2)); \
+ } \
+ typedef ::clang::ast_matchers::internal::Matcher<Type>( \
+ &DefineMatcher##_Type##OverloadId)(ParamType1 const &Param1, \
+ ParamType2 const &Param2); \
+ inline bool internal::matcher_##DefineMatcher##OverloadId##Matcher::matches( \
+ const Type &Node, \
+ ::clang::ast_matchers::internal::ASTMatchFinder *Finder, \
+ ::clang::ast_matchers::internal::BoundNodesTreeBuilder *Builder) const
+
+/// \brief Construct a type-list to be passed to the AST_POLYMORPHIC_MATCHER*
+/// macros.
+///
+/// You can't pass something like \c TypeList<Foo, Bar> to a macro, because it
+/// will look at that as two arguments. However, you can pass
+/// \c void(TypeList<Foo, Bar>), which works thanks to the parenthesis.
+/// The \c PolymorphicMatcherWithParam* classes will unpack the function type to
+/// extract the TypeList object.
+#define AST_POLYMORPHIC_SUPPORTED_TYPES(...) \
+ void(::clang::ast_matchers::internal::TypeList<__VA_ARGS__>)
+
+/// \brief AST_POLYMORPHIC_MATCHER(DefineMatcher) { ... }
+/// defines a single-parameter function named DefineMatcher() that is
+/// polymorphic in the return type.
+///
+/// The variables are the same as for AST_MATCHER, but NodeType will be deduced
+/// from the calling context.
+#define AST_POLYMORPHIC_MATCHER(DefineMatcher, ReturnTypesF) \
+ namespace internal { \
+ template <typename NodeType> \
+ class matcher_##DefineMatcher##Matcher \
+ : public ::clang::ast_matchers::internal::MatcherInterface<NodeType> { \
+ public: \
+ bool matches(const NodeType &Node, \
+ ::clang::ast_matchers::internal::ASTMatchFinder *Finder, \
+ ::clang::ast_matchers::internal::BoundNodesTreeBuilder \
+ *Builder) const override; \
+ }; \
+ } \
+ inline ::clang::ast_matchers::internal::PolymorphicMatcherWithParam0< \
+ internal::matcher_##DefineMatcher##Matcher, ReturnTypesF> \
+ DefineMatcher() { \
+ return ::clang::ast_matchers::internal::PolymorphicMatcherWithParam0< \
+ internal::matcher_##DefineMatcher##Matcher, ReturnTypesF>(); \
+ } \
+ template <typename NodeType> \
+ bool internal::matcher_##DefineMatcher##Matcher<NodeType>::matches( \
+ const NodeType &Node, \
+ ::clang::ast_matchers::internal::ASTMatchFinder *Finder, \
+ ::clang::ast_matchers::internal::BoundNodesTreeBuilder *Builder) const
+
+/// \brief AST_POLYMORPHIC_MATCHER_P(DefineMatcher, ParamType, Param) { ... }
+/// defines a single-parameter function named DefineMatcher() that is
+/// polymorphic in the return type.
+///
+/// The variables are the same as for
+/// AST_MATCHER_P, with the addition of NodeType, which specifies the node type
+/// of the matcher Matcher<NodeType> returned by the function matcher().
+///
+/// FIXME: Pull out common code with above macro?
+#define AST_POLYMORPHIC_MATCHER_P(DefineMatcher, ReturnTypesF, ParamType, \
+ Param) \
+ AST_POLYMORPHIC_MATCHER_P_OVERLOAD(DefineMatcher, ReturnTypesF, ParamType, \
+ Param, 0)
+
+#define AST_POLYMORPHIC_MATCHER_P_OVERLOAD(DefineMatcher, ReturnTypesF, \
+ ParamType, Param, OverloadId) \
+ namespace internal { \
+ template <typename NodeType, typename ParamT> \
+ class matcher_##DefineMatcher##OverloadId##Matcher \
+ : public ::clang::ast_matchers::internal::MatcherInterface<NodeType> { \
+ public: \
+ explicit matcher_##DefineMatcher##OverloadId##Matcher( \
+ ParamType const &A##Param) \
+ : Param(A##Param) {} \
+ bool matches(const NodeType &Node, \
+ ::clang::ast_matchers::internal::ASTMatchFinder *Finder, \
+ ::clang::ast_matchers::internal::BoundNodesTreeBuilder \
+ *Builder) const override; \
+ \
+ private: \
+ ParamType const Param; \
+ }; \
+ } \
+ inline ::clang::ast_matchers::internal::PolymorphicMatcherWithParam1< \
+ internal::matcher_##DefineMatcher##OverloadId##Matcher, ParamType, \
+ ReturnTypesF> \
+ DefineMatcher(ParamType const &Param) { \
+ return ::clang::ast_matchers::internal::PolymorphicMatcherWithParam1< \
+ internal::matcher_##DefineMatcher##OverloadId##Matcher, ParamType, \
+ ReturnTypesF>(Param); \
+ } \
+ typedef ::clang::ast_matchers::internal::PolymorphicMatcherWithParam1< \
+ internal::matcher_##DefineMatcher##OverloadId##Matcher, ParamType, \
+ ReturnTypesF>(&DefineMatcher##_Type##OverloadId)( \
+ ParamType const &Param); \
+ template <typename NodeType, typename ParamT> \
+ bool internal:: \
+ matcher_##DefineMatcher##OverloadId##Matcher<NodeType, ParamT>::matches( \
+ const NodeType &Node, \
+ ::clang::ast_matchers::internal::ASTMatchFinder *Finder, \
+ ::clang::ast_matchers::internal::BoundNodesTreeBuilder *Builder) \
+ const
+
+/// \brief AST_POLYMORPHIC_MATCHER_P2(
+/// DefineMatcher, ParamType1, Param1, ParamType2, Param2) { ... }
+/// defines a two-parameter function named matcher() that is polymorphic in
+/// the return type.
+///
+/// The variables are the same as for AST_MATCHER_P2, with the
+/// addition of NodeType, which specifies the node type of the matcher
+/// Matcher<NodeType> returned by the function DefineMatcher().
+#define AST_POLYMORPHIC_MATCHER_P2(DefineMatcher, ReturnTypesF, ParamType1, \
+ Param1, ParamType2, Param2) \
+ AST_POLYMORPHIC_MATCHER_P2_OVERLOAD(DefineMatcher, ReturnTypesF, ParamType1, \
+ Param1, ParamType2, Param2, 0)
+
+#define AST_POLYMORPHIC_MATCHER_P2_OVERLOAD(DefineMatcher, ReturnTypesF, \
+ ParamType1, Param1, ParamType2, \
+ Param2, OverloadId) \
+ namespace internal { \
+ template <typename NodeType, typename ParamT1, typename ParamT2> \
+ class matcher_##DefineMatcher##OverloadId##Matcher \
+ : public ::clang::ast_matchers::internal::MatcherInterface<NodeType> { \
+ public: \
+ matcher_##DefineMatcher##OverloadId##Matcher(ParamType1 const &A##Param1, \
+ ParamType2 const &A##Param2) \
+ : Param1(A##Param1), Param2(A##Param2) {} \
+ bool matches(const NodeType &Node, \
+ ::clang::ast_matchers::internal::ASTMatchFinder *Finder, \
+ ::clang::ast_matchers::internal::BoundNodesTreeBuilder \
+ *Builder) const override; \
+ \
+ private: \
+ ParamType1 const Param1; \
+ ParamType2 const Param2; \
+ }; \
+ } \
+ inline ::clang::ast_matchers::internal::PolymorphicMatcherWithParam2< \
+ internal::matcher_##DefineMatcher##OverloadId##Matcher, ParamType1, \
+ ParamType2, ReturnTypesF> \
+ DefineMatcher(ParamType1 const &Param1, ParamType2 const &Param2) { \
+ return ::clang::ast_matchers::internal::PolymorphicMatcherWithParam2< \
+ internal::matcher_##DefineMatcher##OverloadId##Matcher, ParamType1, \
+ ParamType2, ReturnTypesF>(Param1, Param2); \
+ } \
+ typedef ::clang::ast_matchers::internal::PolymorphicMatcherWithParam2< \
+ internal::matcher_##DefineMatcher##OverloadId##Matcher, ParamType1, \
+ ParamType2, ReturnTypesF>(&DefineMatcher##_Type##OverloadId)( \
+ ParamType1 const &Param1, ParamType2 const &Param2); \
+ template <typename NodeType, typename ParamT1, typename ParamT2> \
+ bool internal::matcher_##DefineMatcher##OverloadId##Matcher< \
+ NodeType, ParamT1, ParamT2>:: \
+ matches(const NodeType &Node, \
+ ::clang::ast_matchers::internal::ASTMatchFinder *Finder, \
+ ::clang::ast_matchers::internal::BoundNodesTreeBuilder *Builder) \
+ const
+
+/// \brief Creates a variadic matcher for both a specific \c Type as well as
+/// the corresponding \c TypeLoc.
+#define AST_TYPE_MATCHER(NodeType, MatcherName) \
+ const ::clang::ast_matchers::internal::VariadicDynCastAllOfMatcher< \
+ Type, NodeType> MatcherName
+// FIXME: add a matcher for TypeLoc derived classes using its custom casting
+// API (no longer dyn_cast) if/when we need such matching
+
+/// \brief AST_TYPE_TRAVERSE_MATCHER(MatcherName, FunctionName) defines
+/// the matcher \c MatcherName that can be used to traverse from one \c Type
+/// to another.
+///
+/// For a specific \c SpecificType, the traversal is done using
+/// \c SpecificType::FunctionName. The existence of such a function determines
+/// whether a corresponding matcher can be used on \c SpecificType.
+#define AST_TYPE_TRAVERSE_MATCHER(MatcherName, FunctionName, ReturnTypesF) \
+ namespace internal { \
+ template <typename T> struct TypeMatcher##MatcherName##Getter { \
+ static QualType (T::*value())() const { return &T::FunctionName; } \
+ }; \
+ } \
+ const ::clang::ast_matchers::internal::TypeTraversePolymorphicMatcher< \
+ QualType, \
+ ::clang::ast_matchers::internal::TypeMatcher##MatcherName##Getter, \
+ ::clang::ast_matchers::internal::TypeTraverseMatcher, \
+ ReturnTypesF>::Func MatcherName
+
+/// \brief AST_TYPELOC_TRAVERSE_MATCHER(MatcherName, FunctionName) works
+/// identical to \c AST_TYPE_TRAVERSE_MATCHER but operates on \c TypeLocs.
+#define AST_TYPELOC_TRAVERSE_MATCHER(MatcherName, FunctionName, ReturnTypesF) \
+ namespace internal { \
+ template <typename T> struct TypeLocMatcher##MatcherName##Getter { \
+ static TypeLoc (T::*value())() const { return &T::FunctionName##Loc; } \
+ }; \
+ } \
+ const ::clang::ast_matchers::internal::TypeTraversePolymorphicMatcher< \
+ TypeLoc, \
+ ::clang::ast_matchers::internal::TypeLocMatcher##MatcherName##Getter, \
+ ::clang::ast_matchers::internal::TypeLocTraverseMatcher, \
+ ReturnTypesF>::Func MatcherName##Loc; \
+ AST_TYPE_TRAVERSE_MATCHER(MatcherName, FunctionName##Type, ReturnTypesF)
+
+#endif
diff --git a/contrib/llvm/tools/clang/include/clang/ASTMatchers/Dynamic/Diagnostics.h b/contrib/llvm/tools/clang/include/clang/ASTMatchers/Dynamic/Diagnostics.h
new file mode 100644
index 0000000..2c76dda
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/ASTMatchers/Dynamic/Diagnostics.h
@@ -0,0 +1,185 @@
+//===--- Diagnostics.h - Helper class for error diagnostics -----*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+///
+/// \file
+/// \brief Diagnostics class to manage error messages.
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_ASTMATCHERS_DYNAMIC_DIAGNOSTICS_H
+#define LLVM_CLANG_ASTMATCHERS_DYNAMIC_DIAGNOSTICS_H
+
+#include "clang/ASTMatchers/Dynamic/VariantValue.h"
+#include "clang/Basic/LLVM.h"
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/ADT/Twine.h"
+#include "llvm/Support/raw_ostream.h"
+#include <string>
+#include <vector>
+
+namespace clang {
+namespace ast_matchers {
+namespace dynamic {
+
+struct SourceLocation {
+ SourceLocation() : Line(), Column() {}
+ unsigned Line;
+ unsigned Column;
+};
+
+struct SourceRange {
+ SourceLocation Start;
+ SourceLocation End;
+};
+
+/// \brief A VariantValue instance annotated with its parser context.
+struct ParserValue {
+ ParserValue() : Text(), Range(), Value() {}
+ StringRef Text;
+ SourceRange Range;
+ VariantValue Value;
+};
+
+/// \brief Helper class to manage error messages.
+class Diagnostics {
+public:
+ /// \brief Parser context types.
+ enum ContextType {
+ CT_MatcherArg = 0,
+ CT_MatcherConstruct = 1
+ };
+
+ /// \brief All errors from the system.
+ enum ErrorType {
+ ET_None = 0,
+
+ ET_RegistryMatcherNotFound = 1,
+ ET_RegistryWrongArgCount = 2,
+ ET_RegistryWrongArgType = 3,
+ ET_RegistryNotBindable = 4,
+ ET_RegistryAmbiguousOverload = 5,
+ ET_RegistryValueNotFound = 6,
+
+ ET_ParserStringError = 100,
+ ET_ParserNoOpenParen = 101,
+ ET_ParserNoCloseParen = 102,
+ ET_ParserNoComma = 103,
+ ET_ParserNoCode = 104,
+ ET_ParserNotAMatcher = 105,
+ ET_ParserInvalidToken = 106,
+ ET_ParserMalformedBindExpr = 107,
+ ET_ParserTrailingCode = 108,
+ ET_ParserUnsignedError = 109,
+ ET_ParserOverloadedType = 110
+ };
+
+ /// \brief Helper stream class.
+ class ArgStream {
+ public:
+ ArgStream(std::vector<std::string> *Out) : Out(Out) {}
+ template <class T> ArgStream &operator<<(const T &Arg) {
+ return operator<<(Twine(Arg));
+ }
+ ArgStream &operator<<(const Twine &Arg);
+
+ private:
+ std::vector<std::string> *Out;
+ };
+
+ /// \brief Class defining a parser context.
+ ///
+ /// Used by the parser to specify (possibly recursive) contexts where the
+ /// parsing/construction can fail. Any error triggered within a context will
+ /// keep information about the context chain.
+ /// This class should be used as a RAII instance in the stack.
+ struct Context {
+ public:
+ /// \brief About to call the constructor for a matcher.
+ enum ConstructMatcherEnum { ConstructMatcher };
+ Context(ConstructMatcherEnum, Diagnostics *Error, StringRef MatcherName,
+ SourceRange MatcherRange);
+ /// \brief About to recurse into parsing one argument for a matcher.
+ enum MatcherArgEnum { MatcherArg };
+ Context(MatcherArgEnum, Diagnostics *Error, StringRef MatcherName,
+ SourceRange MatcherRange, unsigned ArgNumber);
+ ~Context();
+
+ private:
+ Diagnostics *const Error;
+ };
+
+ /// \brief Context for overloaded matcher construction.
+ ///
+ /// This context will take care of merging all errors that happen within it
+ /// as "candidate" overloads for the same matcher.
+ struct OverloadContext {
+ public:
+ OverloadContext(Diagnostics* Error);
+ ~OverloadContext();
+
+ /// \brief Revert all errors that happened within this context.
+ void revertErrors();
+
+ private:
+ Diagnostics *const Error;
+ unsigned BeginIndex;
+ };
+
+ /// \brief Add an error to the diagnostics.
+ ///
+ /// All the context information will be kept on the error message.
+ /// \return a helper class to allow the caller to pass the arguments for the
+ /// error message, using the << operator.
+ ArgStream addError(SourceRange Range, ErrorType Error);
+
+ /// \brief Information stored for one frame of the context.
+ struct ContextFrame {
+ ContextType Type;
+ SourceRange Range;
+ std::vector<std::string> Args;
+ };
+
+ /// \brief Information stored for each error found.
+ struct ErrorContent {
+ std::vector<ContextFrame> ContextStack;
+ struct Message {
+ SourceRange Range;
+ ErrorType Type;
+ std::vector<std::string> Args;
+ };
+ std::vector<Message> Messages;
+ };
+ ArrayRef<ErrorContent> errors() const { return Errors; }
+
+ /// \brief Returns a simple string representation of each error.
+ ///
+ /// Each error only shows the error message without any context.
+ void printToStream(llvm::raw_ostream &OS) const;
+ std::string toString() const;
+
+ /// \brief Returns the full string representation of each error.
+ ///
+ /// Each error message contains the full context.
+ void printToStreamFull(llvm::raw_ostream &OS) const;
+ std::string toStringFull() const;
+
+private:
+ /// \brief Helper function used by the constructors of ContextFrame.
+ ArgStream pushContextFrame(ContextType Type, SourceRange Range);
+
+ std::vector<ContextFrame> ContextStack;
+ std::vector<ErrorContent> Errors;
+};
+
+} // namespace dynamic
+} // namespace ast_matchers
+} // namespace clang
+
+#endif // LLVM_CLANG_AST_MATCHERS_DYNAMIC_DIAGNOSTICS_H
diff --git a/contrib/llvm/tools/clang/include/clang/ASTMatchers/Dynamic/Parser.h b/contrib/llvm/tools/clang/include/clang/ASTMatchers/Dynamic/Parser.h
new file mode 100644
index 0000000..76926f0
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/ASTMatchers/Dynamic/Parser.h
@@ -0,0 +1,257 @@
+//===--- Parser.h - Matcher expression parser -----*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+///
+/// \file
+/// \brief Simple matcher expression parser.
+///
+/// The parser understands matcher expressions of the form:
+/// MatcherName(Arg0, Arg1, ..., ArgN)
+/// as well as simple types like strings.
+/// The parser does not know how to process the matchers. It delegates this task
+/// to a Sema object received as an argument.
+///
+/// \code
+/// Grammar for the expressions supported:
+/// <Expression> := <Literal> | <NamedValue> | <MatcherExpression>
+/// <Literal> := <StringLiteral> | <Unsigned>
+/// <StringLiteral> := "quoted string"
+/// <Unsigned> := [0-9]+
+/// <NamedValue> := <Identifier>
+/// <MatcherExpression> := <Identifier>(<ArgumentList>) |
+/// <Identifier>(<ArgumentList>).bind(<StringLiteral>)
+/// <Identifier> := [a-zA-Z]+
+/// <ArgumentList> := <Expression> | <Expression>,<ArgumentList>
+/// \endcode
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_ASTMATCHERS_DYNAMIC_PARSER_H
+#define LLVM_CLANG_ASTMATCHERS_DYNAMIC_PARSER_H
+
+#include "clang/ASTMatchers/Dynamic/Diagnostics.h"
+#include "clang/ASTMatchers/Dynamic/Registry.h"
+#include "clang/ASTMatchers/Dynamic/VariantValue.h"
+#include "clang/Basic/LLVM.h"
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/Optional.h"
+#include "llvm/ADT/StringRef.h"
+
+namespace clang {
+namespace ast_matchers {
+namespace dynamic {
+
+/// \brief Matcher expression parser.
+class Parser {
+public:
+ /// \brief Interface to connect the parser with the registry and more.
+ ///
+ /// The parser uses the Sema instance passed into
+ /// parseMatcherExpression() to handle all matcher tokens. The simplest
+ /// processor implementation would simply call into the registry to create
+ /// the matchers.
+ /// However, a more complex processor might decide to intercept the matcher
+ /// creation and do some extra work. For example, it could apply some
+ /// transformation to the matcher by adding some id() nodes, or could detect
+ /// specific matcher nodes for more efficient lookup.
+ class Sema {
+ public:
+ virtual ~Sema();
+
+ /// \brief Process a matcher expression.
+ ///
+ /// All the arguments passed here have already been processed.
+ ///
+ /// \param Ctor A matcher constructor looked up by lookupMatcherCtor.
+ ///
+ /// \param NameRange The location of the name in the matcher source.
+ /// Useful for error reporting.
+ ///
+ /// \param BindID The ID to use to bind the matcher, or a null \c StringRef
+ /// if no ID is specified.
+ ///
+ /// \param Args The argument list for the matcher.
+ ///
+ /// \return The matcher objects constructed by the processor, or a null
+ /// matcher if an error occurred. In that case, \c Error will contain a
+ /// description of the error.
+ virtual VariantMatcher actOnMatcherExpression(MatcherCtor Ctor,
+ SourceRange NameRange,
+ StringRef BindID,
+ ArrayRef<ParserValue> Args,
+ Diagnostics *Error) = 0;
+
+ /// \brief Look up a matcher by name.
+ ///
+ /// \param MatcherName The matcher name found by the parser.
+ ///
+ /// \return The matcher constructor, or Optional<MatcherCtor>() if not
+ /// found.
+ virtual llvm::Optional<MatcherCtor>
+ lookupMatcherCtor(StringRef MatcherName) = 0;
+
+ /// \brief Compute the list of completion types for \p Context.
+ ///
+ /// Each element of \p Context represents a matcher invocation, going from
+ /// outermost to innermost. Elements are pairs consisting of a reference to
+ /// the matcher constructor and the index of the next element in the
+ /// argument list of that matcher (or for the last element, the index of
+ /// the completion point in the argument list). An empty list requests
+ /// completion for the root matcher.
+ virtual std::vector<ArgKind> getAcceptedCompletionTypes(
+ llvm::ArrayRef<std::pair<MatcherCtor, unsigned>> Context);
+
+ /// \brief Compute the list of completions that match any of
+ /// \p AcceptedTypes.
+ ///
+ /// \param AcceptedTypes All types accepted for this completion.
+ ///
+ /// \return All completions for the specified types.
+ /// Completions should be valid when used in \c lookupMatcherCtor().
+ /// The matcher constructed from the return of \c lookupMatcherCtor()
+ /// should be convertible to some type in \p AcceptedTypes.
+ virtual std::vector<MatcherCompletion>
+ getMatcherCompletions(llvm::ArrayRef<ArgKind> AcceptedTypes);
+ };
+
+ /// \brief Sema implementation that uses the matcher registry to process the
+ /// tokens.
+ class RegistrySema : public Parser::Sema {
+ public:
+ ~RegistrySema() override;
+
+ llvm::Optional<MatcherCtor>
+ lookupMatcherCtor(StringRef MatcherName) override;
+
+ VariantMatcher actOnMatcherExpression(MatcherCtor Ctor,
+ SourceRange NameRange,
+ StringRef BindID,
+ ArrayRef<ParserValue> Args,
+ Diagnostics *Error) override;
+
+ std::vector<ArgKind> getAcceptedCompletionTypes(
+ llvm::ArrayRef<std::pair<MatcherCtor, unsigned>> Context) override;
+
+ std::vector<MatcherCompletion>
+ getMatcherCompletions(llvm::ArrayRef<ArgKind> AcceptedTypes) override;
+ };
+
+ typedef llvm::StringMap<VariantValue> NamedValueMap;
+
+ /// \brief Parse a matcher expression.
+ ///
+ /// \param MatcherCode The matcher expression to parse.
+ ///
+ /// \param S The Sema instance that will help the parser
+ /// construct the matchers. If null, it uses the default registry.
+ ///
+ /// \param NamedValues A map of precomputed named values. This provides
+ /// the dictionary for the <NamedValue> rule of the grammar.
+ /// If null, it is ignored.
+ ///
+ /// \return The matcher object constructed by the processor, or an empty
+ /// Optional if an error occurred. In that case, \c Error will contain a
+ /// description of the error.
+ /// The caller takes ownership of the DynTypedMatcher object returned.
+ static llvm::Optional<DynTypedMatcher>
+ parseMatcherExpression(StringRef MatcherCode, Sema *S,
+ const NamedValueMap *NamedValues,
+ Diagnostics *Error);
+ static llvm::Optional<DynTypedMatcher>
+ parseMatcherExpression(StringRef MatcherCode, Sema *S,
+ Diagnostics *Error) {
+ return parseMatcherExpression(MatcherCode, S, nullptr, Error);
+ }
+ static llvm::Optional<DynTypedMatcher>
+ parseMatcherExpression(StringRef MatcherCode, Diagnostics *Error) {
+ return parseMatcherExpression(MatcherCode, nullptr, Error);
+ }
+
+ /// \brief Parse an expression.
+ ///
+ /// Parses any expression supported by this parser. In general, the
+ /// \c parseMatcherExpression function is a better approach to get a matcher
+ /// object.
+ ///
+ /// \param S The Sema instance that will help the parser
+ /// construct the matchers. If null, it uses the default registry.
+ ///
+ /// \param NamedValues A map of precomputed named values. This provides
+ /// the dictionary for the <NamedValue> rule of the grammar.
+ /// If null, it is ignored.
+ static bool parseExpression(StringRef Code, Sema *S,
+ const NamedValueMap *NamedValues,
+ VariantValue *Value, Diagnostics *Error);
+ static bool parseExpression(StringRef Code, Sema *S,
+ VariantValue *Value, Diagnostics *Error) {
+ return parseExpression(Code, S, nullptr, Value, Error);
+ }
+ static bool parseExpression(StringRef Code, VariantValue *Value,
+ Diagnostics *Error) {
+ return parseExpression(Code, nullptr, Value, Error);
+ }
+
+ /// \brief Complete an expression at the given offset.
+ ///
+ /// \param S The Sema instance that will help the parser
+ /// construct the matchers. If null, it uses the default registry.
+ ///
+ /// \param NamedValues A map of precomputed named values. This provides
+ /// the dictionary for the <NamedValue> rule of the grammar.
+ /// If null, it is ignored.
+ ///
+ /// \return The list of completions, which may be empty if there are no
+ /// available completions or if an error occurred.
+ static std::vector<MatcherCompletion>
+ completeExpression(StringRef Code, unsigned CompletionOffset, Sema *S,
+ const NamedValueMap *NamedValues);
+ static std::vector<MatcherCompletion>
+ completeExpression(StringRef Code, unsigned CompletionOffset, Sema *S) {
+ return completeExpression(Code, CompletionOffset, S, nullptr);
+ }
+ static std::vector<MatcherCompletion>
+ completeExpression(StringRef Code, unsigned CompletionOffset) {
+ return completeExpression(Code, CompletionOffset, nullptr);
+ }
+
+private:
+ class CodeTokenizer;
+ struct ScopedContextEntry;
+ struct TokenInfo;
+
+ Parser(CodeTokenizer *Tokenizer, Sema *S,
+ const NamedValueMap *NamedValues,
+ Diagnostics *Error);
+
+ bool parseExpressionImpl(VariantValue *Value);
+ bool parseMatcherExpressionImpl(const TokenInfo &NameToken,
+ VariantValue *Value);
+ bool parseIdentifierPrefixImpl(VariantValue *Value);
+
+ void addCompletion(const TokenInfo &CompToken,
+ const MatcherCompletion &Completion);
+ void addExpressionCompletions();
+
+ std::vector<MatcherCompletion>
+ getNamedValueCompletions(ArrayRef<ArgKind> AcceptedTypes);
+
+ CodeTokenizer *const Tokenizer;
+ Sema *const S;
+ const NamedValueMap *const NamedValues;
+ Diagnostics *const Error;
+
+ typedef std::vector<std::pair<MatcherCtor, unsigned> > ContextStackTy;
+ ContextStackTy ContextStack;
+ std::vector<MatcherCompletion> Completions;
+};
+
+} // namespace dynamic
+} // namespace ast_matchers
+} // namespace clang
+
+#endif // LLVM_CLANG_AST_MATCHERS_DYNAMIC_PARSER_H
diff --git a/contrib/llvm/tools/clang/include/clang/ASTMatchers/Dynamic/Registry.h b/contrib/llvm/tools/clang/include/clang/ASTMatchers/Dynamic/Registry.h
new file mode 100644
index 0000000..3808adb
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/ASTMatchers/Dynamic/Registry.h
@@ -0,0 +1,133 @@
+//===--- Registry.h - Matcher registry -----*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+///
+/// \file
+/// \brief Registry of all known matchers.
+///
+/// The registry provides a generic interface to construct any matcher by name.
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_ASTMATCHERS_DYNAMIC_REGISTRY_H
+#define LLVM_CLANG_ASTMATCHERS_DYNAMIC_REGISTRY_H
+
+#include "clang/ASTMatchers/Dynamic/Diagnostics.h"
+#include "clang/ASTMatchers/Dynamic/VariantValue.h"
+#include "clang/Basic/LLVM.h"
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/Optional.h"
+#include "llvm/ADT/StringRef.h"
+
+namespace clang {
+namespace ast_matchers {
+namespace dynamic {
+
+namespace internal {
+class MatcherDescriptor;
+}
+
+typedef const internal::MatcherDescriptor *MatcherCtor;
+
+struct MatcherCompletion {
+ MatcherCompletion() {}
+ MatcherCompletion(StringRef TypedText, StringRef MatcherDecl,
+ unsigned Specificity)
+ : TypedText(TypedText), MatcherDecl(MatcherDecl),
+ Specificity(Specificity) {}
+
+ /// \brief The text to type to select this matcher.
+ std::string TypedText;
+
+ /// \brief The "declaration" of the matcher, with type information.
+ std::string MatcherDecl;
+
+ /// \brief Value corresponding to the "specificity" of the converted matcher.
+ ///
+ /// Zero specificity indicates that this conversion would produce a trivial
+ /// matcher that will either always or never match.
+ /// Such matchers are excluded from code completion results.
+ unsigned Specificity;
+
+ bool operator==(const MatcherCompletion &Other) const {
+ return TypedText == Other.TypedText && MatcherDecl == Other.MatcherDecl;
+ }
+};
+
+class Registry {
+public:
+ /// \brief Look up a matcher in the registry by name,
+ ///
+ /// \return An opaque value which may be used to refer to the matcher
+ /// constructor, or Optional<MatcherCtor>() if not found.
+ static llvm::Optional<MatcherCtor> lookupMatcherCtor(StringRef MatcherName);
+
+ /// \brief Compute the list of completion types for \p Context.
+ ///
+ /// Each element of \p Context represents a matcher invocation, going from
+ /// outermost to innermost. Elements are pairs consisting of a reference to
+ /// the matcher constructor and the index of the next element in the
+ /// argument list of that matcher (or for the last element, the index of
+ /// the completion point in the argument list). An empty list requests
+ /// completion for the root matcher.
+ static std::vector<ArgKind> getAcceptedCompletionTypes(
+ llvm::ArrayRef<std::pair<MatcherCtor, unsigned>> Context);
+
+ /// \brief Compute the list of completions that match any of
+ /// \p AcceptedTypes.
+ ///
+ /// \param AcceptedTypes All types accepted for this completion.
+ ///
+ /// \return All completions for the specified types.
+ /// Completions should be valid when used in \c lookupMatcherCtor().
+ /// The matcher constructed from the return of \c lookupMatcherCtor()
+ /// should be convertible to some type in \p AcceptedTypes.
+ static std::vector<MatcherCompletion>
+ getMatcherCompletions(ArrayRef<ArgKind> AcceptedTypes);
+
+ /// \brief Construct a matcher from the registry.
+ ///
+ /// \param Ctor The matcher constructor to instantiate.
+ ///
+ /// \param NameRange The location of the name in the matcher source.
+ /// Useful for error reporting.
+ ///
+ /// \param Args The argument list for the matcher. The number and types of the
+ /// values must be valid for the matcher requested. Otherwise, the function
+ /// will return an error.
+ ///
+ /// \return The matcher object constructed if no error was found.
+ /// A null matcher if the number of arguments or argument types do not match
+ /// the signature. In that case \c Error will contain the description of
+ /// the error.
+ static VariantMatcher constructMatcher(MatcherCtor Ctor,
+ SourceRange NameRange,
+ ArrayRef<ParserValue> Args,
+ Diagnostics *Error);
+
+ /// \brief Construct a matcher from the registry and bind it.
+ ///
+ /// Similar the \c constructMatcher() above, but it then tries to bind the
+ /// matcher to the specified \c BindID.
+ /// If the matcher is not bindable, it sets an error in \c Error and returns
+ /// a null matcher.
+ static VariantMatcher constructBoundMatcher(MatcherCtor Ctor,
+ SourceRange NameRange,
+ StringRef BindID,
+ ArrayRef<ParserValue> Args,
+ Diagnostics *Error);
+
+private:
+ Registry() = delete;
+};
+
+} // namespace dynamic
+} // namespace ast_matchers
+} // namespace clang
+
+#endif // LLVM_CLANG_AST_MATCHERS_DYNAMIC_REGISTRY_H
diff --git a/contrib/llvm/tools/clang/include/clang/ASTMatchers/Dynamic/VariantValue.h b/contrib/llvm/tools/clang/include/clang/ASTMatchers/Dynamic/VariantValue.h
new file mode 100644
index 0000000..c391b24
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/ASTMatchers/Dynamic/VariantValue.h
@@ -0,0 +1,326 @@
+//===--- VariantValue.h - Polymorphic value type -*- C++ -*-===/
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+///
+/// \file
+/// \brief Polymorphic value type.
+///
+/// Supports all the types required for dynamic Matcher construction.
+/// Used by the registry to construct matchers in a generic way.
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_ASTMATCHERS_DYNAMIC_VARIANTVALUE_H
+#define LLVM_CLANG_ASTMATCHERS_DYNAMIC_VARIANTVALUE_H
+
+#include "clang/ASTMatchers/ASTMatchers.h"
+#include "clang/ASTMatchers/ASTMatchersInternal.h"
+#include "llvm/ADT/IntrusiveRefCntPtr.h"
+#include "llvm/ADT/Optional.h"
+#include "llvm/ADT/Twine.h"
+#include <memory>
+#include <vector>
+
+namespace clang {
+namespace ast_matchers {
+namespace dynamic {
+
+/// \brief Kind identifier.
+///
+/// It supports all types that VariantValue can contain.
+class ArgKind {
+ public:
+ enum Kind {
+ AK_Matcher,
+ AK_Unsigned,
+ AK_String
+ };
+ /// \brief Constructor for non-matcher types.
+ ArgKind(Kind K) : K(K) { assert(K != AK_Matcher); }
+
+ /// \brief Constructor for matcher types.
+ ArgKind(ast_type_traits::ASTNodeKind MatcherKind)
+ : K(AK_Matcher), MatcherKind(MatcherKind) {}
+
+ Kind getArgKind() const { return K; }
+ ast_type_traits::ASTNodeKind getMatcherKind() const {
+ assert(K == AK_Matcher);
+ return MatcherKind;
+ }
+
+ /// \brief Determines if this type can be converted to \p To.
+ ///
+ /// \param To the requested destination type.
+ ///
+ /// \param Specificity value corresponding to the "specificity" of the
+ /// convertion.
+ bool isConvertibleTo(ArgKind To, unsigned *Specificity) const;
+
+ bool operator<(const ArgKind &Other) const {
+ if (K == AK_Matcher && Other.K == AK_Matcher)
+ return MatcherKind < Other.MatcherKind;
+ return K < Other.K;
+ }
+
+ /// \brief String representation of the type.
+ std::string asString() const;
+
+private:
+ Kind K;
+ ast_type_traits::ASTNodeKind MatcherKind;
+};
+
+using ast_matchers::internal::DynTypedMatcher;
+
+/// \brief A variant matcher object.
+///
+/// The purpose of this object is to abstract simple and polymorphic matchers
+/// into a single object type.
+/// Polymorphic matchers might be implemented as a list of all the possible
+/// overloads of the matcher. \c VariantMatcher knows how to select the
+/// appropriate overload when needed.
+/// To get a real matcher object out of a \c VariantMatcher you can do:
+/// - getSingleMatcher() which returns a matcher, only if it is not ambiguous
+/// to decide which matcher to return. Eg. it contains only a single
+/// matcher, or a polymorphic one with only one overload.
+/// - hasTypedMatcher<T>()/getTypedMatcher<T>(): These calls will determine if
+/// the underlying matcher(s) can unambiguously return a Matcher<T>.
+class VariantMatcher {
+ /// \brief Methods that depend on T from hasTypedMatcher/getTypedMatcher.
+ class MatcherOps {
+ public:
+ MatcherOps(ast_type_traits::ASTNodeKind NodeKind) : NodeKind(NodeKind) {}
+
+ bool canConstructFrom(const DynTypedMatcher &Matcher,
+ bool &IsExactMatch) const;
+
+ /// \brief Convert \p Matcher the destination type and return it as a new
+ /// DynTypedMatcher.
+ virtual DynTypedMatcher
+ convertMatcher(const DynTypedMatcher &Matcher) const = 0;
+
+ /// \brief Constructs a variadic typed matcher from \p InnerMatchers.
+ /// Will try to convert each inner matcher to the destination type and
+ /// return llvm::None if it fails to do so.
+ llvm::Optional<DynTypedMatcher>
+ constructVariadicOperator(DynTypedMatcher::VariadicOperator Op,
+ ArrayRef<VariantMatcher> InnerMatchers) const;
+
+ protected:
+ ~MatcherOps() = default;
+
+ private:
+ ast_type_traits::ASTNodeKind NodeKind;
+ };
+
+ /// \brief Payload interface to be specialized by each matcher type.
+ ///
+ /// It follows a similar interface as VariantMatcher itself.
+ class Payload : public RefCountedBaseVPTR {
+ public:
+ ~Payload() override;
+ virtual llvm::Optional<DynTypedMatcher> getSingleMatcher() const = 0;
+ virtual std::string getTypeAsString() const = 0;
+ virtual llvm::Optional<DynTypedMatcher>
+ getTypedMatcher(const MatcherOps &Ops) const = 0;
+ virtual bool isConvertibleTo(ast_type_traits::ASTNodeKind Kind,
+ unsigned *Specificity) const = 0;
+ };
+
+public:
+ /// \brief A null matcher.
+ VariantMatcher();
+
+ /// \brief Clones the provided matcher.
+ static VariantMatcher SingleMatcher(const DynTypedMatcher &Matcher);
+
+ /// \brief Clones the provided matchers.
+ ///
+ /// They should be the result of a polymorphic matcher.
+ static VariantMatcher
+ PolymorphicMatcher(std::vector<DynTypedMatcher> Matchers);
+
+ /// \brief Creates a 'variadic' operator matcher.
+ ///
+ /// It will bind to the appropriate type on getTypedMatcher<T>().
+ static VariantMatcher
+ VariadicOperatorMatcher(DynTypedMatcher::VariadicOperator Op,
+ std::vector<VariantMatcher> Args);
+
+ /// \brief Makes the matcher the "null" matcher.
+ void reset();
+
+ /// \brief Whether the matcher is null.
+ bool isNull() const { return !Value; }
+
+ /// \brief Return a single matcher, if there is no ambiguity.
+ ///
+ /// \returns the matcher, if there is only one matcher. An empty Optional, if
+ /// the underlying matcher is a polymorphic matcher with more than one
+ /// representation.
+ llvm::Optional<DynTypedMatcher> getSingleMatcher() const;
+
+ /// \brief Determines if the contained matcher can be converted to
+ /// \c Matcher<T>.
+ ///
+ /// For the Single case, it returns true if it can be converted to
+ /// \c Matcher<T>.
+ /// For the Polymorphic case, it returns true if one, and only one, of the
+ /// overloads can be converted to \c Matcher<T>. If there are more than one
+ /// that can, the result would be ambiguous and false is returned.
+ template <class T>
+ bool hasTypedMatcher() const {
+ if (!Value) return false;
+ return Value->getTypedMatcher(TypedMatcherOps<T>()).hasValue();
+ }
+
+ /// \brief Determines if the contained matcher can be converted to \p Kind.
+ ///
+ /// \param Kind the requested destination type.
+ ///
+ /// \param Specificity value corresponding to the "specificity" of the
+ /// convertion.
+ bool isConvertibleTo(ast_type_traits::ASTNodeKind Kind,
+ unsigned *Specificity) const {
+ if (Value)
+ return Value->isConvertibleTo(Kind, Specificity);
+ return false;
+ }
+
+ /// \brief Return this matcher as a \c Matcher<T>.
+ ///
+ /// Handles the different types (Single, Polymorphic) accordingly.
+ /// Asserts that \c hasTypedMatcher<T>() is true.
+ template <class T>
+ ast_matchers::internal::Matcher<T> getTypedMatcher() const {
+ assert(hasTypedMatcher<T>() && "hasTypedMatcher<T>() == false");
+ return Value->getTypedMatcher(TypedMatcherOps<T>())
+ ->template convertTo<T>();
+ }
+
+ /// \brief String representation of the type of the value.
+ ///
+ /// If the underlying matcher is a polymorphic one, the string will show all
+ /// the types.
+ std::string getTypeAsString() const;
+
+private:
+ explicit VariantMatcher(Payload *Value) : Value(Value) {}
+
+ template <typename T> struct TypedMatcherOps;
+
+ class SinglePayload;
+ class PolymorphicPayload;
+ class VariadicOpPayload;
+
+ IntrusiveRefCntPtr<const Payload> Value;
+};
+
+template <typename T>
+struct VariantMatcher::TypedMatcherOps final : VariantMatcher::MatcherOps {
+ TypedMatcherOps()
+ : MatcherOps(ast_type_traits::ASTNodeKind::getFromNodeKind<T>()) {}
+ typedef ast_matchers::internal::Matcher<T> MatcherT;
+
+ DynTypedMatcher
+ convertMatcher(const DynTypedMatcher &Matcher) const override {
+ return DynTypedMatcher(Matcher.convertTo<T>());
+ }
+};
+
+/// \brief Variant value class.
+///
+/// Basically, a tagged union with value type semantics.
+/// It is used by the registry as the return value and argument type for the
+/// matcher factory methods.
+/// It can be constructed from any of the supported types. It supports
+/// copy/assignment.
+///
+/// Supported types:
+/// - \c unsigned
+/// - \c llvm::StringRef
+/// - \c VariantMatcher (\c DynTypedMatcher / \c Matcher<T>)
+class VariantValue {
+public:
+ VariantValue() : Type(VT_Nothing) {}
+
+ VariantValue(const VariantValue &Other);
+ ~VariantValue();
+ VariantValue &operator=(const VariantValue &Other);
+
+ /// \brief Specific constructors for each supported type.
+ VariantValue(unsigned Unsigned);
+ VariantValue(StringRef String);
+ VariantValue(const VariantMatcher &Matchers);
+
+ /// \brief Returns true iff this is not an empty value.
+ explicit operator bool() const { return hasValue(); }
+ bool hasValue() const { return Type != VT_Nothing; }
+
+ /// \brief Unsigned value functions.
+ bool isUnsigned() const;
+ unsigned getUnsigned() const;
+ void setUnsigned(unsigned Unsigned);
+
+ /// \brief String value functions.
+ bool isString() const;
+ const std::string &getString() const;
+ void setString(StringRef String);
+
+ /// \brief Matcher value functions.
+ bool isMatcher() const;
+ const VariantMatcher &getMatcher() const;
+ void setMatcher(const VariantMatcher &Matcher);
+
+ /// \brief Determines if the contained value can be converted to \p Kind.
+ ///
+ /// \param Kind the requested destination type.
+ ///
+ /// \param Specificity value corresponding to the "specificity" of the
+ /// convertion.
+ bool isConvertibleTo(ArgKind Kind, unsigned* Specificity) const;
+
+ /// \brief Determines if the contained value can be converted to any kind
+ /// in \p Kinds.
+ ///
+ /// \param Kinds the requested destination types.
+ ///
+ /// \param Specificity value corresponding to the "specificity" of the
+ /// convertion. It is the maximum specificity of all the possible
+ /// conversions.
+ bool isConvertibleTo(ArrayRef<ArgKind> Kinds, unsigned *Specificity) const;
+
+ /// \brief String representation of the type of the value.
+ std::string getTypeAsString() const;
+
+private:
+ void reset();
+
+ /// \brief All supported value types.
+ enum ValueType {
+ VT_Nothing,
+ VT_Unsigned,
+ VT_String,
+ VT_Matcher
+ };
+
+ /// \brief All supported value types.
+ union AllValues {
+ unsigned Unsigned;
+ std::string *String;
+ VariantMatcher *Matcher;
+ };
+
+ ValueType Type;
+ AllValues Value;
+};
+
+} // end namespace dynamic
+} // end namespace ast_matchers
+} // end namespace clang
+
+#endif // LLVM_CLANG_AST_MATCHERS_DYNAMIC_VARIANT_VALUE_H
diff --git a/contrib/llvm/tools/clang/include/clang/Analysis/Analyses/CFGReachabilityAnalysis.h b/contrib/llvm/tools/clang/include/clang/Analysis/Analyses/CFGReachabilityAnalysis.h
new file mode 100644
index 0000000..cc14c7b
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Analysis/Analyses/CFGReachabilityAnalysis.h
@@ -0,0 +1,49 @@
+//==- CFGReachabilityAnalysis.h - Basic reachability 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 a flow-sensitive, (mostly) path-insensitive reachability
+// analysis based on Clang's CFGs. Clients can query if a given basic block
+// is reachable within the CFG.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_ANALYSIS_ANALYSES_CFGREACHABILITYANALYSIS_H
+#define LLVM_CLANG_ANALYSIS_ANALYSES_CFGREACHABILITYANALYSIS_H
+
+#include "llvm/ADT/BitVector.h"
+#include "llvm/ADT/DenseMap.h"
+
+namespace clang {
+
+class CFG;
+class CFGBlock;
+
+// 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 CFGReverseBlockReachabilityAnalysis {
+ typedef llvm::BitVector ReachableSet;
+ typedef llvm::DenseMap<unsigned, ReachableSet> ReachableMap;
+ ReachableSet analyzed;
+ ReachableMap reachable;
+public:
+ CFGReverseBlockReachabilityAnalysis(const CFG &cfg);
+
+ /// Returns true if the block 'Dst' can be reached from block 'Src'.
+ bool isReachable(const CFGBlock *Src, const CFGBlock *Dst);
+
+private:
+ void mapReachability(const CFGBlock *Dst);
+};
+
+}
+
+#endif
diff --git a/contrib/llvm/tools/clang/include/clang/Analysis/Analyses/Consumed.h b/contrib/llvm/tools/clang/include/clang/Analysis/Analyses/Consumed.h
new file mode 100644
index 0000000..1f5aa12
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Analysis/Analyses/Consumed.h
@@ -0,0 +1,269 @@
+//===- Consumed.h ----------------------------------------------*- C++ --*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// A intra-procedural analysis for checking consumed properties. This is based,
+// in part, on research on linear types.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_ANALYSIS_ANALYSES_CONSUMED_H
+#define LLVM_CLANG_ANALYSIS_ANALYSES_CONSUMED_H
+
+#include "clang/AST/DeclCXX.h"
+#include "clang/AST/ExprCXX.h"
+#include "clang/AST/StmtCXX.h"
+#include "clang/Analysis/Analyses/PostOrderCFGView.h"
+#include "clang/Analysis/AnalysisContext.h"
+#include "clang/Basic/SourceLocation.h"
+
+namespace clang {
+namespace consumed {
+
+ enum ConsumedState {
+ // No state information for the given variable.
+ CS_None,
+
+ CS_Unknown,
+ CS_Unconsumed,
+ CS_Consumed
+ };
+
+ class ConsumedStmtVisitor;
+
+ typedef SmallVector<PartialDiagnosticAt, 1> OptionalNotes;
+ typedef std::pair<PartialDiagnosticAt, OptionalNotes> DelayedDiag;
+ typedef std::list<DelayedDiag> DiagList;
+
+ class ConsumedWarningsHandlerBase {
+
+ public:
+
+ virtual ~ConsumedWarningsHandlerBase();
+
+ /// \brief Emit the warnings and notes left by the analysis.
+ virtual void emitDiagnostics() {}
+
+ /// \brief Warn that a variable's state doesn't match at the entry and exit
+ /// of a loop.
+ ///
+ /// \param Loc -- The location of the end of the loop.
+ ///
+ /// \param VariableName -- The name of the variable that has a mismatched
+ /// state.
+ virtual void warnLoopStateMismatch(SourceLocation Loc,
+ StringRef VariableName) {}
+
+ /// \brief Warn about parameter typestate mismatches upon return.
+ ///
+ /// \param Loc -- The SourceLocation of the return statement.
+ ///
+ /// \param ExpectedState -- The state the return value was expected to be
+ /// in.
+ ///
+ /// \param ObservedState -- The state the return value was observed to be
+ /// in.
+ virtual void warnParamReturnTypestateMismatch(SourceLocation Loc,
+ StringRef VariableName,
+ StringRef ExpectedState,
+ StringRef ObservedState) {}
+
+ // FIXME: Add documentation.
+ virtual void warnParamTypestateMismatch(SourceLocation LOC,
+ StringRef ExpectedState,
+ StringRef ObservedState) {}
+
+ // FIXME: This can be removed when the attr propagation fix for templated
+ // classes lands.
+ /// \brief Warn about return typestates set for unconsumable types.
+ ///
+ /// \param Loc -- The location of the attributes.
+ ///
+ /// \param TypeName -- The name of the unconsumable type.
+ virtual void warnReturnTypestateForUnconsumableType(SourceLocation Loc,
+ StringRef TypeName) {}
+
+ /// \brief Warn about return typestate mismatches.
+ ///
+ /// \param Loc -- The SourceLocation of the return statement.
+ ///
+ /// \param ExpectedState -- The state the return value was expected to be
+ /// in.
+ ///
+ /// \param ObservedState -- The state the return value was observed to be
+ /// in.
+ virtual void warnReturnTypestateMismatch(SourceLocation Loc,
+ StringRef ExpectedState,
+ StringRef ObservedState) {}
+
+ /// \brief Warn about use-while-consumed errors.
+ /// \param MethodName -- The name of the method that was incorrectly
+ /// invoked.
+ ///
+ /// \param State -- The state the object was used in.
+ ///
+ /// \param Loc -- The SourceLocation of the method invocation.
+ virtual void warnUseOfTempInInvalidState(StringRef MethodName,
+ StringRef State,
+ SourceLocation Loc) {}
+
+ /// \brief Warn about use-while-consumed errors.
+ /// \param MethodName -- The name of the method that was incorrectly
+ /// invoked.
+ ///
+ /// \param State -- The state the object was used in.
+ ///
+ /// \param VariableName -- The name of the variable that holds the unique
+ /// value.
+ ///
+ /// \param Loc -- The SourceLocation of the method invocation.
+ virtual void warnUseInInvalidState(StringRef MethodName,
+ StringRef VariableName,
+ StringRef State,
+ SourceLocation Loc) {}
+ };
+
+ class ConsumedStateMap {
+
+ typedef llvm::DenseMap<const VarDecl *, ConsumedState> VarMapType;
+ typedef llvm::DenseMap<const CXXBindTemporaryExpr *, ConsumedState>
+ TmpMapType;
+
+ protected:
+
+ bool Reachable;
+ const Stmt *From;
+ VarMapType VarMap;
+ TmpMapType TmpMap;
+
+ public:
+ ConsumedStateMap() : Reachable(true), From(nullptr) {}
+ ConsumedStateMap(const ConsumedStateMap &Other)
+ : Reachable(Other.Reachable), From(Other.From), VarMap(Other.VarMap),
+ TmpMap() {}
+
+ /// \brief Warn if any of the parameters being tracked are not in the state
+ /// they were declared to be in upon return from a function.
+ void checkParamsForReturnTypestate(SourceLocation BlameLoc,
+ ConsumedWarningsHandlerBase &WarningsHandler) const;
+
+ /// \brief Clear the TmpMap.
+ void clearTemporaries();
+
+ /// \brief Get the consumed state of a given variable.
+ ConsumedState getState(const VarDecl *Var) const;
+
+ /// \brief Get the consumed state of a given temporary value.
+ ConsumedState getState(const CXXBindTemporaryExpr *Tmp) const;
+
+ /// \brief Merge this state map with another map.
+ void intersect(const ConsumedStateMap &Other);
+
+ void intersectAtLoopHead(const CFGBlock *LoopHead, const CFGBlock *LoopBack,
+ const ConsumedStateMap *LoopBackStates,
+ ConsumedWarningsHandlerBase &WarningsHandler);
+
+ /// \brief Return true if this block is reachable.
+ bool isReachable() const { return Reachable; }
+
+ /// \brief Mark the block as unreachable.
+ void markUnreachable();
+
+ /// \brief Set the source for a decision about the branching of states.
+ /// \param Source -- The statement that was the origin of a branching
+ /// decision.
+ void setSource(const Stmt *Source) { this->From = Source; }
+
+ /// \brief Set the consumed state of a given variable.
+ void setState(const VarDecl *Var, ConsumedState State);
+
+ /// \brief Set the consumed state of a given temporary value.
+ void setState(const CXXBindTemporaryExpr *Tmp, ConsumedState State);
+
+ /// \brief Remove the temporary value from our state map.
+ void remove(const CXXBindTemporaryExpr *Tmp);
+
+ /// \brief Tests to see if there is a mismatch in the states stored in two
+ /// maps.
+ ///
+ /// \param Other -- The second map to compare against.
+ bool operator!=(const ConsumedStateMap *Other) const;
+ };
+
+ class ConsumedBlockInfo {
+ std::vector<std::unique_ptr<ConsumedStateMap>> StateMapsArray;
+ std::vector<unsigned int> VisitOrder;
+
+ public:
+ ConsumedBlockInfo() = default;
+ ConsumedBlockInfo &operator=(ConsumedBlockInfo &&Other) {
+ StateMapsArray = std::move(Other.StateMapsArray);
+ VisitOrder = std::move(Other.VisitOrder);
+ return *this;
+ }
+
+ ConsumedBlockInfo(unsigned int NumBlocks, PostOrderCFGView *SortedGraph)
+ : StateMapsArray(NumBlocks), VisitOrder(NumBlocks, 0) {
+ unsigned int VisitOrderCounter = 0;
+ for (PostOrderCFGView::iterator BI = SortedGraph->begin(),
+ BE = SortedGraph->end(); BI != BE; ++BI) {
+ VisitOrder[(*BI)->getBlockID()] = VisitOrderCounter++;
+ }
+ }
+
+ bool allBackEdgesVisited(const CFGBlock *CurrBlock,
+ const CFGBlock *TargetBlock);
+
+ void addInfo(const CFGBlock *Block, ConsumedStateMap *StateMap,
+ std::unique_ptr<ConsumedStateMap> &OwnedStateMap);
+ void addInfo(const CFGBlock *Block,
+ std::unique_ptr<ConsumedStateMap> StateMap);
+
+ ConsumedStateMap* borrowInfo(const CFGBlock *Block);
+
+ void discardInfo(const CFGBlock *Block);
+
+ std::unique_ptr<ConsumedStateMap> getInfo(const CFGBlock *Block);
+
+ bool isBackEdge(const CFGBlock *From, const CFGBlock *To);
+ bool isBackEdgeTarget(const CFGBlock *Block);
+ };
+
+ /// A class that handles the analysis of uniqueness violations.
+ class ConsumedAnalyzer {
+
+ ConsumedBlockInfo BlockInfo;
+ std::unique_ptr<ConsumedStateMap> CurrStates;
+
+ ConsumedState ExpectedReturnState;
+
+ void determineExpectedReturnState(AnalysisDeclContext &AC,
+ const FunctionDecl *D);
+ bool splitState(const CFGBlock *CurrBlock,
+ const ConsumedStmtVisitor &Visitor);
+
+ public:
+
+ ConsumedWarningsHandlerBase &WarningsHandler;
+
+ ConsumedAnalyzer(ConsumedWarningsHandlerBase &WarningsHandler)
+ : WarningsHandler(WarningsHandler) {}
+
+ ConsumedState getExpectedReturnState() const { return ExpectedReturnState; }
+
+ /// \brief Check a function's CFG for consumed violations.
+ ///
+ /// We traverse the blocks in the CFG, keeping track of the state of each
+ /// value who's type has uniquness annotations. If methods are invoked in
+ /// the wrong state a warning is issued. Each block in the CFG is traversed
+ /// exactly once.
+ void run(AnalysisDeclContext &AC);
+ };
+}} // end namespace clang::consumed
+
+#endif
diff --git a/contrib/llvm/tools/clang/include/clang/Analysis/Analyses/Dominators.h b/contrib/llvm/tools/clang/include/clang/Analysis/Analyses/Dominators.h
new file mode 100644
index 0000000..4524aeb
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Analysis/Analyses/Dominators.h
@@ -0,0 +1,210 @@
+//==- Dominators.h - Implementation of dominators tree for Clang 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 implements the dominators tree functionality for Clang CFGs.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_ANALYSIS_ANALYSES_DOMINATORS_H
+#define LLVM_CLANG_ANALYSIS_ANALYSES_DOMINATORS_H
+
+#include "clang/Analysis/AnalysisContext.h"
+#include "clang/Analysis/CFG.h"
+#include "llvm/ADT/GraphTraits.h"
+#include "llvm/Support/GenericDomTree.h"
+#include "llvm/Support/GenericDomTreeConstruction.h"
+
+// FIXME: There is no good reason for the domtree to require a print method
+// which accepts an LLVM Module, so remove this (and the method's argument that
+// needs it) when that is fixed.
+namespace llvm {
+class Module;
+}
+
+namespace clang {
+
+class CFGBlock;
+typedef llvm::DomTreeNodeBase<CFGBlock> DomTreeNode;
+
+/// \brief Concrete subclass of DominatorTreeBase for Clang
+/// This class implements the dominators tree functionality given a Clang CFG.
+///
+class DominatorTree : public ManagedAnalysis {
+ virtual void anchor();
+public:
+ llvm::DominatorTreeBase<CFGBlock>* DT;
+
+ DominatorTree() {
+ DT = new llvm::DominatorTreeBase<CFGBlock>(false);
+ }
+
+ ~DominatorTree() override { delete DT; }
+
+ llvm::DominatorTreeBase<CFGBlock>& getBase() { return *DT; }
+
+ /// \brief This method returns the root CFGBlock of the dominators tree.
+ ///
+ inline CFGBlock *getRoot() const {
+ return DT->getRoot();
+ }
+
+ /// \brief This method returns the root DomTreeNode, which is the wrapper
+ /// for CFGBlock.
+ inline DomTreeNode *getRootNode() const {
+ return DT->getRootNode();
+ }
+
+ /// \brief This method compares two dominator trees.
+ /// The method returns false if the other dominator tree matches this
+ /// dominator tree, otherwise returns true.
+ ///
+ inline bool compare(DominatorTree &Other) const {
+ DomTreeNode *R = getRootNode();
+ DomTreeNode *OtherR = Other.getRootNode();
+
+ if (!R || !OtherR || R->getBlock() != OtherR->getBlock())
+ return true;
+
+ if (DT->compare(Other.getBase()))
+ return true;
+
+ return false;
+ }
+
+ /// \brief This method builds the dominator tree for a given CFG
+ /// The CFG information is passed via AnalysisDeclContext
+ ///
+ void buildDominatorTree(AnalysisDeclContext &AC) {
+ cfg = AC.getCFG();
+ DT->recalculate(*cfg);
+ }
+
+ /// \brief This method dumps immediate dominators for each block,
+ /// mainly used for debug purposes.
+ ///
+ void dump() {
+ llvm::errs() << "Immediate dominance tree (Node#,IDom#):\n";
+ for (CFG::const_iterator I = cfg->begin(),
+ E = cfg->end(); I != E; ++I) {
+ if(DT->getNode(*I)->getIDom())
+ llvm::errs() << "(" << (*I)->getBlockID()
+ << ","
+ << DT->getNode(*I)->getIDom()->getBlock()->getBlockID()
+ << ")\n";
+ else llvm::errs() << "(" << (*I)->getBlockID()
+ << "," << (*I)->getBlockID() << ")\n";
+ }
+ }
+
+ /// \brief This method tests if one CFGBlock dominates the other.
+ /// The method return true if A dominates B, false otherwise.
+ /// Note a block always dominates itself.
+ ///
+ inline bool dominates(const CFGBlock* A, const CFGBlock* B) const {
+ return DT->dominates(A, B);
+ }
+
+ /// \brief This method tests if one CFGBlock properly dominates the other.
+ /// The method return true if A properly dominates B, false otherwise.
+ ///
+ bool properlyDominates(const CFGBlock*A, const CFGBlock*B) const {
+ return DT->properlyDominates(A, B);
+ }
+
+ /// \brief This method finds the nearest common dominator CFG block
+ /// for CFG block A and B. If there is no such block then return NULL.
+ ///
+ inline CFGBlock *findNearestCommonDominator(CFGBlock *A, CFGBlock *B) {
+ return DT->findNearestCommonDominator(A, B);
+ }
+
+ inline const CFGBlock *findNearestCommonDominator(const CFGBlock *A,
+ const CFGBlock *B) {
+ return DT->findNearestCommonDominator(A, B);
+ }
+
+ /// \brief This method is used to update the dominator
+ /// tree information when a node's immediate dominator changes.
+ ///
+ inline void changeImmediateDominator(CFGBlock *N, CFGBlock *NewIDom) {
+ DT->changeImmediateDominator(N, NewIDom);
+ }
+
+ /// \brief This method tests if the given CFGBlock can be reachable from root.
+ /// Returns true if reachable, false otherwise.
+ ///
+ bool isReachableFromEntry(const CFGBlock *A) {
+ return DT->isReachableFromEntry(A);
+ }
+
+ /// \brief This method releases the memory held by the dominator tree.
+ ///
+ virtual void releaseMemory() {
+ DT->releaseMemory();
+ }
+
+ /// \brief This method converts the dominator tree to human readable form.
+ ///
+ virtual void print(raw_ostream &OS, const llvm::Module* M= nullptr) const {
+ DT->print(OS);
+ }
+
+private:
+ CFG *cfg;
+};
+
+} // end namespace clang
+
+//===-------------------------------------
+/// DominatorTree GraphTraits specialization so the DominatorTree can be
+/// iterable by generic graph iterators.
+///
+namespace llvm {
+template <> struct GraphTraits< ::clang::DomTreeNode* > {
+ typedef ::clang::DomTreeNode NodeType;
+ typedef NodeType::iterator ChildIteratorType;
+
+ static NodeType *getEntryNode(NodeType *N) {
+ return N;
+ }
+ static inline ChildIteratorType child_begin(NodeType *N) {
+ return N->begin();
+ }
+ static inline ChildIteratorType child_end(NodeType *N) {
+ return N->end();
+ }
+
+ typedef df_iterator< ::clang::DomTreeNode* > nodes_iterator;
+
+ static nodes_iterator nodes_begin(::clang::DomTreeNode *N) {
+ return df_begin(getEntryNode(N));
+ }
+
+ static nodes_iterator nodes_end(::clang::DomTreeNode *N) {
+ return df_end(getEntryNode(N));
+ }
+};
+
+template <> struct GraphTraits< ::clang::DominatorTree* >
+ : public GraphTraits< ::clang::DomTreeNode* > {
+ static NodeType *getEntryNode(::clang::DominatorTree *DT) {
+ return DT->getRootNode();
+ }
+
+ static nodes_iterator nodes_begin(::clang::DominatorTree *N) {
+ return df_begin(getEntryNode(N));
+ }
+
+ static nodes_iterator nodes_end(::clang::DominatorTree *N) {
+ return df_end(getEntryNode(N));
+ }
+};
+} // end namespace llvm
+
+#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..4471311
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Analysis/Analyses/FormatString.h
@@ -0,0 +1,679 @@
+//= 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_ANALYSIS_ANALYSES_FORMATSTRING_H
+#define LLVM_CLANG_ANALYSIS_ANALYSES_FORMATSTRING_H
+
+#include "clang/AST/CanonicalType.h"
+
+namespace clang {
+
+class TargetInfo;
+
+//===----------------------------------------------------------------------===//
+/// 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);
+ flag = true;
+ this->position = position;
+ }
+ const char *getPosition() const {
+ assert(position);
+ return position;
+ }
+ const char *toString() const { return representation; }
+
+ // Overloaded operators for bool like qualities
+ explicit 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'
+ AsQuad, // 'q' (BSD, deprecated, for 64-bit integer types)
+ AsIntMax, // 'j'
+ AsSizeT, // 'z'
+ AsPtrDiff, // 't'
+ AsInt32, // 'I32' (MSVCRT, like __int32)
+ AsInt3264, // 'I' (MSVCRT, like __int3264 from MIDL)
+ AsInt64, // 'I64' (MSVCRT, like __int64)
+ AsLongDouble, // 'L'
+ AsAllocate, // for '%as', GNU extension to C90 scanf
+ AsMAllocate, // for '%ms', GNU extension to scanf
+ AsWide, // 'w' (MSVCRT, like l but only for c, C, s, S, or Z
+ AsWideChar = AsLong // for '%ls', only makes sense for printf
+ };
+
+ LengthModifier()
+ : Position(nullptr), 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 AsInt32:
+ case AsInt64:
+ return 3;
+ 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,
+ DArg, // Apple extension
+ iArg,
+ IntArgBeg = dArg, IntArgEnd = iArg,
+
+ oArg,
+ OArg, // Apple extension
+ uArg,
+ UArg, // Apple extension
+ 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 **
+
+ ZArg, // MS extension
+
+ // Objective-C specific specifiers.
+ ObjCObjArg, // '@'
+ ObjCBeg = ObjCObjArg, ObjCEnd = ObjCObjArg,
+
+ // FreeBSD kernel specific specifiers.
+ FreeBSDbArg,
+ FreeBSDDArg,
+ FreeBSDrArg,
+ FreeBSDyArg,
+
+ // GlibC specific specifiers.
+ PrintErrno, // 'm'
+
+ PrintfConvBeg = ObjCObjArg, PrintfConvEnd = PrintErrno,
+
+ // ** Scanf-specific **
+ ScanListArg, // '['
+ ScanfConvBeg = ScanListArg, ScanfConvEnd = ScanListArg
+ };
+
+ ConversionSpecifier(bool isPrintf = true)
+ : IsPrintf(isPrintf), Position(nullptr), EndScanList(nullptr),
+ kind(InvalidSpecifier) {}
+
+ ConversionSpecifier(bool isPrintf, const char *pos, Kind k)
+ : IsPrintf(isPrintf), Position(pos), EndScanList(nullptr), kind(k) {}
+
+ const char *getStart() const {
+ return Position;
+ }
+
+ StringRef getCharacters() const {
+ return StringRef(getStart(), getLength());
+ }
+
+ bool consumesDataArgument() const {
+ switch (kind) {
+ case PrintErrno:
+ assert(IsPrintf);
+ return false;
+ 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;
+ }
+
+ bool isIntArg() const { return (kind >= IntArgBeg && kind <= IntArgEnd) ||
+ kind == FreeBSDrArg || kind == FreeBSDyArg; }
+ bool isUIntArg() const { return kind >= UIntArgBeg && kind <= UIntArgEnd; }
+ bool isAnyIntArg() const { return kind >= IntArgBeg && kind <= UIntArgEnd; }
+ const char *toString() const;
+
+ bool isPrintfKind() const { return IsPrintf; }
+
+ Optional<ConversionSpecifier> getStandardSpecifier() const;
+
+protected:
+ bool IsPrintf;
+ const char *Position;
+ const char *EndScanList;
+ Kind kind;
+};
+
+class ArgType {
+public:
+ enum Kind { UnknownTy, InvalidTy, SpecificTy, ObjCPointerTy, CPointerTy,
+ AnyCharTy, CStrTy, WCStrTy, WIntTy };
+
+ enum MatchKind { NoMatch = 0, Match = 1, NoMatchPedantic };
+
+private:
+ const Kind K;
+ QualType T;
+ const char *Name;
+ bool Ptr;
+public:
+ ArgType(Kind k = UnknownTy, const char *n = nullptr)
+ : K(k), Name(n), Ptr(false) {}
+ ArgType(QualType t, const char *n = nullptr)
+ : K(SpecificTy), T(t), Name(n), Ptr(false) {}
+ ArgType(CanQualType t) : K(SpecificTy), T(t), Name(nullptr), Ptr(false) {}
+
+ static ArgType Invalid() { return ArgType(InvalidTy); }
+ bool isValid() const { return K != InvalidTy; }
+
+ /// Create an ArgType which corresponds to the type pointer to A.
+ static ArgType PtrTo(const ArgType& A) {
+ assert(A.K >= InvalidTy && "ArgType cannot be pointer to invalid/unknown");
+ ArgType Res = A;
+ Res.Ptr = true;
+ return Res;
+ }
+
+ MatchKind matchesType(ASTContext &C, QualType argTy) const;
+
+ QualType getRepresentativeType(ASTContext &C) const;
+
+ std::string getRepresentativeTypeName(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(nullptr),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;
+ }
+
+ ArgType getArgType(ASTContext &Ctx) const;
+
+ void toString(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 TargetInfo &Target) const;
+
+ bool hasStandardLengthModifier() const;
+
+ Optional<LengthModifier> getCorrectedLengthModifier() const;
+
+ bool hasStandardConversionSpecifier(const LangOptions &LangOpt) const;
+
+ bool hasStandardLengthConversionCombination() const;
+
+ /// For a TypedefType QT, if it is a named integer type such as size_t,
+ /// assign the appropriate value to LM and return true.
+ static bool namedTypeToLengthModifier(QualType QT, LengthModifier &LM);
+};
+
+} // 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, nullptr, InvalidSpecifier) {}
+
+ PrintfConversionSpecifier(const char *pos, Kind k)
+ : ConversionSpecifier(true, pos, k) {}
+
+ bool isObjCArg() const { return kind >= ObjCBeg && kind <= ObjCEnd; }
+ bool isDoubleArg() const { return kind >= DoubleArgBeg &&
+ kind <= DoubleArgEnd; }
+ 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::ArgType;
+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'
+ OptionalFlag HasObjCTechnicalTerm; // '[tt]'
+ OptionalAmount Precision;
+public:
+ PrintfSpecifier() :
+ FormatSpecifier(/* isPrintf = */ true),
+ HasThousandsGrouping("'"), IsLeftJustified("-"), HasPlusPrefix("+"),
+ HasSpacePrefix(" "), HasAlternativeForm("#"), HasLeadingZeroes("0"),
+ HasObjCTechnicalTerm("tt") {}
+
+ 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.setPosition(position);
+ }
+ void setIsLeftJustified(const char *position) {
+ IsLeftJustified.setPosition(position);
+ }
+ void setHasPlusPrefix(const char *position) {
+ HasPlusPrefix.setPosition(position);
+ }
+ void setHasSpacePrefix(const char *position) {
+ HasSpacePrefix.setPosition(position);
+ }
+ void setHasAlternativeForm(const char *position) {
+ HasAlternativeForm.setPosition(position);
+ }
+ void setHasLeadingZeros(const char *position) {
+ HasLeadingZeroes.setPosition(position);
+ }
+ void setHasObjCTechnicalTerm(const char *position) {
+ HasObjCTechnicalTerm.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.
+ ArgType getArgType(ASTContext &Ctx, bool IsObjCLiteral) 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; }
+ const OptionalFlag &hasObjCTechnicalTerm() const { return HasObjCTechnicalTerm; }
+ 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, const LangOptions &LangOpt, ASTContext &Ctx,
+ bool IsObjCLiteral);
+
+ void toString(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, nullptr, 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::ArgType;
+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.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;
+ }
+
+ ArgType getArgType(ASTContext &Ctx) const;
+
+ bool fixType(QualType QT, QualType RawQT, const LangOptions &LangOpt,
+ ASTContext &Ctx);
+
+ void toString(raw_ostream &os) const;
+
+ 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 HandlePosition(const char *startPos, unsigned posLen) {}
+
+ 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) {}
+
+ virtual void HandleEmptyObjCModifierFlag(const char *startFlags,
+ unsigned flagsLen) {}
+
+ virtual void HandleInvalidObjCModifierFlag(const char *startFlag,
+ unsigned flagLen) {}
+
+ virtual void HandleObjCFlagsWithNonObjCConversion(const char *flagsStart,
+ const char *flagsEnd,
+ const char *conversionPosition) {}
+ // 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, const LangOptions &LO,
+ const TargetInfo &Target, bool isFreeBSDKPrintf);
+
+bool ParseFormatStringHasSArg(const char *beg, const char *end,
+ const LangOptions &LO, const TargetInfo &Target);
+
+bool ParseScanfString(FormatStringHandler &H,
+ const char *beg, const char *end, const LangOptions &LO,
+ const TargetInfo &Target);
+
+} // 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..e17f73a6
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Analysis/Analyses/LiveVariables.h
@@ -0,0 +1,117 @@
+//===- 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_ANALYSIS_ANALYSES_LIVEVARIABLES_H
+#define LLVM_CLANG_ANALYSIS_ANALYSES_LIVEVARIABLES_H
+
+#include "clang/AST/Decl.h"
+#include "clang/Analysis/AnalysisContext.h"
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/ImmutableSet.h"
+
+namespace clang {
+
+class CFG;
+class CFGBlock;
+class Stmt;
+class DeclRefExpr;
+class SourceManager;
+
+class LiveVariables : public ManagedAnalysis {
+public:
+ class LivenessValues {
+ public:
+
+ llvm::ImmutableSet<const Stmt *> liveStmts;
+ llvm::ImmutableSet<const VarDecl *> liveDecls;
+
+ bool equals(const LivenessValues &V) const;
+
+ LivenessValues()
+ : liveStmts(nullptr), liveDecls(nullptr) {}
+
+ LivenessValues(llvm::ImmutableSet<const Stmt *> LiveStmts,
+ llvm::ImmutableSet<const VarDecl *> LiveDecls)
+ : liveStmts(LiveStmts), liveDecls(LiveDecls) {}
+
+ bool isLive(const Stmt *S) const;
+ bool isLive(const VarDecl *D) const;
+
+ friend class LiveVariables;
+ };
+
+ class Observer {
+ virtual void anchor();
+ public:
+ virtual ~Observer() {}
+
+ /// A callback invoked right before invoking the
+ /// liveness transfer function on the given statement.
+ virtual void observeStmt(const Stmt *S,
+ const CFGBlock *currentBlock,
+ const LivenessValues& V) {}
+
+ /// Called when the live variables analysis registers
+ /// that a variable is killed.
+ virtual void observerKill(const DeclRefExpr *DR) {}
+ };
+
+ ~LiveVariables() override;
+
+ /// Compute the liveness information for a given CFG.
+ static LiveVariables *computeLiveness(AnalysisDeclContext &analysisContext,
+ bool killAtAssign);
+
+ /// Return true if a variable is live at the end of a
+ /// specified block.
+ bool isLive(const CFGBlock *B, const VarDecl *D);
+
+ /// 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);
+
+ /// 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);
+
+ /// Print to stderr the liveness information associated with
+ /// each basic block.
+ void dumpBlockLiveness(const SourceManager& M);
+
+ void runOnAllBlocks(Observer &obs);
+
+ static LiveVariables *create(AnalysisDeclContext &analysisContext) {
+ return computeLiveness(analysisContext, true);
+ }
+
+ static const void *getTag();
+
+private:
+ LiveVariables(void *impl);
+ void *impl;
+};
+
+class RelaxedLiveVariables : public LiveVariables {
+public:
+ static LiveVariables *create(AnalysisDeclContext &analysisContext) {
+ return computeLiveness(analysisContext, false);
+ }
+
+ static const void *getTag();
+};
+
+} // end namespace clang
+
+#endif
diff --git a/contrib/llvm/tools/clang/include/clang/Analysis/Analyses/PostOrderCFGView.h b/contrib/llvm/tools/clang/include/clang/Analysis/Analyses/PostOrderCFGView.h
new file mode 100644
index 0000000..a1c6504
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Analysis/Analyses/PostOrderCFGView.h
@@ -0,0 +1,115 @@
+//===- PostOrderCFGView.h - Post order view of CFG blocks ---------*- 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 post order view of the blocks in a CFG.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_ANALYSIS_ANALYSES_POSTORDERCFGVIEW_H
+#define LLVM_CLANG_ANALYSIS_ANALYSES_POSTORDERCFGVIEW_H
+
+#include <vector>
+//#include <algorithm>
+
+#include "llvm/ADT/PostOrderIterator.h"
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/BitVector.h"
+
+#include "clang/Analysis/AnalysisContext.h"
+#include "clang/Analysis/CFG.h"
+
+namespace clang {
+
+class PostOrderCFGView : public ManagedAnalysis {
+ virtual void anchor();
+public:
+ /// \brief Implements a set of CFGBlocks using a BitVector.
+ ///
+ /// This class contains a minimal interface, primarily dictated by the SetType
+ /// template parameter of the llvm::po_iterator template, as used with
+ /// external storage. We also use this set to keep track of which CFGBlocks we
+ /// visit during the analysis.
+ class CFGBlockSet {
+ llvm::BitVector VisitedBlockIDs;
+ public:
+ // po_iterator requires this iterator, but the only interface needed is the
+ // value_type typedef.
+ struct iterator { typedef const CFGBlock *value_type; };
+
+ CFGBlockSet() {}
+ CFGBlockSet(const CFG *G) : VisitedBlockIDs(G->getNumBlockIDs(), false) {}
+
+ /// \brief Set the bit associated with a particular CFGBlock.
+ /// This is the important method for the SetType template parameter.
+ std::pair<llvm::NoneType, bool> insert(const CFGBlock *Block) {
+ // Note that insert() is called by po_iterator, which doesn't check to
+ // make sure that Block is non-null. Moreover, the CFGBlock iterator will
+ // occasionally hand out null pointers for pruned edges, so we catch those
+ // here.
+ if (!Block)
+ return std::make_pair(None, false); // if an edge is trivially false.
+ if (VisitedBlockIDs.test(Block->getBlockID()))
+ return std::make_pair(None, false);
+ VisitedBlockIDs.set(Block->getBlockID());
+ return std::make_pair(None, true);
+ }
+
+ /// \brief Check if the bit for a CFGBlock has been already set.
+ /// This method is for tracking visited blocks in the main threadsafety
+ /// loop. Block must not be null.
+ bool alreadySet(const CFGBlock *Block) {
+ return VisitedBlockIDs.test(Block->getBlockID());
+ }
+ };
+
+private:
+ typedef llvm::po_iterator<const CFG*, CFGBlockSet, true> po_iterator;
+ std::vector<const CFGBlock*> Blocks;
+
+ typedef llvm::DenseMap<const CFGBlock *, unsigned> BlockOrderTy;
+ BlockOrderTy BlockOrder;
+
+public:
+ typedef std::vector<const CFGBlock *>::reverse_iterator iterator;
+ typedef std::vector<const CFGBlock *>::const_reverse_iterator const_iterator;
+
+ PostOrderCFGView(const CFG *cfg);
+
+ iterator begin() { return Blocks.rbegin(); }
+ iterator end() { return Blocks.rend(); }
+
+ const_iterator begin() const { return Blocks.rbegin(); }
+ const_iterator end() const { return Blocks.rend(); }
+
+ bool empty() const { return begin() == end(); }
+
+ struct BlockOrderCompare;
+ friend struct BlockOrderCompare;
+
+ struct BlockOrderCompare {
+ const PostOrderCFGView &POV;
+ public:
+ BlockOrderCompare(const PostOrderCFGView &pov) : POV(pov) {}
+ bool operator()(const CFGBlock *b1, const CFGBlock *b2) const;
+ };
+
+ BlockOrderCompare getComparator() const {
+ return BlockOrderCompare(*this);
+ }
+
+ // Used by AnalyisContext to construct this object.
+ static const void *getTag();
+
+ static PostOrderCFGView *create(AnalysisDeclContext &analysisContext);
+};
+
+} // end clang namespace
+
+#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..c4ec2f2
--- /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_ANALYSES_PSEUDOCONSTANTANALYSIS_H
+#define LLVM_CLANG_ANALYSIS_ANALYSES_PSEUDOCONSTANTANALYSIS_H
+
+#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..4c523bf
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Analysis/Analyses/ReachableCode.h
@@ -0,0 +1,69 @@
+//===- 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_ANALYSIS_ANALYSES_REACHABLECODE_H
+#define LLVM_CLANG_ANALYSIS_ANALYSES_REACHABLECODE_H
+
+#include "clang/Basic/SourceLocation.h"
+
+//===----------------------------------------------------------------------===//
+// Forward declarations.
+//===----------------------------------------------------------------------===//
+
+namespace llvm {
+ class BitVector;
+}
+
+namespace clang {
+ class AnalysisDeclContext;
+ class CFGBlock;
+ class Preprocessor;
+}
+
+//===----------------------------------------------------------------------===//
+// API.
+//===----------------------------------------------------------------------===//
+
+namespace clang {
+namespace reachable_code {
+
+/// Classifications of unreachable code.
+enum UnreachableKind {
+ UK_Return,
+ UK_Break,
+ UK_Loop_Increment,
+ UK_Other
+};
+
+class Callback {
+ virtual void anchor();
+public:
+ virtual ~Callback() {}
+ virtual void HandleUnreachable(UnreachableKind UK,
+ SourceLocation L,
+ SourceRange ConditionVal,
+ 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(AnalysisDeclContext &AC, Preprocessor &PP,
+ Callback &CB);
+
+}} // end namespace clang::reachable_code
+
+#endif
diff --git a/contrib/llvm/tools/clang/include/clang/Analysis/Analyses/ThreadSafety.h b/contrib/llvm/tools/clang/include/clang/Analysis/Analyses/ThreadSafety.h
new file mode 100644
index 0000000..22694a7
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Analysis/Analyses/ThreadSafety.h
@@ -0,0 +1,226 @@
+//===- ThreadSafety.h ------------------------------------------*- C++ --*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+//
+// A intra-procedural analysis for thread safety (e.g. deadlocks and race
+// conditions), based off of an annotation system.
+//
+// See http://clang.llvm.org/docs/LanguageExtensions.html#thread-safety-annotation-checking
+// for more information.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_ANALYSIS_ANALYSES_THREADSAFETY_H
+#define LLVM_CLANG_ANALYSIS_ANALYSES_THREADSAFETY_H
+
+#include "clang/Analysis/AnalysisContext.h"
+#include "clang/Basic/SourceLocation.h"
+#include "llvm/ADT/StringRef.h"
+
+namespace clang {
+namespace threadSafety {
+
+class BeforeSet;
+
+/// This enum distinguishes between different kinds of operations that may
+/// need to be protected by locks. We use this enum in error handling.
+enum ProtectedOperationKind {
+ POK_VarDereference, ///< Dereferencing a variable (e.g. p in *p = 5;)
+ POK_VarAccess, ///< Reading or writing a variable (e.g. x in x = 5;)
+ POK_FunctionCall, ///< Making a function call (e.g. fool())
+ POK_PassByRef, ///< Passing a guarded variable by reference.
+ POK_PtPassByRef, ///< Passing a pt-guarded variable by reference.
+};
+
+/// This enum distinguishes between different kinds of lock actions. For
+/// example, it is an error to write a variable protected by shared version of a
+/// mutex.
+enum LockKind {
+ LK_Shared, ///< Shared/reader lock of a mutex.
+ LK_Exclusive, ///< Exclusive/writer lock of a mutex.
+ LK_Generic ///< Can be either Shared or Exclusive
+};
+
+/// This enum distinguishes between different ways to access (read or write) a
+/// variable.
+enum AccessKind {
+ AK_Read, ///< Reading a variable.
+ AK_Written ///< Writing a variable.
+};
+
+/// This enum distinguishes between different situations where we warn due to
+/// inconsistent locking.
+/// \enum SK_LockedSomeLoopIterations -- a mutex is locked for some but not all
+/// loop iterations.
+/// \enum SK_LockedSomePredecessors -- a mutex is locked in some but not all
+/// predecessors of a CFGBlock.
+/// \enum SK_LockedAtEndOfFunction -- a mutex is still locked at the end of a
+/// function.
+enum LockErrorKind {
+ LEK_LockedSomeLoopIterations,
+ LEK_LockedSomePredecessors,
+ LEK_LockedAtEndOfFunction,
+ LEK_NotLockedAtEndOfFunction
+};
+
+/// Handler class for thread safety warnings.
+class ThreadSafetyHandler {
+public:
+ typedef StringRef Name;
+ ThreadSafetyHandler() : IssueBetaWarnings(false) { }
+ virtual ~ThreadSafetyHandler();
+
+ /// Warn about lock expressions which fail to resolve to lockable objects.
+ /// \param Kind -- the capability's name parameter (role, mutex, etc).
+ /// \param Loc -- the SourceLocation of the unresolved expression.
+ virtual void handleInvalidLockExp(StringRef Kind, SourceLocation Loc) {}
+
+ /// Warn about unlock function calls that do not have a prior matching lock
+ /// expression.
+ /// \param Kind -- the capability's name parameter (role, mutex, etc).
+ /// \param LockName -- A StringRef name for the lock expression, to be printed
+ /// in the error message.
+ /// \param Loc -- The SourceLocation of the Unlock
+ virtual void handleUnmatchedUnlock(StringRef Kind, Name LockName,
+ SourceLocation Loc) {}
+
+ /// Warn about an unlock function call that attempts to unlock a lock with
+ /// the incorrect lock kind. For instance, a shared lock being unlocked
+ /// exclusively, or vice versa.
+ /// \param LockName -- A StringRef name for the lock expression, to be printed
+ /// in the error message.
+ /// \param Kind -- the capability's name parameter (role, mutex, etc).
+ /// \param Expected -- the kind of lock expected.
+ /// \param Received -- the kind of lock received.
+ /// \param Loc -- The SourceLocation of the Unlock.
+ virtual void handleIncorrectUnlockKind(StringRef Kind, Name LockName,
+ LockKind Expected, LockKind Received,
+ SourceLocation Loc) {}
+
+ /// Warn about lock function calls for locks which are already held.
+ /// \param Kind -- the capability's name parameter (role, mutex, etc).
+ /// \param LockName -- A StringRef name for the lock expression, to be printed
+ /// in the error message.
+ /// \param Loc -- The location of the second lock expression.
+ virtual void handleDoubleLock(StringRef Kind, Name LockName,
+ SourceLocation Loc) {}
+
+ /// Warn about situations where a mutex is sometimes held and sometimes not.
+ /// The three situations are:
+ /// 1. a mutex is locked on an "if" branch but not the "else" branch,
+ /// 2, or a mutex is only held at the start of some loop iterations,
+ /// 3. or when a mutex is locked but not unlocked inside a function.
+ /// \param Kind -- the capability's name parameter (role, mutex, etc).
+ /// \param LockName -- A StringRef name for the lock expression, to be printed
+ /// in the error message.
+ /// \param LocLocked -- The location of the lock expression where the mutex is
+ /// locked
+ /// \param LocEndOfScope -- The location of the end of the scope where the
+ /// mutex is no longer held
+ /// \param LEK -- which of the three above cases we should warn for
+ virtual void handleMutexHeldEndOfScope(StringRef Kind, Name LockName,
+ SourceLocation LocLocked,
+ SourceLocation LocEndOfScope,
+ LockErrorKind LEK) {}
+
+ /// Warn when a mutex is held exclusively and shared at the same point. For
+ /// example, if a mutex is locked exclusively during an if branch and shared
+ /// during the else branch.
+ /// \param Kind -- the capability's name parameter (role, mutex, etc).
+ /// \param LockName -- A StringRef name for the lock expression, to be printed
+ /// in the error message.
+ /// \param Loc1 -- The location of the first lock expression.
+ /// \param Loc2 -- The location of the second lock expression.
+ virtual void handleExclusiveAndShared(StringRef Kind, Name LockName,
+ SourceLocation Loc1,
+ SourceLocation Loc2) {}
+
+ /// Warn when a protected operation occurs while no locks are held.
+ /// \param Kind -- the capability's name parameter (role, mutex, etc).
+ /// \param D -- The decl for the protected variable or function
+ /// \param POK -- The kind of protected operation (e.g. variable access)
+ /// \param AK -- The kind of access (i.e. read or write) that occurred
+ /// \param Loc -- The location of the protected operation.
+ virtual void handleNoMutexHeld(StringRef Kind, const NamedDecl *D,
+ ProtectedOperationKind POK, AccessKind AK,
+ SourceLocation Loc) {}
+
+ /// Warn when a protected operation occurs while the specific mutex protecting
+ /// the operation is not locked.
+ /// \param Kind -- the capability's name parameter (role, mutex, etc).
+ /// \param D -- The decl for the protected variable or function
+ /// \param POK -- The kind of protected operation (e.g. variable access)
+ /// \param LockName -- A StringRef name for the lock expression, to be printed
+ /// in the error message.
+ /// \param LK -- The kind of access (i.e. read or write) that occurred
+ /// \param Loc -- The location of the protected operation.
+ virtual void handleMutexNotHeld(StringRef Kind, const NamedDecl *D,
+ ProtectedOperationKind POK, Name LockName,
+ LockKind LK, SourceLocation Loc,
+ Name *PossibleMatch = nullptr) {}
+
+ /// Warn when acquiring a lock that the negative capability is not held.
+ /// \param Kind -- the capability's name parameter (role, mutex, etc).
+ /// \param LockName -- The name for the lock expression, to be printed in the
+ /// diagnostic.
+ /// \param Neg -- The name of the negative capability to be printed in the
+ /// diagnostic.
+ /// \param Loc -- The location of the protected operation.
+ virtual void handleNegativeNotHeld(StringRef Kind, Name LockName, Name Neg,
+ SourceLocation Loc) {}
+
+ /// Warn when a function is called while an excluded mutex is locked. For
+ /// example, the mutex may be locked inside the function.
+ /// \param Kind -- the capability's name parameter (role, mutex, etc).
+ /// \param FunName -- The name of the function
+ /// \param LockName -- A StringRef name for the lock expression, to be printed
+ /// in the error message.
+ /// \param Loc -- The location of the function call.
+ virtual void handleFunExcludesLock(StringRef Kind, Name FunName,
+ Name LockName, SourceLocation Loc) {}
+
+
+ /// Warn that L1 cannot be acquired before L2.
+ virtual void handleLockAcquiredBefore(StringRef Kind, Name L1Name,
+ Name L2Name, SourceLocation Loc) {}
+
+ /// Warn that there is a cycle in acquired_before/after dependencies.
+ virtual void handleBeforeAfterCycle(Name L1Name, SourceLocation Loc) {}
+
+ /// Called by the analysis when starting analysis of a function.
+ /// Used to issue suggestions for changes to annotations.
+ virtual void enterFunction(const FunctionDecl *FD) {}
+
+ /// Called by the analysis when finishing analysis of a function.
+ virtual void leaveFunction(const FunctionDecl *FD) {}
+
+ bool issueBetaWarnings() { return IssueBetaWarnings; }
+ void setIssueBetaWarnings(bool b) { IssueBetaWarnings = b; }
+
+private:
+ bool IssueBetaWarnings;
+};
+
+/// \brief Check a function's CFG for thread-safety violations.
+///
+/// We traverse the blocks in the CFG, compute the set of mutexes that are held
+/// at the end of each block, and issue warnings for thread safety violations.
+/// Each block in the CFG is traversed exactly once.
+void runThreadSafetyAnalysis(AnalysisDeclContext &AC,
+ ThreadSafetyHandler &Handler,
+ BeforeSet **Bset);
+
+void threadSafetyCleanup(BeforeSet *Cache);
+
+/// \brief Helper function that returns a LockKind required for the given level
+/// of access.
+LockKind getLockKindFromAccessKind(AccessKind AK);
+
+}} // end namespace clang::threadSafety
+#endif
diff --git a/contrib/llvm/tools/clang/include/clang/Analysis/Analyses/ThreadSafetyCommon.h b/contrib/llvm/tools/clang/include/clang/Analysis/Analyses/ThreadSafetyCommon.h
new file mode 100644
index 0000000..e357013
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Analysis/Analyses/ThreadSafetyCommon.h
@@ -0,0 +1,505 @@
+//===- ThreadSafetyCommon.h ------------------------------------*- C++ --*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// Parts of thread safety analysis that are not specific to thread safety
+// itself have been factored into classes here, where they can be potentially
+// used by other analyses. Currently these include:
+//
+// * Generalize clang CFG visitors.
+// * Conversion of the clang CFG to SSA form.
+// * Translation of clang Exprs to TIL SExprs
+//
+// UNDER CONSTRUCTION. USE AT YOUR OWN RISK.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_ANALYSIS_ANALYSES_THREADSAFETYCOMMON_H
+#define LLVM_CLANG_ANALYSIS_ANALYSES_THREADSAFETYCOMMON_H
+
+#include "clang/Analysis/Analyses/PostOrderCFGView.h"
+#include "clang/Analysis/Analyses/ThreadSafetyTIL.h"
+#include "clang/Analysis/Analyses/ThreadSafetyTraverse.h"
+#include "clang/Analysis/AnalysisContext.h"
+#include "clang/Basic/OperatorKinds.h"
+#include <memory>
+#include <ostream>
+#include <sstream>
+#include <vector>
+
+
+namespace clang {
+namespace threadSafety {
+
+
+// Various helper functions on til::SExpr
+namespace sx {
+
+inline bool equals(const til::SExpr *E1, const til::SExpr *E2) {
+ return til::EqualsComparator::compareExprs(E1, E2);
+}
+
+inline bool matches(const til::SExpr *E1, const til::SExpr *E2) {
+ // We treat a top-level wildcard as the "univsersal" lock.
+ // It matches everything for the purpose of checking locks, but not
+ // for unlocking them.
+ if (isa<til::Wildcard>(E1))
+ return isa<til::Wildcard>(E2);
+ if (isa<til::Wildcard>(E2))
+ return isa<til::Wildcard>(E1);
+
+ return til::MatchComparator::compareExprs(E1, E2);
+}
+
+inline bool partiallyMatches(const til::SExpr *E1, const til::SExpr *E2) {
+ const auto *PE1 = dyn_cast_or_null<til::Project>(E1);
+ if (!PE1)
+ return false;
+ const auto *PE2 = dyn_cast_or_null<til::Project>(E2);
+ if (!PE2)
+ return false;
+ return PE1->clangDecl() == PE2->clangDecl();
+}
+
+inline std::string toString(const til::SExpr *E) {
+ std::stringstream ss;
+ til::StdPrinter::print(E, ss);
+ return ss.str();
+}
+
+} // end namespace sx
+
+
+
+// This class defines the interface of a clang CFG Visitor.
+// CFGWalker will invoke the following methods.
+// Note that methods are not virtual; the visitor is templatized.
+class CFGVisitor {
+ // Enter the CFG for Decl D, and perform any initial setup operations.
+ void enterCFG(CFG *Cfg, const NamedDecl *D, const CFGBlock *First) {}
+
+ // Enter a CFGBlock.
+ void enterCFGBlock(const CFGBlock *B) {}
+
+ // Returns true if this visitor implements handlePredecessor
+ bool visitPredecessors() { return true; }
+
+ // Process a predecessor edge.
+ void handlePredecessor(const CFGBlock *Pred) {}
+
+ // Process a successor back edge to a previously visited block.
+ void handlePredecessorBackEdge(const CFGBlock *Pred) {}
+
+ // Called just before processing statements.
+ void enterCFGBlockBody(const CFGBlock *B) {}
+
+ // Process an ordinary statement.
+ void handleStatement(const Stmt *S) {}
+
+ // Process a destructor call
+ void handleDestructorCall(const VarDecl *VD, const CXXDestructorDecl *DD) {}
+
+ // Called after all statements have been handled.
+ void exitCFGBlockBody(const CFGBlock *B) {}
+
+ // Return true
+ bool visitSuccessors() { return true; }
+
+ // Process a successor edge.
+ void handleSuccessor(const CFGBlock *Succ) {}
+
+ // Process a successor back edge to a previously visited block.
+ void handleSuccessorBackEdge(const CFGBlock *Succ) {}
+
+ // Leave a CFGBlock.
+ void exitCFGBlock(const CFGBlock *B) {}
+
+ // Leave the CFG, and perform any final cleanup operations.
+ void exitCFG(const CFGBlock *Last) {}
+};
+
+
+// Walks the clang CFG, and invokes methods on a given CFGVisitor.
+class CFGWalker {
+public:
+ CFGWalker() : CFGraph(nullptr), ACtx(nullptr), SortedGraph(nullptr) {}
+
+ // Initialize the CFGWalker. This setup only needs to be done once, even
+ // if there are multiple passes over the CFG.
+ bool init(AnalysisDeclContext &AC) {
+ ACtx = &AC;
+ CFGraph = AC.getCFG();
+ if (!CFGraph)
+ return false;
+
+ // Ignore anonymous functions.
+ if (!dyn_cast_or_null<NamedDecl>(AC.getDecl()))
+ return false;
+
+ SortedGraph = AC.getAnalysis<PostOrderCFGView>();
+ if (!SortedGraph)
+ return false;
+
+ return true;
+ }
+
+ // Traverse the CFG, calling methods on V as appropriate.
+ template <class Visitor>
+ void walk(Visitor &V) {
+ PostOrderCFGView::CFGBlockSet VisitedBlocks(CFGraph);
+
+ V.enterCFG(CFGraph, getDecl(), &CFGraph->getEntry());
+
+ for (const auto *CurrBlock : *SortedGraph) {
+ VisitedBlocks.insert(CurrBlock);
+
+ V.enterCFGBlock(CurrBlock);
+
+ // Process predecessors, handling back edges last
+ if (V.visitPredecessors()) {
+ SmallVector<CFGBlock*, 4> BackEdges;
+ // Process successors
+ for (CFGBlock::const_pred_iterator SI = CurrBlock->pred_begin(),
+ SE = CurrBlock->pred_end();
+ SI != SE; ++SI) {
+ if (*SI == nullptr)
+ continue;
+
+ if (!VisitedBlocks.alreadySet(*SI)) {
+ BackEdges.push_back(*SI);
+ continue;
+ }
+ V.handlePredecessor(*SI);
+ }
+
+ for (auto *Blk : BackEdges)
+ V.handlePredecessorBackEdge(Blk);
+ }
+
+ V.enterCFGBlockBody(CurrBlock);
+
+ // Process statements
+ for (const auto &BI : *CurrBlock) {
+ switch (BI.getKind()) {
+ case CFGElement::Statement: {
+ V.handleStatement(BI.castAs<CFGStmt>().getStmt());
+ break;
+ }
+ case CFGElement::AutomaticObjectDtor: {
+ CFGAutomaticObjDtor AD = BI.castAs<CFGAutomaticObjDtor>();
+ CXXDestructorDecl *DD = const_cast<CXXDestructorDecl*>(
+ AD.getDestructorDecl(ACtx->getASTContext()));
+ VarDecl *VD = const_cast<VarDecl*>(AD.getVarDecl());
+ V.handleDestructorCall(VD, DD);
+ break;
+ }
+ default:
+ break;
+ }
+ }
+
+ V.exitCFGBlockBody(CurrBlock);
+
+ // Process successors, handling back edges first.
+ if (V.visitSuccessors()) {
+ SmallVector<CFGBlock*, 8> ForwardEdges;
+
+ // Process successors
+ for (CFGBlock::const_succ_iterator SI = CurrBlock->succ_begin(),
+ SE = CurrBlock->succ_end();
+ SI != SE; ++SI) {
+ if (*SI == nullptr)
+ continue;
+
+ if (!VisitedBlocks.alreadySet(*SI)) {
+ ForwardEdges.push_back(*SI);
+ continue;
+ }
+ V.handleSuccessorBackEdge(*SI);
+ }
+
+ for (auto *Blk : ForwardEdges)
+ V.handleSuccessor(Blk);
+ }
+
+ V.exitCFGBlock(CurrBlock);
+ }
+ V.exitCFG(&CFGraph->getExit());
+ }
+
+ const CFG *getGraph() const { return CFGraph; }
+ CFG *getGraph() { return CFGraph; }
+
+ const NamedDecl *getDecl() const {
+ return dyn_cast<NamedDecl>(ACtx->getDecl());
+ }
+
+ const PostOrderCFGView *getSortedGraph() const { return SortedGraph; }
+
+private:
+ CFG *CFGraph;
+ AnalysisDeclContext *ACtx;
+ PostOrderCFGView *SortedGraph;
+};
+
+
+
+
+class CapabilityExpr {
+ // TODO: move this back into ThreadSafety.cpp
+ // This is specific to thread safety. It is here because
+ // translateAttrExpr needs it, but that should be moved too.
+
+private:
+ const til::SExpr* CapExpr; ///< The capability expression.
+ bool Negated; ///< True if this is a negative capability
+
+public:
+ CapabilityExpr(const til::SExpr *E, bool Neg) : CapExpr(E), Negated(Neg) {}
+
+ const til::SExpr* sexpr() const { return CapExpr; }
+ bool negative() const { return Negated; }
+
+ CapabilityExpr operator!() const {
+ return CapabilityExpr(CapExpr, !Negated);
+ }
+
+ bool equals(const CapabilityExpr &other) const {
+ return (Negated == other.Negated) && sx::equals(CapExpr, other.CapExpr);
+ }
+
+ bool matches(const CapabilityExpr &other) const {
+ return (Negated == other.Negated) && sx::matches(CapExpr, other.CapExpr);
+ }
+
+ bool matchesUniv(const CapabilityExpr &CapE) const {
+ return isUniversal() || matches(CapE);
+ }
+
+ bool partiallyMatches(const CapabilityExpr &other) const {
+ return (Negated == other.Negated) &&
+ sx::partiallyMatches(CapExpr, other.CapExpr);
+ }
+
+ const ValueDecl* valueDecl() const {
+ if (Negated || CapExpr == nullptr)
+ return nullptr;
+ if (auto *P = dyn_cast<til::Project>(CapExpr))
+ return P->clangDecl();
+ if (auto *P = dyn_cast<til::LiteralPtr>(CapExpr))
+ return P->clangDecl();
+ return nullptr;
+ }
+
+ std::string toString() const {
+ if (Negated)
+ return "!" + sx::toString(CapExpr);
+ return sx::toString(CapExpr);
+ }
+
+ bool shouldIgnore() const { return CapExpr == nullptr; }
+
+ bool isInvalid() const { return sexpr() && isa<til::Undefined>(sexpr()); }
+
+ bool isUniversal() const { return sexpr() && isa<til::Wildcard>(sexpr()); }
+};
+
+
+
+// Translate clang::Expr to til::SExpr.
+class SExprBuilder {
+public:
+ /// \brief Encapsulates the lexical context of a function call. The lexical
+ /// context includes the arguments to the call, including the implicit object
+ /// argument. When an attribute containing a mutex expression is attached to
+ /// a method, the expression may refer to formal parameters of the method.
+ /// Actual arguments must be substituted for formal parameters to derive
+ /// the appropriate mutex expression in the lexical context where the function
+ /// is called. PrevCtx holds the context in which the arguments themselves
+ /// should be evaluated; multiple calling contexts can be chained together
+ /// by the lock_returned attribute.
+ struct CallingContext {
+ CallingContext *Prev; // The previous context; or 0 if none.
+ const NamedDecl *AttrDecl; // The decl to which the attr is attached.
+ const Expr *SelfArg; // Implicit object argument -- e.g. 'this'
+ unsigned NumArgs; // Number of funArgs
+ const Expr *const *FunArgs; // Function arguments
+ bool SelfArrow; // is Self referred to with -> or .?
+
+ CallingContext(CallingContext *P, const NamedDecl *D = nullptr)
+ : Prev(P), AttrDecl(D), SelfArg(nullptr),
+ NumArgs(0), FunArgs(nullptr), SelfArrow(false)
+ {}
+ };
+
+ SExprBuilder(til::MemRegionRef A)
+ : Arena(A), SelfVar(nullptr), Scfg(nullptr), CurrentBB(nullptr),
+ CurrentBlockInfo(nullptr) {
+ // FIXME: we don't always have a self-variable.
+ SelfVar = new (Arena) til::Variable(nullptr);
+ SelfVar->setKind(til::Variable::VK_SFun);
+ }
+
+ // Translate a clang expression in an attribute to a til::SExpr.
+ // Constructs the context from D, DeclExp, and SelfDecl.
+ CapabilityExpr translateAttrExpr(const Expr *AttrExp, const NamedDecl *D,
+ const Expr *DeclExp, VarDecl *SelfD=nullptr);
+
+ CapabilityExpr translateAttrExpr(const Expr *AttrExp, CallingContext *Ctx);
+
+ // Translate a clang statement or expression to a TIL expression.
+ // Also performs substitution of variables; Ctx provides the context.
+ // Dispatches on the type of S.
+ til::SExpr *translate(const Stmt *S, CallingContext *Ctx);
+ til::SCFG *buildCFG(CFGWalker &Walker);
+
+ til::SExpr *lookupStmt(const Stmt *S);
+
+ til::BasicBlock *lookupBlock(const CFGBlock *B) {
+ return BlockMap[B->getBlockID()];
+ }
+
+ const til::SCFG *getCFG() const { return Scfg; }
+ til::SCFG *getCFG() { return Scfg; }
+
+private:
+ til::SExpr *translateDeclRefExpr(const DeclRefExpr *DRE,
+ CallingContext *Ctx) ;
+ til::SExpr *translateCXXThisExpr(const CXXThisExpr *TE, CallingContext *Ctx);
+ til::SExpr *translateMemberExpr(const MemberExpr *ME, CallingContext *Ctx);
+ til::SExpr *translateCallExpr(const CallExpr *CE, CallingContext *Ctx,
+ const Expr *SelfE = nullptr);
+ til::SExpr *translateCXXMemberCallExpr(const CXXMemberCallExpr *ME,
+ CallingContext *Ctx);
+ til::SExpr *translateCXXOperatorCallExpr(const CXXOperatorCallExpr *OCE,
+ CallingContext *Ctx);
+ til::SExpr *translateUnaryOperator(const UnaryOperator *UO,
+ CallingContext *Ctx);
+ til::SExpr *translateBinOp(til::TIL_BinaryOpcode Op,
+ const BinaryOperator *BO,
+ CallingContext *Ctx, bool Reverse = false);
+ til::SExpr *translateBinAssign(til::TIL_BinaryOpcode Op,
+ const BinaryOperator *BO,
+ CallingContext *Ctx, bool Assign = false);
+ til::SExpr *translateBinaryOperator(const BinaryOperator *BO,
+ CallingContext *Ctx);
+ til::SExpr *translateCastExpr(const CastExpr *CE, CallingContext *Ctx);
+ til::SExpr *translateArraySubscriptExpr(const ArraySubscriptExpr *E,
+ CallingContext *Ctx);
+ til::SExpr *translateAbstractConditionalOperator(
+ const AbstractConditionalOperator *C, CallingContext *Ctx);
+
+ til::SExpr *translateDeclStmt(const DeclStmt *S, CallingContext *Ctx);
+
+ // Map from statements in the clang CFG to SExprs in the til::SCFG.
+ typedef llvm::DenseMap<const Stmt*, til::SExpr*> StatementMap;
+
+ // Map from clang local variables to indices in a LVarDefinitionMap.
+ typedef llvm::DenseMap<const ValueDecl *, unsigned> LVarIndexMap;
+
+ // Map from local variable indices to SSA variables (or constants).
+ typedef std::pair<const ValueDecl *, til::SExpr *> NameVarPair;
+ typedef CopyOnWriteVector<NameVarPair> LVarDefinitionMap;
+
+ struct BlockInfo {
+ LVarDefinitionMap ExitMap;
+ bool HasBackEdges;
+ unsigned UnprocessedSuccessors; // Successors yet to be processed
+ unsigned ProcessedPredecessors; // Predecessors already processed
+
+ BlockInfo()
+ : HasBackEdges(false), UnprocessedSuccessors(0),
+ ProcessedPredecessors(0) {}
+ BlockInfo(BlockInfo &&RHS)
+ : ExitMap(std::move(RHS.ExitMap)),
+ HasBackEdges(RHS.HasBackEdges),
+ UnprocessedSuccessors(RHS.UnprocessedSuccessors),
+ ProcessedPredecessors(RHS.ProcessedPredecessors) {}
+
+ BlockInfo &operator=(BlockInfo &&RHS) {
+ if (this != &RHS) {
+ ExitMap = std::move(RHS.ExitMap);
+ HasBackEdges = RHS.HasBackEdges;
+ UnprocessedSuccessors = RHS.UnprocessedSuccessors;
+ ProcessedPredecessors = RHS.ProcessedPredecessors;
+ }
+ return *this;
+ }
+
+ private:
+ BlockInfo(const BlockInfo &) = delete;
+ void operator=(const BlockInfo &) = delete;
+ };
+
+ // We implement the CFGVisitor API
+ friend class CFGWalker;
+
+ void enterCFG(CFG *Cfg, const NamedDecl *D, const CFGBlock *First);
+ void enterCFGBlock(const CFGBlock *B);
+ bool visitPredecessors() { return true; }
+ void handlePredecessor(const CFGBlock *Pred);
+ void handlePredecessorBackEdge(const CFGBlock *Pred);
+ void enterCFGBlockBody(const CFGBlock *B);
+ void handleStatement(const Stmt *S);
+ void handleDestructorCall(const VarDecl *VD, const CXXDestructorDecl *DD);
+ void exitCFGBlockBody(const CFGBlock *B);
+ bool visitSuccessors() { return true; }
+ void handleSuccessor(const CFGBlock *Succ);
+ void handleSuccessorBackEdge(const CFGBlock *Succ);
+ void exitCFGBlock(const CFGBlock *B);
+ void exitCFG(const CFGBlock *Last);
+
+ void insertStmt(const Stmt *S, til::SExpr *E) {
+ SMap.insert(std::make_pair(S, E));
+ }
+ til::SExpr *getCurrentLVarDefinition(const ValueDecl *VD);
+
+ til::SExpr *addStatement(til::SExpr *E, const Stmt *S,
+ const ValueDecl *VD = nullptr);
+ til::SExpr *lookupVarDecl(const ValueDecl *VD);
+ til::SExpr *addVarDecl(const ValueDecl *VD, til::SExpr *E);
+ til::SExpr *updateVarDecl(const ValueDecl *VD, til::SExpr *E);
+
+ void makePhiNodeVar(unsigned i, unsigned NPreds, til::SExpr *E);
+ void mergeEntryMap(LVarDefinitionMap Map);
+ void mergeEntryMapBackEdge();
+ void mergePhiNodesBackEdge(const CFGBlock *Blk);
+
+private:
+ // Set to true when parsing capability expressions, which get translated
+ // inaccurately in order to hack around smart pointers etc.
+ static const bool CapabilityExprMode = true;
+
+ til::MemRegionRef Arena;
+ til::Variable *SelfVar; // Variable to use for 'this'. May be null.
+
+ til::SCFG *Scfg;
+ StatementMap SMap; // Map from Stmt to TIL Variables
+ LVarIndexMap LVarIdxMap; // Indices of clang local vars.
+ std::vector<til::BasicBlock *> BlockMap; // Map from clang to til BBs.
+ std::vector<BlockInfo> BBInfo; // Extra information per BB.
+ // Indexed by clang BlockID.
+
+ LVarDefinitionMap CurrentLVarMap;
+ std::vector<til::Phi*> CurrentArguments;
+ std::vector<til::SExpr*> CurrentInstructions;
+ std::vector<til::Phi*> IncompleteArgs;
+ til::BasicBlock *CurrentBB;
+ BlockInfo *CurrentBlockInfo;
+};
+
+
+// Dump an SCFG to llvm::errs().
+void printSCFG(CFGWalker &Walker);
+
+
+} // end namespace threadSafety
+
+} // end namespace clang
+
+#endif // LLVM_CLANG_THREAD_SAFETY_COMMON_H
diff --git a/contrib/llvm/tools/clang/include/clang/Analysis/Analyses/ThreadSafetyLogical.h b/contrib/llvm/tools/clang/include/clang/Analysis/Analyses/ThreadSafetyLogical.h
new file mode 100644
index 0000000..bc78021
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Analysis/Analyses/ThreadSafetyLogical.h
@@ -0,0 +1,108 @@
+//===- ThreadSafetyLogical.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 a representation for logical expressions with SExpr leaves
+// that are used as part of fact-checking capability expressions.
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_ANALYSIS_ANALYSES_THREADSAFETYLOGICAL_H
+#define LLVM_CLANG_ANALYSIS_ANALYSES_THREADSAFETYLOGICAL_H
+
+#include "clang/Analysis/Analyses/ThreadSafetyTIL.h"
+
+namespace clang {
+namespace threadSafety {
+namespace lexpr {
+
+class LExpr {
+public:
+ enum Opcode {
+ Terminal,
+ And,
+ Or,
+ Not
+ };
+ Opcode kind() const { return Kind; }
+
+ /// \brief Logical implication. Returns true if the LExpr implies RHS, i.e. if
+ /// the LExpr holds, then RHS must hold. For example, (A & B) implies A.
+ inline bool implies(const LExpr *RHS) const;
+
+protected:
+ LExpr(Opcode Kind) : Kind(Kind) {}
+
+private:
+ Opcode Kind;
+};
+
+class Terminal : public LExpr {
+ til::SExpr *Expr;
+
+public:
+ Terminal(til::SExpr *Expr) : LExpr(LExpr::Terminal), Expr(Expr) {}
+
+ const til::SExpr *expr() const { return Expr; }
+ til::SExpr *expr() { return Expr; }
+
+ static bool classof(const LExpr *E) { return E->kind() == LExpr::Terminal; }
+};
+
+class BinOp : public LExpr {
+ LExpr *LHS, *RHS;
+
+protected:
+ BinOp(LExpr *LHS, LExpr *RHS, Opcode Code) : LExpr(Code), LHS(LHS), RHS(RHS) {}
+
+public:
+ const LExpr *left() const { return LHS; }
+ LExpr *left() { return LHS; }
+
+ const LExpr *right() const { return RHS; }
+ LExpr *right() { return RHS; }
+};
+
+class And : public BinOp {
+public:
+ And(LExpr *LHS, LExpr *RHS) : BinOp(LHS, RHS, LExpr::And) {}
+
+ static bool classof(const LExpr *E) { return E->kind() == LExpr::And; }
+};
+
+class Or : public BinOp {
+public:
+ Or(LExpr *LHS, LExpr *RHS) : BinOp(LHS, RHS, LExpr::Or) {}
+
+ static bool classof(const LExpr *E) { return E->kind() == LExpr::Or; }
+};
+
+class Not : public LExpr {
+ LExpr *Exp;
+
+public:
+ Not(LExpr *Exp) : LExpr(LExpr::Not), Exp(Exp) {}
+
+ const LExpr *exp() const { return Exp; }
+ LExpr *exp() { return Exp; }
+
+ static bool classof(const LExpr *E) { return E->kind() == LExpr::Not; }
+};
+
+/// \brief Logical implication. Returns true if LHS implies RHS, i.e. if LHS
+/// holds, then RHS must hold. For example, (A & B) implies A.
+bool implies(const LExpr *LHS, const LExpr *RHS);
+
+bool LExpr::implies(const LExpr *RHS) const {
+ return lexpr::implies(this, RHS);
+}
+
+}
+}
+}
+
+#endif
+
diff --git a/contrib/llvm/tools/clang/include/clang/Analysis/Analyses/ThreadSafetyOps.def b/contrib/llvm/tools/clang/include/clang/Analysis/Analyses/ThreadSafetyOps.def
new file mode 100644
index 0000000..0d2458b
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Analysis/Analyses/ThreadSafetyOps.def
@@ -0,0 +1,57 @@
+//===- ThreadSafetyTIL.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 list of core opcodes for the Thread Safety
+// Typed Intermediate language. Please see ThreadSafetyTIL.h for more
+// information.
+//
+//===----------------------------------------------------------------------===//
+
+
+TIL_OPCODE_DEF(Future)
+TIL_OPCODE_DEF(Undefined)
+TIL_OPCODE_DEF(Wildcard)
+
+TIL_OPCODE_DEF(Literal)
+TIL_OPCODE_DEF(LiteralPtr)
+TIL_OPCODE_DEF(Variable)
+TIL_OPCODE_DEF(Function)
+TIL_OPCODE_DEF(SFunction)
+TIL_OPCODE_DEF(Code)
+TIL_OPCODE_DEF(Field)
+
+TIL_OPCODE_DEF(Apply)
+TIL_OPCODE_DEF(SApply)
+TIL_OPCODE_DEF(Project)
+
+TIL_OPCODE_DEF(Call)
+TIL_OPCODE_DEF(Alloc)
+TIL_OPCODE_DEF(Load)
+TIL_OPCODE_DEF(Store)
+TIL_OPCODE_DEF(ArrayIndex)
+TIL_OPCODE_DEF(ArrayAdd)
+
+TIL_OPCODE_DEF(UnaryOp)
+TIL_OPCODE_DEF(BinaryOp)
+TIL_OPCODE_DEF(Cast)
+
+TIL_OPCODE_DEF(SCFG)
+TIL_OPCODE_DEF(BasicBlock)
+TIL_OPCODE_DEF(Phi)
+
+// Terminator instructions
+TIL_OPCODE_DEF(Goto)
+TIL_OPCODE_DEF(Branch)
+TIL_OPCODE_DEF(Return)
+
+// pseudo-terms
+TIL_OPCODE_DEF(Identifier)
+TIL_OPCODE_DEF(IfThenElse)
+TIL_OPCODE_DEF(Let)
+
diff --git a/contrib/llvm/tools/clang/include/clang/Analysis/Analyses/ThreadSafetyTIL.h b/contrib/llvm/tools/clang/include/clang/Analysis/Analyses/ThreadSafetyTIL.h
new file mode 100644
index 0000000..be8a710
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Analysis/Analyses/ThreadSafetyTIL.h
@@ -0,0 +1,1918 @@
+//===- ThreadSafetyTIL.h ---------------------------------------*- C++ --*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT in the llvm repository for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines a simple Typed Intermediate Language, or TIL, that is used
+// by the thread safety analysis (See ThreadSafety.cpp). The TIL is intended
+// to be largely independent of clang, in the hope that the analysis can be
+// reused for other non-C++ languages. All dependencies on clang/llvm should
+// go in ThreadSafetyUtil.h.
+//
+// Thread safety analysis works by comparing mutex expressions, e.g.
+//
+// class A { Mutex mu; int dat GUARDED_BY(this->mu); }
+// class B { A a; }
+//
+// void foo(B* b) {
+// (*b).a.mu.lock(); // locks (*b).a.mu
+// b->a.dat = 0; // substitute &b->a for 'this';
+// // requires lock on (&b->a)->mu
+// (b->a.mu).unlock(); // unlocks (b->a.mu)
+// }
+//
+// As illustrated by the above example, clang Exprs are not well-suited to
+// represent mutex expressions directly, since there is no easy way to compare
+// Exprs for equivalence. The thread safety analysis thus lowers clang Exprs
+// into a simple intermediate language (IL). The IL supports:
+//
+// (1) comparisons for semantic equality of expressions
+// (2) SSA renaming of variables
+// (3) wildcards and pattern matching over expressions
+// (4) hash-based expression lookup
+//
+// The TIL is currently very experimental, is intended only for use within
+// the thread safety analysis, and is subject to change without notice.
+// After the API stabilizes and matures, it may be appropriate to make this
+// more generally available to other analyses.
+//
+// UNDER CONSTRUCTION. USE AT YOUR OWN RISK.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_ANALYSIS_ANALYSES_THREADSAFETYTIL_H
+#define LLVM_CLANG_ANALYSIS_ANALYSES_THREADSAFETYTIL_H
+
+// All clang include dependencies for this file must be put in
+// ThreadSafetyUtil.h.
+#include "ThreadSafetyUtil.h"
+#include <algorithm>
+#include <cassert>
+#include <cstddef>
+#include <stdint.h>
+#include <utility>
+
+
+namespace clang {
+namespace threadSafety {
+namespace til {
+
+
+/// Enum for the different distinct classes of SExpr
+enum TIL_Opcode {
+#define TIL_OPCODE_DEF(X) COP_##X,
+#include "ThreadSafetyOps.def"
+#undef TIL_OPCODE_DEF
+};
+
+/// Opcode for unary arithmetic operations.
+enum TIL_UnaryOpcode : unsigned char {
+ UOP_Minus, // -
+ UOP_BitNot, // ~
+ UOP_LogicNot // !
+};
+
+/// Opcode for binary arithmetic operations.
+enum TIL_BinaryOpcode : unsigned char {
+ BOP_Add, // +
+ BOP_Sub, // -
+ BOP_Mul, // *
+ BOP_Div, // /
+ BOP_Rem, // %
+ BOP_Shl, // <<
+ BOP_Shr, // >>
+ BOP_BitAnd, // &
+ BOP_BitXor, // ^
+ BOP_BitOr, // |
+ BOP_Eq, // ==
+ BOP_Neq, // !=
+ BOP_Lt, // <
+ BOP_Leq, // <=
+ BOP_LogicAnd, // && (no short-circuit)
+ BOP_LogicOr // || (no short-circuit)
+};
+
+/// Opcode for cast operations.
+enum TIL_CastOpcode : unsigned char {
+ CAST_none = 0,
+ CAST_extendNum, // extend precision of numeric type
+ CAST_truncNum, // truncate precision of numeric type
+ CAST_toFloat, // convert to floating point type
+ CAST_toInt, // convert to integer type
+ CAST_objToPtr // convert smart pointer to pointer (C++ only)
+};
+
+const TIL_Opcode COP_Min = COP_Future;
+const TIL_Opcode COP_Max = COP_Branch;
+const TIL_UnaryOpcode UOP_Min = UOP_Minus;
+const TIL_UnaryOpcode UOP_Max = UOP_LogicNot;
+const TIL_BinaryOpcode BOP_Min = BOP_Add;
+const TIL_BinaryOpcode BOP_Max = BOP_LogicOr;
+const TIL_CastOpcode CAST_Min = CAST_none;
+const TIL_CastOpcode CAST_Max = CAST_toInt;
+
+/// Return the name of a unary opcode.
+StringRef getUnaryOpcodeString(TIL_UnaryOpcode Op);
+
+/// Return the name of a binary opcode.
+StringRef getBinaryOpcodeString(TIL_BinaryOpcode Op);
+
+
+/// ValueTypes are data types that can actually be held in registers.
+/// All variables and expressions must have a value type.
+/// Pointer types are further subdivided into the various heap-allocated
+/// types, such as functions, records, etc.
+/// Structured types that are passed by value (e.g. complex numbers)
+/// require special handling; they use BT_ValueRef, and size ST_0.
+struct ValueType {
+ enum BaseType : unsigned char {
+ BT_Void = 0,
+ BT_Bool,
+ BT_Int,
+ BT_Float,
+ BT_String, // String literals
+ BT_Pointer,
+ BT_ValueRef
+ };
+
+ enum SizeType : unsigned char {
+ ST_0 = 0,
+ ST_1,
+ ST_8,
+ ST_16,
+ ST_32,
+ ST_64,
+ ST_128
+ };
+
+ inline static SizeType getSizeType(unsigned nbytes);
+
+ template <class T>
+ inline static ValueType getValueType();
+
+ ValueType(BaseType B, SizeType Sz, bool S, unsigned char VS)
+ : Base(B), Size(Sz), Signed(S), VectSize(VS)
+ { }
+
+ BaseType Base;
+ SizeType Size;
+ bool Signed;
+ unsigned char VectSize; // 0 for scalar, otherwise num elements in vector
+};
+
+
+inline ValueType::SizeType ValueType::getSizeType(unsigned nbytes) {
+ switch (nbytes) {
+ case 1: return ST_8;
+ case 2: return ST_16;
+ case 4: return ST_32;
+ case 8: return ST_64;
+ case 16: return ST_128;
+ default: return ST_0;
+ }
+}
+
+
+template<>
+inline ValueType ValueType::getValueType<void>() {
+ return ValueType(BT_Void, ST_0, false, 0);
+}
+
+template<>
+inline ValueType ValueType::getValueType<bool>() {
+ return ValueType(BT_Bool, ST_1, false, 0);
+}
+
+template<>
+inline ValueType ValueType::getValueType<int8_t>() {
+ return ValueType(BT_Int, ST_8, true, 0);
+}
+
+template<>
+inline ValueType ValueType::getValueType<uint8_t>() {
+ return ValueType(BT_Int, ST_8, false, 0);
+}
+
+template<>
+inline ValueType ValueType::getValueType<int16_t>() {
+ return ValueType(BT_Int, ST_16, true, 0);
+}
+
+template<>
+inline ValueType ValueType::getValueType<uint16_t>() {
+ return ValueType(BT_Int, ST_16, false, 0);
+}
+
+template<>
+inline ValueType ValueType::getValueType<int32_t>() {
+ return ValueType(BT_Int, ST_32, true, 0);
+}
+
+template<>
+inline ValueType ValueType::getValueType<uint32_t>() {
+ return ValueType(BT_Int, ST_32, false, 0);
+}
+
+template<>
+inline ValueType ValueType::getValueType<int64_t>() {
+ return ValueType(BT_Int, ST_64, true, 0);
+}
+
+template<>
+inline ValueType ValueType::getValueType<uint64_t>() {
+ return ValueType(BT_Int, ST_64, false, 0);
+}
+
+template<>
+inline ValueType ValueType::getValueType<float>() {
+ return ValueType(BT_Float, ST_32, true, 0);
+}
+
+template<>
+inline ValueType ValueType::getValueType<double>() {
+ return ValueType(BT_Float, ST_64, true, 0);
+}
+
+template<>
+inline ValueType ValueType::getValueType<long double>() {
+ return ValueType(BT_Float, ST_128, true, 0);
+}
+
+template<>
+inline ValueType ValueType::getValueType<StringRef>() {
+ return ValueType(BT_String, getSizeType(sizeof(StringRef)), false, 0);
+}
+
+template<>
+inline ValueType ValueType::getValueType<void*>() {
+ return ValueType(BT_Pointer, getSizeType(sizeof(void*)), false, 0);
+}
+
+
+class BasicBlock;
+
+
+/// Base class for AST nodes in the typed intermediate language.
+class SExpr {
+public:
+ TIL_Opcode opcode() const { return static_cast<TIL_Opcode>(Opcode); }
+
+ // Subclasses of SExpr must define the following:
+ //
+ // This(const This& E, ...) {
+ // copy constructor: construct copy of E, with some additional arguments.
+ // }
+ //
+ // template <class V>
+ // typename V::R_SExpr traverse(V &Vs, typename V::R_Ctx Ctx) {
+ // traverse all subexpressions, following the traversal/rewriter interface.
+ // }
+ //
+ // template <class C> typename C::CType compare(CType* E, C& Cmp) {
+ // compare all subexpressions, following the comparator interface
+ // }
+ void *operator new(size_t S, MemRegionRef &R) {
+ return ::operator new(S, R);
+ }
+
+ /// SExpr objects cannot be deleted.
+ // This declaration is public to workaround a gcc bug that breaks building
+ // with REQUIRES_EH=1.
+ void operator delete(void *) = delete;
+
+ /// Returns the instruction ID for this expression.
+ /// All basic block instructions have a unique ID (i.e. virtual register).
+ unsigned id() const { return SExprID; }
+
+ /// Returns the block, if this is an instruction in a basic block,
+ /// otherwise returns null.
+ BasicBlock* block() const { return Block; }
+
+ /// Set the basic block and instruction ID for this expression.
+ void setID(BasicBlock *B, unsigned id) { Block = B; SExprID = id; }
+
+protected:
+ SExpr(TIL_Opcode Op)
+ : Opcode(Op), Reserved(0), Flags(0), SExprID(0), Block(nullptr) {}
+ SExpr(const SExpr &E)
+ : Opcode(E.Opcode), Reserved(0), Flags(E.Flags), SExprID(0),
+ Block(nullptr) {}
+
+ const unsigned char Opcode;
+ unsigned char Reserved;
+ unsigned short Flags;
+ unsigned SExprID;
+ BasicBlock* Block;
+
+private:
+ SExpr() = delete;
+
+ /// SExpr objects must be created in an arena.
+ void *operator new(size_t) = delete;
+};
+
+
+// Contains various helper functions for SExprs.
+namespace ThreadSafetyTIL {
+ inline bool isTrivial(const SExpr *E) {
+ unsigned Op = E->opcode();
+ return Op == COP_Variable || Op == COP_Literal || Op == COP_LiteralPtr;
+ }
+}
+
+// Nodes which declare variables
+class Function;
+class SFunction;
+class Let;
+
+
+/// A named variable, e.g. "x".
+///
+/// There are two distinct places in which a Variable can appear in the AST.
+/// A variable declaration introduces a new variable, and can occur in 3 places:
+/// Let-expressions: (Let (x = t) u)
+/// Functions: (Function (x : t) u)
+/// Self-applicable functions (SFunction (x) t)
+///
+/// If a variable occurs in any other location, it is a reference to an existing
+/// variable declaration -- e.g. 'x' in (x * y + z). To save space, we don't
+/// allocate a separate AST node for variable references; a reference is just a
+/// pointer to the original declaration.
+class Variable : public SExpr {
+public:
+ static bool classof(const SExpr *E) { return E->opcode() == COP_Variable; }
+
+ enum VariableKind {
+ VK_Let, ///< Let-variable
+ VK_Fun, ///< Function parameter
+ VK_SFun ///< SFunction (self) parameter
+ };
+
+ Variable(StringRef s, SExpr *D = nullptr)
+ : SExpr(COP_Variable), Name(s), Definition(D), Cvdecl(nullptr) {
+ Flags = VK_Let;
+ }
+ Variable(SExpr *D, const clang::ValueDecl *Cvd = nullptr)
+ : SExpr(COP_Variable), Name(Cvd ? Cvd->getName() : "_x"),
+ Definition(D), Cvdecl(Cvd) {
+ Flags = VK_Let;
+ }
+ Variable(const Variable &Vd, SExpr *D) // rewrite constructor
+ : SExpr(Vd), Name(Vd.Name), Definition(D), Cvdecl(Vd.Cvdecl) {
+ Flags = Vd.kind();
+ }
+
+ /// Return the kind of variable (let, function param, or self)
+ VariableKind kind() const { return static_cast<VariableKind>(Flags); }
+
+ /// Return the name of the variable, if any.
+ StringRef name() const { return Name; }
+
+ /// Return the clang declaration for this variable, if any.
+ const clang::ValueDecl *clangDecl() const { return Cvdecl; }
+
+ /// Return the definition of the variable.
+ /// For let-vars, this is the setting expression.
+ /// For function and self parameters, it is the type of the variable.
+ SExpr *definition() { return Definition; }
+ const SExpr *definition() const { return Definition; }
+
+ void setName(StringRef S) { Name = S; }
+ void setKind(VariableKind K) { Flags = K; }
+ void setDefinition(SExpr *E) { Definition = E; }
+ void setClangDecl(const clang::ValueDecl *VD) { Cvdecl = VD; }
+
+ template <class V>
+ typename V::R_SExpr traverse(V &Vs, typename V::R_Ctx Ctx) {
+ // This routine is only called for variable references.
+ return Vs.reduceVariableRef(this);
+ }
+
+ template <class C>
+ typename C::CType compare(const Variable* E, C& Cmp) const {
+ return Cmp.compareVariableRefs(this, E);
+ }
+
+private:
+ friend class Function;
+ friend class SFunction;
+ friend class BasicBlock;
+ friend class Let;
+
+ StringRef Name; // The name of the variable.
+ SExpr* Definition; // The TIL type or definition
+ const clang::ValueDecl *Cvdecl; // The clang declaration for this variable.
+};
+
+
+/// Placeholder for an expression that has not yet been created.
+/// Used to implement lazy copy and rewriting strategies.
+class Future : public SExpr {
+public:
+ static bool classof(const SExpr *E) { return E->opcode() == COP_Future; }
+
+ enum FutureStatus {
+ FS_pending,
+ FS_evaluating,
+ FS_done
+ };
+
+ Future() : SExpr(COP_Future), Status(FS_pending), Result(nullptr) {}
+
+private:
+ virtual ~Future() = delete;
+
+public:
+ // A lazy rewriting strategy should subclass Future and override this method.
+ virtual SExpr *compute() { return nullptr; }
+
+ // Return the result of this future if it exists, otherwise return null.
+ SExpr *maybeGetResult() const {
+ return Result;
+ }
+
+ // Return the result of this future; forcing it if necessary.
+ SExpr *result() {
+ switch (Status) {
+ case FS_pending:
+ return force();
+ case FS_evaluating:
+ return nullptr; // infinite loop; illegal recursion.
+ case FS_done:
+ return Result;
+ }
+ }
+
+ template <class V>
+ typename V::R_SExpr traverse(V &Vs, typename V::R_Ctx Ctx) {
+ assert(Result && "Cannot traverse Future that has not been forced.");
+ return Vs.traverse(Result, Ctx);
+ }
+
+ template <class C>
+ typename C::CType compare(const Future* E, C& Cmp) const {
+ if (!Result || !E->Result)
+ return Cmp.comparePointers(this, E);
+ return Cmp.compare(Result, E->Result);
+ }
+
+private:
+ SExpr* force();
+
+ FutureStatus Status;
+ SExpr *Result;
+};
+
+
+/// Placeholder for expressions that cannot be represented in the TIL.
+class Undefined : public SExpr {
+public:
+ static bool classof(const SExpr *E) { return E->opcode() == COP_Undefined; }
+
+ Undefined(const clang::Stmt *S = nullptr) : SExpr(COP_Undefined), Cstmt(S) {}
+ Undefined(const Undefined &U) : SExpr(U), Cstmt(U.Cstmt) {}
+
+ template <class V>
+ typename V::R_SExpr traverse(V &Vs, typename V::R_Ctx Ctx) {
+ return Vs.reduceUndefined(*this);
+ }
+
+ template <class C>
+ typename C::CType compare(const Undefined* E, C& Cmp) const {
+ return Cmp.trueResult();
+ }
+
+private:
+ const clang::Stmt *Cstmt;
+};
+
+
+/// Placeholder for a wildcard that matches any other expression.
+class Wildcard : public SExpr {
+public:
+ static bool classof(const SExpr *E) { return E->opcode() == COP_Wildcard; }
+
+ Wildcard() : SExpr(COP_Wildcard) {}
+ Wildcard(const Wildcard &W) : SExpr(W) {}
+
+ template <class V> typename V::R_SExpr traverse(V &Vs, typename V::R_Ctx Ctx) {
+ return Vs.reduceWildcard(*this);
+ }
+
+ template <class C>
+ typename C::CType compare(const Wildcard* E, C& Cmp) const {
+ return Cmp.trueResult();
+ }
+};
+
+
+template <class T> class LiteralT;
+
+// Base class for literal values.
+class Literal : public SExpr {
+public:
+ static bool classof(const SExpr *E) { return E->opcode() == COP_Literal; }
+
+ Literal(const clang::Expr *C)
+ : SExpr(COP_Literal), ValType(ValueType::getValueType<void>()), Cexpr(C)
+ { }
+ Literal(ValueType VT) : SExpr(COP_Literal), ValType(VT), Cexpr(nullptr) {}
+ Literal(const Literal &L) : SExpr(L), ValType(L.ValType), Cexpr(L.Cexpr) {}
+
+ // The clang expression for this literal.
+ const clang::Expr *clangExpr() const { return Cexpr; }
+
+ ValueType valueType() const { return ValType; }
+
+ template<class T> const LiteralT<T>& as() const {
+ return *static_cast<const LiteralT<T>*>(this);
+ }
+ template<class T> LiteralT<T>& as() {
+ return *static_cast<LiteralT<T>*>(this);
+ }
+
+ template <class V> typename V::R_SExpr traverse(V &Vs, typename V::R_Ctx Ctx);
+
+ template <class C>
+ typename C::CType compare(const Literal* E, C& Cmp) const {
+ // TODO: defer actual comparison to LiteralT
+ return Cmp.trueResult();
+ }
+
+private:
+ const ValueType ValType;
+ const clang::Expr *Cexpr;
+};
+
+
+// Derived class for literal values, which stores the actual value.
+template<class T>
+class LiteralT : public Literal {
+public:
+ LiteralT(T Dat) : Literal(ValueType::getValueType<T>()), Val(Dat) { }
+ LiteralT(const LiteralT<T> &L) : Literal(L), Val(L.Val) { }
+
+ T value() const { return Val;}
+ T& value() { return Val; }
+
+private:
+ T Val;
+};
+
+
+
+template <class V>
+typename V::R_SExpr Literal::traverse(V &Vs, typename V::R_Ctx Ctx) {
+ if (Cexpr)
+ return Vs.reduceLiteral(*this);
+
+ switch (ValType.Base) {
+ case ValueType::BT_Void:
+ break;
+ case ValueType::BT_Bool:
+ return Vs.reduceLiteralT(as<bool>());
+ case ValueType::BT_Int: {
+ switch (ValType.Size) {
+ case ValueType::ST_8:
+ if (ValType.Signed)
+ return Vs.reduceLiteralT(as<int8_t>());
+ else
+ return Vs.reduceLiteralT(as<uint8_t>());
+ case ValueType::ST_16:
+ if (ValType.Signed)
+ return Vs.reduceLiteralT(as<int16_t>());
+ else
+ return Vs.reduceLiteralT(as<uint16_t>());
+ case ValueType::ST_32:
+ if (ValType.Signed)
+ return Vs.reduceLiteralT(as<int32_t>());
+ else
+ return Vs.reduceLiteralT(as<uint32_t>());
+ case ValueType::ST_64:
+ if (ValType.Signed)
+ return Vs.reduceLiteralT(as<int64_t>());
+ else
+ return Vs.reduceLiteralT(as<uint64_t>());
+ default:
+ break;
+ }
+ }
+ case ValueType::BT_Float: {
+ switch (ValType.Size) {
+ case ValueType::ST_32:
+ return Vs.reduceLiteralT(as<float>());
+ case ValueType::ST_64:
+ return Vs.reduceLiteralT(as<double>());
+ default:
+ break;
+ }
+ }
+ case ValueType::BT_String:
+ return Vs.reduceLiteralT(as<StringRef>());
+ case ValueType::BT_Pointer:
+ return Vs.reduceLiteralT(as<void*>());
+ case ValueType::BT_ValueRef:
+ break;
+ }
+ return Vs.reduceLiteral(*this);
+}
+
+
+/// A Literal pointer to an object allocated in memory.
+/// At compile time, pointer literals are represented by symbolic names.
+class LiteralPtr : public SExpr {
+public:
+ static bool classof(const SExpr *E) { return E->opcode() == COP_LiteralPtr; }
+
+ LiteralPtr(const clang::ValueDecl *D) : SExpr(COP_LiteralPtr), Cvdecl(D) {}
+ LiteralPtr(const LiteralPtr &R) : SExpr(R), Cvdecl(R.Cvdecl) {}
+
+ // The clang declaration for the value that this pointer points to.
+ const clang::ValueDecl *clangDecl() const { return Cvdecl; }
+
+ template <class V>
+ typename V::R_SExpr traverse(V &Vs, typename V::R_Ctx Ctx) {
+ return Vs.reduceLiteralPtr(*this);
+ }
+
+ template <class C>
+ typename C::CType compare(const LiteralPtr* E, C& Cmp) const {
+ return Cmp.comparePointers(Cvdecl, E->Cvdecl);
+ }
+
+private:
+ const clang::ValueDecl *Cvdecl;
+};
+
+
+/// A function -- a.k.a. lambda abstraction.
+/// Functions with multiple arguments are created by currying,
+/// e.g. (Function (x: Int) (Function (y: Int) (Code { return x + y })))
+class Function : public SExpr {
+public:
+ static bool classof(const SExpr *E) { return E->opcode() == COP_Function; }
+
+ Function(Variable *Vd, SExpr *Bd)
+ : SExpr(COP_Function), VarDecl(Vd), Body(Bd) {
+ Vd->setKind(Variable::VK_Fun);
+ }
+ Function(const Function &F, Variable *Vd, SExpr *Bd) // rewrite constructor
+ : SExpr(F), VarDecl(Vd), Body(Bd) {
+ Vd->setKind(Variable::VK_Fun);
+ }
+
+ Variable *variableDecl() { return VarDecl; }
+ const Variable *variableDecl() const { return VarDecl; }
+
+ SExpr *body() { return Body; }
+ const SExpr *body() const { return Body; }
+
+ template <class V>
+ typename V::R_SExpr traverse(V &Vs, typename V::R_Ctx Ctx) {
+ // This is a variable declaration, so traverse the definition.
+ auto E0 = Vs.traverse(VarDecl->Definition, Vs.typeCtx(Ctx));
+ // Tell the rewriter to enter the scope of the function.
+ Variable *Nvd = Vs.enterScope(*VarDecl, E0);
+ auto E1 = Vs.traverse(Body, Vs.declCtx(Ctx));
+ Vs.exitScope(*VarDecl);
+ return Vs.reduceFunction(*this, Nvd, E1);
+ }
+
+ template <class C>
+ typename C::CType compare(const Function* E, C& Cmp) const {
+ typename C::CType Ct =
+ Cmp.compare(VarDecl->definition(), E->VarDecl->definition());
+ if (Cmp.notTrue(Ct))
+ return Ct;
+ Cmp.enterScope(variableDecl(), E->variableDecl());
+ Ct = Cmp.compare(body(), E->body());
+ Cmp.leaveScope();
+ return Ct;
+ }
+
+private:
+ Variable *VarDecl;
+ SExpr* Body;
+};
+
+
+/// A self-applicable function.
+/// A self-applicable function can be applied to itself. It's useful for
+/// implementing objects and late binding.
+class SFunction : public SExpr {
+public:
+ static bool classof(const SExpr *E) { return E->opcode() == COP_SFunction; }
+
+ SFunction(Variable *Vd, SExpr *B)
+ : SExpr(COP_SFunction), VarDecl(Vd), Body(B) {
+ assert(Vd->Definition == nullptr);
+ Vd->setKind(Variable::VK_SFun);
+ Vd->Definition = this;
+ }
+ SFunction(const SFunction &F, Variable *Vd, SExpr *B) // rewrite constructor
+ : SExpr(F), VarDecl(Vd), Body(B) {
+ assert(Vd->Definition == nullptr);
+ Vd->setKind(Variable::VK_SFun);
+ Vd->Definition = this;
+ }
+
+ Variable *variableDecl() { return VarDecl; }
+ const Variable *variableDecl() const { return VarDecl; }
+
+ SExpr *body() { return Body; }
+ const SExpr *body() const { return Body; }
+
+ template <class V>
+ typename V::R_SExpr traverse(V &Vs, typename V::R_Ctx Ctx) {
+ // A self-variable points to the SFunction itself.
+ // A rewrite must introduce the variable with a null definition, and update
+ // it after 'this' has been rewritten.
+ Variable *Nvd = Vs.enterScope(*VarDecl, nullptr);
+ auto E1 = Vs.traverse(Body, Vs.declCtx(Ctx));
+ Vs.exitScope(*VarDecl);
+ // A rewrite operation will call SFun constructor to set Vvd->Definition.
+ return Vs.reduceSFunction(*this, Nvd, E1);
+ }
+
+ template <class C>
+ typename C::CType compare(const SFunction* E, C& Cmp) const {
+ Cmp.enterScope(variableDecl(), E->variableDecl());
+ typename C::CType Ct = Cmp.compare(body(), E->body());
+ Cmp.leaveScope();
+ return Ct;
+ }
+
+private:
+ Variable *VarDecl;
+ SExpr* Body;
+};
+
+
+/// A block of code -- e.g. the body of a function.
+class Code : public SExpr {
+public:
+ static bool classof(const SExpr *E) { return E->opcode() == COP_Code; }
+
+ Code(SExpr *T, SExpr *B) : SExpr(COP_Code), ReturnType(T), Body(B) {}
+ Code(const Code &C, SExpr *T, SExpr *B) // rewrite constructor
+ : SExpr(C), ReturnType(T), Body(B) {}
+
+ SExpr *returnType() { return ReturnType; }
+ const SExpr *returnType() const { return ReturnType; }
+
+ SExpr *body() { return Body; }
+ const SExpr *body() const { return Body; }
+
+ template <class V>
+ typename V::R_SExpr traverse(V &Vs, typename V::R_Ctx Ctx) {
+ auto Nt = Vs.traverse(ReturnType, Vs.typeCtx(Ctx));
+ auto Nb = Vs.traverse(Body, Vs.lazyCtx(Ctx));
+ return Vs.reduceCode(*this, Nt, Nb);
+ }
+
+ template <class C>
+ typename C::CType compare(const Code* E, C& Cmp) const {
+ typename C::CType Ct = Cmp.compare(returnType(), E->returnType());
+ if (Cmp.notTrue(Ct))
+ return Ct;
+ return Cmp.compare(body(), E->body());
+ }
+
+private:
+ SExpr* ReturnType;
+ SExpr* Body;
+};
+
+
+/// A typed, writable location in memory
+class Field : public SExpr {
+public:
+ static bool classof(const SExpr *E) { return E->opcode() == COP_Field; }
+
+ Field(SExpr *R, SExpr *B) : SExpr(COP_Field), Range(R), Body(B) {}
+ Field(const Field &C, SExpr *R, SExpr *B) // rewrite constructor
+ : SExpr(C), Range(R), Body(B) {}
+
+ SExpr *range() { return Range; }
+ const SExpr *range() const { return Range; }
+
+ SExpr *body() { return Body; }
+ const SExpr *body() const { return Body; }
+
+ template <class V>
+ typename V::R_SExpr traverse(V &Vs, typename V::R_Ctx Ctx) {
+ auto Nr = Vs.traverse(Range, Vs.typeCtx(Ctx));
+ auto Nb = Vs.traverse(Body, Vs.lazyCtx(Ctx));
+ return Vs.reduceField(*this, Nr, Nb);
+ }
+
+ template <class C>
+ typename C::CType compare(const Field* E, C& Cmp) const {
+ typename C::CType Ct = Cmp.compare(range(), E->range());
+ if (Cmp.notTrue(Ct))
+ return Ct;
+ return Cmp.compare(body(), E->body());
+ }
+
+private:
+ SExpr* Range;
+ SExpr* Body;
+};
+
+
+/// Apply an argument to a function.
+/// Note that this does not actually call the function. Functions are curried,
+/// so this returns a closure in which the first parameter has been applied.
+/// Once all parameters have been applied, Call can be used to invoke the
+/// function.
+class Apply : public SExpr {
+public:
+ static bool classof(const SExpr *E) { return E->opcode() == COP_Apply; }
+
+ Apply(SExpr *F, SExpr *A) : SExpr(COP_Apply), Fun(F), Arg(A) {}
+ Apply(const Apply &A, SExpr *F, SExpr *Ar) // rewrite constructor
+ : SExpr(A), Fun(F), Arg(Ar)
+ {}
+
+ SExpr *fun() { return Fun; }
+ const SExpr *fun() const { return Fun; }
+
+ SExpr *arg() { return Arg; }
+ const SExpr *arg() const { return Arg; }
+
+ template <class V>
+ typename V::R_SExpr traverse(V &Vs, typename V::R_Ctx Ctx) {
+ auto Nf = Vs.traverse(Fun, Vs.subExprCtx(Ctx));
+ auto Na = Vs.traverse(Arg, Vs.subExprCtx(Ctx));
+ return Vs.reduceApply(*this, Nf, Na);
+ }
+
+ template <class C>
+ typename C::CType compare(const Apply* E, C& Cmp) const {
+ typename C::CType Ct = Cmp.compare(fun(), E->fun());
+ if (Cmp.notTrue(Ct))
+ return Ct;
+ return Cmp.compare(arg(), E->arg());
+ }
+
+private:
+ SExpr* Fun;
+ SExpr* Arg;
+};
+
+
+/// Apply a self-argument to a self-applicable function.
+class SApply : public SExpr {
+public:
+ static bool classof(const SExpr *E) { return E->opcode() == COP_SApply; }
+
+ SApply(SExpr *Sf, SExpr *A = nullptr) : SExpr(COP_SApply), Sfun(Sf), Arg(A) {}
+ SApply(SApply &A, SExpr *Sf, SExpr *Ar = nullptr) // rewrite constructor
+ : SExpr(A), Sfun(Sf), Arg(Ar) {}
+
+ SExpr *sfun() { return Sfun; }
+ const SExpr *sfun() const { return Sfun; }
+
+ SExpr *arg() { return Arg ? Arg : Sfun; }
+ const SExpr *arg() const { return Arg ? Arg : Sfun; }
+
+ bool isDelegation() const { return Arg != nullptr; }
+
+ template <class V>
+ typename V::R_SExpr traverse(V &Vs, typename V::R_Ctx Ctx) {
+ auto Nf = Vs.traverse(Sfun, Vs.subExprCtx(Ctx));
+ typename V::R_SExpr Na = Arg ? Vs.traverse(Arg, Vs.subExprCtx(Ctx))
+ : nullptr;
+ return Vs.reduceSApply(*this, Nf, Na);
+ }
+
+ template <class C>
+ typename C::CType compare(const SApply* E, C& Cmp) const {
+ typename C::CType Ct = Cmp.compare(sfun(), E->sfun());
+ if (Cmp.notTrue(Ct) || (!arg() && !E->arg()))
+ return Ct;
+ return Cmp.compare(arg(), E->arg());
+ }
+
+private:
+ SExpr* Sfun;
+ SExpr* Arg;
+};
+
+
+/// Project a named slot from a C++ struct or class.
+class Project : public SExpr {
+public:
+ static bool classof(const SExpr *E) { return E->opcode() == COP_Project; }
+
+ Project(SExpr *R, StringRef SName)
+ : SExpr(COP_Project), Rec(R), SlotName(SName), Cvdecl(nullptr)
+ { }
+ Project(SExpr *R, const clang::ValueDecl *Cvd)
+ : SExpr(COP_Project), Rec(R), SlotName(Cvd->getName()), Cvdecl(Cvd)
+ { }
+ Project(const Project &P, SExpr *R)
+ : SExpr(P), Rec(R), SlotName(P.SlotName), Cvdecl(P.Cvdecl)
+ { }
+
+ SExpr *record() { return Rec; }
+ const SExpr *record() const { return Rec; }
+
+ const clang::ValueDecl *clangDecl() const { return Cvdecl; }
+
+ bool isArrow() const { return (Flags & 0x01) != 0; }
+ void setArrow(bool b) {
+ if (b) Flags |= 0x01;
+ else Flags &= 0xFFFE;
+ }
+
+ StringRef slotName() const {
+ if (Cvdecl)
+ return Cvdecl->getName();
+ else
+ return SlotName;
+ }
+
+ template <class V>
+ typename V::R_SExpr traverse(V &Vs, typename V::R_Ctx Ctx) {
+ auto Nr = Vs.traverse(Rec, Vs.subExprCtx(Ctx));
+ return Vs.reduceProject(*this, Nr);
+ }
+
+ template <class C>
+ typename C::CType compare(const Project* E, C& Cmp) const {
+ typename C::CType Ct = Cmp.compare(record(), E->record());
+ if (Cmp.notTrue(Ct))
+ return Ct;
+ return Cmp.comparePointers(Cvdecl, E->Cvdecl);
+ }
+
+private:
+ SExpr* Rec;
+ StringRef SlotName;
+ const clang::ValueDecl *Cvdecl;
+};
+
+
+/// Call a function (after all arguments have been applied).
+class Call : public SExpr {
+public:
+ static bool classof(const SExpr *E) { return E->opcode() == COP_Call; }
+
+ Call(SExpr *T, const clang::CallExpr *Ce = nullptr)
+ : SExpr(COP_Call), Target(T), Cexpr(Ce) {}
+ Call(const Call &C, SExpr *T) : SExpr(C), Target(T), Cexpr(C.Cexpr) {}
+
+ SExpr *target() { return Target; }
+ const SExpr *target() const { return Target; }
+
+ const clang::CallExpr *clangCallExpr() const { return Cexpr; }
+
+ template <class V>
+ typename V::R_SExpr traverse(V &Vs, typename V::R_Ctx Ctx) {
+ auto Nt = Vs.traverse(Target, Vs.subExprCtx(Ctx));
+ return Vs.reduceCall(*this, Nt);
+ }
+
+ template <class C>
+ typename C::CType compare(const Call* E, C& Cmp) const {
+ return Cmp.compare(target(), E->target());
+ }
+
+private:
+ SExpr* Target;
+ const clang::CallExpr *Cexpr;
+};
+
+
+/// Allocate memory for a new value on the heap or stack.
+class Alloc : public SExpr {
+public:
+ static bool classof(const SExpr *E) { return E->opcode() == COP_Call; }
+
+ enum AllocKind {
+ AK_Stack,
+ AK_Heap
+ };
+
+ Alloc(SExpr *D, AllocKind K) : SExpr(COP_Alloc), Dtype(D) { Flags = K; }
+ Alloc(const Alloc &A, SExpr *Dt) : SExpr(A), Dtype(Dt) { Flags = A.kind(); }
+
+ AllocKind kind() const { return static_cast<AllocKind>(Flags); }
+
+ SExpr *dataType() { return Dtype; }
+ const SExpr *dataType() const { return Dtype; }
+
+ template <class V>
+ typename V::R_SExpr traverse(V &Vs, typename V::R_Ctx Ctx) {
+ auto Nd = Vs.traverse(Dtype, Vs.declCtx(Ctx));
+ return Vs.reduceAlloc(*this, Nd);
+ }
+
+ template <class C>
+ typename C::CType compare(const Alloc* E, C& Cmp) const {
+ typename C::CType Ct = Cmp.compareIntegers(kind(), E->kind());
+ if (Cmp.notTrue(Ct))
+ return Ct;
+ return Cmp.compare(dataType(), E->dataType());
+ }
+
+private:
+ SExpr* Dtype;
+};
+
+
+/// Load a value from memory.
+class Load : public SExpr {
+public:
+ static bool classof(const SExpr *E) { return E->opcode() == COP_Load; }
+
+ Load(SExpr *P) : SExpr(COP_Load), Ptr(P) {}
+ Load(const Load &L, SExpr *P) : SExpr(L), Ptr(P) {}
+
+ SExpr *pointer() { return Ptr; }
+ const SExpr *pointer() const { return Ptr; }
+
+ template <class V>
+ typename V::R_SExpr traverse(V &Vs, typename V::R_Ctx Ctx) {
+ auto Np = Vs.traverse(Ptr, Vs.subExprCtx(Ctx));
+ return Vs.reduceLoad(*this, Np);
+ }
+
+ template <class C>
+ typename C::CType compare(const Load* E, C& Cmp) const {
+ return Cmp.compare(pointer(), E->pointer());
+ }
+
+private:
+ SExpr* Ptr;
+};
+
+
+/// Store a value to memory.
+/// The destination is a pointer to a field, the source is the value to store.
+class Store : public SExpr {
+public:
+ static bool classof(const SExpr *E) { return E->opcode() == COP_Store; }
+
+ Store(SExpr *P, SExpr *V) : SExpr(COP_Store), Dest(P), Source(V) {}
+ Store(const Store &S, SExpr *P, SExpr *V) : SExpr(S), Dest(P), Source(V) {}
+
+ SExpr *destination() { return Dest; } // Address to store to
+ const SExpr *destination() const { return Dest; }
+
+ SExpr *source() { return Source; } // Value to store
+ const SExpr *source() const { return Source; }
+
+ template <class V>
+ typename V::R_SExpr traverse(V &Vs, typename V::R_Ctx Ctx) {
+ auto Np = Vs.traverse(Dest, Vs.subExprCtx(Ctx));
+ auto Nv = Vs.traverse(Source, Vs.subExprCtx(Ctx));
+ return Vs.reduceStore(*this, Np, Nv);
+ }
+
+ template <class C>
+ typename C::CType compare(const Store* E, C& Cmp) const {
+ typename C::CType Ct = Cmp.compare(destination(), E->destination());
+ if (Cmp.notTrue(Ct))
+ return Ct;
+ return Cmp.compare(source(), E->source());
+ }
+
+private:
+ SExpr* Dest;
+ SExpr* Source;
+};
+
+
+/// If p is a reference to an array, then p[i] is a reference to the i'th
+/// element of the array.
+class ArrayIndex : public SExpr {
+public:
+ static bool classof(const SExpr *E) { return E->opcode() == COP_ArrayIndex; }
+
+ ArrayIndex(SExpr *A, SExpr *N) : SExpr(COP_ArrayIndex), Array(A), Index(N) {}
+ ArrayIndex(const ArrayIndex &E, SExpr *A, SExpr *N)
+ : SExpr(E), Array(A), Index(N) {}
+
+ SExpr *array() { return Array; }
+ const SExpr *array() const { return Array; }
+
+ SExpr *index() { return Index; }
+ const SExpr *index() const { return Index; }
+
+ template <class V>
+ typename V::R_SExpr traverse(V &Vs, typename V::R_Ctx Ctx) {
+ auto Na = Vs.traverse(Array, Vs.subExprCtx(Ctx));
+ auto Ni = Vs.traverse(Index, Vs.subExprCtx(Ctx));
+ return Vs.reduceArrayIndex(*this, Na, Ni);
+ }
+
+ template <class C>
+ typename C::CType compare(const ArrayIndex* E, C& Cmp) const {
+ typename C::CType Ct = Cmp.compare(array(), E->array());
+ if (Cmp.notTrue(Ct))
+ return Ct;
+ return Cmp.compare(index(), E->index());
+ }
+
+private:
+ SExpr* Array;
+ SExpr* Index;
+};
+
+
+/// Pointer arithmetic, restricted to arrays only.
+/// If p is a reference to an array, then p + n, where n is an integer, is
+/// a reference to a subarray.
+class ArrayAdd : public SExpr {
+public:
+ static bool classof(const SExpr *E) { return E->opcode() == COP_ArrayAdd; }
+
+ ArrayAdd(SExpr *A, SExpr *N) : SExpr(COP_ArrayAdd), Array(A), Index(N) {}
+ ArrayAdd(const ArrayAdd &E, SExpr *A, SExpr *N)
+ : SExpr(E), Array(A), Index(N) {}
+
+ SExpr *array() { return Array; }
+ const SExpr *array() const { return Array; }
+
+ SExpr *index() { return Index; }
+ const SExpr *index() const { return Index; }
+
+ template <class V>
+ typename V::R_SExpr traverse(V &Vs, typename V::R_Ctx Ctx) {
+ auto Na = Vs.traverse(Array, Vs.subExprCtx(Ctx));
+ auto Ni = Vs.traverse(Index, Vs.subExprCtx(Ctx));
+ return Vs.reduceArrayAdd(*this, Na, Ni);
+ }
+
+ template <class C>
+ typename C::CType compare(const ArrayAdd* E, C& Cmp) const {
+ typename C::CType Ct = Cmp.compare(array(), E->array());
+ if (Cmp.notTrue(Ct))
+ return Ct;
+ return Cmp.compare(index(), E->index());
+ }
+
+private:
+ SExpr* Array;
+ SExpr* Index;
+};
+
+
+/// Simple arithmetic unary operations, e.g. negate and not.
+/// These operations have no side-effects.
+class UnaryOp : public SExpr {
+public:
+ static bool classof(const SExpr *E) { return E->opcode() == COP_UnaryOp; }
+
+ UnaryOp(TIL_UnaryOpcode Op, SExpr *E) : SExpr(COP_UnaryOp), Expr0(E) {
+ Flags = Op;
+ }
+ UnaryOp(const UnaryOp &U, SExpr *E) : SExpr(U), Expr0(E) { Flags = U.Flags; }
+
+ TIL_UnaryOpcode unaryOpcode() const {
+ return static_cast<TIL_UnaryOpcode>(Flags);
+ }
+
+ SExpr *expr() { return Expr0; }
+ const SExpr *expr() const { return Expr0; }
+
+ template <class V>
+ typename V::R_SExpr traverse(V &Vs, typename V::R_Ctx Ctx) {
+ auto Ne = Vs.traverse(Expr0, Vs.subExprCtx(Ctx));
+ return Vs.reduceUnaryOp(*this, Ne);
+ }
+
+ template <class C>
+ typename C::CType compare(const UnaryOp* E, C& Cmp) const {
+ typename C::CType Ct =
+ Cmp.compareIntegers(unaryOpcode(), E->unaryOpcode());
+ if (Cmp.notTrue(Ct))
+ return Ct;
+ return Cmp.compare(expr(), E->expr());
+ }
+
+private:
+ SExpr* Expr0;
+};
+
+
+/// Simple arithmetic binary operations, e.g. +, -, etc.
+/// These operations have no side effects.
+class BinaryOp : public SExpr {
+public:
+ static bool classof(const SExpr *E) { return E->opcode() == COP_BinaryOp; }
+
+ BinaryOp(TIL_BinaryOpcode Op, SExpr *E0, SExpr *E1)
+ : SExpr(COP_BinaryOp), Expr0(E0), Expr1(E1) {
+ Flags = Op;
+ }
+ BinaryOp(const BinaryOp &B, SExpr *E0, SExpr *E1)
+ : SExpr(B), Expr0(E0), Expr1(E1) {
+ Flags = B.Flags;
+ }
+
+ TIL_BinaryOpcode binaryOpcode() const {
+ return static_cast<TIL_BinaryOpcode>(Flags);
+ }
+
+ SExpr *expr0() { return Expr0; }
+ const SExpr *expr0() const { return Expr0; }
+
+ SExpr *expr1() { return Expr1; }
+ const SExpr *expr1() const { return Expr1; }
+
+ template <class V>
+ typename V::R_SExpr traverse(V &Vs, typename V::R_Ctx Ctx) {
+ auto Ne0 = Vs.traverse(Expr0, Vs.subExprCtx(Ctx));
+ auto Ne1 = Vs.traverse(Expr1, Vs.subExprCtx(Ctx));
+ return Vs.reduceBinaryOp(*this, Ne0, Ne1);
+ }
+
+ template <class C>
+ typename C::CType compare(const BinaryOp* E, C& Cmp) const {
+ typename C::CType Ct =
+ Cmp.compareIntegers(binaryOpcode(), E->binaryOpcode());
+ if (Cmp.notTrue(Ct))
+ return Ct;
+ Ct = Cmp.compare(expr0(), E->expr0());
+ if (Cmp.notTrue(Ct))
+ return Ct;
+ return Cmp.compare(expr1(), E->expr1());
+ }
+
+private:
+ SExpr* Expr0;
+ SExpr* Expr1;
+};
+
+
+/// Cast expressions.
+/// Cast expressions are essentially unary operations, but we treat them
+/// as a distinct AST node because they only change the type of the result.
+class Cast : public SExpr {
+public:
+ static bool classof(const SExpr *E) { return E->opcode() == COP_Cast; }
+
+ Cast(TIL_CastOpcode Op, SExpr *E) : SExpr(COP_Cast), Expr0(E) { Flags = Op; }
+ Cast(const Cast &C, SExpr *E) : SExpr(C), Expr0(E) { Flags = C.Flags; }
+
+ TIL_CastOpcode castOpcode() const {
+ return static_cast<TIL_CastOpcode>(Flags);
+ }
+
+ SExpr *expr() { return Expr0; }
+ const SExpr *expr() const { return Expr0; }
+
+ template <class V>
+ typename V::R_SExpr traverse(V &Vs, typename V::R_Ctx Ctx) {
+ auto Ne = Vs.traverse(Expr0, Vs.subExprCtx(Ctx));
+ return Vs.reduceCast(*this, Ne);
+ }
+
+ template <class C>
+ typename C::CType compare(const Cast* E, C& Cmp) const {
+ typename C::CType Ct =
+ Cmp.compareIntegers(castOpcode(), E->castOpcode());
+ if (Cmp.notTrue(Ct))
+ return Ct;
+ return Cmp.compare(expr(), E->expr());
+ }
+
+private:
+ SExpr* Expr0;
+};
+
+
+class SCFG;
+
+
+/// Phi Node, for code in SSA form.
+/// Each Phi node has an array of possible values that it can take,
+/// depending on where control flow comes from.
+class Phi : public SExpr {
+public:
+ typedef SimpleArray<SExpr *> ValArray;
+
+ // In minimal SSA form, all Phi nodes are MultiVal.
+ // During conversion to SSA, incomplete Phi nodes may be introduced, which
+ // are later determined to be SingleVal, and are thus redundant.
+ enum Status {
+ PH_MultiVal = 0, // Phi node has multiple distinct values. (Normal)
+ PH_SingleVal, // Phi node has one distinct value, and can be eliminated
+ PH_Incomplete // Phi node is incomplete
+ };
+
+ static bool classof(const SExpr *E) { return E->opcode() == COP_Phi; }
+
+ Phi()
+ : SExpr(COP_Phi), Cvdecl(nullptr) {}
+ Phi(MemRegionRef A, unsigned Nvals)
+ : SExpr(COP_Phi), Values(A, Nvals), Cvdecl(nullptr) {}
+ Phi(const Phi &P, ValArray &&Vs)
+ : SExpr(P), Values(std::move(Vs)), Cvdecl(nullptr) {}
+
+ const ValArray &values() const { return Values; }
+ ValArray &values() { return Values; }
+
+ Status status() const { return static_cast<Status>(Flags); }
+ void setStatus(Status s) { Flags = s; }
+
+ /// Return the clang declaration of the variable for this Phi node, if any.
+ const clang::ValueDecl *clangDecl() const { return Cvdecl; }
+
+ /// Set the clang variable associated with this Phi node.
+ void setClangDecl(const clang::ValueDecl *Cvd) { Cvdecl = Cvd; }
+
+ template <class V>
+ typename V::R_SExpr traverse(V &Vs, typename V::R_Ctx Ctx) {
+ typename V::template Container<typename V::R_SExpr>
+ Nvs(Vs, Values.size());
+
+ for (auto *Val : Values) {
+ Nvs.push_back( Vs.traverse(Val, Vs.subExprCtx(Ctx)) );
+ }
+ return Vs.reducePhi(*this, Nvs);
+ }
+
+ template <class C>
+ typename C::CType compare(const Phi *E, C &Cmp) const {
+ // TODO: implement CFG comparisons
+ return Cmp.comparePointers(this, E);
+ }
+
+private:
+ ValArray Values;
+ const clang::ValueDecl* Cvdecl;
+};
+
+
+/// Base class for basic block terminators: Branch, Goto, and Return.
+class Terminator : public SExpr {
+public:
+ static bool classof(const SExpr *E) {
+ return E->opcode() >= COP_Goto && E->opcode() <= COP_Return;
+ }
+
+protected:
+ Terminator(TIL_Opcode Op) : SExpr(Op) {}
+ Terminator(const SExpr &E) : SExpr(E) {}
+
+public:
+ /// Return the list of basic blocks that this terminator can branch to.
+ ArrayRef<BasicBlock*> successors();
+
+ ArrayRef<BasicBlock*> successors() const {
+ return const_cast<Terminator*>(this)->successors();
+ }
+};
+
+
+/// Jump to another basic block.
+/// A goto instruction is essentially a tail-recursive call into another
+/// block. In addition to the block pointer, it specifies an index into the
+/// phi nodes of that block. The index can be used to retrieve the "arguments"
+/// of the call.
+class Goto : public Terminator {
+public:
+ static bool classof(const SExpr *E) { return E->opcode() == COP_Goto; }
+
+ Goto(BasicBlock *B, unsigned I)
+ : Terminator(COP_Goto), TargetBlock(B), Index(I) {}
+ Goto(const Goto &G, BasicBlock *B, unsigned I)
+ : Terminator(COP_Goto), TargetBlock(B), Index(I) {}
+
+ const BasicBlock *targetBlock() const { return TargetBlock; }
+ BasicBlock *targetBlock() { return TargetBlock; }
+
+ /// Returns the index into the
+ unsigned index() const { return Index; }
+
+ /// Return the list of basic blocks that this terminator can branch to.
+ ArrayRef<BasicBlock*> successors() {
+ return TargetBlock;
+ }
+
+ template <class V>
+ typename V::R_SExpr traverse(V &Vs, typename V::R_Ctx Ctx) {
+ BasicBlock *Ntb = Vs.reduceBasicBlockRef(TargetBlock);
+ return Vs.reduceGoto(*this, Ntb);
+ }
+
+ template <class C>
+ typename C::CType compare(const Goto *E, C &Cmp) const {
+ // TODO: implement CFG comparisons
+ return Cmp.comparePointers(this, E);
+ }
+
+private:
+ BasicBlock *TargetBlock;
+ unsigned Index;
+};
+
+
+/// A conditional branch to two other blocks.
+/// Note that unlike Goto, Branch does not have an index. The target blocks
+/// must be child-blocks, and cannot have Phi nodes.
+class Branch : public Terminator {
+public:
+ static bool classof(const SExpr *E) { return E->opcode() == COP_Branch; }
+
+ Branch(SExpr *C, BasicBlock *T, BasicBlock *E)
+ : Terminator(COP_Branch), Condition(C) {
+ Branches[0] = T;
+ Branches[1] = E;
+ }
+ Branch(const Branch &Br, SExpr *C, BasicBlock *T, BasicBlock *E)
+ : Terminator(Br), Condition(C) {
+ Branches[0] = T;
+ Branches[1] = E;
+ }
+
+ const SExpr *condition() const { return Condition; }
+ SExpr *condition() { return Condition; }
+
+ const BasicBlock *thenBlock() const { return Branches[0]; }
+ BasicBlock *thenBlock() { return Branches[0]; }
+
+ const BasicBlock *elseBlock() const { return Branches[1]; }
+ BasicBlock *elseBlock() { return Branches[1]; }
+
+ /// Return the list of basic blocks that this terminator can branch to.
+ ArrayRef<BasicBlock*> successors() {
+ return llvm::makeArrayRef(Branches);
+ }
+
+ template <class V>
+ typename V::R_SExpr traverse(V &Vs, typename V::R_Ctx Ctx) {
+ auto Nc = Vs.traverse(Condition, Vs.subExprCtx(Ctx));
+ BasicBlock *Ntb = Vs.reduceBasicBlockRef(Branches[0]);
+ BasicBlock *Nte = Vs.reduceBasicBlockRef(Branches[1]);
+ return Vs.reduceBranch(*this, Nc, Ntb, Nte);
+ }
+
+ template <class C>
+ typename C::CType compare(const Branch *E, C &Cmp) const {
+ // TODO: implement CFG comparisons
+ return Cmp.comparePointers(this, E);
+ }
+
+private:
+ SExpr* Condition;
+ BasicBlock *Branches[2];
+};
+
+
+/// Return from the enclosing function, passing the return value to the caller.
+/// Only the exit block should end with a return statement.
+class Return : public Terminator {
+public:
+ static bool classof(const SExpr *E) { return E->opcode() == COP_Return; }
+
+ Return(SExpr* Rval) : Terminator(COP_Return), Retval(Rval) {}
+ Return(const Return &R, SExpr* Rval) : Terminator(R), Retval(Rval) {}
+
+ /// Return an empty list.
+ ArrayRef<BasicBlock*> successors() {
+ return None;
+ }
+
+ SExpr *returnValue() { return Retval; }
+ const SExpr *returnValue() const { return Retval; }
+
+ template <class V>
+ typename V::R_SExpr traverse(V &Vs, typename V::R_Ctx Ctx) {
+ auto Ne = Vs.traverse(Retval, Vs.subExprCtx(Ctx));
+ return Vs.reduceReturn(*this, Ne);
+ }
+
+ template <class C>
+ typename C::CType compare(const Return *E, C &Cmp) const {
+ return Cmp.compare(Retval, E->Retval);
+ }
+
+private:
+ SExpr* Retval;
+};
+
+
+inline ArrayRef<BasicBlock*> Terminator::successors() {
+ switch (opcode()) {
+ case COP_Goto: return cast<Goto>(this)->successors();
+ case COP_Branch: return cast<Branch>(this)->successors();
+ case COP_Return: return cast<Return>(this)->successors();
+ default:
+ return None;
+ }
+}
+
+
+/// A basic block is part of an SCFG. It can be treated as a function in
+/// continuation passing style. A block consists of a sequence of phi nodes,
+/// which are "arguments" to the function, followed by a sequence of
+/// instructions. It ends with a Terminator, which is a Branch or Goto to
+/// another basic block in the same SCFG.
+class BasicBlock : public SExpr {
+public:
+ typedef SimpleArray<SExpr*> InstrArray;
+ typedef SimpleArray<BasicBlock*> BlockArray;
+
+ // TopologyNodes are used to overlay tree structures on top of the CFG,
+ // such as dominator and postdominator trees. Each block is assigned an
+ // ID in the tree according to a depth-first search. Tree traversals are
+ // always up, towards the parents.
+ struct TopologyNode {
+ TopologyNode() : NodeID(0), SizeOfSubTree(0), Parent(nullptr) {}
+
+ bool isParentOf(const TopologyNode& OtherNode) {
+ return OtherNode.NodeID > NodeID &&
+ OtherNode.NodeID < NodeID + SizeOfSubTree;
+ }
+
+ bool isParentOfOrEqual(const TopologyNode& OtherNode) {
+ return OtherNode.NodeID >= NodeID &&
+ OtherNode.NodeID < NodeID + SizeOfSubTree;
+ }
+
+ int NodeID;
+ int SizeOfSubTree; // Includes this node, so must be > 1.
+ BasicBlock *Parent; // Pointer to parent.
+ };
+
+ static bool classof(const SExpr *E) { return E->opcode() == COP_BasicBlock; }
+
+ explicit BasicBlock(MemRegionRef A)
+ : SExpr(COP_BasicBlock), Arena(A), CFGPtr(nullptr), BlockID(0),
+ Visited(0), TermInstr(nullptr) {}
+ BasicBlock(BasicBlock &B, MemRegionRef A, InstrArray &&As, InstrArray &&Is,
+ Terminator *T)
+ : SExpr(COP_BasicBlock), Arena(A), CFGPtr(nullptr), BlockID(0),Visited(0),
+ Args(std::move(As)), Instrs(std::move(Is)), TermInstr(T) {}
+
+ /// Returns the block ID. Every block has a unique ID in the CFG.
+ int blockID() const { return BlockID; }
+
+ /// Returns the number of predecessors.
+ size_t numPredecessors() const { return Predecessors.size(); }
+ size_t numSuccessors() const { return successors().size(); }
+
+ const SCFG* cfg() const { return CFGPtr; }
+ SCFG* cfg() { return CFGPtr; }
+
+ const BasicBlock *parent() const { return DominatorNode.Parent; }
+ BasicBlock *parent() { return DominatorNode.Parent; }
+
+ const InstrArray &arguments() const { return Args; }
+ InstrArray &arguments() { return Args; }
+
+ InstrArray &instructions() { return Instrs; }
+ const InstrArray &instructions() const { return Instrs; }
+
+ /// Returns a list of predecessors.
+ /// The order of predecessors in the list is important; each phi node has
+ /// exactly one argument for each precessor, in the same order.
+ BlockArray &predecessors() { return Predecessors; }
+ const BlockArray &predecessors() const { return Predecessors; }
+
+ ArrayRef<BasicBlock*> successors() { return TermInstr->successors(); }
+ ArrayRef<BasicBlock*> successors() const { return TermInstr->successors(); }
+
+ const Terminator *terminator() const { return TermInstr; }
+ Terminator *terminator() { return TermInstr; }
+
+ void setTerminator(Terminator *E) { TermInstr = E; }
+
+ bool Dominates(const BasicBlock &Other) {
+ return DominatorNode.isParentOfOrEqual(Other.DominatorNode);
+ }
+
+ bool PostDominates(const BasicBlock &Other) {
+ return PostDominatorNode.isParentOfOrEqual(Other.PostDominatorNode);
+ }
+
+ /// Add a new argument.
+ void addArgument(Phi *V) {
+ Args.reserveCheck(1, Arena);
+ Args.push_back(V);
+ }
+ /// Add a new instruction.
+ void addInstruction(SExpr *V) {
+ Instrs.reserveCheck(1, Arena);
+ Instrs.push_back(V);
+ }
+ // Add a new predecessor, and return the phi-node index for it.
+ // Will add an argument to all phi-nodes, initialized to nullptr.
+ unsigned addPredecessor(BasicBlock *Pred);
+
+ // Reserve space for Nargs arguments.
+ void reserveArguments(unsigned Nargs) { Args.reserve(Nargs, Arena); }
+
+ // Reserve space for Nins instructions.
+ void reserveInstructions(unsigned Nins) { Instrs.reserve(Nins, Arena); }
+
+ // Reserve space for NumPreds predecessors, including space in phi nodes.
+ void reservePredecessors(unsigned NumPreds);
+
+ /// Return the index of BB, or Predecessors.size if BB is not a predecessor.
+ unsigned findPredecessorIndex(const BasicBlock *BB) const {
+ auto I = std::find(Predecessors.cbegin(), Predecessors.cend(), BB);
+ return std::distance(Predecessors.cbegin(), I);
+ }
+
+ template <class V>
+ typename V::R_BasicBlock traverse(V &Vs, typename V::R_Ctx Ctx) {
+ typename V::template Container<SExpr*> Nas(Vs, Args.size());
+ typename V::template Container<SExpr*> Nis(Vs, Instrs.size());
+
+ // Entering the basic block should do any scope initialization.
+ Vs.enterBasicBlock(*this);
+
+ for (auto *E : Args) {
+ auto Ne = Vs.traverse(E, Vs.subExprCtx(Ctx));
+ Nas.push_back(Ne);
+ }
+ for (auto *E : Instrs) {
+ auto Ne = Vs.traverse(E, Vs.subExprCtx(Ctx));
+ Nis.push_back(Ne);
+ }
+ auto Nt = Vs.traverse(TermInstr, Ctx);
+
+ // Exiting the basic block should handle any scope cleanup.
+ Vs.exitBasicBlock(*this);
+
+ return Vs.reduceBasicBlock(*this, Nas, Nis, Nt);
+ }
+
+ template <class C>
+ typename C::CType compare(const BasicBlock *E, C &Cmp) const {
+ // TODO: implement CFG comparisons
+ return Cmp.comparePointers(this, E);
+ }
+
+private:
+ friend class SCFG;
+
+ int renumberInstrs(int id); // assign unique ids to all instructions
+ int topologicalSort(SimpleArray<BasicBlock*>& Blocks, int ID);
+ int topologicalFinalSort(SimpleArray<BasicBlock*>& Blocks, int ID);
+ void computeDominator();
+ void computePostDominator();
+
+private:
+ MemRegionRef Arena; // The arena used to allocate this block.
+ SCFG *CFGPtr; // The CFG that contains this block.
+ int BlockID : 31; // unique id for this BB in the containing CFG.
+ // IDs are in topological order.
+ bool Visited : 1; // Bit to determine if a block has been visited
+ // during a traversal.
+ BlockArray Predecessors; // Predecessor blocks in the CFG.
+ InstrArray Args; // Phi nodes. One argument per predecessor.
+ InstrArray Instrs; // Instructions.
+ Terminator* TermInstr; // Terminating instruction
+
+ TopologyNode DominatorNode; // The dominator tree
+ TopologyNode PostDominatorNode; // The post-dominator tree
+};
+
+
+/// An SCFG is a control-flow graph. It consists of a set of basic blocks,
+/// each of which terminates in a branch to another basic block. There is one
+/// entry point, and one exit point.
+class SCFG : public SExpr {
+public:
+ typedef SimpleArray<BasicBlock *> BlockArray;
+ typedef BlockArray::iterator iterator;
+ typedef BlockArray::const_iterator const_iterator;
+
+ static bool classof(const SExpr *E) { return E->opcode() == COP_SCFG; }
+
+ SCFG(MemRegionRef A, unsigned Nblocks)
+ : SExpr(COP_SCFG), Arena(A), Blocks(A, Nblocks),
+ Entry(nullptr), Exit(nullptr), NumInstructions(0), Normal(false) {
+ Entry = new (A) BasicBlock(A);
+ Exit = new (A) BasicBlock(A);
+ auto *V = new (A) Phi();
+ Exit->addArgument(V);
+ Exit->setTerminator(new (A) Return(V));
+ add(Entry);
+ add(Exit);
+ }
+ SCFG(const SCFG &Cfg, BlockArray &&Ba) // steals memory from Ba
+ : SExpr(COP_SCFG), Arena(Cfg.Arena), Blocks(std::move(Ba)),
+ Entry(nullptr), Exit(nullptr), NumInstructions(0), Normal(false) {
+ // TODO: set entry and exit!
+ }
+
+ /// Return true if this CFG is valid.
+ bool valid() const { return Entry && Exit && Blocks.size() > 0; }
+
+ /// Return true if this CFG has been normalized.
+ /// After normalization, blocks are in topological order, and block and
+ /// instruction IDs have been assigned.
+ bool normal() const { return Normal; }
+
+ iterator begin() { return Blocks.begin(); }
+ iterator end() { return Blocks.end(); }
+
+ const_iterator begin() const { return cbegin(); }
+ const_iterator end() const { return cend(); }
+
+ const_iterator cbegin() const { return Blocks.cbegin(); }
+ const_iterator cend() const { return Blocks.cend(); }
+
+ const BasicBlock *entry() const { return Entry; }
+ BasicBlock *entry() { return Entry; }
+ const BasicBlock *exit() const { return Exit; }
+ BasicBlock *exit() { return Exit; }
+
+ /// Return the number of blocks in the CFG.
+ /// Block::blockID() will return a number less than numBlocks();
+ size_t numBlocks() const { return Blocks.size(); }
+
+ /// Return the total number of instructions in the CFG.
+ /// This is useful for building instruction side-tables;
+ /// A call to SExpr::id() will return a number less than numInstructions().
+ unsigned numInstructions() { return NumInstructions; }
+
+ inline void add(BasicBlock *BB) {
+ assert(BB->CFGPtr == nullptr);
+ BB->CFGPtr = this;
+ Blocks.reserveCheck(1, Arena);
+ Blocks.push_back(BB);
+ }
+
+ void setEntry(BasicBlock *BB) { Entry = BB; }
+ void setExit(BasicBlock *BB) { Exit = BB; }
+
+ void computeNormalForm();
+
+ template <class V>
+ typename V::R_SExpr traverse(V &Vs, typename V::R_Ctx Ctx) {
+ Vs.enterCFG(*this);
+ typename V::template Container<BasicBlock *> Bbs(Vs, Blocks.size());
+
+ for (auto *B : Blocks) {
+ Bbs.push_back( B->traverse(Vs, Vs.subExprCtx(Ctx)) );
+ }
+ Vs.exitCFG(*this);
+ return Vs.reduceSCFG(*this, Bbs);
+ }
+
+ template <class C>
+ typename C::CType compare(const SCFG *E, C &Cmp) const {
+ // TODO: implement CFG comparisons
+ return Cmp.comparePointers(this, E);
+ }
+
+private:
+ void renumberInstrs(); // assign unique ids to all instructions
+
+private:
+ MemRegionRef Arena;
+ BlockArray Blocks;
+ BasicBlock *Entry;
+ BasicBlock *Exit;
+ unsigned NumInstructions;
+ bool Normal;
+};
+
+
+
+/// An identifier, e.g. 'foo' or 'x'.
+/// This is a pseduo-term; it will be lowered to a variable or projection.
+class Identifier : public SExpr {
+public:
+ static bool classof(const SExpr *E) { return E->opcode() == COP_Identifier; }
+
+ Identifier(StringRef Id): SExpr(COP_Identifier), Name(Id) { }
+ Identifier(const Identifier& I) : SExpr(I), Name(I.Name) { }
+
+ StringRef name() const { return Name; }
+
+ template <class V>
+ typename V::R_SExpr traverse(V &Vs, typename V::R_Ctx Ctx) {
+ return Vs.reduceIdentifier(*this);
+ }
+
+ template <class C>
+ typename C::CType compare(const Identifier* E, C& Cmp) const {
+ return Cmp.compareStrings(name(), E->name());
+ }
+
+private:
+ StringRef Name;
+};
+
+
+/// An if-then-else expression.
+/// This is a pseduo-term; it will be lowered to a branch in a CFG.
+class IfThenElse : public SExpr {
+public:
+ static bool classof(const SExpr *E) { return E->opcode() == COP_IfThenElse; }
+
+ IfThenElse(SExpr *C, SExpr *T, SExpr *E)
+ : SExpr(COP_IfThenElse), Condition(C), ThenExpr(T), ElseExpr(E)
+ { }
+ IfThenElse(const IfThenElse &I, SExpr *C, SExpr *T, SExpr *E)
+ : SExpr(I), Condition(C), ThenExpr(T), ElseExpr(E)
+ { }
+
+ SExpr *condition() { return Condition; } // Address to store to
+ const SExpr *condition() const { return Condition; }
+
+ SExpr *thenExpr() { return ThenExpr; } // Value to store
+ const SExpr *thenExpr() const { return ThenExpr; }
+
+ SExpr *elseExpr() { return ElseExpr; } // Value to store
+ const SExpr *elseExpr() const { return ElseExpr; }
+
+ template <class V>
+ typename V::R_SExpr traverse(V &Vs, typename V::R_Ctx Ctx) {
+ auto Nc = Vs.traverse(Condition, Vs.subExprCtx(Ctx));
+ auto Nt = Vs.traverse(ThenExpr, Vs.subExprCtx(Ctx));
+ auto Ne = Vs.traverse(ElseExpr, Vs.subExprCtx(Ctx));
+ return Vs.reduceIfThenElse(*this, Nc, Nt, Ne);
+ }
+
+ template <class C>
+ typename C::CType compare(const IfThenElse* E, C& Cmp) const {
+ typename C::CType Ct = Cmp.compare(condition(), E->condition());
+ if (Cmp.notTrue(Ct))
+ return Ct;
+ Ct = Cmp.compare(thenExpr(), E->thenExpr());
+ if (Cmp.notTrue(Ct))
+ return Ct;
+ return Cmp.compare(elseExpr(), E->elseExpr());
+ }
+
+private:
+ SExpr* Condition;
+ SExpr* ThenExpr;
+ SExpr* ElseExpr;
+};
+
+
+/// A let-expression, e.g. let x=t; u.
+/// This is a pseduo-term; it will be lowered to instructions in a CFG.
+class Let : public SExpr {
+public:
+ static bool classof(const SExpr *E) { return E->opcode() == COP_Let; }
+
+ Let(Variable *Vd, SExpr *Bd) : SExpr(COP_Let), VarDecl(Vd), Body(Bd) {
+ Vd->setKind(Variable::VK_Let);
+ }
+ Let(const Let &L, Variable *Vd, SExpr *Bd) : SExpr(L), VarDecl(Vd), Body(Bd) {
+ Vd->setKind(Variable::VK_Let);
+ }
+
+ Variable *variableDecl() { return VarDecl; }
+ const Variable *variableDecl() const { return VarDecl; }
+
+ SExpr *body() { return Body; }
+ const SExpr *body() const { return Body; }
+
+ template <class V>
+ typename V::R_SExpr traverse(V &Vs, typename V::R_Ctx Ctx) {
+ // This is a variable declaration, so traverse the definition.
+ auto E0 = Vs.traverse(VarDecl->Definition, Vs.subExprCtx(Ctx));
+ // Tell the rewriter to enter the scope of the let variable.
+ Variable *Nvd = Vs.enterScope(*VarDecl, E0);
+ auto E1 = Vs.traverse(Body, Ctx);
+ Vs.exitScope(*VarDecl);
+ return Vs.reduceLet(*this, Nvd, E1);
+ }
+
+ template <class C>
+ typename C::CType compare(const Let* E, C& Cmp) const {
+ typename C::CType Ct =
+ Cmp.compare(VarDecl->definition(), E->VarDecl->definition());
+ if (Cmp.notTrue(Ct))
+ return Ct;
+ Cmp.enterScope(variableDecl(), E->variableDecl());
+ Ct = Cmp.compare(body(), E->body());
+ Cmp.leaveScope();
+ return Ct;
+ }
+
+private:
+ Variable *VarDecl;
+ SExpr* Body;
+};
+
+
+
+const SExpr *getCanonicalVal(const SExpr *E);
+SExpr* simplifyToCanonicalVal(SExpr *E);
+void simplifyIncompleteArg(til::Phi *Ph);
+
+
+} // end namespace til
+} // end namespace threadSafety
+} // end namespace clang
+
+#endif
diff --git a/contrib/llvm/tools/clang/include/clang/Analysis/Analyses/ThreadSafetyTraverse.h b/contrib/llvm/tools/clang/include/clang/Analysis/Analyses/ThreadSafetyTraverse.h
new file mode 100644
index 0000000..705fe91
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Analysis/Analyses/ThreadSafetyTraverse.h
@@ -0,0 +1,902 @@
+//===- ThreadSafetyTraverse.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 a framework for doing generic traversals and rewriting
+// operations over the Thread Safety TIL.
+//
+// UNDER CONSTRUCTION. USE AT YOUR OWN RISK.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_ANALYSIS_ANALYSES_THREADSAFETYTRAVERSE_H
+#define LLVM_CLANG_ANALYSIS_ANALYSES_THREADSAFETYTRAVERSE_H
+
+#include "ThreadSafetyTIL.h"
+#include <ostream>
+
+namespace clang {
+namespace threadSafety {
+namespace til {
+
+// Defines an interface used to traverse SExprs. Traversals have been made as
+// generic as possible, and are intended to handle any kind of pass over the
+// AST, e.g. visiters, copying, non-destructive rewriting, destructive
+// (in-place) rewriting, hashing, typing, etc.
+//
+// Traversals implement the functional notion of a "fold" operation on SExprs.
+// Each SExpr class provides a traverse method, which does the following:
+// * e->traverse(v):
+// // compute a result r_i for each subexpression e_i
+// for (i = 1..n) r_i = v.traverse(e_i);
+// // combine results into a result for e, where X is the class of e
+// return v.reduceX(*e, r_1, .. r_n).
+//
+// A visitor can control the traversal by overriding the following methods:
+// * v.traverse(e):
+// return v.traverseByCase(e), which returns v.traverseX(e)
+// * v.traverseX(e): (X is the class of e)
+// return e->traverse(v).
+// * v.reduceX(*e, r_1, .. r_n):
+// compute a result for a node of type X
+//
+// The reduceX methods control the kind of traversal (visitor, copy, etc.).
+// They are defined in derived classes.
+//
+// Class R defines the basic interface types (R_SExpr).
+template <class Self, class R>
+class Traversal {
+public:
+ Self *self() { return static_cast<Self *>(this); }
+
+ // Traverse an expression -- returning a result of type R_SExpr.
+ // Override this method to do something for every expression, regardless
+ // of which kind it is.
+ // E is a reference, so this can be use for in-place updates.
+ // The type T must be a subclass of SExpr.
+ template <class T>
+ typename R::R_SExpr traverse(T* &E, typename R::R_Ctx Ctx) {
+ return traverseSExpr(E, Ctx);
+ }
+
+ // Override this method to do something for every expression.
+ // Does not allow in-place updates.
+ typename R::R_SExpr traverseSExpr(SExpr *E, typename R::R_Ctx Ctx) {
+ return traverseByCase(E, Ctx);
+ }
+
+ // Helper method to call traverseX(e) on the appropriate type.
+ typename R::R_SExpr traverseByCase(SExpr *E, typename R::R_Ctx Ctx) {
+ switch (E->opcode()) {
+#define TIL_OPCODE_DEF(X) \
+ case COP_##X: \
+ return self()->traverse##X(cast<X>(E), Ctx);
+#include "ThreadSafetyOps.def"
+#undef TIL_OPCODE_DEF
+ }
+ return self()->reduceNull();
+ }
+
+// Traverse e, by static dispatch on the type "X" of e.
+// Override these methods to do something for a particular kind of term.
+#define TIL_OPCODE_DEF(X) \
+ typename R::R_SExpr traverse##X(X *e, typename R::R_Ctx Ctx) { \
+ return e->traverse(*self(), Ctx); \
+ }
+#include "ThreadSafetyOps.def"
+#undef TIL_OPCODE_DEF
+};
+
+
+// Base class for simple reducers that don't much care about the context.
+class SimpleReducerBase {
+public:
+ enum TraversalKind {
+ TRV_Normal, // ordinary subexpressions
+ TRV_Decl, // declarations (e.g. function bodies)
+ TRV_Lazy, // expressions that require lazy evaluation
+ TRV_Type // type expressions
+ };
+
+ // R_Ctx defines a "context" for the traversal, which encodes information
+ // about where a term appears. This can be used to encoding the
+ // "current continuation" for CPS transforms, or other information.
+ typedef TraversalKind R_Ctx;
+
+ // Create context for an ordinary subexpression.
+ R_Ctx subExprCtx(R_Ctx Ctx) { return TRV_Normal; }
+
+ // Create context for a subexpression that occurs in a declaration position
+ // (e.g. function body).
+ R_Ctx declCtx(R_Ctx Ctx) { return TRV_Decl; }
+
+ // Create context for a subexpression that occurs in a position that
+ // should be reduced lazily. (e.g. code body).
+ R_Ctx lazyCtx(R_Ctx Ctx) { return TRV_Lazy; }
+
+ // Create context for a subexpression that occurs in a type position.
+ R_Ctx typeCtx(R_Ctx Ctx) { return TRV_Type; }
+};
+
+
+// Base class for traversals that rewrite an SExpr to another SExpr.
+class CopyReducerBase : public SimpleReducerBase {
+public:
+ // R_SExpr is the result type for a traversal.
+ // A copy or non-destructive rewrite returns a newly allocated term.
+ typedef SExpr *R_SExpr;
+ typedef BasicBlock *R_BasicBlock;
+
+ // Container is a minimal interface used to store results when traversing
+ // SExprs of variable arity, such as Phi, Goto, and SCFG.
+ template <class T> class Container {
+ public:
+ // Allocate a new container with a capacity for n elements.
+ Container(CopyReducerBase &S, unsigned N) : Elems(S.Arena, N) {}
+
+ // Push a new element onto the container.
+ void push_back(T E) { Elems.push_back(E); }
+
+ SimpleArray<T> Elems;
+ };
+
+ CopyReducerBase(MemRegionRef A) : Arena(A) {}
+
+protected:
+ MemRegionRef Arena;
+};
+
+
+// Base class for visit traversals.
+class VisitReducerBase : public SimpleReducerBase {
+public:
+ // A visitor returns a bool, representing success or failure.
+ typedef bool R_SExpr;
+ typedef bool R_BasicBlock;
+
+ // A visitor "container" is a single bool, which accumulates success.
+ template <class T> class Container {
+ public:
+ Container(VisitReducerBase &S, unsigned N) : Success(true) {}
+ void push_back(bool E) { Success = Success && E; }
+
+ bool Success;
+ };
+};
+
+
+// Implements a traversal that visits each subexpression, and returns either
+// true or false.
+template <class Self>
+class VisitReducer : public Traversal<Self, VisitReducerBase>,
+ public VisitReducerBase {
+public:
+ VisitReducer() {}
+
+public:
+ R_SExpr reduceNull() { return true; }
+ R_SExpr reduceUndefined(Undefined &Orig) { return true; }
+ R_SExpr reduceWildcard(Wildcard &Orig) { return true; }
+
+ R_SExpr reduceLiteral(Literal &Orig) { return true; }
+ template<class T>
+ R_SExpr reduceLiteralT(LiteralT<T> &Orig) { return true; }
+ R_SExpr reduceLiteralPtr(Literal &Orig) { return true; }
+
+ R_SExpr reduceFunction(Function &Orig, Variable *Nvd, R_SExpr E0) {
+ return Nvd && E0;
+ }
+ R_SExpr reduceSFunction(SFunction &Orig, Variable *Nvd, R_SExpr E0) {
+ return Nvd && E0;
+ }
+ R_SExpr reduceCode(Code &Orig, R_SExpr E0, R_SExpr E1) {
+ return E0 && E1;
+ }
+ R_SExpr reduceField(Field &Orig, R_SExpr E0, R_SExpr E1) {
+ return E0 && E1;
+ }
+ R_SExpr reduceApply(Apply &Orig, R_SExpr E0, R_SExpr E1) {
+ return E0 && E1;
+ }
+ R_SExpr reduceSApply(SApply &Orig, R_SExpr E0, R_SExpr E1) {
+ return E0 && E1;
+ }
+ R_SExpr reduceProject(Project &Orig, R_SExpr E0) { return E0; }
+ R_SExpr reduceCall(Call &Orig, R_SExpr E0) { return E0; }
+ R_SExpr reduceAlloc(Alloc &Orig, R_SExpr E0) { return E0; }
+ R_SExpr reduceLoad(Load &Orig, R_SExpr E0) { return E0; }
+ R_SExpr reduceStore(Store &Orig, R_SExpr E0, R_SExpr E1) { return E0 && E1; }
+ R_SExpr reduceArrayIndex(Store &Orig, R_SExpr E0, R_SExpr E1) {
+ return E0 && E1;
+ }
+ R_SExpr reduceArrayAdd(Store &Orig, R_SExpr E0, R_SExpr E1) {
+ return E0 && E1;
+ }
+ R_SExpr reduceUnaryOp(UnaryOp &Orig, R_SExpr E0) { return E0; }
+ R_SExpr reduceBinaryOp(BinaryOp &Orig, R_SExpr E0, R_SExpr E1) {
+ return E0 && E1;
+ }
+ R_SExpr reduceCast(Cast &Orig, R_SExpr E0) { return E0; }
+
+ R_SExpr reduceSCFG(SCFG &Orig, Container<BasicBlock *> Bbs) {
+ return Bbs.Success;
+ }
+ R_BasicBlock reduceBasicBlock(BasicBlock &Orig, Container<R_SExpr> &As,
+ Container<R_SExpr> &Is, R_SExpr T) {
+ return (As.Success && Is.Success && T);
+ }
+ R_SExpr reducePhi(Phi &Orig, Container<R_SExpr> &As) {
+ return As.Success;
+ }
+ R_SExpr reduceGoto(Goto &Orig, BasicBlock *B) {
+ return true;
+ }
+ R_SExpr reduceBranch(Branch &O, R_SExpr C, BasicBlock *B0, BasicBlock *B1) {
+ return C;
+ }
+ R_SExpr reduceReturn(Return &O, R_SExpr E) {
+ return E;
+ }
+
+ R_SExpr reduceIdentifier(Identifier &Orig) {
+ return true;
+ }
+ R_SExpr reduceIfThenElse(IfThenElse &Orig, R_SExpr C, R_SExpr T, R_SExpr E) {
+ return C && T && E;
+ }
+ R_SExpr reduceLet(Let &Orig, Variable *Nvd, R_SExpr B) {
+ return Nvd && B;
+ }
+
+ Variable *enterScope(Variable &Orig, R_SExpr E0) { return &Orig; }
+ void exitScope(const Variable &Orig) {}
+ void enterCFG(SCFG &Cfg) {}
+ void exitCFG(SCFG &Cfg) {}
+ void enterBasicBlock(BasicBlock &BB) {}
+ void exitBasicBlock(BasicBlock &BB) {}
+
+ Variable *reduceVariableRef (Variable *Ovd) { return Ovd; }
+ BasicBlock *reduceBasicBlockRef(BasicBlock *Obb) { return Obb; }
+
+public:
+ bool traverse(SExpr *E, TraversalKind K = TRV_Normal) {
+ Success = Success && this->traverseByCase(E);
+ return Success;
+ }
+
+ static bool visit(SExpr *E) {
+ Self Visitor;
+ return Visitor.traverse(E, TRV_Normal);
+ }
+
+private:
+ bool Success;
+};
+
+
+// Basic class for comparison operations over expressions.
+template <typename Self>
+class Comparator {
+protected:
+ Self *self() { return reinterpret_cast<Self *>(this); }
+
+public:
+ bool compareByCase(const SExpr *E1, const SExpr* E2) {
+ switch (E1->opcode()) {
+#define TIL_OPCODE_DEF(X) \
+ case COP_##X: \
+ return cast<X>(E1)->compare(cast<X>(E2), *self());
+#include "ThreadSafetyOps.def"
+#undef TIL_OPCODE_DEF
+ }
+ return false;
+ }
+};
+
+
+class EqualsComparator : public Comparator<EqualsComparator> {
+public:
+ // Result type for the comparison, e.g. bool for simple equality,
+ // or int for lexigraphic comparison (-1, 0, 1). Must have one value which
+ // denotes "true".
+ typedef bool CType;
+
+ CType trueResult() { return true; }
+ bool notTrue(CType ct) { return !ct; }
+
+ bool compareIntegers(unsigned i, unsigned j) { return i == j; }
+ bool compareStrings (StringRef s, StringRef r) { return s == r; }
+ bool comparePointers(const void* P, const void* Q) { return P == Q; }
+
+ bool compare(const SExpr *E1, const SExpr* E2) {
+ if (E1->opcode() != E2->opcode())
+ return false;
+ return compareByCase(E1, E2);
+ }
+
+ // TODO -- handle alpha-renaming of variables
+ void enterScope(const Variable* V1, const Variable* V2) { }
+ void leaveScope() { }
+
+ bool compareVariableRefs(const Variable* V1, const Variable* V2) {
+ return V1 == V2;
+ }
+
+ static bool compareExprs(const SExpr *E1, const SExpr* E2) {
+ EqualsComparator Eq;
+ return Eq.compare(E1, E2);
+ }
+};
+
+
+
+class MatchComparator : public Comparator<MatchComparator> {
+public:
+ // Result type for the comparison, e.g. bool for simple equality,
+ // or int for lexigraphic comparison (-1, 0, 1). Must have one value which
+ // denotes "true".
+ typedef bool CType;
+
+ CType trueResult() { return true; }
+ bool notTrue(CType ct) { return !ct; }
+
+ bool compareIntegers(unsigned i, unsigned j) { return i == j; }
+ bool compareStrings (StringRef s, StringRef r) { return s == r; }
+ bool comparePointers(const void* P, const void* Q) { return P == Q; }
+
+ bool compare(const SExpr *E1, const SExpr* E2) {
+ // Wildcards match anything.
+ if (E1->opcode() == COP_Wildcard || E2->opcode() == COP_Wildcard)
+ return true;
+ // otherwise normal equality.
+ if (E1->opcode() != E2->opcode())
+ return false;
+ return compareByCase(E1, E2);
+ }
+
+ // TODO -- handle alpha-renaming of variables
+ void enterScope(const Variable* V1, const Variable* V2) { }
+ void leaveScope() { }
+
+ bool compareVariableRefs(const Variable* V1, const Variable* V2) {
+ return V1 == V2;
+ }
+
+ static bool compareExprs(const SExpr *E1, const SExpr* E2) {
+ MatchComparator Matcher;
+ return Matcher.compare(E1, E2);
+ }
+};
+
+
+
+// inline std::ostream& operator<<(std::ostream& SS, StringRef R) {
+// return SS.write(R.data(), R.size());
+// }
+
+// Pretty printer for TIL expressions
+template <typename Self, typename StreamType>
+class PrettyPrinter {
+private:
+ bool Verbose; // Print out additional information
+ bool Cleanup; // Omit redundant decls.
+ bool CStyle; // Print exprs in C-like syntax.
+
+public:
+ PrettyPrinter(bool V = false, bool C = true, bool CS = true)
+ : Verbose(V), Cleanup(C), CStyle(CS)
+ {}
+
+ static void print(const SExpr *E, StreamType &SS) {
+ Self printer;
+ printer.printSExpr(E, SS, Prec_MAX);
+ }
+
+protected:
+ Self *self() { return reinterpret_cast<Self *>(this); }
+
+ void newline(StreamType &SS) {
+ SS << "\n";
+ }
+
+ // TODO: further distinguish between binary operations.
+ static const unsigned Prec_Atom = 0;
+ static const unsigned Prec_Postfix = 1;
+ static const unsigned Prec_Unary = 2;
+ static const unsigned Prec_Binary = 3;
+ static const unsigned Prec_Other = 4;
+ static const unsigned Prec_Decl = 5;
+ static const unsigned Prec_MAX = 6;
+
+ // Return the precedence of a given node, for use in pretty printing.
+ unsigned precedence(const SExpr *E) {
+ switch (E->opcode()) {
+ case COP_Future: return Prec_Atom;
+ case COP_Undefined: return Prec_Atom;
+ case COP_Wildcard: return Prec_Atom;
+
+ case COP_Literal: return Prec_Atom;
+ case COP_LiteralPtr: return Prec_Atom;
+ case COP_Variable: return Prec_Atom;
+ case COP_Function: return Prec_Decl;
+ case COP_SFunction: return Prec_Decl;
+ case COP_Code: return Prec_Decl;
+ case COP_Field: return Prec_Decl;
+
+ case COP_Apply: return Prec_Postfix;
+ case COP_SApply: return Prec_Postfix;
+ case COP_Project: return Prec_Postfix;
+
+ case COP_Call: return Prec_Postfix;
+ case COP_Alloc: return Prec_Other;
+ case COP_Load: return Prec_Postfix;
+ case COP_Store: return Prec_Other;
+ case COP_ArrayIndex: return Prec_Postfix;
+ case COP_ArrayAdd: return Prec_Postfix;
+
+ case COP_UnaryOp: return Prec_Unary;
+ case COP_BinaryOp: return Prec_Binary;
+ case COP_Cast: return Prec_Atom;
+
+ case COP_SCFG: return Prec_Decl;
+ case COP_BasicBlock: return Prec_MAX;
+ case COP_Phi: return Prec_Atom;
+ case COP_Goto: return Prec_Atom;
+ case COP_Branch: return Prec_Atom;
+ case COP_Return: return Prec_Other;
+
+ case COP_Identifier: return Prec_Atom;
+ case COP_IfThenElse: return Prec_Other;
+ case COP_Let: return Prec_Decl;
+ }
+ return Prec_MAX;
+ }
+
+ void printBlockLabel(StreamType & SS, const BasicBlock *BB, int index) {
+ if (!BB) {
+ SS << "BB_null";
+ return;
+ }
+ SS << "BB_";
+ SS << BB->blockID();
+ if (index >= 0) {
+ SS << ":";
+ SS << index;
+ }
+ }
+
+
+ void printSExpr(const SExpr *E, StreamType &SS, unsigned P, bool Sub=true) {
+ if (!E) {
+ self()->printNull(SS);
+ return;
+ }
+ if (Sub && E->block() && E->opcode() != COP_Variable) {
+ SS << "_x" << E->id();
+ return;
+ }
+ if (self()->precedence(E) > P) {
+ // Wrap expr in () if necessary.
+ SS << "(";
+ self()->printSExpr(E, SS, Prec_MAX);
+ SS << ")";
+ return;
+ }
+
+ switch (E->opcode()) {
+#define TIL_OPCODE_DEF(X) \
+ case COP_##X: \
+ self()->print##X(cast<X>(E), SS); \
+ return;
+#include "ThreadSafetyOps.def"
+#undef TIL_OPCODE_DEF
+ }
+ }
+
+ void printNull(StreamType &SS) {
+ SS << "#null";
+ }
+
+ void printFuture(const Future *E, StreamType &SS) {
+ self()->printSExpr(E->maybeGetResult(), SS, Prec_Atom);
+ }
+
+ void printUndefined(const Undefined *E, StreamType &SS) {
+ SS << "#undefined";
+ }
+
+ void printWildcard(const Wildcard *E, StreamType &SS) {
+ SS << "*";
+ }
+
+ template<class T>
+ void printLiteralT(const LiteralT<T> *E, StreamType &SS) {
+ SS << E->value();
+ }
+
+ void printLiteralT(const LiteralT<uint8_t> *E, StreamType &SS) {
+ SS << "'" << E->value() << "'";
+ }
+
+ void printLiteral(const Literal *E, StreamType &SS) {
+ if (E->clangExpr()) {
+ SS << getSourceLiteralString(E->clangExpr());
+ return;
+ }
+ else {
+ ValueType VT = E->valueType();
+ switch (VT.Base) {
+ case ValueType::BT_Void: {
+ SS << "void";
+ return;
+ }
+ case ValueType::BT_Bool: {
+ if (E->as<bool>().value())
+ SS << "true";
+ else
+ SS << "false";
+ return;
+ }
+ case ValueType::BT_Int: {
+ switch (VT.Size) {
+ case ValueType::ST_8:
+ if (VT.Signed)
+ printLiteralT(&E->as<int8_t>(), SS);
+ else
+ printLiteralT(&E->as<uint8_t>(), SS);
+ return;
+ case ValueType::ST_16:
+ if (VT.Signed)
+ printLiteralT(&E->as<int16_t>(), SS);
+ else
+ printLiteralT(&E->as<uint16_t>(), SS);
+ return;
+ case ValueType::ST_32:
+ if (VT.Signed)
+ printLiteralT(&E->as<int32_t>(), SS);
+ else
+ printLiteralT(&E->as<uint32_t>(), SS);
+ return;
+ case ValueType::ST_64:
+ if (VT.Signed)
+ printLiteralT(&E->as<int64_t>(), SS);
+ else
+ printLiteralT(&E->as<uint64_t>(), SS);
+ return;
+ default:
+ break;
+ }
+ break;
+ }
+ case ValueType::BT_Float: {
+ switch (VT.Size) {
+ case ValueType::ST_32:
+ printLiteralT(&E->as<float>(), SS);
+ return;
+ case ValueType::ST_64:
+ printLiteralT(&E->as<double>(), SS);
+ return;
+ default:
+ break;
+ }
+ break;
+ }
+ case ValueType::BT_String: {
+ SS << "\"";
+ printLiteralT(&E->as<StringRef>(), SS);
+ SS << "\"";
+ return;
+ }
+ case ValueType::BT_Pointer: {
+ SS << "#ptr";
+ return;
+ }
+ case ValueType::BT_ValueRef: {
+ SS << "#vref";
+ return;
+ }
+ }
+ }
+ SS << "#lit";
+ }
+
+ void printLiteralPtr(const LiteralPtr *E, StreamType &SS) {
+ SS << E->clangDecl()->getNameAsString();
+ }
+
+ void printVariable(const Variable *V, StreamType &SS, bool IsVarDecl=false) {
+ if (CStyle && V->kind() == Variable::VK_SFun)
+ SS << "this";
+ else
+ SS << V->name() << V->id();
+ }
+
+ void printFunction(const Function *E, StreamType &SS, unsigned sugared = 0) {
+ switch (sugared) {
+ default:
+ SS << "\\("; // Lambda
+ break;
+ case 1:
+ SS << "("; // Slot declarations
+ break;
+ case 2:
+ SS << ", "; // Curried functions
+ break;
+ }
+ self()->printVariable(E->variableDecl(), SS, true);
+ SS << ": ";
+ self()->printSExpr(E->variableDecl()->definition(), SS, Prec_MAX);
+
+ const SExpr *B = E->body();
+ if (B && B->opcode() == COP_Function)
+ self()->printFunction(cast<Function>(B), SS, 2);
+ else {
+ SS << ")";
+ self()->printSExpr(B, SS, Prec_Decl);
+ }
+ }
+
+ void printSFunction(const SFunction *E, StreamType &SS) {
+ SS << "@";
+ self()->printVariable(E->variableDecl(), SS, true);
+ SS << " ";
+ self()->printSExpr(E->body(), SS, Prec_Decl);
+ }
+
+ void printCode(const Code *E, StreamType &SS) {
+ SS << ": ";
+ self()->printSExpr(E->returnType(), SS, Prec_Decl-1);
+ SS << " -> ";
+ self()->printSExpr(E->body(), SS, Prec_Decl);
+ }
+
+ void printField(const Field *E, StreamType &SS) {
+ SS << ": ";
+ self()->printSExpr(E->range(), SS, Prec_Decl-1);
+ SS << " = ";
+ self()->printSExpr(E->body(), SS, Prec_Decl);
+ }
+
+ void printApply(const Apply *E, StreamType &SS, bool sugared = false) {
+ const SExpr *F = E->fun();
+ if (F->opcode() == COP_Apply) {
+ printApply(cast<Apply>(F), SS, true);
+ SS << ", ";
+ } else {
+ self()->printSExpr(F, SS, Prec_Postfix);
+ SS << "(";
+ }
+ self()->printSExpr(E->arg(), SS, Prec_MAX);
+ if (!sugared)
+ SS << ")$";
+ }
+
+ void printSApply(const SApply *E, StreamType &SS) {
+ self()->printSExpr(E->sfun(), SS, Prec_Postfix);
+ if (E->isDelegation()) {
+ SS << "@(";
+ self()->printSExpr(E->arg(), SS, Prec_MAX);
+ SS << ")";
+ }
+ }
+
+ void printProject(const Project *E, StreamType &SS) {
+ if (CStyle) {
+ // Omit the this->
+ if (const SApply *SAP = dyn_cast<SApply>(E->record())) {
+ if (const Variable *V = dyn_cast<Variable>(SAP->sfun())) {
+ if (!SAP->isDelegation() && V->kind() == Variable::VK_SFun) {
+ SS << E->slotName();
+ return;
+ }
+ }
+ }
+ if (isa<Wildcard>(E->record())) {
+ // handle existentials
+ SS << "&";
+ SS << E->clangDecl()->getQualifiedNameAsString();
+ return;
+ }
+ }
+ self()->printSExpr(E->record(), SS, Prec_Postfix);
+ if (CStyle && E->isArrow()) {
+ SS << "->";
+ }
+ else {
+ SS << ".";
+ }
+ SS << E->slotName();
+ }
+
+ void printCall(const Call *E, StreamType &SS) {
+ const SExpr *T = E->target();
+ if (T->opcode() == COP_Apply) {
+ self()->printApply(cast<Apply>(T), SS, true);
+ SS << ")";
+ }
+ else {
+ self()->printSExpr(T, SS, Prec_Postfix);
+ SS << "()";
+ }
+ }
+
+ void printAlloc(const Alloc *E, StreamType &SS) {
+ SS << "new ";
+ self()->printSExpr(E->dataType(), SS, Prec_Other-1);
+ }
+
+ void printLoad(const Load *E, StreamType &SS) {
+ self()->printSExpr(E->pointer(), SS, Prec_Postfix);
+ if (!CStyle)
+ SS << "^";
+ }
+
+ void printStore(const Store *E, StreamType &SS) {
+ self()->printSExpr(E->destination(), SS, Prec_Other-1);
+ SS << " := ";
+ self()->printSExpr(E->source(), SS, Prec_Other-1);
+ }
+
+ void printArrayIndex(const ArrayIndex *E, StreamType &SS) {
+ self()->printSExpr(E->array(), SS, Prec_Postfix);
+ SS << "[";
+ self()->printSExpr(E->index(), SS, Prec_MAX);
+ SS << "]";
+ }
+
+ void printArrayAdd(const ArrayAdd *E, StreamType &SS) {
+ self()->printSExpr(E->array(), SS, Prec_Postfix);
+ SS << " + ";
+ self()->printSExpr(E->index(), SS, Prec_Atom);
+ }
+
+ void printUnaryOp(const UnaryOp *E, StreamType &SS) {
+ SS << getUnaryOpcodeString(E->unaryOpcode());
+ self()->printSExpr(E->expr(), SS, Prec_Unary);
+ }
+
+ void printBinaryOp(const BinaryOp *E, StreamType &SS) {
+ self()->printSExpr(E->expr0(), SS, Prec_Binary-1);
+ SS << " " << getBinaryOpcodeString(E->binaryOpcode()) << " ";
+ self()->printSExpr(E->expr1(), SS, Prec_Binary-1);
+ }
+
+ void printCast(const Cast *E, StreamType &SS) {
+ if (!CStyle) {
+ SS << "cast[";
+ SS << E->castOpcode();
+ SS << "](";
+ self()->printSExpr(E->expr(), SS, Prec_Unary);
+ SS << ")";
+ return;
+ }
+ self()->printSExpr(E->expr(), SS, Prec_Unary);
+ }
+
+ void printSCFG(const SCFG *E, StreamType &SS) {
+ SS << "CFG {\n";
+ for (auto BBI : *E) {
+ printBasicBlock(BBI, SS);
+ }
+ SS << "}";
+ newline(SS);
+ }
+
+
+ void printBBInstr(const SExpr *E, StreamType &SS) {
+ bool Sub = false;
+ if (E->opcode() == COP_Variable) {
+ auto *V = cast<Variable>(E);
+ SS << "let " << V->name() << V->id() << " = ";
+ E = V->definition();
+ Sub = true;
+ }
+ else if (E->opcode() != COP_Store) {
+ SS << "let _x" << E->id() << " = ";
+ }
+ self()->printSExpr(E, SS, Prec_MAX, Sub);
+ SS << ";";
+ newline(SS);
+ }
+
+ void printBasicBlock(const BasicBlock *E, StreamType &SS) {
+ SS << "BB_" << E->blockID() << ":";
+ if (E->parent())
+ SS << " BB_" << E->parent()->blockID();
+ newline(SS);
+
+ for (auto *A : E->arguments())
+ printBBInstr(A, SS);
+
+ for (auto *I : E->instructions())
+ printBBInstr(I, SS);
+
+ const SExpr *T = E->terminator();
+ if (T) {
+ self()->printSExpr(T, SS, Prec_MAX, false);
+ SS << ";";
+ newline(SS);
+ }
+ newline(SS);
+ }
+
+ void printPhi(const Phi *E, StreamType &SS) {
+ SS << "phi(";
+ if (E->status() == Phi::PH_SingleVal)
+ self()->printSExpr(E->values()[0], SS, Prec_MAX);
+ else {
+ unsigned i = 0;
+ for (auto V : E->values()) {
+ if (i++ > 0)
+ SS << ", ";
+ self()->printSExpr(V, SS, Prec_MAX);
+ }
+ }
+ SS << ")";
+ }
+
+ void printGoto(const Goto *E, StreamType &SS) {
+ SS << "goto ";
+ printBlockLabel(SS, E->targetBlock(), E->index());
+ }
+
+ void printBranch(const Branch *E, StreamType &SS) {
+ SS << "branch (";
+ self()->printSExpr(E->condition(), SS, Prec_MAX);
+ SS << ") ";
+ printBlockLabel(SS, E->thenBlock(), -1);
+ SS << " ";
+ printBlockLabel(SS, E->elseBlock(), -1);
+ }
+
+ void printReturn(const Return *E, StreamType &SS) {
+ SS << "return ";
+ self()->printSExpr(E->returnValue(), SS, Prec_Other);
+ }
+
+ void printIdentifier(const Identifier *E, StreamType &SS) {
+ SS << E->name();
+ }
+
+ void printIfThenElse(const IfThenElse *E, StreamType &SS) {
+ if (CStyle) {
+ printSExpr(E->condition(), SS, Prec_Unary);
+ SS << " ? ";
+ printSExpr(E->thenExpr(), SS, Prec_Unary);
+ SS << " : ";
+ printSExpr(E->elseExpr(), SS, Prec_Unary);
+ return;
+ }
+ SS << "if (";
+ printSExpr(E->condition(), SS, Prec_MAX);
+ SS << ") then ";
+ printSExpr(E->thenExpr(), SS, Prec_Other);
+ SS << " else ";
+ printSExpr(E->elseExpr(), SS, Prec_Other);
+ }
+
+ void printLet(const Let *E, StreamType &SS) {
+ SS << "let ";
+ printVariable(E->variableDecl(), SS, true);
+ SS << " = ";
+ printSExpr(E->variableDecl()->definition(), SS, Prec_Decl-1);
+ SS << "; ";
+ printSExpr(E->body(), SS, Prec_Decl-1);
+ }
+};
+
+
+class StdPrinter : public PrettyPrinter<StdPrinter, std::ostream> { };
+
+
+
+} // end namespace til
+} // end namespace threadSafety
+} // end namespace clang
+
+#endif // LLVM_CLANG_THREAD_SAFETY_TRAVERSE_H
diff --git a/contrib/llvm/tools/clang/include/clang/Analysis/Analyses/ThreadSafetyUtil.h b/contrib/llvm/tools/clang/include/clang/Analysis/Analyses/ThreadSafetyUtil.h
new file mode 100644
index 0000000..4d3402f
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Analysis/Analyses/ThreadSafetyUtil.h
@@ -0,0 +1,358 @@
+//===- ThreadSafetyUtil.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 some basic utility classes for use by ThreadSafetyTIL.h
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_ANALYSIS_ANALYSES_THREADSAFETYUTIL_H
+#define LLVM_CLANG_ANALYSIS_ANALYSES_THREADSAFETYUTIL_H
+
+#include "clang/AST/ExprCXX.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/Support/AlignOf.h"
+#include "llvm/Support/Allocator.h"
+#include "llvm/Support/Compiler.h"
+#include <cassert>
+#include <cstddef>
+#include <ostream>
+#include <utility>
+#include <vector>
+
+namespace clang {
+namespace threadSafety {
+namespace til {
+
+// Simple wrapper class to abstract away from the details of memory management.
+// SExprs are allocated in pools, and deallocated all at once.
+class MemRegionRef {
+private:
+ union AlignmentType {
+ double d;
+ void *p;
+ long double dd;
+ long long ii;
+ };
+
+public:
+ MemRegionRef() : Allocator(nullptr) {}
+ MemRegionRef(llvm::BumpPtrAllocator *A) : Allocator(A) {}
+
+ void *allocate(size_t Sz) {
+ return Allocator->Allocate(Sz, llvm::AlignOf<AlignmentType>::Alignment);
+ }
+
+ template <typename T> T *allocateT() { return Allocator->Allocate<T>(); }
+
+ template <typename T> T *allocateT(size_t NumElems) {
+ return Allocator->Allocate<T>(NumElems);
+ }
+
+private:
+ llvm::BumpPtrAllocator *Allocator;
+};
+
+
+} // end namespace til
+} // end namespace threadSafety
+} // end namespace clang
+
+
+inline void *operator new(size_t Sz,
+ clang::threadSafety::til::MemRegionRef &R) {
+ return R.allocate(Sz);
+}
+
+
+namespace clang {
+namespace threadSafety {
+
+std::string getSourceLiteralString(const clang::Expr *CE);
+
+using llvm::StringRef;
+using clang::SourceLocation;
+
+namespace til {
+
+
+// A simple fixed size array class that does not manage its own memory,
+// suitable for use with bump pointer allocation.
+template <class T> class SimpleArray {
+public:
+ SimpleArray() : Data(nullptr), Size(0), Capacity(0) {}
+ SimpleArray(T *Dat, size_t Cp, size_t Sz = 0)
+ : Data(Dat), Size(Sz), Capacity(Cp) {}
+ SimpleArray(MemRegionRef A, size_t Cp)
+ : Data(Cp == 0 ? nullptr : A.allocateT<T>(Cp)), Size(0), Capacity(Cp) {}
+ SimpleArray(SimpleArray<T> &&A)
+ : Data(A.Data), Size(A.Size), Capacity(A.Capacity) {
+ A.Data = nullptr;
+ A.Size = 0;
+ A.Capacity = 0;
+ }
+
+ SimpleArray &operator=(SimpleArray &&RHS) {
+ if (this != &RHS) {
+ Data = RHS.Data;
+ Size = RHS.Size;
+ Capacity = RHS.Capacity;
+
+ RHS.Data = nullptr;
+ RHS.Size = RHS.Capacity = 0;
+ }
+ return *this;
+ }
+
+ // Reserve space for at least Ncp items, reallocating if necessary.
+ void reserve(size_t Ncp, MemRegionRef A) {
+ if (Ncp <= Capacity)
+ return;
+ T *Odata = Data;
+ Data = A.allocateT<T>(Ncp);
+ Capacity = Ncp;
+ memcpy(Data, Odata, sizeof(T) * Size);
+ return;
+ }
+
+ // Reserve space for at least N more items.
+ void reserveCheck(size_t N, MemRegionRef A) {
+ if (Capacity == 0)
+ reserve(u_max(InitialCapacity, N), A);
+ else if (Size + N < Capacity)
+ reserve(u_max(Size + N, Capacity * 2), A);
+ }
+
+ typedef T *iterator;
+ typedef const T *const_iterator;
+ typedef std::reverse_iterator<iterator> reverse_iterator;
+ typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
+
+ size_t size() const { return Size; }
+ size_t capacity() const { return Capacity; }
+
+ T &operator[](unsigned i) {
+ assert(i < Size && "Array index out of bounds.");
+ return Data[i];
+ }
+ const T &operator[](unsigned i) const {
+ assert(i < Size && "Array index out of bounds.");
+ return Data[i];
+ }
+ T &back() {
+ assert(Size && "No elements in the array.");
+ return Data[Size - 1];
+ }
+ const T &back() const {
+ assert(Size && "No elements in the array.");
+ return Data[Size - 1];
+ }
+
+ iterator begin() { return Data; }
+ iterator end() { return Data + Size; }
+
+ const_iterator begin() const { return Data; }
+ const_iterator end() const { return Data + Size; }
+
+ const_iterator cbegin() const { return Data; }
+ const_iterator cend() const { return Data + Size; }
+
+ reverse_iterator rbegin() { return reverse_iterator(end()); }
+ reverse_iterator rend() { return reverse_iterator(begin()); }
+
+ const_reverse_iterator rbegin() const {
+ return const_reverse_iterator(end());
+ }
+ const_reverse_iterator rend() const {
+ return const_reverse_iterator(begin());
+ }
+
+ void push_back(const T &Elem) {
+ assert(Size < Capacity);
+ Data[Size++] = Elem;
+ }
+
+ // drop last n elements from array
+ void drop(unsigned n = 0) {
+ assert(Size > n);
+ Size -= n;
+ }
+
+ void setValues(unsigned Sz, const T& C) {
+ assert(Sz <= Capacity);
+ Size = Sz;
+ for (unsigned i = 0; i < Sz; ++i) {
+ Data[i] = C;
+ }
+ }
+
+ template <class Iter> unsigned append(Iter I, Iter E) {
+ size_t Osz = Size;
+ size_t J = Osz;
+ for (; J < Capacity && I != E; ++J, ++I)
+ Data[J] = *I;
+ Size = J;
+ return J - Osz;
+ }
+
+ llvm::iterator_range<reverse_iterator> reverse() {
+ return llvm::make_range(rbegin(), rend());
+ }
+ llvm::iterator_range<const_reverse_iterator> reverse() const {
+ return llvm::make_range(rbegin(), rend());
+ }
+
+private:
+ // std::max is annoying here, because it requires a reference,
+ // thus forcing InitialCapacity to be initialized outside the .h file.
+ size_t u_max(size_t i, size_t j) { return (i < j) ? j : i; }
+
+ static const size_t InitialCapacity = 4;
+
+ SimpleArray(const SimpleArray<T> &A) = delete;
+
+ T *Data;
+ size_t Size;
+ size_t Capacity;
+};
+
+
+} // end namespace til
+
+
+// A copy on write vector.
+// The vector can be in one of three states:
+// * invalid -- no operations are permitted.
+// * read-only -- read operations are permitted.
+// * writable -- read and write operations are permitted.
+// The init(), destroy(), and makeWritable() methods will change state.
+template<typename T>
+class CopyOnWriteVector {
+ class VectorData {
+ public:
+ VectorData() : NumRefs(1) { }
+ VectorData(const VectorData &VD) : NumRefs(1), Vect(VD.Vect) { }
+
+ unsigned NumRefs;
+ std::vector<T> Vect;
+ };
+
+ // No copy constructor or copy assignment. Use clone() with move assignment.
+ CopyOnWriteVector(const CopyOnWriteVector &V) = delete;
+ void operator=(const CopyOnWriteVector &V) = delete;
+
+public:
+ CopyOnWriteVector() : Data(nullptr) {}
+ CopyOnWriteVector(CopyOnWriteVector &&V) : Data(V.Data) { V.Data = nullptr; }
+ ~CopyOnWriteVector() { destroy(); }
+
+ // Returns true if this holds a valid vector.
+ bool valid() const { return Data; }
+
+ // Returns true if this vector is writable.
+ bool writable() const { return Data && Data->NumRefs == 1; }
+
+ // If this vector is not valid, initialize it to a valid vector.
+ void init() {
+ if (!Data) {
+ Data = new VectorData();
+ }
+ }
+
+ // Destroy this vector; thus making it invalid.
+ void destroy() {
+ if (!Data)
+ return;
+ if (Data->NumRefs <= 1)
+ delete Data;
+ else
+ --Data->NumRefs;
+ Data = nullptr;
+ }
+
+ // Make this vector writable, creating a copy if needed.
+ void makeWritable() {
+ if (!Data) {
+ Data = new VectorData();
+ return;
+ }
+ if (Data->NumRefs == 1)
+ return; // already writeable.
+ --Data->NumRefs;
+ Data = new VectorData(*Data);
+ }
+
+ // Create a lazy copy of this vector.
+ CopyOnWriteVector clone() { return CopyOnWriteVector(Data); }
+
+ CopyOnWriteVector &operator=(CopyOnWriteVector &&V) {
+ destroy();
+ Data = V.Data;
+ V.Data = nullptr;
+ return *this;
+ }
+
+ typedef typename std::vector<T>::const_iterator const_iterator;
+
+ const std::vector<T> &elements() const { return Data->Vect; }
+
+ const_iterator begin() const { return elements().cbegin(); }
+ const_iterator end() const { return elements().cend(); }
+
+ const T& operator[](unsigned i) const { return elements()[i]; }
+
+ unsigned size() const { return Data ? elements().size() : 0; }
+
+ // Return true if V and this vector refer to the same data.
+ bool sameAs(const CopyOnWriteVector &V) const { return Data == V.Data; }
+
+ // Clear vector. The vector must be writable.
+ void clear() {
+ assert(writable() && "Vector is not writable!");
+ Data->Vect.clear();
+ }
+
+ // Push a new element onto the end. The vector must be writable.
+ void push_back(const T &Elem) {
+ assert(writable() && "Vector is not writable!");
+ Data->Vect.push_back(Elem);
+ }
+
+ // Gets a mutable reference to the element at index(i).
+ // The vector must be writable.
+ T& elem(unsigned i) {
+ assert(writable() && "Vector is not writable!");
+ return Data->Vect[i];
+ }
+
+ // Drops elements from the back until the vector has size i.
+ void downsize(unsigned i) {
+ assert(writable() && "Vector is not writable!");
+ Data->Vect.erase(Data->Vect.begin() + i, Data->Vect.end());
+ }
+
+private:
+ CopyOnWriteVector(VectorData *D) : Data(D) {
+ if (!Data)
+ return;
+ ++Data->NumRefs;
+ }
+
+ VectorData *Data;
+};
+
+
+inline std::ostream& operator<<(std::ostream& ss, const StringRef str) {
+ return ss.write(str.data(), str.size());
+}
+
+
+} // end namespace threadSafety
+} // end namespace clang
+
+#endif // LLVM_CLANG_THREAD_SAFETY_UTIL_H
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..53ff20c
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Analysis/Analyses/UninitializedValues.h
@@ -0,0 +1,126 @@
+//= UninitializedValues.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_ANALYSIS_ANALYSES_UNINITIALIZEDVALUES_H
+#define LLVM_CLANG_ANALYSIS_ANALYSES_UNINITIALIZEDVALUES_H
+
+#include "clang/AST/Stmt.h"
+#include "llvm/ADT/SmallVector.h"
+
+namespace clang {
+
+class AnalysisDeclContext;
+class CFG;
+class DeclContext;
+class Expr;
+class VarDecl;
+
+/// A use of a variable, which might be uninitialized.
+class UninitUse {
+public:
+ struct Branch {
+ const Stmt *Terminator;
+ unsigned Output;
+ };
+
+private:
+ /// The expression which uses this variable.
+ const Expr *User;
+
+ /// Is this use uninitialized whenever the function is called?
+ bool UninitAfterCall;
+
+ /// Is this use uninitialized whenever the variable declaration is reached?
+ bool UninitAfterDecl;
+
+ /// Does this use always see an uninitialized value?
+ bool AlwaysUninit;
+
+ /// This use is always uninitialized if it occurs after any of these branches
+ /// is taken.
+ SmallVector<Branch, 2> UninitBranches;
+
+public:
+ UninitUse(const Expr *User, bool AlwaysUninit)
+ : User(User), UninitAfterCall(false), UninitAfterDecl(false),
+ AlwaysUninit(AlwaysUninit) {}
+
+ void addUninitBranch(Branch B) {
+ UninitBranches.push_back(B);
+ }
+
+ void setUninitAfterCall() { UninitAfterCall = true; }
+ void setUninitAfterDecl() { UninitAfterDecl = true; }
+
+ /// Get the expression containing the uninitialized use.
+ const Expr *getUser() const { return User; }
+
+ /// The kind of uninitialized use.
+ enum Kind {
+ /// The use might be uninitialized.
+ Maybe,
+ /// The use is uninitialized whenever a certain branch is taken.
+ Sometimes,
+ /// The use is uninitialized the first time it is reached after we reach
+ /// the variable's declaration.
+ AfterDecl,
+ /// The use is uninitialized the first time it is reached after the function
+ /// is called.
+ AfterCall,
+ /// The use is always uninitialized.
+ Always
+ };
+
+ /// Get the kind of uninitialized use.
+ Kind getKind() const {
+ return AlwaysUninit ? Always :
+ UninitAfterCall ? AfterCall :
+ UninitAfterDecl ? AfterDecl :
+ !branch_empty() ? Sometimes : Maybe;
+ }
+
+ typedef SmallVectorImpl<Branch>::const_iterator branch_iterator;
+ /// Branches which inevitably result in the variable being used uninitialized.
+ branch_iterator branch_begin() const { return UninitBranches.begin(); }
+ branch_iterator branch_end() const { return UninitBranches.end(); }
+ bool branch_empty() const { return UninitBranches.empty(); }
+};
+
+class UninitVariablesHandler {
+public:
+ UninitVariablesHandler() {}
+ virtual ~UninitVariablesHandler();
+
+ /// Called when the uninitialized variable is used at the given expression.
+ virtual void handleUseOfUninitVariable(const VarDecl *vd,
+ const UninitUse &use) {}
+
+ /// Called when the uninitialized variable analysis detects the
+ /// idiom 'int x = x'. All other uses of 'x' within the initializer
+ /// are handled by handleUseOfUninitVariable.
+ virtual void handleSelfInit(const VarDecl *vd) {}
+};
+
+struct UninitVariablesAnalysisStats {
+ unsigned NumVariablesAnalyzed;
+ unsigned NumBlockVisits;
+};
+
+void runUninitializedVariablesAnalysis(const DeclContext &dc, const CFG &cfg,
+ AnalysisDeclContext &ac,
+ UninitVariablesHandler &handler,
+ UninitVariablesAnalysisStats &stats);
+
+}
+#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..931190e
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Analysis/AnalysisContext.h
@@ -0,0 +1,480 @@
+//=== 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 AnalysisDeclContext, 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/Analysis/CFG.h"
+#include "clang/Analysis/CodeInjector.h"
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/FoldingSet.h"
+#include "llvm/Support/Allocator.h"
+#include <memory>
+
+namespace clang {
+
+class Stmt;
+class CFGReverseBlockReachabilityAnalysis;
+class CFGStmtMap;
+class LiveVariables;
+class ManagedAnalysis;
+class ParentMap;
+class PseudoConstantAnalysis;
+class LocationContextManager;
+class StackFrameContext;
+class BlockInvocationContext;
+class AnalysisDeclContextManager;
+class LocationContext;
+
+namespace idx { class TranslationUnit; }
+
+/// The base class of a hierarchy of objects representing analyses tied
+/// to AnalysisDeclContext.
+class ManagedAnalysis {
+protected:
+ ManagedAnalysis() {}
+public:
+ virtual ~ManagedAnalysis();
+
+ // Subclasses need to implement:
+ //
+ // static const void *getTag();
+ //
+ // Which returns a fixed pointer address to distinguish classes of
+ // analysis objects. They also need to implement:
+ //
+ // static [Derived*] create(AnalysisDeclContext &Ctx);
+ //
+ // which creates the analysis object given an AnalysisDeclContext.
+};
+
+
+/// AnalysisDeclContext contains the context data for the function or method
+/// under analysis.
+class AnalysisDeclContext {
+ /// Backpoint to the AnalysisManager object that created this
+ /// AnalysisDeclContext. This may be null.
+ AnalysisDeclContextManager *Manager;
+
+ const Decl * const D;
+
+ std::unique_ptr<CFG> cfg, completeCFG;
+ std::unique_ptr<CFGStmtMap> cfgStmtMap;
+
+ CFG::BuildOptions cfgBuildOptions;
+ CFG::BuildOptions::ForcedBlkExprs *forcedBlkExprs;
+
+ bool builtCFG, builtCompleteCFG;
+ std::unique_ptr<ParentMap> PM;
+ std::unique_ptr<PseudoConstantAnalysis> PCA;
+ std::unique_ptr<CFGReverseBlockReachabilityAnalysis> CFA;
+
+ llvm::BumpPtrAllocator A;
+
+ llvm::DenseMap<const BlockDecl*,void*> *ReferencedBlockVars;
+
+ void *ManagedAnalyses;
+
+public:
+ AnalysisDeclContext(AnalysisDeclContextManager *Mgr,
+ const Decl *D);
+
+ AnalysisDeclContext(AnalysisDeclContextManager *Mgr,
+ const Decl *D,
+ const CFG::BuildOptions &BuildOptions);
+
+ ~AnalysisDeclContext();
+
+ ASTContext &getASTContext() const { return D->getASTContext(); }
+ const Decl *getDecl() const { return D; }
+
+ /// Return the AnalysisDeclContextManager (if any) that created
+ /// this AnalysisDeclContext.
+ AnalysisDeclContextManager *getManager() const {
+ return Manager;
+ }
+
+ /// Return the build options used to construct the CFG.
+ CFG::BuildOptions &getCFGBuildOptions() {
+ return cfgBuildOptions;
+ }
+
+ const CFG::BuildOptions &getCFGBuildOptions() const {
+ return cfgBuildOptions;
+ }
+
+ /// 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 cfgBuildOptions.AddEHEdges; }
+ bool getUseUnoptimizedCFG() const {
+ return !cfgBuildOptions.PruneTriviallyFalseEdges;
+ }
+ bool getAddImplicitDtors() const { return cfgBuildOptions.AddImplicitDtors; }
+ bool getAddInitializers() const { return cfgBuildOptions.AddInitializers; }
+
+ void registerForcedBlockExpression(const Stmt *stmt);
+ const CFGBlock *getBlockForRegisteredExpression(const Stmt *stmt);
+
+ /// \brief Get the body of the Declaration.
+ Stmt *getBody() const;
+
+ /// \brief Get the body of the Declaration.
+ /// \param[out] IsAutosynthesized Specifies if the body is auto-generated
+ /// by the BodyFarm.
+ Stmt *getBody(bool &IsAutosynthesized) const;
+
+ /// \brief Checks if the body of the Decl is generated by the BodyFarm.
+ ///
+ /// Note, the lookup is not free. We are going to call getBody behind
+ /// the scenes.
+ /// \sa getBody
+ bool isBodyAutosynthesized() const;
+
+ /// \brief Checks if the body of the Decl is generated by the BodyFarm from a
+ /// model file.
+ ///
+ /// Note, the lookup is not free. We are going to call getBody behind
+ /// the scenes.
+ /// \sa getBody
+ bool isBodyAutosynthesizedFromModelFile() const;
+
+ CFG *getCFG();
+
+ CFGStmtMap *getCFGStmtMap();
+
+ CFGReverseBlockReachabilityAnalysis *getCFGReachablityAnalysis();
+
+ /// Return a version of the CFG without any edges pruned.
+ CFG *getUnoptimizedCFG();
+
+ void dumpCFG(bool ShowColors);
+
+ /// \brief Returns true if we have built a CFG for this analysis context.
+ /// Note that this doesn't correspond to whether or not a valid CFG exists, it
+ /// corresponds to whether we *attempted* to build one.
+ bool isCFGBuilt() const { return builtCFG; }
+
+ ParentMap &getParentMap();
+ PseudoConstantAnalysis *getPseudoConstantAnalysis();
+
+ typedef const VarDecl * const * referenced_decls_iterator;
+
+ llvm::iterator_range<referenced_decls_iterator>
+ getReferencedBlockVars(const BlockDecl *BD);
+
+ /// Return the ImplicitParamDecl* associated with 'self' if this
+ /// AnalysisDeclContext wraps an ObjCMethodDecl. Returns NULL otherwise.
+ const ImplicitParamDecl *getSelfDecl() const;
+
+ const StackFrameContext *getStackFrame(LocationContext const *Parent,
+ const Stmt *S,
+ const CFGBlock *Blk,
+ unsigned Idx);
+
+ const BlockInvocationContext *
+ getBlockInvocationContext(const LocationContext *parent,
+ const BlockDecl *BD,
+ const void *ContextData);
+
+ /// Return the specified analysis object, lazily running the analysis if
+ /// necessary. Return NULL if the analysis could not run.
+ template <typename T>
+ T *getAnalysis() {
+ const void *tag = T::getTag();
+ ManagedAnalysis *&data = getAnalysisImpl(tag);
+ if (!data) {
+ data = T::create(*this);
+ }
+ return static_cast<T*>(data);
+ }
+private:
+ ManagedAnalysis *&getAnalysisImpl(const void* tag);
+
+ LocationContextManager &getLocationContextManager();
+};
+
+class LocationContext : public llvm::FoldingSetNode {
+public:
+ enum ContextKind { StackFrame, Scope, Block };
+
+private:
+ ContextKind Kind;
+
+ // AnalysisDeclContext can't be const since some methods may modify its
+ // member.
+ AnalysisDeclContext *Ctx;
+
+ const LocationContext *Parent;
+
+protected:
+ LocationContext(ContextKind k, AnalysisDeclContext *ctx,
+ const LocationContext *parent)
+ : Kind(k), Ctx(ctx), Parent(parent) {}
+
+public:
+ virtual ~LocationContext();
+
+ ContextKind getKind() const { return Kind; }
+
+ AnalysisDeclContext *getAnalysisDeclContext() const { return Ctx; }
+
+ const LocationContext *getParent() const { return Parent; }
+
+ bool isParentOf(const LocationContext *LC) const;
+
+ const Decl *getDecl() const { return getAnalysisDeclContext()->getDecl(); }
+
+ CFG *getCFG() const { return getAnalysisDeclContext()->getCFG(); }
+
+ template <typename T>
+ T *getAnalysis() const {
+ return getAnalysisDeclContext()->getAnalysis<T>();
+ }
+
+ ParentMap &getParentMap() const {
+ return getAnalysisDeclContext()->getParentMap();
+ }
+
+ const ImplicitParamDecl *getSelfDecl() const {
+ return Ctx->getSelfDecl();
+ }
+
+ const StackFrameContext *getCurrentStackFrame() const;
+
+ /// Return true if the current LocationContext has no caller context.
+ virtual bool inTopFrame() const;
+
+ virtual void Profile(llvm::FoldingSetNodeID &ID) = 0;
+
+ void dumpStack(raw_ostream &OS, StringRef Indent = "") const;
+ void dumpStack() const;
+
+public:
+ static void ProfileCommon(llvm::FoldingSetNodeID &ID,
+ ContextKind ck,
+ AnalysisDeclContext *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(AnalysisDeclContext *ctx, const LocationContext *parent,
+ const Stmt *s, const CFGBlock *blk,
+ unsigned idx)
+ : LocationContext(StackFrame, ctx, parent), CallSite(s),
+ Block(blk), Index(idx) {}
+
+public:
+ ~StackFrameContext() override {}
+
+ const Stmt *getCallSite() const { return CallSite; }
+
+ const CFGBlock *getCallSiteBlock() const { return Block; }
+
+ /// Return true if the current LocationContext has no caller context.
+ bool inTopFrame() const override { return getParent() == nullptr; }
+
+ unsigned getIndex() const { return Index; }
+
+ void Profile(llvm::FoldingSetNodeID &ID) override;
+
+ static void Profile(llvm::FoldingSetNodeID &ID, AnalysisDeclContext *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(AnalysisDeclContext *ctx, const LocationContext *parent,
+ const Stmt *s)
+ : LocationContext(Scope, ctx, parent), Enter(s) {}
+
+public:
+ ~ScopeContext() override {}
+
+ void Profile(llvm::FoldingSetNodeID &ID) override;
+
+ static void Profile(llvm::FoldingSetNodeID &ID, AnalysisDeclContext *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 {
+ const BlockDecl *BD;
+
+ // FIXME: Come up with a more type-safe way to model context-sensitivity.
+ const void *ContextData;
+
+ friend class LocationContextManager;
+
+ BlockInvocationContext(AnalysisDeclContext *ctx,
+ const LocationContext *parent,
+ const BlockDecl *bd, const void *contextData)
+ : LocationContext(Block, ctx, parent), BD(bd), ContextData(contextData) {}
+
+public:
+ ~BlockInvocationContext() override {}
+
+ const BlockDecl *getBlockDecl() const { return BD; }
+
+ const void *getContextData() const { return ContextData; }
+
+ void Profile(llvm::FoldingSetNodeID &ID) override;
+
+ static void Profile(llvm::FoldingSetNodeID &ID, AnalysisDeclContext *ctx,
+ const LocationContext *parent, const BlockDecl *bd,
+ const void *contextData) {
+ ProfileCommon(ID, Block, ctx, parent, bd);
+ ID.AddPointer(contextData);
+ }
+
+ static bool classof(const LocationContext *Ctx) {
+ return Ctx->getKind() == Block;
+ }
+};
+
+class LocationContextManager {
+ llvm::FoldingSet<LocationContext> Contexts;
+public:
+ ~LocationContextManager();
+
+ const StackFrameContext *getStackFrame(AnalysisDeclContext *ctx,
+ const LocationContext *parent,
+ const Stmt *s,
+ const CFGBlock *blk, unsigned idx);
+
+ const ScopeContext *getScope(AnalysisDeclContext *ctx,
+ const LocationContext *parent,
+ const Stmt *s);
+
+ const BlockInvocationContext *
+ getBlockInvocationContext(AnalysisDeclContext *ctx,
+ const LocationContext *parent,
+ const BlockDecl *BD,
+ const void *ContextData);
+
+ /// Discard all previously created LocationContext objects.
+ void clear();
+private:
+ template <typename LOC, typename DATA>
+ const LOC *getLocationContext(AnalysisDeclContext *ctx,
+ const LocationContext *parent,
+ const DATA *d);
+};
+
+class AnalysisDeclContextManager {
+ typedef llvm::DenseMap<const Decl*, AnalysisDeclContext*> ContextMap;
+
+ ContextMap Contexts;
+ LocationContextManager LocContexts;
+ CFG::BuildOptions cfgBuildOptions;
+
+ /// Pointer to an interface that can provide function bodies for
+ /// declarations from external source.
+ std::unique_ptr<CodeInjector> Injector;
+
+ /// Flag to indicate whether or not bodies should be synthesized
+ /// for well-known functions.
+ bool SynthesizeBodies;
+
+public:
+ AnalysisDeclContextManager(bool useUnoptimizedCFG = false,
+ bool addImplicitDtors = false,
+ bool addInitializers = false,
+ bool addTemporaryDtors = false,
+ bool synthesizeBodies = false,
+ bool addStaticInitBranches = false,
+ bool addCXXNewAllocator = true,
+ CodeInjector* injector = nullptr);
+
+ ~AnalysisDeclContextManager();
+
+ AnalysisDeclContext *getContext(const Decl *D);
+
+ bool getUseUnoptimizedCFG() const {
+ return !cfgBuildOptions.PruneTriviallyFalseEdges;
+ }
+
+ CFG::BuildOptions &getCFGBuildOptions() {
+ return cfgBuildOptions;
+ }
+
+ /// Return true if faux bodies should be synthesized for well-known
+ /// functions.
+ bool synthesizeBodies() const { return SynthesizeBodies; }
+
+ const StackFrameContext *getStackFrame(AnalysisDeclContext *Ctx,
+ LocationContext const *Parent,
+ const Stmt *S,
+ const CFGBlock *Blk,
+ unsigned Idx) {
+ return LocContexts.getStackFrame(Ctx, Parent, S, Blk, Idx);
+ }
+
+ // Get the top level stack frame.
+ const StackFrameContext *getStackFrame(const Decl *D) {
+ return LocContexts.getStackFrame(getContext(D), nullptr, nullptr, nullptr,
+ 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 LocContexts.getStackFrame(getContext(D), Parent, S, Blk, Idx);
+ }
+
+ /// Discard all previously created AnalysisDeclContexts.
+ void clear();
+
+private:
+ friend class AnalysisDeclContext;
+
+ LocationContextManager &getLocationContextManager() {
+ return LocContexts;
+ }
+};
+
+} // 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..8d28971
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Analysis/AnalysisDiagnostic.h
@@ -0,0 +1,28 @@
+//===--- 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_ANALYSIS_ANALYSISDIAGNOSTIC_H
+#define LLVM_CLANG_ANALYSIS_ANALYSISDIAGNOSTIC_H
+
+#include "clang/Basic/Diagnostic.h"
+
+namespace clang {
+ namespace diag {
+ enum {
+#define DIAG(ENUM,FLAGS,DEFAULT_MAPPING,DESC,GROUP,\
+ SFINAE,NOWERROR,SHOWINSYSHEADER,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..293990c
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Analysis/CFG.h
@@ -0,0 +1,1113 @@
+//===--- 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_ANALYSIS_CFG_H
+#define LLVM_CLANG_ANALYSIS_CFG_H
+
+#include "clang/AST/Stmt.h"
+#include "clang/Analysis/Support/BumpVector.h"
+#include "clang/Basic/SourceLocation.h"
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/GraphTraits.h"
+#include "llvm/ADT/Optional.h"
+#include "llvm/ADT/PointerIntPair.h"
+#include "llvm/Support/Allocator.h"
+#include "llvm/Support/Casting.h"
+#include "llvm/Support/raw_ostream.h"
+#include <bitset>
+#include <cassert>
+#include <iterator>
+#include <memory>
+
+namespace clang {
+ class CXXDestructorDecl;
+ class Decl;
+ class Stmt;
+ class Expr;
+ class FieldDecl;
+ class VarDecl;
+ class CXXCtorInitializer;
+ class CXXBaseSpecifier;
+ class CXXBindTemporaryExpr;
+ class CFG;
+ class PrinterHelper;
+ class LangOptions;
+ class ASTContext;
+ class CXXRecordDecl;
+ class CXXDeleteExpr;
+ class CXXNewExpr;
+ class BinaryOperator;
+
+/// CFGElement - Represents a top-level expression in a basic block.
+class CFGElement {
+public:
+ enum Kind {
+ // main kind
+ Statement,
+ Initializer,
+ NewAllocator,
+ // dtor kind
+ AutomaticObjectDtor,
+ DeleteDtor,
+ BaseDtor,
+ MemberDtor,
+ TemporaryDtor,
+ DTOR_BEGIN = AutomaticObjectDtor,
+ DTOR_END = TemporaryDtor
+ };
+
+protected:
+ // The int bits are used to mark the kind.
+ llvm::PointerIntPair<void *, 2> Data1;
+ llvm::PointerIntPair<void *, 2> Data2;
+
+ CFGElement(Kind kind, const void *Ptr1, const void *Ptr2 = nullptr)
+ : Data1(const_cast<void*>(Ptr1), ((unsigned) kind) & 0x3),
+ Data2(const_cast<void*>(Ptr2), (((unsigned) kind) >> 2) & 0x3) {
+ assert(getKind() == kind);
+ }
+
+ CFGElement() {}
+public:
+
+ /// \brief Convert to the specified CFGElement type, asserting that this
+ /// CFGElement is of the desired type.
+ template<typename T>
+ T castAs() const {
+ assert(T::isKind(*this));
+ T t;
+ CFGElement& e = t;
+ e = *this;
+ return t;
+ }
+
+ /// \brief Convert to the specified CFGElement type, returning None if this
+ /// CFGElement is not of the desired type.
+ template<typename T>
+ Optional<T> getAs() const {
+ if (!T::isKind(*this))
+ return None;
+ T t;
+ CFGElement& e = t;
+ e = *this;
+ return t;
+ }
+
+ Kind getKind() const {
+ unsigned x = Data2.getInt();
+ x <<= 2;
+ x |= Data1.getInt();
+ return (Kind) x;
+ }
+};
+
+class CFGStmt : public CFGElement {
+public:
+ CFGStmt(Stmt *S) : CFGElement(Statement, S) {}
+
+ const Stmt *getStmt() const {
+ return static_cast<const Stmt *>(Data1.getPointer());
+ }
+
+private:
+ friend class CFGElement;
+ CFGStmt() {}
+ static bool isKind(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(CXXCtorInitializer *initializer)
+ : CFGElement(Initializer, initializer) {}
+
+ CXXCtorInitializer* getInitializer() const {
+ return static_cast<CXXCtorInitializer*>(Data1.getPointer());
+ }
+
+private:
+ friend class CFGElement;
+ CFGInitializer() {}
+ static bool isKind(const CFGElement &E) {
+ return E.getKind() == Initializer;
+ }
+};
+
+/// CFGNewAllocator - Represents C++ allocator call.
+class CFGNewAllocator : public CFGElement {
+public:
+ explicit CFGNewAllocator(const CXXNewExpr *S)
+ : CFGElement(NewAllocator, S) {}
+
+ // Get the new expression.
+ const CXXNewExpr *getAllocatorExpr() const {
+ return static_cast<CXXNewExpr *>(Data1.getPointer());
+ }
+
+private:
+ friend class CFGElement;
+ CFGNewAllocator() {}
+ static bool isKind(const CFGElement &elem) {
+ return elem.getKind() == NewAllocator;
+ }
+};
+
+/// CFGImplicitDtor - Represents C++ object destructor implicitly generated
+/// by compiler on various occasions.
+class CFGImplicitDtor : public CFGElement {
+protected:
+ CFGImplicitDtor() {}
+ CFGImplicitDtor(Kind kind, const void *data1, const void *data2 = nullptr)
+ : CFGElement(kind, data1, data2) {
+ assert(kind >= DTOR_BEGIN && kind <= DTOR_END);
+ }
+
+public:
+ const CXXDestructorDecl *getDestructorDecl(ASTContext &astContext) const;
+ bool isNoReturn(ASTContext &astContext) const;
+
+private:
+ friend class CFGElement;
+ static bool isKind(const CFGElement &E) {
+ Kind kind = E.getKind();
+ return kind >= DTOR_BEGIN && kind <= DTOR_END;
+ }
+};
+
+/// 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(const VarDecl *var, const Stmt *stmt)
+ : CFGImplicitDtor(AutomaticObjectDtor, var, stmt) {}
+
+ const VarDecl *getVarDecl() const {
+ return static_cast<VarDecl*>(Data1.getPointer());
+ }
+
+ // Get statement end of which triggered the destructor call.
+ const Stmt *getTriggerStmt() const {
+ return static_cast<Stmt*>(Data2.getPointer());
+ }
+
+private:
+ friend class CFGElement;
+ CFGAutomaticObjDtor() {}
+ static bool isKind(const CFGElement &elem) {
+ return elem.getKind() == AutomaticObjectDtor;
+ }
+};
+
+/// CFGDeleteDtor - Represents C++ object destructor generated
+/// from a call to delete.
+class CFGDeleteDtor : public CFGImplicitDtor {
+public:
+ CFGDeleteDtor(const CXXRecordDecl *RD, const CXXDeleteExpr *DE)
+ : CFGImplicitDtor(DeleteDtor, RD, DE) {}
+
+ const CXXRecordDecl *getCXXRecordDecl() const {
+ return static_cast<CXXRecordDecl*>(Data1.getPointer());
+ }
+
+ // Get Delete expression which triggered the destructor call.
+ const CXXDeleteExpr *getDeleteExpr() const {
+ return static_cast<CXXDeleteExpr *>(Data2.getPointer());
+ }
+
+private:
+ friend class CFGElement;
+ CFGDeleteDtor() {}
+ static bool isKind(const CFGElement &elem) {
+ return elem.getKind() == DeleteDtor;
+ }
+};
+
+/// CFGBaseDtor - Represents C++ object destructor implicitly generated for
+/// base object in destructor.
+class CFGBaseDtor : public CFGImplicitDtor {
+public:
+ CFGBaseDtor(const CXXBaseSpecifier *base)
+ : CFGImplicitDtor(BaseDtor, base) {}
+
+ const CXXBaseSpecifier *getBaseSpecifier() const {
+ return static_cast<const CXXBaseSpecifier*>(Data1.getPointer());
+ }
+
+private:
+ friend class CFGElement;
+ CFGBaseDtor() {}
+ static bool isKind(const CFGElement &E) {
+ return E.getKind() == BaseDtor;
+ }
+};
+
+/// CFGMemberDtor - Represents C++ object destructor implicitly generated for
+/// member object in destructor.
+class CFGMemberDtor : public CFGImplicitDtor {
+public:
+ CFGMemberDtor(const FieldDecl *field)
+ : CFGImplicitDtor(MemberDtor, field, nullptr) {}
+
+ const FieldDecl *getFieldDecl() const {
+ return static_cast<const FieldDecl*>(Data1.getPointer());
+ }
+
+private:
+ friend class CFGElement;
+ CFGMemberDtor() {}
+ static bool isKind(const CFGElement &E) {
+ return E.getKind() == MemberDtor;
+ }
+};
+
+/// CFGTemporaryDtor - Represents C++ object destructor implicitly generated
+/// at the end of full expression for temporary object.
+class CFGTemporaryDtor : public CFGImplicitDtor {
+public:
+ CFGTemporaryDtor(CXXBindTemporaryExpr *expr)
+ : CFGImplicitDtor(TemporaryDtor, expr, nullptr) {}
+
+ const CXXBindTemporaryExpr *getBindTemporaryExpr() const {
+ return static_cast<const CXXBindTemporaryExpr *>(Data1.getPointer());
+ }
+
+private:
+ friend class CFGElement;
+ CFGTemporaryDtor() {}
+ static bool isKind(const CFGElement &E) {
+ return E.getKind() == 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(); }
+
+ explicit 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
+///
+/// But note that any of that may be NULL in case of optimized-out edges.
+///
+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;
+ typedef ImplTy::const_reference const_reference;
+
+ 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);
+ }
+
+ const_reference front() const { return Impl.back(); }
+ const_reference 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;
+
+public:
+ /// This class represents a potential adjacent block in the CFG. It encodes
+ /// whether or not the block is actually reachable, or can be proved to be
+ /// trivially unreachable. For some cases it allows one to encode scenarios
+ /// where a block was substituted because the original (now alternate) block
+ /// is unreachable.
+ class AdjacentBlock {
+ enum Kind {
+ AB_Normal,
+ AB_Unreachable,
+ AB_Alternate
+ };
+
+ CFGBlock *ReachableBlock;
+ llvm::PointerIntPair<CFGBlock*, 2> UnreachableBlock;
+
+ public:
+ /// Construct an AdjacentBlock with a possibly unreachable block.
+ AdjacentBlock(CFGBlock *B, bool IsReachable);
+
+ /// Construct an AdjacentBlock with a reachable block and an alternate
+ /// unreachable block.
+ AdjacentBlock(CFGBlock *B, CFGBlock *AlternateBlock);
+
+ /// Get the reachable block, if one exists.
+ CFGBlock *getReachableBlock() const {
+ return ReachableBlock;
+ }
+
+ /// Get the potentially unreachable block.
+ CFGBlock *getPossiblyUnreachableBlock() const {
+ return UnreachableBlock.getPointer();
+ }
+
+ /// Provide an implicit conversion to CFGBlock* so that
+ /// AdjacentBlock can be substituted for CFGBlock*.
+ operator CFGBlock*() const {
+ return getReachableBlock();
+ }
+
+ CFGBlock& operator *() const {
+ return *getReachableBlock();
+ }
+
+ CFGBlock* operator ->() const {
+ return getReachableBlock();
+ }
+
+ bool isReachable() const {
+ Kind K = (Kind) UnreachableBlock.getInt();
+ return K == AB_Normal || K == AB_Alternate;
+ }
+ };
+
+private:
+ /// Predecessors/Successors - Keep track of the predecessor / successor
+ /// CFG blocks.
+ typedef BumpVector<AdjacentBlock> AdjacentBlocks;
+ AdjacentBlocks Preds;
+ AdjacentBlocks Succs;
+
+ /// NoReturn - This bit is set when the basic block contains a function call
+ /// or implicit destructor that is attributed as 'noreturn'. In that case,
+ /// control cannot technically ever proceed past this block. All such blocks
+ /// will have a single immediate successor: the exit block. This allows them
+ /// to be easily reached from the exit block and using this bit quickly
+ /// recognized without scanning the contents of the block.
+ ///
+ /// Optimization Note: This bit could be profitably folded with Terminator's
+ /// storage if the memory usage of CFGBlock becomes an issue.
+ unsigned HasNoReturnElement : 1;
+
+ /// Parent - The parent CFG that owns this CFGBlock.
+ CFG *Parent;
+
+public:
+ explicit CFGBlock(unsigned blockid, BumpVectorContext &C, CFG *parent)
+ : Elements(C), Label(nullptr), Terminator(nullptr), LoopTarget(nullptr),
+ BlockID(blockid), Preds(C, 1), Succs(C, 1), HasNoReturnElement(false),
+ Parent(parent) {}
+
+ // 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() {
+ IgnoreNullPredecessors = 1;
+ IgnoreDefaultsWithCoveredEnums = 0;
+ }
+
+ unsigned IgnoreNullPredecessors : 1;
+ 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) {
+ while (hasMore() && Filter(*I))
+ ++I;
+ }
+
+ 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(CFGTerminator Term) { Terminator = Term; }
+ void setLabel(Stmt *Statement) { Label = Statement; }
+ void setLoopTarget(const Stmt *loopTarget) { LoopTarget = loopTarget; }
+ void setHasNoReturnElement() { HasNoReturnElement = true; }
+
+ CFGTerminator getTerminator() { return Terminator; }
+ const CFGTerminator getTerminator() const { return Terminator; }
+
+ Stmt *getTerminatorCondition(bool StripParens = true);
+
+ const Stmt *getTerminatorCondition(bool StripParens = true) const {
+ return const_cast<CFGBlock*>(this)->getTerminatorCondition(StripParens);
+ }
+
+ const Stmt *getLoopTarget() const { return LoopTarget; }
+
+ Stmt *getLabel() { return Label; }
+ const Stmt *getLabel() const { return Label; }
+
+ bool hasNoReturnElement() const { return HasNoReturnElement; }
+
+ unsigned getBlockID() const { return BlockID; }
+
+ CFG *getParent() const { return Parent; }
+
+ void dump() const;
+
+ void dump(const CFG *cfg, const LangOptions &LO, bool ShowColors = false) const;
+ void print(raw_ostream &OS, const CFG* cfg, const LangOptions &LO,
+ bool ShowColors) const;
+ void printTerminator(raw_ostream &OS, const LangOptions &LO) const;
+ void printAsOperand(raw_ostream &OS, bool /*PrintType*/) {
+ OS << "BB#" << getBlockID();
+ }
+
+ /// Adds a (potentially unreachable) successor block to the current block.
+ void addSuccessor(AdjacentBlock Succ, BumpVectorContext &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 appendNewAllocator(CXXNewExpr *NE,
+ BumpVectorContext &C) {
+ Elements.push_back(CFGNewAllocator(NE), 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);
+ }
+
+ void appendAutomaticObjDtor(VarDecl *VD, Stmt *S, BumpVectorContext &C) {
+ Elements.push_back(CFGAutomaticObjDtor(VD, S), C);
+ }
+
+ void appendDeleteDtor(CXXRecordDecl *RD, CXXDeleteExpr *DE, BumpVectorContext &C) {
+ Elements.push_back(CFGDeleteDtor(RD, DE), 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,
+ CFGAutomaticObjDtor(nullptr, nullptr), C));
+ }
+ iterator insertAutomaticObjDtor(iterator I, VarDecl *VD, Stmt *S) {
+ *I = CFGAutomaticObjDtor(VD, S);
+ return ++I;
+ }
+};
+
+/// \brief CFGCallback defines methods that should be called when a logical
+/// operator error is found when building the CFG.
+class CFGCallback {
+public:
+ CFGCallback() {}
+ virtual void compareAlwaysTrue(const BinaryOperator *B, bool isAlwaysTrue) {}
+ virtual void compareBitwiseEquality(const BinaryOperator *B,
+ bool isAlwaysTrue) {}
+ virtual ~CFGCallback() {}
+};
+
+/// 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 {
+ std::bitset<Stmt::lastStmtConstant> alwaysAddMask;
+ public:
+ typedef llvm::DenseMap<const Stmt *, const CFGBlock*> ForcedBlkExprs;
+ ForcedBlkExprs **forcedBlkExprs;
+ CFGCallback *Observer;
+ bool PruneTriviallyFalseEdges;
+ bool AddEHEdges;
+ bool AddInitializers;
+ bool AddImplicitDtors;
+ bool AddTemporaryDtors;
+ bool AddStaticInitBranches;
+ bool AddCXXNewAllocator;
+ bool AddCXXDefaultInitExprInCtors;
+
+ bool alwaysAdd(const Stmt *stmt) const {
+ return alwaysAddMask[stmt->getStmtClass()];
+ }
+
+ BuildOptions &setAlwaysAdd(Stmt::StmtClass stmtClass, bool val = true) {
+ alwaysAddMask[stmtClass] = val;
+ return *this;
+ }
+
+ BuildOptions &setAllAlwaysAdd() {
+ alwaysAddMask.set();
+ return *this;
+ }
+
+ BuildOptions()
+ : forcedBlkExprs(nullptr), Observer(nullptr),
+ PruneTriviallyFalseEdges(true), AddEHEdges(false),
+ AddInitializers(false), AddImplicitDtors(false),
+ AddTemporaryDtors(false), AddStaticInitBranches(false),
+ AddCXXNewAllocator(false), AddCXXDefaultInitExprInCtors(false) {}
+ };
+
+ /// \brief Provides a custom implementation of the iterator class to have the
+ /// same interface as Function::iterator - iterator returns CFGBlock
+ /// (not a pointer to CFGBlock).
+ class graph_iterator {
+ public:
+ typedef CFGBlock value_type;
+ typedef value_type& reference;
+ typedef value_type* pointer;
+ typedef BumpVector<CFGBlock*>::iterator ImplTy;
+
+ graph_iterator(const ImplTy &i) : I(i) {}
+
+ bool operator==(const graph_iterator &X) const { return I == X.I; }
+ bool operator!=(const graph_iterator &X) const { return I != X.I; }
+
+ reference operator*() const { return **I; }
+ pointer operator->() const { return *I; }
+ operator CFGBlock* () { return *I; }
+
+ graph_iterator &operator++() { ++I; return *this; }
+ graph_iterator &operator--() { --I; return *this; }
+
+ private:
+ ImplTy I;
+ };
+
+ class const_graph_iterator {
+ public:
+ typedef const CFGBlock value_type;
+ typedef value_type& reference;
+ typedef value_type* pointer;
+ typedef BumpVector<CFGBlock*>::const_iterator ImplTy;
+
+ const_graph_iterator(const ImplTy &i) : I(i) {}
+
+ bool operator==(const const_graph_iterator &X) const { return I == X.I; }
+ bool operator!=(const const_graph_iterator &X) const { return I != X.I; }
+
+ reference operator*() const { return **I; }
+ pointer operator->() const { return *I; }
+ operator CFGBlock* () const { return *I; }
+
+ const_graph_iterator &operator++() { ++I; return *this; }
+ const_graph_iterator &operator--() { --I; return *this; }
+
+ private:
+ ImplTy I;
+ };
+
+ /// buildCFG - Builds a CFG from an AST.
+ static std::unique_ptr<CFG> buildCFG(const Decl *D, Stmt *AST, ASTContext *C,
+ const BuildOptions &BO);
+
+ /// 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(); }
+
+ graph_iterator nodes_begin() { return graph_iterator(Blocks.begin()); }
+ graph_iterator nodes_end() { return graph_iterator(Blocks.end()); }
+ const_graph_iterator nodes_begin() const {
+ return const_graph_iterator(Blocks.begin());
+ }
+ const_graph_iterator nodes_end() const {
+ return const_graph_iterator(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; }
+
+ typedef std::vector<const CFGBlock*>::const_iterator try_block_iterator;
+ try_block_iterator try_blocks_begin() const {
+ return TryDispatchBlocks.begin();
+ }
+ try_block_iterator try_blocks_end() const {
+ return TryDispatchBlocks.end();
+ }
+
+ void addTryDispatchBlock(const CFGBlock *block) {
+ TryDispatchBlocks.push_back(block);
+ }
+
+ /// Records a synthetic DeclStmt and the DeclStmt it was constructed from.
+ ///
+ /// The CFG uses synthetic DeclStmts when a single AST DeclStmt contains
+ /// multiple decls.
+ void addSyntheticDeclStmt(const DeclStmt *Synthetic,
+ const DeclStmt *Source) {
+ assert(Synthetic->isSingleDecl() && "Can handle single declarations only");
+ assert(Synthetic != Source && "Don't include original DeclStmts in map");
+ assert(!SyntheticDeclStmts.count(Synthetic) && "Already in map");
+ SyntheticDeclStmts[Synthetic] = Source;
+ }
+
+ typedef llvm::DenseMap<const DeclStmt *, const DeclStmt *>::const_iterator
+ synthetic_stmt_iterator;
+
+ /// Iterates over synthetic DeclStmts in the CFG.
+ ///
+ /// Each element is a (synthetic statement, source statement) pair.
+ ///
+ /// \sa addSyntheticDeclStmt
+ synthetic_stmt_iterator synthetic_stmt_begin() const {
+ return SyntheticDeclStmts.begin();
+ }
+
+ /// \sa synthetic_stmt_begin
+ synthetic_stmt_iterator synthetic_stmt_end() const {
+ return SyntheticDeclStmts.end();
+ }
+
+ //===--------------------------------------------------------------------===//
+ // 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 (Optional<CFGStmt> stmt = BI->getAs<CFGStmt>())
+ O(const_cast<Stmt*>(stmt->getStmt()));
+ }
+ }
+
+ //===--------------------------------------------------------------------===//
+ // CFG Introspection.
+ //===--------------------------------------------------------------------===//
+
+ /// getNumBlockIDs - Returns the total number of BlockIDs allocated (which
+ /// start at 0).
+ unsigned getNumBlockIDs() const { return NumBlockIDs; }
+
+ /// size - Return the total number of CFGBlocks within the CFG
+ /// This is simply a renaming of the getNumBlockIDs(). This is necessary
+ /// because the dominator implementation needs such an interface.
+ unsigned size() const { return NumBlockIDs; }
+
+ //===--------------------------------------------------------------------===//
+ // CFG Debugging: Pretty-Printing and Visualization.
+ //===--------------------------------------------------------------------===//
+
+ void viewCFG(const LangOptions &LO) const;
+ void print(raw_ostream &OS, const LangOptions &LO, bool ShowColors) const;
+ void dump(const LangOptions &LO, bool ShowColors) const;
+
+ //===--------------------------------------------------------------------===//
+ // Internal: constructors and data.
+ //===--------------------------------------------------------------------===//
+
+ CFG()
+ : Entry(nullptr), Exit(nullptr), IndirectGotoBlock(nullptr), NumBlockIDs(0),
+ Blocks(BlkBVC, 10) {}
+
+ 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;
+
+ BumpVectorContext BlkBVC;
+
+ CFGBlockListTy Blocks;
+
+ /// C++ 'try' statements are modeled with an indirect dispatch block.
+ /// This is the collection of such blocks present in the CFG.
+ std::vector<const CFGBlock *> TryDispatchBlocks;
+
+ /// Collects DeclStmts synthesized for this CFG and maps each one back to its
+ /// source DeclStmt.
+ llvm::DenseMap<const DeclStmt *, const DeclStmt *> SyntheticDeclStmts;
+};
+} // 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< ::clang::CFGTerminator> {
+ typedef ::clang::Stmt *SimpleType;
+ static SimpleType getSimplifiedValue(::clang::CFGTerminator Val) {
+ return 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< ::clang::CFGBlock*> > {
+ typedef ::clang::CFGBlock NodeType;
+ typedef ::clang::CFGBlock::const_pred_iterator ChildIteratorType;
+
+ static NodeType *getEntryNode(Inverse< ::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(); }
+};
+
+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::graph_iterator nodes_iterator;
+
+ static NodeType *getEntryNode(::clang::CFG* F) { return &F->getEntry(); }
+ static nodes_iterator nodes_begin(::clang::CFG* F) { return F->nodes_begin();}
+ static nodes_iterator nodes_end(::clang::CFG* F) { return F->nodes_end(); }
+ static unsigned size(::clang::CFG* F) { return F->size(); }
+};
+
+template <> struct GraphTraits<const ::clang::CFG* >
+ : public GraphTraits<const ::clang::CFGBlock *> {
+
+ typedef ::clang::CFG::const_graph_iterator nodes_iterator;
+
+ static NodeType *getEntryNode( const ::clang::CFG* F) {
+ return &F->getEntry();
+ }
+ static nodes_iterator nodes_begin( const ::clang::CFG* F) {
+ return F->nodes_begin();
+ }
+ static nodes_iterator nodes_end( const ::clang::CFG* F) {
+ return F->nodes_end();
+ }
+ static unsigned size(const ::clang::CFG* F) {
+ return F->size();
+ }
+};
+
+template <> struct GraphTraits<Inverse< ::clang::CFG*> >
+ : public GraphTraits<Inverse< ::clang::CFGBlock*> > {
+
+ typedef ::clang::CFG::graph_iterator nodes_iterator;
+
+ static NodeType *getEntryNode( ::clang::CFG* F) { return &F->getExit(); }
+ static nodes_iterator nodes_begin( ::clang::CFG* F) {return F->nodes_begin();}
+ static nodes_iterator nodes_end( ::clang::CFG* F) { return F->nodes_end(); }
+};
+
+template <> struct GraphTraits<Inverse<const ::clang::CFG*> >
+ : public GraphTraits<Inverse<const ::clang::CFGBlock*> > {
+
+ typedef ::clang::CFG::const_graph_iterator nodes_iterator;
+
+ static NodeType *getEntryNode(const ::clang::CFG* F) { return &F->getExit(); }
+ static nodes_iterator nodes_begin(const ::clang::CFG* F) {
+ return F->nodes_begin();
+ }
+ static nodes_iterator nodes_end(const ::clang::CFG* F) {
+ return F->nodes_end();
+ }
+};
+} // end llvm namespace
+
+#endif // LLVM_CLANG_ANALYSIS_CFG_H
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..4dfa91d
--- /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_ANALYSIS_CFGSTMTMAP_H
+#define LLVM_CLANG_ANALYSIS_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/CallGraph.h b/contrib/llvm/tools/clang/include/clang/Analysis/CallGraph.h
new file mode 100644
index 0000000..eda22a5
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Analysis/CallGraph.h
@@ -0,0 +1,253 @@
+//== CallGraph.h - AST-based Call 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 declares the AST-based CallGraph.
+//
+// A call graph for functions whose definitions/bodies are available in the
+// current translation unit. The graph has a "virtual" root node that contains
+// edges to all externally available functions.
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_ANALYSIS_CALLGRAPH_H
+#define LLVM_CLANG_ANALYSIS_CALLGRAPH_H
+
+#include "clang/AST/DeclBase.h"
+#include "clang/AST/RecursiveASTVisitor.h"
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/GraphTraits.h"
+#include "llvm/ADT/SetVector.h"
+
+namespace clang {
+class CallGraphNode;
+
+/// \brief The AST-based call graph.
+///
+/// The call graph extends itself with the given declarations by implementing
+/// the recursive AST visitor, which constructs the graph by visiting the given
+/// declarations.
+class CallGraph : public RecursiveASTVisitor<CallGraph> {
+ friend class CallGraphNode;
+
+ typedef llvm::DenseMap<const Decl *, CallGraphNode *> FunctionMapTy;
+
+ /// FunctionMap owns all CallGraphNodes.
+ FunctionMapTy FunctionMap;
+
+ /// This is a virtual root node that has edges to all the functions.
+ CallGraphNode *Root;
+
+public:
+ CallGraph();
+ ~CallGraph();
+
+ /// \brief Populate the call graph with the functions in the given
+ /// declaration.
+ ///
+ /// Recursively walks the declaration to find all the dependent Decls as well.
+ void addToCallGraph(Decl *D) {
+ TraverseDecl(D);
+ }
+
+ /// \brief Determine if a declaration should be included in the graph.
+ static bool includeInGraph(const Decl *D);
+
+ /// \brief Lookup the node for the given declaration.
+ CallGraphNode *getNode(const Decl *) const;
+
+ /// \brief Lookup the node for the given declaration. If none found, insert
+ /// one into the graph.
+ CallGraphNode *getOrInsertNode(Decl *);
+
+ /// Iterators through all the elements in the graph. Note, this gives
+ /// non-deterministic order.
+ 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(); }
+
+ /// \brief Get the number of nodes in the graph.
+ unsigned size() const { return FunctionMap.size(); }
+
+ /// \ brief Get the virtual root of the graph, all the functions available
+ /// externally are represented as callees of the node.
+ CallGraphNode *getRoot() const { return Root; }
+
+ /// Iterators through all the nodes of the graph that have no parent. These
+ /// are the unreachable nodes, which are either unused or are due to us
+ /// failing to add a call edge due to the analysis imprecision.
+ typedef llvm::SetVector<CallGraphNode *>::iterator nodes_iterator;
+ typedef llvm::SetVector<CallGraphNode *>::const_iterator const_nodes_iterator;
+
+ void print(raw_ostream &os) const;
+ void dump() const;
+ void viewGraph() const;
+
+ void addNodesForBlocks(DeclContext *D);
+
+ /// Part of recursive declaration visitation. We recursively visit all the
+ /// declarations to collect the root functions.
+ bool VisitFunctionDecl(FunctionDecl *FD) {
+ // We skip function template definitions, as their semantics is
+ // only determined when they are instantiated.
+ if (includeInGraph(FD)) {
+ // Add all blocks declared inside this function to the graph.
+ addNodesForBlocks(FD);
+ // If this function has external linkage, anything could call it.
+ // Note, we are not precise here. For example, the function could have
+ // its address taken.
+ addNodeForDecl(FD, FD->isGlobal());
+ }
+ return true;
+ }
+
+ /// Part of recursive declaration visitation.
+ bool VisitObjCMethodDecl(ObjCMethodDecl *MD) {
+ if (includeInGraph(MD)) {
+ addNodesForBlocks(MD);
+ addNodeForDecl(MD, true);
+ }
+ return true;
+ }
+
+ // We are only collecting the declarations, so do not step into the bodies.
+ bool TraverseStmt(Stmt *S) { return true; }
+
+ bool shouldWalkTypesOfTypeLocs() const { return false; }
+
+private:
+ /// \brief Add the given declaration to the call graph.
+ void addNodeForDecl(Decl *D, bool IsGlobal);
+
+ /// \brief Allocate a new node in the graph.
+ CallGraphNode *allocateNewNode(Decl *);
+};
+
+class CallGraphNode {
+public:
+ typedef CallGraphNode* CallRecord;
+
+private:
+ /// \brief The function/method declaration.
+ Decl *FD;
+
+ /// \brief The list of functions called from this node.
+ SmallVector<CallRecord, 5> CalledFunctions;
+
+public:
+ CallGraphNode(Decl *D) : FD(D) {}
+
+ typedef SmallVectorImpl<CallRecord>::iterator iterator;
+ typedef SmallVectorImpl<CallRecord>::const_iterator const_iterator;
+
+ /// Iterators through all the callees/children of the node.
+ inline iterator begin() { return CalledFunctions.begin(); }
+ inline iterator end() { return CalledFunctions.end(); }
+ inline const_iterator begin() const { return CalledFunctions.begin(); }
+ inline const_iterator end() const { return CalledFunctions.end(); }
+
+ inline bool empty() const {return CalledFunctions.empty(); }
+ inline unsigned size() const {return CalledFunctions.size(); }
+
+ void addCallee(CallGraphNode *N, CallGraph *CG) {
+ CalledFunctions.push_back(N);
+ }
+
+ Decl *getDecl() const { return FD; }
+
+ void print(raw_ostream &os) const;
+ void dump() const;
+};
+
+} // end clang namespace
+
+// Graph traits for iteration, viewing.
+namespace llvm {
+template <> struct GraphTraits<clang::CallGraphNode*> {
+ typedef clang::CallGraphNode NodeType;
+ typedef clang::CallGraphNode::CallRecord CallRecordTy;
+ typedef std::pointer_to_unary_function<CallRecordTy,
+ clang::CallGraphNode*> CGNDerefFun;
+ static NodeType *getEntryNode(clang::CallGraphNode *CGN) { return CGN; }
+ typedef mapped_iterator<NodeType::iterator, CGNDerefFun> ChildIteratorType;
+ static inline ChildIteratorType child_begin(NodeType *N) {
+ return map_iterator(N->begin(), CGNDerefFun(CGNDeref));
+ }
+ static inline ChildIteratorType child_end (NodeType *N) {
+ return map_iterator(N->end(), CGNDerefFun(CGNDeref));
+ }
+ static clang::CallGraphNode *CGNDeref(CallRecordTy P) {
+ return P;
+ }
+};
+
+template <> struct GraphTraits<const clang::CallGraphNode*> {
+ typedef const clang::CallGraphNode NodeType;
+ typedef NodeType::const_iterator ChildIteratorType;
+ static NodeType *getEntryNode(const clang::CallGraphNode *CGN) { return CGN; }
+ static inline ChildIteratorType child_begin(NodeType *N) { return N->begin();}
+ static inline ChildIteratorType child_end(NodeType *N) { return N->end(); }
+};
+
+template <> struct GraphTraits<clang::CallGraph*>
+ : public GraphTraits<clang::CallGraphNode*> {
+
+ static NodeType *getEntryNode(clang::CallGraph *CGN) {
+ return CGN->getRoot(); // Start at the external node!
+ }
+ typedef std::pair<const clang::Decl*, clang::CallGraphNode*> PairTy;
+ typedef std::pointer_to_unary_function<PairTy, clang::CallGraphNode&> DerefFun;
+ // nodes_iterator/begin/end - Allow iteration over all nodes in the graph
+ typedef mapped_iterator<clang::CallGraph::iterator, DerefFun> nodes_iterator;
+
+ static nodes_iterator nodes_begin(clang::CallGraph *CG) {
+ return map_iterator(CG->begin(), DerefFun(CGdereference));
+ }
+ static nodes_iterator nodes_end (clang::CallGraph *CG) {
+ return map_iterator(CG->end(), DerefFun(CGdereference));
+ }
+ static clang::CallGraphNode &CGdereference(PairTy P) {
+ return *(P.second);
+ }
+
+ static unsigned size(clang::CallGraph *CG) {
+ return CG->size();
+ }
+};
+
+template <> struct GraphTraits<const clang::CallGraph*> :
+ public GraphTraits<const clang::CallGraphNode*> {
+ static NodeType *getEntryNode(const clang::CallGraph *CGN) {
+ return CGN->getRoot();
+ }
+ typedef std::pair<const clang::Decl*, clang::CallGraphNode*> PairTy;
+ typedef std::pointer_to_unary_function<PairTy, clang::CallGraphNode&> DerefFun;
+ // nodes_iterator/begin/end - Allow iteration over all nodes in the graph
+ typedef mapped_iterator<clang::CallGraph::const_iterator,
+ DerefFun> nodes_iterator;
+
+ static nodes_iterator nodes_begin(const clang::CallGraph *CG) {
+ return map_iterator(CG->begin(), DerefFun(CGdereference));
+ }
+ static nodes_iterator nodes_end(const clang::CallGraph *CG) {
+ return map_iterator(CG->end(), DerefFun(CGdereference));
+ }
+ static clang::CallGraphNode &CGdereference(PairTy P) {
+ return *(P.second);
+ }
+
+ static unsigned size(const clang::CallGraph *CG) {
+ return CG->size();
+ }
+};
+
+} // end llvm namespace
+
+#endif
diff --git a/contrib/llvm/tools/clang/include/clang/Analysis/CodeInjector.h b/contrib/llvm/tools/clang/include/clang/Analysis/CodeInjector.h
new file mode 100644
index 0000000..413a55b
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Analysis/CodeInjector.h
@@ -0,0 +1,46 @@
+//===-- CodeInjector.h ------------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+///
+/// \file
+/// \brief Defines the clang::CodeInjector interface which is responsible for
+/// injecting AST of function definitions that may not be available in the
+/// original source.
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_ANALYSIS_CODEINJECTOR_H
+#define LLVM_CLANG_ANALYSIS_CODEINJECTOR_H
+
+namespace clang {
+
+class Stmt;
+class FunctionDecl;
+class ObjCMethodDecl;
+
+/// \brief CodeInjector is an interface which is responsible for injecting AST
+/// of function definitions that may not be available in the original source.
+///
+/// The getBody function will be called each time the static analyzer examines a
+/// function call that has no definition available in the current translation
+/// unit. If the returned statement is not a null pointer, it is assumed to be
+/// the body of a function which will be used for the analysis. The source of
+/// the body can be arbitrary, but it is advised to use memoization to avoid
+/// unnecessary reparsing of the external source that provides the body of the
+/// functions.
+class CodeInjector {
+public:
+ CodeInjector();
+ virtual ~CodeInjector();
+
+ virtual Stmt *getBody(const FunctionDecl *D) = 0;
+ virtual Stmt *getBody(const ObjCMethodDecl *D) = 0;
+};
+}
+
+#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..8b3fcff
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Analysis/DomainSpecific/CocoaConventions.h
@@ -0,0 +1,42 @@
+//===- 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 implements cocoa naming convention analysis.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_ANALYSIS_DOMAINSPECIFIC_COCOACONVENTIONS_H
+#define LLVM_CLANG_ANALYSIS_DOMAINSPECIFIC_COCOACONVENTIONS_H
+
+#include "clang/Basic/LLVM.h"
+#include "llvm/ADT/StringRef.h"
+
+namespace clang {
+class FunctionDecl;
+class QualType;
+
+namespace ento {
+namespace cocoa {
+
+ bool isRefType(QualType RetTy, StringRef Prefix,
+ StringRef Name = StringRef());
+
+ bool isCocoaObjectRef(QualType T);
+
+}
+
+namespace coreFoundation {
+ bool isCFObjectRef(QualType T);
+
+ bool followsCreateRule(const FunctionDecl *FD);
+}
+
+}} // end: "clang:ento"
+
+#endif
diff --git a/contrib/llvm/tools/clang/include/clang/Analysis/DomainSpecific/ObjCNoReturn.h b/contrib/llvm/tools/clang/include/clang/Analysis/DomainSpecific/ObjCNoReturn.h
new file mode 100644
index 0000000..f9e800a
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Analysis/DomainSpecific/ObjCNoReturn.h
@@ -0,0 +1,46 @@
+//= ObjCNoReturn.h - Handling of Cocoa APIs known not to return --*- 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 special handling of recognizing ObjC API hooks that
+// do not return but aren't marked as such in API headers.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_ANALYSIS_DOMAINSPECIFIC_OBJCNORETURN_H
+#define LLVM_CLANG_ANALYSIS_DOMAINSPECIFIC_OBJCNORETURN_H
+
+#include "clang/Basic/IdentifierTable.h"
+
+namespace clang {
+
+class ASTContext;
+class ObjCMessageExpr;
+
+class ObjCNoReturn {
+ /// Cached "raise" selector.
+ Selector RaiseSel;
+
+ /// Cached identifier for "NSException".
+ IdentifierInfo *NSExceptionII;
+
+ enum { NUM_RAISE_SELECTORS = 2 };
+
+ /// Cached set of selectors in NSException that are 'noreturn'.
+ Selector NSExceptionInstanceRaiseSelectors[NUM_RAISE_SELECTORS];
+
+public:
+ ObjCNoReturn(ASTContext &C);
+
+ /// Return true if the given message expression is known to never
+ /// return.
+ bool isImplicitNoReturn(const ObjCMessageExpr *ME);
+};
+}
+
+#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..f86b2b0
--- /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..6d816fd
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Analysis/ProgramPoint.h
@@ -0,0 +1,704 @@
+//==- 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_PROGRAMPOINT_H
+#define LLVM_CLANG_ANALYSIS_PROGRAMPOINT_H
+
+#include "clang/Analysis/AnalysisContext.h"
+#include "clang/Analysis/CFG.h"
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/FoldingSet.h"
+#include "llvm/ADT/Optional.h"
+#include "llvm/ADT/PointerIntPair.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/Support/Casting.h"
+#include "llvm/Support/DataTypes.h"
+#include <cassert>
+#include <string>
+#include <utility>
+
+namespace clang {
+
+class AnalysisDeclContext;
+class FunctionDecl;
+class LocationContext;
+
+/// ProgramPoints can be "tagged" as representing points specific to a given
+/// analysis entity. Tags are abstract annotations, with an associated
+/// description and potentially other information.
+class ProgramPointTag {
+public:
+ ProgramPointTag(void *tagKind = nullptr) : TagKind(tagKind) {}
+ virtual ~ProgramPointTag();
+ virtual StringRef getTagDescription() const = 0;
+
+protected:
+ /// Used to implement 'isKind' in subclasses.
+ const void *getTagKind() { return TagKind; }
+
+private:
+ const void *TagKind;
+};
+
+class SimpleProgramPointTag : public ProgramPointTag {
+ std::string Desc;
+public:
+ SimpleProgramPointTag(StringRef MsgProvider, StringRef Msg);
+ StringRef getTagDescription() const override;
+};
+
+class ProgramPoint {
+public:
+ enum Kind { BlockEdgeKind,
+ BlockEntranceKind,
+ BlockExitKind,
+ PreStmtKind,
+ PreStmtPurgeDeadSymbolsKind,
+ PostStmtPurgeDeadSymbolsKind,
+ PostStmtKind,
+ PreLoadKind,
+ PostLoadKind,
+ PreStoreKind,
+ PostStoreKind,
+ PostConditionKind,
+ PostLValueKind,
+ MinPostStmtKind = PostStmtKind,
+ MaxPostStmtKind = PostLValueKind,
+ PostInitializerKind,
+ CallEnterKind,
+ CallExitBeginKind,
+ CallExitEndKind,
+ PreImplicitCallKind,
+ PostImplicitCallKind,
+ MinImplicitCallKind = PreImplicitCallKind,
+ MaxImplicitCallKind = PostImplicitCallKind,
+ EpsilonKind};
+
+private:
+ const void *Data1;
+ llvm::PointerIntPair<const void *, 2, unsigned> Data2;
+
+ // The LocationContext could be NULL to allow ProgramPoint to be used in
+ // context insensitive analysis.
+ llvm::PointerIntPair<const LocationContext *, 2, unsigned> L;
+
+ llvm::PointerIntPair<const ProgramPointTag *, 2, unsigned> Tag;
+
+protected:
+ ProgramPoint() {}
+ ProgramPoint(const void *P,
+ Kind k,
+ const LocationContext *l,
+ const ProgramPointTag *tag = nullptr)
+ : Data1(P),
+ Data2(nullptr, (((unsigned) k) >> 0) & 0x3),
+ L(l, (((unsigned) k) >> 2) & 0x3),
+ Tag(tag, (((unsigned) k) >> 4) & 0x3) {
+ assert(getKind() == k);
+ assert(getLocationContext() == l);
+ assert(getData1() == P);
+ }
+
+ ProgramPoint(const void *P1,
+ const void *P2,
+ Kind k,
+ const LocationContext *l,
+ const ProgramPointTag *tag = nullptr)
+ : Data1(P1),
+ Data2(P2, (((unsigned) k) >> 0) & 0x3),
+ L(l, (((unsigned) k) >> 2) & 0x3),
+ Tag(tag, (((unsigned) k) >> 4) & 0x3) {}
+
+protected:
+ const void *getData1() const { return Data1; }
+ const void *getData2() const { return Data2.getPointer(); }
+ void setData2(const void *d) { Data2.setPointer(d); }
+
+public:
+ /// Create a new ProgramPoint object that is the same as the original
+ /// except for using the specified tag value.
+ ProgramPoint withTag(const ProgramPointTag *tag) const {
+ return ProgramPoint(getData1(), getData2(), getKind(),
+ getLocationContext(), tag);
+ }
+
+ /// \brief Convert to the specified ProgramPoint type, asserting that this
+ /// ProgramPoint is of the desired type.
+ template<typename T>
+ T castAs() const {
+ assert(T::isKind(*this));
+ T t;
+ ProgramPoint& PP = t;
+ PP = *this;
+ return t;
+ }
+
+ /// \brief Convert to the specified ProgramPoint type, returning None if this
+ /// ProgramPoint is not of the desired type.
+ template<typename T>
+ Optional<T> getAs() const {
+ if (!T::isKind(*this))
+ return None;
+ T t;
+ ProgramPoint& PP = t;
+ PP = *this;
+ return t;
+ }
+
+ Kind getKind() const {
+ unsigned x = Tag.getInt();
+ x <<= 2;
+ x |= L.getInt();
+ x <<= 2;
+ x |= Data2.getInt();
+ return (Kind) x;
+ }
+
+ /// \brief Is this a program point corresponding to purge/removal of dead
+ /// symbols and bindings.
+ bool isPurgeKind() {
+ Kind K = getKind();
+ return (K == PostStmtPurgeDeadSymbolsKind ||
+ K == PreStmtPurgeDeadSymbolsKind);
+ }
+
+ const ProgramPointTag *getTag() const { return Tag.getPointer(); }
+
+ const LocationContext *getLocationContext() const {
+ return L.getPointer();
+ }
+
+ // For use with DenseMap. This hash is probably slow.
+ unsigned getHashValue() const {
+ llvm::FoldingSetNodeID ID;
+ Profile(ID);
+ return ID.ComputeHash();
+ }
+
+ bool operator==(const ProgramPoint & RHS) const {
+ return Data1 == RHS.Data1 &&
+ Data2 == RHS.Data2 &&
+ L == RHS.L &&
+ Tag == RHS.Tag;
+ }
+
+ bool operator!=(const ProgramPoint &RHS) const {
+ return Data1 != RHS.Data1 ||
+ Data2 != RHS.Data2 ||
+ L != RHS.L ||
+ Tag != RHS.Tag;
+ }
+
+ void Profile(llvm::FoldingSetNodeID& ID) const {
+ ID.AddInteger((unsigned) getKind());
+ ID.AddPointer(getData1());
+ ID.AddPointer(getData2());
+ ID.AddPointer(getLocationContext());
+ ID.AddPointer(getTag());
+ }
+
+ static ProgramPoint getProgramPoint(const Stmt *S, ProgramPoint::Kind K,
+ const LocationContext *LC,
+ const ProgramPointTag *tag);
+};
+
+class BlockEntrance : public ProgramPoint {
+public:
+ BlockEntrance(const CFGBlock *B, const LocationContext *L,
+ const ProgramPointTag *tag = nullptr)
+ : ProgramPoint(B, BlockEntranceKind, L, tag) {
+ assert(B && "BlockEntrance requires non-null block");
+ }
+
+ const CFGBlock *getBlock() const {
+ return reinterpret_cast<const CFGBlock*>(getData1());
+ }
+
+ Optional<CFGElement> getFirstElement() const {
+ const CFGBlock *B = getBlock();
+ return B->empty() ? Optional<CFGElement>() : B->front();
+ }
+
+private:
+ friend class ProgramPoint;
+ BlockEntrance() {}
+ static bool isKind(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();
+ }
+
+private:
+ friend class ProgramPoint;
+ BlockExit() {}
+ static bool isKind(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 ProgramPointTag *tag)
+ : ProgramPoint(S, p2, k, L, tag) {
+ assert(S);
+ }
+
+ const Stmt *getStmt() const { return (const Stmt*) getData1(); }
+
+ template <typename T>
+ const T* getStmtAs() const { return dyn_cast<T>(getStmt()); }
+
+protected:
+ StmtPoint() {}
+private:
+ friend class ProgramPoint;
+ static bool isKind(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 ProgramPointTag *tag,
+ const Stmt *SubStmt = nullptr)
+ : StmtPoint(S, SubStmt, PreStmtKind, L, tag) {}
+
+ const Stmt *getSubStmt() const { return (const Stmt*) getData2(); }
+
+private:
+ friend class ProgramPoint;
+ PreStmt() {}
+ static bool isKind(const ProgramPoint &Location) {
+ return Location.getKind() == PreStmtKind;
+ }
+};
+
+class PostStmt : public StmtPoint {
+protected:
+ PostStmt() {}
+ PostStmt(const Stmt *S, const void *data, Kind k, const LocationContext *L,
+ const ProgramPointTag *tag = nullptr)
+ : StmtPoint(S, data, k, L, tag) {}
+
+public:
+ explicit PostStmt(const Stmt *S, Kind k, const LocationContext *L,
+ const ProgramPointTag *tag = nullptr)
+ : StmtPoint(S, nullptr, k, L, tag) {}
+
+ explicit PostStmt(const Stmt *S, const LocationContext *L,
+ const ProgramPointTag *tag = nullptr)
+ : StmtPoint(S, nullptr, PostStmtKind, L, tag) {}
+
+private:
+ friend class ProgramPoint;
+ static bool isKind(const ProgramPoint &Location) {
+ unsigned k = Location.getKind();
+ return k >= MinPostStmtKind && k <= MaxPostStmtKind;
+ }
+};
+
+// PostCondition represents the post program point of a branch condition.
+class PostCondition : public PostStmt {
+public:
+ PostCondition(const Stmt *S, const LocationContext *L,
+ const ProgramPointTag *tag = nullptr)
+ : PostStmt(S, PostConditionKind, L, tag) {}
+
+private:
+ friend class ProgramPoint;
+ PostCondition() {}
+ static bool isKind(const ProgramPoint &Location) {
+ return Location.getKind() == PostConditionKind;
+ }
+};
+
+class LocationCheck : public StmtPoint {
+protected:
+ LocationCheck() {}
+ LocationCheck(const Stmt *S, const LocationContext *L,
+ ProgramPoint::Kind K, const ProgramPointTag *tag)
+ : StmtPoint(S, nullptr, K, L, tag) {}
+
+private:
+ friend class ProgramPoint;
+ static bool isKind(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 ProgramPointTag *tag = nullptr)
+ : LocationCheck(S, L, PreLoadKind, tag) {}
+
+private:
+ friend class ProgramPoint;
+ PreLoad() {}
+ static bool isKind(const ProgramPoint &location) {
+ return location.getKind() == PreLoadKind;
+ }
+};
+
+class PreStore : public LocationCheck {
+public:
+ PreStore(const Stmt *S, const LocationContext *L,
+ const ProgramPointTag *tag = nullptr)
+ : LocationCheck(S, L, PreStoreKind, tag) {}
+
+private:
+ friend class ProgramPoint;
+ PreStore() {}
+ static bool isKind(const ProgramPoint &location) {
+ return location.getKind() == PreStoreKind;
+ }
+};
+
+class PostLoad : public PostStmt {
+public:
+ PostLoad(const Stmt *S, const LocationContext *L,
+ const ProgramPointTag *tag = nullptr)
+ : PostStmt(S, PostLoadKind, L, tag) {}
+
+private:
+ friend class ProgramPoint;
+ PostLoad() {}
+ static bool isKind(const ProgramPoint &Location) {
+ return Location.getKind() == PostLoadKind;
+ }
+};
+
+/// \brief Represents a program point after a store evaluation.
+class PostStore : public PostStmt {
+public:
+ /// Construct the post store point.
+ /// \param Loc can be used to store the information about the location
+ /// used in the form it was uttered in the code.
+ PostStore(const Stmt *S, const LocationContext *L, const void *Loc,
+ const ProgramPointTag *tag = nullptr)
+ : PostStmt(S, PostStoreKind, L, tag) {
+ assert(getData2() == nullptr);
+ setData2(Loc);
+ }
+
+ /// \brief Returns the information about the location used in the store,
+ /// how it was uttered in the code.
+ const void *getLocationValue() const {
+ return getData2();
+ }
+
+private:
+ friend class ProgramPoint;
+ PostStore() {}
+ static bool isKind(const ProgramPoint &Location) {
+ return Location.getKind() == PostStoreKind;
+ }
+};
+
+class PostLValue : public PostStmt {
+public:
+ PostLValue(const Stmt *S, const LocationContext *L,
+ const ProgramPointTag *tag = nullptr)
+ : PostStmt(S, PostLValueKind, L, tag) {}
+
+private:
+ friend class ProgramPoint;
+ PostLValue() {}
+ static bool isKind(const ProgramPoint &Location) {
+ return Location.getKind() == PostLValueKind;
+ }
+};
+
+/// Represents a point after we ran remove dead bindings BEFORE
+/// processing the given statement.
+class PreStmtPurgeDeadSymbols : public StmtPoint {
+public:
+ PreStmtPurgeDeadSymbols(const Stmt *S, const LocationContext *L,
+ const ProgramPointTag *tag = nullptr)
+ : StmtPoint(S, nullptr, PreStmtPurgeDeadSymbolsKind, L, tag) { }
+
+private:
+ friend class ProgramPoint;
+ PreStmtPurgeDeadSymbols() {}
+ static bool isKind(const ProgramPoint &Location) {
+ return Location.getKind() == PreStmtPurgeDeadSymbolsKind;
+ }
+};
+
+/// Represents a point after we ran remove dead bindings AFTER
+/// processing the given statement.
+class PostStmtPurgeDeadSymbols : public StmtPoint {
+public:
+ PostStmtPurgeDeadSymbols(const Stmt *S, const LocationContext *L,
+ const ProgramPointTag *tag = nullptr)
+ : StmtPoint(S, nullptr, PostStmtPurgeDeadSymbolsKind, L, tag) { }
+
+private:
+ friend class ProgramPoint;
+ PostStmtPurgeDeadSymbols() {}
+ static bool isKind(const ProgramPoint &Location) {
+ return Location.getKind() == PostStmtPurgeDeadSymbolsKind;
+ }
+};
+
+class BlockEdge : public ProgramPoint {
+public:
+ BlockEdge(const CFGBlock *B1, const CFGBlock *B2, const LocationContext *L)
+ : ProgramPoint(B1, B2, BlockEdgeKind, L) {
+ assert(B1 && "BlockEdge: source block must be non-null");
+ assert(B2 && "BlockEdge: destination block must be non-null");
+ }
+
+ const CFGBlock *getSrc() const {
+ return static_cast<const CFGBlock*>(getData1());
+ }
+
+ const CFGBlock *getDst() const {
+ return static_cast<const CFGBlock*>(getData2());
+ }
+
+private:
+ friend class ProgramPoint;
+ BlockEdge() {}
+ static bool isKind(const ProgramPoint &Location) {
+ return Location.getKind() == BlockEdgeKind;
+ }
+};
+
+class PostInitializer : public ProgramPoint {
+public:
+ /// \brief Construct a PostInitializer point that represents a location after
+ /// CXXCtorInitializer expression evaluation.
+ ///
+ /// \param I The initializer.
+ /// \param Loc The location of the field being initialized.
+ PostInitializer(const CXXCtorInitializer *I,
+ const void *Loc,
+ const LocationContext *L)
+ : ProgramPoint(I, Loc, PostInitializerKind, L) {}
+
+ const CXXCtorInitializer *getInitializer() const {
+ return static_cast<const CXXCtorInitializer *>(getData1());
+ }
+
+ /// \brief Returns the location of the field.
+ const void *getLocationValue() const {
+ return getData2();
+ }
+
+private:
+ friend class ProgramPoint;
+ PostInitializer() {}
+ static bool isKind(const ProgramPoint &Location) {
+ return Location.getKind() == PostInitializerKind;
+ }
+};
+
+/// Represents an implicit call event.
+///
+/// The nearest statement is provided for diagnostic purposes.
+class ImplicitCallPoint : public ProgramPoint {
+public:
+ ImplicitCallPoint(const Decl *D, SourceLocation Loc, Kind K,
+ const LocationContext *L, const ProgramPointTag *Tag)
+ : ProgramPoint(Loc.getPtrEncoding(), D, K, L, Tag) {}
+
+ const Decl *getDecl() const { return static_cast<const Decl *>(getData2()); }
+ SourceLocation getLocation() const {
+ return SourceLocation::getFromPtrEncoding(getData1());
+ }
+
+protected:
+ ImplicitCallPoint() {}
+private:
+ friend class ProgramPoint;
+ static bool isKind(const ProgramPoint &Location) {
+ return Location.getKind() >= MinImplicitCallKind &&
+ Location.getKind() <= MaxImplicitCallKind;
+ }
+};
+
+/// Represents a program point just before an implicit call event.
+///
+/// Explicit calls will appear as PreStmt program points.
+class PreImplicitCall : public ImplicitCallPoint {
+public:
+ PreImplicitCall(const Decl *D, SourceLocation Loc, const LocationContext *L,
+ const ProgramPointTag *Tag = nullptr)
+ : ImplicitCallPoint(D, Loc, PreImplicitCallKind, L, Tag) {}
+
+private:
+ friend class ProgramPoint;
+ PreImplicitCall() {}
+ static bool isKind(const ProgramPoint &Location) {
+ return Location.getKind() == PreImplicitCallKind;
+ }
+};
+
+/// Represents a program point just after an implicit call event.
+///
+/// Explicit calls will appear as PostStmt program points.
+class PostImplicitCall : public ImplicitCallPoint {
+public:
+ PostImplicitCall(const Decl *D, SourceLocation Loc, const LocationContext *L,
+ const ProgramPointTag *Tag = nullptr)
+ : ImplicitCallPoint(D, Loc, PostImplicitCallKind, L, Tag) {}
+
+private:
+ friend class ProgramPoint;
+ PostImplicitCall() {}
+ static bool isKind(const ProgramPoint &Location) {
+ return Location.getKind() == PostImplicitCallKind;
+ }
+};
+
+/// Represents a point when we begin processing an inlined call.
+/// CallEnter uses the caller's location context.
+class CallEnter : public ProgramPoint {
+public:
+ CallEnter(const Stmt *stmt, const StackFrameContext *calleeCtx,
+ const LocationContext *callerCtx)
+ : ProgramPoint(stmt, calleeCtx, CallEnterKind, callerCtx, nullptr) {}
+
+ const Stmt *getCallExpr() const {
+ return static_cast<const Stmt *>(getData1());
+ }
+
+ const StackFrameContext *getCalleeContext() const {
+ return static_cast<const StackFrameContext *>(getData2());
+ }
+
+private:
+ friend class ProgramPoint;
+ CallEnter() {}
+ static bool isKind(const ProgramPoint &Location) {
+ return Location.getKind() == CallEnterKind;
+ }
+};
+
+/// Represents a point when we start the call exit sequence (for inlined call).
+///
+/// The call exit is simulated with a sequence of nodes, which occur between
+/// CallExitBegin and CallExitEnd. The following operations occur between the
+/// two program points:
+/// - CallExitBegin
+/// - Bind the return value
+/// - Run Remove dead bindings (to clean up the dead symbols from the callee).
+/// - CallExitEnd
+class CallExitBegin : public ProgramPoint {
+public:
+ // CallExitBegin uses the callee's location context.
+ CallExitBegin(const StackFrameContext *L)
+ : ProgramPoint(nullptr, CallExitBeginKind, L, nullptr) {}
+
+private:
+ friend class ProgramPoint;
+ CallExitBegin() {}
+ static bool isKind(const ProgramPoint &Location) {
+ return Location.getKind() == CallExitBeginKind;
+ }
+};
+
+/// Represents a point when we finish the call exit sequence (for inlined call).
+/// \sa CallExitBegin
+class CallExitEnd : public ProgramPoint {
+public:
+ // CallExitEnd uses the caller's location context.
+ CallExitEnd(const StackFrameContext *CalleeCtx,
+ const LocationContext *CallerCtx)
+ : ProgramPoint(CalleeCtx, CallExitEndKind, CallerCtx, nullptr) {}
+
+ const StackFrameContext *getCalleeContext() const {
+ return static_cast<const StackFrameContext *>(getData1());
+ }
+
+private:
+ friend class ProgramPoint;
+ CallExitEnd() {}
+ static bool isKind(const ProgramPoint &Location) {
+ return Location.getKind() == CallExitEndKind;
+ }
+};
+
+/// This is a meta program point, which should be skipped by all the diagnostic
+/// reasoning etc.
+class EpsilonPoint : public ProgramPoint {
+public:
+ EpsilonPoint(const LocationContext *L, const void *Data1,
+ const void *Data2 = nullptr,
+ const ProgramPointTag *tag = nullptr)
+ : ProgramPoint(Data1, Data2, EpsilonKind, L, tag) {}
+
+ const void *getData() const { return getData1(); }
+
+private:
+ friend class ProgramPoint;
+ EpsilonPoint() {}
+ static bool isKind(const ProgramPoint &Location) {
+ return Location.getKind() == EpsilonKind;
+ }
+};
+
+} // 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), nullptr);
+}
+
+static inline clang::ProgramPoint getTombstoneKey() {
+ uintptr_t x =
+ reinterpret_cast<uintptr_t>(DenseMapInfo<void*>::getTombstoneKey()) & ~0x7;
+ return clang::BlockEntrance(reinterpret_cast<clang::CFGBlock*>(x), nullptr);
+}
+
+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/BumpVector.h b/contrib/llvm/tools/clang/include/clang/Analysis/Support/BumpVector.h
new file mode 100644
index 0000000..591d17b
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Analysis/Support/BumpVector.h
@@ -0,0 +1,250 @@
+//===-- 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_ANALYSIS_SUPPORT_BUMPVECTOR_H
+#define LLVM_CLANG_ANALYSIS_SUPPORT_BUMPVECTOR_H
+
+#include "llvm/ADT/PointerIntPair.h"
+#include "llvm/Support/Allocator.h"
+#include "llvm/Support/type_traits.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) {}
+
+ BumpVectorContext(BumpVectorContext &&Other) : Alloc(Other.Alloc) {
+ Other.Alloc.setInt(false);
+ Other.Alloc.setPointer(nullptr);
+ }
+
+ /// 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(nullptr), End(nullptr), Capacity(nullptr) {
+ reserve(C, N);
+ }
+
+ ~BumpVector() {
+ if (std::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 (std::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 (Begin != End) {
+ if (std::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
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..75e9faf
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Basic/ABI.h
@@ -0,0 +1,211 @@
+//===----- 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.
+//
+//===----------------------------------------------------------------------===//
+///
+/// \file
+/// \brief Enums/classes describing ABI related information about constructors,
+/// destructors and thunks.
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_BASIC_ABI_H
+#define LLVM_CLANG_BASIC_ABI_H
+
+#include "llvm/Support/DataTypes.h"
+#include <cstring>
+
+namespace clang {
+
+/// \brief C++ constructor types.
+enum CXXCtorType {
+ Ctor_Complete, ///< Complete object ctor
+ Ctor_Base, ///< Base object ctor
+ Ctor_Comdat, ///< The COMDAT used for ctors
+ Ctor_CopyingClosure, ///< Copying closure variant of a ctor
+ Ctor_DefaultClosure, ///< Default closure variant of a ctor
+};
+
+/// \brief C++ destructor types.
+enum CXXDtorType {
+ Dtor_Deleting, ///< Deleting dtor
+ Dtor_Complete, ///< Complete object dtor
+ Dtor_Base, ///< Base object dtor
+ Dtor_Comdat ///< The COMDAT used for dtors
+};
+
+/// \brief A return adjustment.
+struct ReturnAdjustment {
+ /// \brief The non-virtual adjustment from the derived object to its
+ /// nearest virtual base.
+ int64_t NonVirtual;
+
+ /// \brief Holds the ABI-specific information about the virtual return
+ /// adjustment, if needed.
+ union VirtualAdjustment {
+ // Itanium ABI
+ struct {
+ /// \brief The offset (in bytes), relative to the address point
+ /// of the virtual base class offset.
+ int64_t VBaseOffsetOffset;
+ } Itanium;
+
+ // Microsoft ABI
+ struct {
+ /// \brief The offset (in bytes) of the vbptr, relative to the beginning
+ /// of the derived class.
+ uint32_t VBPtrOffset;
+
+ /// \brief Index of the virtual base in the vbtable.
+ uint32_t VBIndex;
+ } Microsoft;
+
+ VirtualAdjustment() {
+ memset(this, 0, sizeof(*this));
+ }
+
+ bool Equals(const VirtualAdjustment &Other) const {
+ return memcmp(this, &Other, sizeof(Other)) == 0;
+ }
+
+ bool isEmpty() const {
+ VirtualAdjustment Zero;
+ return Equals(Zero);
+ }
+
+ bool Less(const VirtualAdjustment &RHS) const {
+ return memcmp(this, &RHS, sizeof(RHS)) < 0;
+ }
+ } Virtual;
+
+ ReturnAdjustment() : NonVirtual(0) {}
+
+ bool isEmpty() const { return !NonVirtual && Virtual.isEmpty(); }
+
+ friend bool operator==(const ReturnAdjustment &LHS,
+ const ReturnAdjustment &RHS) {
+ return LHS.NonVirtual == RHS.NonVirtual && LHS.Virtual.Equals(RHS.Virtual);
+ }
+
+ friend bool operator!=(const ReturnAdjustment &LHS, const ReturnAdjustment &RHS) {
+ return !(LHS == RHS);
+ }
+
+ friend bool operator<(const ReturnAdjustment &LHS,
+ const ReturnAdjustment &RHS) {
+ if (LHS.NonVirtual < RHS.NonVirtual)
+ return true;
+
+ return LHS.NonVirtual == RHS.NonVirtual && LHS.Virtual.Less(RHS.Virtual);
+ }
+};
+
+/// \brief A \c this pointer adjustment.
+struct ThisAdjustment {
+ /// \brief The non-virtual adjustment from the derived object to its
+ /// nearest virtual base.
+ int64_t NonVirtual;
+
+ /// \brief Holds the ABI-specific information about the virtual this
+ /// adjustment, if needed.
+ union VirtualAdjustment {
+ // Itanium ABI
+ struct {
+ /// \brief The offset (in bytes), relative to the address point,
+ /// of the virtual call offset.
+ int64_t VCallOffsetOffset;
+ } Itanium;
+
+ struct {
+ /// \brief The offset of the vtordisp (in bytes), relative to the ECX.
+ int32_t VtordispOffset;
+
+ /// \brief The offset of the vbptr of the derived class (in bytes),
+ /// relative to the ECX after vtordisp adjustment.
+ int32_t VBPtrOffset;
+
+ /// \brief The offset (in bytes) of the vbase offset in the vbtable.
+ int32_t VBOffsetOffset;
+ } Microsoft;
+
+ VirtualAdjustment() {
+ memset(this, 0, sizeof(*this));
+ }
+
+ bool Equals(const VirtualAdjustment &Other) const {
+ return memcmp(this, &Other, sizeof(Other)) == 0;
+ }
+
+ bool isEmpty() const {
+ VirtualAdjustment Zero;
+ return Equals(Zero);
+ }
+
+ bool Less(const VirtualAdjustment &RHS) const {
+ return memcmp(this, &RHS, sizeof(RHS)) < 0;
+ }
+ } Virtual;
+
+ ThisAdjustment() : NonVirtual(0) { }
+
+ bool isEmpty() const { return !NonVirtual && Virtual.isEmpty(); }
+
+ friend bool operator==(const ThisAdjustment &LHS,
+ const ThisAdjustment &RHS) {
+ return LHS.NonVirtual == RHS.NonVirtual && LHS.Virtual.Equals(RHS.Virtual);
+ }
+
+ friend bool operator!=(const ThisAdjustment &LHS, const ThisAdjustment &RHS) {
+ return !(LHS == RHS);
+ }
+
+ friend bool operator<(const ThisAdjustment &LHS,
+ const ThisAdjustment &RHS) {
+ if (LHS.NonVirtual < RHS.NonVirtual)
+ return true;
+
+ return LHS.NonVirtual == RHS.NonVirtual && LHS.Virtual.Less(RHS.Virtual);
+ }
+};
+
+class CXXMethodDecl;
+
+/// \brief The \c this pointer adjustment as well as an optional return
+/// adjustment for a thunk.
+struct ThunkInfo {
+ /// \brief The \c this pointer adjustment.
+ ThisAdjustment This;
+
+ /// \brief The return adjustment.
+ ReturnAdjustment Return;
+
+ /// \brief Holds a pointer to the overridden method this thunk is for,
+ /// if needed by the ABI to distinguish different thunks with equal
+ /// adjustments. Otherwise, null.
+ /// CAUTION: In the unlikely event you need to sort ThunkInfos, consider using
+ /// an ABI-specific comparator.
+ const CXXMethodDecl *Method;
+
+ ThunkInfo() : Method(nullptr) { }
+
+ ThunkInfo(const ThisAdjustment &This, const ReturnAdjustment &Return,
+ const CXXMethodDecl *Method = nullptr)
+ : This(This), Return(Return), Method(Method) {}
+
+ friend bool operator==(const ThunkInfo &LHS, const ThunkInfo &RHS) {
+ return LHS.This == RHS.This && LHS.Return == RHS.Return &&
+ LHS.Method == RHS.Method;
+ }
+
+ bool isEmpty() const {
+ return This.isEmpty() && Return.isEmpty() && Method == nullptr;
+ }
+};
+
+} // end namespace clang
+
+#endif
diff --git a/contrib/llvm/tools/clang/include/clang/Basic/AddressSpaces.h b/contrib/llvm/tools/clang/include/clang/Basic/AddressSpaces.h
new file mode 100644
index 0000000..8dd7566
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Basic/AddressSpaces.h
@@ -0,0 +1,51 @@
+//===--- AddressSpaces.h - Language-specific address spaces -----*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+///
+/// \file
+/// \brief Provides definitions for the various language-specific address
+/// spaces.
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_BASIC_ADDRESSSPACES_H
+#define LLVM_CLANG_BASIC_ADDRESSSPACES_H
+
+namespace clang {
+
+namespace LangAS {
+
+/// \brief Defines the set of possible language-specific address spaces.
+///
+/// This uses a high starting offset so as not to conflict with any address
+/// space used by a target.
+enum ID {
+ Offset = 0xFFFF00,
+
+ opencl_global = Offset,
+ opencl_local,
+ opencl_constant,
+ opencl_generic,
+
+ cuda_device,
+ cuda_constant,
+ cuda_shared,
+
+ Last,
+ Count = Last-Offset
+};
+
+/// The type of a lookup table which maps from language-specific address spaces
+/// to target-specific ones.
+typedef unsigned Map[Count];
+
+}
+
+}
+
+#endif
diff --git a/contrib/llvm/tools/clang/include/clang/Basic/AllDiagnostics.h b/contrib/llvm/tools/clang/include/clang/Basic/AllDiagnostics.h
new file mode 100644
index 0000000..18a2b8a
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Basic/AllDiagnostics.h
@@ -0,0 +1,40 @@
+//===--- AllDiagnostics.h - Aggregate Diagnostic headers --------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+///
+/// \file
+/// \brief Includes all the separate Diagnostic headers & some related helpers.
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_BASIC_ALLDIAGNOSTICS_H
+#define LLVM_CLANG_BASIC_ALLDIAGNOSTICS_H
+
+#include "clang/AST/ASTDiagnostic.h"
+#include "clang/AST/CommentDiagnostic.h"
+#include "clang/Analysis/AnalysisDiagnostic.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 "clang/Serialization/SerializationDiagnostic.h"
+
+namespace clang {
+template <size_t SizeOfStr, typename FieldType>
+class StringSizerHelper {
+ char FIELD_TOO_SMALL[SizeOfStr <= FieldType(~0U) ? 1 : -1];
+public:
+ enum { Size = SizeOfStr };
+};
+} // end namespace clang
+
+#define STR_SIZE(str, fieldTy) clang::StringSizerHelper<sizeof(str)-1, \
+ fieldTy>::Size
+
+#endif
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..d5ba722
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Basic/Attr.td
@@ -0,0 +1,2172 @@
+//==--- Attr.td - attribute definitions -----------------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// The documentation is organized by category. Attributes can have category-
+// specific documentation that is collated within the larger document.
+class DocumentationCategory<string name> {
+ string Name = name;
+ code Content = [{}];
+}
+def DocCatFunction : DocumentationCategory<"Function Attributes">;
+def DocCatVariable : DocumentationCategory<"Variable Attributes">;
+def DocCatType : DocumentationCategory<"Type Attributes">;
+def DocCatStmt : DocumentationCategory<"Statement Attributes">;
+// Attributes listed under the Undocumented category do not generate any public
+// documentation. Ideally, this category should be used for internal-only
+// attributes which contain no spellings.
+def DocCatUndocumented : DocumentationCategory<"Undocumented">;
+
+class DocDeprecated<string replacement = ""> {
+ // If the Replacement field is empty, no replacement will be listed with the
+ // documentation. Otherwise, the documentation will specify the attribute has
+ // been superseded by this replacement.
+ string Replacement = replacement;
+}
+
+// Specifies the documentation to be associated with the given category.
+class Documentation {
+ DocumentationCategory Category;
+ code Content;
+
+ // If the heading is empty, one may be picked automatically. If the attribute
+ // only has one spelling, no heading is required as the attribute's sole
+ // spelling is sufficient. If all spellings are semantically common, the
+ // heading will be the semantic spelling. If the spellings are not
+ // semantically common and no heading is provided, an error will be emitted.
+ string Heading = "";
+
+ // When set, specifies that the attribute is deprecated and can optionally
+ // specify a replacement attribute.
+ DocDeprecated Deprecated;
+}
+
+// Specifies that the attribute is explicitly undocumented. This can be a
+// helpful placeholder for the attribute while working on the implementation,
+// but should not be used once feature work has been completed.
+def Undocumented : Documentation {
+ let Category = DocCatUndocumented;
+}
+
+include "clang/Basic/AttrDocs.td"
+
+// 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 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, code check> : AttrSubject {
+ AttrSubject Base = base;
+ code CheckCode = check;
+}
+
+// This is the type of a variable which C++11 allows alignas(...) to appertain
+// to.
+def NormalVar : SubsetSubject<Var,
+ [{S->getStorageClass() != VarDecl::Register &&
+ S->getKind() != Decl::ImplicitParam &&
+ S->getKind() != Decl::ParmVar &&
+ S->getKind() != Decl::NonTypeTemplateParm}]>;
+def NonBitField : SubsetSubject<Field,
+ [{!S->isBitField()}]>;
+
+def ObjCInstanceMethod : SubsetSubject<ObjCMethod,
+ [{S->isInstanceMethod()}]>;
+
+def ObjCInterfaceDeclInitMethod : SubsetSubject<ObjCMethod,
+ [{S->getMethodFamily() == OMF_init &&
+ (isa<ObjCInterfaceDecl>(S->getDeclContext()) ||
+ (isa<ObjCCategoryDecl>(S->getDeclContext()) &&
+ cast<ObjCCategoryDecl>(S->getDeclContext())->IsClassExtension()))}]>;
+
+def Struct : SubsetSubject<Record,
+ [{!S->isUnion()}]>;
+
+def TLSVar : SubsetSubject<Var,
+ [{S->getTLSKind() != 0}]>;
+
+def SharedVar : SubsetSubject<Var,
+ [{S->hasGlobalStorage() && !S->getTLSKind()}]>;
+
+def GlobalVar : SubsetSubject<Var,
+ [{S->hasGlobalStorage()}]>;
+
+// FIXME: this hack is needed because DeclNodes.td defines the base Decl node
+// type to be a class, not a definition. This makes it impossible to create an
+// attribute subject which accepts a Decl. Normally, this is not a problem,
+// because the attribute can have no Subjects clause to accomplish this. But in
+// the case of a SubsetSubject, there's no way to express it without this hack.
+def DeclBase : AttrSubject;
+def FunctionLike : SubsetSubject<DeclBase,
+ [{S->getFunctionType(false) != nullptr}]>;
+
+def OpenCLKernelFunction : SubsetSubject<Function, [{
+ S->hasAttr<OpenCLKernelAttr>()
+}]>;
+
+// HasFunctionProto is a more strict version of FunctionLike, so it should
+// never be specified in a Subjects list along with FunctionLike (due to the
+// inclusive nature of subject testing).
+def HasFunctionProto : SubsetSubject<DeclBase,
+ [{(S->getFunctionType(true) != nullptr &&
+ isa<FunctionProtoType>(S->getFunctionType())) ||
+ isa<ObjCMethodDecl>(S) ||
+ isa<BlockDecl>(S)}]>;
+
+// A single argument to an attribute
+class Argument<string name, bit optional, bit fake = 0> {
+ string Name = name;
+ bit Optional = optional;
+
+ /// A fake argument is used to store and serialize additional information
+ /// in an attribute without actually changing its parsing or pretty-printing.
+ bit Fake = fake;
+}
+
+class BoolArgument<string name, bit opt = 0> : Argument<name, opt>;
+class IdentifierArgument<string name, bit opt = 0> : Argument<name, opt>;
+class IntArgument<string name, bit opt = 0> : Argument<name, opt>;
+class StringArgument<string name, bit opt = 0> : Argument<name, opt>;
+class ExprArgument<string name, bit opt = 0> : Argument<name, opt>;
+class FunctionArgument<string name, bit opt = 0> : Argument<name, opt>;
+class TypeArgument<string name, bit opt = 0> : Argument<name, opt>;
+class UnsignedArgument<string name, bit opt = 0> : Argument<name, opt>;
+class VariadicUnsignedArgument<string name> : Argument<name, 1>;
+class VariadicExprArgument<string name> : Argument<name, 1>;
+class VariadicStringArgument<string name> : Argument<name, 1>;
+
+// A version of the form major.minor[.subminor].
+class VersionArgument<string name, bit opt = 0> : Argument<name, opt>;
+
+// 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, bit opt = 0> : Argument<name, opt>;
+
+// A bool argument with a default value
+class DefaultBoolArgument<string name, bit default> : BoolArgument<name, 1> {
+ bit Default = default;
+}
+
+// An integer argument with a default value
+class DefaultIntArgument<string name, int default> : IntArgument<name, 1> {
+ 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, bit opt = 0, bit fake = 0>
+ : Argument<name, opt, fake> {
+ string Type = type;
+ list<string> Values = values;
+ list<string> Enums = enums;
+}
+
+// FIXME: There should be a VariadicArgument type that takes any other type
+// of argument and generates the appropriate type.
+class VariadicEnumArgument<string name, string type, list<string> values,
+ list<string> enums> : Argument<name, 1> {
+ string Type = type;
+ list<string> Values = values;
+ list<string> Enums = enums;
+}
+
+// This handles one spelling of an attribute.
+class Spelling<string name, string variety> {
+ string Name = name;
+ string Variety = variety;
+ bit KnownToGCC;
+}
+
+class GNU<string name> : Spelling<name, "GNU">;
+class Declspec<string name> : Spelling<name, "Declspec">;
+class CXX11<string namespace, string name, int version = 1>
+ : Spelling<name, "CXX11"> {
+ string Namespace = namespace;
+ int Version = version;
+}
+class Keyword<string name> : Spelling<name, "Keyword">;
+class Pragma<string namespace, string name> : Spelling<name, "Pragma"> {
+ string Namespace = namespace;
+}
+
+// The GCC spelling implies GNU<name, "GNU"> and CXX11<"gnu", name> and also
+// sets KnownToGCC to 1. This spelling should be used for any GCC-compatible
+// attributes.
+class GCC<string name> : Spelling<name, "GCC"> {
+ let KnownToGCC = 1;
+}
+
+class Accessor<string name, list<Spelling> spellings> {
+ string Name = name;
+ list<Spelling> Spellings = spellings;
+}
+
+class SubjectDiag<bit warn> {
+ bit Warn = warn;
+}
+def WarnDiag : SubjectDiag<1>;
+def ErrorDiag : SubjectDiag<0>;
+
+class SubjectList<list<AttrSubject> subjects, SubjectDiag diag = WarnDiag,
+ string customDiag = ""> {
+ list<AttrSubject> Subjects = subjects;
+ SubjectDiag Diag = diag;
+ string CustomDiag = customDiag;
+}
+
+class LangOpt<string name, bit negated = 0> {
+ string Name = name;
+ bit Negated = negated;
+}
+def MicrosoftExt : LangOpt<"MicrosoftExt">;
+def Borland : LangOpt<"Borland">;
+def CUDA : LangOpt<"CUDA">;
+def COnly : LangOpt<"CPlusPlus", 1>;
+
+// Defines targets for target-specific attributes. The list of strings should
+// specify architectures for which the target applies, based off the ArchType
+// enumeration in Triple.h.
+class TargetArch<list<string> arches> {
+ list<string> Arches = arches;
+ list<string> OSes;
+ list<string> CXXABIs;
+}
+def TargetARM : TargetArch<["arm", "thumb"]>;
+def TargetMips : TargetArch<["mips", "mipsel"]>;
+def TargetMSP430 : TargetArch<["msp430"]>;
+def TargetX86 : TargetArch<["x86"]>;
+def TargetWindows : TargetArch<["x86", "x86_64", "arm", "thumb"]> {
+ let OSes = ["Win32"];
+}
+def TargetMicrosoftCXXABI : TargetArch<["x86", "x86_64", "arm", "thumb"]> {
+ let CXXABIs = ["Microsoft"];
+}
+
+class Attr {
+ // The various ways in which an attribute can be spelled in source
+ list<Spelling> Spellings;
+ // The things to which an attribute can appertain
+ SubjectList Subjects;
+ // The arguments allowed on an attribute
+ list<Argument> Args = [];
+ // Accessors which should be generated for the attribute.
+ list<Accessor> Accessors = [];
+ // Set to true for attributes with arguments which require delayed parsing.
+ bit LateParsed = 0;
+ // Set to false to prevent an attribute from being propagated from a template
+ // to the instantiation.
+ bit Clone = 1;
+ // Set to true for attributes which must be instantiated within templates
+ bit TemplateDependent = 0;
+ // Set to true for attributes that have a corresponding AST node.
+ bit ASTNode = 1;
+ // Set to true for attributes which have handler in Sema.
+ bit SemaHandler = 1;
+ // Set to true for attributes that are completely ignored.
+ bit Ignored = 0;
+ // Set to true if the attribute's parsing does not match its semantic
+ // content. Eg) It parses 3 args, but semantically takes 4 args. Opts out of
+ // common attribute error checking.
+ bit HasCustomParsing = 0;
+ // Set to true if all of the attribute's arguments should be parsed in an
+ // unevaluated context.
+ bit ParseArgumentsAsUnevaluated = 0;
+ // Set to true if this attribute can be duplicated on a subject when merging
+ // attributes. By default, attributes are not merged.
+ bit DuplicatesAllowedWhileMerging = 0;
+ // Lists language options, one of which is required to be true for the
+ // attribute to be applicable. If empty, no language options are required.
+ list<LangOpt> LangOpts = [];
+ // Any additional text that should be included verbatim in the class.
+ // Note: Any additional data members will leak and should be constructed
+ // externally on the ASTContext.
+ code AdditionalMembers = [{}];
+ // Any documentation that should be associated with the attribute. Since an
+ // attribute may be documented under multiple categories, more than one
+ // Documentation entry may be listed.
+ list<Documentation> Documentation;
+}
+
+/// A type attribute is not processed on a declaration or a statement.
+class TypeAttr : Attr {
+ // By default, type attributes do not get an AST node.
+ let ASTNode = 0;
+}
+
+/// An inheritable attribute is inherited by later redeclarations.
+class InheritableAttr : Attr;
+
+/// A target-specific attribute. This class is meant to be used as a mixin
+/// with InheritableAttr or Attr depending on the attribute's needs.
+class TargetSpecificAttr<TargetArch target> {
+ TargetArch Target = target;
+ // Attributes are generally required to have unique spellings for their names
+ // so that the parser can determine what kind of attribute it has parsed.
+ // However, target-specific attributes are special in that the attribute only
+ // "exists" for a given target. So two target-specific attributes can share
+ // the same name when they exist in different targets. To support this, a
+ // Kind can be explicitly specified for a target-specific attribute. This
+ // corresponds to the AttributeList::AT_* enum that is generated and it
+ // should contain a shared value between the attributes.
+ //
+ // Target-specific attributes which use this feature should ensure that the
+ // spellings match exactly betweeen the attributes, and if the arguments or
+ // subjects differ, should specify HasCustomParsing = 1 and implement their
+ // own parsing and semantic handling requirements as-needed.
+ string ParseKind;
+}
+
+/// An inheritable parameter attribute is inherited by later
+/// redeclarations, even when it's written on a parameter.
+class InheritableParamAttr : InheritableAttr;
+
+/// An ignored attribute, which we parse but discard with no checking.
+class IgnoredAttr : Attr {
+ let Ignored = 1;
+ let ASTNode = 0;
+ let SemaHandler = 0;
+ let Documentation = [Undocumented];
+}
+
+//
+// Attributes begin here
+//
+
+def AddressSpace : TypeAttr {
+ let Spellings = [GNU<"address_space">];
+ let Args = [IntArgument<"AddressSpace">];
+ let Documentation = [Undocumented];
+}
+
+def Alias : Attr {
+ let Spellings = [GCC<"alias">];
+ let Args = [StringArgument<"Aliasee">];
+ let Subjects = SubjectList<[Function, GlobalVar], ErrorDiag,
+ "ExpectedFunctionGlobalVarMethodOrProperty">;
+ let Documentation = [Undocumented];
+}
+
+def Aligned : InheritableAttr {
+ let Spellings = [GCC<"aligned">, Declspec<"align">, Keyword<"alignas">,
+ Keyword<"_Alignas">];
+// let Subjects = SubjectList<[NonBitField, NormalVar, Tag]>;
+ let Args = [AlignedArgument<"Alignment", 1>];
+ let Accessors = [Accessor<"isGNU", [GCC<"aligned">]>,
+ Accessor<"isC11", [Keyword<"_Alignas">]>,
+ Accessor<"isAlignas", [Keyword<"alignas">,
+ Keyword<"_Alignas">]>,
+ Accessor<"isDeclspec",[Declspec<"align">]>];
+ let Documentation = [Undocumented];
+}
+
+def AlignValue : Attr {
+ let Spellings = [
+ // Unfortunately, this is semantically an assertion, not a directive
+ // (something else must ensure the alignment), so aligned_value is a
+ // probably a better name. We might want to add an aligned_value spelling in
+ // the future (and a corresponding C++ attribute), but this can be done
+ // later once we decide if we also want them to have slightly-different
+ // semantics than Intel's align_value.
+ GNU<"align_value">
+ // Intel's compiler on Windows also supports:
+ // , Declspec<"align_value">
+ ];
+ let Args = [ExprArgument<"Alignment">];
+ let Subjects = SubjectList<[Var, TypedefName], WarnDiag,
+ "ExpectedVariableOrTypedef">;
+ let Documentation = [AlignValueDocs];
+}
+
+def AlignMac68k : InheritableAttr {
+ // This attribute has no spellings as it is only ever created implicitly.
+ let Spellings = [];
+ let SemaHandler = 0;
+ let Documentation = [Undocumented];
+}
+
+def AlwaysInline : InheritableAttr {
+ let Spellings = [GCC<"always_inline">, Keyword<"__forceinline">];
+ let Subjects = SubjectList<[Function]>;
+ let Documentation = [Undocumented];
+}
+
+def TLSModel : InheritableAttr {
+ let Spellings = [GCC<"tls_model">];
+ let Subjects = SubjectList<[TLSVar], ErrorDiag, "ExpectedTLSVar">;
+ let Args = [StringArgument<"Model">];
+ let Documentation = [TLSModelDocs];
+}
+
+def AnalyzerNoReturn : InheritableAttr {
+ let Spellings = [GNU<"analyzer_noreturn">];
+ let Documentation = [Undocumented];
+}
+
+def Annotate : InheritableParamAttr {
+ let Spellings = [GNU<"annotate">];
+ let Args = [StringArgument<"Annotation">];
+ let Documentation = [Undocumented];
+}
+
+def ARMInterrupt : InheritableAttr, TargetSpecificAttr<TargetARM> {
+ // NOTE: If you add any additional spellings, MSP430Interrupt's and
+ // MipsInterrupt's spellings must match.
+ let Spellings = [GNU<"interrupt">];
+ let Args = [EnumArgument<"Interrupt", "InterruptType",
+ ["IRQ", "FIQ", "SWI", "ABORT", "UNDEF", ""],
+ ["IRQ", "FIQ", "SWI", "ABORT", "UNDEF", "Generic"],
+ 1>];
+ let ParseKind = "Interrupt";
+ let HasCustomParsing = 1;
+ let Documentation = [ARMInterruptDocs];
+}
+
+def AsmLabel : InheritableAttr {
+ let Spellings = [Keyword<"asm">, Keyword<"__asm__">];
+ let Args = [StringArgument<"Label">];
+ let SemaHandler = 0;
+ let Documentation = [Undocumented];
+}
+
+def Availability : InheritableAttr {
+ let Spellings = [GNU<"availability">];
+ let Args = [IdentifierArgument<"platform">, VersionArgument<"introduced">,
+ VersionArgument<"deprecated">, VersionArgument<"obsoleted">,
+ BoolArgument<"unavailable">, StringArgument<"message">];
+ let AdditionalMembers =
+[{static llvm::StringRef getPrettyPlatformName(llvm::StringRef Platform) {
+ return llvm::StringSwitch<llvm::StringRef>(Platform)
+ .Case("android", "Android")
+ .Case("ios", "iOS")
+ .Case("macosx", "OS X")
+ .Case("tvos", "tvOS")
+ .Case("watchos", "watchOS")
+ .Case("ios_app_extension", "iOS (App Extension)")
+ .Case("macosx_app_extension", "OS X (App Extension)")
+ .Case("tvos_app_extension", "tvOS (App Extension)")
+ .Case("watchos_app_extension", "watchOS (App Extension)")
+ .Default(llvm::StringRef());
+} }];
+ let HasCustomParsing = 1;
+ let DuplicatesAllowedWhileMerging = 1;
+// let Subjects = SubjectList<[Named]>;
+ let Documentation = [AvailabilityDocs];
+}
+
+def Blocks : InheritableAttr {
+ let Spellings = [GNU<"blocks">];
+ let Args = [EnumArgument<"Type", "BlockType", ["byref"], ["ByRef"]>];
+ let Documentation = [Undocumented];
+}
+
+def Bounded : IgnoredAttr {
+ let Spellings = [GNU<"bounded">];
+}
+
+def CarriesDependency : InheritableParamAttr {
+ let Spellings = [GNU<"carries_dependency">,
+ CXX11<"","carries_dependency", 200809>];
+ let Subjects = SubjectList<[ParmVar, ObjCMethod, Function], ErrorDiag>;
+ let Documentation = [CarriesDependencyDocs];
+}
+
+def CDecl : InheritableAttr {
+ let Spellings = [GCC<"cdecl">, Keyword<"__cdecl">, Keyword<"_cdecl">];
+// let Subjects = [Function, ObjCMethod];
+ let Documentation = [Undocumented];
+}
+
+// cf_audited_transfer indicates that the given function has been
+// audited and has been marked with the appropriate cf_consumed and
+// cf_returns_retained attributes. It is generally applied by
+// '#pragma clang arc_cf_code_audited' rather than explicitly.
+def CFAuditedTransfer : InheritableAttr {
+ let Spellings = [GNU<"cf_audited_transfer">];
+ let Subjects = SubjectList<[Function], ErrorDiag>;
+ let Documentation = [Undocumented];
+}
+
+// cf_unknown_transfer is an explicit opt-out of cf_audited_transfer.
+// It indicates that the function has unknown or unautomatable
+// transfer semantics.
+def CFUnknownTransfer : InheritableAttr {
+ let Spellings = [GNU<"cf_unknown_transfer">];
+ let Subjects = SubjectList<[Function], ErrorDiag>;
+ let Documentation = [Undocumented];
+}
+
+def CFReturnsRetained : InheritableAttr {
+ let Spellings = [GNU<"cf_returns_retained">];
+// let Subjects = SubjectList<[ObjCMethod, ObjCProperty, Function]>;
+ let Documentation = [Undocumented];
+}
+
+def CFReturnsNotRetained : InheritableAttr {
+ let Spellings = [GNU<"cf_returns_not_retained">];
+// let Subjects = SubjectList<[ObjCMethod, ObjCProperty, Function]>;
+ let Documentation = [Undocumented];
+}
+
+def CFConsumed : InheritableParamAttr {
+ let Spellings = [GNU<"cf_consumed">];
+ let Subjects = SubjectList<[ParmVar]>;
+ let Documentation = [Undocumented];
+}
+
+def Cleanup : InheritableAttr {
+ let Spellings = [GCC<"cleanup">];
+ let Args = [FunctionArgument<"FunctionDecl">];
+ let Subjects = SubjectList<[Var]>;
+ let Documentation = [Undocumented];
+}
+
+def Cold : InheritableAttr {
+ let Spellings = [GCC<"cold">];
+ let Subjects = SubjectList<[Function]>;
+ let Documentation = [Undocumented];
+}
+
+def Common : InheritableAttr {
+ let Spellings = [GCC<"common">];
+ let Subjects = SubjectList<[Var]>;
+ let Documentation = [Undocumented];
+}
+
+def Const : InheritableAttr {
+ let Spellings = [GCC<"const">, GCC<"__const">];
+ let Documentation = [Undocumented];
+}
+
+def Constructor : InheritableAttr {
+ let Spellings = [GCC<"constructor">];
+ let Args = [DefaultIntArgument<"Priority", 65535>];
+ let Subjects = SubjectList<[Function]>;
+ let Documentation = [Undocumented];
+}
+
+def CUDAConstant : InheritableAttr {
+ let Spellings = [GNU<"constant">];
+ let Subjects = SubjectList<[Var]>;
+ let LangOpts = [CUDA];
+ let Documentation = [Undocumented];
+}
+
+def CUDACudartBuiltin : IgnoredAttr {
+ let Spellings = [GNU<"cudart_builtin">];
+ let LangOpts = [CUDA];
+}
+
+def CUDADevice : InheritableAttr {
+ let Spellings = [GNU<"device">];
+ let Subjects = SubjectList<[Function, Var]>;
+ let LangOpts = [CUDA];
+ let Documentation = [Undocumented];
+}
+
+def CUDADeviceBuiltin : IgnoredAttr {
+ let Spellings = [GNU<"device_builtin">];
+ let LangOpts = [CUDA];
+}
+
+def CUDADeviceBuiltinSurfaceType : IgnoredAttr {
+ let Spellings = [GNU<"device_builtin_surface_type">];
+ let LangOpts = [CUDA];
+}
+
+def CUDADeviceBuiltinTextureType : IgnoredAttr {
+ let Spellings = [GNU<"device_builtin_texture_type">];
+ let LangOpts = [CUDA];
+}
+
+def CUDAGlobal : InheritableAttr {
+ let Spellings = [GNU<"global">];
+ let Subjects = SubjectList<[Function]>;
+ let LangOpts = [CUDA];
+ let Documentation = [Undocumented];
+}
+
+def CUDAHost : InheritableAttr {
+ let Spellings = [GNU<"host">];
+ let Subjects = SubjectList<[Function]>;
+ let LangOpts = [CUDA];
+ let Documentation = [Undocumented];
+}
+
+def CUDAInvalidTarget : InheritableAttr {
+ let Spellings = [];
+ let Subjects = SubjectList<[Function]>;
+ let LangOpts = [CUDA];
+ let Documentation = [Undocumented];
+}
+
+def CUDALaunchBounds : InheritableAttr {
+ let Spellings = [GNU<"launch_bounds">];
+ let Args = [ExprArgument<"MaxThreads">, ExprArgument<"MinBlocks", 1>];
+ let LangOpts = [CUDA];
+ let Subjects = SubjectList<[ObjCMethod, FunctionLike], WarnDiag,
+ "ExpectedFunctionOrMethod">;
+ // An AST node is created for this attribute, but is not used by other parts
+ // of the compiler. However, this node needs to exist in the AST because
+ // non-LLVM backends may be relying on the attribute's presence.
+ let Documentation = [Undocumented];
+}
+
+def CUDAShared : InheritableAttr {
+ let Spellings = [GNU<"shared">];
+ let Subjects = SubjectList<[Var]>;
+ let LangOpts = [CUDA];
+ let Documentation = [Undocumented];
+}
+
+def C11NoReturn : InheritableAttr {
+ let Spellings = [Keyword<"_Noreturn">];
+ let Subjects = SubjectList<[Function], ErrorDiag>;
+ let SemaHandler = 0;
+ let Documentation = [C11NoReturnDocs];
+}
+
+def CXX11NoReturn : InheritableAttr {
+ let Spellings = [CXX11<"","noreturn", 200809>];
+ let Subjects = SubjectList<[Function], ErrorDiag>;
+ let Documentation = [CXX11NoReturnDocs];
+}
+
+def OpenCLKernel : InheritableAttr {
+ let Spellings = [Keyword<"__kernel">, Keyword<"kernel">];
+ let Subjects = SubjectList<[Function], ErrorDiag>;
+ let Documentation = [Undocumented];
+}
+
+// This attribute is both a type attribute, and a declaration attribute (for
+// parameter variables).
+def OpenCLImageAccess : Attr {
+ let Spellings = [Keyword<"__read_only">, Keyword<"read_only">,
+ Keyword<"__write_only">, Keyword<"write_only">,
+ Keyword<"__read_write">, Keyword<"read_write">];
+ let Subjects = SubjectList<[ParmVar], ErrorDiag>;
+ let Accessors = [Accessor<"isReadOnly", [Keyword<"__read_only">,
+ Keyword<"read_only">]>,
+ Accessor<"isReadWrite", [Keyword<"__read_write">,
+ Keyword<"read_write">]>,
+ Accessor<"isWriteOnly", [Keyword<"__write_only">,
+ Keyword<"write_only">]>];
+ let Documentation = [Undocumented];
+}
+
+def OpenCLPrivateAddressSpace : TypeAttr {
+ let Spellings = [Keyword<"__private">, Keyword<"private">];
+ let Documentation = [OpenCLAddressSpacePrivateDocs];
+}
+
+def OpenCLGlobalAddressSpace : TypeAttr {
+ let Spellings = [Keyword<"__global">, Keyword<"global">];
+ let Documentation = [OpenCLAddressSpaceGlobalDocs];
+}
+
+def OpenCLLocalAddressSpace : TypeAttr {
+ let Spellings = [Keyword<"__local">, Keyword<"local">];
+ let Documentation = [OpenCLAddressSpaceLocalDocs];
+}
+
+def OpenCLConstantAddressSpace : TypeAttr {
+ let Spellings = [Keyword<"__constant">, Keyword<"constant">];
+ let Documentation = [OpenCLAddressSpaceConstantDocs];
+}
+
+def OpenCLGenericAddressSpace : TypeAttr {
+ let Spellings = [Keyword<"__generic">, Keyword<"generic">];
+ let Documentation = [OpenCLAddressSpaceGenericDocs];
+}
+
+def Deprecated : InheritableAttr {
+ let Spellings = [GCC<"deprecated">, Declspec<"deprecated">,
+ CXX11<"","deprecated", 201309>];
+ let Args = [StringArgument<"Message", 1>];
+ let Documentation = [Undocumented];
+}
+
+def Destructor : InheritableAttr {
+ let Spellings = [GCC<"destructor">];
+ let Args = [DefaultIntArgument<"Priority", 65535>];
+ let Subjects = SubjectList<[Function]>;
+ let Documentation = [Undocumented];
+}
+
+def EnableIf : InheritableAttr {
+ let Spellings = [GNU<"enable_if">];
+ let Subjects = SubjectList<[Function]>;
+ let Args = [ExprArgument<"Cond">, StringArgument<"Message">];
+ let TemplateDependent = 1;
+ let Documentation = [EnableIfDocs];
+}
+
+def ExtVectorType : Attr {
+ let Spellings = [GNU<"ext_vector_type">];
+ let Subjects = SubjectList<[TypedefName], ErrorDiag>;
+ let Args = [ExprArgument<"NumElements">];
+ let ASTNode = 0;
+ let Documentation = [Undocumented];
+}
+
+def FallThrough : Attr {
+ let Spellings = [CXX11<"clang", "fallthrough">];
+// let Subjects = [NullStmt];
+ let Documentation = [FallthroughDocs];
+}
+
+def FastCall : InheritableAttr {
+ let Spellings = [GCC<"fastcall">, Keyword<"__fastcall">,
+ Keyword<"_fastcall">];
+// let Subjects = [Function, ObjCMethod];
+ let Documentation = [FastCallDocs];
+}
+
+def Final : InheritableAttr {
+ let Spellings = [Keyword<"final">, Keyword<"sealed">];
+ let Accessors = [Accessor<"isSpelledAsSealed", [Keyword<"sealed">]>];
+ let SemaHandler = 0;
+ let Documentation = [Undocumented];
+}
+
+def MinSize : InheritableAttr {
+ let Spellings = [GNU<"minsize">];
+ let Subjects = SubjectList<[Function, ObjCMethod], ErrorDiag>;
+ let Documentation = [Undocumented];
+}
+
+def FlagEnum : InheritableAttr {
+ let Spellings = [GNU<"flag_enum">];
+ let Subjects = SubjectList<[Enum]>;
+ let Documentation = [FlagEnumDocs];
+ let LangOpts = [COnly];
+}
+
+def Flatten : InheritableAttr {
+ let Spellings = [GCC<"flatten">];
+ let Subjects = SubjectList<[Function], ErrorDiag>;
+ let Documentation = [FlattenDocs];
+}
+
+def Format : InheritableAttr {
+ let Spellings = [GCC<"format">];
+ let Args = [IdentifierArgument<"Type">, IntArgument<"FormatIdx">,
+ IntArgument<"FirstArg">];
+ let Subjects = SubjectList<[ObjCMethod, Block, HasFunctionProto], WarnDiag,
+ "ExpectedFunctionWithProtoType">;
+ let Documentation = [FormatDocs];
+}
+
+def FormatArg : InheritableAttr {
+ let Spellings = [GCC<"format_arg">];
+ let Args = [IntArgument<"FormatIdx">];
+ let Subjects = SubjectList<[ObjCMethod, HasFunctionProto], WarnDiag,
+ "ExpectedFunctionWithProtoType">;
+ let Documentation = [Undocumented];
+}
+
+def GNUInline : InheritableAttr {
+ let Spellings = [GCC<"gnu_inline">];
+ let Subjects = SubjectList<[Function]>;
+ let Documentation = [Undocumented];
+}
+
+def Hot : InheritableAttr {
+ let Spellings = [GCC<"hot">];
+ let Subjects = SubjectList<[Function]>;
+ // An AST node is created for this attribute, but not actually used beyond
+ // semantic checking for mutual exclusion with the Cold attribute.
+ let Documentation = [Undocumented];
+}
+
+def IBAction : InheritableAttr {
+ let Spellings = [GNU<"ibaction">];
+ let Subjects = SubjectList<[ObjCInstanceMethod], WarnDiag,
+ "ExpectedObjCInstanceMethod">;
+ // An AST node is created for this attribute, but is not used by other parts
+ // of the compiler. However, this node needs to exist in the AST because
+ // external tools rely on it.
+ let Documentation = [Undocumented];
+}
+
+def IBOutlet : InheritableAttr {
+ let Spellings = [GNU<"iboutlet">];
+// let Subjects = [ObjCIvar, ObjCProperty];
+ let Documentation = [Undocumented];
+}
+
+def IBOutletCollection : InheritableAttr {
+ let Spellings = [GNU<"iboutletcollection">];
+ let Args = [TypeArgument<"Interface", 1>];
+// let Subjects = [ObjCIvar, ObjCProperty];
+ let Documentation = [Undocumented];
+}
+
+def Restrict : InheritableAttr {
+ let Spellings = [Declspec<"restrict">, GCC<"malloc">];
+ let Subjects = SubjectList<[Function]>;
+ let Documentation = [Undocumented];
+}
+
+def MaxFieldAlignment : InheritableAttr {
+ // This attribute has no spellings as it is only ever created implicitly.
+ let Spellings = [];
+ let Args = [UnsignedArgument<"Alignment">];
+ let SemaHandler = 0;
+ let Documentation = [Undocumented];
+}
+
+def MayAlias : InheritableAttr {
+ // FIXME: this is a type attribute in GCC, but a declaration attribute here.
+ let Spellings = [GCC<"may_alias">];
+ let Documentation = [Undocumented];
+}
+
+def MSABI : InheritableAttr {
+ let Spellings = [GCC<"ms_abi">];
+// let Subjects = [Function, ObjCMethod];
+ let Documentation = [MSABIDocs];
+}
+
+def MSP430Interrupt : InheritableAttr, TargetSpecificAttr<TargetMSP430> {
+ // NOTE: If you add any additional spellings, ARMInterrupt's and
+ // MipsInterrupt's spellings must match.
+ let Spellings = [GNU<"interrupt">];
+ let Args = [UnsignedArgument<"Number">];
+ let ParseKind = "Interrupt";
+ let HasCustomParsing = 1;
+ let Documentation = [Undocumented];
+}
+
+def Mips16 : InheritableAttr, TargetSpecificAttr<TargetMips> {
+ let Spellings = [GCC<"mips16">];
+ let Subjects = SubjectList<[Function], ErrorDiag>;
+ let Documentation = [Undocumented];
+}
+
+def MipsInterrupt : InheritableAttr, TargetSpecificAttr<TargetMips> {
+ // NOTE: If you add any additional spellings, ARMInterrupt's and
+ // MSP430Interrupt's spellings must match.
+ let Spellings = [GNU<"interrupt">];
+ let Subjects = SubjectList<[Function]>;
+ let Args = [EnumArgument<"Interrupt", "InterruptType",
+ ["vector=sw0", "vector=sw1", "vector=hw0",
+ "vector=hw1", "vector=hw2", "vector=hw3",
+ "vector=hw4", "vector=hw5", "eic", ""],
+ ["sw0", "sw1", "hw0", "hw1", "hw2", "hw3",
+ "hw4", "hw5", "eic", "eic"]
+ >];
+ let ParseKind = "Interrupt";
+ let Documentation = [MipsInterruptDocs];
+}
+
+def Mode : Attr {
+ let Spellings = [GCC<"mode">];
+ let Args = [IdentifierArgument<"Mode">];
+ let Documentation = [Undocumented];
+}
+
+def Naked : InheritableAttr {
+ let Spellings = [GCC<"naked">, Declspec<"naked">];
+ let Subjects = SubjectList<[Function]>;
+ let Documentation = [Undocumented];
+}
+
+def NeonPolyVectorType : TypeAttr {
+ let Spellings = [GNU<"neon_polyvector_type">];
+ let Args = [IntArgument<"NumElements">];
+ let Documentation = [Undocumented];
+}
+
+def NeonVectorType : TypeAttr {
+ let Spellings = [GNU<"neon_vector_type">];
+ let Args = [IntArgument<"NumElements">];
+ let Documentation = [Undocumented];
+}
+
+def ReturnsTwice : InheritableAttr {
+ let Spellings = [GCC<"returns_twice">];
+ let Subjects = SubjectList<[Function]>;
+ let Documentation = [Undocumented];
+}
+
+def DisableTailCalls : InheritableAttr {
+ let Spellings = [GNU<"disable_tail_calls">,
+ CXX11<"clang", "disable_tail_calls">];
+ let Subjects = SubjectList<[Function, ObjCMethod]>;
+ let Documentation = [DisableTailCallsDocs];
+}
+
+def NoAlias : InheritableAttr {
+ let Spellings = [Declspec<"noalias">];
+ let Subjects = SubjectList<[Function]>;
+ let Documentation = [NoAliasDocs];
+}
+
+def NoCommon : InheritableAttr {
+ let Spellings = [GCC<"nocommon">];
+ let Subjects = SubjectList<[Var]>;
+ let Documentation = [Undocumented];
+}
+
+def NoDebug : InheritableAttr {
+ let Spellings = [GCC<"nodebug">];
+ let Documentation = [Undocumented];
+}
+
+def NoDuplicate : InheritableAttr {
+ let Spellings = [GNU<"noduplicate">, CXX11<"clang", "noduplicate">];
+ let Subjects = SubjectList<[Function]>;
+ let Documentation = [NoDuplicateDocs];
+}
+
+def NoInline : InheritableAttr {
+ let Spellings = [GCC<"noinline">, Declspec<"noinline">];
+ let Subjects = SubjectList<[Function]>;
+ let Documentation = [Undocumented];
+}
+
+def NoMips16 : InheritableAttr, TargetSpecificAttr<TargetMips> {
+ let Spellings = [GCC<"nomips16">];
+ let Subjects = SubjectList<[Function], ErrorDiag>;
+ let Documentation = [Undocumented];
+}
+
+// This is not a TargetSpecificAttr so that is silently accepted and
+// ignored on other targets as encouraged by the OpenCL spec.
+//
+// See OpenCL 1.2 6.11.5: "It is our intention that a particular
+// implementation of OpenCL be free to ignore all attributes and the
+// resulting executable binary will produce the same result."
+//
+// However, only AMD GPU targets will emit the corresponding IR
+// attribute.
+//
+// FIXME: This provides a sub-optimal error message if you attempt to
+// use this in CUDA, since CUDA does not use the same terminology.
+def AMDGPUNumVGPR : InheritableAttr {
+ let Spellings = [GNU<"amdgpu_num_vgpr">];
+ let Args = [UnsignedArgument<"NumVGPR">];
+ let Documentation = [AMDGPUNumVGPRDocs];
+
+// FIXME: This should be for OpenCLKernelFunction, but is not to
+// workaround needing to see kernel attribute before others to know if
+// this should be rejected on non-kernels.
+ let Subjects = SubjectList<[Function], ErrorDiag,
+ "ExpectedKernelFunction">;
+}
+
+def AMDGPUNumSGPR : InheritableAttr {
+ let Spellings = [GNU<"amdgpu_num_sgpr">];
+ let Args = [UnsignedArgument<"NumSGPR">];
+ let Documentation = [AMDGPUNumSGPRDocs];
+ let Subjects = SubjectList<[Function], ErrorDiag,
+ "ExpectedKernelFunction">;
+}
+
+def NoSplitStack : InheritableAttr {
+ let Spellings = [GCC<"no_split_stack">];
+ let Subjects = SubjectList<[Function], ErrorDiag>;
+ let Documentation = [NoSplitStackDocs];
+}
+
+def NonNull : InheritableAttr {
+ let Spellings = [GCC<"nonnull">];
+ let Subjects = SubjectList<[ObjCMethod, HasFunctionProto, ParmVar], WarnDiag,
+ "ExpectedFunctionMethodOrParameter">;
+ let Args = [VariadicUnsignedArgument<"Args">];
+ let AdditionalMembers =
+[{bool isNonNull(unsigned idx) const {
+ if (!args_size())
+ return true;
+ for (const auto &V : args())
+ if (V == idx)
+ return true;
+ return false;
+ } }];
+ // FIXME: We should merge duplicates into a single nonnull attribute.
+ let DuplicatesAllowedWhileMerging = 1;
+ let Documentation = [NonNullDocs];
+}
+
+def ReturnsNonNull : InheritableAttr {
+ let Spellings = [GCC<"returns_nonnull">];
+ let Subjects = SubjectList<[ObjCMethod, Function], WarnDiag,
+ "ExpectedFunctionOrMethod">;
+ let Documentation = [ReturnsNonNullDocs];
+}
+
+// pass_object_size(N) indicates that the parameter should have
+// __builtin_object_size with Type=N evaluated on the parameter at the callsite.
+def PassObjectSize : InheritableParamAttr {
+ let Spellings = [GNU<"pass_object_size">];
+ let Args = [IntArgument<"Type">];
+ let Subjects = SubjectList<[ParmVar]>;
+ let Documentation = [PassObjectSizeDocs];
+}
+
+// Nullability type attributes.
+def TypeNonNull : TypeAttr {
+ let Spellings = [Keyword<"_Nonnull">];
+ let Documentation = [TypeNonNullDocs];
+}
+
+def TypeNullable : TypeAttr {
+ let Spellings = [Keyword<"_Nullable">];
+ let Documentation = [TypeNullableDocs];
+}
+
+def TypeNullUnspecified : TypeAttr {
+ let Spellings = [Keyword<"_Null_unspecified">];
+ let Documentation = [TypeNullUnspecifiedDocs];
+}
+
+def ObjCKindOf : TypeAttr {
+ let Spellings = [Keyword<"__kindof">];
+ let Documentation = [Undocumented];
+}
+
+def AssumeAligned : InheritableAttr {
+ let Spellings = [GCC<"assume_aligned">];
+ let Subjects = SubjectList<[ObjCMethod, Function]>;
+ let Args = [ExprArgument<"Alignment">, ExprArgument<"Offset", 1>];
+ let Documentation = [AssumeAlignedDocs];
+}
+
+def NoReturn : InheritableAttr {
+ let Spellings = [GCC<"noreturn">, Declspec<"noreturn">];
+ // FIXME: Does GCC allow this on the function instead?
+ let Documentation = [Undocumented];
+}
+
+def NoInstrumentFunction : InheritableAttr {
+ let Spellings = [GCC<"no_instrument_function">];
+ let Subjects = SubjectList<[Function]>;
+ let Documentation = [Undocumented];
+}
+
+def NotTailCalled : InheritableAttr {
+ let Spellings = [GNU<"not_tail_called">, CXX11<"clang", "not_tail_called">];
+ let Subjects = SubjectList<[Function]>;
+ let Documentation = [NotTailCalledDocs];
+}
+
+def NoThrow : InheritableAttr {
+ let Spellings = [GCC<"nothrow">, Declspec<"nothrow">];
+ let Documentation = [Undocumented];
+}
+
+def NvWeak : IgnoredAttr {
+ let Spellings = [GNU<"nv_weak">];
+ let LangOpts = [CUDA];
+}
+
+def ObjCBridge : InheritableAttr {
+ let Spellings = [GNU<"objc_bridge">];
+ let Subjects = SubjectList<[Record, TypedefName], ErrorDiag,
+ "ExpectedStructOrUnionOrTypedef">;
+ let Args = [IdentifierArgument<"BridgedType">];
+ let Documentation = [Undocumented];
+}
+
+def ObjCBridgeMutable : InheritableAttr {
+ let Spellings = [GNU<"objc_bridge_mutable">];
+ let Subjects = SubjectList<[Record], ErrorDiag>;
+ let Args = [IdentifierArgument<"BridgedType">];
+ let Documentation = [Undocumented];
+}
+
+def ObjCBridgeRelated : InheritableAttr {
+ let Spellings = [GNU<"objc_bridge_related">];
+ let Subjects = SubjectList<[Record], ErrorDiag>;
+ let Args = [IdentifierArgument<"RelatedClass">,
+ IdentifierArgument<"ClassMethod", 1>,
+ IdentifierArgument<"InstanceMethod", 1>];
+ let HasCustomParsing = 1;
+ let Documentation = [Undocumented];
+}
+
+def NSReturnsRetained : InheritableAttr {
+ let Spellings = [GNU<"ns_returns_retained">];
+// let Subjects = SubjectList<[ObjCMethod, ObjCProperty, Function]>;
+ let Documentation = [Undocumented];
+}
+
+def NSReturnsNotRetained : InheritableAttr {
+ let Spellings = [GNU<"ns_returns_not_retained">];
+// let Subjects = SubjectList<[ObjCMethod, ObjCProperty, Function]>;
+ let Documentation = [Undocumented];
+}
+
+def NSReturnsAutoreleased : InheritableAttr {
+ let Spellings = [GNU<"ns_returns_autoreleased">];
+// let Subjects = SubjectList<[ObjCMethod, ObjCProperty, Function]>;
+ let Documentation = [Undocumented];
+}
+
+def NSConsumesSelf : InheritableAttr {
+ let Spellings = [GNU<"ns_consumes_self">];
+ let Subjects = SubjectList<[ObjCMethod]>;
+ let Documentation = [Undocumented];
+}
+
+def NSConsumed : InheritableParamAttr {
+ let Spellings = [GNU<"ns_consumed">];
+ let Subjects = SubjectList<[ParmVar]>;
+ let Documentation = [Undocumented];
+}
+
+def ObjCException : InheritableAttr {
+ let Spellings = [GNU<"objc_exception">];
+ let Subjects = SubjectList<[ObjCInterface], ErrorDiag>;
+ let Documentation = [Undocumented];
+}
+
+def ObjCMethodFamily : InheritableAttr {
+ let Spellings = [GNU<"objc_method_family">];
+ let Subjects = SubjectList<[ObjCMethod], ErrorDiag>;
+ let Args = [EnumArgument<"Family", "FamilyKind",
+ ["none", "alloc", "copy", "init", "mutableCopy", "new"],
+ ["OMF_None", "OMF_alloc", "OMF_copy", "OMF_init",
+ "OMF_mutableCopy", "OMF_new"]>];
+ let Documentation = [ObjCMethodFamilyDocs];
+}
+
+def ObjCNSObject : InheritableAttr {
+ let Spellings = [GNU<"NSObject">];
+ let Documentation = [Undocumented];
+}
+
+def ObjCIndependentClass : InheritableAttr {
+ let Spellings = [GNU<"objc_independent_class">];
+ let Documentation = [Undocumented];
+}
+
+def ObjCPreciseLifetime : InheritableAttr {
+ let Spellings = [GNU<"objc_precise_lifetime">];
+ let Subjects = SubjectList<[Var], ErrorDiag>;
+ let Documentation = [Undocumented];
+}
+
+def ObjCReturnsInnerPointer : InheritableAttr {
+ let Spellings = [GNU<"objc_returns_inner_pointer">];
+ let Subjects = SubjectList<[ObjCMethod, ObjCProperty], ErrorDiag>;
+ let Documentation = [Undocumented];
+}
+
+def ObjCRequiresSuper : InheritableAttr {
+ let Spellings = [GNU<"objc_requires_super">];
+ let Subjects = SubjectList<[ObjCMethod], ErrorDiag>;
+ let Documentation = [ObjCRequiresSuperDocs];
+}
+
+def ObjCRootClass : InheritableAttr {
+ let Spellings = [GNU<"objc_root_class">];
+ let Subjects = SubjectList<[ObjCInterface], ErrorDiag>;
+ let Documentation = [Undocumented];
+}
+
+def ObjCExplicitProtocolImpl : InheritableAttr {
+ let Spellings = [GNU<"objc_protocol_requires_explicit_implementation">];
+ let Subjects = SubjectList<[ObjCProtocol], ErrorDiag>;
+ let Documentation = [Undocumented];
+}
+
+def ObjCDesignatedInitializer : Attr {
+ let Spellings = [GNU<"objc_designated_initializer">];
+ let Subjects = SubjectList<[ObjCInterfaceDeclInitMethod], ErrorDiag,
+ "ExpectedObjCInterfaceDeclInitMethod">;
+ let Documentation = [Undocumented];
+}
+
+def ObjCRuntimeName : Attr {
+ let Spellings = [GNU<"objc_runtime_name">];
+ let Subjects = SubjectList<[ObjCInterface, ObjCProtocol], ErrorDiag>;
+ let Args = [StringArgument<"MetadataName">];
+ let Documentation = [ObjCRuntimeNameDocs];
+}
+
+def ObjCBoxable : Attr {
+ let Spellings = [GNU<"objc_boxable">];
+ let Subjects = SubjectList<[Record], ErrorDiag, "ExpectedStructOrUnion">;
+ let Documentation = [ObjCBoxableDocs];
+}
+
+def OptimizeNone : InheritableAttr {
+ let Spellings = [GNU<"optnone">, CXX11<"clang", "optnone">];
+ let Subjects = SubjectList<[Function, ObjCMethod]>;
+ let Documentation = [OptnoneDocs];
+}
+
+def Overloadable : Attr {
+ let Spellings = [GNU<"overloadable">];
+ let Subjects = SubjectList<[Function], ErrorDiag>;
+ let Documentation = [OverloadableDocs];
+}
+
+def Override : InheritableAttr {
+ let Spellings = [Keyword<"override">];
+ let SemaHandler = 0;
+ let Documentation = [Undocumented];
+}
+
+def Ownership : InheritableAttr {
+ let Spellings = [GNU<"ownership_holds">, GNU<"ownership_returns">,
+ GNU<"ownership_takes">];
+ let Accessors = [Accessor<"isHolds", [GNU<"ownership_holds">]>,
+ Accessor<"isReturns", [GNU<"ownership_returns">]>,
+ Accessor<"isTakes", [GNU<"ownership_takes">]>];
+ let AdditionalMembers = [{
+ enum OwnershipKind { Holds, Returns, Takes };
+ OwnershipKind getOwnKind() const {
+ return isHolds() ? Holds :
+ isTakes() ? Takes :
+ Returns;
+ }
+ }];
+ let Args = [IdentifierArgument<"Module">, VariadicUnsignedArgument<"Args">];
+ let Subjects = SubjectList<[HasFunctionProto], WarnDiag,
+ "ExpectedFunctionWithProtoType">;
+ let Documentation = [Undocumented];
+}
+
+def Packed : InheritableAttr {
+ let Spellings = [GCC<"packed">];
+// let Subjects = [Tag, Field];
+ let Documentation = [Undocumented];
+}
+
+def IntelOclBicc : InheritableAttr {
+ let Spellings = [GNU<"intel_ocl_bicc">];
+// let Subjects = [Function, ObjCMethod];
+ let Documentation = [Undocumented];
+}
+
+def Pcs : InheritableAttr {
+ let Spellings = [GCC<"pcs">];
+ let Args = [EnumArgument<"PCS", "PCSType",
+ ["aapcs", "aapcs-vfp"],
+ ["AAPCS", "AAPCS_VFP"]>];
+// let Subjects = [Function, ObjCMethod];
+ let Documentation = [PcsDocs];
+}
+
+def Pure : InheritableAttr {
+ let Spellings = [GCC<"pure">];
+ let Documentation = [Undocumented];
+}
+
+def Regparm : TypeAttr {
+ let Spellings = [GCC<"regparm">];
+ let Args = [UnsignedArgument<"NumParams">];
+ let Documentation = [RegparmDocs];
+}
+
+def ReqdWorkGroupSize : InheritableAttr {
+ let Spellings = [GNU<"reqd_work_group_size">];
+ let Args = [UnsignedArgument<"XDim">, UnsignedArgument<"YDim">,
+ UnsignedArgument<"ZDim">];
+ let Subjects = SubjectList<[Function], ErrorDiag>;
+ let Documentation = [Undocumented];
+}
+
+def WorkGroupSizeHint : InheritableAttr {
+ let Spellings = [GNU<"work_group_size_hint">];
+ let Args = [UnsignedArgument<"XDim">,
+ UnsignedArgument<"YDim">,
+ UnsignedArgument<"ZDim">];
+ let Subjects = SubjectList<[Function], ErrorDiag>;
+ let Documentation = [Undocumented];
+}
+
+def InitPriority : InheritableAttr {
+ let Spellings = [GNU<"init_priority">];
+ let Args = [UnsignedArgument<"Priority">];
+ let Subjects = SubjectList<[Var], ErrorDiag>;
+ let Documentation = [Undocumented];
+}
+
+def Section : InheritableAttr {
+ let Spellings = [GCC<"section">, Declspec<"allocate">];
+ let Args = [StringArgument<"Name">];
+ let Subjects = SubjectList<[Function, GlobalVar,
+ ObjCMethod, ObjCProperty], ErrorDiag,
+ "ExpectedFunctionGlobalVarMethodOrProperty">;
+ let Documentation = [SectionDocs];
+}
+
+def Sentinel : InheritableAttr {
+ let Spellings = [GCC<"sentinel">];
+ let Args = [DefaultIntArgument<"Sentinel", 0>,
+ DefaultIntArgument<"NullPos", 0>];
+// let Subjects = SubjectList<[Function, ObjCMethod, Block, Var]>;
+ let Documentation = [Undocumented];
+}
+
+def StdCall : InheritableAttr {
+ let Spellings = [GCC<"stdcall">, Keyword<"__stdcall">, Keyword<"_stdcall">];
+// let Subjects = [Function, ObjCMethod];
+ let Documentation = [StdCallDocs];
+}
+
+def SysVABI : InheritableAttr {
+ let Spellings = [GCC<"sysv_abi">];
+// let Subjects = [Function, ObjCMethod];
+ let Documentation = [Undocumented];
+}
+
+def ThisCall : InheritableAttr {
+ let Spellings = [GCC<"thiscall">, Keyword<"__thiscall">,
+ Keyword<"_thiscall">];
+// let Subjects = [Function, ObjCMethod];
+ let Documentation = [ThisCallDocs];
+}
+
+def VectorCall : InheritableAttr {
+ let Spellings = [GNU<"vectorcall">, Keyword<"__vectorcall">,
+ Keyword<"_vectorcall">];
+// let Subjects = [Function, ObjCMethod];
+ let Documentation = [VectorCallDocs];
+}
+
+def Pascal : InheritableAttr {
+ let Spellings = [GNU<"pascal">, Keyword<"__pascal">, Keyword<"_pascal">];
+// let Subjects = [Function, ObjCMethod];
+ let Documentation = [Undocumented];
+}
+
+def Target : InheritableAttr {
+ let Spellings = [GCC<"target">];
+ let Args = [StringArgument<"featuresStr">];
+ let Subjects = SubjectList<[Function], ErrorDiag>;
+ let Documentation = [TargetDocs];
+ let AdditionalMembers = [{
+ typedef std::pair<std::vector<std::string>, StringRef> ParsedTargetAttr;
+ ParsedTargetAttr parse() const {
+ ParsedTargetAttr Ret;
+ SmallVector<StringRef, 1> AttrFeatures;
+ getFeaturesStr().split(AttrFeatures, ",");
+
+ // Grab the various features and prepend a "+" to turn on the feature to
+ // the backend and add them to our existing set of features.
+ for (auto &Feature : AttrFeatures) {
+ // Go ahead and trim whitespace rather than either erroring or
+ // accepting it weirdly.
+ Feature = Feature.trim();
+
+ // We don't support cpu tuning this way currently.
+ // TODO: Support the fpmath option. It will require checking
+ // overall feature validity for the function with the rest of the
+ // attributes on the function.
+ if (Feature.startswith("fpmath=") || Feature.startswith("tune="))
+ continue;
+
+ // While we're here iterating check for a different target cpu.
+ if (Feature.startswith("arch="))
+ Ret.second = Feature.split("=").second.trim();
+ else if (Feature.startswith("no-"))
+ Ret.first.push_back("-" + Feature.split("-").second.str());
+ else
+ Ret.first.push_back("+" + Feature.str());
+ }
+ return Ret;
+ }
+ }];
+}
+
+def TransparentUnion : InheritableAttr {
+ let Spellings = [GCC<"transparent_union">];
+// let Subjects = SubjectList<[Record, TypedefName]>;
+ let Documentation = [Undocumented];
+}
+
+def Unavailable : InheritableAttr {
+ let Spellings = [GNU<"unavailable">];
+ let Args = [StringArgument<"Message", 1>,
+ EnumArgument<"ImplicitReason", "ImplicitReason",
+ ["", "", "", ""],
+ ["IR_None",
+ "IR_ARCForbiddenType",
+ "IR_ForbiddenWeak",
+ "IR_ARCForbiddenConversion",
+ "IR_ARCInitReturnsUnrelated",
+ "IR_ARCFieldWithOwnership"], 1, /*fake*/ 1>];
+ let Documentation = [Undocumented];
+}
+
+def ArcWeakrefUnavailable : InheritableAttr {
+ let Spellings = [GNU<"objc_arc_weak_reference_unavailable">];
+ let Subjects = SubjectList<[ObjCInterface], ErrorDiag>;
+ let Documentation = [Undocumented];
+}
+
+def ObjCGC : TypeAttr {
+ let Spellings = [GNU<"objc_gc">];
+ let Args = [IdentifierArgument<"Kind">];
+ let Documentation = [Undocumented];
+}
+
+def ObjCOwnership : InheritableAttr {
+ let Spellings = [GNU<"objc_ownership">];
+ let Args = [IdentifierArgument<"Kind">];
+ let ASTNode = 0;
+ let Documentation = [Undocumented];
+}
+
+def ObjCRequiresPropertyDefs : InheritableAttr {
+ let Spellings = [GNU<"objc_requires_property_definitions">];
+ let Subjects = SubjectList<[ObjCInterface], ErrorDiag>;
+ let Documentation = [Undocumented];
+}
+
+def Unused : InheritableAttr {
+ let Spellings = [GCC<"unused">];
+ let Subjects = SubjectList<[Var, ObjCIvar, Type, Label, Field, ObjCMethod,
+ FunctionLike], WarnDiag,
+ "ExpectedVariableFunctionOrLabel">;
+ let Documentation = [Undocumented];
+}
+
+def Used : InheritableAttr {
+ let Spellings = [GCC<"used">];
+ let Documentation = [Undocumented];
+}
+
+def Uuid : InheritableAttr {
+ let Spellings = [Declspec<"uuid">];
+ let Args = [StringArgument<"Guid">];
+// let Subjects = SubjectList<[CXXRecord]>;
+ let LangOpts = [MicrosoftExt, Borland];
+ let Documentation = [Undocumented];
+}
+
+def VectorSize : TypeAttr {
+ let Spellings = [GCC<"vector_size">];
+ let Args = [ExprArgument<"NumBytes">];
+ let Documentation = [Undocumented];
+}
+
+def VecTypeHint : InheritableAttr {
+ let Spellings = [GNU<"vec_type_hint">];
+ let Args = [TypeArgument<"TypeHint">];
+ let Subjects = SubjectList<[Function], ErrorDiag>;
+ let Documentation = [Undocumented];
+}
+
+def Visibility : InheritableAttr {
+ let Clone = 0;
+ let Spellings = [GCC<"visibility">];
+ let Args = [EnumArgument<"Visibility", "VisibilityType",
+ ["default", "hidden", "internal", "protected"],
+ ["Default", "Hidden", "Hidden", "Protected"]>];
+ let Documentation = [Undocumented];
+}
+
+def TypeVisibility : InheritableAttr {
+ let Clone = 0;
+ let Spellings = [GNU<"type_visibility">, CXX11<"clang", "type_visibility">];
+ let Args = [EnumArgument<"Visibility", "VisibilityType",
+ ["default", "hidden", "internal", "protected"],
+ ["Default", "Hidden", "Hidden", "Protected"]>];
+// let Subjects = [Tag, ObjCInterface, Namespace];
+ let Documentation = [Undocumented];
+}
+
+def VecReturn : InheritableAttr {
+ let Spellings = [GNU<"vecreturn">];
+ let Subjects = SubjectList<[CXXRecord], ErrorDiag>;
+ let Documentation = [Undocumented];
+}
+
+def WarnUnused : InheritableAttr {
+ let Spellings = [GNU<"warn_unused">];
+ let Subjects = SubjectList<[Record]>;
+ let Documentation = [Undocumented];
+}
+
+def WarnUnusedResult : InheritableAttr {
+ let Spellings = [GCC<"warn_unused_result">,
+ CXX11<"clang", "warn_unused_result">];
+ let Subjects = SubjectList<[ObjCMethod, CXXRecord, FunctionLike], WarnDiag,
+ "ExpectedFunctionMethodOrClass">;
+ let Documentation = [Undocumented];
+}
+
+def Weak : InheritableAttr {
+ let Spellings = [GCC<"weak">];
+ let Subjects = SubjectList<[Var, Function, CXXRecord]>;
+ let Documentation = [Undocumented];
+}
+
+def WeakImport : InheritableAttr {
+ let Spellings = [GNU<"weak_import">];
+ let Documentation = [Undocumented];
+}
+
+def WeakRef : InheritableAttr {
+ let Spellings = [GCC<"weakref">];
+ // A WeakRef that has an argument is treated as being an AliasAttr
+ let Args = [StringArgument<"Aliasee", 1>];
+ let Subjects = SubjectList<[Var, Function], ErrorDiag>;
+ let Documentation = [Undocumented];
+}
+
+def X86ForceAlignArgPointer : InheritableAttr, TargetSpecificAttr<TargetX86> {
+ let Spellings = [GNU<"force_align_arg_pointer">];
+ // Technically, this appertains to a FunctionDecl, but the target-specific
+ // code silently allows anything function-like (such as typedefs or function
+ // pointers), but does not apply the attribute to them.
+ let Documentation = [Undocumented];
+}
+
+def NoSanitize : InheritableAttr {
+ let Spellings = [GNU<"no_sanitize">, CXX11<"clang", "no_sanitize">];
+ let Args = [VariadicStringArgument<"Sanitizers">];
+ let Subjects = SubjectList<[Function, ObjCMethod], ErrorDiag>;
+ let Documentation = [NoSanitizeDocs];
+ let AdditionalMembers = [{
+ SanitizerMask getMask() const {
+ SanitizerMask Mask = 0;
+ for (auto SanitizerName : sanitizers()) {
+ SanitizerMask ParsedMask =
+ parseSanitizerValue(SanitizerName, /*AllowGroups=*/true);
+ Mask |= expandSanitizerGroups(ParsedMask);
+ }
+ return Mask;
+ }
+ }];
+}
+
+// Attributes to disable a specific sanitizer. No new sanitizers should be added
+// to this list; the no_sanitize attribute should be extended instead.
+def NoSanitizeSpecific : InheritableAttr {
+ let Spellings = [GCC<"no_address_safety_analysis">,
+ GCC<"no_sanitize_address">,
+ GCC<"no_sanitize_thread">,
+ GNU<"no_sanitize_memory">];
+ let Subjects = SubjectList<[Function], ErrorDiag>;
+ let Documentation = [NoSanitizeAddressDocs, NoSanitizeThreadDocs,
+ NoSanitizeMemoryDocs];
+ let ASTNode = 0;
+}
+
+// C/C++ Thread safety attributes (e.g. for deadlock, data race checking)
+
+def GuardedVar : InheritableAttr {
+ let Spellings = [GNU<"guarded_var">];
+ let Subjects = SubjectList<[Field, SharedVar], WarnDiag,
+ "ExpectedFieldOrGlobalVar">;
+ let Documentation = [Undocumented];
+}
+
+def PtGuardedVar : InheritableAttr {
+ let Spellings = [GNU<"pt_guarded_var">];
+ let Subjects = SubjectList<[Field, SharedVar], WarnDiag,
+ "ExpectedFieldOrGlobalVar">;
+ let Documentation = [Undocumented];
+}
+
+def Lockable : InheritableAttr {
+ let Spellings = [GNU<"lockable">];
+ let Subjects = SubjectList<[Record]>;
+ let Documentation = [Undocumented];
+ let ASTNode = 0; // Replaced by Capability
+}
+
+def ScopedLockable : InheritableAttr {
+ let Spellings = [GNU<"scoped_lockable">];
+ let Subjects = SubjectList<[Record]>;
+ let Documentation = [Undocumented];
+}
+
+def Capability : InheritableAttr {
+ let Spellings = [GNU<"capability">, CXX11<"clang", "capability">,
+ GNU<"shared_capability">,
+ CXX11<"clang", "shared_capability">];
+ let Subjects = SubjectList<[Record, TypedefName], ErrorDiag,
+ "ExpectedStructOrUnionOrTypedef">;
+ let Args = [StringArgument<"Name">];
+ let Accessors = [Accessor<"isShared",
+ [GNU<"shared_capability">,
+ CXX11<"clang","shared_capability">]>];
+ let Documentation = [Undocumented];
+ let AdditionalMembers = [{
+ bool isMutex() const { return getName().equals_lower("mutex"); }
+ bool isRole() const { return getName().equals_lower("role"); }
+ }];
+}
+
+def AssertCapability : InheritableAttr {
+ let Spellings = [GNU<"assert_capability">,
+ CXX11<"clang", "assert_capability">,
+ GNU<"assert_shared_capability">,
+ CXX11<"clang", "assert_shared_capability">];
+ let Subjects = SubjectList<[Function]>;
+ let LateParsed = 1;
+ let TemplateDependent = 1;
+ let ParseArgumentsAsUnevaluated = 1;
+ let DuplicatesAllowedWhileMerging = 1;
+ let Args = [ExprArgument<"Expr">];
+ let Accessors = [Accessor<"isShared",
+ [GNU<"assert_shared_capability">,
+ CXX11<"clang", "assert_shared_capability">]>];
+ let Documentation = [AssertCapabilityDocs];
+}
+
+def AcquireCapability : InheritableAttr {
+ let Spellings = [GNU<"acquire_capability">,
+ CXX11<"clang", "acquire_capability">,
+ GNU<"acquire_shared_capability">,
+ CXX11<"clang", "acquire_shared_capability">,
+ GNU<"exclusive_lock_function">,
+ GNU<"shared_lock_function">];
+ let Subjects = SubjectList<[Function]>;
+ let LateParsed = 1;
+ let TemplateDependent = 1;
+ let ParseArgumentsAsUnevaluated = 1;
+ let DuplicatesAllowedWhileMerging = 1;
+ let Args = [VariadicExprArgument<"Args">];
+ let Accessors = [Accessor<"isShared",
+ [GNU<"acquire_shared_capability">,
+ CXX11<"clang", "acquire_shared_capability">,
+ GNU<"shared_lock_function">]>];
+ let Documentation = [AcquireCapabilityDocs];
+}
+
+def TryAcquireCapability : InheritableAttr {
+ let Spellings = [GNU<"try_acquire_capability">,
+ CXX11<"clang", "try_acquire_capability">,
+ GNU<"try_acquire_shared_capability">,
+ CXX11<"clang", "try_acquire_shared_capability">];
+ let Subjects = SubjectList<[Function],
+ ErrorDiag>;
+ let LateParsed = 1;
+ let TemplateDependent = 1;
+ let ParseArgumentsAsUnevaluated = 1;
+ let DuplicatesAllowedWhileMerging = 1;
+ let Args = [ExprArgument<"SuccessValue">, VariadicExprArgument<"Args">];
+ let Accessors = [Accessor<"isShared",
+ [GNU<"try_acquire_shared_capability">,
+ CXX11<"clang", "try_acquire_shared_capability">]>];
+ let Documentation = [TryAcquireCapabilityDocs];
+}
+
+def ReleaseCapability : InheritableAttr {
+ let Spellings = [GNU<"release_capability">,
+ CXX11<"clang", "release_capability">,
+ GNU<"release_shared_capability">,
+ CXX11<"clang", "release_shared_capability">,
+ GNU<"release_generic_capability">,
+ CXX11<"clang", "release_generic_capability">,
+ GNU<"unlock_function">];
+ let Subjects = SubjectList<[Function]>;
+ let LateParsed = 1;
+ let TemplateDependent = 1;
+ let ParseArgumentsAsUnevaluated = 1;
+ let DuplicatesAllowedWhileMerging = 1;
+ let Args = [VariadicExprArgument<"Args">];
+ let Accessors = [Accessor<"isShared",
+ [GNU<"release_shared_capability">,
+ CXX11<"clang", "release_shared_capability">]>,
+ Accessor<"isGeneric",
+ [GNU<"release_generic_capability">,
+ CXX11<"clang", "release_generic_capability">,
+ GNU<"unlock_function">]>];
+ let Documentation = [ReleaseCapabilityDocs];
+}
+
+def RequiresCapability : InheritableAttr {
+ let Spellings = [GNU<"requires_capability">,
+ CXX11<"clang", "requires_capability">,
+ GNU<"exclusive_locks_required">,
+ GNU<"requires_shared_capability">,
+ CXX11<"clang", "requires_shared_capability">,
+ GNU<"shared_locks_required">];
+ let Args = [VariadicExprArgument<"Args">];
+ let LateParsed = 1;
+ let TemplateDependent = 1;
+ let ParseArgumentsAsUnevaluated = 1;
+ let DuplicatesAllowedWhileMerging = 1;
+ let Subjects = SubjectList<[Function]>;
+ let Accessors = [Accessor<"isShared", [GNU<"requires_shared_capability">,
+ GNU<"shared_locks_required">,
+ CXX11<"clang","requires_shared_capability">]>];
+ let Documentation = [Undocumented];
+}
+
+def NoThreadSafetyAnalysis : InheritableAttr {
+ let Spellings = [GNU<"no_thread_safety_analysis">];
+ let Subjects = SubjectList<[Function]>;
+ let Documentation = [Undocumented];
+}
+
+def GuardedBy : InheritableAttr {
+ let Spellings = [GNU<"guarded_by">];
+ let Args = [ExprArgument<"Arg">];
+ let LateParsed = 1;
+ let TemplateDependent = 1;
+ let ParseArgumentsAsUnevaluated = 1;
+ let DuplicatesAllowedWhileMerging = 1;
+ let Subjects = SubjectList<[Field, SharedVar], WarnDiag,
+ "ExpectedFieldOrGlobalVar">;
+ let Documentation = [Undocumented];
+}
+
+def PtGuardedBy : InheritableAttr {
+ let Spellings = [GNU<"pt_guarded_by">];
+ let Args = [ExprArgument<"Arg">];
+ let LateParsed = 1;
+ let TemplateDependent = 1;
+ let ParseArgumentsAsUnevaluated = 1;
+ let DuplicatesAllowedWhileMerging = 1;
+ let Subjects = SubjectList<[Field, SharedVar], WarnDiag,
+ "ExpectedFieldOrGlobalVar">;
+ let Documentation = [Undocumented];
+}
+
+def AcquiredAfter : InheritableAttr {
+ let Spellings = [GNU<"acquired_after">];
+ let Args = [VariadicExprArgument<"Args">];
+ let LateParsed = 1;
+ let TemplateDependent = 1;
+ let ParseArgumentsAsUnevaluated = 1;
+ let DuplicatesAllowedWhileMerging = 1;
+ let Subjects = SubjectList<[Field, SharedVar], WarnDiag,
+ "ExpectedFieldOrGlobalVar">;
+ let Documentation = [Undocumented];
+}
+
+def AcquiredBefore : InheritableAttr {
+ let Spellings = [GNU<"acquired_before">];
+ let Args = [VariadicExprArgument<"Args">];
+ let LateParsed = 1;
+ let TemplateDependent = 1;
+ let ParseArgumentsAsUnevaluated = 1;
+ let DuplicatesAllowedWhileMerging = 1;
+ let Subjects = SubjectList<[Field, SharedVar], WarnDiag,
+ "ExpectedFieldOrGlobalVar">;
+ let Documentation = [Undocumented];
+}
+
+def AssertExclusiveLock : InheritableAttr {
+ let Spellings = [GNU<"assert_exclusive_lock">];
+ let Args = [VariadicExprArgument<"Args">];
+ let LateParsed = 1;
+ let TemplateDependent = 1;
+ let ParseArgumentsAsUnevaluated = 1;
+ let DuplicatesAllowedWhileMerging = 1;
+ let Subjects = SubjectList<[Function]>;
+ let Documentation = [Undocumented];
+}
+
+def AssertSharedLock : InheritableAttr {
+ let Spellings = [GNU<"assert_shared_lock">];
+ let Args = [VariadicExprArgument<"Args">];
+ let LateParsed = 1;
+ let TemplateDependent = 1;
+ let ParseArgumentsAsUnevaluated = 1;
+ let DuplicatesAllowedWhileMerging = 1;
+ let Subjects = SubjectList<[Function]>;
+ let Documentation = [Undocumented];
+}
+
+// The first argument is an integer or boolean value specifying the return value
+// of a successful lock acquisition.
+def ExclusiveTrylockFunction : InheritableAttr {
+ let Spellings = [GNU<"exclusive_trylock_function">];
+ let Args = [ExprArgument<"SuccessValue">, VariadicExprArgument<"Args">];
+ let LateParsed = 1;
+ let TemplateDependent = 1;
+ let ParseArgumentsAsUnevaluated = 1;
+ let DuplicatesAllowedWhileMerging = 1;
+ let Subjects = SubjectList<[Function]>;
+ let Documentation = [Undocumented];
+}
+
+// The first argument is an integer or boolean value specifying the return value
+// of a successful lock acquisition.
+def SharedTrylockFunction : InheritableAttr {
+ let Spellings = [GNU<"shared_trylock_function">];
+ let Args = [ExprArgument<"SuccessValue">, VariadicExprArgument<"Args">];
+ let LateParsed = 1;
+ let TemplateDependent = 1;
+ let ParseArgumentsAsUnevaluated = 1;
+ let DuplicatesAllowedWhileMerging = 1;
+ let Subjects = SubjectList<[Function]>;
+ let Documentation = [Undocumented];
+}
+
+def LockReturned : InheritableAttr {
+ let Spellings = [GNU<"lock_returned">];
+ let Args = [ExprArgument<"Arg">];
+ let LateParsed = 1;
+ let TemplateDependent = 1;
+ let ParseArgumentsAsUnevaluated = 1;
+ let Subjects = SubjectList<[Function]>;
+ let Documentation = [Undocumented];
+}
+
+def LocksExcluded : InheritableAttr {
+ let Spellings = [GNU<"locks_excluded">];
+ let Args = [VariadicExprArgument<"Args">];
+ let LateParsed = 1;
+ let TemplateDependent = 1;
+ let ParseArgumentsAsUnevaluated = 1;
+ let DuplicatesAllowedWhileMerging = 1;
+ let Subjects = SubjectList<[Function]>;
+ let Documentation = [Undocumented];
+}
+
+// C/C++ consumed attributes.
+
+def Consumable : InheritableAttr {
+ let Spellings = [GNU<"consumable">];
+ let Subjects = SubjectList<[CXXRecord]>;
+ let Args = [EnumArgument<"DefaultState", "ConsumedState",
+ ["unknown", "consumed", "unconsumed"],
+ ["Unknown", "Consumed", "Unconsumed"]>];
+ let Documentation = [ConsumableDocs];
+}
+
+def ConsumableAutoCast : InheritableAttr {
+ let Spellings = [GNU<"consumable_auto_cast_state">];
+ let Subjects = SubjectList<[CXXRecord]>;
+ let Documentation = [Undocumented];
+}
+
+def ConsumableSetOnRead : InheritableAttr {
+ let Spellings = [GNU<"consumable_set_state_on_read">];
+ let Subjects = SubjectList<[CXXRecord]>;
+ let Documentation = [Undocumented];
+}
+
+def CallableWhen : InheritableAttr {
+ let Spellings = [GNU<"callable_when">];
+ let Subjects = SubjectList<[CXXMethod]>;
+ let Args = [VariadicEnumArgument<"CallableStates", "ConsumedState",
+ ["unknown", "consumed", "unconsumed"],
+ ["Unknown", "Consumed", "Unconsumed"]>];
+ let Documentation = [CallableWhenDocs];
+}
+
+def ParamTypestate : InheritableAttr {
+ let Spellings = [GNU<"param_typestate">];
+ let Subjects = SubjectList<[ParmVar]>;
+ let Args = [EnumArgument<"ParamState", "ConsumedState",
+ ["unknown", "consumed", "unconsumed"],
+ ["Unknown", "Consumed", "Unconsumed"]>];
+ let Documentation = [ParamTypestateDocs];
+}
+
+def ReturnTypestate : InheritableAttr {
+ let Spellings = [GNU<"return_typestate">];
+ let Subjects = SubjectList<[Function, ParmVar]>;
+ let Args = [EnumArgument<"State", "ConsumedState",
+ ["unknown", "consumed", "unconsumed"],
+ ["Unknown", "Consumed", "Unconsumed"]>];
+ let Documentation = [ReturnTypestateDocs];
+}
+
+def SetTypestate : InheritableAttr {
+ let Spellings = [GNU<"set_typestate">];
+ let Subjects = SubjectList<[CXXMethod]>;
+ let Args = [EnumArgument<"NewState", "ConsumedState",
+ ["unknown", "consumed", "unconsumed"],
+ ["Unknown", "Consumed", "Unconsumed"]>];
+ let Documentation = [SetTypestateDocs];
+}
+
+def TestTypestate : InheritableAttr {
+ let Spellings = [GNU<"test_typestate">];
+ let Subjects = SubjectList<[CXXMethod]>;
+ let Args = [EnumArgument<"TestState", "ConsumedState",
+ ["consumed", "unconsumed"],
+ ["Consumed", "Unconsumed"]>];
+ let Documentation = [TestTypestateDocs];
+}
+
+// Type safety attributes for `void *' pointers and type tags.
+
+def ArgumentWithTypeTag : InheritableAttr {
+ let Spellings = [GNU<"argument_with_type_tag">,
+ GNU<"pointer_with_type_tag">];
+ let Args = [IdentifierArgument<"ArgumentKind">,
+ UnsignedArgument<"ArgumentIdx">,
+ UnsignedArgument<"TypeTagIdx">,
+ BoolArgument<"IsPointer">];
+ let HasCustomParsing = 1;
+ let Documentation = [ArgumentWithTypeTagDocs, PointerWithTypeTagDocs];
+}
+
+def TypeTagForDatatype : InheritableAttr {
+ let Spellings = [GNU<"type_tag_for_datatype">];
+ let Args = [IdentifierArgument<"ArgumentKind">,
+ TypeArgument<"MatchingCType">,
+ BoolArgument<"LayoutCompatible">,
+ BoolArgument<"MustBeNull">];
+// let Subjects = SubjectList<[Var], ErrorDiag>;
+ let HasCustomParsing = 1;
+ let Documentation = [TypeTagForDatatypeDocs];
+}
+
+// Microsoft-related attributes
+
+def MSNoVTable : InheritableAttr, TargetSpecificAttr<TargetMicrosoftCXXABI> {
+ let Spellings = [Declspec<"novtable">];
+ let Subjects = SubjectList<[CXXRecord]>;
+ let Documentation = [MSNoVTableDocs];
+}
+
+def : IgnoredAttr {
+ let Spellings = [Declspec<"property">];
+}
+
+def MSStruct : InheritableAttr {
+ let Spellings = [GCC<"ms_struct">];
+ let Subjects = SubjectList<[Record]>;
+ let Documentation = [Undocumented];
+}
+
+def DLLExport : InheritableAttr, TargetSpecificAttr<TargetWindows> {
+ let Spellings = [Declspec<"dllexport">, GCC<"dllexport">];
+ let Subjects = SubjectList<[Function, Var, CXXRecord]>;
+ let Documentation = [Undocumented];
+}
+
+def DLLImport : InheritableAttr, TargetSpecificAttr<TargetWindows> {
+ let Spellings = [Declspec<"dllimport">, GCC<"dllimport">];
+ let Subjects = SubjectList<[Function, Var, CXXRecord]>;
+ let Documentation = [Undocumented];
+}
+
+def SelectAny : InheritableAttr {
+ let Spellings = [Declspec<"selectany">];
+ let LangOpts = [MicrosoftExt];
+ let Documentation = [Undocumented];
+}
+
+def Thread : Attr {
+ let Spellings = [Declspec<"thread">];
+ let LangOpts = [MicrosoftExt];
+ let Documentation = [ThreadDocs];
+ let Subjects = SubjectList<[Var]>;
+}
+
+def Win64 : IgnoredAttr {
+ let Spellings = [Keyword<"__w64">];
+ let LangOpts = [MicrosoftExt];
+}
+
+def Ptr32 : TypeAttr {
+ let Spellings = [Keyword<"__ptr32">];
+ let Documentation = [Undocumented];
+}
+
+def Ptr64 : TypeAttr {
+ let Spellings = [Keyword<"__ptr64">];
+ let Documentation = [Undocumented];
+}
+
+def SPtr : TypeAttr {
+ let Spellings = [Keyword<"__sptr">];
+ let Documentation = [Undocumented];
+}
+
+def UPtr : TypeAttr {
+ let Spellings = [Keyword<"__uptr">];
+ let Documentation = [Undocumented];
+}
+
+def MSInheritance : InheritableAttr {
+ let LangOpts = [MicrosoftExt];
+ let Args = [DefaultBoolArgument<"BestCase", 1>];
+ let Spellings = [Keyword<"__single_inheritance">,
+ Keyword<"__multiple_inheritance">,
+ Keyword<"__virtual_inheritance">,
+ Keyword<"__unspecified_inheritance">];
+ let AdditionalMembers = [{
+ static bool hasVBPtrOffsetField(Spelling Inheritance) {
+ return Inheritance == Keyword_unspecified_inheritance;
+ }
+
+ // Only member pointers to functions need a this adjustment, since it can be
+ // combined with the field offset for data pointers.
+ static bool hasNVOffsetField(bool IsMemberFunction, Spelling Inheritance) {
+ return IsMemberFunction && Inheritance >= Keyword_multiple_inheritance;
+ }
+
+ static bool hasVBTableOffsetField(Spelling Inheritance) {
+ return Inheritance >= Keyword_virtual_inheritance;
+ }
+
+ static bool hasOnlyOneField(bool IsMemberFunction,
+ Spelling Inheritance) {
+ if (IsMemberFunction)
+ return Inheritance <= Keyword_single_inheritance;
+ return Inheritance <= Keyword_multiple_inheritance;
+ }
+ }];
+ let Documentation = [MSInheritanceDocs];
+}
+
+def MSVtorDisp : InheritableAttr {
+ // This attribute has no spellings as it is only ever created implicitly.
+ let Spellings = [];
+ let Args = [UnsignedArgument<"vdm">];
+ let SemaHandler = 0;
+
+ let AdditionalMembers = [{
+ enum Mode {
+ Never,
+ ForVBaseOverride,
+ ForVFTable
+ };
+
+ Mode getVtorDispMode() const { return Mode(vdm); }
+ }];
+ let Documentation = [Undocumented];
+}
+
+def InitSeg : Attr {
+ let Spellings = [Pragma<"", "init_seg">];
+ let Args = [StringArgument<"Section">];
+ let SemaHandler = 0;
+ let Documentation = [InitSegDocs];
+ let AdditionalMembers = [{
+ void printPrettyPragma(raw_ostream &OS, const PrintingPolicy &Policy) const {
+ OS << '(' << getSection() << ')';
+ }
+ }];
+}
+
+def Unaligned : IgnoredAttr {
+ let Spellings = [Keyword<"__unaligned">];
+}
+
+def LoopHint : Attr {
+ /// #pragma clang loop <option> directive
+ /// vectorize: vectorizes loop operations if State == Enable.
+ /// vectorize_width: vectorize loop operations with width 'Value'.
+ /// interleave: interleave multiple loop iterations if State == Enable.
+ /// interleave_count: interleaves 'Value' loop interations.
+ /// unroll: fully unroll loop if State == Enable.
+ /// unroll_count: unrolls loop 'Value' times.
+
+ /// #pragma unroll <argument> directive
+ /// <no arg>: fully unrolls loop.
+ /// boolean: fully unrolls loop if State == Enable.
+ /// expression: unrolls loop 'Value' times.
+
+ let Spellings = [Pragma<"clang", "loop">, Pragma<"", "unroll">,
+ Pragma<"", "nounroll">];
+
+ /// State of the loop optimization specified by the spelling.
+ let Args = [EnumArgument<"Option", "OptionType",
+ ["vectorize", "vectorize_width", "interleave", "interleave_count",
+ "unroll", "unroll_count"],
+ ["Vectorize", "VectorizeWidth", "Interleave", "InterleaveCount",
+ "Unroll", "UnrollCount"]>,
+ EnumArgument<"State", "LoopHintState",
+ ["enable", "disable", "numeric", "assume_safety", "full"],
+ ["Enable", "Disable", "Numeric", "AssumeSafety", "Full"]>,
+ ExprArgument<"Value">];
+
+ let AdditionalMembers = [{
+ static const char *getOptionName(int Option) {
+ switch(Option) {
+ case Vectorize: return "vectorize";
+ case VectorizeWidth: return "vectorize_width";
+ case Interleave: return "interleave";
+ case InterleaveCount: return "interleave_count";
+ case Unroll: return "unroll";
+ case UnrollCount: return "unroll_count";
+ }
+ llvm_unreachable("Unhandled LoopHint option.");
+ }
+
+ void printPrettyPragma(raw_ostream &OS, const PrintingPolicy &Policy) const {
+ unsigned SpellingIndex = getSpellingListIndex();
+ // For "#pragma unroll" and "#pragma nounroll" the string "unroll" or
+ // "nounroll" is already emitted as the pragma name.
+ if (SpellingIndex == Pragma_nounroll)
+ return;
+ else if (SpellingIndex == Pragma_unroll) {
+ OS << getValueString(Policy);
+ return;
+ }
+
+ assert(SpellingIndex == Pragma_clang_loop && "Unexpected spelling");
+ OS << getOptionName(option) << getValueString(Policy);
+ }
+
+ // Return a string containing the loop hint argument including the
+ // enclosing parentheses.
+ std::string getValueString(const PrintingPolicy &Policy) const {
+ std::string ValueName;
+ llvm::raw_string_ostream OS(ValueName);
+ OS << "(";
+ if (state == Numeric)
+ value->printPretty(OS, nullptr, Policy);
+ else if (state == Enable)
+ OS << "enable";
+ else if (state == Full)
+ OS << "full";
+ else if (state == AssumeSafety)
+ OS << "assume_safety";
+ else
+ OS << "disable";
+ OS << ")";
+ return OS.str();
+ }
+
+ // Return a string suitable for identifying this attribute in diagnostics.
+ std::string getDiagnosticName(const PrintingPolicy &Policy) const {
+ unsigned SpellingIndex = getSpellingListIndex();
+ if (SpellingIndex == Pragma_nounroll)
+ return "#pragma nounroll";
+ else if (SpellingIndex == Pragma_unroll)
+ return "#pragma unroll" + (option == UnrollCount ? getValueString(Policy) : "");
+
+ assert(SpellingIndex == Pragma_clang_loop && "Unexpected spelling");
+ return getOptionName(option) + getValueString(Policy);
+ }
+ }];
+
+ let Documentation = [LoopHintDocs, UnrollHintDocs];
+}
+
+def CapturedRecord : InheritableAttr {
+ // This attribute has no spellings as it is only ever created implicitly.
+ let Spellings = [];
+ let SemaHandler = 0;
+ let Documentation = [Undocumented];
+}
+
+def OMPThreadPrivateDecl : InheritableAttr {
+ // This attribute has no spellings as it is only ever created implicitly.
+ let Spellings = [];
+ let SemaHandler = 0;
+ let Documentation = [Undocumented];
+}
+
+def InternalLinkage : InheritableAttr {
+ let Spellings = [GNU<"internal_linkage">, CXX11<"clang", "internal_linkage">];
+ let Subjects = SubjectList<[Var, Function, CXXRecord]>;
+ let Documentation = [InternalLinkageDocs];
+}
diff --git a/contrib/llvm/tools/clang/include/clang/Basic/AttrDocs.td b/contrib/llvm/tools/clang/include/clang/Basic/AttrDocs.td
new file mode 100644
index 0000000..2567d55
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Basic/AttrDocs.td
@@ -0,0 +1,1861 @@
+//==--- AttrDocs.td - Attribute documentation ----------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===---------------------------------------------------------------------===//
+
+def GlobalDocumentation {
+ code Intro =[{..
+ -------------------------------------------------------------------
+ NOTE: This file is automatically generated by running clang-tblgen
+ -gen-attr-docs. Do not edit this file by hand!!
+ -------------------------------------------------------------------
+
+===================
+Attributes in Clang
+===================
+.. contents::
+ :local:
+
+Introduction
+============
+
+This page lists the attributes currently supported by Clang.
+}];
+}
+
+def SectionDocs : Documentation {
+ let Category = DocCatVariable;
+ let Content = [{
+The ``section`` attribute allows you to specify a specific section a
+global variable or function should be in after translation.
+ }];
+ let Heading = "section (gnu::section, __declspec(allocate))";
+}
+
+def InitSegDocs : Documentation {
+ let Category = DocCatVariable;
+ let Content = [{
+The attribute applied by ``pragma init_seg()`` controls the section into
+which global initialization function pointers are emitted. It is only
+available with ``-fms-extensions``. Typically, this function pointer is
+emitted into ``.CRT$XCU`` on Windows. The user can change the order of
+initialization by using a different section name with the same
+``.CRT$XC`` prefix and a suffix that sorts lexicographically before or
+after the standard ``.CRT$XCU`` sections. See the init_seg_
+documentation on MSDN for more information.
+
+.. _init_seg: http://msdn.microsoft.com/en-us/library/7977wcck(v=vs.110).aspx
+ }];
+}
+
+def TLSModelDocs : Documentation {
+ let Category = DocCatVariable;
+ let Content = [{
+The ``tls_model`` attribute allows you to specify which thread-local storage
+model to use. It accepts the following strings:
+
+* global-dynamic
+* local-dynamic
+* initial-exec
+* local-exec
+
+TLS models are mutually exclusive.
+ }];
+}
+
+def ThreadDocs : Documentation {
+ let Category = DocCatVariable;
+ let Content = [{
+The ``__declspec(thread)`` attribute declares a variable with thread local
+storage. It is available under the ``-fms-extensions`` flag for MSVC
+compatibility. See the documentation for `__declspec(thread)`_ on MSDN.
+
+.. _`__declspec(thread)`: http://msdn.microsoft.com/en-us/library/9w1sdazb.aspx
+
+In Clang, ``__declspec(thread)`` is generally equivalent in functionality to the
+GNU ``__thread`` keyword. The variable must not have a destructor and must have
+a constant initializer, if any. The attribute only applies to variables
+declared with static storage duration, such as globals, class static data
+members, and static locals.
+ }];
+}
+
+def CarriesDependencyDocs : Documentation {
+ let Category = DocCatFunction;
+ let Content = [{
+The ``carries_dependency`` attribute specifies dependency propagation into and
+out of functions.
+
+When specified on a function or Objective-C method, the ``carries_dependency``
+attribute means that the return value carries a dependency out of the function,
+so that the implementation need not constrain ordering upon return from that
+function. Implementations of the function and its caller may choose to preserve
+dependencies instead of emitting memory ordering instructions such as fences.
+
+Note, this attribute does not change the meaning of the program, but may result
+in generation of more efficient code.
+ }];
+}
+
+def C11NoReturnDocs : Documentation {
+ let Category = DocCatFunction;
+ let Content = [{
+A function declared as ``_Noreturn`` shall not return to its caller. The
+compiler will generate a diagnostic for a function declared as ``_Noreturn``
+that appears to be capable of returning to its caller.
+ }];
+}
+
+def CXX11NoReturnDocs : Documentation {
+ let Category = DocCatFunction;
+ let Content = [{
+A function declared as ``[[noreturn]]`` shall not return to its caller. The
+compiler will generate a diagnostic for a function declared as ``[[noreturn]]``
+that appears to be capable of returning to its caller.
+ }];
+}
+
+def AssertCapabilityDocs : Documentation {
+ let Category = DocCatFunction;
+ let Heading = "assert_capability (assert_shared_capability, clang::assert_capability, clang::assert_shared_capability)";
+ let Content = [{
+Marks a function that dynamically tests whether a capability is held, and halts
+the program if it is not held.
+ }];
+}
+
+def AcquireCapabilityDocs : Documentation {
+ let Category = DocCatFunction;
+ let Heading = "acquire_capability (acquire_shared_capability, clang::acquire_capability, clang::acquire_shared_capability)";
+ let Content = [{
+Marks a function as acquiring a capability.
+ }];
+}
+
+def TryAcquireCapabilityDocs : Documentation {
+ let Category = DocCatFunction;
+ let Heading = "try_acquire_capability (try_acquire_shared_capability, clang::try_acquire_capability, clang::try_acquire_shared_capability)";
+ let Content = [{
+Marks a function that attempts to acquire a capability. This function may fail to
+actually acquire the capability; they accept a Boolean value determining
+whether acquiring the capability means success (true), or failing to acquire
+the capability means success (false).
+ }];
+}
+
+def ReleaseCapabilityDocs : Documentation {
+ let Category = DocCatFunction;
+ let Heading = "release_capability (release_shared_capability, clang::release_capability, clang::release_shared_capability)";
+ let Content = [{
+Marks a function as releasing a capability.
+ }];
+}
+
+def AssumeAlignedDocs : Documentation {
+ let Category = DocCatFunction;
+ let Content = [{
+Use ``__attribute__((assume_aligned(<alignment>[,<offset>]))`` on a function
+declaration to specify that the return value of the function (which must be a
+pointer type) has the specified offset, in bytes, from an address with the
+specified alignment. The offset is taken to be zero if omitted.
+
+.. code-block:: c++
+
+ // The returned pointer value has 32-byte alignment.
+ void *a() __attribute__((assume_aligned (32)));
+
+ // The returned pointer value is 4 bytes greater than an address having
+ // 32-byte alignment.
+ void *b() __attribute__((assume_aligned (32, 4)));
+
+Note that this attribute provides information to the compiler regarding a
+condition that the code already ensures is true. It does not cause the compiler
+to enforce the provided alignment assumption.
+ }];
+}
+
+def EnableIfDocs : Documentation {
+ let Category = DocCatFunction;
+ let Content = [{
+.. Note:: Some features of this attribute are experimental. The meaning of
+ multiple enable_if attributes on a single declaration is subject to change in
+ a future version of clang. Also, the ABI is not standardized and the name
+ mangling may change in future versions. To avoid that, use asm labels.
+
+The ``enable_if`` attribute can be placed on function declarations to control
+which overload is selected based on the values of the function's arguments.
+When combined with the ``overloadable`` attribute, this feature is also
+available in C.
+
+.. code-block:: c++
+
+ int isdigit(int c);
+ int isdigit(int c) __attribute__((enable_if(c <= -1 || c > 255, "chosen when 'c' is out of range"))) __attribute__((unavailable("'c' must have the value of an unsigned char or EOF")));
+
+ void foo(char c) {
+ isdigit(c);
+ isdigit(10);
+ isdigit(-10); // results in a compile-time error.
+ }
+
+The enable_if attribute takes two arguments, the first is an expression written
+in terms of the function parameters, the second is a string explaining why this
+overload candidate could not be selected to be displayed in diagnostics. The
+expression is part of the function signature for the purposes of determining
+whether it is a redeclaration (following the rules used when determining
+whether a C++ template specialization is ODR-equivalent), but is not part of
+the type.
+
+The enable_if expression is evaluated as if it were the body of a
+bool-returning constexpr function declared with the arguments of the function
+it is being applied to, then called with the parameters at the call site. If the
+result is false or could not be determined through constant expression
+evaluation, then this overload will not be chosen and the provided string may
+be used in a diagnostic if the compile fails as a result.
+
+Because the enable_if expression is an unevaluated context, there are no global
+state changes, nor the ability to pass information from the enable_if
+expression to the function body. For example, suppose we want calls to
+strnlen(strbuf, maxlen) to resolve to strnlen_chk(strbuf, maxlen, size of
+strbuf) only if the size of strbuf can be determined:
+
+.. code-block:: c++
+
+ __attribute__((always_inline))
+ static inline size_t strnlen(const char *s, size_t maxlen)
+ __attribute__((overloadable))
+ __attribute__((enable_if(__builtin_object_size(s, 0) != -1))),
+ "chosen when the buffer size is known but 'maxlen' is not")))
+ {
+ return strnlen_chk(s, maxlen, __builtin_object_size(s, 0));
+ }
+
+Multiple enable_if attributes may be applied to a single declaration. In this
+case, the enable_if expressions are evaluated from left to right in the
+following manner. First, the candidates whose enable_if expressions evaluate to
+false or cannot be evaluated are discarded. If the remaining candidates do not
+share ODR-equivalent enable_if expressions, the overload resolution is
+ambiguous. Otherwise, enable_if overload resolution continues with the next
+enable_if attribute on the candidates that have not been discarded and have
+remaining enable_if attributes. In this way, we pick the most specific
+overload out of a number of viable overloads using enable_if.
+
+.. code-block:: c++
+
+ void f() __attribute__((enable_if(true, ""))); // #1
+ void f() __attribute__((enable_if(true, ""))) __attribute__((enable_if(true, ""))); // #2
+
+ void g(int i, int j) __attribute__((enable_if(i, ""))); // #1
+ void g(int i, int j) __attribute__((enable_if(j, ""))) __attribute__((enable_if(true))); // #2
+
+In this example, a call to f() is always resolved to #2, as the first enable_if
+expression is ODR-equivalent for both declarations, but #1 does not have another
+enable_if expression to continue evaluating, so the next round of evaluation has
+only a single candidate. In a call to g(1, 1), the call is ambiguous even though
+#2 has more enable_if attributes, because the first enable_if expressions are
+not ODR-equivalent.
+
+Query for this feature with ``__has_attribute(enable_if)``.
+ }];
+}
+
+def PassObjectSizeDocs : Documentation {
+ let Category = DocCatVariable; // Technically it's a parameter doc, but eh.
+ let Content = [{
+.. Note:: The mangling of functions with parameters that are annotated with
+ ``pass_object_size`` is subject to change. You can get around this by
+ using ``__asm__("foo")`` to explicitly name your functions, thus preserving
+ your ABI; also, non-overloadable C functions with ``pass_object_size`` are
+ not mangled.
+
+The ``pass_object_size(Type)`` attribute can be placed on function parameters to
+instruct clang to call ``__builtin_object_size(param, Type)`` at each callsite
+of said function, and implicitly pass the result of this call in as an invisible
+argument of type ``size_t`` directly after the parameter annotated with
+``pass_object_size``. Clang will also replace any calls to
+``__builtin_object_size(param, Type)`` in the function by said implicit
+parameter.
+
+Example usage:
+
+.. code-block:: c
+
+ int bzero1(char *const p __attribute__((pass_object_size(0))))
+ __attribute__((noinline)) {
+ int i = 0;
+ for (/**/; i < (int)__builtin_object_size(p, 0); ++i) {
+ p[i] = 0;
+ }
+ return i;
+ }
+
+ int main() {
+ char chars[100];
+ int n = bzero1(&chars[0]);
+ assert(n == sizeof(chars));
+ return 0;
+ }
+
+If successfully evaluating ``__builtin_object_size(param, Type)`` at the
+callsite is not possible, then the "failed" value is passed in. So, using the
+definition of ``bzero1`` from above, the following code would exit cleanly:
+
+.. code-block:: c
+
+ int main2(int argc, char *argv[]) {
+ int n = bzero1(argv);
+ assert(n == -1);
+ return 0;
+ }
+
+``pass_object_size`` plays a part in overload resolution. If two overload
+candidates are otherwise equally good, then the overload with one or more
+parameters with ``pass_object_size`` is preferred. This implies that the choice
+between two identical overloads both with ``pass_object_size`` on one or more
+parameters will always be ambiguous; for this reason, having two such overloads
+is illegal. For example:
+
+.. code-block:: c++
+
+ #define PS(N) __attribute__((pass_object_size(N)))
+ // OK
+ void Foo(char *a, char *b); // Overload A
+ // OK -- overload A has no parameters with pass_object_size.
+ void Foo(char *a PS(0), char *b PS(0)); // Overload B
+ // Error -- Same signature (sans pass_object_size) as overload B, and both
+ // overloads have one or more parameters with the pass_object_size attribute.
+ void Foo(void *a PS(0), void *b);
+
+ // OK
+ void Bar(void *a PS(0)); // Overload C
+ // OK
+ void Bar(char *c PS(1)); // Overload D
+
+ void main() {
+ char known[10], *unknown;
+ Foo(unknown, unknown); // Calls overload B
+ Foo(known, unknown); // Calls overload B
+ Foo(unknown, known); // Calls overload B
+ Foo(known, known); // Calls overload B
+
+ Bar(known); // Calls overload D
+ Bar(unknown); // Calls overload D
+ }
+
+Currently, ``pass_object_size`` is a bit restricted in terms of its usage:
+
+* Only one use of ``pass_object_size`` is allowed per parameter.
+
+* It is an error to take the address of a function with ``pass_object_size`` on
+ any of its parameters. If you wish to do this, you can create an overload
+ without ``pass_object_size`` on any parameters.
+
+* It is an error to apply the ``pass_object_size`` attribute to parameters that
+ are not pointers. Additionally, any parameter that ``pass_object_size`` is
+ applied to must be marked ``const`` at its function's definition.
+ }];
+}
+
+def OverloadableDocs : Documentation {
+ let Category = DocCatFunction;
+ let Content = [{
+Clang provides support for C++ function overloading in C. Function overloading
+in C is introduced using the ``overloadable`` attribute. For example, one
+might provide several overloaded versions of a ``tgsin`` function that invokes
+the appropriate standard function computing the sine of a value with ``float``,
+``double``, or ``long double`` precision:
+
+.. code-block:: c
+
+ #include <math.h>
+ float __attribute__((overloadable)) tgsin(float x) { return sinf(x); }
+ double __attribute__((overloadable)) tgsin(double x) { return sin(x); }
+ long double __attribute__((overloadable)) tgsin(long double x) { return sinl(x); }
+
+Given these declarations, one can call ``tgsin`` with a ``float`` value to
+receive a ``float`` result, with a ``double`` to receive a ``double`` result,
+etc. Function overloading in C follows the rules of C++ function overloading
+to pick the best overload given the call arguments, with a few C-specific
+semantics:
+
+* Conversion from ``float`` or ``double`` to ``long double`` is ranked as a
+ floating-point promotion (per C99) rather than as a floating-point conversion
+ (as in C++).
+
+* A conversion from a pointer of type ``T*`` to a pointer of type ``U*`` is
+ considered a pointer conversion (with conversion rank) if ``T`` and ``U`` are
+ compatible types.
+
+* A conversion from type ``T`` to a value of type ``U`` is permitted if ``T``
+ and ``U`` are compatible types. This conversion is given "conversion" rank.
+
+The declaration of ``overloadable`` functions is restricted to function
+declarations and definitions. Most importantly, if any function with a given
+name is given the ``overloadable`` attribute, then all function declarations
+and definitions with that name (and in that scope) must have the
+``overloadable`` attribute. This rule even applies to redeclarations of
+functions whose original declaration had the ``overloadable`` attribute, e.g.,
+
+.. code-block:: c
+
+ int f(int) __attribute__((overloadable));
+ float f(float); // error: declaration of "f" must have the "overloadable" attribute
+
+ int g(int) __attribute__((overloadable));
+ int g(int) { } // error: redeclaration of "g" must also have the "overloadable" attribute
+
+Functions marked ``overloadable`` must have prototypes. Therefore, the
+following code is ill-formed:
+
+.. code-block:: c
+
+ int h() __attribute__((overloadable)); // error: h does not have a prototype
+
+However, ``overloadable`` functions are allowed to use a ellipsis even if there
+are no named parameters (as is permitted in C++). This feature is particularly
+useful when combined with the ``unavailable`` attribute:
+
+.. code-block:: c++
+
+ void honeypot(...) __attribute__((overloadable, unavailable)); // calling me is an error
+
+Functions declared with the ``overloadable`` attribute have their names mangled
+according to the same rules as C++ function names. For example, the three
+``tgsin`` functions in our motivating example get the mangled names
+``_Z5tgsinf``, ``_Z5tgsind``, and ``_Z5tgsine``, respectively. There are two
+caveats to this use of name mangling:
+
+* Future versions of Clang may change the name mangling of functions overloaded
+ in C, so you should not depend on an specific mangling. To be completely
+ safe, we strongly urge the use of ``static inline`` with ``overloadable``
+ functions.
+
+* The ``overloadable`` attribute has almost no meaning when used in C++,
+ because names will already be mangled and functions are already overloadable.
+ However, when an ``overloadable`` function occurs within an ``extern "C"``
+ linkage specification, it's name *will* be mangled in the same way as it
+ would in C.
+
+Query for this feature with ``__has_extension(attribute_overloadable)``.
+ }];
+}
+
+def ObjCMethodFamilyDocs : Documentation {
+ let Category = DocCatFunction;
+ let Content = [{
+Many methods in Objective-C have conventional meanings determined by their
+selectors. It is sometimes useful to be able to mark a method as having a
+particular conventional meaning despite not having the right selector, or as
+not having the conventional meaning that its selector would suggest. For these
+use cases, we provide an attribute to specifically describe the "method family"
+that a method belongs to.
+
+**Usage**: ``__attribute__((objc_method_family(X)))``, where ``X`` is one of
+``none``, ``alloc``, ``copy``, ``init``, ``mutableCopy``, or ``new``. This
+attribute can only be placed at the end of a method declaration:
+
+.. code-block:: objc
+
+ - (NSString *)initMyStringValue __attribute__((objc_method_family(none)));
+
+Users who do not wish to change the conventional meaning of a method, and who
+merely want to document its non-standard retain and release semantics, should
+use the retaining behavior attributes (``ns_returns_retained``,
+``ns_returns_not_retained``, etc).
+
+Query for this feature with ``__has_attribute(objc_method_family)``.
+ }];
+}
+
+def NoDuplicateDocs : Documentation {
+ let Category = DocCatFunction;
+ let Content = [{
+The ``noduplicate`` attribute can be placed on function declarations to control
+whether function calls to this function can be duplicated or not as a result of
+optimizations. This is required for the implementation of functions with
+certain special requirements, like the OpenCL "barrier" function, that might
+need to be run concurrently by all the threads that are executing in lockstep
+on the hardware. For example this attribute applied on the function
+"nodupfunc" in the code below avoids that:
+
+.. code-block:: c
+
+ void nodupfunc() __attribute__((noduplicate));
+ // Setting it as a C++11 attribute is also valid
+ // void nodupfunc() [[clang::noduplicate]];
+ void foo();
+ void bar();
+
+ nodupfunc();
+ if (a > n) {
+ foo();
+ } else {
+ bar();
+ }
+
+gets possibly modified by some optimizations into code similar to this:
+
+.. code-block:: c
+
+ if (a > n) {
+ nodupfunc();
+ foo();
+ } else {
+ nodupfunc();
+ bar();
+ }
+
+where the call to "nodupfunc" is duplicated and sunk into the two branches
+of the condition.
+ }];
+}
+
+def NoSplitStackDocs : Documentation {
+ let Category = DocCatFunction;
+ let Content = [{
+The ``no_split_stack`` attribute disables the emission of the split stack
+preamble for a particular function. It has no effect if ``-fsplit-stack``
+is not specified.
+ }];
+}
+
+def ObjCRequiresSuperDocs : Documentation {
+ let Category = DocCatFunction;
+ let Content = [{
+Some Objective-C classes allow a subclass to override a particular method in a
+parent class but expect that the overriding method also calls the overridden
+method in the parent class. For these cases, we provide an attribute to
+designate that a method requires a "call to ``super``" in the overriding
+method in the subclass.
+
+**Usage**: ``__attribute__((objc_requires_super))``. This attribute can only
+be placed at the end of a method declaration:
+
+.. code-block:: objc
+
+ - (void)foo __attribute__((objc_requires_super));
+
+This attribute can only be applied the method declarations within a class, and
+not a protocol. Currently this attribute does not enforce any placement of
+where the call occurs in the overriding method (such as in the case of
+``-dealloc`` where the call must appear at the end). It checks only that it
+exists.
+
+Note that on both OS X and iOS that the Foundation framework provides a
+convenience macro ``NS_REQUIRES_SUPER`` that provides syntactic sugar for this
+attribute:
+
+.. code-block:: objc
+
+ - (void)foo NS_REQUIRES_SUPER;
+
+This macro is conditionally defined depending on the compiler's support for
+this attribute. If the compiler does not support the attribute the macro
+expands to nothing.
+
+Operationally, when a method has this annotation the compiler will warn if the
+implementation of an override in a subclass does not call super. For example:
+
+.. code-block:: objc
+
+ warning: method possibly missing a [super AnnotMeth] call
+ - (void) AnnotMeth{};
+ ^
+ }];
+}
+
+def ObjCRuntimeNameDocs : Documentation {
+ let Category = DocCatFunction;
+ let Content = [{
+By default, the Objective-C interface or protocol identifier is used
+in the metadata name for that object. The `objc_runtime_name`
+attribute allows annotated interfaces or protocols to use the
+specified string argument in the object's metadata name instead of the
+default name.
+
+**Usage**: ``__attribute__((objc_runtime_name("MyLocalName")))``. This attribute
+can only be placed before an @protocol or @interface declaration:
+
+.. code-block:: objc
+
+ __attribute__((objc_runtime_name("MyLocalName")))
+ @interface Message
+ @end
+
+ }];
+}
+
+def ObjCBoxableDocs : Documentation {
+ let Category = DocCatFunction;
+ let Content = [{
+Structs and unions marked with the ``objc_boxable`` attribute can be used
+with the Objective-C boxed expression syntax, ``@(...)``.
+
+**Usage**: ``__attribute__((objc_boxable))``. This attribute
+can only be placed on a declaration of a trivially-copyable struct or union:
+
+.. code-block:: objc
+
+ struct __attribute__((objc_boxable)) some_struct {
+ int i;
+ };
+ union __attribute__((objc_boxable)) some_union {
+ int i;
+ float f;
+ };
+ typedef struct __attribute__((objc_boxable)) _some_struct some_struct;
+
+ // ...
+
+ some_struct ss;
+ NSValue *boxed = @(ss);
+
+ }];
+}
+
+def AvailabilityDocs : Documentation {
+ let Category = DocCatFunction;
+ let Content = [{
+The ``availability`` attribute can be placed on declarations to describe the
+lifecycle of that declaration relative to operating system versions. Consider
+the function declaration for a hypothetical function ``f``:
+
+.. code-block:: c++
+
+ void f(void) __attribute__((availability(macosx,introduced=10.4,deprecated=10.6,obsoleted=10.7)));
+
+The availability attribute states that ``f`` was introduced in Mac OS X 10.4,
+deprecated in Mac OS X 10.6, and obsoleted in Mac OS X 10.7. This information
+is used by Clang to determine when it is safe to use ``f``: for example, if
+Clang is instructed to compile code for Mac OS X 10.5, a call to ``f()``
+succeeds. If Clang is instructed to compile code for Mac OS X 10.6, the call
+succeeds but Clang emits a warning specifying that the function is deprecated.
+Finally, if Clang is instructed to compile code for Mac OS X 10.7, the call
+fails because ``f()`` is no longer available.
+
+The availability attribute is a comma-separated list starting with the
+platform name and then including clauses specifying important milestones in the
+declaration's lifetime (in any order) along with additional information. Those
+clauses can be:
+
+introduced=\ *version*
+ The first version in which this declaration was introduced.
+
+deprecated=\ *version*
+ The first version in which this declaration was deprecated, meaning that
+ users should migrate away from this API.
+
+obsoleted=\ *version*
+ The first version in which this declaration was obsoleted, meaning that it
+ was removed completely and can no longer be used.
+
+unavailable
+ This declaration is never available on this platform.
+
+message=\ *string-literal*
+ Additional message text that Clang will provide when emitting a warning or
+ error about use of a deprecated or obsoleted declaration. Useful to direct
+ users to replacement APIs.
+
+Multiple availability attributes can be placed on a declaration, which may
+correspond to different platforms. Only the availability attribute with the
+platform corresponding to the target platform will be used; any others will be
+ignored. If no availability attribute specifies availability for the current
+target platform, the availability attributes are ignored. Supported platforms
+are:
+
+``ios``
+ Apple's iOS operating system. The minimum deployment target is specified by
+ the ``-mios-version-min=*version*`` or ``-miphoneos-version-min=*version*``
+ command-line arguments.
+
+``macosx``
+ Apple's Mac OS X operating system. The minimum deployment target is
+ specified by the ``-mmacosx-version-min=*version*`` command-line argument.
+
+``tvos``
+ Apple's tvOS operating system. The minimum deployment target is specified by
+ the ``-mtvos-version-min=*version*`` command-line argument.
+
+``watchos``
+ Apple's watchOS operating system. The minimum deployment target is specified by
+ the ``-mwatchos-version-min=*version*`` command-line argument.
+
+A declaration can be used even when deploying back to a platform version prior
+to when the declaration was introduced. When this happens, the declaration is
+`weakly linked
+<https://developer.apple.com/library/mac/#documentation/MacOSX/Conceptual/BPFrameworks/Concepts/WeakLinking.html>`_,
+as if the ``weak_import`` attribute were added to the declaration. A
+weakly-linked declaration may or may not be present a run-time, and a program
+can determine whether the declaration is present by checking whether the
+address of that declaration is non-NULL.
+
+If there are multiple declarations of the same entity, the availability
+attributes must either match on a per-platform basis or later
+declarations must not have availability attributes for that
+platform. For example:
+
+.. code-block:: c
+
+ void g(void) __attribute__((availability(macosx,introduced=10.4)));
+ void g(void) __attribute__((availability(macosx,introduced=10.4))); // okay, matches
+ void g(void) __attribute__((availability(ios,introduced=4.0))); // okay, adds a new platform
+ void g(void); // okay, inherits both macosx and ios availability from above.
+ void g(void) __attribute__((availability(macosx,introduced=10.5))); // error: mismatch
+
+When one method overrides another, the overriding method can be more widely available than the overridden method, e.g.,:
+
+.. code-block:: objc
+
+ @interface A
+ - (id)method __attribute__((availability(macosx,introduced=10.4)));
+ - (id)method2 __attribute__((availability(macosx,introduced=10.4)));
+ @end
+
+ @interface B : A
+ - (id)method __attribute__((availability(macosx,introduced=10.3))); // okay: method moved into base class later
+ - (id)method __attribute__((availability(macosx,introduced=10.5))); // error: this method was available via the base class in 10.4
+ @end
+ }];
+}
+
+def FallthroughDocs : Documentation {
+ let Category = DocCatStmt;
+ let Content = [{
+The ``clang::fallthrough`` attribute is used along with the
+``-Wimplicit-fallthrough`` argument to annotate intentional fall-through
+between switch labels. It can only be applied to a null statement placed at a
+point of execution between any statement and the next switch label. It is
+common to mark these places with a specific comment, but this attribute is
+meant to replace comments with a more strict annotation, which can be checked
+by the compiler. This attribute doesn't change semantics of the code and can
+be used wherever an intended fall-through occurs. It is designed to mimic
+control-flow statements like ``break;``, so it can be placed in most places
+where ``break;`` can, but only if there are no statements on the execution path
+between it and the next switch label.
+
+Here is an example:
+
+.. code-block:: c++
+
+ // compile with -Wimplicit-fallthrough
+ switch (n) {
+ case 22:
+ case 33: // no warning: no statements between case labels
+ f();
+ case 44: // warning: unannotated fall-through
+ g();
+ [[clang::fallthrough]];
+ case 55: // no warning
+ if (x) {
+ h();
+ break;
+ }
+ else {
+ i();
+ [[clang::fallthrough]];
+ }
+ case 66: // no warning
+ p();
+ [[clang::fallthrough]]; // warning: fallthrough annotation does not
+ // directly precede case label
+ q();
+ case 77: // warning: unannotated fall-through
+ r();
+ }
+ }];
+}
+
+def ARMInterruptDocs : Documentation {
+ let Category = DocCatFunction;
+ let Content = [{
+Clang supports the GNU style ``__attribute__((interrupt("TYPE")))`` attribute on
+ARM targets. This attribute may be attached to a function definition and
+instructs the backend to generate appropriate function entry/exit code so that
+it can be used directly as an interrupt service routine.
+
+The parameter passed to the interrupt attribute is optional, but if
+provided it must be a string literal with one of the following values: "IRQ",
+"FIQ", "SWI", "ABORT", "UNDEF".
+
+The semantics are as follows:
+
+- If the function is AAPCS, Clang instructs the backend to realign the stack to
+ 8 bytes on entry. This is a general requirement of the AAPCS at public
+ interfaces, but may not hold when an exception is taken. Doing this allows
+ other AAPCS functions to be called.
+- If the CPU is M-class this is all that needs to be done since the architecture
+ itself is designed in such a way that functions obeying the normal AAPCS ABI
+ constraints are valid exception handlers.
+- If the CPU is not M-class, the prologue and epilogue are modified to save all
+ non-banked registers that are used, so that upon return the user-mode state
+ will not be corrupted. Note that to avoid unnecessary overhead, only
+ general-purpose (integer) registers are saved in this way. If VFP operations
+ are needed, that state must be saved manually.
+
+ Specifically, interrupt kinds other than "FIQ" will save all core registers
+ except "lr" and "sp". "FIQ" interrupts will save r0-r7.
+- If the CPU is not M-class, the return instruction is changed to one of the
+ canonical sequences permitted by the architecture for exception return. Where
+ possible the function itself will make the necessary "lr" adjustments so that
+ the "preferred return address" is selected.
+
+ Unfortunately the compiler is unable to make this guarantee for an "UNDEF"
+ handler, where the offset from "lr" to the preferred return address depends on
+ the execution state of the code which generated the exception. In this case
+ a sequence equivalent to "movs pc, lr" will be used.
+ }];
+}
+
+def MipsInterruptDocs : Documentation {
+ let Category = DocCatFunction;
+ let Content = [{
+Clang supports the GNU style ``__attribute__((interrupt("ARGUMENT")))`` attribute on
+MIPS targets. This attribute may be attached to a function definition and instructs
+the backend to generate appropriate function entry/exit code so that it can be used
+directly as an interrupt service routine.
+
+By default, the compiler will produce a function prologue and epilogue suitable for
+an interrupt service routine that handles an External Interrupt Controller (eic)
+generated interrupt. This behaviour can be explicitly requested with the "eic"
+argument.
+
+Otherwise, for use with vectored interrupt mode, the argument passed should be
+of the form "vector=LEVEL" where LEVEL is one of the following values:
+"sw0", "sw1", "hw0", "hw1", "hw2", "hw3", "hw4", "hw5". The compiler will
+then set the interrupt mask to the corresponding level which will mask all
+interrupts up to and including the argument.
+
+The semantics are as follows:
+
+- The prologue is modified so that the Exception Program Counter (EPC) and
+ Status coprocessor registers are saved to the stack. The interrupt mask is
+ set so that the function can only be interrupted by a higher priority
+ interrupt. The epilogue will restore the previous values of EPC and Status.
+
+- The prologue and epilogue are modified to save and restore all non-kernel
+ registers as necessary.
+
+- The FPU is disabled in the prologue, as the floating pointer registers are not
+ spilled to the stack.
+
+- The function return sequence is changed to use an exception return instruction.
+
+- The parameter sets the interrupt mask for the function corresponding to the
+ interrupt level specified. If no mask is specified the interrupt mask
+ defaults to "eic".
+ }];
+}
+
+def TargetDocs : Documentation {
+ let Category = DocCatFunction;
+ let Content = [{
+Clang supports the GNU style ``__attribute__((target("OPTIONS")))`` attribute.
+This attribute may be attached to a function definition and instructs
+the backend to use different code generation options than were passed on the
+command line.
+
+The current set of options correspond to the existing "subtarget features" for
+the target with or without a "-mno-" in front corresponding to the absence
+of the feature, as well as ``arch="CPU"`` which will change the default "CPU"
+for the function.
+
+Example "subtarget features" from the x86 backend include: "mmx", "sse", "sse4.2",
+"avx", "xop" and largely correspond to the machine specific options handled by
+the front end.
+}];
+}
+
+def DocCatAMDGPURegisterAttributes :
+ DocumentationCategory<"AMD GPU Register Attributes"> {
+ let Content = [{
+Clang supports attributes for controlling register usage on AMD GPU
+targets. These attributes may be attached to a kernel function
+definition and is an optimization hint to the backend for the maximum
+number of registers to use. This is useful in cases where register
+limited occupancy is known to be an important factor for the
+performance for the kernel.
+
+The semantics are as follows:
+
+- The backend will attempt to limit the number of used registers to
+ the specified value, but the exact number used is not
+ guaranteed. The number used may be rounded up to satisfy the
+ allocation requirements or ABI constraints of the subtarget. For
+ example, on Southern Islands VGPRs may only be allocated in
+ increments of 4, so requesting a limit of 39 VGPRs will really
+ attempt to use up to 40. Requesting more registers than the
+ subtarget supports will truncate to the maximum allowed. The backend
+ may also use fewer registers than requested whenever possible.
+
+- 0 implies the default no limit on register usage.
+
+- Ignored on older VLIW subtargets which did not have separate scalar
+ and vector registers, R600 through Northern Islands.
+
+}];
+}
+
+
+def AMDGPUNumVGPRDocs : Documentation {
+ let Category = DocCatAMDGPURegisterAttributes;
+ let Content = [{
+Clang supports the
+``__attribute__((amdgpu_num_vgpr(<num_registers>)))`` attribute on AMD
+Southern Islands GPUs and later for controlling the number of vector
+registers. A typical value would be between 4 and 256 in increments
+of 4.
+}];
+}
+
+def AMDGPUNumSGPRDocs : Documentation {
+ let Category = DocCatAMDGPURegisterAttributes;
+ let Content = [{
+
+Clang supports the
+``__attribute__((amdgpu_num_sgpr(<num_registers>)))`` attribute on AMD
+Southern Islands GPUs and later for controlling the number of scalar
+registers. A typical value would be between 8 and 104 in increments of
+8.
+
+Due to common instruction constraints, an additional 2-4 SGPRs are
+typically required for internal use depending on features used. This
+value is a hint for the total number of SGPRs to use, and not the
+number of user SGPRs, so no special consideration needs to be given
+for these.
+}];
+}
+
+def DocCatCallingConvs : DocumentationCategory<"Calling Conventions"> {
+ let Content = [{
+Clang supports several different calling conventions, depending on the target
+platform and architecture. The calling convention used for a function determines
+how parameters are passed, how results are returned to the caller, and other
+low-level details of calling a function.
+ }];
+}
+
+def PcsDocs : Documentation {
+ let Category = DocCatCallingConvs;
+ let Content = [{
+On ARM targets, this attribute can be used to select calling conventions
+similar to ``stdcall`` on x86. Valid parameter values are "aapcs" and
+"aapcs-vfp".
+ }];
+}
+
+def RegparmDocs : Documentation {
+ let Category = DocCatCallingConvs;
+ let Content = [{
+On 32-bit x86 targets, the regparm attribute causes the compiler to pass
+the first three integer parameters in EAX, EDX, and ECX instead of on the
+stack. This attribute has no effect on variadic functions, and all parameters
+are passed via the stack as normal.
+ }];
+}
+
+def SysVABIDocs : Documentation {
+ let Category = DocCatCallingConvs;
+ let Content = [{
+On Windows x86_64 targets, this attribute changes the calling convention of a
+function to match the default convention used on Sys V targets such as Linux,
+Mac, and BSD. This attribute has no effect on other targets.
+ }];
+}
+
+def MSABIDocs : Documentation {
+ let Category = DocCatCallingConvs;
+ let Content = [{
+On non-Windows x86_64 targets, this attribute changes the calling convention of
+a function to match the default convention used on Windows x86_64. This
+attribute has no effect on Windows targets or non-x86_64 targets.
+ }];
+}
+
+def StdCallDocs : Documentation {
+ let Category = DocCatCallingConvs;
+ let Content = [{
+On 32-bit x86 targets, this attribute changes the calling convention of a
+function to clear parameters off of the stack on return. This convention does
+not support variadic calls or unprototyped functions in C, and has no effect on
+x86_64 targets. This calling convention is used widely by the Windows API and
+COM applications. See the documentation for `__stdcall`_ on MSDN.
+
+.. _`__stdcall`: http://msdn.microsoft.com/en-us/library/zxk0tw93.aspx
+ }];
+}
+
+def FastCallDocs : Documentation {
+ let Category = DocCatCallingConvs;
+ let Content = [{
+On 32-bit x86 targets, this attribute changes the calling convention of a
+function to use ECX and EDX as register parameters and clear parameters off of
+the stack on return. This convention does not support variadic calls or
+unprototyped functions in C, and has no effect on x86_64 targets. This calling
+convention is supported primarily for compatibility with existing code. Users
+seeking register parameters should use the ``regparm`` attribute, which does
+not require callee-cleanup. See the documentation for `__fastcall`_ on MSDN.
+
+.. _`__fastcall`: http://msdn.microsoft.com/en-us/library/6xa169sk.aspx
+ }];
+}
+
+def ThisCallDocs : Documentation {
+ let Category = DocCatCallingConvs;
+ let Content = [{
+On 32-bit x86 targets, this attribute changes the calling convention of a
+function to use ECX for the first parameter (typically the implicit ``this``
+parameter of C++ methods) and clear parameters off of the stack on return. This
+convention does not support variadic calls or unprototyped functions in C, and
+has no effect on x86_64 targets. See the documentation for `__thiscall`_ on
+MSDN.
+
+.. _`__thiscall`: http://msdn.microsoft.com/en-us/library/ek8tkfbw.aspx
+ }];
+}
+
+def VectorCallDocs : Documentation {
+ let Category = DocCatCallingConvs;
+ let Content = [{
+On 32-bit x86 *and* x86_64 targets, this attribute changes the calling
+convention of a function to pass vector parameters in SSE registers.
+
+On 32-bit x86 targets, this calling convention is similar to ``__fastcall``.
+The first two integer parameters are passed in ECX and EDX. Subsequent integer
+parameters are passed in memory, and callee clears the stack. On x86_64
+targets, the callee does *not* clear the stack, and integer parameters are
+passed in RCX, RDX, R8, and R9 as is done for the default Windows x64 calling
+convention.
+
+On both 32-bit x86 and x86_64 targets, vector and floating point arguments are
+passed in XMM0-XMM5. Homogenous vector aggregates of up to four elements are
+passed in sequential SSE registers if enough are available. If AVX is enabled,
+256 bit vectors are passed in YMM0-YMM5. Any vector or aggregate type that
+cannot be passed in registers for any reason is passed by reference, which
+allows the caller to align the parameter memory.
+
+See the documentation for `__vectorcall`_ on MSDN for more details.
+
+.. _`__vectorcall`: http://msdn.microsoft.com/en-us/library/dn375768.aspx
+ }];
+}
+
+def DocCatConsumed : DocumentationCategory<"Consumed Annotation Checking"> {
+ let Content = [{
+Clang supports additional attributes for checking basic resource management
+properties, specifically for unique objects that have a single owning reference.
+The following attributes are currently supported, although **the implementation
+for these annotations is currently in development and are subject to change.**
+ }];
+}
+
+def SetTypestateDocs : Documentation {
+ let Category = DocCatConsumed;
+ let Content = [{
+Annotate methods that transition an object into a new state with
+``__attribute__((set_typestate(new_state)))``. The new state must be
+unconsumed, consumed, or unknown.
+ }];
+}
+
+def CallableWhenDocs : Documentation {
+ let Category = DocCatConsumed;
+ let Content = [{
+Use ``__attribute__((callable_when(...)))`` to indicate what states a method
+may be called in. Valid states are unconsumed, consumed, or unknown. Each
+argument to this attribute must be a quoted string. E.g.:
+
+``__attribute__((callable_when("unconsumed", "unknown")))``
+ }];
+}
+
+def TestTypestateDocs : Documentation {
+ let Category = DocCatConsumed;
+ let Content = [{
+Use ``__attribute__((test_typestate(tested_state)))`` to indicate that a method
+returns true if the object is in the specified state..
+ }];
+}
+
+def ParamTypestateDocs : Documentation {
+ let Category = DocCatConsumed;
+ let Content = [{
+This attribute specifies expectations about function parameters. Calls to an
+function with annotated parameters will issue a warning if the corresponding
+argument isn't in the expected state. The attribute is also used to set the
+initial state of the parameter when analyzing the function's body.
+ }];
+}
+
+def ReturnTypestateDocs : Documentation {
+ let Category = DocCatConsumed;
+ let Content = [{
+The ``return_typestate`` attribute can be applied to functions or parameters.
+When applied to a function the attribute specifies the state of the returned
+value. The function's body is checked to ensure that it always returns a value
+in the specified state. On the caller side, values returned by the annotated
+function are initialized to the given state.
+
+When applied to a function parameter it modifies the state of an argument after
+a call to the function returns. The function's body is checked to ensure that
+the parameter is in the expected state before returning.
+ }];
+}
+
+def ConsumableDocs : Documentation {
+ let Category = DocCatConsumed;
+ let Content = [{
+Each ``class`` that uses any of the typestate annotations must first be marked
+using the ``consumable`` attribute. Failure to do so will result in a warning.
+
+This attribute accepts a single parameter that must be one of the following:
+``unknown``, ``consumed``, or ``unconsumed``.
+ }];
+}
+
+def NoSanitizeDocs : Documentation {
+ let Category = DocCatFunction;
+ let Content = [{
+Use the ``no_sanitize`` attribute on a function declaration to specify
+that a particular instrumentation or set of instrumentations should not be
+applied to that function. The attribute takes a list of string literals,
+which have the same meaning as values accepted by the ``-fno-sanitize=``
+flag. For example, ``__attribute__((no_sanitize("address", "thread")))``
+specifies that AddressSanitizer and ThreadSanitizer should not be applied
+to the function.
+
+See :ref:`Controlling Code Generation <controlling-code-generation>` for a
+full list of supported sanitizer flags.
+ }];
+}
+
+def NoSanitizeAddressDocs : Documentation {
+ let Category = DocCatFunction;
+ // This function has multiple distinct spellings, and so it requires a custom
+ // heading to be specified. The most common spelling is sufficient.
+ let Heading = "no_sanitize_address (no_address_safety_analysis, gnu::no_address_safety_analysis, gnu::no_sanitize_address)";
+ let Content = [{
+.. _langext-address_sanitizer:
+
+Use ``__attribute__((no_sanitize_address))`` on a function declaration to
+specify that address safety instrumentation (e.g. AddressSanitizer) should
+not be applied to that function.
+ }];
+}
+
+def NoSanitizeThreadDocs : Documentation {
+ let Category = DocCatFunction;
+ let Heading = "no_sanitize_thread";
+ let Content = [{
+.. _langext-thread_sanitizer:
+
+Use ``__attribute__((no_sanitize_thread))`` on a function declaration to
+specify that checks for data races on plain (non-atomic) memory accesses should
+not be inserted by ThreadSanitizer. The function is still instrumented by the
+tool to avoid false positives and provide meaningful stack traces.
+ }];
+}
+
+def NoSanitizeMemoryDocs : Documentation {
+ let Category = DocCatFunction;
+ let Heading = "no_sanitize_memory";
+ let Content = [{
+.. _langext-memory_sanitizer:
+
+Use ``__attribute__((no_sanitize_memory))`` on a function declaration to
+specify that checks for uninitialized memory should not be inserted
+(e.g. by MemorySanitizer). The function may still be instrumented by the tool
+to avoid false positives in other places.
+ }];
+}
+
+def DocCatTypeSafety : DocumentationCategory<"Type Safety Checking"> {
+ let Content = [{
+Clang supports additional attributes to enable checking type safety properties
+that can't be enforced by the C type system. Use cases include:
+
+* MPI library implementations, where these attributes enable checking that
+ the buffer type matches the passed ``MPI_Datatype``;
+* for HDF5 library there is a similar use case to MPI;
+* checking types of variadic functions' arguments for functions like
+ ``fcntl()`` and ``ioctl()``.
+
+You can detect support for these attributes with ``__has_attribute()``. For
+example:
+
+.. code-block:: c++
+
+ #if defined(__has_attribute)
+ # if __has_attribute(argument_with_type_tag) && \
+ __has_attribute(pointer_with_type_tag) && \
+ __has_attribute(type_tag_for_datatype)
+ # define ATTR_MPI_PWT(buffer_idx, type_idx) __attribute__((pointer_with_type_tag(mpi,buffer_idx,type_idx)))
+ /* ... other macros ... */
+ # endif
+ #endif
+
+ #if !defined(ATTR_MPI_PWT)
+ # define ATTR_MPI_PWT(buffer_idx, type_idx)
+ #endif
+
+ int MPI_Send(void *buf, int count, MPI_Datatype datatype /*, other args omitted */)
+ ATTR_MPI_PWT(1,3);
+ }];
+}
+
+def ArgumentWithTypeTagDocs : Documentation {
+ let Category = DocCatTypeSafety;
+ let Heading = "argument_with_type_tag";
+ let Content = [{
+Use ``__attribute__((argument_with_type_tag(arg_kind, arg_idx,
+type_tag_idx)))`` on a function declaration to specify that the function
+accepts a type tag that determines the type of some other argument.
+``arg_kind`` is an identifier that should be used when annotating all
+applicable type tags.
+
+This attribute is primarily useful for checking arguments of variadic functions
+(``pointer_with_type_tag`` can be used in most non-variadic cases).
+
+For example:
+
+.. code-block:: c++
+
+ int fcntl(int fd, int cmd, ...)
+ __attribute__(( argument_with_type_tag(fcntl,3,2) ));
+ }];
+}
+
+def PointerWithTypeTagDocs : Documentation {
+ let Category = DocCatTypeSafety;
+ let Heading = "pointer_with_type_tag";
+ let Content = [{
+Use ``__attribute__((pointer_with_type_tag(ptr_kind, ptr_idx, type_tag_idx)))``
+on a function declaration to specify that the function accepts a type tag that
+determines the pointee type of some other pointer argument.
+
+For example:
+
+.. code-block:: c++
+
+ int MPI_Send(void *buf, int count, MPI_Datatype datatype /*, other args omitted */)
+ __attribute__(( pointer_with_type_tag(mpi,1,3) ));
+ }];
+}
+
+def TypeTagForDatatypeDocs : Documentation {
+ let Category = DocCatTypeSafety;
+ let Content = [{
+Clang supports annotating type tags of two forms.
+
+* **Type tag that is an expression containing a reference to some declared
+ identifier.** Use ``__attribute__((type_tag_for_datatype(kind, type)))`` on a
+ declaration with that identifier:
+
+ .. code-block:: c++
+
+ extern struct mpi_datatype mpi_datatype_int
+ __attribute__(( type_tag_for_datatype(mpi,int) ));
+ #define MPI_INT ((MPI_Datatype) &mpi_datatype_int)
+
+* **Type tag that is an integral literal.** Introduce a ``static const``
+ variable with a corresponding initializer value and attach
+ ``__attribute__((type_tag_for_datatype(kind, type)))`` on that declaration,
+ for example:
+
+ .. code-block:: c++
+
+ #define MPI_INT ((MPI_Datatype) 42)
+ static const MPI_Datatype mpi_datatype_int
+ __attribute__(( type_tag_for_datatype(mpi,int) )) = 42
+
+The attribute also accepts an optional third argument that determines how the
+expression is compared to the type tag. There are two supported flags:
+
+* ``layout_compatible`` will cause types to be compared according to
+ layout-compatibility rules (C++11 [class.mem] p 17, 18). This is
+ implemented to support annotating types like ``MPI_DOUBLE_INT``.
+
+ For example:
+
+ .. code-block:: c++
+
+ /* In mpi.h */
+ struct internal_mpi_double_int { double d; int i; };
+ extern struct mpi_datatype mpi_datatype_double_int
+ __attribute__(( type_tag_for_datatype(mpi, struct internal_mpi_double_int, layout_compatible) ));
+
+ #define MPI_DOUBLE_INT ((MPI_Datatype) &mpi_datatype_double_int)
+
+ /* In user code */
+ struct my_pair { double a; int b; };
+ struct my_pair *buffer;
+ MPI_Send(buffer, 1, MPI_DOUBLE_INT /*, ... */); // no warning
+
+ struct my_int_pair { int a; int b; }
+ struct my_int_pair *buffer2;
+ MPI_Send(buffer2, 1, MPI_DOUBLE_INT /*, ... */); // warning: actual buffer element
+ // type 'struct my_int_pair'
+ // doesn't match specified MPI_Datatype
+
+* ``must_be_null`` specifies that the expression should be a null pointer
+ constant, for example:
+
+ .. code-block:: c++
+
+ /* In mpi.h */
+ extern struct mpi_datatype mpi_datatype_null
+ __attribute__(( type_tag_for_datatype(mpi, void, must_be_null) ));
+
+ #define MPI_DATATYPE_NULL ((MPI_Datatype) &mpi_datatype_null)
+
+ /* In user code */
+ MPI_Send(buffer, 1, MPI_DATATYPE_NULL /*, ... */); // warning: MPI_DATATYPE_NULL
+ // was specified but buffer
+ // is not a null pointer
+ }];
+}
+
+def FlattenDocs : Documentation {
+ let Category = DocCatFunction;
+ let Content = [{
+The ``flatten`` attribute causes calls within the attributed function to
+be inlined unless it is impossible to do so, for example if the body of the
+callee is unavailable or if the callee has the ``noinline`` attribute.
+ }];
+}
+
+def FormatDocs : Documentation {
+ let Category = DocCatFunction;
+ let Content = [{
+
+Clang supports the ``format`` attribute, which indicates that the function
+accepts a ``printf`` or ``scanf``-like format string and corresponding
+arguments or a ``va_list`` that contains these arguments.
+
+Please see `GCC documentation about format attribute
+<http://gcc.gnu.org/onlinedocs/gcc/Function-Attributes.html>`_ to find details
+about attribute syntax.
+
+Clang implements two kinds of checks with this attribute.
+
+#. Clang checks that the function with the ``format`` attribute is called with
+ a format string that uses format specifiers that are allowed, and that
+ arguments match the format string. This is the ``-Wformat`` warning, it is
+ on by default.
+
+#. Clang checks that the format string argument is a literal string. This is
+ the ``-Wformat-nonliteral`` warning, it is off by default.
+
+ Clang implements this mostly the same way as GCC, but there is a difference
+ for functions that accept a ``va_list`` argument (for example, ``vprintf``).
+ GCC does not emit ``-Wformat-nonliteral`` warning for calls to such
+ functions. Clang does not warn if the format string comes from a function
+ parameter, where the function is annotated with a compatible attribute,
+ otherwise it warns. For example:
+
+ .. code-block:: c
+
+ __attribute__((__format__ (__scanf__, 1, 3)))
+ void foo(const char* s, char *buf, ...) {
+ va_list ap;
+ va_start(ap, buf);
+
+ vprintf(s, ap); // warning: format string is not a string literal
+ }
+
+ In this case we warn because ``s`` contains a format string for a
+ ``scanf``-like function, but it is passed to a ``printf``-like function.
+
+ If the attribute is removed, clang still warns, because the format string is
+ not a string literal.
+
+ Another example:
+
+ .. code-block:: c
+
+ __attribute__((__format__ (__printf__, 1, 3)))
+ void foo(const char* s, char *buf, ...) {
+ va_list ap;
+ va_start(ap, buf);
+
+ vprintf(s, ap); // warning
+ }
+
+ In this case Clang does not warn because the format string ``s`` and
+ the corresponding arguments are annotated. If the arguments are
+ incorrect, the caller of ``foo`` will receive a warning.
+ }];
+}
+
+def AlignValueDocs : Documentation {
+ let Category = DocCatType;
+ let Content = [{
+The align_value attribute can be added to the typedef of a pointer type or the
+declaration of a variable of pointer or reference type. It specifies that the
+pointer will point to, or the reference will bind to, only objects with at
+least the provided alignment. This alignment value must be some positive power
+of 2.
+
+ .. code-block:: c
+
+ typedef double * aligned_double_ptr __attribute__((align_value(64)));
+ void foo(double & x __attribute__((align_value(128)),
+ aligned_double_ptr y) { ... }
+
+If the pointer value does not have the specified alignment at runtime, the
+behavior of the program is undefined.
+ }];
+}
+
+def FlagEnumDocs : Documentation {
+ let Category = DocCatType;
+ let Content = [{
+This attribute can be added to an enumerator to signal to the compiler that it
+is intended to be used as a flag type. This will cause the compiler to assume
+that the range of the type includes all of the values that you can get by
+manipulating bits of the enumerator when issuing warnings.
+ }];
+}
+
+def MSInheritanceDocs : Documentation {
+ let Category = DocCatType;
+ let Heading = "__single_inhertiance, __multiple_inheritance, __virtual_inheritance";
+ let Content = [{
+This collection of keywords is enabled under ``-fms-extensions`` and controls
+the pointer-to-member representation used on ``*-*-win32`` targets.
+
+The ``*-*-win32`` targets utilize a pointer-to-member representation which
+varies in size and alignment depending on the definition of the underlying
+class.
+
+However, this is problematic when a forward declaration is only available and
+no definition has been made yet. In such cases, Clang is forced to utilize the
+most general representation that is available to it.
+
+These keywords make it possible to use a pointer-to-member representation other
+than the most general one regardless of whether or not the definition will ever
+be present in the current translation unit.
+
+This family of keywords belong between the ``class-key`` and ``class-name``:
+
+.. code-block:: c++
+
+ struct __single_inheritance S;
+ int S::*i;
+ struct S {};
+
+This keyword can be applied to class templates but only has an effect when used
+on full specializations:
+
+.. code-block:: c++
+
+ template <typename T, typename U> struct __single_inheritance A; // warning: inheritance model ignored on primary template
+ template <typename T> struct __multiple_inheritance A<T, T>; // warning: inheritance model ignored on partial specialization
+ template <> struct __single_inheritance A<int, float>;
+
+Note that choosing an inheritance model less general than strictly necessary is
+an error:
+
+.. code-block:: c++
+
+ struct __multiple_inheritance S; // error: inheritance model does not match definition
+ int S::*i;
+ struct S {};
+}];
+}
+
+def MSNoVTableDocs : Documentation {
+ let Category = DocCatType;
+ let Content = [{
+This attribute can be added to a class declaration or definition to signal to
+the compiler that constructors and destructors will not reference the virtual
+function table. It is only supported when using the Microsoft C++ ABI.
+ }];
+}
+
+def OptnoneDocs : Documentation {
+ let Category = DocCatFunction;
+ let Content = [{
+The ``optnone`` attribute suppresses essentially all optimizations
+on a function or method, regardless of the optimization level applied to
+the compilation unit as a whole. This is particularly useful when you
+need to debug a particular function, but it is infeasible to build the
+entire application without optimization. Avoiding optimization on the
+specified function can improve the quality of the debugging information
+for that function.
+
+This attribute is incompatible with the ``always_inline`` and ``minsize``
+attributes.
+ }];
+}
+
+def LoopHintDocs : Documentation {
+ let Category = DocCatStmt;
+ let Heading = "#pragma clang loop";
+ let Content = [{
+The ``#pragma clang loop`` directive allows loop optimization hints to be
+specified for the subsequent loop. The directive allows vectorization,
+interleaving, and unrolling to be enabled or disabled. Vector width as well
+as interleave and unrolling count can be manually specified. See
+`language extensions
+<http://clang.llvm.org/docs/LanguageExtensions.html#extensions-for-loop-hint-optimizations>`_
+for details.
+ }];
+}
+
+def UnrollHintDocs : Documentation {
+ let Category = DocCatStmt;
+ let Heading = "#pragma unroll, #pragma nounroll";
+ let Content = [{
+Loop unrolling optimization hints can be specified with ``#pragma unroll`` and
+``#pragma nounroll``. The pragma is placed immediately before a for, while,
+do-while, or c++11 range-based for loop.
+
+Specifying ``#pragma unroll`` without a parameter directs the loop unroller to
+attempt to fully unroll the loop if the trip count is known at compile time and
+attempt to partially unroll the loop if the trip count is not known at compile
+time:
+
+.. code-block:: c++
+
+ #pragma unroll
+ for (...) {
+ ...
+ }
+
+Specifying the optional parameter, ``#pragma unroll _value_``, directs the
+unroller to unroll the loop ``_value_`` times. The parameter may optionally be
+enclosed in parentheses:
+
+.. code-block:: c++
+
+ #pragma unroll 16
+ for (...) {
+ ...
+ }
+
+ #pragma unroll(16)
+ for (...) {
+ ...
+ }
+
+Specifying ``#pragma nounroll`` indicates that the loop should not be unrolled:
+
+.. code-block:: c++
+
+ #pragma nounroll
+ for (...) {
+ ...
+ }
+
+``#pragma unroll`` and ``#pragma unroll _value_`` have identical semantics to
+``#pragma clang loop unroll(full)`` and
+``#pragma clang loop unroll_count(_value_)`` respectively. ``#pragma nounroll``
+is equivalent to ``#pragma clang loop unroll(disable)``. See
+`language extensions
+<http://clang.llvm.org/docs/LanguageExtensions.html#extensions-for-loop-hint-optimizations>`_
+for further details including limitations of the unroll hints.
+ }];
+}
+
+def DocOpenCLAddressSpaces : DocumentationCategory<"OpenCL Address Spaces"> {
+ let Content = [{
+The address space qualifier may be used to specify the region of memory that is
+used to allocate the object. OpenCL supports the following address spaces:
+__generic(generic), __global(global), __local(local), __private(private),
+__constant(constant).
+
+ .. code-block:: c
+
+ __constant int c = ...;
+
+ __generic int* foo(global int* g) {
+ __local int* l;
+ private int p;
+ ...
+ return l;
+ }
+
+More details can be found in the OpenCL C language Spec v2.0, Section 6.5.
+ }];
+}
+
+def OpenCLAddressSpaceGenericDocs : Documentation {
+ let Category = DocOpenCLAddressSpaces;
+ let Content = [{
+The generic address space attribute is only available with OpenCL v2.0 and later.
+It can be used with pointer types. Variables in global and local scope and
+function parameters in non-kernel functions can have the generic address space
+type attribute. It is intended to be a placeholder for any other address space
+except for '__constant' in OpenCL code which can be used with multiple address
+spaces.
+ }];
+}
+
+def OpenCLAddressSpaceConstantDocs : Documentation {
+ let Category = DocOpenCLAddressSpaces;
+ let Content = [{
+The constant address space attribute signals that an object is located in
+a constant (non-modifiable) memory region. It is available to all work items.
+Any type can be annotated with the constant address space attribute. Objects
+with the constant address space qualifier can be declared in any scope and must
+have an initializer.
+ }];
+}
+
+def OpenCLAddressSpaceGlobalDocs : Documentation {
+ let Category = DocOpenCLAddressSpaces;
+ let Content = [{
+The global address space attribute specifies that an object is allocated in
+global memory, which is accessible by all work items. The content stored in this
+memory area persists between kernel executions. Pointer types to the global
+address space are allowed as function parameters or local variables. Starting
+with OpenCL v2.0, the global address space can be used with global (program
+scope) variables and static local variable as well.
+ }];
+}
+
+def OpenCLAddressSpaceLocalDocs : Documentation {
+ let Category = DocOpenCLAddressSpaces;
+ let Content = [{
+The local address space specifies that an object is allocated in the local (work
+group) memory area, which is accessible to all work items in the same work
+group. The content stored in this memory region is not accessible after
+the kernel execution ends. In a kernel function scope, any variable can be in
+the local address space. In other scopes, only pointer types to the local address
+space are allowed. Local address space variables cannot have an initializer.
+ }];
+}
+
+def OpenCLAddressSpacePrivateDocs : Documentation {
+ let Category = DocOpenCLAddressSpaces;
+ let Content = [{
+The private address space specifies that an object is allocated in the private
+(work item) memory. Other work items cannot access the same memory area and its
+content is destroyed after work item execution ends. Local variables can be
+declared in the private address space. Function arguments are always in the
+private address space. Kernel function arguments of a pointer or an array type
+cannot point to the private address space.
+ }];
+}
+
+def NullabilityDocs : DocumentationCategory<"Nullability Attributes"> {
+ let Content = [{
+Whether a particular pointer may be "null" is an important concern when working with pointers in the C family of languages. The various nullability attributes indicate whether a particular pointer can be null or not, which makes APIs more expressive and can help static analysis tools identify bugs involving null pointers. Clang supports several kinds of nullability attributes: the ``nonnull`` and ``returns_nonnull`` attributes indicate which function or method parameters and result types can never be null, while nullability type qualifiers indicate which pointer types can be null (``_Nullable``) or cannot be null (``_Nonnull``).
+
+The nullability (type) qualifiers express whether a value of a given pointer type can be null (the ``_Nullable`` qualifier), doesn't have a defined meaning for null (the ``_Nonnull`` qualifier), or for which the purpose of null is unclear (the ``_Null_unspecified`` qualifier). Because nullability qualifiers are expressed within the type system, they are more general than the ``nonnull`` and ``returns_nonnull`` attributes, allowing one to express (for example) a nullable pointer to an array of nonnull pointers. Nullability qualifiers are written to the right of the pointer to which they apply. For example:
+
+ .. code-block:: c
+
+ // No meaningful result when 'ptr' is null (here, it happens to be undefined behavior).
+ int fetch(int * _Nonnull ptr) { return *ptr; }
+
+ // 'ptr' may be null.
+ int fetch_or_zero(int * _Nullable ptr) {
+ return ptr ? *ptr : 0;
+ }
+
+ // A nullable pointer to non-null pointers to const characters.
+ const char *join_strings(const char * _Nonnull * _Nullable strings, unsigned n);
+
+In Objective-C, there is an alternate spelling for the nullability qualifiers that can be used in Objective-C methods and properties using context-sensitive, non-underscored keywords. For example:
+
+ .. code-block:: objective-c
+
+ @interface NSView : NSResponder
+ - (nullable NSView *)ancestorSharedWithView:(nonnull NSView *)aView;
+ @property (assign, nullable) NSView *superview;
+ @property (readonly, nonnull) NSArray *subviews;
+ @end
+ }];
+}
+
+def TypeNonNullDocs : Documentation {
+ let Category = NullabilityDocs;
+ let Content = [{
+The ``_Nonnull`` nullability qualifier indicates that null is not a meaningful value for a value of the ``_Nonnull`` pointer type. For example, given a declaration such as:
+
+ .. code-block:: c
+
+ int fetch(int * _Nonnull ptr);
+
+a caller of ``fetch`` should not provide a null value, and the compiler will produce a warning if it sees a literal null value passed to ``fetch``. Note that, unlike the declaration attribute ``nonnull``, the presence of ``_Nonnull`` does not imply that passing null is undefined behavior: ``fetch`` is free to consider null undefined behavior or (perhaps for backward-compatibility reasons) defensively handle null.
+ }];
+}
+
+def TypeNullableDocs : Documentation {
+ let Category = NullabilityDocs;
+ let Content = [{
+The ``_Nullable`` nullability qualifier indicates that a value of the ``_Nullable`` pointer type can be null. For example, given:
+
+ .. code-block:: c
+
+ int fetch_or_zero(int * _Nullable ptr);
+
+a caller of ``fetch_or_zero`` can provide null.
+ }];
+}
+
+def TypeNullUnspecifiedDocs : Documentation {
+ let Category = NullabilityDocs;
+ let Content = [{
+The ``_Null_unspecified`` nullability qualifier indicates that neither the ``_Nonnull`` nor ``_Nullable`` qualifiers make sense for a particular pointer type. It is used primarily to indicate that the role of null with specific pointers in a nullability-annotated header is unclear, e.g., due to overly-complex implementations or historical factors with a long-lived API.
+ }];
+}
+
+def NonNullDocs : Documentation {
+ let Category = NullabilityDocs;
+ let Content = [{
+The ``nonnull`` attribute indicates that some function parameters must not be null, and can be used in several different ways. It's original usage (`from GCC <https://gcc.gnu.org/onlinedocs/gcc/Common-Function-Attributes.html#Common-Function-Attributes>`_) is as a function (or Objective-C method) attribute that specifies which parameters of the function are nonnull in a comma-separated list. For example:
+
+ .. code-block:: c
+
+ extern void * my_memcpy (void *dest, const void *src, size_t len)
+ __attribute__((nonnull (1, 2)));
+
+Here, the ``nonnull`` attribute indicates that parameters 1 and 2
+cannot have a null value. Omitting the parenthesized list of parameter indices means that all parameters of pointer type cannot be null:
+
+ .. code-block:: c
+
+ extern void * my_memcpy (void *dest, const void *src, size_t len)
+ __attribute__((nonnull));
+
+Clang also allows the ``nonnull`` attribute to be placed directly on a function (or Objective-C method) parameter, eliminating the need to specify the parameter index ahead of type. For example:
+
+ .. code-block:: c
+
+ extern void * my_memcpy (void *dest __attribute__((nonnull)),
+ const void *src __attribute__((nonnull)), size_t len);
+
+Note that the ``nonnull`` attribute indicates that passing null to a non-null parameter is undefined behavior, which the optimizer may take advantage of to, e.g., remove null checks. The ``_Nonnull`` type qualifier indicates that a pointer cannot be null in a more general manner (because it is part of the type system) and does not imply undefined behavior, making it more widely applicable.
+ }];
+}
+
+def ReturnsNonNullDocs : Documentation {
+ let Category = NullabilityDocs;
+ let Content = [{
+The ``returns_nonnull`` attribute indicates that a particular function (or Objective-C method) always returns a non-null pointer. For example, a particular system ``malloc`` might be defined to terminate a process when memory is not available rather than returning a null pointer:
+
+ .. code-block:: c
+
+ extern void * malloc (size_t size) __attribute__((returns_nonnull));
+
+The ``returns_nonnull`` attribute implies that returning a null pointer is undefined behavior, which the optimizer may take advantage of. The ``_Nonnull`` type qualifier indicates that a pointer cannot be null in a more general manner (because it is part of the type system) and does not imply undefined behavior, making it more widely applicable
+}];
+}
+
+def NoAliasDocs : Documentation {
+ let Category = DocCatFunction;
+ let Content = [{
+The ``noalias`` attribute indicates that the only memory accesses inside
+function are loads and stores from objects pointed to by its pointer-typed
+arguments, with arbitrary offsets.
+ }];
+}
+
+def NotTailCalledDocs : Documentation {
+ let Category = DocCatFunction;
+ let Content = [{
+The ``not_tail_called`` attribute prevents tail-call optimization on statically bound calls. It has no effect on indirect calls. Virtual functions, objective-c methods, and functions marked as ``always_inline`` cannot be marked as ``not_tail_called``.
+
+For example, it prevents tail-call optimization in the following case:
+
+ .. code-block: c
+
+ int __attribute__((not_tail_called)) foo1(int);
+
+ int foo2(int a) {
+ return foo1(a); // No tail-call optimization on direct calls.
+ }
+
+However, it doesn't prevent tail-call optimization in this case:
+
+ .. code-block: c
+
+ int __attribute__((not_tail_called)) foo1(int);
+
+ int foo2(int a) {
+ int (*fn)(int) = &foo1;
+
+ // not_tail_called has no effect on an indirect call even if the call can be
+ // resolved at compile time.
+ return (*fn)(a);
+ }
+
+Marking virtual functions as ``not_tail_called`` is an error:
+
+ .. code-block: c++
+
+ class Base {
+ public:
+ // not_tail_called on a virtual function is an error.
+ [[clang::not_tail_called]] virtual int foo1();
+
+ virtual int foo2();
+
+ // Non-virtual functions can be marked ``not_tail_called``.
+ [[clang::not_tail_called]] int foo3();
+ };
+
+ class Derived1 : public Base {
+ public:
+ int foo1() override;
+
+ // not_tail_called on a virtual function is an error.
+ [[clang::not_tail_called]] int foo2() override;
+ };
+ }];
+}
+
+def InternalLinkageDocs : Documentation {
+ let Category = DocCatFunction;
+ let Content = [{
+The ``internal_linkage`` attribute changes the linkage type of the declaration to internal.
+This is similar to C-style ``static``, but can be used on classes and class methods. When applied to a class definition,
+this attribute affects all methods and static data members of that class.
+This can be used to contain the ABI of a C++ library by excluding unwanted class methods from the export tables.
+ }];
+}
+
+def DisableTailCallsDocs : Documentation {
+ let Category = DocCatFunction;
+ let Content = [{
+The ``disable_tail_calls`` attribute instructs the backend to not perform tail call optimization inside the marked function.
+
+For example:
+
+ .. code-block:: c
+
+ int callee(int);
+
+ int foo(int a) __attribute__((disable_tail_calls)) {
+ return callee(a); // This call is not tail-call optimized.
+ }
+
+Marking virtual functions as ``disable_tail_calls`` is legal.
+
+ .. code-block: c++
+
+ int callee(int);
+
+ class Base {
+ public:
+ [[clang::disable_tail_calls]] virtual int foo1() {
+ return callee(); // This call is not tail-call optimized.
+ }
+ };
+
+ class Derived1 : public Base {
+ public:
+ int foo1() override {
+ return callee(); // This call is tail-call optimized.
+ }
+ };
+
+ }];
+}
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..f0b0a64
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Basic/AttrKinds.h
@@ -0,0 +1,34 @@
+//===----- 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.
+//
+//===----------------------------------------------------------------------===//
+///
+/// \file
+/// \brief Defines the clang::attr::Kind enum.
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_BASIC_ATTRKINDS_H
+#define LLVM_CLANG_BASIC_ATTRKINDS_H
+
+namespace clang {
+
+namespace attr {
+
+// \brief A list of all the recognized kinds of attributes.
+enum Kind {
+#define ATTR(X) X,
+#define LAST_INHERITABLE_ATTR(X) X, LAST_INHERITABLE = X,
+#define LAST_INHERITABLE_PARAM_ATTR(X) X, LAST_INHERITABLE_PARAM = 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/Attributes.h b/contrib/llvm/tools/clang/include/clang/Basic/Attributes.h
new file mode 100644
index 0000000..a2b8684
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Basic/Attributes.h
@@ -0,0 +1,39 @@
+//===--- Attributes.h - Attributes header -----------------------*- 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_BASIC_ATTRIBUTES_H
+#define LLVM_CLANG_BASIC_ATTRIBUTES_H
+
+#include "clang/Basic/LangOptions.h"
+#include "clang/Basic/TargetInfo.h"
+
+namespace clang {
+
+class IdentifierInfo;
+
+enum class AttrSyntax {
+ /// Is the identifier known as a GNU-style attribute?
+ GNU,
+ /// Is the identifier known as a __declspec-style attribute?
+ Declspec,
+ // Is the identifier known as a C++-style attribute?
+ CXX,
+ // Is the identifier known as a pragma attribute?
+ Pragma
+};
+
+/// \brief Return the version number associated with the attribute if we
+/// recognize and implement the attribute specified by the given information.
+int hasAttribute(AttrSyntax Syntax, const IdentifierInfo *Scope,
+ const IdentifierInfo *Attr, const TargetInfo &Target,
+ const LangOptions &LangOpts);
+
+} // end namespace clang
+
+#endif // LLVM_CLANG_BASIC_ATTRIBUTES_H
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..4f474eb
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Basic/Builtins.def
@@ -0,0 +1,1257 @@
+//===--- 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
+// h -> half
+// f -> float
+// d -> double
+// z -> size_t
+// F -> constant CFString
+// G -> id
+// H -> SEL
+// M -> struct objc_super
+// a -> __builtin_va_list
+// A -> "reference" to __builtin_va_list
+// V -> Vector, followed by the number of elements and the base type.
+// E -> ext_vector, followed by the number of elements and the base type.
+// X -> _Complex, followed by the base type.
+// Y -> ptrdiff_t
+// P -> FILE
+// J -> jmp_buf
+// SJ -> sigjmp_buf
+// K -> ucontext_t
+// p -> pid_t
+// . -> "...". 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)
+// W -> int64_t
+// 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, if no address
+// space is specified than any address space will be accepted)
+// & -> 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
+// t -> signature is meaningless, use custom typechecking
+// 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.
+// i -> this is a runtime library implemented function without the
+// '__builtin_' prefix. It will be implemented in compiler-rt or libgcc.
+// 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
+// j -> returns_twice (like setjmp)
+// u -> arguments are not evaluated for their side-effects
+// FIXME: gcc has nonnull
+
+#if defined(BUILTIN) && !defined(LIBBUILTIN)
+# define LIBBUILTIN(ID, TYPE, ATTRS, HEADER, BUILTIN_LANG) BUILTIN(ID, TYPE, ATTRS)
+#endif
+
+#if defined(BUILTIN) && !defined(LANGBUILTIN)
+# define LANGBUILTIN(ID, TYPE, ATTRS, 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*" , "Fn")
+BUILTIN(__builtin_frexpf, "ffi*" , "Fn")
+BUILTIN(__builtin_frexpl, "LdLdi*", "Fn")
+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_labs , "LiLi" , "Fnc")
+BUILTIN(__builtin_llabs, "LLiLLi", "Fnc")
+BUILTIN(__builtin_ldexp , "ddi" , "Fnc")
+BUILTIN(__builtin_ldexpf, "ffi" , "Fnc")
+BUILTIN(__builtin_ldexpl, "LdLdi", "Fnc")
+BUILTIN(__builtin_modf , "ddd*" , "Fn")
+BUILTIN(__builtin_modff, "fff*" , "Fn")
+BUILTIN(__builtin_modfl, "LdLdLd*", "Fn")
+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 , "ddLd", "Fnc")
+BUILTIN(__builtin_nexttowardf, "ffLd", "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*", "Fn")
+BUILTIN(__builtin_remquof, "fffi*", "Fn")
+BUILTIN(__builtin_remquol, "LdLdLdi*", "Fn")
+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.", "Fnc")
+BUILTIN(__builtin_isgreaterequal, "i.", "Fnc")
+BUILTIN(__builtin_isless , "i.", "Fnc")
+BUILTIN(__builtin_islessequal , "i.", "Fnc")
+BUILTIN(__builtin_islessgreater , "i.", "Fnc")
+BUILTIN(__builtin_isunordered , "i.", "Fnc")
+
+// Unary FP classification
+BUILTIN(__builtin_fpclassify, "iiiii.", "Fnc")
+BUILTIN(__builtin_isfinite, "i.", "Fnc")
+BUILTIN(__builtin_isinf, "i.", "Fnc")
+BUILTIN(__builtin_isinf_sign, "i.", "Fnc")
+BUILTIN(__builtin_isnan, "i.", "Fnc")
+BUILTIN(__builtin_isnormal, "i.", "Fnc")
+
+// FP signbit builtins
+BUILTIN(__builtin_signbit, "i.", "Fnc")
+BUILTIN(__builtin_signbitf, "if", "Fnc")
+BUILTIN(__builtin_signbitl, "iLd", "Fnc")
+
+// Builtins for arithmetic.
+BUILTIN(__builtin_clzs , "iUs" , "nc")
+BUILTIN(__builtin_clz , "iUi" , "nc")
+BUILTIN(__builtin_clzl , "iULi" , "nc")
+BUILTIN(__builtin_clzll, "iULLi", "nc")
+// TODO: int clzimax(uintmax_t)
+BUILTIN(__builtin_ctzs , "iUs" , "nc")
+BUILTIN(__builtin_ctz , "iUi" , "nc")
+BUILTIN(__builtin_ctzl , "iULi" , "nc")
+BUILTIN(__builtin_ctzll, "iULLi", "nc")
+// TODO: int ctzimax(uintmax_t)
+BUILTIN(__builtin_ffs , "ii" , "Fnc")
+BUILTIN(__builtin_ffsl , "iLi" , "Fnc")
+BUILTIN(__builtin_ffsll, "iLLi", "Fnc")
+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_bswap16, "UsUs", "nc")
+BUILTIN(__builtin_bswap32, "UiUi", "nc")
+BUILTIN(__builtin_bswap64, "ULLiULLi", "nc")
+
+// Random GCC builtins
+BUILTIN(__builtin_constant_p, "i.", "nctu")
+BUILTIN(__builtin_classify_type, "i.", "nctu")
+BUILTIN(__builtin___CFStringMakeConstantString, "FC*cC*", "nc")
+BUILTIN(__builtin___NSStringMakeConstantString, "FC*cC*", "nc")
+BUILTIN(__builtin_va_start, "vA.", "nt")
+BUILTIN(__builtin_va_end, "vA", "n")
+BUILTIN(__builtin_va_copy, "vAA", "n")
+BUILTIN(__builtin_stdarg_start, "vA.", "n")
+BUILTIN(__builtin_assume_aligned, "v*vC*z.", "nc")
+BUILTIN(__builtin_bcmp, "iv*v*z", "Fn")
+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___clear_cache, "vc*c*", "n")
+BUILTIN(__builtin_flt_rounds, "i", "nc")
+BUILTIN(__builtin_setjmp, "iv**", "j")
+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, "zvC*i", "nu")
+BUILTIN(__builtin___memcpy_chk, "v*v*vC*zz", "nF")
+BUILTIN(__builtin___memccpy_chk, "v*v*vC*izz", "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___strlcat_chk, "zc*cC*zz", "nF")
+BUILTIN(__builtin___strlcpy_chk, "zc*cC*zz", "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_unpredictable, "LiLi" , "nc")
+BUILTIN(__builtin_expect, "LiLiLi" , "nc")
+BUILTIN(__builtin_prefetch, "vvC*.", "nc")
+BUILTIN(__builtin_readcyclecounter, "ULLi", "n")
+BUILTIN(__builtin_trap, "v", "nr")
+BUILTIN(__builtin_debugtrap, "v", "n")
+BUILTIN(__builtin_unreachable, "v", "nr")
+BUILTIN(__builtin_shufflevector, "v." , "nc")
+BUILTIN(__builtin_convertvector, "v." , "nct")
+BUILTIN(__builtin_alloca, "v*z" , "Fn")
+BUILTIN(__builtin_call_with_static_chain, "v.", "nt")
+
+// "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.", "t")
+BUILTIN(__sync_fetch_and_add_1, "ccD*c.", "nt")
+BUILTIN(__sync_fetch_and_add_2, "ssD*s.", "nt")
+BUILTIN(__sync_fetch_and_add_4, "iiD*i.", "nt")
+BUILTIN(__sync_fetch_and_add_8, "LLiLLiD*LLi.", "nt")
+BUILTIN(__sync_fetch_and_add_16, "LLLiLLLiD*LLLi.", "nt")
+
+BUILTIN(__sync_fetch_and_sub, "v.", "t")
+BUILTIN(__sync_fetch_and_sub_1, "ccD*c.", "nt")
+BUILTIN(__sync_fetch_and_sub_2, "ssD*s.", "nt")
+BUILTIN(__sync_fetch_and_sub_4, "iiD*i.", "nt")
+BUILTIN(__sync_fetch_and_sub_8, "LLiLLiD*LLi.", "nt")
+BUILTIN(__sync_fetch_and_sub_16, "LLLiLLLiD*LLLi.", "nt")
+
+BUILTIN(__sync_fetch_and_or, "v.", "t")
+BUILTIN(__sync_fetch_and_or_1, "ccD*c.", "nt")
+BUILTIN(__sync_fetch_and_or_2, "ssD*s.", "nt")
+BUILTIN(__sync_fetch_and_or_4, "iiD*i.", "nt")
+BUILTIN(__sync_fetch_and_or_8, "LLiLLiD*LLi.", "nt")
+BUILTIN(__sync_fetch_and_or_16, "LLLiLLLiD*LLLi.", "nt")
+
+BUILTIN(__sync_fetch_and_and, "v.", "t")
+BUILTIN(__sync_fetch_and_and_1, "ccD*c.", "tn")
+BUILTIN(__sync_fetch_and_and_2, "ssD*s.", "tn")
+BUILTIN(__sync_fetch_and_and_4, "iiD*i.", "tn")
+BUILTIN(__sync_fetch_and_and_8, "LLiLLiD*LLi.", "tn")
+BUILTIN(__sync_fetch_and_and_16, "LLLiLLLiD*LLLi.", "tn")
+
+BUILTIN(__sync_fetch_and_xor, "v.", "t")
+BUILTIN(__sync_fetch_and_xor_1, "ccD*c.", "tn")
+BUILTIN(__sync_fetch_and_xor_2, "ssD*s.", "tn")
+BUILTIN(__sync_fetch_and_xor_4, "iiD*i.", "tn")
+BUILTIN(__sync_fetch_and_xor_8, "LLiLLiD*LLi.", "tn")
+BUILTIN(__sync_fetch_and_xor_16, "LLLiLLLiD*LLLi.", "tn")
+
+BUILTIN(__sync_fetch_and_nand, "v.", "t")
+BUILTIN(__sync_fetch_and_nand_1, "ccD*c.", "tn")
+BUILTIN(__sync_fetch_and_nand_2, "ssD*s.", "tn")
+BUILTIN(__sync_fetch_and_nand_4, "iiD*i.", "tn")
+BUILTIN(__sync_fetch_and_nand_8, "LLiLLiD*LLi.", "tn")
+BUILTIN(__sync_fetch_and_nand_16, "LLLiLLLiD*LLLi.", "tn")
+
+BUILTIN(__sync_add_and_fetch, "v.", "t")
+BUILTIN(__sync_add_and_fetch_1, "ccD*c.", "tn")
+BUILTIN(__sync_add_and_fetch_2, "ssD*s.", "tn")
+BUILTIN(__sync_add_and_fetch_4, "iiD*i.", "tn")
+BUILTIN(__sync_add_and_fetch_8, "LLiLLiD*LLi.", "tn")
+BUILTIN(__sync_add_and_fetch_16, "LLLiLLLiD*LLLi.", "tn")
+
+BUILTIN(__sync_sub_and_fetch, "v.", "t")
+BUILTIN(__sync_sub_and_fetch_1, "ccD*c.", "tn")
+BUILTIN(__sync_sub_and_fetch_2, "ssD*s.", "tn")
+BUILTIN(__sync_sub_and_fetch_4, "iiD*i.", "tn")
+BUILTIN(__sync_sub_and_fetch_8, "LLiLLiD*LLi.", "tn")
+BUILTIN(__sync_sub_and_fetch_16, "LLLiLLLiD*LLLi.", "tn")
+
+BUILTIN(__sync_or_and_fetch, "v.", "t")
+BUILTIN(__sync_or_and_fetch_1, "ccD*c.", "tn")
+BUILTIN(__sync_or_and_fetch_2, "ssD*s.", "tn")
+BUILTIN(__sync_or_and_fetch_4, "iiD*i.", "tn")
+BUILTIN(__sync_or_and_fetch_8, "LLiLLiD*LLi.", "tn")
+BUILTIN(__sync_or_and_fetch_16, "LLLiLLLiD*LLLi.", "tn")
+
+BUILTIN(__sync_and_and_fetch, "v.", "t")
+BUILTIN(__sync_and_and_fetch_1, "ccD*c.", "tn")
+BUILTIN(__sync_and_and_fetch_2, "ssD*s.", "tn")
+BUILTIN(__sync_and_and_fetch_4, "iiD*i.", "tn")
+BUILTIN(__sync_and_and_fetch_8, "LLiLLiD*LLi.", "tn")
+BUILTIN(__sync_and_and_fetch_16, "LLLiLLLiD*LLLi.", "tn")
+
+BUILTIN(__sync_xor_and_fetch, "v.", "t")
+BUILTIN(__sync_xor_and_fetch_1, "ccD*c.", "tn")
+BUILTIN(__sync_xor_and_fetch_2, "ssD*s.", "tn")
+BUILTIN(__sync_xor_and_fetch_4, "iiD*i.", "tn")
+BUILTIN(__sync_xor_and_fetch_8, "LLiLLiD*LLi.", "tn")
+BUILTIN(__sync_xor_and_fetch_16, "LLLiLLLiD*LLLi.", "tn")
+
+BUILTIN(__sync_nand_and_fetch, "v.", "t")
+BUILTIN(__sync_nand_and_fetch_1, "ccD*c.", "tn")
+BUILTIN(__sync_nand_and_fetch_2, "ssD*s.", "tn")
+BUILTIN(__sync_nand_and_fetch_4, "iiD*i.", "tn")
+BUILTIN(__sync_nand_and_fetch_8, "LLiLLiD*LLi.", "tn")
+BUILTIN(__sync_nand_and_fetch_16, "LLLiLLLiD*LLLi.", "tn")
+
+BUILTIN(__sync_bool_compare_and_swap, "v.", "t")
+BUILTIN(__sync_bool_compare_and_swap_1, "bcD*cc.", "tn")
+BUILTIN(__sync_bool_compare_and_swap_2, "bsD*ss.", "tn")
+BUILTIN(__sync_bool_compare_and_swap_4, "biD*ii.", "tn")
+BUILTIN(__sync_bool_compare_and_swap_8, "bLLiD*LLiLLi.", "tn")
+BUILTIN(__sync_bool_compare_and_swap_16, "bLLLiD*LLLiLLLi.", "tn")
+
+BUILTIN(__sync_val_compare_and_swap, "v.", "t")
+BUILTIN(__sync_val_compare_and_swap_1, "ccD*cc.", "tn")
+BUILTIN(__sync_val_compare_and_swap_2, "ssD*ss.", "tn")
+BUILTIN(__sync_val_compare_and_swap_4, "iiD*ii.", "tn")
+BUILTIN(__sync_val_compare_and_swap_8, "LLiLLiD*LLiLLi.", "tn")
+BUILTIN(__sync_val_compare_and_swap_16, "LLLiLLLiD*LLLiLLLi.", "tn")
+
+BUILTIN(__sync_lock_test_and_set, "v.", "t")
+BUILTIN(__sync_lock_test_and_set_1, "ccD*c.", "tn")
+BUILTIN(__sync_lock_test_and_set_2, "ssD*s.", "tn")
+BUILTIN(__sync_lock_test_and_set_4, "iiD*i.", "tn")
+BUILTIN(__sync_lock_test_and_set_8, "LLiLLiD*LLi.", "tn")
+BUILTIN(__sync_lock_test_and_set_16, "LLLiLLLiD*LLLi.", "tn")
+
+BUILTIN(__sync_lock_release, "v.", "t")
+BUILTIN(__sync_lock_release_1, "vcD*.", "tn")
+BUILTIN(__sync_lock_release_2, "vsD*.", "tn")
+BUILTIN(__sync_lock_release_4, "viD*.", "tn")
+BUILTIN(__sync_lock_release_8, "vLLiD*.", "tn")
+BUILTIN(__sync_lock_release_16, "vLLLiD*.", "tn")
+
+BUILTIN(__sync_swap, "v.", "t")
+BUILTIN(__sync_swap_1, "ccD*c.", "tn")
+BUILTIN(__sync_swap_2, "ssD*s.", "tn")
+BUILTIN(__sync_swap_4, "iiD*i.", "tn")
+BUILTIN(__sync_swap_8, "LLiLLiD*LLi.", "tn")
+BUILTIN(__sync_swap_16, "LLLiLLLiD*LLLi.", "tn")
+
+// Some of our atomics builtins are handled by AtomicExpr rather than
+// as normal builtin CallExprs. This macro is used for such builtins.
+#ifndef ATOMIC_BUILTIN
+#define ATOMIC_BUILTIN(ID, TYPE, ATTRS) BUILTIN(ID, TYPE, ATTRS)
+#endif
+
+// C11 _Atomic operations for <stdatomic.h>.
+ATOMIC_BUILTIN(__c11_atomic_init, "v.", "t")
+ATOMIC_BUILTIN(__c11_atomic_load, "v.", "t")
+ATOMIC_BUILTIN(__c11_atomic_store, "v.", "t")
+ATOMIC_BUILTIN(__c11_atomic_exchange, "v.", "t")
+ATOMIC_BUILTIN(__c11_atomic_compare_exchange_strong, "v.", "t")
+ATOMIC_BUILTIN(__c11_atomic_compare_exchange_weak, "v.", "t")
+ATOMIC_BUILTIN(__c11_atomic_fetch_add, "v.", "t")
+ATOMIC_BUILTIN(__c11_atomic_fetch_sub, "v.", "t")
+ATOMIC_BUILTIN(__c11_atomic_fetch_and, "v.", "t")
+ATOMIC_BUILTIN(__c11_atomic_fetch_or, "v.", "t")
+ATOMIC_BUILTIN(__c11_atomic_fetch_xor, "v.", "t")
+BUILTIN(__c11_atomic_thread_fence, "vi", "n")
+BUILTIN(__c11_atomic_signal_fence, "vi", "n")
+BUILTIN(__c11_atomic_is_lock_free, "iz", "n")
+
+// GNU atomic builtins.
+ATOMIC_BUILTIN(__atomic_load, "v.", "t")
+ATOMIC_BUILTIN(__atomic_load_n, "v.", "t")
+ATOMIC_BUILTIN(__atomic_store, "v.", "t")
+ATOMIC_BUILTIN(__atomic_store_n, "v.", "t")
+ATOMIC_BUILTIN(__atomic_exchange, "v.", "t")
+ATOMIC_BUILTIN(__atomic_exchange_n, "v.", "t")
+ATOMIC_BUILTIN(__atomic_compare_exchange, "v.", "t")
+ATOMIC_BUILTIN(__atomic_compare_exchange_n, "v.", "t")
+ATOMIC_BUILTIN(__atomic_fetch_add, "v.", "t")
+ATOMIC_BUILTIN(__atomic_fetch_sub, "v.", "t")
+ATOMIC_BUILTIN(__atomic_fetch_and, "v.", "t")
+ATOMIC_BUILTIN(__atomic_fetch_or, "v.", "t")
+ATOMIC_BUILTIN(__atomic_fetch_xor, "v.", "t")
+ATOMIC_BUILTIN(__atomic_fetch_nand, "v.", "t")
+ATOMIC_BUILTIN(__atomic_add_fetch, "v.", "t")
+ATOMIC_BUILTIN(__atomic_sub_fetch, "v.", "t")
+ATOMIC_BUILTIN(__atomic_and_fetch, "v.", "t")
+ATOMIC_BUILTIN(__atomic_or_fetch, "v.", "t")
+ATOMIC_BUILTIN(__atomic_xor_fetch, "v.", "t")
+ATOMIC_BUILTIN(__atomic_nand_fetch, "v.", "t")
+BUILTIN(__atomic_test_and_set, "bvD*i", "n")
+BUILTIN(__atomic_clear, "vvD*i", "n")
+BUILTIN(__atomic_thread_fence, "vi", "n")
+BUILTIN(__atomic_signal_fence, "vi", "n")
+BUILTIN(__atomic_always_lock_free, "izvCD*", "n")
+BUILTIN(__atomic_is_lock_free, "izvCD*", "n")
+
+#undef ATOMIC_BUILTIN
+
+// Non-overloaded atomic builtins.
+BUILTIN(__sync_synchronize, "v.", "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. These are only active with -fms-extensions.
+LANGBUILTIN(_alloca, "v*z", "n", ALL_MS_LANGUAGES)
+LANGBUILTIN(__assume, "vb", "n", ALL_MS_LANGUAGES)
+LANGBUILTIN(__debugbreak, "v", "n", ALL_MS_LANGUAGES)
+LANGBUILTIN(__exception_code, "ULi", "n", ALL_MS_LANGUAGES)
+LANGBUILTIN(_exception_code, "ULi", "n", ALL_MS_LANGUAGES)
+LANGBUILTIN(__exception_info, "v*", "n", ALL_MS_LANGUAGES)
+LANGBUILTIN(_exception_info, "v*", "n", ALL_MS_LANGUAGES)
+LANGBUILTIN(__abnormal_termination, "i", "n", ALL_MS_LANGUAGES)
+LANGBUILTIN(_abnormal_termination, "i", "n", ALL_MS_LANGUAGES)
+LANGBUILTIN(__GetExceptionInfo, "v*.", "ntu", ALL_MS_LANGUAGES)
+LANGBUILTIN(_InterlockedCompareExchange, "LiLiD*LiLi", "n", ALL_MS_LANGUAGES)
+LANGBUILTIN(_InterlockedCompareExchangePointer, "v*v*D*v*v*", "n", ALL_MS_LANGUAGES)
+LANGBUILTIN(_InterlockedDecrement, "LiLiD*", "n", ALL_MS_LANGUAGES)
+LANGBUILTIN(_InterlockedExchangeAdd, "LiLiD*Li", "n", ALL_MS_LANGUAGES)
+LANGBUILTIN(_InterlockedExchange, "LiLiD*Li", "n", ALL_MS_LANGUAGES)
+LANGBUILTIN(_InterlockedExchangePointer, "v*v*D*v*", "n", ALL_MS_LANGUAGES)
+LANGBUILTIN(_InterlockedIncrement, "LiLiD*", "n", ALL_MS_LANGUAGES)
+LANGBUILTIN(__noop, "i.", "n", ALL_MS_LANGUAGES)
+LANGBUILTIN(__readfsdword, "ULiULi", "n", ALL_MS_LANGUAGES)
+LANGBUILTIN(__va_start, "vc**.", "nt", ALL_MS_LANGUAGES)
+
+// Microsoft library builtins.
+LIBBUILTIN(_setjmpex, "iJ", "fj", "setjmpex.h", ALL_MS_LANGUAGES)
+
+// 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(memcmp, "ivC*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(strcmp, "icC*cC*", "f", "string.h", ALL_LANGUAGES)
+LIBBUILTIN(strncmp, "icC*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*R.", "fs:0:", "stdio.h", ALL_LANGUAGES)
+LIBBUILTIN(fscanf, "iP*RcC*R.", "fs:1:", "stdio.h", ALL_LANGUAGES)
+LIBBUILTIN(sscanf, "icC*RcC*R.", "fs:1:", "stdio.h", ALL_LANGUAGES)
+LIBBUILTIN(vscanf, "icC*Ra", "fS:0:", "stdio.h", ALL_LANGUAGES)
+LIBBUILTIN(vfscanf, "iP*RcC*Ra", "fS:1:", "stdio.h", ALL_LANGUAGES)
+LIBBUILTIN(vsscanf, "icC*RcC*Ra", "fS:1:", "stdio.h", ALL_LANGUAGES)
+// C99
+// In some systems setjmp is a macro that expands to _setjmp. We undefine
+// it here to avoid having two identical LIBBUILTIN entries.
+#undef setjmp
+LIBBUILTIN(setjmp, "iJ", "fj", "setjmp.h", ALL_LANGUAGES)
+LIBBUILTIN(longjmp, "vJi", "fr", "setjmp.h", ALL_LANGUAGES)
+
+// Non-C library functions, active in GNU mode only.
+// Functions with (returns_twice) attribute (marked as "j") are still active in
+// all languages, because losing this attribute would result in miscompilation
+// when these functions are used in non-GNU mode. PR16138.
+LIBBUILTIN(alloca, "v*z", "f", "stdlib.h", ALL_GNU_LANGUAGES)
+// POSIX string.h
+LIBBUILTIN(stpcpy, "c*c*cC*", "f", "string.h", ALL_GNU_LANGUAGES)
+LIBBUILTIN(stpncpy, "c*c*cC*z", "f", "string.h", ALL_GNU_LANGUAGES)
+LIBBUILTIN(strdup, "c*cC*", "f", "string.h", ALL_GNU_LANGUAGES)
+LIBBUILTIN(strndup, "c*cC*z", "f", "string.h", ALL_GNU_LANGUAGES)
+// POSIX strings.h
+LIBBUILTIN(index, "c*cC*i", "f", "strings.h", ALL_GNU_LANGUAGES)
+LIBBUILTIN(rindex, "c*cC*i", "f", "strings.h", ALL_GNU_LANGUAGES)
+LIBBUILTIN(bzero, "vv*z", "f", "strings.h", ALL_GNU_LANGUAGES)
+// In some systems str[n]casejmp is a macro that expands to _str[n]icmp.
+// We undefine then here to avoid wrong name.
+#undef strcasecmp
+#undef strncasecmp
+LIBBUILTIN(strcasecmp, "icC*cC*", "f", "strings.h", ALL_GNU_LANGUAGES)
+LIBBUILTIN(strncasecmp, "icC*cC*z", "f", "strings.h", ALL_GNU_LANGUAGES)
+// POSIX unistd.h
+LIBBUILTIN(_exit, "vi", "fr", "unistd.h", ALL_GNU_LANGUAGES)
+LIBBUILTIN(vfork, "p", "fj", "unistd.h", ALL_LANGUAGES)
+// POSIX setjmp.h
+
+LIBBUILTIN(_setjmp, "iJ", "fj", "setjmp.h", ALL_LANGUAGES)
+LIBBUILTIN(__sigsetjmp, "iSJi", "fj", "setjmp.h", ALL_LANGUAGES)
+LIBBUILTIN(sigsetjmp, "iSJi", "fj", "setjmp.h", ALL_LANGUAGES)
+LIBBUILTIN(setjmp_syscall, "iJ", "fj", "setjmp.h", ALL_LANGUAGES)
+LIBBUILTIN(savectx, "iJ", "fj", "setjmp.h", ALL_LANGUAGES)
+LIBBUILTIN(qsetjmp, "iJ", "fj", "setjmp.h", ALL_LANGUAGES)
+LIBBUILTIN(getcontext, "iK*", "fj", "setjmp.h", ALL_LANGUAGES)
+
+LIBBUILTIN(_longjmp, "vJi", "fr", "setjmp.h", ALL_GNU_LANGUAGES)
+LIBBUILTIN(siglongjmp, "vSJi", "fr", "setjmp.h", ALL_GNU_LANGUAGES)
+// non-standard but very common
+LIBBUILTIN(strlcpy, "zc*cC*z", "f", "string.h", ALL_GNU_LANGUAGES)
+LIBBUILTIN(strlcat, "zc*cC*z", "f", "string.h", ALL_GNU_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)
+// _Complex long double objc_msgSend_fp2ret(id self, SEL op, ...)
+LIBBUILTIN(objc_msgSend_fp2ret, "XLdGH.", "f", "objc/message.h", OBJC_LANG)
+// void objc_msgSend_stret (id, SEL, ...)
+LIBBUILTIN(objc_msgSend_stret, "vGH.", "f", "objc/message.h", OBJC_LANG)
+// id objc_msgSendSuper(struct objc_super *super, SEL op, ...)
+LIBBUILTIN(objc_msgSendSuper, "GM*H.", "f", "objc/message.h", OBJC_LANG)
+// void objc_msgSendSuper_stret(struct objc_super *super, SEL op, ...)
+LIBBUILTIN(objc_msgSendSuper_stret, "vM*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)
+LIBBUILTIN(objc_assign_ivar, "GGGY", "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")
+
+// void NSLog(NSString *fmt, ...)
+LIBBUILTIN(NSLog, "vG.", "fp:0:", "Foundation/NSObjCRuntime.h", OBJC_LANG)
+// void NSLogv(NSString *fmt, va_list args)
+LIBBUILTIN(NSLogv, "vGa", "fP:0:", "Foundation/NSObjCRuntime.h", OBJC_LANG)
+
+// Builtin math library functions
+LIBBUILTIN(atan2, "ddd", "fne", "math.h", ALL_LANGUAGES)
+LIBBUILTIN(atan2f, "fff", "fne", "math.h", ALL_LANGUAGES)
+LIBBUILTIN(atan2l, "LdLdLd", "fne", "math.h", ALL_LANGUAGES)
+
+LIBBUILTIN(abs, "ii", "fnc", "stdlib.h", ALL_LANGUAGES)
+LIBBUILTIN(labs, "LiLi", "fnc", "stdlib.h", ALL_LANGUAGES)
+LIBBUILTIN(llabs, "LLiLLi", "fnc", "stdlib.h", ALL_LANGUAGES)
+
+LIBBUILTIN(copysign, "ddd", "fnc", "math.h", ALL_LANGUAGES)
+LIBBUILTIN(copysignf, "fff", "fnc", "math.h", ALL_LANGUAGES)
+LIBBUILTIN(copysignl, "LdLdLd", "fnc", "math.h", ALL_LANGUAGES)
+
+LIBBUILTIN(fabs, "dd", "fnc", "math.h", ALL_LANGUAGES)
+LIBBUILTIN(fabsf, "ff", "fnc", "math.h", ALL_LANGUAGES)
+LIBBUILTIN(fabsl, "LdLd", "fnc", "math.h", ALL_LANGUAGES)
+
+LIBBUILTIN(fmod, "ddd", "fne", "math.h", ALL_LANGUAGES)
+LIBBUILTIN(fmodf, "fff", "fne", "math.h", ALL_LANGUAGES)
+LIBBUILTIN(fmodl, "LdLdLd", "fne", "math.h", ALL_LANGUAGES)
+
+LIBBUILTIN(frexp, "ddi*", "fn", "math.h", ALL_LANGUAGES)
+LIBBUILTIN(frexpf, "ffi*", "fn", "math.h", ALL_LANGUAGES)
+LIBBUILTIN(frexpl, "LdLdi*", "fn", "math.h", ALL_LANGUAGES)
+
+LIBBUILTIN(ldexp, "ddi", "fne", "math.h", ALL_LANGUAGES)
+LIBBUILTIN(ldexpf, "ffi", "fne", "math.h", ALL_LANGUAGES)
+LIBBUILTIN(ldexpl, "LdLdi", "fne", "math.h", ALL_LANGUAGES)
+
+LIBBUILTIN(modf, "ddd*", "fn", "math.h", ALL_LANGUAGES)
+LIBBUILTIN(modff, "fff*", "fn", "math.h", ALL_LANGUAGES)
+LIBBUILTIN(modfl, "LdLdLd*", "fn", "math.h", ALL_LANGUAGES)
+
+LIBBUILTIN(nan, "dcC*", "fnc", "math.h", ALL_LANGUAGES)
+LIBBUILTIN(nanf, "fcC*", "fnc", "math.h", ALL_LANGUAGES)
+LIBBUILTIN(nanl, "LdcC*", "fnc", "math.h", ALL_LANGUAGES)
+
+LIBBUILTIN(pow, "ddd", "fne", "math.h", ALL_LANGUAGES)
+LIBBUILTIN(powf, "fff", "fne", "math.h", ALL_LANGUAGES)
+LIBBUILTIN(powl, "LdLdLd", "fne", "math.h", ALL_LANGUAGES)
+
+LIBBUILTIN(acos, "dd", "fne", "math.h", ALL_LANGUAGES)
+LIBBUILTIN(acosf, "ff", "fne", "math.h", ALL_LANGUAGES)
+LIBBUILTIN(acosl, "LdLd", "fne", "math.h", ALL_LANGUAGES)
+
+LIBBUILTIN(acosh, "dd", "fne", "math.h", ALL_LANGUAGES)
+LIBBUILTIN(acoshf, "ff", "fne", "math.h", ALL_LANGUAGES)
+LIBBUILTIN(acoshl, "LdLd", "fne", "math.h", ALL_LANGUAGES)
+
+LIBBUILTIN(asin, "dd", "fne", "math.h", ALL_LANGUAGES)
+LIBBUILTIN(asinf, "ff", "fne", "math.h", ALL_LANGUAGES)
+LIBBUILTIN(asinl, "LdLd", "fne", "math.h", ALL_LANGUAGES)
+
+LIBBUILTIN(asinh, "dd", "fne", "math.h", ALL_LANGUAGES)
+LIBBUILTIN(asinhf, "ff", "fne", "math.h", ALL_LANGUAGES)
+LIBBUILTIN(asinhl, "LdLd", "fne", "math.h", ALL_LANGUAGES)
+
+LIBBUILTIN(atan, "dd", "fne", "math.h", ALL_LANGUAGES)
+LIBBUILTIN(atanf, "ff", "fne", "math.h", ALL_LANGUAGES)
+LIBBUILTIN(atanl, "LdLd", "fne", "math.h", ALL_LANGUAGES)
+
+LIBBUILTIN(atanh, "dd", "fne", "math.h", ALL_LANGUAGES)
+LIBBUILTIN(atanhf, "ff", "fne", "math.h", ALL_LANGUAGES)
+LIBBUILTIN(atanhl, "LdLd", "fne", "math.h", ALL_LANGUAGES)
+
+LIBBUILTIN(cbrt, "dd", "fne", "math.h", ALL_LANGUAGES)
+LIBBUILTIN(cbrtf, "ff", "fne", "math.h", ALL_LANGUAGES)
+LIBBUILTIN(cbrtl, "LdLd", "fne", "math.h", ALL_LANGUAGES)
+
+LIBBUILTIN(ceil, "dd", "fnc", "math.h", ALL_LANGUAGES)
+LIBBUILTIN(ceilf, "ff", "fnc", "math.h", ALL_LANGUAGES)
+LIBBUILTIN(ceill, "LdLd", "fnc", "math.h", ALL_LANGUAGES)
+
+LIBBUILTIN(cos, "dd", "fne", "math.h", ALL_LANGUAGES)
+LIBBUILTIN(cosf, "ff", "fne", "math.h", ALL_LANGUAGES)
+LIBBUILTIN(cosl, "LdLd", "fne", "math.h", ALL_LANGUAGES)
+
+LIBBUILTIN(cosh, "dd", "fne", "math.h", ALL_LANGUAGES)
+LIBBUILTIN(coshf, "ff", "fne", "math.h", ALL_LANGUAGES)
+LIBBUILTIN(coshl, "LdLd", "fne", "math.h", ALL_LANGUAGES)
+
+LIBBUILTIN(erf, "dd", "fne", "math.h", ALL_LANGUAGES)
+LIBBUILTIN(erff, "ff", "fne", "math.h", ALL_LANGUAGES)
+LIBBUILTIN(erfl, "LdLd", "fne", "math.h", ALL_LANGUAGES)
+
+LIBBUILTIN(erfc, "dd", "fne", "math.h", ALL_LANGUAGES)
+LIBBUILTIN(erfcf, "ff", "fne", "math.h", ALL_LANGUAGES)
+LIBBUILTIN(erfcl, "LdLd", "fne", "math.h", ALL_LANGUAGES)
+
+LIBBUILTIN(exp, "dd", "fne", "math.h", ALL_LANGUAGES)
+LIBBUILTIN(expf, "ff", "fne", "math.h", ALL_LANGUAGES)
+LIBBUILTIN(expl, "LdLd", "fne", "math.h", ALL_LANGUAGES)
+
+LIBBUILTIN(exp2, "dd", "fne", "math.h", ALL_LANGUAGES)
+LIBBUILTIN(exp2f, "ff", "fne", "math.h", ALL_LANGUAGES)
+LIBBUILTIN(exp2l, "LdLd", "fne", "math.h", ALL_LANGUAGES)
+
+LIBBUILTIN(expm1, "dd", "fne", "math.h", ALL_LANGUAGES)
+LIBBUILTIN(expm1f, "ff", "fne", "math.h", ALL_LANGUAGES)
+LIBBUILTIN(expm1l, "LdLd", "fne", "math.h", ALL_LANGUAGES)
+
+LIBBUILTIN(fdim, "ddd", "fne", "math.h", ALL_LANGUAGES)
+LIBBUILTIN(fdimf, "fff", "fne", "math.h", ALL_LANGUAGES)
+LIBBUILTIN(fdiml, "LdLdLd", "fne", "math.h", ALL_LANGUAGES)
+
+LIBBUILTIN(floor, "dd", "fnc", "math.h", ALL_LANGUAGES)
+LIBBUILTIN(floorf, "ff", "fnc", "math.h", ALL_LANGUAGES)
+LIBBUILTIN(floorl, "LdLd", "fnc", "math.h", ALL_LANGUAGES)
+
+LIBBUILTIN(fma, "dddd", "fne", "math.h", ALL_LANGUAGES)
+LIBBUILTIN(fmaf, "ffff", "fne", "math.h", ALL_LANGUAGES)
+LIBBUILTIN(fmal, "LdLdLdLd", "fne", "math.h", ALL_LANGUAGES)
+
+LIBBUILTIN(fmax, "ddd", "fnc", "math.h", ALL_LANGUAGES)
+LIBBUILTIN(fmaxf, "fff", "fnc", "math.h", ALL_LANGUAGES)
+LIBBUILTIN(fmaxl, "LdLdLd", "fnc", "math.h", ALL_LANGUAGES)
+
+LIBBUILTIN(fmin, "ddd", "fnc", "math.h", ALL_LANGUAGES)
+LIBBUILTIN(fminf, "fff", "fnc", "math.h", ALL_LANGUAGES)
+LIBBUILTIN(fminl, "LdLdLd", "fnc", "math.h", ALL_LANGUAGES)
+
+LIBBUILTIN(hypot, "ddd", "fne", "math.h", ALL_LANGUAGES)
+LIBBUILTIN(hypotf, "fff", "fne", "math.h", ALL_LANGUAGES)
+LIBBUILTIN(hypotl, "LdLdLd", "fne", "math.h", ALL_LANGUAGES)
+
+LIBBUILTIN(ilogb, "id", "fne", "math.h", ALL_LANGUAGES)
+LIBBUILTIN(ilogbf, "if", "fne", "math.h", ALL_LANGUAGES)
+LIBBUILTIN(ilogbl, "iLd", "fne", "math.h", ALL_LANGUAGES)
+
+LIBBUILTIN(lgamma, "dd", "fne", "math.h", ALL_LANGUAGES)
+LIBBUILTIN(lgammaf, "ff", "fne", "math.h", ALL_LANGUAGES)
+LIBBUILTIN(lgammal, "LdLd", "fne", "math.h", ALL_LANGUAGES)
+
+LIBBUILTIN(llrint, "LLid", "fne", "math.h", ALL_LANGUAGES)
+LIBBUILTIN(llrintf, "LLif", "fne", "math.h", ALL_LANGUAGES)
+LIBBUILTIN(llrintl, "LLiLd", "fne", "math.h", ALL_LANGUAGES)
+
+LIBBUILTIN(llround, "LLid", "fne", "math.h", ALL_LANGUAGES)
+LIBBUILTIN(llroundf, "LLif", "fne", "math.h", ALL_LANGUAGES)
+LIBBUILTIN(llroundl, "LLiLd", "fne", "math.h", ALL_LANGUAGES)
+
+LIBBUILTIN(log, "dd", "fne", "math.h", ALL_LANGUAGES)
+LIBBUILTIN(logf, "ff", "fne", "math.h", ALL_LANGUAGES)
+LIBBUILTIN(logl, "LdLd", "fne", "math.h", ALL_LANGUAGES)
+
+LIBBUILTIN(log10, "dd", "fne", "math.h", ALL_LANGUAGES)
+LIBBUILTIN(log10f, "ff", "fne", "math.h", ALL_LANGUAGES)
+LIBBUILTIN(log10l, "LdLd", "fne", "math.h", ALL_LANGUAGES)
+
+LIBBUILTIN(log1p, "dd", "fne", "math.h", ALL_LANGUAGES)
+LIBBUILTIN(log1pf, "ff", "fne", "math.h", ALL_LANGUAGES)
+LIBBUILTIN(log1pl, "LdLd", "fne", "math.h", ALL_LANGUAGES)
+
+LIBBUILTIN(log2, "dd", "fne", "math.h", ALL_LANGUAGES)
+LIBBUILTIN(log2f, "ff", "fne", "math.h", ALL_LANGUAGES)
+LIBBUILTIN(log2l, "LdLd", "fne", "math.h", ALL_LANGUAGES)
+
+LIBBUILTIN(logb, "dd", "fne", "math.h", ALL_LANGUAGES)
+LIBBUILTIN(logbf, "ff", "fne", "math.h", ALL_LANGUAGES)
+LIBBUILTIN(logbl, "LdLd", "fne", "math.h", ALL_LANGUAGES)
+
+LIBBUILTIN(lrint, "Lid", "fne", "math.h", ALL_LANGUAGES)
+LIBBUILTIN(lrintf, "Lif", "fne", "math.h", ALL_LANGUAGES)
+LIBBUILTIN(lrintl, "LiLd", "fne", "math.h", ALL_LANGUAGES)
+
+LIBBUILTIN(lround, "Lid", "fne", "math.h", ALL_LANGUAGES)
+LIBBUILTIN(lroundf, "Lif", "fne", "math.h", ALL_LANGUAGES)
+LIBBUILTIN(lroundl, "LiLd", "fne", "math.h", ALL_LANGUAGES)
+
+LIBBUILTIN(nearbyint, "dd", "fnc", "math.h", ALL_LANGUAGES)
+LIBBUILTIN(nearbyintf, "ff", "fnc", "math.h", ALL_LANGUAGES)
+LIBBUILTIN(nearbyintl, "LdLd", "fnc", "math.h", ALL_LANGUAGES)
+
+LIBBUILTIN(nextafter, "ddd", "fne", "math.h", ALL_LANGUAGES)
+LIBBUILTIN(nextafterf, "fff", "fne", "math.h", ALL_LANGUAGES)
+LIBBUILTIN(nextafterl, "LdLdLd", "fne", "math.h", ALL_LANGUAGES)
+
+LIBBUILTIN(nexttoward, "ddLd", "fne", "math.h", ALL_LANGUAGES)
+LIBBUILTIN(nexttowardf, "ffLd", "fne", "math.h", ALL_LANGUAGES)
+LIBBUILTIN(nexttowardl, "LdLdLd", "fne", "math.h", ALL_LANGUAGES)
+
+LIBBUILTIN(remainder, "ddd", "fne", "math.h", ALL_LANGUAGES)
+LIBBUILTIN(remainderf, "fff", "fne", "math.h", ALL_LANGUAGES)
+LIBBUILTIN(remainderl, "LdLdLd", "fne", "math.h", ALL_LANGUAGES)
+
+LIBBUILTIN(rint, "dd", "fnc", "math.h", ALL_LANGUAGES)
+LIBBUILTIN(rintf, "ff", "fnc", "math.h", ALL_LANGUAGES)
+LIBBUILTIN(rintl, "LdLd", "fnc", "math.h", ALL_LANGUAGES)
+
+LIBBUILTIN(round, "dd", "fnc", "math.h", ALL_LANGUAGES)
+LIBBUILTIN(roundf, "ff", "fnc", "math.h", ALL_LANGUAGES)
+LIBBUILTIN(roundl, "LdLd", "fnc", "math.h", ALL_LANGUAGES)
+
+LIBBUILTIN(scalbln, "ddLi", "fne", "math.h", ALL_LANGUAGES)
+LIBBUILTIN(scalblnf, "ffLi", "fne", "math.h", ALL_LANGUAGES)
+LIBBUILTIN(scalblnl, "LdLdLi", "fne", "math.h", ALL_LANGUAGES)
+
+LIBBUILTIN(scalbn, "ddi", "fne", "math.h", ALL_LANGUAGES)
+LIBBUILTIN(scalbnf, "ffi", "fne", "math.h", ALL_LANGUAGES)
+LIBBUILTIN(scalbnl, "LdLdi", "fne", "math.h", ALL_LANGUAGES)
+
+LIBBUILTIN(sin, "dd", "fne", "math.h", ALL_LANGUAGES)
+LIBBUILTIN(sinf, "ff", "fne", "math.h", ALL_LANGUAGES)
+LIBBUILTIN(sinl, "LdLd", "fne", "math.h", ALL_LANGUAGES)
+
+LIBBUILTIN(sinh, "dd", "fne", "math.h", ALL_LANGUAGES)
+LIBBUILTIN(sinhf, "ff", "fne", "math.h", ALL_LANGUAGES)
+LIBBUILTIN(sinhl, "LdLd", "fne", "math.h", ALL_LANGUAGES)
+
+LIBBUILTIN(sqrt, "dd", "fne", "math.h", ALL_LANGUAGES)
+LIBBUILTIN(sqrtf, "ff", "fne", "math.h", ALL_LANGUAGES)
+LIBBUILTIN(sqrtl, "LdLd", "fne", "math.h", ALL_LANGUAGES)
+
+LIBBUILTIN(tan, "dd", "fne", "math.h", ALL_LANGUAGES)
+LIBBUILTIN(tanf, "ff", "fne", "math.h", ALL_LANGUAGES)
+LIBBUILTIN(tanl, "LdLd", "fne", "math.h", ALL_LANGUAGES)
+
+LIBBUILTIN(tanh, "dd", "fne", "math.h", ALL_LANGUAGES)
+LIBBUILTIN(tanhf, "ff", "fne", "math.h", ALL_LANGUAGES)
+LIBBUILTIN(tanhl, "LdLd", "fne", "math.h", ALL_LANGUAGES)
+
+LIBBUILTIN(tgamma, "dd", "fne", "math.h", ALL_LANGUAGES)
+LIBBUILTIN(tgammaf, "ff", "fne", "math.h", ALL_LANGUAGES)
+LIBBUILTIN(tgammal, "LdLd", "fne", "math.h", ALL_LANGUAGES)
+
+LIBBUILTIN(trunc, "dd", "fnc", "math.h", ALL_LANGUAGES)
+LIBBUILTIN(truncf, "ff", "fnc", "math.h", ALL_LANGUAGES)
+LIBBUILTIN(truncl, "LdLd", "fnc", "math.h", ALL_LANGUAGES)
+
+LIBBUILTIN(cabs, "dXd", "fnc", "complex.h", ALL_LANGUAGES)
+LIBBUILTIN(cabsf, "fXf", "fnc", "complex.h", ALL_LANGUAGES)
+LIBBUILTIN(cabsl, "LdXLd", "fnc", "complex.h", ALL_LANGUAGES)
+
+LIBBUILTIN(cacos, "XdXd", "fnc", "complex.h", ALL_LANGUAGES)
+LIBBUILTIN(cacosf, "XfXf", "fnc", "complex.h", ALL_LANGUAGES)
+LIBBUILTIN(cacosl, "XLdXLd", "fnc", "complex.h", ALL_LANGUAGES)
+
+LIBBUILTIN(cacosh, "XdXd", "fnc", "complex.h", ALL_LANGUAGES)
+LIBBUILTIN(cacoshf, "XfXf", "fnc", "complex.h", ALL_LANGUAGES)
+LIBBUILTIN(cacoshl, "XLdXLd", "fnc", "complex.h", ALL_LANGUAGES)
+
+LIBBUILTIN(carg, "dXd", "fnc", "complex.h", ALL_LANGUAGES)
+LIBBUILTIN(cargf, "fXf", "fnc", "complex.h", ALL_LANGUAGES)
+LIBBUILTIN(cargl, "LdXLd", "fnc", "complex.h", ALL_LANGUAGES)
+
+LIBBUILTIN(casin, "XdXd", "fnc", "complex.h", ALL_LANGUAGES)
+LIBBUILTIN(casinf, "XfXf", "fnc", "complex.h", ALL_LANGUAGES)
+LIBBUILTIN(casinl, "XLdXLd", "fnc", "complex.h", ALL_LANGUAGES)
+
+LIBBUILTIN(casinh, "XdXd", "fnc", "complex.h", ALL_LANGUAGES)
+LIBBUILTIN(casinhf, "XfXf", "fnc", "complex.h", ALL_LANGUAGES)
+LIBBUILTIN(casinhl, "XLdXLd", "fnc", "complex.h", ALL_LANGUAGES)
+
+LIBBUILTIN(catan, "XdXd", "fnc", "complex.h", ALL_LANGUAGES)
+LIBBUILTIN(catanf, "XfXf", "fnc", "complex.h", ALL_LANGUAGES)
+LIBBUILTIN(catanl, "XLdXLd", "fnc", "complex.h", ALL_LANGUAGES)
+
+LIBBUILTIN(catanh, "XdXd", "fnc", "complex.h", ALL_LANGUAGES)
+LIBBUILTIN(catanhf, "XfXf", "fnc", "complex.h", ALL_LANGUAGES)
+LIBBUILTIN(catanhl, "XLdXLd", "fnc", "complex.h", ALL_LANGUAGES)
+
+LIBBUILTIN(ccos, "XdXd", "fnc", "complex.h", ALL_LANGUAGES)
+LIBBUILTIN(ccosf, "XfXf", "fnc", "complex.h", ALL_LANGUAGES)
+LIBBUILTIN(ccosl, "XLdXLd", "fnc", "complex.h", ALL_LANGUAGES)
+
+LIBBUILTIN(ccosh, "XdXd", "fnc", "complex.h", ALL_LANGUAGES)
+LIBBUILTIN(ccoshf, "XfXf", "fnc", "complex.h", ALL_LANGUAGES)
+LIBBUILTIN(ccoshl, "XLdXLd", "fnc", "complex.h", ALL_LANGUAGES)
+
+LIBBUILTIN(cexp, "XdXd", "fnc", "complex.h", ALL_LANGUAGES)
+LIBBUILTIN(cexpf, "XfXf", "fnc", "complex.h", ALL_LANGUAGES)
+LIBBUILTIN(cexpl, "XLdXLd", "fnc", "complex.h", ALL_LANGUAGES)
+
+LIBBUILTIN(cimag, "dXd", "fnc", "complex.h", ALL_LANGUAGES)
+LIBBUILTIN(cimagf, "fXf", "fnc", "complex.h", ALL_LANGUAGES)
+LIBBUILTIN(cimagl, "LdXLd", "fnc", "complex.h", ALL_LANGUAGES)
+
+LIBBUILTIN(conj, "XdXd", "fnc", "complex.h", ALL_LANGUAGES)
+LIBBUILTIN(conjf, "XfXf", "fnc", "complex.h", ALL_LANGUAGES)
+LIBBUILTIN(conjl, "XLdXLd", "fnc", "complex.h", ALL_LANGUAGES)
+
+LIBBUILTIN(clog, "XdXd", "fnc", "complex.h", ALL_LANGUAGES)
+LIBBUILTIN(clogf, "XfXf", "fnc", "complex.h", ALL_LANGUAGES)
+LIBBUILTIN(clogl, "XLdXLd", "fnc", "complex.h", ALL_LANGUAGES)
+
+LIBBUILTIN(cproj, "XdXd", "fnc", "complex.h", ALL_LANGUAGES)
+LIBBUILTIN(cprojf, "XfXf", "fnc", "complex.h", ALL_LANGUAGES)
+LIBBUILTIN(cprojl, "XLdXLd", "fnc", "complex.h", ALL_LANGUAGES)
+
+LIBBUILTIN(cpow, "XdXdXd", "fnc", "complex.h", ALL_LANGUAGES)
+LIBBUILTIN(cpowf, "XfXfXf", "fnc", "complex.h", ALL_LANGUAGES)
+LIBBUILTIN(cpowl, "XLdXLdXLd", "fnc", "complex.h", ALL_LANGUAGES)
+
+LIBBUILTIN(creal, "dXd", "fnc", "complex.h", ALL_LANGUAGES)
+LIBBUILTIN(crealf, "fXf", "fnc", "complex.h", ALL_LANGUAGES)
+LIBBUILTIN(creall, "LdXLd", "fnc", "complex.h", ALL_LANGUAGES)
+
+LIBBUILTIN(csin, "XdXd", "fnc", "complex.h", ALL_LANGUAGES)
+LIBBUILTIN(csinf, "XfXf", "fnc", "complex.h", ALL_LANGUAGES)
+LIBBUILTIN(csinl, "XLdXLd", "fnc", "complex.h", ALL_LANGUAGES)
+
+LIBBUILTIN(csinh, "XdXd", "fnc", "complex.h", ALL_LANGUAGES)
+LIBBUILTIN(csinhf, "XfXf", "fnc", "complex.h", ALL_LANGUAGES)
+LIBBUILTIN(csinhl, "XLdXLd", "fnc", "complex.h", ALL_LANGUAGES)
+
+LIBBUILTIN(csqrt, "XdXd", "fnc", "complex.h", ALL_LANGUAGES)
+LIBBUILTIN(csqrtf, "XfXf", "fnc", "complex.h", ALL_LANGUAGES)
+LIBBUILTIN(csqrtl, "XLdXLd", "fnc", "complex.h", ALL_LANGUAGES)
+
+LIBBUILTIN(ctan, "XdXd", "fnc", "complex.h", ALL_LANGUAGES)
+LIBBUILTIN(ctanf, "XfXf", "fnc", "complex.h", ALL_LANGUAGES)
+LIBBUILTIN(ctanl, "XLdXLd", "fnc", "complex.h", ALL_LANGUAGES)
+
+LIBBUILTIN(ctanh, "XdXd", "fnc", "complex.h", ALL_LANGUAGES)
+LIBBUILTIN(ctanhf, "XfXf", "fnc", "complex.h", ALL_LANGUAGES)
+LIBBUILTIN(ctanhl, "XLdXLd", "fnc", "complex.h", ALL_LANGUAGES)
+
+// __sinpi and friends are OS X specific library functions, but otherwise much
+// like the standard (non-complex) sin (etc).
+LIBBUILTIN(__sinpi, "dd", "fne", "math.h", ALL_LANGUAGES)
+LIBBUILTIN(__sinpif, "ff", "fne", "math.h", ALL_LANGUAGES)
+
+LIBBUILTIN(__cospi, "dd", "fne", "math.h", ALL_LANGUAGES)
+LIBBUILTIN(__cospif, "ff", "fne", "math.h", ALL_LANGUAGES)
+
+LIBBUILTIN(__tanpi, "dd", "fne", "math.h", ALL_LANGUAGES)
+LIBBUILTIN(__tanpif, "ff", "fne", "math.h", ALL_LANGUAGES)
+
+// Similarly, __exp10 is OS X only
+LIBBUILTIN(__exp10, "dd", "fne", "math.h", ALL_LANGUAGES)
+LIBBUILTIN(__exp10f, "ff", "fne", "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.
+
+// Annotation function
+BUILTIN(__builtin_annotation, "v.", "tn")
+
+// Invariants
+BUILTIN(__builtin_assume, "vb", "n")
+
+// Multiprecision Arithmetic Builtins.
+BUILTIN(__builtin_addcb, "UcUcCUcCUcCUc*", "n")
+BUILTIN(__builtin_addcs, "UsUsCUsCUsCUs*", "n")
+BUILTIN(__builtin_addc, "UiUiCUiCUiCUi*", "n")
+BUILTIN(__builtin_addcl, "ULiULiCULiCULiCULi*", "n")
+BUILTIN(__builtin_addcll, "ULLiULLiCULLiCULLiCULLi*", "n")
+BUILTIN(__builtin_subcb, "UcUcCUcCUcCUc*", "n")
+BUILTIN(__builtin_subcs, "UsUsCUsCUsCUs*", "n")
+BUILTIN(__builtin_subc, "UiUiCUiCUiCUi*", "n")
+BUILTIN(__builtin_subcl, "ULiULiCULiCULiCULi*", "n")
+BUILTIN(__builtin_subcll, "ULLiULLiCULLiCULLiCULLi*", "n")
+
+// Checked Arithmetic Builtins for Security.
+BUILTIN(__builtin_add_overflow, "v.", "nt")
+BUILTIN(__builtin_sub_overflow, "v.", "nt")
+BUILTIN(__builtin_mul_overflow, "v.", "nt")
+BUILTIN(__builtin_uadd_overflow, "bUiCUiCUi*", "n")
+BUILTIN(__builtin_uaddl_overflow, "bULiCULiCULi*", "n")
+BUILTIN(__builtin_uaddll_overflow, "bULLiCULLiCULLi*", "n")
+BUILTIN(__builtin_usub_overflow, "bUiCUiCUi*", "n")
+BUILTIN(__builtin_usubl_overflow, "bULiCULiCULi*", "n")
+BUILTIN(__builtin_usubll_overflow, "bULLiCULLiCULLi*", "n")
+BUILTIN(__builtin_umul_overflow, "bUiCUiCUi*", "n")
+BUILTIN(__builtin_umull_overflow, "bULiCULiCULi*", "n")
+BUILTIN(__builtin_umulll_overflow, "bULLiCULLiCULLi*", "n")
+BUILTIN(__builtin_sadd_overflow, "bSiCSiCSi*", "n")
+BUILTIN(__builtin_saddl_overflow, "bSLiCSLiCSLi*", "n")
+BUILTIN(__builtin_saddll_overflow, "bSLLiCSLLiCSLLi*", "n")
+BUILTIN(__builtin_ssub_overflow, "bSiCSiCSi*", "n")
+BUILTIN(__builtin_ssubl_overflow, "bSLiCSLiCSLi*", "n")
+BUILTIN(__builtin_ssubll_overflow, "bSLLiCSLLiCSLLi*", "n")
+BUILTIN(__builtin_smul_overflow, "bSiCSiCSi*", "n")
+BUILTIN(__builtin_smull_overflow, "bSLiCSLiCSLi*", "n")
+BUILTIN(__builtin_smulll_overflow, "bSLLiCSLLiCSLLi*", "n")
+
+// Clang builtins (not available in GCC).
+BUILTIN(__builtin_addressof, "v*v&", "nct")
+BUILTIN(__builtin_operator_new, "v*z", "c")
+BUILTIN(__builtin_operator_delete, "vv*", "n")
+
+// Safestack builtins
+BUILTIN(__builtin___get_unsafe_stack_start, "v*", "Fn")
+BUILTIN(__builtin___get_unsafe_stack_ptr, "v*", "Fn")
+
+// Nontemporal loads/stores builtins
+BUILTIN(__builtin_nontemporal_store, "v.", "t")
+BUILTIN(__builtin_nontemporal_load, "v.", "t")
+
+#undef BUILTIN
+#undef LIBBUILTIN
+#undef LANGBUILTIN
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..c0a6af9
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Basic/Builtins.h
@@ -0,0 +1,220 @@
+//===--- 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.
+//
+//===----------------------------------------------------------------------===//
+///
+/// \file
+/// \brief Defines enum values for all the target-independent builtin
+/// functions.
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_BASIC_BUILTINS_H
+#define LLVM_CLANG_BASIC_BUILTINS_H
+
+#include "llvm/ADT/ArrayRef.h"
+#include <cstring>
+
+// VC++ defines 'alloca' as an object-like macro, which interferes with our
+// builtins.
+#undef alloca
+
+namespace clang {
+class TargetInfo;
+class IdentifierTable;
+class ASTContext;
+class QualType;
+class LangOptions;
+
+enum LanguageID {
+ GNU_LANG = 0x1, // builtin requires GNU mode.
+ C_LANG = 0x2, // builtin for c only.
+ CXX_LANG = 0x4, // builtin for cplusplus only.
+ OBJC_LANG = 0x8, // builtin for objective-c and objective-c++
+ MS_LANG = 0x10, // builtin requires MS mode.
+ ALL_LANGUAGES = C_LANG | CXX_LANG | OBJC_LANG, // builtin for all languages.
+ ALL_GNU_LANGUAGES = ALL_LANGUAGES | GNU_LANG, // builtin requires GNU mode.
+ ALL_MS_LANGUAGES = ALL_LANGUAGES | MS_LANG // builtin requires MS mode.
+};
+
+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 Langs;
+ const char *Features;
+};
+
+/// \brief Holds information about both target-independent and
+/// target-specific builtins, allowing easy queries by clients.
+///
+/// Builtins from an optional auxiliary target are stored in
+/// AuxTSRecords. Their IDs are shifted up by TSRecords.size() and need to
+/// be translated back with getAuxBuiltinID() before use.
+class Context {
+ llvm::ArrayRef<Info> TSRecords;
+ llvm::ArrayRef<Info> AuxTSRecords;
+
+public:
+ Context() {}
+
+ /// \brief Perform target-specific initialization
+ /// \param AuxTarget Target info to incorporate builtins from. May be nullptr.
+ void InitializeTarget(const TargetInfo &Target, const TargetInfo *AuxTarget);
+
+ /// \brief 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 Return the identifier name for the specified builtin,
+ /// e.g. "__builtin_abs".
+ const char *getName(unsigned ID) const {
+ return getRecord(ID).Name;
+ }
+
+ /// \brief Get the type descriptor string for the specified builtin.
+ const char *getTypeString(unsigned ID) const {
+ return getRecord(ID).Type;
+ }
+
+ /// \brief Return true if this function is a target-specific builtin
+ bool isTSBuiltin(unsigned ID) const {
+ return ID >= Builtin::FirstTSBuiltin;
+ }
+
+ /// \brief 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') != nullptr;
+ }
+
+ /// \brief Return true if we know this builtin never throws an exception.
+ bool isNoThrow(unsigned ID) const {
+ return strchr(getRecord(ID).Attributes, 'n') != nullptr;
+ }
+
+ /// \brief Return true if we know this builtin never returns.
+ bool isNoReturn(unsigned ID) const {
+ return strchr(getRecord(ID).Attributes, 'r') != nullptr;
+ }
+
+ /// \brief Return true if we know this builtin can return twice.
+ bool isReturnsTwice(unsigned ID) const {
+ return strchr(getRecord(ID).Attributes, 'j') != nullptr;
+ }
+
+ /// \brief Returns true if this builtin does not perform the side-effects
+ /// of its arguments.
+ bool isUnevaluated(unsigned ID) const {
+ return strchr(getRecord(ID).Attributes, 'u') != nullptr;
+ }
+
+ /// \brief 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') != nullptr;
+ }
+
+ /// \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') != nullptr;
+ }
+
+ /// \brief Determines whether this builtin is a predefined compiler-rt/libgcc
+ /// function, such as "__clear_cache", where we know the signature a
+ /// priori.
+ bool isPredefinedRuntimeFunction(unsigned ID) const {
+ return strchr(getRecord(ID).Attributes, 'i') != nullptr;
+ }
+
+ /// \brief Determines whether this builtin has custom typechecking.
+ bool hasCustomTypechecking(unsigned ID) const {
+ return strchr(getRecord(ID).Attributes, 't') != nullptr;
+ }
+
+ /// \brief Determines whether this builtin has a result or any arguments which
+ /// are pointer types.
+ bool hasPtrArgsOrResult(unsigned ID) const {
+ return strchr(getRecord(ID).Type, '*') != nullptr;
+ }
+
+ /// \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);
+
+ /// \brief 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') != nullptr;
+ }
+
+ const char *getRequiredFeatures(unsigned ID) const {
+ return getRecord(ID).Features;
+ }
+
+ /// \brief Return true if builtin ID belongs to AuxTarget.
+ bool isAuxBuiltinID(unsigned ID) const {
+ return ID >= (Builtin::FirstTSBuiltin + TSRecords.size());
+ }
+
+ /// Return real buitin ID (i.e. ID it would have furing compilation
+ /// for AuxTarget).
+ unsigned getAuxBuiltinID(unsigned ID) const { return ID - TSRecords.size(); }
+
+ /// Returns true if this is a libc/libm function without the '__builtin_'
+ /// prefix.
+ static bool isBuiltinFunc(const char *Name);
+
+private:
+ const Info &getRecord(unsigned ID) const;
+
+ /// \brief Is this builtin supported according to the given language options?
+ bool builtinIsSupported(const Builtin::Info &BuiltinInfo,
+ const LangOptions &LangOpts);
+
+ /// \brief Helper function for isPrintfLike and isScanfLike.
+ bool isLike(unsigned ID, unsigned &FormatIdx, bool &HasVAListArg,
+ const char *Fmt) const;
+};
+
+}
+
+/// \brief Kinds of BuiltinTemplateDecl.
+enum BuiltinTemplateKind : int {
+ /// \brief This names the __make_integer_seq BuiltinTemplateDecl.
+ BTK__make_integer_seq
+};
+
+} // end namespace clang
+#endif
diff --git a/contrib/llvm/tools/clang/include/clang/Basic/BuiltinsAArch64.def b/contrib/llvm/tools/clang/include/clang/Basic/BuiltinsAArch64.def
new file mode 100644
index 0000000..b440443
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Basic/BuiltinsAArch64.def
@@ -0,0 +1,65 @@
+//==- BuiltinsAArch64.def - AArch64 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 AArch64-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, "vv*v*", "i")
+
+BUILTIN(__builtin_arm_ldrex, "v.", "t")
+BUILTIN(__builtin_arm_ldaex, "v.", "t")
+BUILTIN(__builtin_arm_strex, "i.", "t")
+BUILTIN(__builtin_arm_stlex, "i.", "t")
+BUILTIN(__builtin_arm_clrex, "v", "")
+
+// Bit manipulation
+BUILTIN(__builtin_arm_rbit, "UiUi", "nc")
+BUILTIN(__builtin_arm_rbit64, "LUiLUi", "nc")
+
+// HINT
+BUILTIN(__builtin_arm_nop, "v", "")
+BUILTIN(__builtin_arm_yield, "v", "")
+BUILTIN(__builtin_arm_wfe, "v", "")
+BUILTIN(__builtin_arm_wfi, "v", "")
+BUILTIN(__builtin_arm_sev, "v", "")
+BUILTIN(__builtin_arm_sevl, "v", "")
+
+// CRC32
+BUILTIN(__builtin_arm_crc32b, "UiUiUc", "nc")
+BUILTIN(__builtin_arm_crc32cb, "UiUiUc", "nc")
+BUILTIN(__builtin_arm_crc32h, "UiUiUs", "nc")
+BUILTIN(__builtin_arm_crc32ch, "UiUiUs", "nc")
+BUILTIN(__builtin_arm_crc32w, "UiUiUi", "nc")
+BUILTIN(__builtin_arm_crc32cw, "UiUiUi", "nc")
+BUILTIN(__builtin_arm_crc32d, "UiUiLUi", "nc")
+BUILTIN(__builtin_arm_crc32cd, "UiUiLUi", "nc")
+
+// Memory barrier
+BUILTIN(__builtin_arm_dmb, "vUi", "nc")
+BUILTIN(__builtin_arm_dsb, "vUi", "nc")
+BUILTIN(__builtin_arm_isb, "vUi", "nc")
+
+// Prefetch
+BUILTIN(__builtin_arm_prefetch, "vvC*UiUiUiUi", "nc")
+
+// System Registers
+BUILTIN(__builtin_arm_rsr, "UicC*", "nc")
+BUILTIN(__builtin_arm_rsr64, "LUicC*", "nc")
+BUILTIN(__builtin_arm_rsrp, "v*cC*", "nc")
+BUILTIN(__builtin_arm_wsr, "vcC*Ui", "nc")
+BUILTIN(__builtin_arm_wsr64, "vcC*LUi", "nc")
+BUILTIN(__builtin_arm_wsrp, "vcC*vC*", "nc")
+BUILTIN(__builtin_thread_pointer, "v*", "nc")
+
+#undef BUILTIN
diff --git a/contrib/llvm/tools/clang/include/clang/Basic/BuiltinsAMDGPU.def b/contrib/llvm/tools/clang/include/clang/Basic/BuiltinsAMDGPU.def
new file mode 100644
index 0000000..bb9931f
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Basic/BuiltinsAMDGPU.def
@@ -0,0 +1,36 @@
+//==- BuiltinsAMDGPU.def - AMDGPU 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 R600-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.
+
+BUILTIN(__builtin_amdgpu_div_scale, "dddbb*", "n")
+BUILTIN(__builtin_amdgpu_div_scalef, "fffbb*", "n")
+BUILTIN(__builtin_amdgpu_div_fmas, "ddddb", "nc")
+BUILTIN(__builtin_amdgpu_div_fmasf, "ffffb", "nc")
+BUILTIN(__builtin_amdgpu_div_fixup, "dddd", "nc")
+BUILTIN(__builtin_amdgpu_div_fixupf, "ffff", "nc")
+BUILTIN(__builtin_amdgpu_trig_preop, "ddi", "nc")
+BUILTIN(__builtin_amdgpu_trig_preopf, "ffi", "nc")
+BUILTIN(__builtin_amdgpu_rcp, "dd", "nc")
+BUILTIN(__builtin_amdgpu_rcpf, "ff", "nc")
+BUILTIN(__builtin_amdgpu_rsq, "dd", "nc")
+BUILTIN(__builtin_amdgpu_rsqf, "ff", "nc")
+BUILTIN(__builtin_amdgpu_rsq_clamped, "dd", "nc")
+BUILTIN(__builtin_amdgpu_rsq_clampedf, "ff", "nc")
+BUILTIN(__builtin_amdgpu_ldexp, "ddi", "nc")
+BUILTIN(__builtin_amdgpu_ldexpf, "ffi", "nc")
+BUILTIN(__builtin_amdgpu_class, "bdi", "nc")
+BUILTIN(__builtin_amdgpu_classf, "bfi", "nc")
+
+#undef BUILTIN
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..3e8e2bf
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Basic/BuiltinsARM.def
@@ -0,0 +1,114 @@
+//===--- 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.
+
+#if defined(BUILTIN) && !defined(LANGBUILTIN)
+# define LANGBUILTIN(ID, TYPE, ATTRS, BUILTIN_LANG) BUILTIN(ID, TYPE, ATTRS)
+#endif
+
+// In libgcc
+BUILTIN(__clear_cache, "vv*v*", "i")
+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")
+
+// Bit manipulation
+BUILTIN(__builtin_arm_rbit, "UiUi", "nc")
+
+// Store and load exclusive
+BUILTIN(__builtin_arm_ldrexd, "LLUiv*", "")
+BUILTIN(__builtin_arm_strexd, "iLLUiv*", "")
+
+BUILTIN(__builtin_arm_ldrex, "v.", "t")
+BUILTIN(__builtin_arm_ldaex, "v.", "t")
+BUILTIN(__builtin_arm_strex, "i.", "t")
+BUILTIN(__builtin_arm_stlex, "i.", "t")
+BUILTIN(__builtin_arm_clrex, "v", "")
+
+// 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")
+
+// Coprocessor
+BUILTIN(__builtin_arm_mcr, "vUIiUIiUiUIiUIiUIi", "")
+BUILTIN(__builtin_arm_mcr2, "vUIiUIiUiUIiUIiUIi", "")
+BUILTIN(__builtin_arm_mrc, "UiUIiUIiUIiUIiUIi", "")
+BUILTIN(__builtin_arm_mrc2, "UiUIiUIiUIiUIiUIi", "")
+BUILTIN(__builtin_arm_cdp, "vUiUiUiUiUiUi", "")
+BUILTIN(__builtin_arm_cdp2, "vUiUiUiUiUiUi", "")
+BUILTIN(__builtin_arm_mcrr, "vUIiUIiUiUiUIi", "")
+BUILTIN(__builtin_arm_mcrr2, "vUIiUIiUiUiUIi", "")
+
+// CRC32
+BUILTIN(__builtin_arm_crc32b, "UiUiUc", "nc")
+BUILTIN(__builtin_arm_crc32cb, "UiUiUc", "nc")
+BUILTIN(__builtin_arm_crc32h, "UiUiUs", "nc")
+BUILTIN(__builtin_arm_crc32ch, "UiUiUs", "nc")
+BUILTIN(__builtin_arm_crc32w, "UiUiUi", "nc")
+BUILTIN(__builtin_arm_crc32cw, "UiUiUi", "nc")
+BUILTIN(__builtin_arm_crc32d, "UiUiLLUi", "nc")
+BUILTIN(__builtin_arm_crc32cd, "UiUiLLUi", "nc")
+
+// HINT
+BUILTIN(__builtin_arm_nop, "v", "")
+BUILTIN(__builtin_arm_yield, "v", "")
+BUILTIN(__builtin_arm_wfe, "v", "")
+BUILTIN(__builtin_arm_wfi, "v", "")
+BUILTIN(__builtin_arm_sev, "v", "")
+BUILTIN(__builtin_arm_sevl, "v", "")
+BUILTIN(__builtin_arm_dbg, "vUi", "")
+
+// Data barrier
+BUILTIN(__builtin_arm_dmb, "vUi", "nc")
+BUILTIN(__builtin_arm_dsb, "vUi", "nc")
+BUILTIN(__builtin_arm_isb, "vUi", "nc")
+
+// Prefetch
+BUILTIN(__builtin_arm_prefetch, "vvC*UiUi", "nc")
+
+// System registers (ACLE)
+BUILTIN(__builtin_arm_rsr, "UicC*", "nc")
+BUILTIN(__builtin_arm_rsr64, "LLUicC*", "nc")
+BUILTIN(__builtin_arm_rsrp, "v*cC*", "nc")
+BUILTIN(__builtin_arm_wsr, "vcC*Ui", "nc")
+BUILTIN(__builtin_arm_wsr64, "vcC*LLUi", "nc")
+BUILTIN(__builtin_arm_wsrp, "vcC*vC*", "nc")
+
+// MSVC
+LANGBUILTIN(__emit, "vIUiC", "", ALL_MS_LANGUAGES)
+
+LANGBUILTIN(__yield, "v", "", ALL_MS_LANGUAGES)
+LANGBUILTIN(__wfe, "v", "", ALL_MS_LANGUAGES)
+LANGBUILTIN(__wfi, "v", "", ALL_MS_LANGUAGES)
+LANGBUILTIN(__sev, "v", "", ALL_MS_LANGUAGES)
+LANGBUILTIN(__sevl, "v", "", ALL_MS_LANGUAGES)
+
+LANGBUILTIN(__dmb, "vUi", "nc", ALL_MS_LANGUAGES)
+LANGBUILTIN(__dsb, "vUi", "nc", ALL_MS_LANGUAGES)
+LANGBUILTIN(__isb, "vUi", "nc", ALL_MS_LANGUAGES)
+LANGBUILTIN(__ldrexd, "WiWiCD*", "", ALL_MS_LANGUAGES)
+LANGBUILTIN(_MoveFromCoprocessor, "UiIUiIUiIUiIUiIUi", "", ALL_MS_LANGUAGES)
+LANGBUILTIN(_MoveFromCoprocessor2, "UiIUiIUiIUiIUiIUi", "", ALL_MS_LANGUAGES)
+LANGBUILTIN(_MoveToCoprocessor, "vUiIUiIUiIUiIUiIUi", "", ALL_MS_LANGUAGES)
+LANGBUILTIN(_MoveToCoprocessor2, "vUiIUiIUiIUiIUiIUi", "", ALL_MS_LANGUAGES)
+
+#undef BUILTIN
+#undef LANGBUILTIN
diff --git a/contrib/llvm/tools/clang/include/clang/Basic/BuiltinsHexagon.def b/contrib/llvm/tools/clang/include/clang/Basic/BuiltinsHexagon.def
new file mode 100644
index 0000000..c071a46
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Basic/BuiltinsHexagon.def
@@ -0,0 +1,878 @@
+//===-- BuiltinsHexagon.def - Hexagon 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 Hexagon-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.
+
+// The builtins below are not autogenerated from iset.py.
+// Make sure you do not overwrite these.
+
+BUILTIN(__builtin_SI_to_SXTHI_asrh, "ii", "")
+BUILTIN(__builtin_circ_ldd, "LLi*LLi*LLi*ii", "")
+
+// The builtins above are not autogenerated from iset.py.
+// Make sure you do not overwrite these.
+
+BUILTIN(__builtin_HEXAGON_C2_cmpeq,"bii","")
+BUILTIN(__builtin_HEXAGON_C2_cmpgt,"bii","")
+BUILTIN(__builtin_HEXAGON_C2_cmpgtu,"bii","")
+BUILTIN(__builtin_HEXAGON_C2_cmpeqp,"bLLiLLi","")
+BUILTIN(__builtin_HEXAGON_C2_cmpgtp,"bLLiLLi","")
+BUILTIN(__builtin_HEXAGON_C2_cmpgtup,"bLLiLLi","")
+BUILTIN(__builtin_HEXAGON_A4_rcmpeqi,"iii","")
+BUILTIN(__builtin_HEXAGON_A4_rcmpneqi,"iii","")
+BUILTIN(__builtin_HEXAGON_A4_rcmpeq,"iii","")
+BUILTIN(__builtin_HEXAGON_A4_rcmpneq,"iii","")
+BUILTIN(__builtin_HEXAGON_C2_bitsset,"bii","")
+BUILTIN(__builtin_HEXAGON_C2_bitsclr,"bii","")
+BUILTIN(__builtin_HEXAGON_C4_nbitsset,"bii","")
+BUILTIN(__builtin_HEXAGON_C4_nbitsclr,"bii","")
+BUILTIN(__builtin_HEXAGON_C2_cmpeqi,"bii","")
+BUILTIN(__builtin_HEXAGON_C2_cmpgti,"bii","")
+BUILTIN(__builtin_HEXAGON_C2_cmpgtui,"bii","")
+BUILTIN(__builtin_HEXAGON_C2_cmpgei,"bii","")
+BUILTIN(__builtin_HEXAGON_C2_cmpgeui,"bii","")
+BUILTIN(__builtin_HEXAGON_C2_cmplt,"bii","")
+BUILTIN(__builtin_HEXAGON_C2_cmpltu,"bii","")
+BUILTIN(__builtin_HEXAGON_C2_bitsclri,"bii","")
+BUILTIN(__builtin_HEXAGON_C4_nbitsclri,"bii","")
+BUILTIN(__builtin_HEXAGON_C4_cmpneqi,"bii","")
+BUILTIN(__builtin_HEXAGON_C4_cmpltei,"bii","")
+BUILTIN(__builtin_HEXAGON_C4_cmplteui,"bii","")
+BUILTIN(__builtin_HEXAGON_C4_cmpneq,"bii","")
+BUILTIN(__builtin_HEXAGON_C4_cmplte,"bii","")
+BUILTIN(__builtin_HEXAGON_C4_cmplteu,"bii","")
+BUILTIN(__builtin_HEXAGON_C2_and,"bii","")
+BUILTIN(__builtin_HEXAGON_C2_or,"bii","")
+BUILTIN(__builtin_HEXAGON_C2_xor,"bii","")
+BUILTIN(__builtin_HEXAGON_C2_andn,"bii","")
+BUILTIN(__builtin_HEXAGON_C2_not,"bi","")
+BUILTIN(__builtin_HEXAGON_C2_orn,"bii","")
+BUILTIN(__builtin_HEXAGON_C4_and_and,"biii","")
+BUILTIN(__builtin_HEXAGON_C4_and_or,"biii","")
+BUILTIN(__builtin_HEXAGON_C4_or_and,"biii","")
+BUILTIN(__builtin_HEXAGON_C4_or_or,"biii","")
+BUILTIN(__builtin_HEXAGON_C4_and_andn,"biii","")
+BUILTIN(__builtin_HEXAGON_C4_and_orn,"biii","")
+BUILTIN(__builtin_HEXAGON_C4_or_andn,"biii","")
+BUILTIN(__builtin_HEXAGON_C4_or_orn,"biii","")
+BUILTIN(__builtin_HEXAGON_C2_pxfer_map,"bi","")
+BUILTIN(__builtin_HEXAGON_C2_any8,"bi","")
+BUILTIN(__builtin_HEXAGON_C2_all8,"bi","")
+BUILTIN(__builtin_HEXAGON_C2_vitpack,"iii","")
+BUILTIN(__builtin_HEXAGON_C2_mux,"iiii","")
+BUILTIN(__builtin_HEXAGON_C2_muxii,"iiii","")
+BUILTIN(__builtin_HEXAGON_C2_muxir,"iiii","")
+BUILTIN(__builtin_HEXAGON_C2_muxri,"iiii","")
+BUILTIN(__builtin_HEXAGON_C2_vmux,"LLiiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_C2_mask,"LLii","")
+BUILTIN(__builtin_HEXAGON_A2_vcmpbeq,"bLLiLLi","")
+BUILTIN(__builtin_HEXAGON_A4_vcmpbeqi,"bLLii","")
+BUILTIN(__builtin_HEXAGON_A4_vcmpbeq_any,"bLLiLLi","")
+BUILTIN(__builtin_HEXAGON_A2_vcmpbgtu,"bLLiLLi","")
+BUILTIN(__builtin_HEXAGON_A4_vcmpbgtui,"bLLii","")
+BUILTIN(__builtin_HEXAGON_A4_vcmpbgt,"bLLiLLi","")
+BUILTIN(__builtin_HEXAGON_A4_vcmpbgti,"bLLii","")
+BUILTIN(__builtin_HEXAGON_A4_cmpbeq,"bii","")
+BUILTIN(__builtin_HEXAGON_A4_cmpbeqi,"bii","")
+BUILTIN(__builtin_HEXAGON_A4_cmpbgtu,"bii","")
+BUILTIN(__builtin_HEXAGON_A4_cmpbgtui,"bii","")
+BUILTIN(__builtin_HEXAGON_A4_cmpbgt,"bii","")
+BUILTIN(__builtin_HEXAGON_A4_cmpbgti,"bii","")
+BUILTIN(__builtin_HEXAGON_A2_vcmpheq,"bLLiLLi","")
+BUILTIN(__builtin_HEXAGON_A2_vcmphgt,"bLLiLLi","")
+BUILTIN(__builtin_HEXAGON_A2_vcmphgtu,"bLLiLLi","")
+BUILTIN(__builtin_HEXAGON_A4_vcmpheqi,"bLLii","")
+BUILTIN(__builtin_HEXAGON_A4_vcmphgti,"bLLii","")
+BUILTIN(__builtin_HEXAGON_A4_vcmphgtui,"bLLii","")
+BUILTIN(__builtin_HEXAGON_A4_cmpheq,"bii","")
+BUILTIN(__builtin_HEXAGON_A4_cmphgt,"bii","")
+BUILTIN(__builtin_HEXAGON_A4_cmphgtu,"bii","")
+BUILTIN(__builtin_HEXAGON_A4_cmpheqi,"bii","")
+BUILTIN(__builtin_HEXAGON_A4_cmphgti,"bii","")
+BUILTIN(__builtin_HEXAGON_A4_cmphgtui,"bii","")
+BUILTIN(__builtin_HEXAGON_A2_vcmpweq,"bLLiLLi","")
+BUILTIN(__builtin_HEXAGON_A2_vcmpwgt,"bLLiLLi","")
+BUILTIN(__builtin_HEXAGON_A2_vcmpwgtu,"bLLiLLi","")
+BUILTIN(__builtin_HEXAGON_A4_vcmpweqi,"bLLii","")
+BUILTIN(__builtin_HEXAGON_A4_vcmpwgti,"bLLii","")
+BUILTIN(__builtin_HEXAGON_A4_vcmpwgtui,"bLLii","")
+BUILTIN(__builtin_HEXAGON_A4_boundscheck,"biLLi","")
+BUILTIN(__builtin_HEXAGON_A4_tlbmatch,"bLLii","")
+BUILTIN(__builtin_HEXAGON_C2_tfrpr,"ii","")
+BUILTIN(__builtin_HEXAGON_C2_tfrrp,"bi","")
+BUILTIN(__builtin_HEXAGON_C4_fastcorner9,"bii","")
+BUILTIN(__builtin_HEXAGON_C4_fastcorner9_not,"bii","")
+BUILTIN(__builtin_HEXAGON_M2_mpy_acc_hh_s0,"iiii","")
+BUILTIN(__builtin_HEXAGON_M2_mpy_acc_hh_s1,"iiii","")
+BUILTIN(__builtin_HEXAGON_M2_mpy_acc_hl_s0,"iiii","")
+BUILTIN(__builtin_HEXAGON_M2_mpy_acc_hl_s1,"iiii","")
+BUILTIN(__builtin_HEXAGON_M2_mpy_acc_lh_s0,"iiii","")
+BUILTIN(__builtin_HEXAGON_M2_mpy_acc_lh_s1,"iiii","")
+BUILTIN(__builtin_HEXAGON_M2_mpy_acc_ll_s0,"iiii","")
+BUILTIN(__builtin_HEXAGON_M2_mpy_acc_ll_s1,"iiii","")
+BUILTIN(__builtin_HEXAGON_M2_mpy_nac_hh_s0,"iiii","")
+BUILTIN(__builtin_HEXAGON_M2_mpy_nac_hh_s1,"iiii","")
+BUILTIN(__builtin_HEXAGON_M2_mpy_nac_hl_s0,"iiii","")
+BUILTIN(__builtin_HEXAGON_M2_mpy_nac_hl_s1,"iiii","")
+BUILTIN(__builtin_HEXAGON_M2_mpy_nac_lh_s0,"iiii","")
+BUILTIN(__builtin_HEXAGON_M2_mpy_nac_lh_s1,"iiii","")
+BUILTIN(__builtin_HEXAGON_M2_mpy_nac_ll_s0,"iiii","")
+BUILTIN(__builtin_HEXAGON_M2_mpy_nac_ll_s1,"iiii","")
+BUILTIN(__builtin_HEXAGON_M2_mpy_acc_sat_hh_s0,"iiii","")
+BUILTIN(__builtin_HEXAGON_M2_mpy_acc_sat_hh_s1,"iiii","")
+BUILTIN(__builtin_HEXAGON_M2_mpy_acc_sat_hl_s0,"iiii","")
+BUILTIN(__builtin_HEXAGON_M2_mpy_acc_sat_hl_s1,"iiii","")
+BUILTIN(__builtin_HEXAGON_M2_mpy_acc_sat_lh_s0,"iiii","")
+BUILTIN(__builtin_HEXAGON_M2_mpy_acc_sat_lh_s1,"iiii","")
+BUILTIN(__builtin_HEXAGON_M2_mpy_acc_sat_ll_s0,"iiii","")
+BUILTIN(__builtin_HEXAGON_M2_mpy_acc_sat_ll_s1,"iiii","")
+BUILTIN(__builtin_HEXAGON_M2_mpy_nac_sat_hh_s0,"iiii","")
+BUILTIN(__builtin_HEXAGON_M2_mpy_nac_sat_hh_s1,"iiii","")
+BUILTIN(__builtin_HEXAGON_M2_mpy_nac_sat_hl_s0,"iiii","")
+BUILTIN(__builtin_HEXAGON_M2_mpy_nac_sat_hl_s1,"iiii","")
+BUILTIN(__builtin_HEXAGON_M2_mpy_nac_sat_lh_s0,"iiii","")
+BUILTIN(__builtin_HEXAGON_M2_mpy_nac_sat_lh_s1,"iiii","")
+BUILTIN(__builtin_HEXAGON_M2_mpy_nac_sat_ll_s0,"iiii","")
+BUILTIN(__builtin_HEXAGON_M2_mpy_nac_sat_ll_s1,"iiii","")
+BUILTIN(__builtin_HEXAGON_M2_mpy_hh_s0,"iii","")
+BUILTIN(__builtin_HEXAGON_M2_mpy_hh_s1,"iii","")
+BUILTIN(__builtin_HEXAGON_M2_mpy_hl_s0,"iii","")
+BUILTIN(__builtin_HEXAGON_M2_mpy_hl_s1,"iii","")
+BUILTIN(__builtin_HEXAGON_M2_mpy_lh_s0,"iii","")
+BUILTIN(__builtin_HEXAGON_M2_mpy_lh_s1,"iii","")
+BUILTIN(__builtin_HEXAGON_M2_mpy_ll_s0,"iii","")
+BUILTIN(__builtin_HEXAGON_M2_mpy_ll_s1,"iii","")
+BUILTIN(__builtin_HEXAGON_M2_mpy_sat_hh_s0,"iii","")
+BUILTIN(__builtin_HEXAGON_M2_mpy_sat_hh_s1,"iii","")
+BUILTIN(__builtin_HEXAGON_M2_mpy_sat_hl_s0,"iii","")
+BUILTIN(__builtin_HEXAGON_M2_mpy_sat_hl_s1,"iii","")
+BUILTIN(__builtin_HEXAGON_M2_mpy_sat_lh_s0,"iii","")
+BUILTIN(__builtin_HEXAGON_M2_mpy_sat_lh_s1,"iii","")
+BUILTIN(__builtin_HEXAGON_M2_mpy_sat_ll_s0,"iii","")
+BUILTIN(__builtin_HEXAGON_M2_mpy_sat_ll_s1,"iii","")
+BUILTIN(__builtin_HEXAGON_M2_mpy_rnd_hh_s0,"iii","")
+BUILTIN(__builtin_HEXAGON_M2_mpy_rnd_hh_s1,"iii","")
+BUILTIN(__builtin_HEXAGON_M2_mpy_rnd_hl_s0,"iii","")
+BUILTIN(__builtin_HEXAGON_M2_mpy_rnd_hl_s1,"iii","")
+BUILTIN(__builtin_HEXAGON_M2_mpy_rnd_lh_s0,"iii","")
+BUILTIN(__builtin_HEXAGON_M2_mpy_rnd_lh_s1,"iii","")
+BUILTIN(__builtin_HEXAGON_M2_mpy_rnd_ll_s0,"iii","")
+BUILTIN(__builtin_HEXAGON_M2_mpy_rnd_ll_s1,"iii","")
+BUILTIN(__builtin_HEXAGON_M2_mpy_sat_rnd_hh_s0,"iii","")
+BUILTIN(__builtin_HEXAGON_M2_mpy_sat_rnd_hh_s1,"iii","")
+BUILTIN(__builtin_HEXAGON_M2_mpy_sat_rnd_hl_s0,"iii","")
+BUILTIN(__builtin_HEXAGON_M2_mpy_sat_rnd_hl_s1,"iii","")
+BUILTIN(__builtin_HEXAGON_M2_mpy_sat_rnd_lh_s0,"iii","")
+BUILTIN(__builtin_HEXAGON_M2_mpy_sat_rnd_lh_s1,"iii","")
+BUILTIN(__builtin_HEXAGON_M2_mpy_sat_rnd_ll_s0,"iii","")
+BUILTIN(__builtin_HEXAGON_M2_mpy_sat_rnd_ll_s1,"iii","")
+BUILTIN(__builtin_HEXAGON_M2_mpyd_acc_hh_s0,"LLiLLiii","")
+BUILTIN(__builtin_HEXAGON_M2_mpyd_acc_hh_s1,"LLiLLiii","")
+BUILTIN(__builtin_HEXAGON_M2_mpyd_acc_hl_s0,"LLiLLiii","")
+BUILTIN(__builtin_HEXAGON_M2_mpyd_acc_hl_s1,"LLiLLiii","")
+BUILTIN(__builtin_HEXAGON_M2_mpyd_acc_lh_s0,"LLiLLiii","")
+BUILTIN(__builtin_HEXAGON_M2_mpyd_acc_lh_s1,"LLiLLiii","")
+BUILTIN(__builtin_HEXAGON_M2_mpyd_acc_ll_s0,"LLiLLiii","")
+BUILTIN(__builtin_HEXAGON_M2_mpyd_acc_ll_s1,"LLiLLiii","")
+BUILTIN(__builtin_HEXAGON_M2_mpyd_nac_hh_s0,"LLiLLiii","")
+BUILTIN(__builtin_HEXAGON_M2_mpyd_nac_hh_s1,"LLiLLiii","")
+BUILTIN(__builtin_HEXAGON_M2_mpyd_nac_hl_s0,"LLiLLiii","")
+BUILTIN(__builtin_HEXAGON_M2_mpyd_nac_hl_s1,"LLiLLiii","")
+BUILTIN(__builtin_HEXAGON_M2_mpyd_nac_lh_s0,"LLiLLiii","")
+BUILTIN(__builtin_HEXAGON_M2_mpyd_nac_lh_s1,"LLiLLiii","")
+BUILTIN(__builtin_HEXAGON_M2_mpyd_nac_ll_s0,"LLiLLiii","")
+BUILTIN(__builtin_HEXAGON_M2_mpyd_nac_ll_s1,"LLiLLiii","")
+BUILTIN(__builtin_HEXAGON_M2_mpyd_hh_s0,"LLiii","")
+BUILTIN(__builtin_HEXAGON_M2_mpyd_hh_s1,"LLiii","")
+BUILTIN(__builtin_HEXAGON_M2_mpyd_hl_s0,"LLiii","")
+BUILTIN(__builtin_HEXAGON_M2_mpyd_hl_s1,"LLiii","")
+BUILTIN(__builtin_HEXAGON_M2_mpyd_lh_s0,"LLiii","")
+BUILTIN(__builtin_HEXAGON_M2_mpyd_lh_s1,"LLiii","")
+BUILTIN(__builtin_HEXAGON_M2_mpyd_ll_s0,"LLiii","")
+BUILTIN(__builtin_HEXAGON_M2_mpyd_ll_s1,"LLiii","")
+BUILTIN(__builtin_HEXAGON_M2_mpyd_rnd_hh_s0,"LLiii","")
+BUILTIN(__builtin_HEXAGON_M2_mpyd_rnd_hh_s1,"LLiii","")
+BUILTIN(__builtin_HEXAGON_M2_mpyd_rnd_hl_s0,"LLiii","")
+BUILTIN(__builtin_HEXAGON_M2_mpyd_rnd_hl_s1,"LLiii","")
+BUILTIN(__builtin_HEXAGON_M2_mpyd_rnd_lh_s0,"LLiii","")
+BUILTIN(__builtin_HEXAGON_M2_mpyd_rnd_lh_s1,"LLiii","")
+BUILTIN(__builtin_HEXAGON_M2_mpyd_rnd_ll_s0,"LLiii","")
+BUILTIN(__builtin_HEXAGON_M2_mpyd_rnd_ll_s1,"LLiii","")
+BUILTIN(__builtin_HEXAGON_M2_mpyu_acc_hh_s0,"iiii","")
+BUILTIN(__builtin_HEXAGON_M2_mpyu_acc_hh_s1,"iiii","")
+BUILTIN(__builtin_HEXAGON_M2_mpyu_acc_hl_s0,"iiii","")
+BUILTIN(__builtin_HEXAGON_M2_mpyu_acc_hl_s1,"iiii","")
+BUILTIN(__builtin_HEXAGON_M2_mpyu_acc_lh_s0,"iiii","")
+BUILTIN(__builtin_HEXAGON_M2_mpyu_acc_lh_s1,"iiii","")
+BUILTIN(__builtin_HEXAGON_M2_mpyu_acc_ll_s0,"iiii","")
+BUILTIN(__builtin_HEXAGON_M2_mpyu_acc_ll_s1,"iiii","")
+BUILTIN(__builtin_HEXAGON_M2_mpyu_nac_hh_s0,"iiii","")
+BUILTIN(__builtin_HEXAGON_M2_mpyu_nac_hh_s1,"iiii","")
+BUILTIN(__builtin_HEXAGON_M2_mpyu_nac_hl_s0,"iiii","")
+BUILTIN(__builtin_HEXAGON_M2_mpyu_nac_hl_s1,"iiii","")
+BUILTIN(__builtin_HEXAGON_M2_mpyu_nac_lh_s0,"iiii","")
+BUILTIN(__builtin_HEXAGON_M2_mpyu_nac_lh_s1,"iiii","")
+BUILTIN(__builtin_HEXAGON_M2_mpyu_nac_ll_s0,"iiii","")
+BUILTIN(__builtin_HEXAGON_M2_mpyu_nac_ll_s1,"iiii","")
+BUILTIN(__builtin_HEXAGON_M2_mpyu_hh_s0,"Uiii","")
+BUILTIN(__builtin_HEXAGON_M2_mpyu_hh_s1,"Uiii","")
+BUILTIN(__builtin_HEXAGON_M2_mpyu_hl_s0,"Uiii","")
+BUILTIN(__builtin_HEXAGON_M2_mpyu_hl_s1,"Uiii","")
+BUILTIN(__builtin_HEXAGON_M2_mpyu_lh_s0,"Uiii","")
+BUILTIN(__builtin_HEXAGON_M2_mpyu_lh_s1,"Uiii","")
+BUILTIN(__builtin_HEXAGON_M2_mpyu_ll_s0,"Uiii","")
+BUILTIN(__builtin_HEXAGON_M2_mpyu_ll_s1,"Uiii","")
+BUILTIN(__builtin_HEXAGON_M2_mpyud_acc_hh_s0,"LLiLLiii","")
+BUILTIN(__builtin_HEXAGON_M2_mpyud_acc_hh_s1,"LLiLLiii","")
+BUILTIN(__builtin_HEXAGON_M2_mpyud_acc_hl_s0,"LLiLLiii","")
+BUILTIN(__builtin_HEXAGON_M2_mpyud_acc_hl_s1,"LLiLLiii","")
+BUILTIN(__builtin_HEXAGON_M2_mpyud_acc_lh_s0,"LLiLLiii","")
+BUILTIN(__builtin_HEXAGON_M2_mpyud_acc_lh_s1,"LLiLLiii","")
+BUILTIN(__builtin_HEXAGON_M2_mpyud_acc_ll_s0,"LLiLLiii","")
+BUILTIN(__builtin_HEXAGON_M2_mpyud_acc_ll_s1,"LLiLLiii","")
+BUILTIN(__builtin_HEXAGON_M2_mpyud_nac_hh_s0,"LLiLLiii","")
+BUILTIN(__builtin_HEXAGON_M2_mpyud_nac_hh_s1,"LLiLLiii","")
+BUILTIN(__builtin_HEXAGON_M2_mpyud_nac_hl_s0,"LLiLLiii","")
+BUILTIN(__builtin_HEXAGON_M2_mpyud_nac_hl_s1,"LLiLLiii","")
+BUILTIN(__builtin_HEXAGON_M2_mpyud_nac_lh_s0,"LLiLLiii","")
+BUILTIN(__builtin_HEXAGON_M2_mpyud_nac_lh_s1,"LLiLLiii","")
+BUILTIN(__builtin_HEXAGON_M2_mpyud_nac_ll_s0,"LLiLLiii","")
+BUILTIN(__builtin_HEXAGON_M2_mpyud_nac_ll_s1,"LLiLLiii","")
+BUILTIN(__builtin_HEXAGON_M2_mpyud_hh_s0,"ULLiii","")
+BUILTIN(__builtin_HEXAGON_M2_mpyud_hh_s1,"ULLiii","")
+BUILTIN(__builtin_HEXAGON_M2_mpyud_hl_s0,"ULLiii","")
+BUILTIN(__builtin_HEXAGON_M2_mpyud_hl_s1,"ULLiii","")
+BUILTIN(__builtin_HEXAGON_M2_mpyud_lh_s0,"ULLiii","")
+BUILTIN(__builtin_HEXAGON_M2_mpyud_lh_s1,"ULLiii","")
+BUILTIN(__builtin_HEXAGON_M2_mpyud_ll_s0,"ULLiii","")
+BUILTIN(__builtin_HEXAGON_M2_mpyud_ll_s1,"ULLiii","")
+BUILTIN(__builtin_HEXAGON_M2_mpysmi,"iii","")
+BUILTIN(__builtin_HEXAGON_M2_macsip,"iiii","")
+BUILTIN(__builtin_HEXAGON_M2_macsin,"iiii","")
+BUILTIN(__builtin_HEXAGON_M2_dpmpyss_s0,"LLiii","")
+BUILTIN(__builtin_HEXAGON_M2_dpmpyss_acc_s0,"LLiLLiii","")
+BUILTIN(__builtin_HEXAGON_M2_dpmpyss_nac_s0,"LLiLLiii","")
+BUILTIN(__builtin_HEXAGON_M2_dpmpyuu_s0,"ULLiii","")
+BUILTIN(__builtin_HEXAGON_M2_dpmpyuu_acc_s0,"LLiLLiii","")
+BUILTIN(__builtin_HEXAGON_M2_dpmpyuu_nac_s0,"LLiLLiii","")
+BUILTIN(__builtin_HEXAGON_M2_mpy_up,"iii","")
+BUILTIN(__builtin_HEXAGON_M2_mpy_up_s1,"iii","")
+BUILTIN(__builtin_HEXAGON_M2_mpy_up_s1_sat,"iii","")
+BUILTIN(__builtin_HEXAGON_M2_mpyu_up,"Uiii","")
+BUILTIN(__builtin_HEXAGON_M2_mpysu_up,"iii","")
+BUILTIN(__builtin_HEXAGON_M2_dpmpyss_rnd_s0,"iii","")
+BUILTIN(__builtin_HEXAGON_M4_mac_up_s1_sat,"iiii","")
+BUILTIN(__builtin_HEXAGON_M4_nac_up_s1_sat,"iiii","")
+BUILTIN(__builtin_HEXAGON_M2_mpyi,"iii","")
+BUILTIN(__builtin_HEXAGON_M2_mpyui,"iii","")
+BUILTIN(__builtin_HEXAGON_M2_maci,"iiii","")
+BUILTIN(__builtin_HEXAGON_M2_acci,"iiii","")
+BUILTIN(__builtin_HEXAGON_M2_accii,"iiii","")
+BUILTIN(__builtin_HEXAGON_M2_nacci,"iiii","")
+BUILTIN(__builtin_HEXAGON_M2_naccii,"iiii","")
+BUILTIN(__builtin_HEXAGON_M2_subacc,"iiii","")
+BUILTIN(__builtin_HEXAGON_M4_mpyrr_addr,"iiii","")
+BUILTIN(__builtin_HEXAGON_M4_mpyri_addr_u2,"iiii","")
+BUILTIN(__builtin_HEXAGON_M4_mpyri_addr,"iiii","")
+BUILTIN(__builtin_HEXAGON_M4_mpyri_addi,"iiii","")
+BUILTIN(__builtin_HEXAGON_M4_mpyrr_addi,"iiii","")
+BUILTIN(__builtin_HEXAGON_M2_vmpy2s_s0,"LLiii","")
+BUILTIN(__builtin_HEXAGON_M2_vmpy2s_s1,"LLiii","")
+BUILTIN(__builtin_HEXAGON_M2_vmac2s_s0,"LLiLLiii","")
+BUILTIN(__builtin_HEXAGON_M2_vmac2s_s1,"LLiLLiii","")
+BUILTIN(__builtin_HEXAGON_M2_vmpy2su_s0,"LLiii","")
+BUILTIN(__builtin_HEXAGON_M2_vmpy2su_s1,"LLiii","")
+BUILTIN(__builtin_HEXAGON_M2_vmac2su_s0,"LLiLLiii","")
+BUILTIN(__builtin_HEXAGON_M2_vmac2su_s1,"LLiLLiii","")
+BUILTIN(__builtin_HEXAGON_M2_vmpy2s_s0pack,"iii","")
+BUILTIN(__builtin_HEXAGON_M2_vmpy2s_s1pack,"iii","")
+BUILTIN(__builtin_HEXAGON_M2_vmac2,"LLiLLiii","")
+BUILTIN(__builtin_HEXAGON_M2_vmpy2es_s0,"LLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_M2_vmpy2es_s1,"LLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_M2_vmac2es_s0,"LLiLLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_M2_vmac2es_s1,"LLiLLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_M2_vmac2es,"LLiLLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_M2_vrmac_s0,"LLiLLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_M2_vrmpy_s0,"LLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_M2_vdmpyrs_s0,"iLLiLLi","")
+BUILTIN(__builtin_HEXAGON_M2_vdmpyrs_s1,"iLLiLLi","")
+BUILTIN(__builtin_HEXAGON_M5_vrmpybuu,"LLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_M5_vrmacbuu,"LLiLLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_M5_vrmpybsu,"LLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_M5_vrmacbsu,"LLiLLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_M5_vmpybuu,"LLiii","")
+BUILTIN(__builtin_HEXAGON_M5_vmpybsu,"LLiii","")
+BUILTIN(__builtin_HEXAGON_M5_vmacbuu,"LLiLLiii","")
+BUILTIN(__builtin_HEXAGON_M5_vmacbsu,"LLiLLiii","")
+BUILTIN(__builtin_HEXAGON_M5_vdmpybsu,"LLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_M5_vdmacbsu,"LLiLLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_M2_vdmacs_s0,"LLiLLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_M2_vdmacs_s1,"LLiLLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_M2_vdmpys_s0,"LLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_M2_vdmpys_s1,"LLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_M2_cmpyrs_s0,"iii","")
+BUILTIN(__builtin_HEXAGON_M2_cmpyrs_s1,"iii","")
+BUILTIN(__builtin_HEXAGON_M2_cmpyrsc_s0,"iii","")
+BUILTIN(__builtin_HEXAGON_M2_cmpyrsc_s1,"iii","")
+BUILTIN(__builtin_HEXAGON_M2_cmacs_s0,"LLiLLiii","")
+BUILTIN(__builtin_HEXAGON_M2_cmacs_s1,"LLiLLiii","")
+BUILTIN(__builtin_HEXAGON_M2_cmacsc_s0,"LLiLLiii","")
+BUILTIN(__builtin_HEXAGON_M2_cmacsc_s1,"LLiLLiii","")
+BUILTIN(__builtin_HEXAGON_M2_cmpys_s0,"LLiii","")
+BUILTIN(__builtin_HEXAGON_M2_cmpys_s1,"LLiii","")
+BUILTIN(__builtin_HEXAGON_M2_cmpysc_s0,"LLiii","")
+BUILTIN(__builtin_HEXAGON_M2_cmpysc_s1,"LLiii","")
+BUILTIN(__builtin_HEXAGON_M2_cnacs_s0,"LLiLLiii","")
+BUILTIN(__builtin_HEXAGON_M2_cnacs_s1,"LLiLLiii","")
+BUILTIN(__builtin_HEXAGON_M2_cnacsc_s0,"LLiLLiii","")
+BUILTIN(__builtin_HEXAGON_M2_cnacsc_s1,"LLiLLiii","")
+BUILTIN(__builtin_HEXAGON_M2_vrcmpys_s1,"LLiLLii","")
+BUILTIN(__builtin_HEXAGON_M2_vrcmpys_acc_s1,"LLiLLiLLii","")
+BUILTIN(__builtin_HEXAGON_M2_vrcmpys_s1rp,"iLLii","")
+BUILTIN(__builtin_HEXAGON_M2_mmacls_s0,"LLiLLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_M2_mmacls_s1,"LLiLLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_M2_mmachs_s0,"LLiLLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_M2_mmachs_s1,"LLiLLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_M2_mmpyl_s0,"LLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_M2_mmpyl_s1,"LLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_M2_mmpyh_s0,"LLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_M2_mmpyh_s1,"LLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_M2_mmacls_rs0,"LLiLLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_M2_mmacls_rs1,"LLiLLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_M2_mmachs_rs0,"LLiLLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_M2_mmachs_rs1,"LLiLLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_M2_mmpyl_rs0,"LLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_M2_mmpyl_rs1,"LLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_M2_mmpyh_rs0,"LLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_M2_mmpyh_rs1,"LLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_M4_vrmpyeh_s0,"LLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_M4_vrmpyeh_s1,"LLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_M4_vrmpyeh_acc_s0,"LLiLLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_M4_vrmpyeh_acc_s1,"LLiLLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_M4_vrmpyoh_s0,"LLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_M4_vrmpyoh_s1,"LLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_M4_vrmpyoh_acc_s0,"LLiLLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_M4_vrmpyoh_acc_s1,"LLiLLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_M2_hmmpyl_rs1,"iii","")
+BUILTIN(__builtin_HEXAGON_M2_hmmpyh_rs1,"iii","")
+BUILTIN(__builtin_HEXAGON_M2_hmmpyl_s1,"iii","")
+BUILTIN(__builtin_HEXAGON_M2_hmmpyh_s1,"iii","")
+BUILTIN(__builtin_HEXAGON_M2_mmaculs_s0,"LLiLLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_M2_mmaculs_s1,"LLiLLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_M2_mmacuhs_s0,"LLiLLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_M2_mmacuhs_s1,"LLiLLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_M2_mmpyul_s0,"LLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_M2_mmpyul_s1,"LLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_M2_mmpyuh_s0,"LLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_M2_mmpyuh_s1,"LLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_M2_mmaculs_rs0,"LLiLLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_M2_mmaculs_rs1,"LLiLLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_M2_mmacuhs_rs0,"LLiLLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_M2_mmacuhs_rs1,"LLiLLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_M2_mmpyul_rs0,"LLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_M2_mmpyul_rs1,"LLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_M2_mmpyuh_rs0,"LLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_M2_mmpyuh_rs1,"LLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_M2_vrcmaci_s0,"LLiLLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_M2_vrcmacr_s0,"LLiLLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_M2_vrcmaci_s0c,"LLiLLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_M2_vrcmacr_s0c,"LLiLLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_M2_cmaci_s0,"LLiLLiii","")
+BUILTIN(__builtin_HEXAGON_M2_cmacr_s0,"LLiLLiii","")
+BUILTIN(__builtin_HEXAGON_M2_vrcmpyi_s0,"LLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_M2_vrcmpyr_s0,"LLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_M2_vrcmpyi_s0c,"LLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_M2_vrcmpyr_s0c,"LLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_M2_cmpyi_s0,"LLiii","")
+BUILTIN(__builtin_HEXAGON_M2_cmpyr_s0,"LLiii","")
+BUILTIN(__builtin_HEXAGON_M4_cmpyi_wh,"iLLii","")
+BUILTIN(__builtin_HEXAGON_M4_cmpyr_wh,"iLLii","")
+BUILTIN(__builtin_HEXAGON_M4_cmpyi_whc,"iLLii","")
+BUILTIN(__builtin_HEXAGON_M4_cmpyr_whc,"iLLii","")
+BUILTIN(__builtin_HEXAGON_M2_vcmpy_s0_sat_i,"LLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_M2_vcmpy_s0_sat_r,"LLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_M2_vcmpy_s1_sat_i,"LLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_M2_vcmpy_s1_sat_r,"LLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_M2_vcmac_s0_sat_i,"LLiLLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_M2_vcmac_s0_sat_r,"LLiLLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_S2_vcrotate,"LLiLLii","")
+BUILTIN(__builtin_HEXAGON_S4_vrcrotate_acc,"LLiLLiLLiii","")
+BUILTIN(__builtin_HEXAGON_S4_vrcrotate,"LLiLLiii","")
+BUILTIN(__builtin_HEXAGON_S2_vcnegh,"LLiLLii","")
+BUILTIN(__builtin_HEXAGON_S2_vrcnegh,"LLiLLiLLii","")
+BUILTIN(__builtin_HEXAGON_M4_pmpyw,"LLiii","")
+BUILTIN(__builtin_HEXAGON_M4_vpmpyh,"LLiii","")
+BUILTIN(__builtin_HEXAGON_M4_pmpyw_acc,"LLiLLiii","")
+BUILTIN(__builtin_HEXAGON_M4_vpmpyh_acc,"LLiLLiii","")
+BUILTIN(__builtin_HEXAGON_A2_add,"iii","")
+BUILTIN(__builtin_HEXAGON_A2_sub,"iii","")
+BUILTIN(__builtin_HEXAGON_A2_addsat,"iii","")
+BUILTIN(__builtin_HEXAGON_A2_subsat,"iii","")
+BUILTIN(__builtin_HEXAGON_A2_addi,"iii","")
+BUILTIN(__builtin_HEXAGON_A2_addh_l16_ll,"iii","")
+BUILTIN(__builtin_HEXAGON_A2_addh_l16_hl,"iii","")
+BUILTIN(__builtin_HEXAGON_A2_addh_l16_sat_ll,"iii","")
+BUILTIN(__builtin_HEXAGON_A2_addh_l16_sat_hl,"iii","")
+BUILTIN(__builtin_HEXAGON_A2_subh_l16_ll,"iii","")
+BUILTIN(__builtin_HEXAGON_A2_subh_l16_hl,"iii","")
+BUILTIN(__builtin_HEXAGON_A2_subh_l16_sat_ll,"iii","")
+BUILTIN(__builtin_HEXAGON_A2_subh_l16_sat_hl,"iii","")
+BUILTIN(__builtin_HEXAGON_A2_addh_h16_ll,"iii","")
+BUILTIN(__builtin_HEXAGON_A2_addh_h16_lh,"iii","")
+BUILTIN(__builtin_HEXAGON_A2_addh_h16_hl,"iii","")
+BUILTIN(__builtin_HEXAGON_A2_addh_h16_hh,"iii","")
+BUILTIN(__builtin_HEXAGON_A2_addh_h16_sat_ll,"iii","")
+BUILTIN(__builtin_HEXAGON_A2_addh_h16_sat_lh,"iii","")
+BUILTIN(__builtin_HEXAGON_A2_addh_h16_sat_hl,"iii","")
+BUILTIN(__builtin_HEXAGON_A2_addh_h16_sat_hh,"iii","")
+BUILTIN(__builtin_HEXAGON_A2_subh_h16_ll,"iii","")
+BUILTIN(__builtin_HEXAGON_A2_subh_h16_lh,"iii","")
+BUILTIN(__builtin_HEXAGON_A2_subh_h16_hl,"iii","")
+BUILTIN(__builtin_HEXAGON_A2_subh_h16_hh,"iii","")
+BUILTIN(__builtin_HEXAGON_A2_subh_h16_sat_ll,"iii","")
+BUILTIN(__builtin_HEXAGON_A2_subh_h16_sat_lh,"iii","")
+BUILTIN(__builtin_HEXAGON_A2_subh_h16_sat_hl,"iii","")
+BUILTIN(__builtin_HEXAGON_A2_subh_h16_sat_hh,"iii","")
+BUILTIN(__builtin_HEXAGON_A2_aslh,"ii","")
+BUILTIN(__builtin_HEXAGON_A2_asrh,"ii","")
+BUILTIN(__builtin_HEXAGON_A2_addp,"LLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_A2_addpsat,"LLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_A2_addsp,"LLiiLLi","")
+BUILTIN(__builtin_HEXAGON_A2_subp,"LLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_A2_neg,"ii","")
+BUILTIN(__builtin_HEXAGON_A2_negsat,"ii","")
+BUILTIN(__builtin_HEXAGON_A2_abs,"ii","")
+BUILTIN(__builtin_HEXAGON_A2_abssat,"ii","")
+BUILTIN(__builtin_HEXAGON_A2_vconj,"LLiLLi","")
+BUILTIN(__builtin_HEXAGON_A2_negp,"LLiLLi","")
+BUILTIN(__builtin_HEXAGON_A2_absp,"LLiLLi","")
+BUILTIN(__builtin_HEXAGON_A2_max,"iii","")
+BUILTIN(__builtin_HEXAGON_A2_maxu,"Uiii","")
+BUILTIN(__builtin_HEXAGON_A2_min,"iii","")
+BUILTIN(__builtin_HEXAGON_A2_minu,"Uiii","")
+BUILTIN(__builtin_HEXAGON_A2_maxp,"LLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_A2_maxup,"ULLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_A2_minp,"LLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_A2_minup,"ULLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_A2_tfr,"ii","")
+BUILTIN(__builtin_HEXAGON_A2_tfrsi,"ii","")
+BUILTIN(__builtin_HEXAGON_A2_tfrp,"LLiLLi","")
+BUILTIN(__builtin_HEXAGON_A2_tfrpi,"LLii","")
+BUILTIN(__builtin_HEXAGON_A2_zxtb,"ii","")
+BUILTIN(__builtin_HEXAGON_A2_sxtb,"ii","")
+BUILTIN(__builtin_HEXAGON_A2_zxth,"ii","")
+BUILTIN(__builtin_HEXAGON_A2_sxth,"ii","")
+BUILTIN(__builtin_HEXAGON_A2_combinew,"LLiii","")
+BUILTIN(__builtin_HEXAGON_A4_combineri,"LLiii","")
+BUILTIN(__builtin_HEXAGON_A4_combineir,"LLiii","")
+BUILTIN(__builtin_HEXAGON_A2_combineii,"LLiii","")
+BUILTIN(__builtin_HEXAGON_A2_combine_hh,"iii","")
+BUILTIN(__builtin_HEXAGON_A2_combine_hl,"iii","")
+BUILTIN(__builtin_HEXAGON_A2_combine_lh,"iii","")
+BUILTIN(__builtin_HEXAGON_A2_combine_ll,"iii","")
+BUILTIN(__builtin_HEXAGON_A2_tfril,"iii","")
+BUILTIN(__builtin_HEXAGON_A2_tfrih,"iii","")
+BUILTIN(__builtin_HEXAGON_A2_and,"iii","")
+BUILTIN(__builtin_HEXAGON_A2_or,"iii","")
+BUILTIN(__builtin_HEXAGON_A2_xor,"iii","")
+BUILTIN(__builtin_HEXAGON_A2_not,"ii","")
+BUILTIN(__builtin_HEXAGON_M2_xor_xacc,"iiii","")
+BUILTIN(__builtin_HEXAGON_M4_xor_xacc,"LLiLLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_A4_andn,"iii","")
+BUILTIN(__builtin_HEXAGON_A4_orn,"iii","")
+BUILTIN(__builtin_HEXAGON_A4_andnp,"LLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_A4_ornp,"LLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_S4_addaddi,"iiii","")
+BUILTIN(__builtin_HEXAGON_S4_subaddi,"iiii","")
+BUILTIN(__builtin_HEXAGON_M4_and_and,"iiii","")
+BUILTIN(__builtin_HEXAGON_M4_and_andn,"iiii","")
+BUILTIN(__builtin_HEXAGON_M4_and_or,"iiii","")
+BUILTIN(__builtin_HEXAGON_M4_and_xor,"iiii","")
+BUILTIN(__builtin_HEXAGON_M4_or_and,"iiii","")
+BUILTIN(__builtin_HEXAGON_M4_or_andn,"iiii","")
+BUILTIN(__builtin_HEXAGON_M4_or_or,"iiii","")
+BUILTIN(__builtin_HEXAGON_M4_or_xor,"iiii","")
+BUILTIN(__builtin_HEXAGON_S4_or_andix,"iiii","")
+BUILTIN(__builtin_HEXAGON_S4_or_andi,"iiii","")
+BUILTIN(__builtin_HEXAGON_S4_or_ori,"iiii","")
+BUILTIN(__builtin_HEXAGON_M4_xor_and,"iiii","")
+BUILTIN(__builtin_HEXAGON_M4_xor_or,"iiii","")
+BUILTIN(__builtin_HEXAGON_M4_xor_andn,"iiii","")
+BUILTIN(__builtin_HEXAGON_A2_subri,"iii","")
+BUILTIN(__builtin_HEXAGON_A2_andir,"iii","")
+BUILTIN(__builtin_HEXAGON_A2_orir,"iii","")
+BUILTIN(__builtin_HEXAGON_A2_andp,"LLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_A2_orp,"LLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_A2_xorp,"LLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_A2_notp,"LLiLLi","")
+BUILTIN(__builtin_HEXAGON_A2_sxtw,"LLii","")
+BUILTIN(__builtin_HEXAGON_A2_sat,"iLLi","")
+BUILTIN(__builtin_HEXAGON_A2_roundsat,"iLLi","")
+BUILTIN(__builtin_HEXAGON_A2_sath,"ii","")
+BUILTIN(__builtin_HEXAGON_A2_satuh,"ii","")
+BUILTIN(__builtin_HEXAGON_A2_satub,"ii","")
+BUILTIN(__builtin_HEXAGON_A2_satb,"ii","")
+BUILTIN(__builtin_HEXAGON_A2_vaddub,"LLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_A2_vaddb_map,"LLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_A2_vaddubs,"LLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_A2_vaddh,"LLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_A2_vaddhs,"LLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_A2_vadduhs,"LLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_A5_vaddhubs,"iLLiLLi","")
+BUILTIN(__builtin_HEXAGON_A2_vaddw,"LLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_A2_vaddws,"LLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_S4_vxaddsubw,"LLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_S4_vxsubaddw,"LLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_S4_vxaddsubh,"LLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_S4_vxsubaddh,"LLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_S4_vxaddsubhr,"LLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_S4_vxsubaddhr,"LLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_A2_svavgh,"iii","")
+BUILTIN(__builtin_HEXAGON_A2_svavghs,"iii","")
+BUILTIN(__builtin_HEXAGON_A2_svnavgh,"iii","")
+BUILTIN(__builtin_HEXAGON_A2_svaddh,"iii","")
+BUILTIN(__builtin_HEXAGON_A2_svaddhs,"iii","")
+BUILTIN(__builtin_HEXAGON_A2_svadduhs,"iii","")
+BUILTIN(__builtin_HEXAGON_A2_svsubh,"iii","")
+BUILTIN(__builtin_HEXAGON_A2_svsubhs,"iii","")
+BUILTIN(__builtin_HEXAGON_A2_svsubuhs,"iii","")
+BUILTIN(__builtin_HEXAGON_A2_vraddub,"LLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_A2_vraddub_acc,"LLiLLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_M2_vraddh,"iLLiLLi","")
+BUILTIN(__builtin_HEXAGON_M2_vradduh,"iLLiLLi","")
+BUILTIN(__builtin_HEXAGON_A2_vsubub,"LLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_A2_vsubb_map,"LLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_A2_vsububs,"LLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_A2_vsubh,"LLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_A2_vsubhs,"LLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_A2_vsubuhs,"LLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_A2_vsubw,"LLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_A2_vsubws,"LLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_A2_vabsh,"LLiLLi","")
+BUILTIN(__builtin_HEXAGON_A2_vabshsat,"LLiLLi","")
+BUILTIN(__builtin_HEXAGON_A2_vabsw,"LLiLLi","")
+BUILTIN(__builtin_HEXAGON_A2_vabswsat,"LLiLLi","")
+BUILTIN(__builtin_HEXAGON_M2_vabsdiffw,"LLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_M2_vabsdiffh,"LLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_A2_vrsadub,"LLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_A2_vrsadub_acc,"LLiLLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_A2_vavgub,"LLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_A2_vavguh,"LLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_A2_vavgh,"LLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_A2_vnavgh,"LLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_A2_vavgw,"LLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_A2_vnavgw,"LLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_A2_vavgwr,"LLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_A2_vnavgwr,"LLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_A2_vavgwcr,"LLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_A2_vnavgwcr,"LLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_A2_vavghcr,"LLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_A2_vnavghcr,"LLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_A2_vavguw,"LLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_A2_vavguwr,"LLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_A2_vavgubr,"LLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_A2_vavguhr,"LLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_A2_vavghr,"LLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_A2_vnavghr,"LLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_A4_round_ri,"iii","")
+BUILTIN(__builtin_HEXAGON_A4_round_rr,"iii","")
+BUILTIN(__builtin_HEXAGON_A4_round_ri_sat,"iii","")
+BUILTIN(__builtin_HEXAGON_A4_round_rr_sat,"iii","")
+BUILTIN(__builtin_HEXAGON_A4_cround_ri,"iii","")
+BUILTIN(__builtin_HEXAGON_A4_cround_rr,"iii","")
+BUILTIN(__builtin_HEXAGON_A4_vrminh,"LLiLLiLLii","")
+BUILTIN(__builtin_HEXAGON_A4_vrmaxh,"LLiLLiLLii","")
+BUILTIN(__builtin_HEXAGON_A4_vrminuh,"LLiLLiLLii","")
+BUILTIN(__builtin_HEXAGON_A4_vrmaxuh,"LLiLLiLLii","")
+BUILTIN(__builtin_HEXAGON_A4_vrminw,"LLiLLiLLii","")
+BUILTIN(__builtin_HEXAGON_A4_vrmaxw,"LLiLLiLLii","")
+BUILTIN(__builtin_HEXAGON_A4_vrminuw,"LLiLLiLLii","")
+BUILTIN(__builtin_HEXAGON_A4_vrmaxuw,"LLiLLiLLii","")
+BUILTIN(__builtin_HEXAGON_A2_vminb,"LLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_A2_vmaxb,"LLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_A2_vminub,"LLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_A2_vmaxub,"LLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_A2_vminh,"LLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_A2_vmaxh,"LLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_A2_vminuh,"LLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_A2_vmaxuh,"LLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_A2_vminw,"LLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_A2_vmaxw,"LLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_A2_vminuw,"LLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_A2_vmaxuw,"LLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_A4_modwrapu,"iii","")
+BUILTIN(__builtin_HEXAGON_F2_sfadd,"fff","")
+BUILTIN(__builtin_HEXAGON_F2_sfsub,"fff","")
+BUILTIN(__builtin_HEXAGON_F2_sfmpy,"fff","")
+BUILTIN(__builtin_HEXAGON_F2_sffma,"ffff","")
+BUILTIN(__builtin_HEXAGON_F2_sffma_sc,"ffffi","")
+BUILTIN(__builtin_HEXAGON_F2_sffms,"ffff","")
+BUILTIN(__builtin_HEXAGON_F2_sffma_lib,"ffff","")
+BUILTIN(__builtin_HEXAGON_F2_sffms_lib,"ffff","")
+BUILTIN(__builtin_HEXAGON_F2_sfcmpeq,"bff","")
+BUILTIN(__builtin_HEXAGON_F2_sfcmpgt,"bff","")
+BUILTIN(__builtin_HEXAGON_F2_sfcmpge,"bff","")
+BUILTIN(__builtin_HEXAGON_F2_sfcmpuo,"bff","")
+BUILTIN(__builtin_HEXAGON_F2_sfmax,"fff","")
+BUILTIN(__builtin_HEXAGON_F2_sfmin,"fff","")
+BUILTIN(__builtin_HEXAGON_F2_sfclass,"bfi","")
+BUILTIN(__builtin_HEXAGON_F2_sfimm_p,"fi","")
+BUILTIN(__builtin_HEXAGON_F2_sfimm_n,"fi","")
+BUILTIN(__builtin_HEXAGON_F2_sffixupn,"fff","")
+BUILTIN(__builtin_HEXAGON_F2_sffixupd,"fff","")
+BUILTIN(__builtin_HEXAGON_F2_sffixupr,"ff","")
+BUILTIN(__builtin_HEXAGON_F2_dfadd,"ddd","")
+BUILTIN(__builtin_HEXAGON_F2_dfsub,"ddd","")
+BUILTIN(__builtin_HEXAGON_F2_dfmpy,"ddd","")
+BUILTIN(__builtin_HEXAGON_F2_dffma,"dddd","")
+BUILTIN(__builtin_HEXAGON_F2_dffms,"dddd","")
+BUILTIN(__builtin_HEXAGON_F2_dffma_lib,"dddd","")
+BUILTIN(__builtin_HEXAGON_F2_dffms_lib,"dddd","")
+BUILTIN(__builtin_HEXAGON_F2_dffma_sc,"ddddi","")
+BUILTIN(__builtin_HEXAGON_F2_dfmax,"ddd","")
+BUILTIN(__builtin_HEXAGON_F2_dfmin,"ddd","")
+BUILTIN(__builtin_HEXAGON_F2_dfcmpeq,"bdd","")
+BUILTIN(__builtin_HEXAGON_F2_dfcmpgt,"bdd","")
+BUILTIN(__builtin_HEXAGON_F2_dfcmpge,"bdd","")
+BUILTIN(__builtin_HEXAGON_F2_dfcmpuo,"bdd","")
+BUILTIN(__builtin_HEXAGON_F2_dfclass,"bdi","")
+BUILTIN(__builtin_HEXAGON_F2_dfimm_p,"di","")
+BUILTIN(__builtin_HEXAGON_F2_dfimm_n,"di","")
+BUILTIN(__builtin_HEXAGON_F2_dffixupn,"ddd","")
+BUILTIN(__builtin_HEXAGON_F2_dffixupd,"ddd","")
+BUILTIN(__builtin_HEXAGON_F2_dffixupr,"dd","")
+BUILTIN(__builtin_HEXAGON_F2_conv_sf2df,"df","")
+BUILTIN(__builtin_HEXAGON_F2_conv_df2sf,"fd","")
+BUILTIN(__builtin_HEXAGON_F2_conv_uw2sf,"fi","")
+BUILTIN(__builtin_HEXAGON_F2_conv_uw2df,"di","")
+BUILTIN(__builtin_HEXAGON_F2_conv_w2sf,"fi","")
+BUILTIN(__builtin_HEXAGON_F2_conv_w2df,"di","")
+BUILTIN(__builtin_HEXAGON_F2_conv_ud2sf,"fLLi","")
+BUILTIN(__builtin_HEXAGON_F2_conv_ud2df,"dLLi","")
+BUILTIN(__builtin_HEXAGON_F2_conv_d2sf,"fLLi","")
+BUILTIN(__builtin_HEXAGON_F2_conv_d2df,"dLLi","")
+BUILTIN(__builtin_HEXAGON_F2_conv_sf2uw,"if","")
+BUILTIN(__builtin_HEXAGON_F2_conv_sf2w,"if","")
+BUILTIN(__builtin_HEXAGON_F2_conv_sf2ud,"LLif","")
+BUILTIN(__builtin_HEXAGON_F2_conv_sf2d,"LLif","")
+BUILTIN(__builtin_HEXAGON_F2_conv_df2uw,"id","")
+BUILTIN(__builtin_HEXAGON_F2_conv_df2w,"id","")
+BUILTIN(__builtin_HEXAGON_F2_conv_df2ud,"LLid","")
+BUILTIN(__builtin_HEXAGON_F2_conv_df2d,"LLid","")
+BUILTIN(__builtin_HEXAGON_F2_conv_sf2uw_chop,"if","")
+BUILTIN(__builtin_HEXAGON_F2_conv_sf2w_chop,"if","")
+BUILTIN(__builtin_HEXAGON_F2_conv_sf2ud_chop,"LLif","")
+BUILTIN(__builtin_HEXAGON_F2_conv_sf2d_chop,"LLif","")
+BUILTIN(__builtin_HEXAGON_F2_conv_df2uw_chop,"id","")
+BUILTIN(__builtin_HEXAGON_F2_conv_df2w_chop,"id","")
+BUILTIN(__builtin_HEXAGON_F2_conv_df2ud_chop,"LLid","")
+BUILTIN(__builtin_HEXAGON_F2_conv_df2d_chop,"LLid","")
+BUILTIN(__builtin_HEXAGON_S2_asr_r_r,"iii","")
+BUILTIN(__builtin_HEXAGON_S2_asl_r_r,"iii","")
+BUILTIN(__builtin_HEXAGON_S2_lsr_r_r,"iii","")
+BUILTIN(__builtin_HEXAGON_S2_lsl_r_r,"iii","")
+BUILTIN(__builtin_HEXAGON_S2_asr_r_p,"LLiLLii","")
+BUILTIN(__builtin_HEXAGON_S2_asl_r_p,"LLiLLii","")
+BUILTIN(__builtin_HEXAGON_S2_lsr_r_p,"LLiLLii","")
+BUILTIN(__builtin_HEXAGON_S2_lsl_r_p,"LLiLLii","")
+BUILTIN(__builtin_HEXAGON_S2_asr_r_r_acc,"iiii","")
+BUILTIN(__builtin_HEXAGON_S2_asl_r_r_acc,"iiii","")
+BUILTIN(__builtin_HEXAGON_S2_lsr_r_r_acc,"iiii","")
+BUILTIN(__builtin_HEXAGON_S2_lsl_r_r_acc,"iiii","")
+BUILTIN(__builtin_HEXAGON_S2_asr_r_p_acc,"LLiLLiLLii","")
+BUILTIN(__builtin_HEXAGON_S2_asl_r_p_acc,"LLiLLiLLii","")
+BUILTIN(__builtin_HEXAGON_S2_lsr_r_p_acc,"LLiLLiLLii","")
+BUILTIN(__builtin_HEXAGON_S2_lsl_r_p_acc,"LLiLLiLLii","")
+BUILTIN(__builtin_HEXAGON_S2_asr_r_r_nac,"iiii","")
+BUILTIN(__builtin_HEXAGON_S2_asl_r_r_nac,"iiii","")
+BUILTIN(__builtin_HEXAGON_S2_lsr_r_r_nac,"iiii","")
+BUILTIN(__builtin_HEXAGON_S2_lsl_r_r_nac,"iiii","")
+BUILTIN(__builtin_HEXAGON_S2_asr_r_p_nac,"LLiLLiLLii","")
+BUILTIN(__builtin_HEXAGON_S2_asl_r_p_nac,"LLiLLiLLii","")
+BUILTIN(__builtin_HEXAGON_S2_lsr_r_p_nac,"LLiLLiLLii","")
+BUILTIN(__builtin_HEXAGON_S2_lsl_r_p_nac,"LLiLLiLLii","")
+BUILTIN(__builtin_HEXAGON_S2_asr_r_r_and,"iiii","")
+BUILTIN(__builtin_HEXAGON_S2_asl_r_r_and,"iiii","")
+BUILTIN(__builtin_HEXAGON_S2_lsr_r_r_and,"iiii","")
+BUILTIN(__builtin_HEXAGON_S2_lsl_r_r_and,"iiii","")
+BUILTIN(__builtin_HEXAGON_S2_asr_r_r_or,"iiii","")
+BUILTIN(__builtin_HEXAGON_S2_asl_r_r_or,"iiii","")
+BUILTIN(__builtin_HEXAGON_S2_lsr_r_r_or,"iiii","")
+BUILTIN(__builtin_HEXAGON_S2_lsl_r_r_or,"iiii","")
+BUILTIN(__builtin_HEXAGON_S2_asr_r_p_and,"LLiLLiLLii","")
+BUILTIN(__builtin_HEXAGON_S2_asl_r_p_and,"LLiLLiLLii","")
+BUILTIN(__builtin_HEXAGON_S2_lsr_r_p_and,"LLiLLiLLii","")
+BUILTIN(__builtin_HEXAGON_S2_lsl_r_p_and,"LLiLLiLLii","")
+BUILTIN(__builtin_HEXAGON_S2_asr_r_p_or,"LLiLLiLLii","")
+BUILTIN(__builtin_HEXAGON_S2_asl_r_p_or,"LLiLLiLLii","")
+BUILTIN(__builtin_HEXAGON_S2_lsr_r_p_or,"LLiLLiLLii","")
+BUILTIN(__builtin_HEXAGON_S2_lsl_r_p_or,"LLiLLiLLii","")
+BUILTIN(__builtin_HEXAGON_S2_asr_r_p_xor,"LLiLLiLLii","")
+BUILTIN(__builtin_HEXAGON_S2_asl_r_p_xor,"LLiLLiLLii","")
+BUILTIN(__builtin_HEXAGON_S2_lsr_r_p_xor,"LLiLLiLLii","")
+BUILTIN(__builtin_HEXAGON_S2_lsl_r_p_xor,"LLiLLiLLii","")
+BUILTIN(__builtin_HEXAGON_S2_asr_r_r_sat,"iii","")
+BUILTIN(__builtin_HEXAGON_S2_asl_r_r_sat,"iii","")
+BUILTIN(__builtin_HEXAGON_S2_asr_i_r,"iii","")
+BUILTIN(__builtin_HEXAGON_S2_lsr_i_r,"iii","")
+BUILTIN(__builtin_HEXAGON_S2_asl_i_r,"iii","")
+BUILTIN(__builtin_HEXAGON_S2_asr_i_p,"LLiLLii","")
+BUILTIN(__builtin_HEXAGON_S2_lsr_i_p,"LLiLLii","")
+BUILTIN(__builtin_HEXAGON_S2_asl_i_p,"LLiLLii","")
+BUILTIN(__builtin_HEXAGON_S2_asr_i_r_acc,"iiii","")
+BUILTIN(__builtin_HEXAGON_S2_lsr_i_r_acc,"iiii","")
+BUILTIN(__builtin_HEXAGON_S2_asl_i_r_acc,"iiii","")
+BUILTIN(__builtin_HEXAGON_S2_asr_i_p_acc,"LLiLLiLLii","")
+BUILTIN(__builtin_HEXAGON_S2_lsr_i_p_acc,"LLiLLiLLii","")
+BUILTIN(__builtin_HEXAGON_S2_asl_i_p_acc,"LLiLLiLLii","")
+BUILTIN(__builtin_HEXAGON_S2_asr_i_r_nac,"iiii","")
+BUILTIN(__builtin_HEXAGON_S2_lsr_i_r_nac,"iiii","")
+BUILTIN(__builtin_HEXAGON_S2_asl_i_r_nac,"iiii","")
+BUILTIN(__builtin_HEXAGON_S2_asr_i_p_nac,"LLiLLiLLii","")
+BUILTIN(__builtin_HEXAGON_S2_lsr_i_p_nac,"LLiLLiLLii","")
+BUILTIN(__builtin_HEXAGON_S2_asl_i_p_nac,"LLiLLiLLii","")
+BUILTIN(__builtin_HEXAGON_S2_lsr_i_r_xacc,"iiii","")
+BUILTIN(__builtin_HEXAGON_S2_asl_i_r_xacc,"iiii","")
+BUILTIN(__builtin_HEXAGON_S2_lsr_i_p_xacc,"LLiLLiLLii","")
+BUILTIN(__builtin_HEXAGON_S2_asl_i_p_xacc,"LLiLLiLLii","")
+BUILTIN(__builtin_HEXAGON_S2_asr_i_r_and,"iiii","")
+BUILTIN(__builtin_HEXAGON_S2_lsr_i_r_and,"iiii","")
+BUILTIN(__builtin_HEXAGON_S2_asl_i_r_and,"iiii","")
+BUILTIN(__builtin_HEXAGON_S2_asr_i_r_or,"iiii","")
+BUILTIN(__builtin_HEXAGON_S2_lsr_i_r_or,"iiii","")
+BUILTIN(__builtin_HEXAGON_S2_asl_i_r_or,"iiii","")
+BUILTIN(__builtin_HEXAGON_S2_asr_i_p_and,"LLiLLiLLii","")
+BUILTIN(__builtin_HEXAGON_S2_lsr_i_p_and,"LLiLLiLLii","")
+BUILTIN(__builtin_HEXAGON_S2_asl_i_p_and,"LLiLLiLLii","")
+BUILTIN(__builtin_HEXAGON_S2_asr_i_p_or,"LLiLLiLLii","")
+BUILTIN(__builtin_HEXAGON_S2_lsr_i_p_or,"LLiLLiLLii","")
+BUILTIN(__builtin_HEXAGON_S2_asl_i_p_or,"LLiLLiLLii","")
+BUILTIN(__builtin_HEXAGON_S2_asl_i_r_sat,"iii","")
+BUILTIN(__builtin_HEXAGON_S2_asr_i_r_rnd,"iii","")
+BUILTIN(__builtin_HEXAGON_S2_asr_i_r_rnd_goodsyntax,"iii","")
+BUILTIN(__builtin_HEXAGON_S2_asr_i_p_rnd,"LLiLLii","")
+BUILTIN(__builtin_HEXAGON_S2_asr_i_p_rnd_goodsyntax,"LLiLLii","")
+BUILTIN(__builtin_HEXAGON_S4_lsli,"iii","")
+BUILTIN(__builtin_HEXAGON_S2_addasl_rrri,"iiii","")
+BUILTIN(__builtin_HEXAGON_S4_andi_asl_ri,"iiii","")
+BUILTIN(__builtin_HEXAGON_S4_ori_asl_ri,"iiii","")
+BUILTIN(__builtin_HEXAGON_S4_addi_asl_ri,"iiii","")
+BUILTIN(__builtin_HEXAGON_S4_subi_asl_ri,"iiii","")
+BUILTIN(__builtin_HEXAGON_S4_andi_lsr_ri,"iiii","")
+BUILTIN(__builtin_HEXAGON_S4_ori_lsr_ri,"iiii","")
+BUILTIN(__builtin_HEXAGON_S4_addi_lsr_ri,"iiii","")
+BUILTIN(__builtin_HEXAGON_S4_subi_lsr_ri,"iiii","")
+BUILTIN(__builtin_HEXAGON_S2_valignib,"LLiLLiLLii","")
+BUILTIN(__builtin_HEXAGON_S2_valignrb,"LLiLLiLLii","")
+BUILTIN(__builtin_HEXAGON_S2_vspliceib,"LLiLLiLLii","")
+BUILTIN(__builtin_HEXAGON_S2_vsplicerb,"LLiLLiLLii","")
+BUILTIN(__builtin_HEXAGON_S2_vsplatrh,"LLii","")
+BUILTIN(__builtin_HEXAGON_S2_vsplatrb,"ii","")
+BUILTIN(__builtin_HEXAGON_S2_insert,"iiiii","")
+BUILTIN(__builtin_HEXAGON_S2_tableidxb_goodsyntax,"iiiii","")
+BUILTIN(__builtin_HEXAGON_S2_tableidxh_goodsyntax,"iiiii","")
+BUILTIN(__builtin_HEXAGON_S2_tableidxw_goodsyntax,"iiiii","")
+BUILTIN(__builtin_HEXAGON_S2_tableidxd_goodsyntax,"iiiii","")
+BUILTIN(__builtin_HEXAGON_A4_bitspliti,"LLiii","")
+BUILTIN(__builtin_HEXAGON_A4_bitsplit,"LLiii","")
+BUILTIN(__builtin_HEXAGON_S4_extract,"iiii","")
+BUILTIN(__builtin_HEXAGON_S2_extractu,"iiii","")
+BUILTIN(__builtin_HEXAGON_S2_insertp,"LLiLLiLLiii","")
+BUILTIN(__builtin_HEXAGON_S4_extractp,"LLiLLiii","")
+BUILTIN(__builtin_HEXAGON_S2_extractup,"LLiLLiii","")
+BUILTIN(__builtin_HEXAGON_S2_insert_rp,"iiiLLi","")
+BUILTIN(__builtin_HEXAGON_S4_extract_rp,"iiLLi","")
+BUILTIN(__builtin_HEXAGON_S2_extractu_rp,"iiLLi","")
+BUILTIN(__builtin_HEXAGON_S2_insertp_rp,"LLiLLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_S4_extractp_rp,"LLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_S2_extractup_rp,"LLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_S2_tstbit_i,"bii","")
+BUILTIN(__builtin_HEXAGON_S4_ntstbit_i,"bii","")
+BUILTIN(__builtin_HEXAGON_S2_setbit_i,"iii","")
+BUILTIN(__builtin_HEXAGON_S2_togglebit_i,"iii","")
+BUILTIN(__builtin_HEXAGON_S2_clrbit_i,"iii","")
+BUILTIN(__builtin_HEXAGON_S2_tstbit_r,"bii","")
+BUILTIN(__builtin_HEXAGON_S4_ntstbit_r,"bii","")
+BUILTIN(__builtin_HEXAGON_S2_setbit_r,"iii","")
+BUILTIN(__builtin_HEXAGON_S2_togglebit_r,"iii","")
+BUILTIN(__builtin_HEXAGON_S2_clrbit_r,"iii","")
+BUILTIN(__builtin_HEXAGON_S2_asr_i_vh,"LLiLLii","")
+BUILTIN(__builtin_HEXAGON_S2_lsr_i_vh,"LLiLLii","")
+BUILTIN(__builtin_HEXAGON_S2_asl_i_vh,"LLiLLii","")
+BUILTIN(__builtin_HEXAGON_S2_asr_r_vh,"LLiLLii","")
+BUILTIN(__builtin_HEXAGON_S5_asrhub_rnd_sat_goodsyntax,"iLLii","")
+BUILTIN(__builtin_HEXAGON_S5_asrhub_sat,"iLLii","")
+BUILTIN(__builtin_HEXAGON_S5_vasrhrnd_goodsyntax,"LLiLLii","")
+BUILTIN(__builtin_HEXAGON_S2_asl_r_vh,"LLiLLii","")
+BUILTIN(__builtin_HEXAGON_S2_lsr_r_vh,"LLiLLii","")
+BUILTIN(__builtin_HEXAGON_S2_lsl_r_vh,"LLiLLii","")
+BUILTIN(__builtin_HEXAGON_S2_asr_i_vw,"LLiLLii","")
+BUILTIN(__builtin_HEXAGON_S2_asr_i_svw_trun,"iLLii","")
+BUILTIN(__builtin_HEXAGON_S2_asr_r_svw_trun,"iLLii","")
+BUILTIN(__builtin_HEXAGON_S2_lsr_i_vw,"LLiLLii","")
+BUILTIN(__builtin_HEXAGON_S2_asl_i_vw,"LLiLLii","")
+BUILTIN(__builtin_HEXAGON_S2_asr_r_vw,"LLiLLii","")
+BUILTIN(__builtin_HEXAGON_S2_asl_r_vw,"LLiLLii","")
+BUILTIN(__builtin_HEXAGON_S2_lsr_r_vw,"LLiLLii","")
+BUILTIN(__builtin_HEXAGON_S2_lsl_r_vw,"LLiLLii","")
+BUILTIN(__builtin_HEXAGON_S2_vrndpackwh,"iLLi","")
+BUILTIN(__builtin_HEXAGON_S2_vrndpackwhs,"iLLi","")
+BUILTIN(__builtin_HEXAGON_S2_vsxtbh,"LLii","")
+BUILTIN(__builtin_HEXAGON_S2_vzxtbh,"LLii","")
+BUILTIN(__builtin_HEXAGON_S2_vsathub,"iLLi","")
+BUILTIN(__builtin_HEXAGON_S2_svsathub,"ii","")
+BUILTIN(__builtin_HEXAGON_S2_svsathb,"ii","")
+BUILTIN(__builtin_HEXAGON_S2_vsathb,"iLLi","")
+BUILTIN(__builtin_HEXAGON_S2_vtrunohb,"iLLi","")
+BUILTIN(__builtin_HEXAGON_S2_vtrunewh,"LLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_S2_vtrunowh,"LLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_S2_vtrunehb,"iLLi","")
+BUILTIN(__builtin_HEXAGON_S2_vsxthw,"LLii","")
+BUILTIN(__builtin_HEXAGON_S2_vzxthw,"LLii","")
+BUILTIN(__builtin_HEXAGON_S2_vsatwh,"iLLi","")
+BUILTIN(__builtin_HEXAGON_S2_vsatwuh,"iLLi","")
+BUILTIN(__builtin_HEXAGON_S2_packhl,"LLiii","")
+BUILTIN(__builtin_HEXAGON_A2_swiz,"ii","")
+BUILTIN(__builtin_HEXAGON_S2_vsathub_nopack,"LLiLLi","")
+BUILTIN(__builtin_HEXAGON_S2_vsathb_nopack,"LLiLLi","")
+BUILTIN(__builtin_HEXAGON_S2_vsatwh_nopack,"LLiLLi","")
+BUILTIN(__builtin_HEXAGON_S2_vsatwuh_nopack,"LLiLLi","")
+BUILTIN(__builtin_HEXAGON_S2_shuffob,"LLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_S2_shuffeb,"LLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_S2_shuffoh,"LLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_S2_shuffeh,"LLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_S5_popcountp,"iLLi","")
+BUILTIN(__builtin_HEXAGON_S4_parity,"iii","")
+BUILTIN(__builtin_HEXAGON_S2_parityp,"iLLiLLi","")
+BUILTIN(__builtin_HEXAGON_S2_lfsp,"LLiLLiLLi","")
+BUILTIN(__builtin_HEXAGON_S2_clbnorm,"ii","")
+BUILTIN(__builtin_HEXAGON_S4_clbaddi,"iii","")
+BUILTIN(__builtin_HEXAGON_S4_clbpnorm,"iLLi","")
+BUILTIN(__builtin_HEXAGON_S4_clbpaddi,"iLLii","")
+BUILTIN(__builtin_HEXAGON_S2_clb,"ii","")
+BUILTIN(__builtin_HEXAGON_S2_cl0,"ii","")
+BUILTIN(__builtin_HEXAGON_S2_cl1,"ii","")
+BUILTIN(__builtin_HEXAGON_S2_clbp,"iLLi","")
+BUILTIN(__builtin_HEXAGON_S2_cl0p,"iLLi","")
+BUILTIN(__builtin_HEXAGON_S2_cl1p,"iLLi","")
+BUILTIN(__builtin_HEXAGON_S2_brev,"ii","")
+BUILTIN(__builtin_HEXAGON_S2_brevp,"LLiLLi","")
+BUILTIN(__builtin_HEXAGON_S2_ct0,"ii","")
+BUILTIN(__builtin_HEXAGON_S2_ct1,"ii","")
+BUILTIN(__builtin_HEXAGON_S2_ct0p,"iLLi","")
+BUILTIN(__builtin_HEXAGON_S2_ct1p,"iLLi","")
+BUILTIN(__builtin_HEXAGON_S2_interleave,"LLiLLi","")
+BUILTIN(__builtin_HEXAGON_S2_deinterleave,"LLiLLi","")
+
+#undef BUILTIN
diff --git a/contrib/llvm/tools/clang/include/clang/Basic/BuiltinsLe64.def b/contrib/llvm/tools/clang/include/clang/Basic/BuiltinsLe64.def
new file mode 100644
index 0000000..5328606
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Basic/BuiltinsLe64.def
@@ -0,0 +1,19 @@
+//==- BuiltinsLe64.def - Le64 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 Le64-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.
+
+BUILTIN(__clear_cache, "vv*v*", "i")
+
+#undef BUILTIN
diff --git a/contrib/llvm/tools/clang/include/clang/Basic/BuiltinsMips.def b/contrib/llvm/tools/clang/include/clang/Basic/BuiltinsMips.def
new file mode 100644
index 0000000..2d217f7
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Basic/BuiltinsMips.def
@@ -0,0 +1,900 @@
+//===-- BuiltinsMips.def - Mips 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 MIPS-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.
+
+// MIPS DSP Rev 1
+
+// Add/subtract with optional saturation
+BUILTIN(__builtin_mips_addu_qb, "V4ScV4ScV4Sc", "n")
+BUILTIN(__builtin_mips_addu_s_qb, "V4ScV4ScV4Sc", "n")
+BUILTIN(__builtin_mips_subu_qb, "V4ScV4ScV4Sc", "n")
+BUILTIN(__builtin_mips_subu_s_qb, "V4ScV4ScV4Sc", "n")
+
+BUILTIN(__builtin_mips_addq_ph, "V2sV2sV2s", "n")
+BUILTIN(__builtin_mips_addq_s_ph, "V2sV2sV2s", "n")
+BUILTIN(__builtin_mips_subq_ph, "V2sV2sV2s", "n")
+BUILTIN(__builtin_mips_subq_s_ph, "V2sV2sV2s", "n")
+
+BUILTIN(__builtin_mips_madd, "LLiLLiii", "nc")
+BUILTIN(__builtin_mips_maddu, "LLiLLiUiUi", "nc")
+BUILTIN(__builtin_mips_msub, "LLiLLiii", "nc")
+BUILTIN(__builtin_mips_msubu, "LLiLLiUiUi", "nc")
+
+BUILTIN(__builtin_mips_addq_s_w, "iii", "n")
+BUILTIN(__builtin_mips_subq_s_w, "iii", "n")
+
+BUILTIN(__builtin_mips_addsc, "iii", "n")
+BUILTIN(__builtin_mips_addwc, "iii", "n")
+
+BUILTIN(__builtin_mips_modsub, "iii", "nc")
+
+BUILTIN(__builtin_mips_raddu_w_qb, "iV4Sc", "nc")
+
+BUILTIN(__builtin_mips_absq_s_ph, "V2sV2s", "n")
+BUILTIN(__builtin_mips_absq_s_w, "ii", "n")
+
+BUILTIN(__builtin_mips_precrq_qb_ph, "V4ScV2sV2s", "nc")
+BUILTIN(__builtin_mips_precrqu_s_qb_ph, "V4ScV2sV2s", "n")
+BUILTIN(__builtin_mips_precrq_ph_w, "V2sii", "nc")
+BUILTIN(__builtin_mips_precrq_rs_ph_w, "V2sii", "n")
+BUILTIN(__builtin_mips_preceq_w_phl, "iV2s", "nc")
+BUILTIN(__builtin_mips_preceq_w_phr, "iV2s", "nc")
+BUILTIN(__builtin_mips_precequ_ph_qbl, "V2sV4Sc", "nc")
+BUILTIN(__builtin_mips_precequ_ph_qbr, "V2sV4Sc", "nc")
+BUILTIN(__builtin_mips_precequ_ph_qbla, "V2sV4Sc", "nc")
+BUILTIN(__builtin_mips_precequ_ph_qbra, "V2sV4Sc", "nc")
+BUILTIN(__builtin_mips_preceu_ph_qbl, "V2sV4Sc", "nc")
+BUILTIN(__builtin_mips_preceu_ph_qbr, "V2sV4Sc", "nc")
+BUILTIN(__builtin_mips_preceu_ph_qbla, "V2sV4Sc", "nc")
+BUILTIN(__builtin_mips_preceu_ph_qbra, "V2sV4Sc", "nc")
+
+BUILTIN(__builtin_mips_shll_qb, "V4ScV4Sci", "n")
+BUILTIN(__builtin_mips_shrl_qb, "V4ScV4Sci", "nc")
+BUILTIN(__builtin_mips_shll_ph, "V2sV2si", "n")
+BUILTIN(__builtin_mips_shll_s_ph, "V2sV2si", "n")
+BUILTIN(__builtin_mips_shra_ph, "V2sV2si", "nc")
+BUILTIN(__builtin_mips_shra_r_ph, "V2sV2si", "nc")
+BUILTIN(__builtin_mips_shll_s_w, "iii", "n")
+BUILTIN(__builtin_mips_shra_r_w, "iii", "nc")
+BUILTIN(__builtin_mips_shilo, "LLiLLii", "nc")
+
+BUILTIN(__builtin_mips_muleu_s_ph_qbl, "V2sV4ScV2s", "n")
+BUILTIN(__builtin_mips_muleu_s_ph_qbr, "V2sV4ScV2s", "n")
+BUILTIN(__builtin_mips_mulq_rs_ph, "V2sV2sV2s", "n")
+BUILTIN(__builtin_mips_muleq_s_w_phl, "iV2sV2s", "n")
+BUILTIN(__builtin_mips_muleq_s_w_phr, "iV2sV2s", "n")
+BUILTIN(__builtin_mips_mulsaq_s_w_ph, "LLiLLiV2sV2s", "n")
+BUILTIN(__builtin_mips_maq_s_w_phl, "LLiLLiV2sV2s", "n")
+BUILTIN(__builtin_mips_maq_s_w_phr, "LLiLLiV2sV2s", "n")
+BUILTIN(__builtin_mips_maq_sa_w_phl, "LLiLLiV2sV2s", "n")
+BUILTIN(__builtin_mips_maq_sa_w_phr, "LLiLLiV2sV2s", "n")
+BUILTIN(__builtin_mips_mult, "LLiii", "nc")
+BUILTIN(__builtin_mips_multu, "LLiUiUi", "nc")
+
+BUILTIN(__builtin_mips_dpau_h_qbl, "LLiLLiV4ScV4Sc", "nc")
+BUILTIN(__builtin_mips_dpau_h_qbr, "LLiLLiV4ScV4Sc", "nc")
+BUILTIN(__builtin_mips_dpsu_h_qbl, "LLiLLiV4ScV4Sc", "nc")
+BUILTIN(__builtin_mips_dpsu_h_qbr, "LLiLLiV4ScV4Sc", "nc")
+BUILTIN(__builtin_mips_dpaq_s_w_ph, "LLiLLiV2sV2s", "n")
+BUILTIN(__builtin_mips_dpsq_s_w_ph, "LLiLLiV2sV2s", "n")
+BUILTIN(__builtin_mips_dpaq_sa_l_w, "LLiLLiii", "n")
+BUILTIN(__builtin_mips_dpsq_sa_l_w, "LLiLLiii", "n")
+
+BUILTIN(__builtin_mips_cmpu_eq_qb, "vV4ScV4Sc", "n")
+BUILTIN(__builtin_mips_cmpu_lt_qb, "vV4ScV4Sc", "n")
+BUILTIN(__builtin_mips_cmpu_le_qb, "vV4ScV4Sc", "n")
+BUILTIN(__builtin_mips_cmpgu_eq_qb, "iV4ScV4Sc", "n")
+BUILTIN(__builtin_mips_cmpgu_lt_qb, "iV4ScV4Sc", "n")
+BUILTIN(__builtin_mips_cmpgu_le_qb, "iV4ScV4Sc", "n")
+BUILTIN(__builtin_mips_cmp_eq_ph, "vV2sV2s", "n")
+BUILTIN(__builtin_mips_cmp_lt_ph, "vV2sV2s", "n")
+BUILTIN(__builtin_mips_cmp_le_ph, "vV2sV2s", "n")
+
+BUILTIN(__builtin_mips_extr_s_h, "iLLii", "n")
+BUILTIN(__builtin_mips_extr_w, "iLLii", "n")
+BUILTIN(__builtin_mips_extr_rs_w, "iLLii", "n")
+BUILTIN(__builtin_mips_extr_r_w, "iLLii", "n")
+BUILTIN(__builtin_mips_extp, "iLLii", "n")
+BUILTIN(__builtin_mips_extpdp, "iLLii", "n")
+
+BUILTIN(__builtin_mips_wrdsp, "viIi", "n")
+BUILTIN(__builtin_mips_rddsp, "iIi", "n")
+BUILTIN(__builtin_mips_insv, "iii", "n")
+BUILTIN(__builtin_mips_bitrev, "ii", "nc")
+BUILTIN(__builtin_mips_packrl_ph, "V2sV2sV2s", "nc")
+BUILTIN(__builtin_mips_repl_qb, "V4Sci", "nc")
+BUILTIN(__builtin_mips_repl_ph, "V2si", "nc")
+BUILTIN(__builtin_mips_pick_qb, "V4ScV4ScV4Sc", "n")
+BUILTIN(__builtin_mips_pick_ph, "V2sV2sV2s", "n")
+BUILTIN(__builtin_mips_mthlip, "LLiLLii", "n")
+BUILTIN(__builtin_mips_bposge32, "i", "n")
+BUILTIN(__builtin_mips_lbux, "iv*i", "n")
+BUILTIN(__builtin_mips_lhx, "iv*i", "n")
+BUILTIN(__builtin_mips_lwx, "iv*i", "n")
+
+// MIPS DSP Rev 2
+
+BUILTIN(__builtin_mips_absq_s_qb, "V4ScV4Sc", "n")
+
+BUILTIN(__builtin_mips_addqh_ph, "V2sV2sV2s", "nc")
+BUILTIN(__builtin_mips_addqh_r_ph, "V2sV2sV2s", "nc")
+BUILTIN(__builtin_mips_addqh_w, "iii", "nc")
+BUILTIN(__builtin_mips_addqh_r_w, "iii", "nc")
+
+BUILTIN(__builtin_mips_addu_ph, "V2sV2sV2s", "n")
+BUILTIN(__builtin_mips_addu_s_ph, "V2sV2sV2s", "n")
+
+BUILTIN(__builtin_mips_adduh_qb, "V4ScV4ScV4Sc", "nc")
+BUILTIN(__builtin_mips_adduh_r_qb, "V4ScV4ScV4Sc", "nc")
+
+BUILTIN(__builtin_mips_append, "iiiIi", "nc")
+BUILTIN(__builtin_mips_balign, "iiiIi", "nc")
+
+BUILTIN(__builtin_mips_cmpgdu_eq_qb, "iV4ScV4Sc", "n")
+BUILTIN(__builtin_mips_cmpgdu_lt_qb, "iV4ScV4Sc", "n")
+BUILTIN(__builtin_mips_cmpgdu_le_qb, "iV4ScV4Sc", "n")
+
+BUILTIN(__builtin_mips_dpa_w_ph, "LLiLLiV2sV2s", "nc")
+BUILTIN(__builtin_mips_dps_w_ph, "LLiLLiV2sV2s", "nc")
+
+BUILTIN(__builtin_mips_dpaqx_s_w_ph, "LLiLLiV2sV2s", "n")
+BUILTIN(__builtin_mips_dpaqx_sa_w_ph, "LLiLLiV2sV2s", "n")
+BUILTIN(__builtin_mips_dpax_w_ph, "LLiLLiV2sV2s", "nc")
+BUILTIN(__builtin_mips_dpsx_w_ph, "LLiLLiV2sV2s", "nc")
+BUILTIN(__builtin_mips_dpsqx_s_w_ph, "LLiLLiV2sV2s", "n")
+BUILTIN(__builtin_mips_dpsqx_sa_w_ph, "LLiLLiV2sV2s", "n")
+
+BUILTIN(__builtin_mips_mul_ph, "V2sV2sV2s", "n")
+BUILTIN(__builtin_mips_mul_s_ph, "V2sV2sV2s", "n")
+
+BUILTIN(__builtin_mips_mulq_rs_w, "iii", "n")
+BUILTIN(__builtin_mips_mulq_s_ph, "V2sV2sV2s", "n")
+BUILTIN(__builtin_mips_mulq_s_w, "iii", "n")
+BUILTIN(__builtin_mips_mulsa_w_ph, "LLiLLiV2sV2s", "nc")
+
+BUILTIN(__builtin_mips_precr_qb_ph, "V4ScV2sV2s", "n")
+BUILTIN(__builtin_mips_precr_sra_ph_w, "V2siiIi", "nc")
+BUILTIN(__builtin_mips_precr_sra_r_ph_w, "V2siiIi", "nc")
+
+BUILTIN(__builtin_mips_prepend, "iiiIi", "nc")
+
+BUILTIN(__builtin_mips_shra_qb, "V4ScV4Sci", "nc")
+BUILTIN(__builtin_mips_shra_r_qb, "V4ScV4Sci", "nc")
+BUILTIN(__builtin_mips_shrl_ph, "V2sV2si", "nc")
+
+BUILTIN(__builtin_mips_subqh_ph, "V2sV2sV2s", "nc")
+BUILTIN(__builtin_mips_subqh_r_ph, "V2sV2sV2s", "nc")
+BUILTIN(__builtin_mips_subqh_w, "iii", "nc")
+BUILTIN(__builtin_mips_subqh_r_w, "iii", "nc")
+
+BUILTIN(__builtin_mips_subu_ph, "V2sV2sV2s", "n")
+BUILTIN(__builtin_mips_subu_s_ph, "V2sV2sV2s", "n")
+
+BUILTIN(__builtin_mips_subuh_qb, "V4ScV4ScV4Sc", "nc")
+BUILTIN(__builtin_mips_subuh_r_qb, "V4ScV4ScV4Sc", "nc")
+
+// MIPS MSA
+
+BUILTIN(__builtin_msa_add_a_b, "V16ScV16ScV16Sc", "nc")
+BUILTIN(__builtin_msa_add_a_h, "V8SsV8SsV8Ss", "nc")
+BUILTIN(__builtin_msa_add_a_w, "V4SiV4SiV4Si", "nc")
+BUILTIN(__builtin_msa_add_a_d, "V2SLLiV2SLLiV2SLLi", "nc")
+
+BUILTIN(__builtin_msa_adds_a_b, "V16ScV16ScV16Sc", "nc")
+BUILTIN(__builtin_msa_adds_a_h, "V8SsV8SsV8Ss", "nc")
+BUILTIN(__builtin_msa_adds_a_w, "V4SiV4SiV4Si", "nc")
+BUILTIN(__builtin_msa_adds_a_d, "V2SLLiV2SLLiV2SLLi", "nc")
+
+BUILTIN(__builtin_msa_adds_s_b, "V16ScV16ScV16Sc", "nc")
+BUILTIN(__builtin_msa_adds_s_h, "V8SsV8SsV8Ss", "nc")
+BUILTIN(__builtin_msa_adds_s_w, "V4SiV4SiV4Si", "nc")
+BUILTIN(__builtin_msa_adds_s_d, "V2SLLiV2SLLiV2SLLi", "nc")
+
+BUILTIN(__builtin_msa_adds_u_b, "V16UcV16UcV16Uc", "nc")
+BUILTIN(__builtin_msa_adds_u_h, "V8UsV8UsV8Us", "nc")
+BUILTIN(__builtin_msa_adds_u_w, "V4UiV4UiV4Ui", "nc")
+BUILTIN(__builtin_msa_adds_u_d, "V2ULLiV2ULLiV2ULLi", "nc")
+
+BUILTIN(__builtin_msa_addv_b, "V16cV16cV16c", "nc")
+BUILTIN(__builtin_msa_addv_h, "V8sV8sV8s", "nc")
+BUILTIN(__builtin_msa_addv_w, "V4iV4iV4i", "nc")
+BUILTIN(__builtin_msa_addv_d, "V2LLiV2LLiV2LLi", "nc")
+
+BUILTIN(__builtin_msa_addvi_b, "V16cV16cIUi", "nc")
+BUILTIN(__builtin_msa_addvi_h, "V8sV8sIUi", "nc")
+BUILTIN(__builtin_msa_addvi_w, "V4iV4iIUi", "nc")
+BUILTIN(__builtin_msa_addvi_d, "V2LLiV2LLiIUi", "nc")
+
+BUILTIN(__builtin_msa_and_v, "V16UcV16UcV16Uc", "nc")
+
+BUILTIN(__builtin_msa_andi_b, "V16UcV16UcIUi", "nc")
+
+BUILTIN(__builtin_msa_asub_s_b, "V16ScV16ScV16Sc", "nc")
+BUILTIN(__builtin_msa_asub_s_h, "V8SsV8SsV8Ss", "nc")
+BUILTIN(__builtin_msa_asub_s_w, "V4SiV4SiV4Si", "nc")
+BUILTIN(__builtin_msa_asub_s_d, "V2SLLiV2SLLiV2SLLi", "nc")
+
+BUILTIN(__builtin_msa_asub_u_b, "V16UcV16UcV16Uc", "nc")
+BUILTIN(__builtin_msa_asub_u_h, "V8UsV8UsV8Us", "nc")
+BUILTIN(__builtin_msa_asub_u_w, "V4UiV4UiV4Ui", "nc")
+BUILTIN(__builtin_msa_asub_u_d, "V2ULLiV2ULLiV2ULLi", "nc")
+
+BUILTIN(__builtin_msa_ave_s_b, "V16ScV16ScV16Sc", "nc")
+BUILTIN(__builtin_msa_ave_s_h, "V8SsV8SsV8Ss", "nc")
+BUILTIN(__builtin_msa_ave_s_w, "V4SiV4SiV4Si", "nc")
+BUILTIN(__builtin_msa_ave_s_d, "V2SLLiV2SLLiV2SLLi", "nc")
+
+BUILTIN(__builtin_msa_ave_u_b, "V16UcV16UcV16Uc", "nc")
+BUILTIN(__builtin_msa_ave_u_h, "V8UsV8UsV8Us", "nc")
+BUILTIN(__builtin_msa_ave_u_w, "V4UiV4UiV4Ui", "nc")
+BUILTIN(__builtin_msa_ave_u_d, "V2ULLiV2ULLiV2ULLi", "nc")
+
+BUILTIN(__builtin_msa_aver_s_b, "V16ScV16ScV16Sc", "nc")
+BUILTIN(__builtin_msa_aver_s_h, "V8SsV8SsV8Ss", "nc")
+BUILTIN(__builtin_msa_aver_s_w, "V4SiV4SiV4Si", "nc")
+BUILTIN(__builtin_msa_aver_s_d, "V2SLLiV2SLLiV2SLLi", "nc")
+
+BUILTIN(__builtin_msa_aver_u_b, "V16UcV16UcV16Uc", "nc")
+BUILTIN(__builtin_msa_aver_u_h, "V8UsV8UsV8Us", "nc")
+BUILTIN(__builtin_msa_aver_u_w, "V4UiV4UiV4Ui", "nc")
+BUILTIN(__builtin_msa_aver_u_d, "V2ULLiV2ULLiV2ULLi", "nc")
+
+BUILTIN(__builtin_msa_bclr_b, "V16UcV16UcV16Uc", "nc")
+BUILTIN(__builtin_msa_bclr_h, "V8UsV8UsV8Us", "nc")
+BUILTIN(__builtin_msa_bclr_w, "V4UiV4UiV4Ui", "nc")
+BUILTIN(__builtin_msa_bclr_d, "V2ULLiV2ULLiV2ULLi", "nc")
+
+BUILTIN(__builtin_msa_bclri_b, "V16UcV16UcIUi", "nc")
+BUILTIN(__builtin_msa_bclri_h, "V8UsV8UsIUi", "nc")
+BUILTIN(__builtin_msa_bclri_w, "V4UiV4UiIUi", "nc")
+BUILTIN(__builtin_msa_bclri_d, "V2ULLiV2ULLiIUi", "nc")
+
+BUILTIN(__builtin_msa_binsl_b, "V16UcV16UcV16UcV16Uc", "nc")
+BUILTIN(__builtin_msa_binsl_h, "V8UsV8UsV8UsV8Us", "nc")
+BUILTIN(__builtin_msa_binsl_w, "V4UiV4UiV4UiV4Ui", "nc")
+BUILTIN(__builtin_msa_binsl_d, "V2ULLiV2ULLiV2ULLiV2ULLi", "nc")
+
+BUILTIN(__builtin_msa_binsli_b, "V16UcV16UcV16UcIUi", "nc")
+BUILTIN(__builtin_msa_binsli_h, "V8UsV8UsV8UsIUi", "nc")
+BUILTIN(__builtin_msa_binsli_w, "V4UiV4UiV4UiIUi", "nc")
+BUILTIN(__builtin_msa_binsli_d, "V2ULLiV2ULLiV2ULLiIUi", "nc")
+
+BUILTIN(__builtin_msa_binsr_b, "V16UcV16UcV16UcV16Uc", "nc")
+BUILTIN(__builtin_msa_binsr_h, "V8UsV8UsV8UsV8Us", "nc")
+BUILTIN(__builtin_msa_binsr_w, "V4UiV4UiV4UiV4Ui", "nc")
+BUILTIN(__builtin_msa_binsr_d, "V2ULLiV2ULLiV2ULLiV2ULLi", "nc")
+
+BUILTIN(__builtin_msa_binsri_b, "V16UcV16UcV16UcIUi", "nc")
+BUILTIN(__builtin_msa_binsri_h, "V8UsV8UsV8UsIUi", "nc")
+BUILTIN(__builtin_msa_binsri_w, "V4UiV4UiV4UiIUi", "nc")
+BUILTIN(__builtin_msa_binsri_d, "V2ULLiV2ULLiV2ULLiIUi", "nc")
+
+BUILTIN(__builtin_msa_bmnz_v, "V16UcV16UcV16UcV16Uc", "nc")
+
+BUILTIN(__builtin_msa_bmnzi_b, "V16UcV16UcV16UcIUi", "nc")
+
+BUILTIN(__builtin_msa_bmz_v, "V16UcV16UcV16UcV16Uc", "nc")
+
+BUILTIN(__builtin_msa_bmzi_b, "V16UcV16UcV16UcIUi", "nc")
+
+BUILTIN(__builtin_msa_bneg_b, "V16UcV16UcV16Uc", "nc")
+BUILTIN(__builtin_msa_bneg_h, "V8UsV8UsV8Us", "nc")
+BUILTIN(__builtin_msa_bneg_w, "V4UiV4UiV4Ui", "nc")
+BUILTIN(__builtin_msa_bneg_d, "V2ULLiV2ULLiV2ULLi", "nc")
+
+BUILTIN(__builtin_msa_bnegi_b, "V16UcV16UcIUi", "nc")
+BUILTIN(__builtin_msa_bnegi_h, "V8UsV8UsIUi", "nc")
+BUILTIN(__builtin_msa_bnegi_w, "V4UiV4UiIUi", "nc")
+BUILTIN(__builtin_msa_bnegi_d, "V2ULLiV2ULLiIUi", "nc")
+
+BUILTIN(__builtin_msa_bnz_b, "iV16Uc", "nc")
+BUILTIN(__builtin_msa_bnz_h, "iV8Us", "nc")
+BUILTIN(__builtin_msa_bnz_w, "iV4Ui", "nc")
+BUILTIN(__builtin_msa_bnz_d, "iV2ULLi", "nc")
+
+BUILTIN(__builtin_msa_bnz_v, "iV16Uc", "nc")
+
+BUILTIN(__builtin_msa_bsel_v, "V16UcV16UcV16UcV16Uc", "nc")
+
+BUILTIN(__builtin_msa_bseli_b, "V16UcV16UcV16UcIUi", "nc")
+
+BUILTIN(__builtin_msa_bset_b, "V16UcV16UcV16Uc", "nc")
+BUILTIN(__builtin_msa_bset_h, "V8UsV8UsV8Us", "nc")
+BUILTIN(__builtin_msa_bset_w, "V4UiV4UiV4Ui", "nc")
+BUILTIN(__builtin_msa_bset_d, "V2ULLiV2ULLiV2ULLi", "nc")
+
+BUILTIN(__builtin_msa_bseti_b, "V16UcV16UcIUi", "nc")
+BUILTIN(__builtin_msa_bseti_h, "V8UsV8UsIUi", "nc")
+BUILTIN(__builtin_msa_bseti_w, "V4UiV4UiIUi", "nc")
+BUILTIN(__builtin_msa_bseti_d, "V2ULLiV2ULLiIUi", "nc")
+
+BUILTIN(__builtin_msa_bz_b, "iV16Uc", "nc")
+BUILTIN(__builtin_msa_bz_h, "iV8Us", "nc")
+BUILTIN(__builtin_msa_bz_w, "iV4Ui", "nc")
+BUILTIN(__builtin_msa_bz_d, "iV2ULLi", "nc")
+
+BUILTIN(__builtin_msa_bz_v, "iV16Uc", "nc")
+
+BUILTIN(__builtin_msa_ceq_b, "V16ScV16ScV16Sc", "nc")
+BUILTIN(__builtin_msa_ceq_h, "V8SsV8SsV8Ss", "nc")
+BUILTIN(__builtin_msa_ceq_w, "V4SiV4SiV4Si", "nc")
+BUILTIN(__builtin_msa_ceq_d, "V2SLLiV2SLLiV2SLLi", "nc")
+
+BUILTIN(__builtin_msa_ceqi_b, "V16ScV16ScISi", "nc")
+BUILTIN(__builtin_msa_ceqi_h, "V8SsV8SsISi", "nc")
+BUILTIN(__builtin_msa_ceqi_w, "V4SiV4SiISi", "nc")
+BUILTIN(__builtin_msa_ceqi_d, "V2SLLiV2SLLiISi", "nc")
+
+BUILTIN(__builtin_msa_cfcmsa, "iIi", "n")
+
+BUILTIN(__builtin_msa_cle_s_b, "V16ScV16ScV16Sc", "nc")
+BUILTIN(__builtin_msa_cle_s_h, "V8SsV8SsV8Ss", "nc")
+BUILTIN(__builtin_msa_cle_s_w, "V4SiV4SiV4Si", "nc")
+BUILTIN(__builtin_msa_cle_s_d, "V2SLLiV2SLLiV2SLLi", "nc")
+
+BUILTIN(__builtin_msa_cle_u_b, "V16ScV16UcV16Uc", "nc")
+BUILTIN(__builtin_msa_cle_u_h, "V8SsV8UsV8Us", "nc")
+BUILTIN(__builtin_msa_cle_u_w, "V4SiV4UiV4Ui", "nc")
+BUILTIN(__builtin_msa_cle_u_d, "V2SLLiV2ULLiV2ULLi", "nc")
+
+BUILTIN(__builtin_msa_clei_s_b, "V16ScV16ScISi", "nc")
+BUILTIN(__builtin_msa_clei_s_h, "V8SsV8SsISi", "nc")
+BUILTIN(__builtin_msa_clei_s_w, "V4SiV4SiISi", "nc")
+BUILTIN(__builtin_msa_clei_s_d, "V2SLLiV2SLLiISi", "nc")
+
+BUILTIN(__builtin_msa_clei_u_b, "V16ScV16UcIUi", "nc")
+BUILTIN(__builtin_msa_clei_u_h, "V8SsV8UsIUi", "nc")
+BUILTIN(__builtin_msa_clei_u_w, "V4SiV4UiIUi", "nc")
+BUILTIN(__builtin_msa_clei_u_d, "V2SLLiV2ULLiIUi", "nc")
+
+BUILTIN(__builtin_msa_clt_s_b, "V16ScV16ScV16Sc", "nc")
+BUILTIN(__builtin_msa_clt_s_h, "V8SsV8SsV8Ss", "nc")
+BUILTIN(__builtin_msa_clt_s_w, "V4SiV4SiV4Si", "nc")
+BUILTIN(__builtin_msa_clt_s_d, "V2SLLiV2SLLiV2SLLi", "nc")
+
+BUILTIN(__builtin_msa_clt_u_b, "V16ScV16UcV16Uc", "nc")
+BUILTIN(__builtin_msa_clt_u_h, "V8SsV8UsV8Us", "nc")
+BUILTIN(__builtin_msa_clt_u_w, "V4SiV4UiV4Ui", "nc")
+BUILTIN(__builtin_msa_clt_u_d, "V2SLLiV2ULLiV2ULLi", "nc")
+
+BUILTIN(__builtin_msa_clti_s_b, "V16ScV16ScISi", "nc")
+BUILTIN(__builtin_msa_clti_s_h, "V8SsV8SsISi", "nc")
+BUILTIN(__builtin_msa_clti_s_w, "V4SiV4SiISi", "nc")
+BUILTIN(__builtin_msa_clti_s_d, "V2SLLiV2SLLiISi", "nc")
+
+BUILTIN(__builtin_msa_clti_u_b, "V16ScV16UcIUi", "nc")
+BUILTIN(__builtin_msa_clti_u_h, "V8SsV8UsIUi", "nc")
+BUILTIN(__builtin_msa_clti_u_w, "V4SiV4UiIUi", "nc")
+BUILTIN(__builtin_msa_clti_u_d, "V2SLLiV2ULLiIUi", "nc")
+
+BUILTIN(__builtin_msa_copy_s_b, "iV16ScIUi", "nc")
+BUILTIN(__builtin_msa_copy_s_h, "iV8SsIUi", "nc")
+BUILTIN(__builtin_msa_copy_s_w, "iV4SiIUi", "nc")
+BUILTIN(__builtin_msa_copy_s_d, "LLiV2SLLiIUi", "nc")
+
+BUILTIN(__builtin_msa_copy_u_b, "iV16UcIUi", "nc")
+BUILTIN(__builtin_msa_copy_u_h, "iV8UsIUi", "nc")
+BUILTIN(__builtin_msa_copy_u_w, "iV4UiIUi", "nc")
+BUILTIN(__builtin_msa_copy_u_d, "LLiV2ULLiIUi", "nc")
+
+BUILTIN(__builtin_msa_ctcmsa, "vIii", "n")
+
+BUILTIN(__builtin_msa_div_s_b, "V16ScV16ScV16Sc", "nc")
+BUILTIN(__builtin_msa_div_s_h, "V8SsV8SsV8Ss", "nc")
+BUILTIN(__builtin_msa_div_s_w, "V4SiV4SiV4Si", "nc")
+BUILTIN(__builtin_msa_div_s_d, "V2SLLiV2SLLiV2SLLi", "nc")
+
+BUILTIN(__builtin_msa_div_u_b, "V16UcV16UcV16Uc", "nc")
+BUILTIN(__builtin_msa_div_u_h, "V8UsV8UsV8Us", "nc")
+BUILTIN(__builtin_msa_div_u_w, "V4UiV4UiV4Ui", "nc")
+BUILTIN(__builtin_msa_div_u_d, "V2ULLiV2ULLiV2ULLi", "nc")
+
+BUILTIN(__builtin_msa_dotp_s_h, "V8SsV16ScV16Sc", "nc")
+BUILTIN(__builtin_msa_dotp_s_w, "V4SiV8SsV8Ss", "nc")
+BUILTIN(__builtin_msa_dotp_s_d, "V2SLLiV4SiV4Si", "nc")
+
+BUILTIN(__builtin_msa_dotp_u_h, "V8UsV16UcV16Uc", "nc")
+BUILTIN(__builtin_msa_dotp_u_w, "V4UiV8UsV8Us", "nc")
+BUILTIN(__builtin_msa_dotp_u_d, "V2ULLiV4UiV4Ui", "nc")
+
+BUILTIN(__builtin_msa_dpadd_s_h, "V8SsV8SsV16ScV16Sc", "nc")
+BUILTIN(__builtin_msa_dpadd_s_w, "V4SiV4SiV8SsV8Ss", "nc")
+BUILTIN(__builtin_msa_dpadd_s_d, "V2SLLiV2SLLiV4SiV4Si", "nc")
+
+BUILTIN(__builtin_msa_dpadd_u_h, "V8UsV8UsV16UcV16Uc", "nc")
+BUILTIN(__builtin_msa_dpadd_u_w, "V4UiV4UiV8UsV8Us", "nc")
+BUILTIN(__builtin_msa_dpadd_u_d, "V2ULLiV2ULLiV4UiV4Ui", "nc")
+
+BUILTIN(__builtin_msa_dpsub_s_h, "V8SsV8SsV16ScV16Sc", "nc")
+BUILTIN(__builtin_msa_dpsub_s_w, "V4SiV4SiV8SsV8Ss", "nc")
+BUILTIN(__builtin_msa_dpsub_s_d, "V2SLLiV2SLLiV4SiV4Si", "nc")
+
+BUILTIN(__builtin_msa_dpsub_u_h, "V8UsV8UsV16UcV16Uc", "nc")
+BUILTIN(__builtin_msa_dpsub_u_w, "V4UiV4UiV8UsV8Us", "nc")
+BUILTIN(__builtin_msa_dpsub_u_d, "V2ULLiV2ULLiV4UiV4Ui", "nc")
+
+BUILTIN(__builtin_msa_fadd_w, "V4fV4fV4f", "nc")
+BUILTIN(__builtin_msa_fadd_d, "V2dV2dV2d", "nc")
+
+BUILTIN(__builtin_msa_fcaf_w, "V4iV4fV4f", "nc")
+BUILTIN(__builtin_msa_fcaf_d, "V2LLiV2dV2d", "nc")
+
+BUILTIN(__builtin_msa_fceq_w, "V4iV4fV4f", "nc")
+BUILTIN(__builtin_msa_fceq_d, "V2LLiV2dV2d", "nc")
+
+BUILTIN(__builtin_msa_fclass_w, "V4iV4f", "nc")
+BUILTIN(__builtin_msa_fclass_d, "V2LLiV2d", "nc")
+
+BUILTIN(__builtin_msa_fcle_w, "V4iV4fV4f", "nc")
+BUILTIN(__builtin_msa_fcle_d, "V2LLiV2dV2d", "nc")
+
+BUILTIN(__builtin_msa_fclt_w, "V4iV4fV4f", "nc")
+BUILTIN(__builtin_msa_fclt_d, "V2LLiV2dV2d", "nc")
+
+BUILTIN(__builtin_msa_fcne_w, "V4iV4fV4f", "nc")
+BUILTIN(__builtin_msa_fcne_d, "V2LLiV2dV2d", "nc")
+
+BUILTIN(__builtin_msa_fcor_w, "V4iV4fV4f", "nc")
+BUILTIN(__builtin_msa_fcor_d, "V2LLiV2dV2d", "nc")
+
+BUILTIN(__builtin_msa_fcueq_w, "V4iV4fV4f", "nc")
+BUILTIN(__builtin_msa_fcueq_d, "V2LLiV2dV2d", "nc")
+
+BUILTIN(__builtin_msa_fcule_w, "V4iV4fV4f", "nc")
+BUILTIN(__builtin_msa_fcule_d, "V2LLiV2dV2d", "nc")
+
+BUILTIN(__builtin_msa_fcult_w, "V4iV4fV4f", "nc")
+BUILTIN(__builtin_msa_fcult_d, "V2LLiV2dV2d", "nc")
+
+BUILTIN(__builtin_msa_fcun_w, "V4iV4fV4f", "nc")
+BUILTIN(__builtin_msa_fcun_d, "V2LLiV2dV2d", "nc")
+
+BUILTIN(__builtin_msa_fcune_w, "V4iV4fV4f", "nc")
+BUILTIN(__builtin_msa_fcune_d, "V2LLiV2dV2d", "nc")
+
+BUILTIN(__builtin_msa_fdiv_w, "V4fV4fV4f", "nc")
+BUILTIN(__builtin_msa_fdiv_d, "V2dV2dV2d", "nc")
+
+BUILTIN(__builtin_msa_fexdo_h, "V8hV4fV4f", "nc")
+BUILTIN(__builtin_msa_fexdo_w, "V4fV2dV2d", "nc")
+
+BUILTIN(__builtin_msa_fexp2_w, "V4fV4fV4i", "nc")
+BUILTIN(__builtin_msa_fexp2_d, "V2dV2dV2LLi", "nc")
+
+BUILTIN(__builtin_msa_fexupl_w, "V4fV8h", "nc")
+BUILTIN(__builtin_msa_fexupl_d, "V2dV4f", "nc")
+
+BUILTIN(__builtin_msa_fexupr_w, "V4fV8h", "nc")
+BUILTIN(__builtin_msa_fexupr_d, "V2dV4f", "nc")
+
+BUILTIN(__builtin_msa_ffint_s_w, "V4fV4Si", "nc")
+BUILTIN(__builtin_msa_ffint_s_d, "V2dV2SLLi", "nc")
+
+BUILTIN(__builtin_msa_ffint_u_w, "V4fV4Ui", "nc")
+BUILTIN(__builtin_msa_ffint_u_d, "V2dV2ULLi", "nc")
+
+// ffql uses integers since long _Fract is not implemented
+BUILTIN(__builtin_msa_ffql_w, "V4fV8Ss", "nc")
+BUILTIN(__builtin_msa_ffql_d, "V2dV4Si", "nc")
+
+// ffqr uses integers since long _Fract is not implemented
+BUILTIN(__builtin_msa_ffqr_w, "V4fV8Ss", "nc")
+BUILTIN(__builtin_msa_ffqr_d, "V2dV4Si", "nc")
+
+BUILTIN(__builtin_msa_fill_b, "V16Sci", "nc")
+BUILTIN(__builtin_msa_fill_h, "V8Ssi", "nc")
+BUILTIN(__builtin_msa_fill_w, "V4Sii", "nc")
+BUILTIN(__builtin_msa_fill_d, "V2SLLiLLi", "nc")
+
+BUILTIN(__builtin_msa_flog2_w, "V4fV4f", "nc")
+BUILTIN(__builtin_msa_flog2_d, "V2dV2d", "nc")
+
+BUILTIN(__builtin_msa_fmadd_w, "V4fV4fV4fV4f", "nc")
+BUILTIN(__builtin_msa_fmadd_d, "V2dV2dV2dV2d", "nc")
+
+BUILTIN(__builtin_msa_fmax_w, "V4fV4fV4f", "nc")
+BUILTIN(__builtin_msa_fmax_d, "V2dV2dV2d", "nc")
+
+BUILTIN(__builtin_msa_fmax_a_w, "V4fV4fV4f", "nc")
+BUILTIN(__builtin_msa_fmax_a_d, "V2dV2dV2d", "nc")
+
+BUILTIN(__builtin_msa_fmin_w, "V4fV4fV4f", "nc")
+BUILTIN(__builtin_msa_fmin_d, "V2dV2dV2d", "nc")
+
+BUILTIN(__builtin_msa_fmin_a_w, "V4fV4fV4f", "nc")
+BUILTIN(__builtin_msa_fmin_a_d, "V2dV2dV2d", "nc")
+
+BUILTIN(__builtin_msa_fmsub_w, "V4fV4fV4fV4f", "nc")
+BUILTIN(__builtin_msa_fmsub_d, "V2dV2dV2dV2d", "nc")
+
+BUILTIN(__builtin_msa_fmul_w, "V4fV4fV4f", "nc")
+BUILTIN(__builtin_msa_fmul_d, "V2dV2dV2d", "nc")
+
+BUILTIN(__builtin_msa_frint_w, "V4fV4f", "nc")
+BUILTIN(__builtin_msa_frint_d, "V2dV2d", "nc")
+
+BUILTIN(__builtin_msa_frcp_w, "V4fV4f", "nc")
+BUILTIN(__builtin_msa_frcp_d, "V2dV2d", "nc")
+
+BUILTIN(__builtin_msa_frsqrt_w, "V4fV4f", "nc")
+BUILTIN(__builtin_msa_frsqrt_d, "V2dV2d", "nc")
+
+BUILTIN(__builtin_msa_fsaf_w, "V4iV4fV4f", "nc")
+BUILTIN(__builtin_msa_fsaf_d, "V2LLiV2dV2d", "nc")
+
+BUILTIN(__builtin_msa_fseq_w, "V4iV4fV4f", "nc")
+BUILTIN(__builtin_msa_fseq_d, "V2LLiV2dV2d", "nc")
+
+BUILTIN(__builtin_msa_fsle_w, "V4iV4fV4f", "nc")
+BUILTIN(__builtin_msa_fsle_d, "V2LLiV2dV2d", "nc")
+
+BUILTIN(__builtin_msa_fslt_w, "V4iV4fV4f", "nc")
+BUILTIN(__builtin_msa_fslt_d, "V2LLiV2dV2d", "nc")
+
+BUILTIN(__builtin_msa_fsne_w, "V4iV4fV4f", "nc")
+BUILTIN(__builtin_msa_fsne_d, "V2LLiV2dV2d", "nc")
+
+BUILTIN(__builtin_msa_fsor_w, "V4iV4fV4f", "nc")
+BUILTIN(__builtin_msa_fsor_d, "V2LLiV2dV2d", "nc")
+
+BUILTIN(__builtin_msa_fsqrt_w, "V4fV4f", "nc")
+BUILTIN(__builtin_msa_fsqrt_d, "V2dV2d", "nc")
+
+BUILTIN(__builtin_msa_fsub_w, "V4fV4fV4f", "nc")
+BUILTIN(__builtin_msa_fsub_d, "V2dV2dV2d", "nc")
+
+BUILTIN(__builtin_msa_fsueq_w, "V4iV4fV4f", "nc")
+BUILTIN(__builtin_msa_fsueq_d, "V2LLiV2dV2d", "nc")
+
+BUILTIN(__builtin_msa_fsule_w, "V4iV4fV4f", "nc")
+BUILTIN(__builtin_msa_fsule_d, "V2LLiV2dV2d", "nc")
+
+BUILTIN(__builtin_msa_fsult_w, "V4iV4fV4f", "nc")
+BUILTIN(__builtin_msa_fsult_d, "V2LLiV2dV2d", "nc")
+
+BUILTIN(__builtin_msa_fsun_w, "V4iV4fV4f", "nc")
+BUILTIN(__builtin_msa_fsun_d, "V2LLiV2dV2d", "nc")
+
+BUILTIN(__builtin_msa_fsune_w, "V4iV4fV4f", "nc")
+BUILTIN(__builtin_msa_fsune_d, "V2LLiV2dV2d", "nc")
+
+BUILTIN(__builtin_msa_ftint_s_w, "V4SiV4f", "nc")
+BUILTIN(__builtin_msa_ftint_s_d, "V2SLLiV2d", "nc")
+
+BUILTIN(__builtin_msa_ftint_u_w, "V4UiV4f", "nc")
+BUILTIN(__builtin_msa_ftint_u_d, "V2ULLiV2d", "nc")
+
+BUILTIN(__builtin_msa_ftq_h, "V4UiV4fV4f", "nc")
+BUILTIN(__builtin_msa_ftq_w, "V2ULLiV2dV2d", "nc")
+
+BUILTIN(__builtin_msa_ftrunc_s_w, "V4SiV4f", "nc")
+BUILTIN(__builtin_msa_ftrunc_s_d, "V2SLLiV2d", "nc")
+
+BUILTIN(__builtin_msa_ftrunc_u_w, "V4UiV4f", "nc")
+BUILTIN(__builtin_msa_ftrunc_u_d, "V2ULLiV2d", "nc")
+
+BUILTIN(__builtin_msa_hadd_s_h, "V8SsV16ScV16Sc", "nc")
+BUILTIN(__builtin_msa_hadd_s_w, "V4SiV8SsV8Ss", "nc")
+BUILTIN(__builtin_msa_hadd_s_d, "V2SLLiV4SiV4Si", "nc")
+
+BUILTIN(__builtin_msa_hadd_u_h, "V8UsV16UcV16Uc", "nc")
+BUILTIN(__builtin_msa_hadd_u_w, "V4UiV8UsV8Us", "nc")
+BUILTIN(__builtin_msa_hadd_u_d, "V2ULLiV4UiV4Ui", "nc")
+
+BUILTIN(__builtin_msa_hsub_s_h, "V8SsV16ScV16Sc", "nc")
+BUILTIN(__builtin_msa_hsub_s_w, "V4SiV8SsV8Ss", "nc")
+BUILTIN(__builtin_msa_hsub_s_d, "V2SLLiV4SiV4Si", "nc")
+
+BUILTIN(__builtin_msa_hsub_u_h, "V8UsV16UcV16Uc", "nc")
+BUILTIN(__builtin_msa_hsub_u_w, "V4UiV8UsV8Us", "nc")
+BUILTIN(__builtin_msa_hsub_u_d, "V2ULLiV4UiV4Ui", "nc")
+
+BUILTIN(__builtin_msa_ilvev_b, "V16cV16cV16c", "nc")
+BUILTIN(__builtin_msa_ilvev_h, "V8sV8sV8s", "nc")
+BUILTIN(__builtin_msa_ilvev_w, "V4iV4iV4i", "nc")
+BUILTIN(__builtin_msa_ilvev_d, "V2LLiV2LLiV2LLi", "nc")
+
+BUILTIN(__builtin_msa_ilvl_b, "V16cV16cV16c", "nc")
+BUILTIN(__builtin_msa_ilvl_h, "V8sV8sV8s", "nc")
+BUILTIN(__builtin_msa_ilvl_w, "V4iV4iV4i", "nc")
+BUILTIN(__builtin_msa_ilvl_d, "V2LLiV2LLiV2LLi", "nc")
+
+BUILTIN(__builtin_msa_ilvod_b, "V16cV16cV16c", "nc")
+BUILTIN(__builtin_msa_ilvod_h, "V8sV8sV8s", "nc")
+BUILTIN(__builtin_msa_ilvod_w, "V4iV4iV4i", "nc")
+BUILTIN(__builtin_msa_ilvod_d, "V2LLiV2LLiV2LLi", "nc")
+
+BUILTIN(__builtin_msa_ilvr_b, "V16cV16cV16c", "nc")
+BUILTIN(__builtin_msa_ilvr_h, "V8sV8sV8s", "nc")
+BUILTIN(__builtin_msa_ilvr_w, "V4iV4iV4i", "nc")
+BUILTIN(__builtin_msa_ilvr_d, "V2LLiV2LLiV2LLi", "nc")
+
+BUILTIN(__builtin_msa_insert_b, "V16ScV16ScIUii", "nc")
+BUILTIN(__builtin_msa_insert_h, "V8SsV8SsIUii", "nc")
+BUILTIN(__builtin_msa_insert_w, "V4SiV4SiIUii", "nc")
+BUILTIN(__builtin_msa_insert_d, "V2SLLiV2SLLiIUiLLi", "nc")
+
+BUILTIN(__builtin_msa_insve_b, "V16ScV16ScIUiV16Sc", "nc")
+BUILTIN(__builtin_msa_insve_h, "V8SsV8SsIUiV8Ss", "nc")
+BUILTIN(__builtin_msa_insve_w, "V4SiV4SiIUiV4Si", "nc")
+BUILTIN(__builtin_msa_insve_d, "V2SLLiV2SLLiIUiV2SLLi", "nc")
+
+BUILTIN(__builtin_msa_ld_b, "V16Scv*Ii", "nc")
+BUILTIN(__builtin_msa_ld_h, "V8Ssv*Ii", "nc")
+BUILTIN(__builtin_msa_ld_w, "V4Siv*Ii", "nc")
+BUILTIN(__builtin_msa_ld_d, "V2SLLiv*Ii", "nc")
+
+BUILTIN(__builtin_msa_ldi_b, "V16cIi", "nc")
+BUILTIN(__builtin_msa_ldi_h, "V8sIi", "nc")
+BUILTIN(__builtin_msa_ldi_w, "V4iIi", "nc")
+BUILTIN(__builtin_msa_ldi_d, "V2LLiIi", "nc")
+
+BUILTIN(__builtin_msa_madd_q_h, "V8SsV8SsV8SsV8Ss", "nc")
+BUILTIN(__builtin_msa_madd_q_w, "V4SiV4SiV4SiV4Si", "nc")
+
+BUILTIN(__builtin_msa_maddr_q_h, "V8SsV8SsV8SsV8Ss", "nc")
+BUILTIN(__builtin_msa_maddr_q_w, "V4SiV4SiV4SiV4Si", "nc")
+
+BUILTIN(__builtin_msa_maddv_b, "V16ScV16ScV16ScV16Sc", "nc")
+BUILTIN(__builtin_msa_maddv_h, "V8SsV8SsV8SsV8Ss", "nc")
+BUILTIN(__builtin_msa_maddv_w, "V4SiV4SiV4SiV4Si", "nc")
+BUILTIN(__builtin_msa_maddv_d, "V2SLLiV2SLLiV2SLLiV2SLLi", "nc")
+
+BUILTIN(__builtin_msa_max_a_b, "V16ScV16ScV16Sc", "nc")
+BUILTIN(__builtin_msa_max_a_h, "V8SsV8SsV8Ss", "nc")
+BUILTIN(__builtin_msa_max_a_w, "V4SiV4SiV4Si", "nc")
+BUILTIN(__builtin_msa_max_a_d, "V2SLLiV2SLLiV2SLLi", "nc")
+
+BUILTIN(__builtin_msa_max_s_b, "V16ScV16ScV16Sc", "nc")
+BUILTIN(__builtin_msa_max_s_h, "V8SsV8SsV8Ss", "nc")
+BUILTIN(__builtin_msa_max_s_w, "V4SiV4SiV4Si", "nc")
+BUILTIN(__builtin_msa_max_s_d, "V2SLLiV2SLLiV2SLLi", "nc")
+
+BUILTIN(__builtin_msa_max_u_b, "V16UcV16UcV16Uc", "nc")
+BUILTIN(__builtin_msa_max_u_h, "V8UsV8UsV8Us", "nc")
+BUILTIN(__builtin_msa_max_u_w, "V4UiV4UiV4Ui", "nc")
+BUILTIN(__builtin_msa_max_u_d, "V2ULLiV2ULLiV2ULLi", "nc")
+
+BUILTIN(__builtin_msa_maxi_s_b, "V16ScV16ScIi", "nc")
+BUILTIN(__builtin_msa_maxi_s_h, "V8SsV8SsIi", "nc")
+BUILTIN(__builtin_msa_maxi_s_w, "V4SiV4SiIi", "nc")
+BUILTIN(__builtin_msa_maxi_s_d, "V2SLLiV2SLLiIi", "nc")
+
+BUILTIN(__builtin_msa_maxi_u_b, "V16UcV16UcIi", "nc")
+BUILTIN(__builtin_msa_maxi_u_h, "V8UsV8UsIi", "nc")
+BUILTIN(__builtin_msa_maxi_u_w, "V4UiV4UiIi", "nc")
+BUILTIN(__builtin_msa_maxi_u_d, "V2ULLiV2ULLiIi", "nc")
+
+BUILTIN(__builtin_msa_min_a_b, "V16ScV16ScV16Sc", "nc")
+BUILTIN(__builtin_msa_min_a_h, "V8SsV8SsV8Ss", "nc")
+BUILTIN(__builtin_msa_min_a_w, "V4SiV4SiV4Si", "nc")
+BUILTIN(__builtin_msa_min_a_d, "V2SLLiV2SLLiV2SLLi", "nc")
+
+BUILTIN(__builtin_msa_min_s_b, "V16ScV16ScV16Sc", "nc")
+BUILTIN(__builtin_msa_min_s_h, "V8SsV8SsV8Ss", "nc")
+BUILTIN(__builtin_msa_min_s_w, "V4SiV4SiV4Si", "nc")
+BUILTIN(__builtin_msa_min_s_d, "V2SLLiV2SLLiV2SLLi", "nc")
+
+BUILTIN(__builtin_msa_min_u_b, "V16UcV16UcV16Uc", "nc")
+BUILTIN(__builtin_msa_min_u_h, "V8UsV8UsV8Us", "nc")
+BUILTIN(__builtin_msa_min_u_w, "V4UiV4UiV4Ui", "nc")
+BUILTIN(__builtin_msa_min_u_d, "V2ULLiV2ULLiV2ULLi", "nc")
+
+BUILTIN(__builtin_msa_mini_s_b, "V16ScV16ScIi", "nc")
+BUILTIN(__builtin_msa_mini_s_h, "V8SsV8SsIi", "nc")
+BUILTIN(__builtin_msa_mini_s_w, "V4SiV4SiIi", "nc")
+BUILTIN(__builtin_msa_mini_s_d, "V2SLLiV2SLLiIi", "nc")
+
+BUILTIN(__builtin_msa_mini_u_b, "V16UcV16UcIi", "nc")
+BUILTIN(__builtin_msa_mini_u_h, "V8UsV8UsIi", "nc")
+BUILTIN(__builtin_msa_mini_u_w, "V4UiV4UiIi", "nc")
+BUILTIN(__builtin_msa_mini_u_d, "V2ULLiV2ULLiIi", "nc")
+
+BUILTIN(__builtin_msa_mod_s_b, "V16ScV16ScV16Sc", "nc")
+BUILTIN(__builtin_msa_mod_s_h, "V8SsV8SsV8Ss", "nc")
+BUILTIN(__builtin_msa_mod_s_w, "V4SiV4SiV4Si", "nc")
+BUILTIN(__builtin_msa_mod_s_d, "V2SLLiV2SLLiV2SLLi", "nc")
+
+BUILTIN(__builtin_msa_mod_u_b, "V16UcV16UcV16Uc", "nc")
+BUILTIN(__builtin_msa_mod_u_h, "V8UsV8UsV8Us", "nc")
+BUILTIN(__builtin_msa_mod_u_w, "V4UiV4UiV4Ui", "nc")
+BUILTIN(__builtin_msa_mod_u_d, "V2ULLiV2ULLiV2ULLi", "nc")
+
+BUILTIN(__builtin_msa_move_v, "V16ScV16Sc", "nc")
+
+BUILTIN(__builtin_msa_msub_q_h, "V8SsV8SsV8SsV8Ss", "nc")
+BUILTIN(__builtin_msa_msub_q_w, "V4SiV4SiV4SiV4Si", "nc")
+
+BUILTIN(__builtin_msa_msubr_q_h, "V8SsV8SsV8SsV8Ss", "nc")
+BUILTIN(__builtin_msa_msubr_q_w, "V4SiV4SiV4SiV4Si", "nc")
+
+BUILTIN(__builtin_msa_msubv_b, "V16ScV16ScV16ScV16Sc", "nc")
+BUILTIN(__builtin_msa_msubv_h, "V8SsV8SsV8SsV8Ss", "nc")
+BUILTIN(__builtin_msa_msubv_w, "V4SiV4SiV4SiV4Si", "nc")
+BUILTIN(__builtin_msa_msubv_d, "V2SLLiV2SLLiV2SLLiV2SLLi", "nc")
+
+BUILTIN(__builtin_msa_mul_q_h, "V8SsV8SsV8Ss", "nc")
+BUILTIN(__builtin_msa_mul_q_w, "V4SiV4SiV4Si", "nc")
+
+BUILTIN(__builtin_msa_mulr_q_h, "V8SsV8SsV8Ss", "nc")
+BUILTIN(__builtin_msa_mulr_q_w, "V4SiV4SiV4Si", "nc")
+
+BUILTIN(__builtin_msa_mulv_b, "V16ScV16ScV16Sc", "nc")
+BUILTIN(__builtin_msa_mulv_h, "V8SsV8SsV8Ss", "nc")
+BUILTIN(__builtin_msa_mulv_w, "V4SiV4SiV4Si", "nc")
+BUILTIN(__builtin_msa_mulv_d, "V2SLLiV2SLLiV2SLLi", "nc")
+
+BUILTIN(__builtin_msa_nloc_b, "V16ScV16Sc", "nc")
+BUILTIN(__builtin_msa_nloc_h, "V8SsV8Ss", "nc")
+BUILTIN(__builtin_msa_nloc_w, "V4SiV4Si", "nc")
+BUILTIN(__builtin_msa_nloc_d, "V2SLLiV2SLLi", "nc")
+
+BUILTIN(__builtin_msa_nlzc_b, "V16ScV16Sc", "nc")
+BUILTIN(__builtin_msa_nlzc_h, "V8SsV8Ss", "nc")
+BUILTIN(__builtin_msa_nlzc_w, "V4SiV4Si", "nc")
+BUILTIN(__builtin_msa_nlzc_d, "V2SLLiV2SLLi", "nc")
+
+BUILTIN(__builtin_msa_nor_v, "V16UcV16UcV16Uc", "nc")
+
+BUILTIN(__builtin_msa_nori_b, "V16UcV16cIUi", "nc")
+
+BUILTIN(__builtin_msa_or_v, "V16UcV16UcV16Uc", "nc")
+
+BUILTIN(__builtin_msa_ori_b, "V16UcV16UcIUi", "nc")
+
+BUILTIN(__builtin_msa_pckev_b, "V16cV16cV16c", "nc")
+BUILTIN(__builtin_msa_pckev_h, "V8sV8sV8s", "nc")
+BUILTIN(__builtin_msa_pckev_w, "V4iV4iV4i", "nc")
+BUILTIN(__builtin_msa_pckev_d, "V2LLiV2LLiV2LLi", "nc")
+
+BUILTIN(__builtin_msa_pckod_b, "V16cV16cV16c", "nc")
+BUILTIN(__builtin_msa_pckod_h, "V8sV8sV8s", "nc")
+BUILTIN(__builtin_msa_pckod_w, "V4iV4iV4i", "nc")
+BUILTIN(__builtin_msa_pckod_d, "V2LLiV2LLiV2LLi", "nc")
+
+BUILTIN(__builtin_msa_pcnt_b, "V16ScV16Sc", "nc")
+BUILTIN(__builtin_msa_pcnt_h, "V8SsV8Ss", "nc")
+BUILTIN(__builtin_msa_pcnt_w, "V4SiV4Si", "nc")
+BUILTIN(__builtin_msa_pcnt_d, "V2SLLiV2SLLi", "nc")
+
+BUILTIN(__builtin_msa_sat_s_b, "V16ScV16ScIUi", "nc")
+BUILTIN(__builtin_msa_sat_s_h, "V8SsV8SsIUi", "nc")
+BUILTIN(__builtin_msa_sat_s_w, "V4SiV4SiIUi", "nc")
+BUILTIN(__builtin_msa_sat_s_d, "V2SLLiV2SLLiIUi", "nc")
+
+BUILTIN(__builtin_msa_sat_u_b, "V16UcV16UcIUi", "nc")
+BUILTIN(__builtin_msa_sat_u_h, "V8UsV8UsIUi", "nc")
+BUILTIN(__builtin_msa_sat_u_w, "V4UiV4UiIUi", "nc")
+BUILTIN(__builtin_msa_sat_u_d, "V2ULLiV2ULLiIUi", "nc")
+
+BUILTIN(__builtin_msa_shf_b, "V16cV16cIUi", "nc")
+BUILTIN(__builtin_msa_shf_h, "V8sV8sIUi", "nc")
+BUILTIN(__builtin_msa_shf_w, "V4iV4iIUi", "nc")
+
+BUILTIN(__builtin_msa_sld_b, "V16cV16cV16cUi", "nc")
+BUILTIN(__builtin_msa_sld_h, "V8sV8sV8sUi", "nc")
+BUILTIN(__builtin_msa_sld_w, "V4iV4iV4iUi", "nc")
+BUILTIN(__builtin_msa_sld_d, "V2LLiV2LLiV2LLiUi", "nc")
+
+BUILTIN(__builtin_msa_sldi_b, "V16cV16cV16cIUi", "nc")
+BUILTIN(__builtin_msa_sldi_h, "V8sV8sV8sIUi", "nc")
+BUILTIN(__builtin_msa_sldi_w, "V4iV4iV4iIUi", "nc")
+BUILTIN(__builtin_msa_sldi_d, "V2LLiV2LLiV2LLiIUi", "nc")
+
+BUILTIN(__builtin_msa_sll_b, "V16cV16cV16c", "nc")
+BUILTIN(__builtin_msa_sll_h, "V8sV8sV8s", "nc")
+BUILTIN(__builtin_msa_sll_w, "V4iV4iV4i", "nc")
+BUILTIN(__builtin_msa_sll_d, "V2LLiV2LLiV2LLi", "nc")
+
+BUILTIN(__builtin_msa_slli_b, "V16cV16cIUi", "nc")
+BUILTIN(__builtin_msa_slli_h, "V8sV8sIUi", "nc")
+BUILTIN(__builtin_msa_slli_w, "V4iV4iIUi", "nc")
+BUILTIN(__builtin_msa_slli_d, "V2LLiV2LLiIUi", "nc")
+
+BUILTIN(__builtin_msa_splat_b, "V16cV16cUi", "nc")
+BUILTIN(__builtin_msa_splat_h, "V8sV8sUi", "nc")
+BUILTIN(__builtin_msa_splat_w, "V4iV4iUi", "nc")
+BUILTIN(__builtin_msa_splat_d, "V2LLiV2LLiUi", "nc")
+
+BUILTIN(__builtin_msa_splati_b, "V16cV16cIUi", "nc")
+BUILTIN(__builtin_msa_splati_h, "V8sV8sIUi", "nc")
+BUILTIN(__builtin_msa_splati_w, "V4iV4iIUi", "nc")
+BUILTIN(__builtin_msa_splati_d, "V2LLiV2LLiIUi", "nc")
+
+BUILTIN(__builtin_msa_sra_b, "V16cV16cV16c", "nc")
+BUILTIN(__builtin_msa_sra_h, "V8sV8sV8s", "nc")
+BUILTIN(__builtin_msa_sra_w, "V4iV4iV4i", "nc")
+BUILTIN(__builtin_msa_sra_d, "V2LLiV2LLiV2LLi", "nc")
+
+BUILTIN(__builtin_msa_srai_b, "V16cV16cIUi", "nc")
+BUILTIN(__builtin_msa_srai_h, "V8sV8sIUi", "nc")
+BUILTIN(__builtin_msa_srai_w, "V4iV4iIUi", "nc")
+BUILTIN(__builtin_msa_srai_d, "V2LLiV2LLiIUi", "nc")
+
+BUILTIN(__builtin_msa_srar_b, "V16cV16cV16c", "nc")
+BUILTIN(__builtin_msa_srar_h, "V8sV8sV8s", "nc")
+BUILTIN(__builtin_msa_srar_w, "V4iV4iV4i", "nc")
+BUILTIN(__builtin_msa_srar_d, "V2LLiV2LLiV2LLi", "nc")
+
+BUILTIN(__builtin_msa_srari_b, "V16cV16cIUi", "nc")
+BUILTIN(__builtin_msa_srari_h, "V8sV8sIUi", "nc")
+BUILTIN(__builtin_msa_srari_w, "V4iV4iIUi", "nc")
+BUILTIN(__builtin_msa_srari_d, "V2LLiV2LLiIUi", "nc")
+
+BUILTIN(__builtin_msa_srl_b, "V16cV16cV16c", "nc")
+BUILTIN(__builtin_msa_srl_h, "V8sV8sV8s", "nc")
+BUILTIN(__builtin_msa_srl_w, "V4iV4iV4i", "nc")
+BUILTIN(__builtin_msa_srl_d, "V2LLiV2LLiV2LLi", "nc")
+
+BUILTIN(__builtin_msa_srli_b, "V16cV16cIUi", "nc")
+BUILTIN(__builtin_msa_srli_h, "V8sV8sIUi", "nc")
+BUILTIN(__builtin_msa_srli_w, "V4iV4iIUi", "nc")
+BUILTIN(__builtin_msa_srli_d, "V2LLiV2LLiIUi", "nc")
+
+BUILTIN(__builtin_msa_srlr_b, "V16cV16cV16c", "nc")
+BUILTIN(__builtin_msa_srlr_h, "V8sV8sV8s", "nc")
+BUILTIN(__builtin_msa_srlr_w, "V4iV4iV4i", "nc")
+BUILTIN(__builtin_msa_srlr_d, "V2LLiV2LLiV2LLi", "nc")
+
+BUILTIN(__builtin_msa_srlri_b, "V16cV16cIUi", "nc")
+BUILTIN(__builtin_msa_srlri_h, "V8sV8sIUi", "nc")
+BUILTIN(__builtin_msa_srlri_w, "V4iV4iIUi", "nc")
+BUILTIN(__builtin_msa_srlri_d, "V2LLiV2LLiIUi", "nc")
+
+BUILTIN(__builtin_msa_st_b, "vV16Scv*Ii", "nc")
+BUILTIN(__builtin_msa_st_h, "vV8Ssv*Ii", "nc")
+BUILTIN(__builtin_msa_st_w, "vV4Siv*Ii", "nc")
+BUILTIN(__builtin_msa_st_d, "vV2SLLiv*Ii", "nc")
+
+BUILTIN(__builtin_msa_subs_s_b, "V16ScV16ScV16Sc", "nc")
+BUILTIN(__builtin_msa_subs_s_h, "V8SsV8SsV8Ss", "nc")
+BUILTIN(__builtin_msa_subs_s_w, "V4SiV4SiV4Si", "nc")
+BUILTIN(__builtin_msa_subs_s_d, "V2SLLiV2SLLiV2SLLi", "nc")
+
+BUILTIN(__builtin_msa_subs_u_b, "V16UcV16UcV16Uc", "nc")
+BUILTIN(__builtin_msa_subs_u_h, "V8UsV8UsV8Us", "nc")
+BUILTIN(__builtin_msa_subs_u_w, "V4UiV4UiV4Ui", "nc")
+BUILTIN(__builtin_msa_subs_u_d, "V2ULLiV2ULLiV2ULLi", "nc")
+
+BUILTIN(__builtin_msa_subsus_u_b, "V16UcV16UcV16Sc", "nc")
+BUILTIN(__builtin_msa_subsus_u_h, "V8UsV8UsV8Ss", "nc")
+BUILTIN(__builtin_msa_subsus_u_w, "V4UiV4UiV4Si", "nc")
+BUILTIN(__builtin_msa_subsus_u_d, "V2ULLiV2ULLiV2SLLi", "nc")
+
+BUILTIN(__builtin_msa_subsuu_s_b, "V16ScV16UcV16Uc", "nc")
+BUILTIN(__builtin_msa_subsuu_s_h, "V8SsV8UsV8Us", "nc")
+BUILTIN(__builtin_msa_subsuu_s_w, "V4SiV4UiV4Ui", "nc")
+BUILTIN(__builtin_msa_subsuu_s_d, "V2SLLiV2ULLiV2ULLi", "nc")
+
+BUILTIN(__builtin_msa_subv_b, "V16cV16cV16c", "nc")
+BUILTIN(__builtin_msa_subv_h, "V8sV8sV8s", "nc")
+BUILTIN(__builtin_msa_subv_w, "V4iV4iV4i", "nc")
+BUILTIN(__builtin_msa_subv_d, "V2LLiV2LLiV2LLi", "nc")
+
+BUILTIN(__builtin_msa_subvi_b, "V16cV16cIUi", "nc")
+BUILTIN(__builtin_msa_subvi_h, "V8sV8sIUi", "nc")
+BUILTIN(__builtin_msa_subvi_w, "V4iV4iIUi", "nc")
+BUILTIN(__builtin_msa_subvi_d, "V2LLiV2LLiIUi", "nc")
+
+BUILTIN(__builtin_msa_vshf_b, "V16cV16cV16cV16c", "nc")
+BUILTIN(__builtin_msa_vshf_h, "V8sV8sV8sV8s", "nc")
+BUILTIN(__builtin_msa_vshf_w, "V4iV4iV4iV4i", "nc")
+BUILTIN(__builtin_msa_vshf_d, "V2LLiV2LLiV2LLiV2LLi", "nc")
+
+BUILTIN(__builtin_msa_xor_v, "V16cV16cV16c", "nc")
+
+BUILTIN(__builtin_msa_xori_b, "V16cV16cIUi", "nc")
+
+#undef BUILTIN
diff --git a/contrib/llvm/tools/clang/include/clang/Basic/BuiltinsNEON.def b/contrib/llvm/tools/clang/include/clang/Basic/BuiltinsNEON.def
new file mode 100644
index 0000000..7800ae69
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Basic/BuiltinsNEON.def
@@ -0,0 +1,21 @@
+//===--- BuiltinsNEON.def - NEON 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 NEON-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.
+
+#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/BuiltinsNVPTX.def b/contrib/llvm/tools/clang/include/clang/Basic/BuiltinsNVPTX.def
new file mode 100644
index 0000000..3ab6413
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Basic/BuiltinsNVPTX.def
@@ -0,0 +1,569 @@
+//===--- BuiltinsPTX.def - PTX 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 PTX-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.
+
+// Builtins retained from previous PTX back-end
+BUILTIN(__builtin_ptx_read_tid_x, "i", "nc")
+BUILTIN(__builtin_ptx_read_tid_y, "i", "nc")
+BUILTIN(__builtin_ptx_read_tid_z, "i", "nc")
+BUILTIN(__builtin_ptx_read_tid_w, "i", "nc")
+
+BUILTIN(__builtin_ptx_read_ntid_x, "i", "nc")
+BUILTIN(__builtin_ptx_read_ntid_y, "i", "nc")
+BUILTIN(__builtin_ptx_read_ntid_z, "i", "nc")
+BUILTIN(__builtin_ptx_read_ntid_w, "i", "nc")
+
+BUILTIN(__builtin_ptx_read_ctaid_x, "i", "nc")
+BUILTIN(__builtin_ptx_read_ctaid_y, "i", "nc")
+BUILTIN(__builtin_ptx_read_ctaid_z, "i", "nc")
+BUILTIN(__builtin_ptx_read_ctaid_w, "i", "nc")
+
+BUILTIN(__builtin_ptx_read_nctaid_x, "i", "nc")
+BUILTIN(__builtin_ptx_read_nctaid_y, "i", "nc")
+BUILTIN(__builtin_ptx_read_nctaid_z, "i", "nc")
+BUILTIN(__builtin_ptx_read_nctaid_w, "i", "nc")
+
+BUILTIN(__builtin_ptx_read_laneid, "i", "nc")
+BUILTIN(__builtin_ptx_read_warpid, "i", "nc")
+BUILTIN(__builtin_ptx_read_nwarpid, "i", "nc")
+
+BUILTIN(__builtin_ptx_read_smid, "i", "nc")
+BUILTIN(__builtin_ptx_read_nsmid, "i", "nc")
+BUILTIN(__builtin_ptx_read_gridid, "i", "nc")
+
+BUILTIN(__builtin_ptx_read_lanemask_eq, "i", "nc")
+BUILTIN(__builtin_ptx_read_lanemask_le, "i", "nc")
+BUILTIN(__builtin_ptx_read_lanemask_lt, "i", "nc")
+BUILTIN(__builtin_ptx_read_lanemask_ge, "i", "nc")
+BUILTIN(__builtin_ptx_read_lanemask_gt, "i", "nc")
+
+BUILTIN(__builtin_ptx_read_clock, "i", "n")
+BUILTIN(__builtin_ptx_read_clock64, "LLi", "n")
+
+BUILTIN(__builtin_ptx_read_pm0, "i", "n")
+BUILTIN(__builtin_ptx_read_pm1, "i", "n")
+BUILTIN(__builtin_ptx_read_pm2, "i", "n")
+BUILTIN(__builtin_ptx_read_pm3, "i", "n")
+
+BUILTIN(__builtin_ptx_bar_sync, "vi", "n")
+
+
+// Builtins exposed as part of NVVM
+// MISC
+
+BUILTIN(__nvvm_clz_i, "ii", "")
+BUILTIN(__nvvm_clz_ll, "iLLi", "")
+BUILTIN(__nvvm_popc_i, "ii", "")
+BUILTIN(__nvvm_popc_ll, "iLLi", "")
+BUILTIN(__nvvm_prmt, "UiUiUiUi", "")
+
+// Min Max
+
+BUILTIN(__nvvm_min_i, "iii", "")
+BUILTIN(__nvvm_min_ui, "UiUiUi", "")
+BUILTIN(__nvvm_min_ll, "LLiLLiLLi", "")
+BUILTIN(__nvvm_min_ull, "ULLiULLiULLi", "")
+
+BUILTIN(__nvvm_max_i, "iii", "")
+BUILTIN(__nvvm_max_ui, "UiUiUi", "")
+BUILTIN(__nvvm_max_ll, "LLiLLiLLi", "")
+BUILTIN(__nvvm_max_ull, "ULLiULLiULLi", "")
+
+BUILTIN(__nvvm_fmax_ftz_f, "fff", "")
+BUILTIN(__nvvm_fmax_f, "fff", "")
+BUILTIN(__nvvm_fmin_ftz_f, "fff", "")
+BUILTIN(__nvvm_fmin_f, "fff", "")
+
+BUILTIN(__nvvm_fmax_d, "ddd", "")
+BUILTIN(__nvvm_fmin_d, "ddd", "")
+
+// Multiplication
+
+BUILTIN(__nvvm_mulhi_i, "iii", "")
+BUILTIN(__nvvm_mulhi_ui, "UiUiUi", "")
+BUILTIN(__nvvm_mulhi_ll, "LLiLLiLLi", "")
+BUILTIN(__nvvm_mulhi_ull, "ULLiULLiULLi", "")
+
+BUILTIN(__nvvm_mul_rn_ftz_f, "fff", "")
+BUILTIN(__nvvm_mul_rn_f, "fff", "")
+BUILTIN(__nvvm_mul_rz_ftz_f, "fff", "")
+BUILTIN(__nvvm_mul_rz_f, "fff", "")
+BUILTIN(__nvvm_mul_rm_ftz_f, "fff", "")
+BUILTIN(__nvvm_mul_rm_f, "fff", "")
+BUILTIN(__nvvm_mul_rp_ftz_f, "fff", "")
+BUILTIN(__nvvm_mul_rp_f, "fff", "")
+
+BUILTIN(__nvvm_mul_rn_d, "ddd", "")
+BUILTIN(__nvvm_mul_rz_d, "ddd", "")
+BUILTIN(__nvvm_mul_rm_d, "ddd", "")
+BUILTIN(__nvvm_mul_rp_d, "ddd", "")
+
+BUILTIN(__nvvm_mul24_i, "iii", "")
+BUILTIN(__nvvm_mul24_ui, "UiUiUi", "")
+
+// Div
+
+BUILTIN(__nvvm_div_approx_ftz_f, "fff", "")
+BUILTIN(__nvvm_div_approx_f, "fff", "")
+
+BUILTIN(__nvvm_div_rn_ftz_f, "fff", "")
+BUILTIN(__nvvm_div_rn_f, "fff", "")
+BUILTIN(__nvvm_div_rz_ftz_f, "fff", "")
+BUILTIN(__nvvm_div_rz_f, "fff", "")
+BUILTIN(__nvvm_div_rm_ftz_f, "fff", "")
+BUILTIN(__nvvm_div_rm_f, "fff", "")
+BUILTIN(__nvvm_div_rp_ftz_f, "fff", "")
+BUILTIN(__nvvm_div_rp_f, "fff", "")
+
+BUILTIN(__nvvm_div_rn_d, "ddd", "")
+BUILTIN(__nvvm_div_rz_d, "ddd", "")
+BUILTIN(__nvvm_div_rm_d, "ddd", "")
+BUILTIN(__nvvm_div_rp_d, "ddd", "")
+
+// Brev
+
+BUILTIN(__nvvm_brev32, "UiUi", "")
+BUILTIN(__nvvm_brev64, "ULLiULLi", "")
+
+// Sad
+
+BUILTIN(__nvvm_sad_i, "iiii", "")
+BUILTIN(__nvvm_sad_ui, "UiUiUiUi", "")
+
+// Floor, Ceil
+
+BUILTIN(__nvvm_floor_ftz_f, "ff", "")
+BUILTIN(__nvvm_floor_f, "ff", "")
+BUILTIN(__nvvm_floor_d, "dd", "")
+
+BUILTIN(__nvvm_ceil_ftz_f, "ff", "")
+BUILTIN(__nvvm_ceil_f, "ff", "")
+BUILTIN(__nvvm_ceil_d, "dd", "")
+
+// Abs
+
+BUILTIN(__nvvm_abs_i, "ii", "")
+BUILTIN(__nvvm_abs_ll, "LLiLLi", "")
+
+BUILTIN(__nvvm_fabs_ftz_f, "ff", "")
+BUILTIN(__nvvm_fabs_f, "ff", "")
+BUILTIN(__nvvm_fabs_d, "dd", "")
+
+// Round
+
+BUILTIN(__nvvm_round_ftz_f, "ff", "")
+BUILTIN(__nvvm_round_f, "ff", "")
+BUILTIN(__nvvm_round_d, "dd", "")
+
+// Trunc
+
+BUILTIN(__nvvm_trunc_ftz_f, "ff", "")
+BUILTIN(__nvvm_trunc_f, "ff", "")
+BUILTIN(__nvvm_trunc_d, "dd", "")
+
+// Saturate
+
+BUILTIN(__nvvm_saturate_ftz_f, "ff", "")
+BUILTIN(__nvvm_saturate_f, "ff", "")
+BUILTIN(__nvvm_saturate_d, "dd", "")
+
+// Exp2, Log2
+
+BUILTIN(__nvvm_ex2_approx_ftz_f, "ff", "")
+BUILTIN(__nvvm_ex2_approx_f, "ff", "")
+BUILTIN(__nvvm_ex2_approx_d, "dd", "")
+
+BUILTIN(__nvvm_lg2_approx_ftz_f, "ff", "")
+BUILTIN(__nvvm_lg2_approx_f, "ff", "")
+BUILTIN(__nvvm_lg2_approx_d, "dd", "")
+
+// Sin, Cos
+
+BUILTIN(__nvvm_sin_approx_ftz_f, "ff", "")
+BUILTIN(__nvvm_sin_approx_f, "ff", "")
+
+BUILTIN(__nvvm_cos_approx_ftz_f, "ff", "")
+BUILTIN(__nvvm_cos_approx_f, "ff", "")
+
+// Fma
+
+BUILTIN(__nvvm_fma_rn_ftz_f, "ffff", "")
+BUILTIN(__nvvm_fma_rn_f, "ffff", "")
+BUILTIN(__nvvm_fma_rz_ftz_f, "ffff", "")
+BUILTIN(__nvvm_fma_rz_f, "ffff", "")
+BUILTIN(__nvvm_fma_rm_ftz_f, "ffff", "")
+BUILTIN(__nvvm_fma_rm_f, "ffff", "")
+BUILTIN(__nvvm_fma_rp_ftz_f, "ffff", "")
+BUILTIN(__nvvm_fma_rp_f, "ffff", "")
+BUILTIN(__nvvm_fma_rn_d, "dddd", "")
+BUILTIN(__nvvm_fma_rz_d, "dddd", "")
+BUILTIN(__nvvm_fma_rm_d, "dddd", "")
+BUILTIN(__nvvm_fma_rp_d, "dddd", "")
+
+// Rcp
+
+BUILTIN(__nvvm_rcp_rn_ftz_f, "ff", "")
+BUILTIN(__nvvm_rcp_rn_f, "ff", "")
+BUILTIN(__nvvm_rcp_rz_ftz_f, "ff", "")
+BUILTIN(__nvvm_rcp_rz_f, "ff", "")
+BUILTIN(__nvvm_rcp_rm_ftz_f, "ff", "")
+BUILTIN(__nvvm_rcp_rm_f, "ff", "")
+BUILTIN(__nvvm_rcp_rp_ftz_f, "ff", "")
+BUILTIN(__nvvm_rcp_rp_f, "ff", "")
+
+BUILTIN(__nvvm_rcp_rn_d, "dd", "")
+BUILTIN(__nvvm_rcp_rz_d, "dd", "")
+BUILTIN(__nvvm_rcp_rm_d, "dd", "")
+BUILTIN(__nvvm_rcp_rp_d, "dd", "")
+BUILTIN(__nvvm_rcp_approx_ftz_d, "dd", "")
+
+// Sqrt
+
+BUILTIN(__nvvm_sqrt_rn_ftz_f, "ff", "")
+BUILTIN(__nvvm_sqrt_rn_f, "ff", "")
+BUILTIN(__nvvm_sqrt_rz_ftz_f, "ff", "")
+BUILTIN(__nvvm_sqrt_rz_f, "ff", "")
+BUILTIN(__nvvm_sqrt_rm_ftz_f, "ff", "")
+BUILTIN(__nvvm_sqrt_rm_f, "ff", "")
+BUILTIN(__nvvm_sqrt_rp_ftz_f, "ff", "")
+BUILTIN(__nvvm_sqrt_rp_f, "ff", "")
+BUILTIN(__nvvm_sqrt_approx_ftz_f, "ff", "")
+BUILTIN(__nvvm_sqrt_approx_f, "ff", "")
+
+BUILTIN(__nvvm_sqrt_rn_d, "dd", "")
+BUILTIN(__nvvm_sqrt_rz_d, "dd", "")
+BUILTIN(__nvvm_sqrt_rm_d, "dd", "")
+BUILTIN(__nvvm_sqrt_rp_d, "dd", "")
+
+// Rsqrt
+
+BUILTIN(__nvvm_rsqrt_approx_ftz_f, "ff", "")
+BUILTIN(__nvvm_rsqrt_approx_f, "ff", "")
+BUILTIN(__nvvm_rsqrt_approx_d, "dd", "")
+
+// Add
+
+BUILTIN(__nvvm_add_rn_ftz_f, "fff", "")
+BUILTIN(__nvvm_add_rn_f, "fff", "")
+BUILTIN(__nvvm_add_rz_ftz_f, "fff", "")
+BUILTIN(__nvvm_add_rz_f, "fff", "")
+BUILTIN(__nvvm_add_rm_ftz_f, "fff", "")
+BUILTIN(__nvvm_add_rm_f, "fff", "")
+BUILTIN(__nvvm_add_rp_ftz_f, "fff", "")
+BUILTIN(__nvvm_add_rp_f, "fff", "")
+
+BUILTIN(__nvvm_add_rn_d, "ddd", "")
+BUILTIN(__nvvm_add_rz_d, "ddd", "")
+BUILTIN(__nvvm_add_rm_d, "ddd", "")
+BUILTIN(__nvvm_add_rp_d, "ddd", "")
+
+// Convert
+
+BUILTIN(__nvvm_d2f_rn_ftz, "fd", "")
+BUILTIN(__nvvm_d2f_rn, "fd", "")
+BUILTIN(__nvvm_d2f_rz_ftz, "fd", "")
+BUILTIN(__nvvm_d2f_rz, "fd", "")
+BUILTIN(__nvvm_d2f_rm_ftz, "fd", "")
+BUILTIN(__nvvm_d2f_rm, "fd", "")
+BUILTIN(__nvvm_d2f_rp_ftz, "fd", "")
+BUILTIN(__nvvm_d2f_rp, "fd", "")
+
+BUILTIN(__nvvm_d2i_rn, "id", "")
+BUILTIN(__nvvm_d2i_rz, "id", "")
+BUILTIN(__nvvm_d2i_rm, "id", "")
+BUILTIN(__nvvm_d2i_rp, "id", "")
+
+BUILTIN(__nvvm_d2ui_rn, "Uid", "")
+BUILTIN(__nvvm_d2ui_rz, "Uid", "")
+BUILTIN(__nvvm_d2ui_rm, "Uid", "")
+BUILTIN(__nvvm_d2ui_rp, "Uid", "")
+
+BUILTIN(__nvvm_i2d_rn, "di", "")
+BUILTIN(__nvvm_i2d_rz, "di", "")
+BUILTIN(__nvvm_i2d_rm, "di", "")
+BUILTIN(__nvvm_i2d_rp, "di", "")
+
+BUILTIN(__nvvm_ui2d_rn, "dUi", "")
+BUILTIN(__nvvm_ui2d_rz, "dUi", "")
+BUILTIN(__nvvm_ui2d_rm, "dUi", "")
+BUILTIN(__nvvm_ui2d_rp, "dUi", "")
+
+BUILTIN(__nvvm_f2i_rn_ftz, "if", "")
+BUILTIN(__nvvm_f2i_rn, "if", "")
+BUILTIN(__nvvm_f2i_rz_ftz, "if", "")
+BUILTIN(__nvvm_f2i_rz, "if", "")
+BUILTIN(__nvvm_f2i_rm_ftz, "if", "")
+BUILTIN(__nvvm_f2i_rm, "if", "")
+BUILTIN(__nvvm_f2i_rp_ftz, "if", "")
+BUILTIN(__nvvm_f2i_rp, "if", "")
+
+BUILTIN(__nvvm_f2ui_rn_ftz, "Uif", "")
+BUILTIN(__nvvm_f2ui_rn, "Uif", "")
+BUILTIN(__nvvm_f2ui_rz_ftz, "Uif", "")
+BUILTIN(__nvvm_f2ui_rz, "Uif", "")
+BUILTIN(__nvvm_f2ui_rm_ftz, "Uif", "")
+BUILTIN(__nvvm_f2ui_rm, "Uif", "")
+BUILTIN(__nvvm_f2ui_rp_ftz, "Uif", "")
+BUILTIN(__nvvm_f2ui_rp, "Uif", "")
+
+BUILTIN(__nvvm_i2f_rn, "fi", "")
+BUILTIN(__nvvm_i2f_rz, "fi", "")
+BUILTIN(__nvvm_i2f_rm, "fi", "")
+BUILTIN(__nvvm_i2f_rp, "fi", "")
+
+BUILTIN(__nvvm_ui2f_rn, "fUi", "")
+BUILTIN(__nvvm_ui2f_rz, "fUi", "")
+BUILTIN(__nvvm_ui2f_rm, "fUi", "")
+BUILTIN(__nvvm_ui2f_rp, "fUi", "")
+
+BUILTIN(__nvvm_lohi_i2d, "dii", "")
+
+BUILTIN(__nvvm_d2i_lo, "id", "")
+BUILTIN(__nvvm_d2i_hi, "id", "")
+
+BUILTIN(__nvvm_f2ll_rn_ftz, "LLif", "")
+BUILTIN(__nvvm_f2ll_rn, "LLif", "")
+BUILTIN(__nvvm_f2ll_rz_ftz, "LLif", "")
+BUILTIN(__nvvm_f2ll_rz, "LLif", "")
+BUILTIN(__nvvm_f2ll_rm_ftz, "LLif", "")
+BUILTIN(__nvvm_f2ll_rm, "LLif", "")
+BUILTIN(__nvvm_f2ll_rp_ftz, "LLif", "")
+BUILTIN(__nvvm_f2ll_rp, "LLif", "")
+
+BUILTIN(__nvvm_f2ull_rn_ftz, "ULLif", "")
+BUILTIN(__nvvm_f2ull_rn, "ULLif", "")
+BUILTIN(__nvvm_f2ull_rz_ftz, "ULLif", "")
+BUILTIN(__nvvm_f2ull_rz, "ULLif", "")
+BUILTIN(__nvvm_f2ull_rm_ftz, "ULLif", "")
+BUILTIN(__nvvm_f2ull_rm, "ULLif", "")
+BUILTIN(__nvvm_f2ull_rp_ftz, "ULLif", "")
+BUILTIN(__nvvm_f2ull_rp, "ULLif", "")
+
+BUILTIN(__nvvm_d2ll_rn, "LLid", "")
+BUILTIN(__nvvm_d2ll_rz, "LLid", "")
+BUILTIN(__nvvm_d2ll_rm, "LLid", "")
+BUILTIN(__nvvm_d2ll_rp, "LLid", "")
+
+BUILTIN(__nvvm_d2ull_rn, "ULLid", "")
+BUILTIN(__nvvm_d2ull_rz, "ULLid", "")
+BUILTIN(__nvvm_d2ull_rm, "ULLid", "")
+BUILTIN(__nvvm_d2ull_rp, "ULLid", "")
+
+BUILTIN(__nvvm_ll2f_rn, "fLLi", "")
+BUILTIN(__nvvm_ll2f_rz, "fLLi", "")
+BUILTIN(__nvvm_ll2f_rm, "fLLi", "")
+BUILTIN(__nvvm_ll2f_rp, "fLLi", "")
+
+BUILTIN(__nvvm_ull2f_rn, "fULLi", "")
+BUILTIN(__nvvm_ull2f_rz, "fULLi", "")
+BUILTIN(__nvvm_ull2f_rm, "fULLi", "")
+BUILTIN(__nvvm_ull2f_rp, "fULLi", "")
+
+BUILTIN(__nvvm_ll2d_rn, "dLLi", "")
+BUILTIN(__nvvm_ll2d_rz, "dLLi", "")
+BUILTIN(__nvvm_ll2d_rm, "dLLi", "")
+BUILTIN(__nvvm_ll2d_rp, "dLLi", "")
+
+BUILTIN(__nvvm_ull2d_rn, "dULLi", "")
+BUILTIN(__nvvm_ull2d_rz, "dULLi", "")
+BUILTIN(__nvvm_ull2d_rm, "dULLi", "")
+BUILTIN(__nvvm_ull2d_rp, "dULLi", "")
+
+BUILTIN(__nvvm_f2h_rn_ftz, "Usf", "")
+BUILTIN(__nvvm_f2h_rn, "Usf", "")
+
+BUILTIN(__nvvm_h2f, "fUs", "")
+
+// Bitcast
+
+BUILTIN(__nvvm_bitcast_f2i, "if", "")
+BUILTIN(__nvvm_bitcast_i2f, "fi", "")
+
+BUILTIN(__nvvm_bitcast_ll2d, "dLLi", "")
+BUILTIN(__nvvm_bitcast_d2ll, "LLid", "")
+
+// Sync
+
+BUILTIN(__syncthreads, "v", "")
+BUILTIN(__nvvm_bar0, "v", "")
+BUILTIN(__nvvm_bar0_popc, "ii", "")
+BUILTIN(__nvvm_bar0_and, "ii", "")
+BUILTIN(__nvvm_bar0_or, "ii", "")
+
+// Membar
+
+BUILTIN(__nvvm_membar_cta, "v", "")
+BUILTIN(__nvvm_membar_gl, "v", "")
+BUILTIN(__nvvm_membar_sys, "v", "")
+
+// Memcpy, Memset
+
+BUILTIN(__nvvm_memcpy, "vUc*Uc*zi","")
+BUILTIN(__nvvm_memset, "vUc*Uczi","")
+
+// Image
+
+BUILTIN(__builtin_ptx_read_image2Dfi_, "V4fiiii", "")
+BUILTIN(__builtin_ptx_read_image2Dff_, "V4fiiff", "")
+BUILTIN(__builtin_ptx_read_image2Dii_, "V4iiiii", "")
+BUILTIN(__builtin_ptx_read_image2Dif_, "V4iiiff", "")
+
+BUILTIN(__builtin_ptx_read_image3Dfi_, "V4fiiiiii", "")
+BUILTIN(__builtin_ptx_read_image3Dff_, "V4fiiffff", "")
+BUILTIN(__builtin_ptx_read_image3Dii_, "V4iiiiiii", "")
+BUILTIN(__builtin_ptx_read_image3Dif_, "V4iiiffff", "")
+
+BUILTIN(__builtin_ptx_write_image2Df_, "viiiffff", "")
+BUILTIN(__builtin_ptx_write_image2Di_, "viiiiiii", "")
+BUILTIN(__builtin_ptx_write_image2Dui_, "viiiUiUiUiUi", "")
+BUILTIN(__builtin_ptx_get_image_depthi_, "ii", "")
+BUILTIN(__builtin_ptx_get_image_heighti_, "ii", "")
+BUILTIN(__builtin_ptx_get_image_widthi_, "ii", "")
+BUILTIN(__builtin_ptx_get_image_channel_data_typei_, "ii", "")
+BUILTIN(__builtin_ptx_get_image_channel_orderi_, "ii", "")
+
+// Atomic
+//
+// We need the atom intrinsics because
+// - they are used in converging analysis
+// - they are used in address space analysis and optimization
+// So it does not hurt to expose them as builtins.
+//
+BUILTIN(__nvvm_atom_add_g_i, "iiD*1i", "n")
+BUILTIN(__nvvm_atom_add_s_i, "iiD*3i", "n")
+BUILTIN(__nvvm_atom_add_gen_i, "iiD*i", "n")
+BUILTIN(__nvvm_atom_add_g_l, "LiLiD*1Li", "n")
+BUILTIN(__nvvm_atom_add_s_l, "LiLiD*3Li", "n")
+BUILTIN(__nvvm_atom_add_gen_l, "LiLiD*Li", "n")
+BUILTIN(__nvvm_atom_add_g_ll, "LLiLLiD*1LLi", "n")
+BUILTIN(__nvvm_atom_add_s_ll, "LLiLLiD*3LLi", "n")
+BUILTIN(__nvvm_atom_add_gen_ll, "LLiLLiD*LLi", "n")
+BUILTIN(__nvvm_atom_add_g_f, "ffD*1f", "n")
+BUILTIN(__nvvm_atom_add_s_f, "ffD*3f", "n")
+BUILTIN(__nvvm_atom_add_gen_f, "ffD*f", "n")
+BUILTIN(__nvvm_atom_add_g_d, "ddD*1d", "n")
+BUILTIN(__nvvm_atom_add_s_d, "ddD*3d", "n")
+BUILTIN(__nvvm_atom_add_gen_d, "ddD*d", "n")
+
+BUILTIN(__nvvm_atom_sub_g_i, "iiD*1i", "n")
+BUILTIN(__nvvm_atom_sub_s_i, "iiD*3i", "n")
+BUILTIN(__nvvm_atom_sub_gen_i, "iiD*i", "n")
+BUILTIN(__nvvm_atom_sub_g_l, "LiLiD*1Li", "n")
+BUILTIN(__nvvm_atom_sub_s_l, "LiLiD*3Li", "n")
+BUILTIN(__nvvm_atom_sub_gen_l, "LiLiD*Li", "n")
+BUILTIN(__nvvm_atom_sub_g_ll, "LLiLLiD*1LLi", "n")
+BUILTIN(__nvvm_atom_sub_s_ll, "LLiLLiD*3LLi", "n")
+BUILTIN(__nvvm_atom_sub_gen_ll, "LLiLLiD*LLi", "n")
+
+BUILTIN(__nvvm_atom_xchg_g_i, "iiD*1i", "n")
+BUILTIN(__nvvm_atom_xchg_s_i, "iiD*3i", "n")
+BUILTIN(__nvvm_atom_xchg_gen_i, "iiD*i", "n")
+BUILTIN(__nvvm_atom_xchg_g_l, "LiLiD*1Li", "n")
+BUILTIN(__nvvm_atom_xchg_s_l, "LiLiD*3Li", "n")
+BUILTIN(__nvvm_atom_xchg_gen_l, "LiLiD*Li", "n")
+BUILTIN(__nvvm_atom_xchg_g_ll, "LLiLLiD*1LLi", "n")
+BUILTIN(__nvvm_atom_xchg_s_ll, "LLiLLiD*3LLi", "n")
+BUILTIN(__nvvm_atom_xchg_gen_ll, "LLiLLiD*LLi", "n")
+
+BUILTIN(__nvvm_atom_max_g_i, "iiD*1i", "n")
+BUILTIN(__nvvm_atom_max_s_i, "iiD*3i", "n")
+BUILTIN(__nvvm_atom_max_gen_i, "iiD*i", "n")
+BUILTIN(__nvvm_atom_max_g_ui, "UiUiD*1Ui", "n")
+BUILTIN(__nvvm_atom_max_s_ui, "UiUiD*3Ui", "n")
+BUILTIN(__nvvm_atom_max_gen_ui, "UiUiD*Ui", "n")
+BUILTIN(__nvvm_atom_max_g_l, "LiLiD*1Li", "n")
+BUILTIN(__nvvm_atom_max_s_l, "LiLiD*3Li", "n")
+BUILTIN(__nvvm_atom_max_gen_l, "LiLiD*Li", "n")
+BUILTIN(__nvvm_atom_max_g_ul, "ULiULiD*1ULi", "n")
+BUILTIN(__nvvm_atom_max_s_ul, "ULiULiD*3ULi", "n")
+BUILTIN(__nvvm_atom_max_gen_ul, "ULiULiD*ULi", "n")
+BUILTIN(__nvvm_atom_max_g_ll, "LLiLLiD*1LLi", "n")
+BUILTIN(__nvvm_atom_max_s_ll, "LLiLLiD*3LLi", "n")
+BUILTIN(__nvvm_atom_max_gen_ll, "LLiLLiD*LLi", "n")
+BUILTIN(__nvvm_atom_max_g_ull, "ULLiULLiD*1ULLi", "n")
+BUILTIN(__nvvm_atom_max_s_ull, "ULLiULLiD*3ULLi", "n")
+BUILTIN(__nvvm_atom_max_gen_ull, "ULLiULLiD*ULLi", "n")
+
+BUILTIN(__nvvm_atom_min_g_i, "iiD*1i", "n")
+BUILTIN(__nvvm_atom_min_s_i, "iiD*3i", "n")
+BUILTIN(__nvvm_atom_min_gen_i, "iiD*i", "n")
+BUILTIN(__nvvm_atom_min_g_ui, "UiUiD*1Ui", "n")
+BUILTIN(__nvvm_atom_min_s_ui, "UiUiD*3Ui", "n")
+BUILTIN(__nvvm_atom_min_gen_ui, "UiUiD*Ui", "n")
+BUILTIN(__nvvm_atom_min_g_l, "LiLiD*1Li", "n")
+BUILTIN(__nvvm_atom_min_s_l, "LiLiD*3Li", "n")
+BUILTIN(__nvvm_atom_min_gen_l, "LiLiD*Li", "n")
+BUILTIN(__nvvm_atom_min_g_ul, "ULiULiD*1ULi", "n")
+BUILTIN(__nvvm_atom_min_s_ul, "ULiULiD*3ULi", "n")
+BUILTIN(__nvvm_atom_min_gen_ul, "ULiULiD*ULi", "n")
+BUILTIN(__nvvm_atom_min_g_ll, "LLiLLiD*1LLi", "n")
+BUILTIN(__nvvm_atom_min_s_ll, "LLiLLiD*3LLi", "n")
+BUILTIN(__nvvm_atom_min_gen_ll, "LLiLLiD*LLi", "n")
+BUILTIN(__nvvm_atom_min_g_ull, "ULLiULLiD*1ULLi", "n")
+BUILTIN(__nvvm_atom_min_s_ull, "ULLiULLiD*3ULLi", "n")
+BUILTIN(__nvvm_atom_min_gen_ull, "ULLiULLiD*ULLi", "n")
+
+BUILTIN(__nvvm_atom_inc_g_ui, "UiUiD*1Ui", "n")
+BUILTIN(__nvvm_atom_inc_s_ui, "UiUiD*3Ui", "n")
+BUILTIN(__nvvm_atom_inc_gen_ui, "UiUiD*Ui", "n")
+BUILTIN(__nvvm_atom_dec_g_ui, "UiUiD*1Ui", "n")
+BUILTIN(__nvvm_atom_dec_s_ui, "UiUiD*3Ui", "n")
+BUILTIN(__nvvm_atom_dec_gen_ui, "UiUiD*Ui", "n")
+
+BUILTIN(__nvvm_atom_and_g_i, "iiD*1i", "n")
+BUILTIN(__nvvm_atom_and_s_i, "iiD*3i", "n")
+BUILTIN(__nvvm_atom_and_gen_i, "iiD*i", "n")
+BUILTIN(__nvvm_atom_and_g_l, "LiLiD*1Li", "n")
+BUILTIN(__nvvm_atom_and_s_l, "LiLiD*3Li", "n")
+BUILTIN(__nvvm_atom_and_gen_l, "LiLiD*Li", "n")
+BUILTIN(__nvvm_atom_and_g_ll, "LLiLLiD*1LLi", "n")
+BUILTIN(__nvvm_atom_and_s_ll, "LLiLLiD*3LLi", "n")
+BUILTIN(__nvvm_atom_and_gen_ll, "LLiLLiD*LLi", "n")
+
+BUILTIN(__nvvm_atom_or_g_i, "iiD*1i", "n")
+BUILTIN(__nvvm_atom_or_s_i, "iiD*3i", "n")
+BUILTIN(__nvvm_atom_or_gen_i, "iiD*i", "n")
+BUILTIN(__nvvm_atom_or_g_l, "LiLiD*1Li", "n")
+BUILTIN(__nvvm_atom_or_s_l, "LiLiD*3Li", "n")
+BUILTIN(__nvvm_atom_or_gen_l, "LiLiD*Li", "n")
+BUILTIN(__nvvm_atom_or_g_ll, "LLiLLiD*1LLi", "n")
+BUILTIN(__nvvm_atom_or_s_ll, "LLiLLiD*3LLi", "n")
+BUILTIN(__nvvm_atom_or_gen_ll, "LLiLLiD*LLi", "n")
+
+BUILTIN(__nvvm_atom_xor_g_i, "iiD*1i", "n")
+BUILTIN(__nvvm_atom_xor_s_i, "iiD*3i", "n")
+BUILTIN(__nvvm_atom_xor_gen_i, "iiD*i", "n")
+BUILTIN(__nvvm_atom_xor_g_l, "LiLiD*1Li", "n")
+BUILTIN(__nvvm_atom_xor_s_l, "LiLiD*3Li", "n")
+BUILTIN(__nvvm_atom_xor_gen_l, "LiLiD*Li", "n")
+BUILTIN(__nvvm_atom_xor_g_ll, "LLiLLiD*1LLi", "n")
+BUILTIN(__nvvm_atom_xor_s_ll, "LLiLLiD*3LLi", "n")
+BUILTIN(__nvvm_atom_xor_gen_ll, "LLiLLiD*LLi", "n")
+
+BUILTIN(__nvvm_atom_cas_g_i, "iiD*1ii", "n")
+BUILTIN(__nvvm_atom_cas_s_i, "iiD*3ii", "n")
+BUILTIN(__nvvm_atom_cas_gen_i, "iiD*ii", "n")
+BUILTIN(__nvvm_atom_cas_g_l, "LiLiD*1LiLi", "n")
+BUILTIN(__nvvm_atom_cas_s_l, "LiLiD*3LiLi", "n")
+BUILTIN(__nvvm_atom_cas_gen_l, "LiLiD*LiLi", "n")
+BUILTIN(__nvvm_atom_cas_g_ll, "LLiLLiD*1LLiLLi", "n")
+BUILTIN(__nvvm_atom_cas_s_ll, "LLiLLiD*3LLiLLi", "n")
+BUILTIN(__nvvm_atom_cas_gen_ll, "LLiLLiD*LLiLLi", "n")
+
+// Compiler Error Warn
+BUILTIN(__nvvm_compiler_error, "vcC*4", "n")
+BUILTIN(__nvvm_compiler_warn, "vcC*4", "n")
+
+#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..5681c1f2
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Basic/BuiltinsPPC.def
@@ -0,0 +1,379 @@
+//===--- 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.
+
+BUILTIN(__builtin_ppc_get_timebase, "ULLi", "n")
+
+// 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_vaddeuqm, "V1ULLLiV1ULLLiV1ULLLiV1ULLLi","")
+BUILTIN(__builtin_altivec_vaddcuq, "V1ULLLiV1ULLLiV1ULLLi","")
+BUILTIN(__builtin_altivec_vaddecuq, "V1ULLLiV1ULLLiV1ULLLiV1ULLLi","")
+
+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_vsubeuqm, "V1ULLLiV1ULLLiV1ULLLiV1ULLLi","")
+BUILTIN(__builtin_altivec_vsubcuq, "V1ULLLiV1ULLLiV1ULLLi","")
+BUILTIN(__builtin_altivec_vsubecuq, "V1ULLLiV1ULLLiV1ULLLiV1ULLLi","")
+
+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_vmuleuw, "V2ULLiV4UiV4Ui", "")
+BUILTIN(__builtin_altivec_vmulesw, "V2SLLiV4SiV4Si", "")
+BUILTIN(__builtin_altivec_vmuloub, "V8UsV16UcV16Uc", "")
+BUILTIN(__builtin_altivec_vmulosb, "V8SsV16ScV16Sc", "")
+BUILTIN(__builtin_altivec_vmulouh, "V4UiV8UsV8Us", "")
+BUILTIN(__builtin_altivec_vmulosh, "V4SiV8SsV8Ss", "")
+BUILTIN(__builtin_altivec_vmulouw, "V2ULLiV4UiV4Ui", "")
+BUILTIN(__builtin_altivec_vmulosw, "V2SLLiV4SiV4Si", "")
+
+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_vpksdss, "V4SiV2SLLiV2SLLi", "")
+BUILTIN(__builtin_altivec_vpksdus, "V4UiV2SLLiV2SLLi", "")
+BUILTIN(__builtin_altivec_vpkudus, "V4UiV2ULLiV2ULLi", "")
+BUILTIN(__builtin_altivec_vpkudum, "V4UiV2ULLiV2ULLi", "")
+
+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_vcmpequd, "V2LLiV2LLiV2LLi", "")
+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_vcmpgtsd, "V2LLiV2LLiV2LLi", "")
+BUILTIN(__builtin_altivec_vcmpgtud, "V2LLiV2ULLiV2ULLi", "")
+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_vmaxsd, "V2LLiV2LLiV2LLi", "")
+BUILTIN(__builtin_altivec_vmaxud, "V2ULLiV2ULLiV2ULLi", "")
+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_vminsd, "V2LLiV2LLiV2LLi", "")
+BUILTIN(__builtin_altivec_vminud, "V2ULLiV2ULLiV2ULLi", "")
+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_vrld, "V2LLiV2LLiV2ULLi", "")
+
+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_vupkhsw, "V2LLiV4i", "")
+
+BUILTIN(__builtin_altivec_vupklsb, "V8sV16c", "")
+BUILTIN(__builtin_altivec_vupklpx, "V4UiV8s", "")
+BUILTIN(__builtin_altivec_vupklsh, "V4iV8s", "")
+BUILTIN(__builtin_altivec_vupklsw, "V2LLiV4i", "")
+
+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_vcmpequd_p, "iiV2LLiV2LLi", "")
+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_vcmpgtsd_p, "iiV2LLiV2LLi", "")
+BUILTIN(__builtin_altivec_vcmpgtud_p, "iiV2ULLiV2ULLi", "")
+BUILTIN(__builtin_altivec_vcmpgtfp_p, "iiV4fV4f", "")
+
+BUILTIN(__builtin_altivec_vgbbd, "V16UcV16Uc", "")
+BUILTIN(__builtin_altivec_vbpermq, "V2ULLiV16UcV16Uc", "")
+
+// P8 Crypto built-ins.
+BUILTIN(__builtin_altivec_crypto_vsbox, "V2ULLiV2ULLi", "")
+BUILTIN(__builtin_altivec_crypto_vpermxor, "V16UcV16UcV16UcV16Uc", "")
+BUILTIN(__builtin_altivec_crypto_vshasigmaw, "V4UiV4UiIiIi", "")
+BUILTIN(__builtin_altivec_crypto_vshasigmad, "V2ULLiV2ULLiIiIi", "")
+BUILTIN(__builtin_altivec_crypto_vcipher, "V2ULLiV2ULLiV2ULLi", "")
+BUILTIN(__builtin_altivec_crypto_vcipherlast, "V2ULLiV2ULLiV2ULLi", "")
+BUILTIN(__builtin_altivec_crypto_vncipher, "V2ULLiV2ULLiV2ULLi", "")
+BUILTIN(__builtin_altivec_crypto_vncipherlast, "V2ULLiV2ULLiV2ULLi", "")
+BUILTIN(__builtin_altivec_crypto_vpmsumb, "V16UcV16UcV16Uc", "")
+BUILTIN(__builtin_altivec_crypto_vpmsumh, "V8UsV8UsV8Us", "")
+BUILTIN(__builtin_altivec_crypto_vpmsumw, "V4UiV4UiV4Ui", "")
+BUILTIN(__builtin_altivec_crypto_vpmsumd, "V2ULLiV2ULLiV2ULLi", "")
+
+BUILTIN(__builtin_altivec_vclzb, "V16UcV16Uc", "")
+BUILTIN(__builtin_altivec_vclzh, "V8UsV8Us", "")
+BUILTIN(__builtin_altivec_vclzw, "V4UiV4Ui", "")
+BUILTIN(__builtin_altivec_vclzd, "V2ULLiV2ULLi", "")
+
+// VSX built-ins.
+
+BUILTIN(__builtin_vsx_lxvd2x, "V2divC*", "")
+BUILTIN(__builtin_vsx_lxvw4x, "V4iivC*", "")
+
+BUILTIN(__builtin_vsx_stxvd2x, "vV2div*", "")
+BUILTIN(__builtin_vsx_stxvw4x, "vV4iiv*", "")
+
+BUILTIN(__builtin_vsx_xvmaxdp, "V2dV2dV2d", "")
+BUILTIN(__builtin_vsx_xvmaxsp, "V4fV4fV4f", "")
+BUILTIN(__builtin_vsx_xsmaxdp, "ddd", "")
+
+BUILTIN(__builtin_vsx_xvmindp, "V2dV2dV2d", "")
+BUILTIN(__builtin_vsx_xvminsp, "V4fV4fV4f", "")
+BUILTIN(__builtin_vsx_xsmindp, "ddd", "")
+
+BUILTIN(__builtin_vsx_xvdivdp, "V2dV2dV2d", "")
+BUILTIN(__builtin_vsx_xvdivsp, "V4fV4fV4f", "")
+
+BUILTIN(__builtin_vsx_xvrdpip, "V2dV2d", "")
+BUILTIN(__builtin_vsx_xvrspip, "V4fV4f", "")
+
+BUILTIN(__builtin_vsx_xvcmpeqdp, "V2ULLiV2dV2d", "")
+BUILTIN(__builtin_vsx_xvcmpeqsp, "V4UiV4fV4f", "")
+
+BUILTIN(__builtin_vsx_xvcmpeqdp_p, "iiV2dV2d", "")
+BUILTIN(__builtin_vsx_xvcmpeqsp_p, "iiV4fV4f", "")
+
+BUILTIN(__builtin_vsx_xvcmpgedp, "V2ULLiV2dV2d", "")
+BUILTIN(__builtin_vsx_xvcmpgesp, "V4UiV4fV4f", "")
+
+BUILTIN(__builtin_vsx_xvcmpgedp_p, "iiV2dV2d", "")
+BUILTIN(__builtin_vsx_xvcmpgesp_p, "iiV4fV4f", "")
+
+BUILTIN(__builtin_vsx_xvcmpgtdp, "V2ULLiV2dV2d", "")
+BUILTIN(__builtin_vsx_xvcmpgtsp, "V4UiV4fV4f", "")
+
+BUILTIN(__builtin_vsx_xvcmpgtdp_p, "iiV2dV2d", "")
+BUILTIN(__builtin_vsx_xvcmpgtsp_p, "iiV4fV4f", "")
+
+BUILTIN(__builtin_vsx_xvrdpim, "V2dV2d", "")
+BUILTIN(__builtin_vsx_xvrspim, "V4fV4f", "")
+
+BUILTIN(__builtin_vsx_xvrdpi, "V2dV2d", "")
+BUILTIN(__builtin_vsx_xvrspi, "V4fV4f", "")
+
+BUILTIN(__builtin_vsx_xvrdpic, "V2dV2d", "")
+BUILTIN(__builtin_vsx_xvrspic, "V4fV4f", "")
+
+BUILTIN(__builtin_vsx_xvrdpiz, "V2dV2d", "")
+BUILTIN(__builtin_vsx_xvrspiz, "V4fV4f", "")
+
+BUILTIN(__builtin_vsx_xvmaddadp, "V2dV2dV2dV2d", "")
+BUILTIN(__builtin_vsx_xvmaddasp, "V4fV4fV4fV4f", "")
+
+BUILTIN(__builtin_vsx_xvmsubadp, "V2dV2dV2dV2d", "")
+BUILTIN(__builtin_vsx_xvmsubasp, "V4fV4fV4fV4f", "")
+
+BUILTIN(__builtin_vsx_xvmuldp, "V2dV2dV2d", "")
+BUILTIN(__builtin_vsx_xvmulsp, "V4fV4fV4f", "")
+
+BUILTIN(__builtin_vsx_xvnmaddadp, "V2dV2dV2dV2d", "")
+BUILTIN(__builtin_vsx_xvnmaddasp, "V4fV4fV4fV4f", "")
+
+BUILTIN(__builtin_vsx_xvnmsubadp, "V2dV2dV2dV2d", "")
+BUILTIN(__builtin_vsx_xvnmsubasp, "V4fV4fV4fV4f", "")
+
+BUILTIN(__builtin_vsx_xvredp, "V2dV2d", "")
+BUILTIN(__builtin_vsx_xvresp, "V4fV4f", "")
+
+BUILTIN(__builtin_vsx_xvrsqrtedp, "V2dV2d", "")
+BUILTIN(__builtin_vsx_xvrsqrtesp, "V4fV4f", "")
+
+BUILTIN(__builtin_vsx_xvsqrtdp, "V2dV2d", "")
+BUILTIN(__builtin_vsx_xvsqrtsp, "V4fV4f", "")
+
+BUILTIN(__builtin_vsx_xxleqv, "V4UiV4UiV4Ui", "")
+
+BUILTIN(__builtin_vsx_xvcpsgndp, "V2dV2dV2d", "")
+BUILTIN(__builtin_vsx_xvcpsgnsp, "V4fV4fV4f", "")
+
+// HTM builtins
+BUILTIN(__builtin_tbegin, "UiUIi", "")
+BUILTIN(__builtin_tend, "UiUIi", "")
+
+BUILTIN(__builtin_tabort, "UiUi", "")
+BUILTIN(__builtin_tabortdc, "UiUiUiUi", "")
+BUILTIN(__builtin_tabortdci, "UiUiUii", "")
+BUILTIN(__builtin_tabortwc, "UiUiUiUi", "")
+BUILTIN(__builtin_tabortwci, "UiUiUii", "")
+
+BUILTIN(__builtin_tcheck, "Ui", "")
+BUILTIN(__builtin_treclaim, "UiUi", "")
+BUILTIN(__builtin_trechkpt, "Ui", "")
+BUILTIN(__builtin_tsr, "UiUi", "")
+
+BUILTIN(__builtin_tendall, "Ui", "")
+BUILTIN(__builtin_tresume, "Ui", "")
+BUILTIN(__builtin_tsuspend, "Ui", "")
+
+BUILTIN(__builtin_get_texasr, "LUi", "c")
+BUILTIN(__builtin_get_texasru, "LUi", "c")
+BUILTIN(__builtin_get_tfhar, "LUi", "c")
+BUILTIN(__builtin_get_tfiar, "LUi", "c")
+
+BUILTIN(__builtin_set_texasr, "vLUi", "c")
+BUILTIN(__builtin_set_texasru, "vLUi", "c")
+BUILTIN(__builtin_set_tfhar, "vLUi", "c")
+BUILTIN(__builtin_set_tfiar, "vLUi", "c")
+
+BUILTIN(__builtin_ttest, "LUi", "")
+
+// Scalar built-ins
+BUILTIN(__builtin_divwe, "SiSiSi", "")
+BUILTIN(__builtin_divweu, "UiUiUi", "")
+BUILTIN(__builtin_divde, "SLLiSLLiSLLi", "")
+BUILTIN(__builtin_divdeu, "ULLiULLiULLi", "")
+BUILTIN(__builtin_bpermd, "SLLiSLLiSLLi", "")
+
+// FIXME: Obviously incomplete.
+
+#undef BUILTIN
diff --git a/contrib/llvm/tools/clang/include/clang/Basic/BuiltinsSystemZ.def b/contrib/llvm/tools/clang/include/clang/Basic/BuiltinsSystemZ.def
new file mode 100644
index 0000000..68d5a1c
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Basic/BuiltinsSystemZ.def
@@ -0,0 +1,252 @@
+//===-- BuiltinsSystemZ.def - SystemZ 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 SystemZ-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.
+
+// Transactional-memory intrinsics
+BUILTIN(__builtin_tbegin, "iv*", "j")
+BUILTIN(__builtin_tbegin_nofloat, "iv*", "j")
+BUILTIN(__builtin_tbeginc, "v", "nj")
+BUILTIN(__builtin_tabort, "vi", "r")
+BUILTIN(__builtin_tend, "i", "n")
+BUILTIN(__builtin_tx_nesting_depth, "i", "nc")
+BUILTIN(__builtin_tx_assist, "vi", "n")
+BUILTIN(__builtin_non_tx_store, "vULi*ULi", "")
+
+// Vector intrinsics.
+// These all map directly to z instructions, except that some variants ending
+// in "s" have a final "int *" that receives the post-instruction CC value.
+
+// Vector support instructions (chapter 21 of the PoP)
+BUILTIN(__builtin_s390_lcbb, "UivC*Ii", "nc")
+BUILTIN(__builtin_s390_vlbb, "V16ScvC*Ii", "")
+BUILTIN(__builtin_s390_vll, "V16ScUivC*", "")
+BUILTIN(__builtin_s390_vstl, "vV16ScUiv*", "")
+BUILTIN(__builtin_s390_vperm, "V16UcV16UcV16UcV16Uc", "nc")
+BUILTIN(__builtin_s390_vpdi, "V2ULLiV2ULLiV2ULLiIi", "nc")
+BUILTIN(__builtin_s390_vpksh, "V16ScV8SsV8Ss", "nc")
+BUILTIN(__builtin_s390_vpkshs, "V16ScV8SsV8Ssi*", "nc")
+BUILTIN(__builtin_s390_vpksf, "V8SsV4SiV4Si", "nc")
+BUILTIN(__builtin_s390_vpksfs, "V8SsV4SiV4Sii*", "nc")
+BUILTIN(__builtin_s390_vpksg, "V4SiV2SLLiV2SLLi", "nc")
+BUILTIN(__builtin_s390_vpksgs, "V4SiV2SLLiV2SLLii*", "nc")
+BUILTIN(__builtin_s390_vpklsh, "V16UcV8UsV8Us", "nc")
+BUILTIN(__builtin_s390_vpklshs, "V16UcV8UsV8Usi*", "nc")
+BUILTIN(__builtin_s390_vpklsf, "V8UsV4UiV4Ui", "nc")
+BUILTIN(__builtin_s390_vpklsfs, "V8UsV4UiV4Uii*", "nc")
+BUILTIN(__builtin_s390_vpklsg, "V4UiV2ULLiV2ULLi", "nc")
+BUILTIN(__builtin_s390_vpklsgs, "V4UiV2ULLiV2ULLii*", "nc")
+BUILTIN(__builtin_s390_vuphb, "V8SsV16Sc", "nc")
+BUILTIN(__builtin_s390_vuphh, "V4SiV8Ss", "nc")
+BUILTIN(__builtin_s390_vuphf, "V2SLLiV4Si", "nc")
+BUILTIN(__builtin_s390_vuplb, "V8SsV16Sc", "nc")
+BUILTIN(__builtin_s390_vuplhw, "V4SiV8Ss", "nc")
+BUILTIN(__builtin_s390_vuplf, "V2SLLiV4Si", "nc")
+BUILTIN(__builtin_s390_vuplhb, "V8UsV16Uc", "nc")
+BUILTIN(__builtin_s390_vuplhh, "V4UiV8Us", "nc")
+BUILTIN(__builtin_s390_vuplhf, "V2ULLiV4Ui", "nc")
+BUILTIN(__builtin_s390_vupllb, "V8UsV16Uc", "nc")
+BUILTIN(__builtin_s390_vupllh, "V4UiV8Us", "nc")
+BUILTIN(__builtin_s390_vupllf, "V2ULLiV4Ui", "nc")
+
+// Vector integer instructions (chapter 22 of the PoP)
+BUILTIN(__builtin_s390_vaq, "V16UcV16UcV16Uc", "nc")
+BUILTIN(__builtin_s390_vacq, "V16UcV16UcV16UcV16Uc", "nc")
+BUILTIN(__builtin_s390_vaccb, "V16UcV16UcV16Uc", "nc")
+BUILTIN(__builtin_s390_vacch, "V8UsV8UsV8Us", "nc")
+BUILTIN(__builtin_s390_vaccf, "V4UiV4UiV4Ui", "nc")
+BUILTIN(__builtin_s390_vaccg, "V2ULLiV2ULLiV2ULLi", "nc")
+BUILTIN(__builtin_s390_vaccq, "V16UcV16UcV16Uc", "nc")
+BUILTIN(__builtin_s390_vacccq, "V16UcV16UcV16UcV16Uc", "nc")
+BUILTIN(__builtin_s390_vavgb, "V16ScV16ScV16Sc", "nc")
+BUILTIN(__builtin_s390_vavgh, "V8SsV8SsV8Ss", "nc")
+BUILTIN(__builtin_s390_vavgf, "V4SiV4SiV4Si", "nc")
+BUILTIN(__builtin_s390_vavgg, "V2SLLiV2SLLiV2SLLi", "nc")
+BUILTIN(__builtin_s390_vavglb, "V16UcV16UcV16Uc", "nc")
+BUILTIN(__builtin_s390_vavglh, "V8UsV8UsV8Us", "nc")
+BUILTIN(__builtin_s390_vavglf, "V4UiV4UiV4Ui", "nc")
+BUILTIN(__builtin_s390_vavglg, "V2ULLiV2ULLiV2ULLi", "nc")
+BUILTIN(__builtin_s390_vceqbs, "V16ScV16ScV16Sci*", "nc")
+BUILTIN(__builtin_s390_vceqhs, "V8SsV8SsV8Ssi*", "nc")
+BUILTIN(__builtin_s390_vceqfs, "V4SiV4SiV4Sii*", "nc")
+BUILTIN(__builtin_s390_vceqgs, "V2SLLiV2SLLiV2SLLii*", "nc")
+BUILTIN(__builtin_s390_vchbs, "V16ScV16ScV16Sci*", "nc")
+BUILTIN(__builtin_s390_vchhs, "V8SsV8SsV8Ssi*", "nc")
+BUILTIN(__builtin_s390_vchfs, "V4SiV4SiV4Sii*", "nc")
+BUILTIN(__builtin_s390_vchgs, "V2SLLiV2SLLiV2SLLii*", "nc")
+BUILTIN(__builtin_s390_vchlbs, "V16ScV16UcV16Uci*", "nc")
+BUILTIN(__builtin_s390_vchlhs, "V8SsV8UsV8Usi*", "nc")
+BUILTIN(__builtin_s390_vchlfs, "V4SiV4UiV4Uii*", "nc")
+BUILTIN(__builtin_s390_vchlgs, "V2SLLiV2ULLiV2ULLii*", "nc")
+BUILTIN(__builtin_s390_vcksm, "V4UiV4UiV4Ui", "nc")
+BUILTIN(__builtin_s390_vclzb, "V16UcV16Uc", "nc")
+BUILTIN(__builtin_s390_vclzh, "V8UsV8Us", "nc")
+BUILTIN(__builtin_s390_vclzf, "V4UiV4Ui", "nc")
+BUILTIN(__builtin_s390_vclzg, "V2ULLiV2ULLi", "nc")
+BUILTIN(__builtin_s390_vctzb, "V16UcV16Uc", "nc")
+BUILTIN(__builtin_s390_vctzh, "V8UsV8Us", "nc")
+BUILTIN(__builtin_s390_vctzf, "V4UiV4Ui", "nc")
+BUILTIN(__builtin_s390_vctzg, "V2ULLiV2ULLi", "nc")
+BUILTIN(__builtin_s390_verimb, "V16UcV16UcV16UcV16UcIi", "nc")
+BUILTIN(__builtin_s390_verimh, "V8UsV8UsV8UsV8UsIi", "nc")
+BUILTIN(__builtin_s390_verimf, "V4UiV4UiV4UiV4UiIi", "nc")
+BUILTIN(__builtin_s390_verimg, "V2ULLiV2ULLiV2ULLiV2ULLiIi", "nc")
+BUILTIN(__builtin_s390_verllb, "V16UcV16UcUi", "nc")
+BUILTIN(__builtin_s390_verllh, "V8UsV8UsUi", "nc")
+BUILTIN(__builtin_s390_verllf, "V4UiV4UiUi", "nc")
+BUILTIN(__builtin_s390_verllg, "V2ULLiV2ULLiUi", "nc")
+BUILTIN(__builtin_s390_verllvb, "V16UcV16UcV16Uc", "nc")
+BUILTIN(__builtin_s390_verllvh, "V8UsV8UsV8Us", "nc")
+BUILTIN(__builtin_s390_verllvf, "V4UiV4UiV4Ui", "nc")
+BUILTIN(__builtin_s390_verllvg, "V2ULLiV2ULLiV2ULLi", "nc")
+BUILTIN(__builtin_s390_vgfmb, "V8UsV16UcV16Uc", "nc")
+BUILTIN(__builtin_s390_vgfmh, "V4UiV8UsV8Us", "nc")
+BUILTIN(__builtin_s390_vgfmf, "V2ULLiV4UiV4Ui", "nc")
+BUILTIN(__builtin_s390_vgfmg, "V16UcV2ULLiV2ULLi", "nc")
+BUILTIN(__builtin_s390_vgfmab, "V8UsV16UcV16UcV8Us", "nc")
+BUILTIN(__builtin_s390_vgfmah, "V4UiV8UsV8UsV4Ui", "nc")
+BUILTIN(__builtin_s390_vgfmaf, "V2ULLiV4UiV4UiV2ULLi", "nc")
+BUILTIN(__builtin_s390_vgfmag, "V16UcV2ULLiV2ULLiV16Uc", "nc")
+BUILTIN(__builtin_s390_vmahb, "V16ScV16ScV16ScV16Sc", "nc")
+BUILTIN(__builtin_s390_vmahh, "V8SsV8SsV8SsV8Ss", "nc")
+BUILTIN(__builtin_s390_vmahf, "V4SiV4SiV4SiV4Si", "nc")
+BUILTIN(__builtin_s390_vmalhb, "V16UcV16UcV16UcV16Uc", "nc")
+BUILTIN(__builtin_s390_vmalhh, "V8UsV8UsV8UsV8Us", "nc")
+BUILTIN(__builtin_s390_vmalhf, "V4UiV4UiV4UiV4Ui", "nc")
+BUILTIN(__builtin_s390_vmaeb, "V8SsV16ScV16ScV8Ss", "nc")
+BUILTIN(__builtin_s390_vmaeh, "V4SiV8SsV8SsV4Si", "nc")
+BUILTIN(__builtin_s390_vmaef, "V2SLLiV4SiV4SiV2SLLi", "nc")
+BUILTIN(__builtin_s390_vmaleb, "V8UsV16UcV16UcV8Us", "nc")
+BUILTIN(__builtin_s390_vmaleh, "V4UiV8UsV8UsV4Ui", "nc")
+BUILTIN(__builtin_s390_vmalef, "V2ULLiV4UiV4UiV2ULLi", "nc")
+BUILTIN(__builtin_s390_vmaob, "V8SsV16ScV16ScV8Ss", "nc")
+BUILTIN(__builtin_s390_vmaoh, "V4SiV8SsV8SsV4Si", "nc")
+BUILTIN(__builtin_s390_vmaof, "V2SLLiV4SiV4SiV2SLLi", "nc")
+BUILTIN(__builtin_s390_vmalob, "V8UsV16UcV16UcV8Us", "nc")
+BUILTIN(__builtin_s390_vmaloh, "V4UiV8UsV8UsV4Ui", "nc")
+BUILTIN(__builtin_s390_vmalof, "V2ULLiV4UiV4UiV2ULLi", "nc")
+BUILTIN(__builtin_s390_vmhb, "V16ScV16ScV16Sc", "nc")
+BUILTIN(__builtin_s390_vmhh, "V8SsV8SsV8Ss", "nc")
+BUILTIN(__builtin_s390_vmhf, "V4SiV4SiV4Si", "nc")
+BUILTIN(__builtin_s390_vmlhb, "V16UcV16UcV16Uc", "nc")
+BUILTIN(__builtin_s390_vmlhh, "V8UsV8UsV8Us", "nc")
+BUILTIN(__builtin_s390_vmlhf, "V4UiV4UiV4Ui", "nc")
+BUILTIN(__builtin_s390_vmeb, "V8SsV16ScV16Sc", "nc")
+BUILTIN(__builtin_s390_vmeh, "V4SiV8SsV8Ss", "nc")
+BUILTIN(__builtin_s390_vmef, "V2SLLiV4SiV4Si", "nc")
+BUILTIN(__builtin_s390_vmleb, "V8UsV16UcV16Uc", "nc")
+BUILTIN(__builtin_s390_vmleh, "V4UiV8UsV8Us", "nc")
+BUILTIN(__builtin_s390_vmlef, "V2ULLiV4UiV4Ui", "nc")
+BUILTIN(__builtin_s390_vmob, "V8SsV16ScV16Sc", "nc")
+BUILTIN(__builtin_s390_vmoh, "V4SiV8SsV8Ss", "nc")
+BUILTIN(__builtin_s390_vmof, "V2SLLiV4SiV4Si", "nc")
+BUILTIN(__builtin_s390_vmlob, "V8UsV16UcV16Uc", "nc")
+BUILTIN(__builtin_s390_vmloh, "V4UiV8UsV8Us", "nc")
+BUILTIN(__builtin_s390_vmlof, "V2ULLiV4UiV4Ui", "nc")
+BUILTIN(__builtin_s390_vpopctb, "V16UcV16Uc", "nc")
+BUILTIN(__builtin_s390_vpopcth, "V8UsV8Us", "nc")
+BUILTIN(__builtin_s390_vpopctf, "V4UiV4Ui", "nc")
+BUILTIN(__builtin_s390_vpopctg, "V2ULLiV2ULLi", "nc")
+BUILTIN(__builtin_s390_vsq, "V16UcV16UcV16Uc", "nc")
+BUILTIN(__builtin_s390_vsbcbiq, "V16UcV16UcV16UcV16Uc", "nc")
+BUILTIN(__builtin_s390_vsbiq, "V16UcV16UcV16UcV16Uc", "nc")
+BUILTIN(__builtin_s390_vscbib, "V16UcV16UcV16Uc", "nc")
+BUILTIN(__builtin_s390_vscbih, "V8UsV8UsV8Us", "nc")
+BUILTIN(__builtin_s390_vscbif, "V4UiV4UiV4Ui", "nc")
+BUILTIN(__builtin_s390_vscbig, "V2ULLiV2ULLiV2ULLi", "nc")
+BUILTIN(__builtin_s390_vscbiq, "V16UcV16UcV16Uc", "nc")
+BUILTIN(__builtin_s390_vsl, "V16UcV16UcV16Uc", "nc")
+BUILTIN(__builtin_s390_vslb, "V16UcV16UcV16Uc", "nc")
+BUILTIN(__builtin_s390_vsldb, "V16UcV16UcV16UcIi", "nc")
+BUILTIN(__builtin_s390_vsra, "V16UcV16UcV16Uc", "nc")
+BUILTIN(__builtin_s390_vsrab, "V16UcV16UcV16Uc", "nc")
+BUILTIN(__builtin_s390_vsrl, "V16UcV16UcV16Uc", "nc")
+BUILTIN(__builtin_s390_vsrlb, "V16UcV16UcV16Uc", "nc")
+BUILTIN(__builtin_s390_vsumb, "V4UiV16UcV16Uc", "nc")
+BUILTIN(__builtin_s390_vsumh, "V4UiV8UsV8Us", "nc")
+BUILTIN(__builtin_s390_vsumgh, "V2ULLiV8UsV8Us", "nc")
+BUILTIN(__builtin_s390_vsumgf, "V2ULLiV4UiV4Ui", "nc")
+BUILTIN(__builtin_s390_vsumqf, "V16UcV4UiV4Ui", "nc")
+BUILTIN(__builtin_s390_vsumqg, "V16UcV2ULLiV2ULLi", "nc")
+BUILTIN(__builtin_s390_vtm, "iV16UcV16Uc", "nc")
+
+// Vector string instructions (chapter 23 of the PoP)
+BUILTIN(__builtin_s390_vfaeb, "V16UcV16UcV16UcIi", "nc")
+BUILTIN(__builtin_s390_vfaebs, "V16UcV16UcV16UcIii*", "nc")
+BUILTIN(__builtin_s390_vfaeh, "V8UsV8UsV8UsIi", "nc")
+BUILTIN(__builtin_s390_vfaehs, "V8UsV8UsV8UsIii*", "nc")
+BUILTIN(__builtin_s390_vfaef, "V4UiV4UiV4UiIi", "nc")
+BUILTIN(__builtin_s390_vfaefs, "V4UiV4UiV4UiIii*", "nc")
+BUILTIN(__builtin_s390_vfaezb, "V16UcV16UcV16UcIi", "nc")
+BUILTIN(__builtin_s390_vfaezbs, "V16UcV16UcV16UcIii*", "nc")
+BUILTIN(__builtin_s390_vfaezh, "V8UsV8UsV8UsIi", "nc")
+BUILTIN(__builtin_s390_vfaezhs, "V8UsV8UsV8UsIii*", "nc")
+BUILTIN(__builtin_s390_vfaezf, "V4UiV4UiV4UiIi", "nc")
+BUILTIN(__builtin_s390_vfaezfs, "V4UiV4UiV4UiIii*", "nc")
+BUILTIN(__builtin_s390_vfeeb, "V16UcV16UcV16Uc", "nc")
+BUILTIN(__builtin_s390_vfeebs, "V16UcV16UcV16Uci*", "nc")
+BUILTIN(__builtin_s390_vfeeh, "V8UsV8UsV8Us", "nc")
+BUILTIN(__builtin_s390_vfeehs, "V8UsV8UsV8Usi*", "nc")
+BUILTIN(__builtin_s390_vfeef, "V4UiV4UiV4Ui", "nc")
+BUILTIN(__builtin_s390_vfeefs, "V4UiV4UiV4Uii*", "nc")
+BUILTIN(__builtin_s390_vfeezb, "V16UcV16UcV16Uc", "nc")
+BUILTIN(__builtin_s390_vfeezbs, "V16UcV16UcV16Uci*", "nc")
+BUILTIN(__builtin_s390_vfeezh, "V8UsV8UsV8Us", "nc")
+BUILTIN(__builtin_s390_vfeezhs, "V8UsV8UsV8Usi*", "nc")
+BUILTIN(__builtin_s390_vfeezf, "V4UiV4UiV4Ui", "nc")
+BUILTIN(__builtin_s390_vfeezfs, "V4UiV4UiV4Uii*", "nc")
+BUILTIN(__builtin_s390_vfeneb, "V16UcV16UcV16Uc", "nc")
+BUILTIN(__builtin_s390_vfenebs, "V16UcV16UcV16Uci*", "nc")
+BUILTIN(__builtin_s390_vfeneh, "V8UsV8UsV8Us", "nc")
+BUILTIN(__builtin_s390_vfenehs, "V8UsV8UsV8Usi*", "nc")
+BUILTIN(__builtin_s390_vfenef, "V4UiV4UiV4Ui", "nc")
+BUILTIN(__builtin_s390_vfenefs, "V4UiV4UiV4Uii*", "nc")
+BUILTIN(__builtin_s390_vfenezb, "V16UcV16UcV16Uc", "nc")
+BUILTIN(__builtin_s390_vfenezbs, "V16UcV16UcV16Uci*", "nc")
+BUILTIN(__builtin_s390_vfenezh, "V8UsV8UsV8Us", "nc")
+BUILTIN(__builtin_s390_vfenezhs, "V8UsV8UsV8Usi*", "nc")
+BUILTIN(__builtin_s390_vfenezf, "V4UiV4UiV4Ui", "nc")
+BUILTIN(__builtin_s390_vfenezfs, "V4UiV4UiV4Uii*", "nc")
+BUILTIN(__builtin_s390_vistrb, "V16UcV16Uc", "nc")
+BUILTIN(__builtin_s390_vistrbs, "V16UcV16Uci*", "nc")
+BUILTIN(__builtin_s390_vistrh, "V8UsV8Us", "nc")
+BUILTIN(__builtin_s390_vistrhs, "V8UsV8Usi*", "nc")
+BUILTIN(__builtin_s390_vistrf, "V4UiV4Ui", "nc")
+BUILTIN(__builtin_s390_vistrfs, "V4UiV4Uii*", "nc")
+BUILTIN(__builtin_s390_vstrcb, "V16UcV16UcV16UcV16UcIi", "nc")
+BUILTIN(__builtin_s390_vstrcbs, "V16UcV16UcV16UcV16UcIii*", "nc")
+BUILTIN(__builtin_s390_vstrch, "V8UsV8UsV8UsV8UsIi", "nc")
+BUILTIN(__builtin_s390_vstrchs, "V8UsV8UsV8UsV8UsIii*", "nc")
+BUILTIN(__builtin_s390_vstrcf, "V4UiV4UiV4UiV4UiIi", "nc")
+BUILTIN(__builtin_s390_vstrcfs, "V4UiV4UiV4UiV4UiIii*", "nc")
+BUILTIN(__builtin_s390_vstrczb, "V16UcV16UcV16UcV16UcIi", "nc")
+BUILTIN(__builtin_s390_vstrczbs, "V16UcV16UcV16UcV16UcIii*", "nc")
+BUILTIN(__builtin_s390_vstrczh, "V8UsV8UsV8UsV8UsIi", "nc")
+BUILTIN(__builtin_s390_vstrczhs, "V8UsV8UsV8UsV8UsIii*", "nc")
+BUILTIN(__builtin_s390_vstrczf, "V4UiV4UiV4UiV4UiIi", "nc")
+BUILTIN(__builtin_s390_vstrczfs, "V4UiV4UiV4UiV4UiIii*", "nc")
+
+// Vector floating-point instructions (chapter 24 of the PoP)
+BUILTIN(__builtin_s390_vfcedbs, "V2SLLiV2dV2di*", "nc")
+BUILTIN(__builtin_s390_vfchdbs, "V2SLLiV2dV2di*", "nc")
+BUILTIN(__builtin_s390_vfchedbs, "V2SLLiV2dV2di*", "nc")
+BUILTIN(__builtin_s390_vfidb, "V2dV2dIiIi", "nc")
+BUILTIN(__builtin_s390_vflndb, "V2dV2d", "nc")
+BUILTIN(__builtin_s390_vflpdb, "V2dV2d", "nc")
+BUILTIN(__builtin_s390_vfmadb, "V2dV2dV2dV2d", "nc")
+BUILTIN(__builtin_s390_vfmsdb, "V2dV2dV2dV2d", "nc")
+BUILTIN(__builtin_s390_vfsqdb, "V2dV2d", "nc")
+BUILTIN(__builtin_s390_vftcidb, "V2SLLiV2dIii*", "nc")
+
+#undef BUILTIN
diff --git a/contrib/llvm/tools/clang/include/clang/Basic/BuiltinsWebAssembly.def b/contrib/llvm/tools/clang/include/clang/Basic/BuiltinsWebAssembly.def
new file mode 100644
index 0000000..9754335
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Basic/BuiltinsWebAssembly.def
@@ -0,0 +1,24 @@
+// BuiltinsWebAssembly.def - WebAssembly 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.
+//
+//===----------------------------------------------------------------------===//
+///
+/// \file
+/// \brief This file defines the WebAssembly-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.
+
+// Note that memory_size is not "c" (readnone) because it must be sequenced with
+// respect to grow_memory calls.
+BUILTIN(__builtin_wasm_memory_size, "z", "n")
+BUILTIN(__builtin_wasm_grow_memory, "vz", "n")
+
+#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..f738cc1
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Basic/BuiltinsX86.def
@@ -0,0 +1,1577 @@
+//===--- 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: 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.
+
+#if defined(BUILTIN) && !defined(TARGET_BUILTIN)
+# define TARGET_BUILTIN(ID, TYPE, ATTRS, FEATURE) BUILTIN(ID, TYPE, ATTRS)
+#endif
+
+// FIXME: Are these nothrow/const?
+
+// Miscellaneous builtin for checking x86 cpu features.
+// TODO: Make this somewhat generic so that other backends
+// can use it?
+BUILTIN(__builtin_cpu_supports, "bcC*", "nc")
+
+// Win64-compatible va_list functions
+BUILTIN(__builtin_ms_va_start, "vc*&.", "nt")
+BUILTIN(__builtin_ms_va_end, "vc*&", "n")
+BUILTIN(__builtin_ms_va_copy, "vc*&c*&", "n")
+
+// Undefined Values
+//
+TARGET_BUILTIN(__builtin_ia32_undef128, "V2d", "nc", "")
+TARGET_BUILTIN(__builtin_ia32_undef256, "V4d", "nc", "")
+TARGET_BUILTIN(__builtin_ia32_undef512, "V8d", "nc", "")
+
+// FLAGS
+//
+TARGET_BUILTIN(__builtin_ia32_readeflags_u32, "Ui", "n", "")
+TARGET_BUILTIN(__builtin_ia32_readeflags_u64, "ULLi", "n", "")
+TARGET_BUILTIN(__builtin_ia32_writeeflags_u32, "vUi", "n", "")
+TARGET_BUILTIN(__builtin_ia32_writeeflags_u64, "vULLi", "n", "")
+
+// 3DNow!
+//
+TARGET_BUILTIN(__builtin_ia32_femms, "v", "", "3dnow")
+TARGET_BUILTIN(__builtin_ia32_pavgusb, "V8cV8cV8c", "nc", "3dnow")
+TARGET_BUILTIN(__builtin_ia32_pf2id, "V2iV2f", "nc", "3dnow")
+TARGET_BUILTIN(__builtin_ia32_pfacc, "V2fV2fV2f", "nc", "3dnow")
+TARGET_BUILTIN(__builtin_ia32_pfadd, "V2fV2fV2f", "nc", "3dnow")
+TARGET_BUILTIN(__builtin_ia32_pfcmpeq, "V2iV2fV2f", "nc", "3dnow")
+TARGET_BUILTIN(__builtin_ia32_pfcmpge, "V2iV2fV2f", "nc", "3dnow")
+TARGET_BUILTIN(__builtin_ia32_pfcmpgt, "V2iV2fV2f", "nc", "3dnow")
+TARGET_BUILTIN(__builtin_ia32_pfmax, "V2fV2fV2f", "nc", "3dnow")
+TARGET_BUILTIN(__builtin_ia32_pfmin, "V2fV2fV2f", "nc", "3dnow")
+TARGET_BUILTIN(__builtin_ia32_pfmul, "V2fV2fV2f", "nc", "3dnow")
+TARGET_BUILTIN(__builtin_ia32_pfrcp, "V2fV2f", "nc", "3dnow")
+TARGET_BUILTIN(__builtin_ia32_pfrcpit1, "V2fV2fV2f", "nc", "3dnow")
+TARGET_BUILTIN(__builtin_ia32_pfrcpit2, "V2fV2fV2f", "nc", "3dnow")
+TARGET_BUILTIN(__builtin_ia32_pfrsqrt, "V2fV2f", "nc", "3dnow")
+TARGET_BUILTIN(__builtin_ia32_pfrsqit1, "V2fV2fV2f", "nc", "3dnow")
+TARGET_BUILTIN(__builtin_ia32_pfsub, "V2fV2fV2f", "nc", "3dnow")
+TARGET_BUILTIN(__builtin_ia32_pfsubr, "V2fV2fV2f", "nc", "3dnow")
+TARGET_BUILTIN(__builtin_ia32_pi2fd, "V2fV2i", "nc", "3dnow")
+TARGET_BUILTIN(__builtin_ia32_pmulhrw, "V4sV4sV4s", "nc", "3dnow")
+// 3DNow! Extensions (3dnowa).
+TARGET_BUILTIN(__builtin_ia32_pf2iw, "V2iV2f", "nc", "3dnowa")
+TARGET_BUILTIN(__builtin_ia32_pfnacc, "V2fV2fV2f", "nc", "3dnowa")
+TARGET_BUILTIN(__builtin_ia32_pfpnacc, "V2fV2fV2f", "nc", "3dnowa")
+TARGET_BUILTIN(__builtin_ia32_pi2fw, "V2fV2i", "nc", "3dnowa")
+TARGET_BUILTIN(__builtin_ia32_pswapdsf, "V2fV2f", "nc", "3dnowa")
+TARGET_BUILTIN(__builtin_ia32_pswapdsi, "V2iV2i", "nc", "3dnowa")
+
+// MMX
+//
+// 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.
+// FIXME: _mm_prefetch must be a built-in because it takes a compile-time constant
+// argument and our prior approach of using a #define to the current built-in
+// doesn't work in the presence of re-declaration of _mm_prefetch for windows.
+TARGET_BUILTIN(_mm_prefetch, "vcC*i", "nc", "mmx")
+TARGET_BUILTIN(__builtin_ia32_emms, "v", "", "mmx")
+TARGET_BUILTIN(__builtin_ia32_paddb, "V8cV8cV8c", "", "mmx")
+TARGET_BUILTIN(__builtin_ia32_paddw, "V4sV4sV4s", "", "mmx")
+TARGET_BUILTIN(__builtin_ia32_paddd, "V2iV2iV2i", "", "mmx")
+TARGET_BUILTIN(__builtin_ia32_paddsb, "V8cV8cV8c", "", "mmx")
+TARGET_BUILTIN(__builtin_ia32_paddsw, "V4sV4sV4s", "", "mmx")
+TARGET_BUILTIN(__builtin_ia32_paddusb, "V8cV8cV8c", "", "mmx")
+TARGET_BUILTIN(__builtin_ia32_paddusw, "V4sV4sV4s", "", "mmx")
+TARGET_BUILTIN(__builtin_ia32_psubb, "V8cV8cV8c", "", "mmx")
+TARGET_BUILTIN(__builtin_ia32_psubw, "V4sV4sV4s", "", "mmx")
+TARGET_BUILTIN(__builtin_ia32_psubd, "V2iV2iV2i", "", "mmx")
+TARGET_BUILTIN(__builtin_ia32_psubsb, "V8cV8cV8c", "", "mmx")
+TARGET_BUILTIN(__builtin_ia32_psubsw, "V4sV4sV4s", "", "mmx")
+TARGET_BUILTIN(__builtin_ia32_psubusb, "V8cV8cV8c", "", "mmx")
+TARGET_BUILTIN(__builtin_ia32_psubusw, "V4sV4sV4s", "", "mmx")
+TARGET_BUILTIN(__builtin_ia32_pmulhw, "V4sV4sV4s", "", "mmx")
+TARGET_BUILTIN(__builtin_ia32_pmullw, "V4sV4sV4s", "", "mmx")
+TARGET_BUILTIN(__builtin_ia32_pmaddwd, "V2iV4sV4s", "", "mmx")
+TARGET_BUILTIN(__builtin_ia32_pand, "V1LLiV1LLiV1LLi", "", "mmx")
+TARGET_BUILTIN(__builtin_ia32_pandn, "V1LLiV1LLiV1LLi", "", "mmx")
+TARGET_BUILTIN(__builtin_ia32_por, "V1LLiV1LLiV1LLi", "", "mmx")
+TARGET_BUILTIN(__builtin_ia32_pxor, "V1LLiV1LLiV1LLi", "", "mmx")
+TARGET_BUILTIN(__builtin_ia32_psllw, "V4sV4sV1LLi", "", "mmx")
+TARGET_BUILTIN(__builtin_ia32_pslld, "V2iV2iV1LLi", "", "mmx")
+TARGET_BUILTIN(__builtin_ia32_psllq, "V1LLiV1LLiV1LLi", "", "mmx")
+TARGET_BUILTIN(__builtin_ia32_psrlw, "V4sV4sV1LLi", "", "mmx")
+TARGET_BUILTIN(__builtin_ia32_psrld, "V2iV2iV1LLi", "", "mmx")
+TARGET_BUILTIN(__builtin_ia32_psrlq, "V1LLiV1LLiV1LLi", "", "mmx")
+TARGET_BUILTIN(__builtin_ia32_psraw, "V4sV4sV1LLi", "", "mmx")
+TARGET_BUILTIN(__builtin_ia32_psrad, "V2iV2iV1LLi", "", "mmx")
+TARGET_BUILTIN(__builtin_ia32_psllwi, "V4sV4si", "", "mmx")
+TARGET_BUILTIN(__builtin_ia32_pslldi, "V2iV2ii", "", "mmx")
+TARGET_BUILTIN(__builtin_ia32_psllqi, "V1LLiV1LLii", "", "mmx")
+TARGET_BUILTIN(__builtin_ia32_psrlwi, "V4sV4si", "", "mmx")
+TARGET_BUILTIN(__builtin_ia32_psrldi, "V2iV2ii", "", "mmx")
+TARGET_BUILTIN(__builtin_ia32_psrlqi, "V1LLiV1LLii", "", "mmx")
+TARGET_BUILTIN(__builtin_ia32_psrawi, "V4sV4si", "", "mmx")
+TARGET_BUILTIN(__builtin_ia32_psradi, "V2iV2ii", "", "mmx")
+TARGET_BUILTIN(__builtin_ia32_packsswb, "V8cV4sV4s", "", "mmx")
+TARGET_BUILTIN(__builtin_ia32_packssdw, "V4sV2iV2i", "", "mmx")
+TARGET_BUILTIN(__builtin_ia32_packuswb, "V8cV4sV4s", "", "mmx")
+TARGET_BUILTIN(__builtin_ia32_punpckhbw, "V8cV8cV8c", "", "mmx")
+TARGET_BUILTIN(__builtin_ia32_punpckhwd, "V4sV4sV4s", "", "mmx")
+TARGET_BUILTIN(__builtin_ia32_punpckhdq, "V2iV2iV2i", "", "mmx")
+TARGET_BUILTIN(__builtin_ia32_punpcklbw, "V8cV8cV8c", "", "mmx")
+TARGET_BUILTIN(__builtin_ia32_punpcklwd, "V4sV4sV4s", "", "mmx")
+TARGET_BUILTIN(__builtin_ia32_punpckldq, "V2iV2iV2i", "", "mmx")
+TARGET_BUILTIN(__builtin_ia32_pcmpeqb, "V8cV8cV8c", "", "mmx")
+TARGET_BUILTIN(__builtin_ia32_pcmpeqw, "V4sV4sV4s", "", "mmx")
+TARGET_BUILTIN(__builtin_ia32_pcmpeqd, "V2iV2iV2i", "", "mmx")
+TARGET_BUILTIN(__builtin_ia32_pcmpgtb, "V8cV8cV8c", "", "mmx")
+TARGET_BUILTIN(__builtin_ia32_pcmpgtw, "V4sV4sV4s", "", "mmx")
+TARGET_BUILTIN(__builtin_ia32_pcmpgtd, "V2iV2iV2i", "", "mmx")
+TARGET_BUILTIN(__builtin_ia32_maskmovq, "vV8cV8cc*", "", "mmx")
+TARGET_BUILTIN(__builtin_ia32_movntq, "vV1LLi*V1LLi", "", "mmx")
+TARGET_BUILTIN(__builtin_ia32_vec_init_v2si, "V2iii", "", "mmx")
+TARGET_BUILTIN(__builtin_ia32_vec_init_v4hi, "V4sssss", "", "mmx")
+TARGET_BUILTIN(__builtin_ia32_vec_init_v8qi, "V8ccccccccc", "", "mmx")
+TARGET_BUILTIN(__builtin_ia32_vec_ext_v2si, "iV2ii", "", "mmx")
+
+// MMX2 (MMX+SSE) intrinsics
+TARGET_BUILTIN(__builtin_ia32_cvtpi2ps, "V4fV4fV2i", "", "sse")
+TARGET_BUILTIN(__builtin_ia32_cvtps2pi, "V2iV4f", "", "sse")
+TARGET_BUILTIN(__builtin_ia32_cvttps2pi, "V2iV4f", "", "sse")
+TARGET_BUILTIN(__builtin_ia32_pavgb, "V8cV8cV8c", "", "sse")
+TARGET_BUILTIN(__builtin_ia32_pavgw, "V4sV4sV4s", "", "sse")
+TARGET_BUILTIN(__builtin_ia32_pmaxsw, "V4sV4sV4s", "", "sse")
+TARGET_BUILTIN(__builtin_ia32_pmaxub, "V8cV8cV8c", "", "sse")
+TARGET_BUILTIN(__builtin_ia32_pminsw, "V4sV4sV4s", "", "sse")
+TARGET_BUILTIN(__builtin_ia32_pminub, "V8cV8cV8c", "", "sse")
+TARGET_BUILTIN(__builtin_ia32_pmovmskb, "iV8c", "", "sse")
+TARGET_BUILTIN(__builtin_ia32_pmulhuw, "V4sV4sV4s", "", "sse")
+TARGET_BUILTIN(__builtin_ia32_psadbw, "V4sV8cV8c", "", "sse")
+TARGET_BUILTIN(__builtin_ia32_pshufw, "V4sV4sIc", "", "sse")
+
+// MMX+SSE2
+TARGET_BUILTIN(__builtin_ia32_cvtpd2pi, "V2iV2d", "", "sse2")
+TARGET_BUILTIN(__builtin_ia32_cvtpi2pd, "V2dV2i", "", "sse2")
+TARGET_BUILTIN(__builtin_ia32_cvttpd2pi, "V2iV2d", "", "sse2")
+TARGET_BUILTIN(__builtin_ia32_paddq, "V1LLiV1LLiV1LLi", "", "sse2")
+TARGET_BUILTIN(__builtin_ia32_pmuludq, "V1LLiV2iV2i", "", "sse2")
+TARGET_BUILTIN(__builtin_ia32_psubq, "V1LLiV1LLiV1LLi", "", "sse2")
+
+// MMX+SSSE3
+TARGET_BUILTIN(__builtin_ia32_pabsb, "V8cV8c", "", "ssse3")
+TARGET_BUILTIN(__builtin_ia32_pabsd, "V2iV2i", "", "ssse3")
+TARGET_BUILTIN(__builtin_ia32_pabsw, "V4sV4s", "", "ssse3")
+TARGET_BUILTIN(__builtin_ia32_palignr, "V8cV8cV8cIc", "", "ssse3")
+TARGET_BUILTIN(__builtin_ia32_phaddd, "V2iV2iV2i", "", "ssse3")
+TARGET_BUILTIN(__builtin_ia32_phaddsw, "V4sV4sV4s", "", "ssse3")
+TARGET_BUILTIN(__builtin_ia32_phaddw, "V4sV4sV4s", "", "ssse3")
+TARGET_BUILTIN(__builtin_ia32_phsubd, "V2iV2iV2i", "", "ssse3")
+TARGET_BUILTIN(__builtin_ia32_phsubsw, "V4sV4sV4s", "", "ssse3")
+TARGET_BUILTIN(__builtin_ia32_phsubw, "V4sV4sV4s", "", "ssse3")
+TARGET_BUILTIN(__builtin_ia32_pmaddubsw, "V8cV8cV8c", "", "ssse3")
+TARGET_BUILTIN(__builtin_ia32_pmulhrsw, "V4sV4sV4s", "", "ssse3")
+TARGET_BUILTIN(__builtin_ia32_pshufb, "V8cV8cV8c", "", "ssse3")
+TARGET_BUILTIN(__builtin_ia32_psignw, "V4sV4sV4s", "", "ssse3")
+TARGET_BUILTIN(__builtin_ia32_psignb, "V8cV8cV8c", "", "ssse3")
+TARGET_BUILTIN(__builtin_ia32_psignd, "V2iV2iV2i", "", "ssse3")
+
+// SSE intrinsics.
+TARGET_BUILTIN(__builtin_ia32_comieq, "iV4fV4f", "", "sse")
+TARGET_BUILTIN(__builtin_ia32_comilt, "iV4fV4f", "", "sse")
+TARGET_BUILTIN(__builtin_ia32_comile, "iV4fV4f", "", "sse")
+TARGET_BUILTIN(__builtin_ia32_comigt, "iV4fV4f", "", "sse")
+TARGET_BUILTIN(__builtin_ia32_comige, "iV4fV4f", "", "sse")
+TARGET_BUILTIN(__builtin_ia32_comineq, "iV4fV4f", "", "sse")
+TARGET_BUILTIN(__builtin_ia32_ucomieq, "iV4fV4f", "", "sse")
+TARGET_BUILTIN(__builtin_ia32_ucomilt, "iV4fV4f", "", "sse")
+TARGET_BUILTIN(__builtin_ia32_ucomile, "iV4fV4f", "", "sse")
+TARGET_BUILTIN(__builtin_ia32_ucomigt, "iV4fV4f", "", "sse")
+TARGET_BUILTIN(__builtin_ia32_ucomige, "iV4fV4f", "", "sse")
+TARGET_BUILTIN(__builtin_ia32_ucomineq, "iV4fV4f", "", "sse")
+
+TARGET_BUILTIN(__builtin_ia32_comisdeq, "iV2dV2d", "", "sse2")
+TARGET_BUILTIN(__builtin_ia32_comisdlt, "iV2dV2d", "", "sse2")
+TARGET_BUILTIN(__builtin_ia32_comisdle, "iV2dV2d", "", "sse2")
+TARGET_BUILTIN(__builtin_ia32_comisdgt, "iV2dV2d", "", "sse2")
+TARGET_BUILTIN(__builtin_ia32_comisdge, "iV2dV2d", "", "sse2")
+TARGET_BUILTIN(__builtin_ia32_comisdneq, "iV2dV2d", "", "sse2")
+TARGET_BUILTIN(__builtin_ia32_ucomisdeq, "iV2dV2d", "", "sse2")
+TARGET_BUILTIN(__builtin_ia32_ucomisdlt, "iV2dV2d", "", "sse2")
+TARGET_BUILTIN(__builtin_ia32_ucomisdle, "iV2dV2d", "", "sse2")
+TARGET_BUILTIN(__builtin_ia32_ucomisdgt, "iV2dV2d", "", "sse2")
+TARGET_BUILTIN(__builtin_ia32_ucomisdge, "iV2dV2d", "", "sse2")
+TARGET_BUILTIN(__builtin_ia32_ucomisdneq, "iV2dV2d", "", "sse2")
+
+TARGET_BUILTIN(__builtin_ia32_cmpps, "V4fV4fV4fIc", "", "sse")
+TARGET_BUILTIN(__builtin_ia32_cmpeqps, "V4fV4fV4f", "", "sse")
+TARGET_BUILTIN(__builtin_ia32_cmpltps, "V4fV4fV4f", "", "sse")
+TARGET_BUILTIN(__builtin_ia32_cmpleps, "V4fV4fV4f", "", "sse")
+TARGET_BUILTIN(__builtin_ia32_cmpunordps, "V4fV4fV4f", "", "sse")
+TARGET_BUILTIN(__builtin_ia32_cmpneqps, "V4fV4fV4f", "", "sse")
+TARGET_BUILTIN(__builtin_ia32_cmpnltps, "V4fV4fV4f", "", "sse")
+TARGET_BUILTIN(__builtin_ia32_cmpnleps, "V4fV4fV4f", "", "sse")
+TARGET_BUILTIN(__builtin_ia32_cmpordps, "V4fV4fV4f", "", "sse")
+TARGET_BUILTIN(__builtin_ia32_cmpss, "V4fV4fV4fIc", "", "sse")
+TARGET_BUILTIN(__builtin_ia32_cmpeqss, "V4fV4fV4f", "", "sse")
+TARGET_BUILTIN(__builtin_ia32_cmpltss, "V4fV4fV4f", "", "sse")
+TARGET_BUILTIN(__builtin_ia32_cmpless, "V4fV4fV4f", "", "sse")
+TARGET_BUILTIN(__builtin_ia32_cmpunordss, "V4fV4fV4f", "", "sse")
+TARGET_BUILTIN(__builtin_ia32_cmpneqss, "V4fV4fV4f", "", "sse")
+TARGET_BUILTIN(__builtin_ia32_cmpnltss, "V4fV4fV4f", "", "sse")
+TARGET_BUILTIN(__builtin_ia32_cmpnless, "V4fV4fV4f", "", "sse")
+TARGET_BUILTIN(__builtin_ia32_cmpordss, "V4fV4fV4f", "", "sse")
+TARGET_BUILTIN(__builtin_ia32_minps, "V4fV4fV4f", "", "sse")
+TARGET_BUILTIN(__builtin_ia32_maxps, "V4fV4fV4f", "", "sse")
+TARGET_BUILTIN(__builtin_ia32_minss, "V4fV4fV4f", "", "sse")
+TARGET_BUILTIN(__builtin_ia32_maxss, "V4fV4fV4f", "", "sse")
+
+TARGET_BUILTIN(__builtin_ia32_cmppd, "V2dV2dV2dIc", "", "sse2")
+TARGET_BUILTIN(__builtin_ia32_cmpeqpd, "V2dV2dV2d", "", "sse2")
+TARGET_BUILTIN(__builtin_ia32_cmpltpd, "V2dV2dV2d", "", "sse2")
+TARGET_BUILTIN(__builtin_ia32_cmplepd, "V2dV2dV2d", "", "sse2")
+TARGET_BUILTIN(__builtin_ia32_cmpunordpd, "V2dV2dV2d", "", "sse2")
+TARGET_BUILTIN(__builtin_ia32_cmpneqpd, "V2dV2dV2d", "", "sse2")
+TARGET_BUILTIN(__builtin_ia32_cmpnltpd, "V2dV2dV2d", "", "sse2")
+TARGET_BUILTIN(__builtin_ia32_cmpnlepd, "V2dV2dV2d", "", "sse2")
+TARGET_BUILTIN(__builtin_ia32_cmpordpd, "V2dV2dV2d", "", "sse2")
+TARGET_BUILTIN(__builtin_ia32_cmpsd, "V2dV2dV2dIc", "", "sse2")
+TARGET_BUILTIN(__builtin_ia32_cmpeqsd, "V2dV2dV2d", "", "sse2")
+TARGET_BUILTIN(__builtin_ia32_cmpltsd, "V2dV2dV2d", "", "sse2")
+TARGET_BUILTIN(__builtin_ia32_cmplesd, "V2dV2dV2d", "", "sse2")
+TARGET_BUILTIN(__builtin_ia32_cmpunordsd, "V2dV2dV2d", "", "sse2")
+TARGET_BUILTIN(__builtin_ia32_cmpneqsd, "V2dV2dV2d", "", "sse2")
+TARGET_BUILTIN(__builtin_ia32_cmpnltsd, "V2dV2dV2d", "", "sse2")
+TARGET_BUILTIN(__builtin_ia32_cmpnlesd, "V2dV2dV2d", "", "sse2")
+TARGET_BUILTIN(__builtin_ia32_cmpordsd, "V2dV2dV2d", "", "sse2")
+TARGET_BUILTIN(__builtin_ia32_minpd, "V2dV2dV2d", "", "sse2")
+TARGET_BUILTIN(__builtin_ia32_maxpd, "V2dV2dV2d", "", "sse2")
+TARGET_BUILTIN(__builtin_ia32_minsd, "V2dV2dV2d", "", "sse2")
+TARGET_BUILTIN(__builtin_ia32_maxsd, "V2dV2dV2d", "", "sse2")
+TARGET_BUILTIN(__builtin_ia32_paddsb128, "V16cV16cV16c", "", "sse2")
+TARGET_BUILTIN(__builtin_ia32_paddsw128, "V8sV8sV8s", "", "sse2")
+TARGET_BUILTIN(__builtin_ia32_psubsb128, "V16cV16cV16c", "", "sse2")
+TARGET_BUILTIN(__builtin_ia32_psubsw128, "V8sV8sV8s", "", "sse2")
+TARGET_BUILTIN(__builtin_ia32_paddusb128, "V16cV16cV16c", "", "sse2")
+TARGET_BUILTIN(__builtin_ia32_paddusw128, "V8sV8sV8s", "", "sse2")
+TARGET_BUILTIN(__builtin_ia32_psubusb128, "V16cV16cV16c", "", "sse2")
+TARGET_BUILTIN(__builtin_ia32_psubusw128, "V8sV8sV8s", "", "sse2")
+TARGET_BUILTIN(__builtin_ia32_pmulhw128, "V8sV8sV8s", "", "sse2")
+TARGET_BUILTIN(__builtin_ia32_pavgb128, "V16cV16cV16c", "", "sse2")
+TARGET_BUILTIN(__builtin_ia32_pavgw128, "V8sV8sV8s", "", "sse2")
+TARGET_BUILTIN(__builtin_ia32_pmaxub128, "V16cV16cV16c", "", "sse2")
+TARGET_BUILTIN(__builtin_ia32_pmaxsw128, "V8sV8sV8s", "", "sse2")
+TARGET_BUILTIN(__builtin_ia32_pminub128, "V16cV16cV16c", "", "sse2")
+TARGET_BUILTIN(__builtin_ia32_pminsw128, "V8sV8sV8s", "", "sse2")
+TARGET_BUILTIN(__builtin_ia32_packsswb128, "V16cV8sV8s", "", "sse2")
+TARGET_BUILTIN(__builtin_ia32_packssdw128, "V8sV4iV4i", "", "sse2")
+TARGET_BUILTIN(__builtin_ia32_packuswb128, "V16cV8sV8s", "", "sse2")
+TARGET_BUILTIN(__builtin_ia32_pmulhuw128, "V8sV8sV8s", "", "sse2")
+
+TARGET_BUILTIN(__builtin_ia32_addsubps, "V4fV4fV4f", "", "sse3")
+TARGET_BUILTIN(__builtin_ia32_addsubpd, "V2dV2dV2d", "", "sse3")
+TARGET_BUILTIN(__builtin_ia32_haddps, "V4fV4fV4f", "", "sse3")
+TARGET_BUILTIN(__builtin_ia32_haddpd, "V2dV2dV2d", "", "sse3")
+TARGET_BUILTIN(__builtin_ia32_hsubps, "V4fV4fV4f", "", "sse3")
+TARGET_BUILTIN(__builtin_ia32_hsubpd, "V2dV2dV2d", "", "sse3")
+TARGET_BUILTIN(__builtin_ia32_phaddw128, "V8sV8sV8s", "", "ssse3")
+TARGET_BUILTIN(__builtin_ia32_phaddd128, "V4iV4iV4i", "", "ssse3")
+TARGET_BUILTIN(__builtin_ia32_phaddsw128, "V8sV8sV8s", "", "ssse3")
+TARGET_BUILTIN(__builtin_ia32_phsubw128, "V8sV8sV8s", "", "ssse3")
+TARGET_BUILTIN(__builtin_ia32_phsubd128, "V4iV4iV4i", "", "ssse3")
+TARGET_BUILTIN(__builtin_ia32_phsubsw128, "V8sV8sV8s", "", "ssse3")
+TARGET_BUILTIN(__builtin_ia32_pmaddubsw128, "V8sV16cV16c", "", "ssse3")
+TARGET_BUILTIN(__builtin_ia32_pmulhrsw128, "V8sV8sV8s", "", "ssse3")
+TARGET_BUILTIN(__builtin_ia32_pshufb128, "V16cV16cV16c", "", "ssse3")
+TARGET_BUILTIN(__builtin_ia32_psignb128, "V16cV16cV16c", "", "ssse3")
+TARGET_BUILTIN(__builtin_ia32_psignw128, "V8sV8sV8s", "", "ssse3")
+TARGET_BUILTIN(__builtin_ia32_psignd128, "V4iV4iV4i", "", "ssse3")
+TARGET_BUILTIN(__builtin_ia32_pabsb128, "V16cV16c", "", "ssse3")
+TARGET_BUILTIN(__builtin_ia32_pabsw128, "V8sV8s", "", "ssse3")
+TARGET_BUILTIN(__builtin_ia32_pabsd128, "V4iV4i", "", "ssse3")
+
+TARGET_BUILTIN(__builtin_ia32_ldmxcsr, "vUi", "", "sse")
+TARGET_BUILTIN(__builtin_ia32_stmxcsr, "Ui", "", "sse")
+TARGET_BUILTIN(__builtin_ia32_cvtss2si, "iV4f", "", "sse")
+TARGET_BUILTIN(__builtin_ia32_cvtss2si64, "LLiV4f", "", "sse")
+TARGET_BUILTIN(__builtin_ia32_storeups, "vf*V4f", "", "sse")
+TARGET_BUILTIN(__builtin_ia32_storehps, "vV2i*V4f", "", "sse")
+TARGET_BUILTIN(__builtin_ia32_storelps, "vV2i*V4f", "", "sse")
+TARGET_BUILTIN(__builtin_ia32_movmskps, "iV4f", "", "sse")
+TARGET_BUILTIN(__builtin_ia32_movntps, "vf*V4f", "", "sse")
+TARGET_BUILTIN(__builtin_ia32_sfence, "v", "", "sse")
+TARGET_BUILTIN(__builtin_ia32_rcpps, "V4fV4f", "", "sse")
+TARGET_BUILTIN(__builtin_ia32_rcpss, "V4fV4f", "", "sse")
+TARGET_BUILTIN(__builtin_ia32_rsqrtps, "V4fV4f", "", "sse")
+TARGET_BUILTIN(__builtin_ia32_rsqrtss, "V4fV4f", "", "sse")
+TARGET_BUILTIN(__builtin_ia32_sqrtps, "V4fV4f", "", "sse")
+TARGET_BUILTIN(__builtin_ia32_sqrtss, "V4fV4f", "", "sse")
+
+TARGET_BUILTIN(__builtin_ia32_maskmovdqu, "vV16cV16cc*", "", "sse2")
+TARGET_BUILTIN(__builtin_ia32_storeupd, "vd*V2d", "", "sse2")
+TARGET_BUILTIN(__builtin_ia32_movmskpd, "iV2d", "", "sse2")
+TARGET_BUILTIN(__builtin_ia32_pmovmskb128, "iV16c", "", "sse2")
+TARGET_BUILTIN(__builtin_ia32_movnti, "vi*i", "", "sse2")
+TARGET_BUILTIN(__builtin_ia32_movnti64, "vLLi*LLi", "", "sse2")
+TARGET_BUILTIN(__builtin_ia32_movntpd, "vd*V2d", "", "sse2")
+TARGET_BUILTIN(__builtin_ia32_movntdq, "vV2LLi*V2LLi", "", "sse2")
+TARGET_BUILTIN(__builtin_ia32_psadbw128, "V2LLiV16cV16c", "", "sse2")
+TARGET_BUILTIN(__builtin_ia32_sqrtpd, "V2dV2d", "", "sse2")
+TARGET_BUILTIN(__builtin_ia32_sqrtsd, "V2dV2d", "", "sse2")
+TARGET_BUILTIN(__builtin_ia32_cvtdq2pd, "V2dV4i", "", "sse2")
+TARGET_BUILTIN(__builtin_ia32_cvtdq2ps, "V4fV4i", "", "sse2")
+TARGET_BUILTIN(__builtin_ia32_cvtpd2dq, "V2LLiV2d", "", "sse2")
+TARGET_BUILTIN(__builtin_ia32_cvtpd2ps, "V4fV2d", "", "sse2")
+TARGET_BUILTIN(__builtin_ia32_cvttpd2dq, "V4iV2d", "", "sse2")
+TARGET_BUILTIN(__builtin_ia32_cvtsd2si, "iV2d", "", "sse2")
+TARGET_BUILTIN(__builtin_ia32_cvtsd2si64, "LLiV2d", "", "sse2")
+TARGET_BUILTIN(__builtin_ia32_cvtps2dq, "V4iV4f", "", "sse2")
+TARGET_BUILTIN(__builtin_ia32_cvtps2pd, "V2dV4f", "", "sse2")
+TARGET_BUILTIN(__builtin_ia32_cvttps2dq, "V4iV4f", "", "sse2")
+TARGET_BUILTIN(__builtin_ia32_clflush, "vvC*", "", "sse2")
+TARGET_BUILTIN(__builtin_ia32_lfence, "v", "", "sse2")
+TARGET_BUILTIN(__builtin_ia32_mfence, "v", "", "sse2")
+TARGET_BUILTIN(__builtin_ia32_pause, "v", "", "sse2")
+TARGET_BUILTIN(__builtin_ia32_storedqu, "vc*V16c", "", "sse2")
+TARGET_BUILTIN(__builtin_ia32_pmuludq128, "V2LLiV4iV4i", "", "sse2")
+TARGET_BUILTIN(__builtin_ia32_psraw128, "V8sV8sV8s", "", "sse2")
+TARGET_BUILTIN(__builtin_ia32_psrad128, "V4iV4iV4i", "", "sse2")
+TARGET_BUILTIN(__builtin_ia32_psrlw128, "V8sV8sV8s", "", "sse2")
+TARGET_BUILTIN(__builtin_ia32_psrld128, "V4iV4iV4i", "", "sse2")
+TARGET_BUILTIN(__builtin_ia32_psrlq128, "V2LLiV2LLiV2LLi", "", "sse2")
+TARGET_BUILTIN(__builtin_ia32_psllw128, "V8sV8sV8s", "", "sse2")
+TARGET_BUILTIN(__builtin_ia32_pslld128, "V4iV4iV4i", "", "sse2")
+TARGET_BUILTIN(__builtin_ia32_psllq128, "V2LLiV2LLiV2LLi", "", "sse2")
+TARGET_BUILTIN(__builtin_ia32_psllwi128, "V8sV8si", "", "sse2")
+TARGET_BUILTIN(__builtin_ia32_pslldi128, "V4iV4ii", "", "sse2")
+TARGET_BUILTIN(__builtin_ia32_psllqi128, "V2LLiV2LLii", "", "sse2")
+TARGET_BUILTIN(__builtin_ia32_psrlwi128, "V8sV8si", "", "sse2")
+TARGET_BUILTIN(__builtin_ia32_psrldi128, "V4iV4ii", "", "sse2")
+TARGET_BUILTIN(__builtin_ia32_psrlqi128, "V2LLiV2LLii", "", "sse2")
+TARGET_BUILTIN(__builtin_ia32_psrawi128, "V8sV8si", "", "sse2")
+TARGET_BUILTIN(__builtin_ia32_psradi128, "V4iV4ii", "", "sse2")
+TARGET_BUILTIN(__builtin_ia32_pmaddwd128, "V4iV8sV8s", "", "sse2")
+
+TARGET_BUILTIN(__builtin_ia32_monitor, "vv*UiUi", "", "sse3")
+TARGET_BUILTIN(__builtin_ia32_mwait, "vUiUi", "", "sse3")
+TARGET_BUILTIN(__builtin_ia32_lddqu, "V16ccC*", "", "sse3")
+
+TARGET_BUILTIN(__builtin_ia32_palignr128, "V16cV16cV16cIc", "", "ssse3")
+
+TARGET_BUILTIN(__builtin_ia32_insertps128, "V4fV4fV4fIc", "", "sse4.1")
+TARGET_BUILTIN(__builtin_ia32_pblendvb128, "V16cV16cV16cV16c", "", "sse4.1")
+TARGET_BUILTIN(__builtin_ia32_blendvpd, "V2dV2dV2dV2d", "", "sse4.1")
+TARGET_BUILTIN(__builtin_ia32_blendvps, "V4fV4fV4fV4f", "", "sse4.1")
+TARGET_BUILTIN(__builtin_ia32_packusdw128, "V8sV4iV4i", "", "sse4.1")
+
+TARGET_BUILTIN(__builtin_ia32_pmaxsb128, "V16cV16cV16c", "", "sse4.1")
+TARGET_BUILTIN(__builtin_ia32_pmaxsd128, "V4iV4iV4i", "", "sse4.1")
+TARGET_BUILTIN(__builtin_ia32_pmaxud128, "V4iV4iV4i", "", "sse4.1")
+TARGET_BUILTIN(__builtin_ia32_pmaxuw128, "V8sV8sV8s", "", "sse4.1")
+TARGET_BUILTIN(__builtin_ia32_pminsb128, "V16cV16cV16c", "", "sse4.1")
+TARGET_BUILTIN(__builtin_ia32_pminsd128, "V4iV4iV4i", "", "sse4.1")
+TARGET_BUILTIN(__builtin_ia32_pminud128, "V4iV4iV4i", "", "sse4.1")
+TARGET_BUILTIN(__builtin_ia32_pminuw128, "V8sV8sV8s", "", "sse4.1")
+TARGET_BUILTIN(__builtin_ia32_pmovzxbd128, "V4iV16c", "", "sse4.1")
+TARGET_BUILTIN(__builtin_ia32_pmovzxbq128, "V2LLiV16c", "", "sse4.1")
+TARGET_BUILTIN(__builtin_ia32_pmovzxbw128, "V8sV16c", "", "sse4.1")
+TARGET_BUILTIN(__builtin_ia32_pmovzxdq128, "V2LLiV4i", "", "sse4.1")
+TARGET_BUILTIN(__builtin_ia32_pmovzxwd128, "V4iV8s", "", "sse4.1")
+TARGET_BUILTIN(__builtin_ia32_pmovzxwq128, "V2LLiV8s", "", "sse4.1")
+TARGET_BUILTIN(__builtin_ia32_pmuldq128, "V2LLiV4iV4i", "", "sse4.1")
+TARGET_BUILTIN(__builtin_ia32_pmulld128, "V4iV4iV4i", "", "sse4.1")
+TARGET_BUILTIN(__builtin_ia32_roundps, "V4fV4fIi", "", "sse4.1")
+TARGET_BUILTIN(__builtin_ia32_roundss, "V4fV4fV4fIi", "", "sse4.1")
+TARGET_BUILTIN(__builtin_ia32_roundsd, "V2dV2dV2dIi", "", "sse4.1")
+TARGET_BUILTIN(__builtin_ia32_roundpd, "V2dV2dIi", "", "sse4.1")
+TARGET_BUILTIN(__builtin_ia32_dpps, "V4fV4fV4fIc", "", "sse4.1")
+TARGET_BUILTIN(__builtin_ia32_dppd, "V2dV2dV2dIc", "", "sse4.1")
+TARGET_BUILTIN(__builtin_ia32_movntdqa, "V2LLiV2LLiC*", "", "sse4.1")
+TARGET_BUILTIN(__builtin_ia32_ptestz128, "iV2LLiV2LLi", "", "sse4.1")
+TARGET_BUILTIN(__builtin_ia32_ptestc128, "iV2LLiV2LLi", "", "sse4.1")
+TARGET_BUILTIN(__builtin_ia32_ptestnzc128, "iV2LLiV2LLi", "", "sse4.1")
+TARGET_BUILTIN(__builtin_ia32_mpsadbw128, "V16cV16cV16cIc", "", "sse4.1")
+TARGET_BUILTIN(__builtin_ia32_phminposuw128, "V8sV8s", "", "sse4.1")
+
+// SSE 4.2
+TARGET_BUILTIN(__builtin_ia32_pcmpistrm128, "V16cV16cV16cIc", "", "sse4.2")
+TARGET_BUILTIN(__builtin_ia32_pcmpistri128, "iV16cV16cIc", "", "sse4.2")
+TARGET_BUILTIN(__builtin_ia32_pcmpestrm128, "V16cV16ciV16ciIc", "", "sse4.2")
+TARGET_BUILTIN(__builtin_ia32_pcmpestri128, "iV16ciV16ciIc","", "sse4.2")
+
+TARGET_BUILTIN(__builtin_ia32_pcmpistria128, "iV16cV16cIc","", "sse4.2")
+TARGET_BUILTIN(__builtin_ia32_pcmpistric128, "iV16cV16cIc","", "sse4.2")
+TARGET_BUILTIN(__builtin_ia32_pcmpistrio128, "iV16cV16cIc","", "sse4.2")
+TARGET_BUILTIN(__builtin_ia32_pcmpistris128, "iV16cV16cIc","", "sse4.2")
+TARGET_BUILTIN(__builtin_ia32_pcmpistriz128, "iV16cV16cIc","", "sse4.2")
+TARGET_BUILTIN(__builtin_ia32_pcmpestria128, "iV16ciV16ciIc","", "sse4.2")
+TARGET_BUILTIN(__builtin_ia32_pcmpestric128, "iV16ciV16ciIc","", "sse4.2")
+TARGET_BUILTIN(__builtin_ia32_pcmpestrio128, "iV16ciV16ciIc","", "sse4.2")
+TARGET_BUILTIN(__builtin_ia32_pcmpestris128, "iV16ciV16ciIc","", "sse4.2")
+TARGET_BUILTIN(__builtin_ia32_pcmpestriz128, "iV16ciV16ciIc","", "sse4.2")
+
+TARGET_BUILTIN(__builtin_ia32_crc32qi, "UiUiUc", "", "sse4.2")
+TARGET_BUILTIN(__builtin_ia32_crc32hi, "UiUiUs", "", "sse4.2")
+TARGET_BUILTIN(__builtin_ia32_crc32si, "UiUiUi", "", "sse4.2")
+TARGET_BUILTIN(__builtin_ia32_crc32di, "ULLiULLiULLi", "", "sse4.2")
+
+// SSE4a
+TARGET_BUILTIN(__builtin_ia32_extrqi, "V2LLiV2LLiIcIc", "", "sse4a")
+TARGET_BUILTIN(__builtin_ia32_extrq, "V2LLiV2LLiV16c", "", "sse4a")
+TARGET_BUILTIN(__builtin_ia32_insertqi, "V2LLiV2LLiV2LLiIcIc", "", "sse4a")
+TARGET_BUILTIN(__builtin_ia32_insertq, "V2LLiV2LLiV2LLi", "", "sse4a")
+TARGET_BUILTIN(__builtin_ia32_movntsd, "vd*V2d", "", "sse4a")
+TARGET_BUILTIN(__builtin_ia32_movntss, "vf*V4f", "", "sse4a")
+
+// AES
+TARGET_BUILTIN(__builtin_ia32_aesenc128, "V2LLiV2LLiV2LLi", "", "aes")
+TARGET_BUILTIN(__builtin_ia32_aesenclast128, "V2LLiV2LLiV2LLi", "", "aes")
+TARGET_BUILTIN(__builtin_ia32_aesdec128, "V2LLiV2LLiV2LLi", "", "aes")
+TARGET_BUILTIN(__builtin_ia32_aesdeclast128, "V2LLiV2LLiV2LLi", "", "aes")
+TARGET_BUILTIN(__builtin_ia32_aesimc128, "V2LLiV2LLi", "", "aes")
+TARGET_BUILTIN(__builtin_ia32_aeskeygenassist128, "V2LLiV2LLiIc", "", "aes")
+
+// CLMUL
+TARGET_BUILTIN(__builtin_ia32_pclmulqdq128, "V2LLiV2LLiV2LLiIc", "", "pclmul")
+
+// AVX
+TARGET_BUILTIN(__builtin_ia32_addsubpd256, "V4dV4dV4d", "", "avx")
+TARGET_BUILTIN(__builtin_ia32_addsubps256, "V8fV8fV8f", "", "avx")
+TARGET_BUILTIN(__builtin_ia32_haddpd256, "V4dV4dV4d", "", "avx")
+TARGET_BUILTIN(__builtin_ia32_hsubps256, "V8fV8fV8f", "", "avx")
+TARGET_BUILTIN(__builtin_ia32_hsubpd256, "V4dV4dV4d", "", "avx")
+TARGET_BUILTIN(__builtin_ia32_haddps256, "V8fV8fV8f", "", "avx")
+TARGET_BUILTIN(__builtin_ia32_maxpd256, "V4dV4dV4d", "", "avx")
+TARGET_BUILTIN(__builtin_ia32_maxps256, "V8fV8fV8f", "", "avx")
+TARGET_BUILTIN(__builtin_ia32_minpd256, "V4dV4dV4d", "", "avx")
+TARGET_BUILTIN(__builtin_ia32_minps256, "V8fV8fV8f", "", "avx")
+TARGET_BUILTIN(__builtin_ia32_vpermilvarpd, "V2dV2dV2LLi", "", "avx")
+TARGET_BUILTIN(__builtin_ia32_vpermilvarps, "V4fV4fV4i", "", "avx")
+TARGET_BUILTIN(__builtin_ia32_vpermilvarpd256, "V4dV4dV4LLi", "", "avx")
+TARGET_BUILTIN(__builtin_ia32_vpermilvarps256, "V8fV8fV8i", "", "avx")
+TARGET_BUILTIN(__builtin_ia32_blendvpd256, "V4dV4dV4dV4d", "", "avx")
+TARGET_BUILTIN(__builtin_ia32_blendvps256, "V8fV8fV8fV8f", "", "avx")
+TARGET_BUILTIN(__builtin_ia32_dpps256, "V8fV8fV8fIc", "", "avx")
+TARGET_BUILTIN(__builtin_ia32_cmppd256, "V4dV4dV4dIc", "", "avx")
+TARGET_BUILTIN(__builtin_ia32_cmpps256, "V8fV8fV8fIc", "", "avx")
+TARGET_BUILTIN(__builtin_ia32_cvtdq2pd256, "V4dV4i", "", "avx")
+TARGET_BUILTIN(__builtin_ia32_cvtdq2ps256, "V8fV8i", "", "avx")
+TARGET_BUILTIN(__builtin_ia32_cvtpd2ps256, "V4fV4d", "", "avx")
+TARGET_BUILTIN(__builtin_ia32_cvtps2dq256, "V8iV8f", "", "avx")
+TARGET_BUILTIN(__builtin_ia32_cvtps2pd256, "V4dV4f", "", "avx")
+TARGET_BUILTIN(__builtin_ia32_cvttpd2dq256, "V4iV4d", "", "avx")
+TARGET_BUILTIN(__builtin_ia32_cvtpd2dq256, "V4iV4d", "", "avx")
+TARGET_BUILTIN(__builtin_ia32_cvttps2dq256, "V8iV8f", "", "avx")
+TARGET_BUILTIN(__builtin_ia32_vperm2f128_pd256, "V4dV4dV4dIc", "", "avx")
+TARGET_BUILTIN(__builtin_ia32_vperm2f128_ps256, "V8fV8fV8fIc", "", "avx")
+TARGET_BUILTIN(__builtin_ia32_vperm2f128_si256, "V8iV8iV8iIc", "", "avx")
+TARGET_BUILTIN(__builtin_ia32_sqrtpd256, "V4dV4d", "", "avx")
+TARGET_BUILTIN(__builtin_ia32_sqrtps256, "V8fV8f", "", "avx")
+TARGET_BUILTIN(__builtin_ia32_rsqrtps256, "V8fV8f", "", "avx")
+TARGET_BUILTIN(__builtin_ia32_rcpps256, "V8fV8f", "", "avx")
+TARGET_BUILTIN(__builtin_ia32_roundpd256, "V4dV4dIi", "", "avx")
+TARGET_BUILTIN(__builtin_ia32_roundps256, "V8fV8fIi", "", "avx")
+TARGET_BUILTIN(__builtin_ia32_vtestzpd, "iV2dV2d", "", "avx")
+TARGET_BUILTIN(__builtin_ia32_vtestcpd, "iV2dV2d", "", "avx")
+TARGET_BUILTIN(__builtin_ia32_vtestnzcpd, "iV2dV2d", "", "avx")
+TARGET_BUILTIN(__builtin_ia32_vtestzps, "iV4fV4f", "", "avx")
+TARGET_BUILTIN(__builtin_ia32_vtestcps, "iV4fV4f", "", "avx")
+TARGET_BUILTIN(__builtin_ia32_vtestnzcps, "iV4fV4f", "", "avx")
+TARGET_BUILTIN(__builtin_ia32_vtestzpd256, "iV4dV4d", "", "avx")
+TARGET_BUILTIN(__builtin_ia32_vtestcpd256, "iV4dV4d", "", "avx")
+TARGET_BUILTIN(__builtin_ia32_vtestnzcpd256, "iV4dV4d", "", "avx")
+TARGET_BUILTIN(__builtin_ia32_vtestzps256, "iV8fV8f", "", "avx")
+TARGET_BUILTIN(__builtin_ia32_vtestcps256, "iV8fV8f", "", "avx")
+TARGET_BUILTIN(__builtin_ia32_vtestnzcps256, "iV8fV8f", "", "avx")
+TARGET_BUILTIN(__builtin_ia32_ptestz256, "iV4LLiV4LLi", "", "avx")
+TARGET_BUILTIN(__builtin_ia32_ptestc256, "iV4LLiV4LLi", "", "avx")
+TARGET_BUILTIN(__builtin_ia32_ptestnzc256, "iV4LLiV4LLi", "", "avx")
+TARGET_BUILTIN(__builtin_ia32_movmskpd256, "iV4d", "", "avx")
+TARGET_BUILTIN(__builtin_ia32_movmskps256, "iV8f", "", "avx")
+TARGET_BUILTIN(__builtin_ia32_vzeroall, "v", "", "avx")
+TARGET_BUILTIN(__builtin_ia32_vzeroupper, "v", "", "avx")
+TARGET_BUILTIN(__builtin_ia32_vbroadcastf128_pd256, "V4dV2dC*", "", "avx")
+TARGET_BUILTIN(__builtin_ia32_vbroadcastf128_ps256, "V8fV4fC*", "", "avx")
+TARGET_BUILTIN(__builtin_ia32_storeupd256, "vd*V4d", "", "avx")
+TARGET_BUILTIN(__builtin_ia32_storeups256, "vf*V8f", "", "avx")
+TARGET_BUILTIN(__builtin_ia32_storedqu256, "vc*V32c", "", "avx")
+TARGET_BUILTIN(__builtin_ia32_lddqu256, "V32ccC*", "", "avx")
+TARGET_BUILTIN(__builtin_ia32_movntdq256, "vV4LLi*V4LLi", "", "avx")
+TARGET_BUILTIN(__builtin_ia32_movntpd256, "vd*V4d", "", "avx")
+TARGET_BUILTIN(__builtin_ia32_movntps256, "vf*V8f", "", "avx")
+TARGET_BUILTIN(__builtin_ia32_maskloadpd, "V2dV2dC*V2LLi", "", "avx")
+TARGET_BUILTIN(__builtin_ia32_maskloadps, "V4fV4fC*V4i", "", "avx")
+TARGET_BUILTIN(__builtin_ia32_maskloadpd256, "V4dV4dC*V4LLi", "", "avx")
+TARGET_BUILTIN(__builtin_ia32_maskloadps256, "V8fV8fC*V8i", "", "avx")
+TARGET_BUILTIN(__builtin_ia32_maskstorepd, "vV2d*V2LLiV2d", "", "avx")
+TARGET_BUILTIN(__builtin_ia32_maskstoreps, "vV4f*V4iV4f", "", "avx")
+TARGET_BUILTIN(__builtin_ia32_maskstorepd256, "vV4d*V4LLiV4d", "", "avx")
+TARGET_BUILTIN(__builtin_ia32_maskstoreps256, "vV8f*V8iV8f", "", "avx")
+
+// AVX2
+TARGET_BUILTIN(__builtin_ia32_mpsadbw256, "V32cV32cV32cIc", "", "avx2")
+TARGET_BUILTIN(__builtin_ia32_pabsb256, "V32cV32c", "", "avx2")
+TARGET_BUILTIN(__builtin_ia32_pabsw256, "V16sV16s", "", "avx2")
+TARGET_BUILTIN(__builtin_ia32_pabsd256, "V8iV8i", "", "avx2")
+TARGET_BUILTIN(__builtin_ia32_packsswb256, "V32cV16sV16s", "", "avx2")
+TARGET_BUILTIN(__builtin_ia32_packssdw256, "V16sV8iV8i", "", "avx2")
+TARGET_BUILTIN(__builtin_ia32_packuswb256, "V32cV16sV16s", "", "avx2")
+TARGET_BUILTIN(__builtin_ia32_packusdw256, "V16sV8iV8i", "", "avx2")
+TARGET_BUILTIN(__builtin_ia32_paddsb256, "V32cV32cV32c", "", "avx2")
+TARGET_BUILTIN(__builtin_ia32_paddsw256, "V16sV16sV16s", "", "avx2")
+TARGET_BUILTIN(__builtin_ia32_psubsb256, "V32cV32cV32c", "", "avx2")
+TARGET_BUILTIN(__builtin_ia32_psubsw256, "V16sV16sV16s", "", "avx2")
+TARGET_BUILTIN(__builtin_ia32_paddusb256, "V32cV32cV32c", "", "avx2")
+TARGET_BUILTIN(__builtin_ia32_paddusw256, "V16sV16sV16s", "", "avx2")
+TARGET_BUILTIN(__builtin_ia32_psubusb256, "V32cV32cV32c", "", "avx2")
+TARGET_BUILTIN(__builtin_ia32_psubusw256, "V16sV16sV16s", "", "avx2")
+TARGET_BUILTIN(__builtin_ia32_palignr256, "V32cV32cV32cIc", "", "avx2")
+TARGET_BUILTIN(__builtin_ia32_pavgb256, "V32cV32cV32c", "", "avx2")
+TARGET_BUILTIN(__builtin_ia32_pavgw256, "V16sV16sV16s", "", "avx2")
+TARGET_BUILTIN(__builtin_ia32_pblendvb256, "V32cV32cV32cV32c", "", "avx2")
+TARGET_BUILTIN(__builtin_ia32_phaddw256, "V16sV16sV16s", "", "avx2")
+TARGET_BUILTIN(__builtin_ia32_phaddd256, "V8iV8iV8i", "", "avx2")
+TARGET_BUILTIN(__builtin_ia32_phaddsw256, "V16sV16sV16s", "", "avx2")
+TARGET_BUILTIN(__builtin_ia32_phsubw256, "V16sV16sV16s", "", "avx2")
+TARGET_BUILTIN(__builtin_ia32_phsubd256, "V8iV8iV8i", "", "avx2")
+TARGET_BUILTIN(__builtin_ia32_phsubsw256, "V16sV16sV16s", "", "avx2")
+TARGET_BUILTIN(__builtin_ia32_pmaddubsw256, "V16sV32cV32c", "", "avx2")
+TARGET_BUILTIN(__builtin_ia32_pmaddwd256, "V8iV16sV16s", "", "avx2")
+TARGET_BUILTIN(__builtin_ia32_pmaxub256, "V32cV32cV32c", "", "avx2")
+TARGET_BUILTIN(__builtin_ia32_pmaxuw256, "V16sV16sV16s", "", "avx2")
+TARGET_BUILTIN(__builtin_ia32_pmaxud256, "V8iV8iV8i", "", "avx2")
+TARGET_BUILTIN(__builtin_ia32_pmaxsb256, "V32cV32cV32c", "", "avx2")
+TARGET_BUILTIN(__builtin_ia32_pmaxsw256, "V16sV16sV16s", "", "avx2")
+TARGET_BUILTIN(__builtin_ia32_pmaxsd256, "V8iV8iV8i", "", "avx2")
+TARGET_BUILTIN(__builtin_ia32_pminub256, "V32cV32cV32c", "", "avx2")
+TARGET_BUILTIN(__builtin_ia32_pminuw256, "V16sV16sV16s", "", "avx2")
+TARGET_BUILTIN(__builtin_ia32_pminud256, "V8iV8iV8i", "", "avx2")
+TARGET_BUILTIN(__builtin_ia32_pminsb256, "V32cV32cV32c", "", "avx2")
+TARGET_BUILTIN(__builtin_ia32_pminsw256, "V16sV16sV16s", "", "avx2")
+TARGET_BUILTIN(__builtin_ia32_pminsd256, "V8iV8iV8i", "", "avx2")
+TARGET_BUILTIN(__builtin_ia32_pmovmskb256, "iV32c", "", "avx2")
+TARGET_BUILTIN(__builtin_ia32_pmovsxbw256, "V16sV16c", "", "avx2")
+TARGET_BUILTIN(__builtin_ia32_pmovsxbd256, "V8iV16c", "", "avx2")
+TARGET_BUILTIN(__builtin_ia32_pmovsxbq256, "V4LLiV16c", "", "avx2")
+TARGET_BUILTIN(__builtin_ia32_pmovsxwd256, "V8iV8s", "", "avx2")
+TARGET_BUILTIN(__builtin_ia32_pmovsxwq256, "V4LLiV8s", "", "avx2")
+TARGET_BUILTIN(__builtin_ia32_pmovsxdq256, "V4LLiV4i", "", "avx2")
+TARGET_BUILTIN(__builtin_ia32_pmovzxbw256, "V16sV16c", "", "avx2")
+TARGET_BUILTIN(__builtin_ia32_pmovzxbd256, "V8iV16c", "", "avx2")
+TARGET_BUILTIN(__builtin_ia32_pmovzxbq256, "V4LLiV16c", "", "avx2")
+TARGET_BUILTIN(__builtin_ia32_pmovzxwd256, "V8iV8s", "", "avx2")
+TARGET_BUILTIN(__builtin_ia32_pmovzxwq256, "V4LLiV8s", "", "avx2")
+TARGET_BUILTIN(__builtin_ia32_pmovzxdq256, "V4LLiV4i", "", "avx2")
+TARGET_BUILTIN(__builtin_ia32_pmuldq256, "V4LLiV8iV8i", "", "avx2")
+TARGET_BUILTIN(__builtin_ia32_pmulhrsw256, "V16sV16sV16s", "", "avx2")
+TARGET_BUILTIN(__builtin_ia32_pmulhuw256, "V16sV16sV16s", "", "avx2")
+TARGET_BUILTIN(__builtin_ia32_pmulhw256, "V16sV16sV16s", "", "avx2")
+TARGET_BUILTIN(__builtin_ia32_pmuludq256, "V4LLiV8iV8i", "", "avx2")
+TARGET_BUILTIN(__builtin_ia32_psadbw256, "V4LLiV32cV32c", "", "avx2")
+TARGET_BUILTIN(__builtin_ia32_pshufb256, "V32cV32cV32c", "", "avx2")
+TARGET_BUILTIN(__builtin_ia32_psignb256, "V32cV32cV32c", "", "avx2")
+TARGET_BUILTIN(__builtin_ia32_psignw256, "V16sV16sV16s", "", "avx2")
+TARGET_BUILTIN(__builtin_ia32_psignd256, "V8iV8iV8i", "", "avx2")
+TARGET_BUILTIN(__builtin_ia32_pslldqi256, "V4LLiV4LLiIi", "", "avx2")
+TARGET_BUILTIN(__builtin_ia32_psllwi256, "V16sV16si", "", "avx2")
+TARGET_BUILTIN(__builtin_ia32_psllw256, "V16sV16sV8s", "", "avx2")
+TARGET_BUILTIN(__builtin_ia32_pslldi256, "V8iV8ii", "", "avx2")
+TARGET_BUILTIN(__builtin_ia32_pslld256, "V8iV8iV4i", "", "avx2")
+TARGET_BUILTIN(__builtin_ia32_psllqi256, "V4LLiV4LLii", "", "avx2")
+TARGET_BUILTIN(__builtin_ia32_psllq256, "V4LLiV4LLiV2LLi", "", "avx2")
+TARGET_BUILTIN(__builtin_ia32_psrawi256, "V16sV16si", "", "avx2")
+TARGET_BUILTIN(__builtin_ia32_psraw256, "V16sV16sV8s", "", "avx2")
+TARGET_BUILTIN(__builtin_ia32_psradi256, "V8iV8ii", "", "avx2")
+TARGET_BUILTIN(__builtin_ia32_psrad256, "V8iV8iV4i", "", "avx2")
+TARGET_BUILTIN(__builtin_ia32_psrldqi256, "V4LLiV4LLiIi", "", "avx2")
+TARGET_BUILTIN(__builtin_ia32_psrlwi256, "V16sV16si", "", "avx2")
+TARGET_BUILTIN(__builtin_ia32_psrlw256, "V16sV16sV8s", "", "avx2")
+TARGET_BUILTIN(__builtin_ia32_psrldi256, "V8iV8ii", "", "avx2")
+TARGET_BUILTIN(__builtin_ia32_psrld256, "V8iV8iV4i", "", "avx2")
+TARGET_BUILTIN(__builtin_ia32_psrlqi256, "V4LLiV4LLii", "", "avx2")
+TARGET_BUILTIN(__builtin_ia32_psrlq256, "V4LLiV4LLiV2LLi", "", "avx2")
+TARGET_BUILTIN(__builtin_ia32_movntdqa256, "V4LLiV4LLiC*", "", "avx2")
+TARGET_BUILTIN(__builtin_ia32_permvarsi256, "V8iV8iV8i", "", "avx2")
+TARGET_BUILTIN(__builtin_ia32_permvarsf256, "V8fV8fV8i", "", "avx2")
+TARGET_BUILTIN(__builtin_ia32_permti256, "V4LLiV4LLiV4LLiIc", "", "avx2")
+TARGET_BUILTIN(__builtin_ia32_maskloadd256, "V8iV8iC*V8i", "", "avx2")
+TARGET_BUILTIN(__builtin_ia32_maskloadq256, "V4LLiV4LLiC*V4LLi", "", "avx2")
+TARGET_BUILTIN(__builtin_ia32_maskloadd, "V4iV4iC*V4i", "", "avx2")
+TARGET_BUILTIN(__builtin_ia32_maskloadq, "V2LLiV2LLiC*V2LLi", "", "avx2")
+TARGET_BUILTIN(__builtin_ia32_maskstored256, "vV8i*V8iV8i", "", "avx2")
+TARGET_BUILTIN(__builtin_ia32_maskstoreq256, "vV4LLi*V4LLiV4LLi", "", "avx2")
+TARGET_BUILTIN(__builtin_ia32_maskstored, "vV4i*V4iV4i", "", "avx2")
+TARGET_BUILTIN(__builtin_ia32_maskstoreq, "vV2LLi*V2LLiV2LLi", "", "avx2")
+TARGET_BUILTIN(__builtin_ia32_psllv8si, "V8iV8iV8i", "", "avx2")
+TARGET_BUILTIN(__builtin_ia32_psllv4si, "V4iV4iV4i", "", "avx2")
+TARGET_BUILTIN(__builtin_ia32_psllv4di, "V4LLiV4LLiV4LLi", "", "avx2")
+TARGET_BUILTIN(__builtin_ia32_psllv2di, "V2LLiV2LLiV2LLi", "", "avx2")
+TARGET_BUILTIN(__builtin_ia32_psrav8si, "V8iV8iV8i", "", "avx2")
+TARGET_BUILTIN(__builtin_ia32_psrav4si, "V4iV4iV4i", "", "avx2")
+TARGET_BUILTIN(__builtin_ia32_psrlv8si, "V8iV8iV8i", "", "avx2")
+TARGET_BUILTIN(__builtin_ia32_psrlv4si, "V4iV4iV4i", "", "avx2")
+TARGET_BUILTIN(__builtin_ia32_psrlv4di, "V4LLiV4LLiV4LLi", "", "avx2")
+TARGET_BUILTIN(__builtin_ia32_psrlv2di, "V2LLiV2LLiV2LLi", "", "avx2")
+
+// GATHER
+TARGET_BUILTIN(__builtin_ia32_gatherd_pd, "V2dV2ddC*V4iV2dIc", "", "avx2")
+TARGET_BUILTIN(__builtin_ia32_gatherd_pd256, "V4dV4ddC*V4iV4dIc", "", "avx2")
+TARGET_BUILTIN(__builtin_ia32_gatherq_pd, "V2dV2ddC*V2LLiV2dIc", "", "avx2")
+TARGET_BUILTIN(__builtin_ia32_gatherq_pd256, "V4dV4ddC*V4LLiV4dIc", "", "avx2")
+TARGET_BUILTIN(__builtin_ia32_gatherd_ps, "V4fV4ffC*V4iV4fIc", "", "avx2")
+TARGET_BUILTIN(__builtin_ia32_gatherd_ps256, "V8fV8ffC*V8iV8fIc", "", "avx2")
+TARGET_BUILTIN(__builtin_ia32_gatherq_ps, "V4fV4ffC*V2LLiV4fIc", "", "avx2")
+TARGET_BUILTIN(__builtin_ia32_gatherq_ps256, "V4fV4ffC*V4LLiV4fIc", "", "avx2")
+
+TARGET_BUILTIN(__builtin_ia32_gatherd_q, "V2LLiV2LLiLLiC*V4iV2LLiIc", "", "avx2")
+TARGET_BUILTIN(__builtin_ia32_gatherd_q256, "V4LLiV4LLiLLiC*V4iV4LLiIc", "", "avx2")
+TARGET_BUILTIN(__builtin_ia32_gatherq_q, "V2LLiV2LLiLLiC*V2LLiV2LLiIc", "", "avx2")
+TARGET_BUILTIN(__builtin_ia32_gatherq_q256, "V4LLiV4LLiLLiC*V4LLiV4LLiIc", "", "avx2")
+TARGET_BUILTIN(__builtin_ia32_gatherd_d, "V4iV4iiC*V4iV4iIc", "", "avx2")
+TARGET_BUILTIN(__builtin_ia32_gatherd_d256, "V8iV8iiC*V8iV8iIc", "", "avx2")
+TARGET_BUILTIN(__builtin_ia32_gatherq_d, "V4iV4iiC*V2LLiV4iIc", "", "avx2")
+TARGET_BUILTIN(__builtin_ia32_gatherq_d256, "V4iV4iiC*V4LLiV4iIc", "", "avx2")
+
+// F16C
+TARGET_BUILTIN(__builtin_ia32_vcvtps2ph, "V8sV4fIi", "", "f16c")
+TARGET_BUILTIN(__builtin_ia32_vcvtps2ph256, "V8sV8fIi", "", "f16c")
+TARGET_BUILTIN(__builtin_ia32_vcvtps2ph512, "V16sV16fIi", "", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_vcvtph2ps, "V4fV8s", "", "f16c")
+TARGET_BUILTIN(__builtin_ia32_vcvtph2ps256, "V8fV8s", "", "f16c")
+TARGET_BUILTIN(__builtin_ia32_vcvtph2ps512, "V16fV16s", "", "avx512f")
+
+// RDRAND
+TARGET_BUILTIN(__builtin_ia32_rdrand16_step, "UiUs*", "", "rdrnd")
+TARGET_BUILTIN(__builtin_ia32_rdrand32_step, "UiUi*", "", "rdrnd")
+TARGET_BUILTIN(__builtin_ia32_rdrand64_step, "UiULLi*", "", "rdrnd")
+
+// FSGSBASE
+TARGET_BUILTIN(__builtin_ia32_rdfsbase32, "Ui", "", "fsgsbase")
+TARGET_BUILTIN(__builtin_ia32_rdfsbase64, "ULLi", "", "fsgsbase")
+TARGET_BUILTIN(__builtin_ia32_rdgsbase32, "Ui", "", "fsgsbase")
+TARGET_BUILTIN(__builtin_ia32_rdgsbase64, "ULLi", "", "fsgsbase")
+TARGET_BUILTIN(__builtin_ia32_wrfsbase32, "vUi", "", "fsgsbase")
+TARGET_BUILTIN(__builtin_ia32_wrfsbase64, "vULLi", "", "fsgsbase")
+TARGET_BUILTIN(__builtin_ia32_wrgsbase32, "vUi", "", "fsgsbase")
+TARGET_BUILTIN(__builtin_ia32_wrgsbase64, "vULLi", "", "fsgsbase")
+
+// FXSR
+TARGET_BUILTIN(__builtin_ia32_fxrstor, "vv*", "", "fxsr")
+TARGET_BUILTIN(__builtin_ia32_fxrstor64, "vv*", "", "fxsr")
+TARGET_BUILTIN(__builtin_ia32_fxsave, "vv*", "", "fxsr")
+TARGET_BUILTIN(__builtin_ia32_fxsave64, "vv*", "", "fxsr")
+
+// XSAVE
+TARGET_BUILTIN(__builtin_ia32_xsave, "vv*ULLi", "", "xsave")
+TARGET_BUILTIN(__builtin_ia32_xsave64, "vv*ULLi", "", "xsave")
+TARGET_BUILTIN(__builtin_ia32_xrstor, "vv*ULLi", "", "xsave")
+TARGET_BUILTIN(__builtin_ia32_xrstor64, "vv*ULLi", "", "xsave")
+TARGET_BUILTIN(__builtin_ia32_xsaveopt, "vv*ULLi", "", "xsaveopt")
+TARGET_BUILTIN(__builtin_ia32_xsaveopt64, "vv*ULLi", "", "xsaveopt")
+TARGET_BUILTIN(__builtin_ia32_xrstors, "vv*ULLi", "", "xsaves")
+TARGET_BUILTIN(__builtin_ia32_xrstors64, "vv*ULLi", "", "xsaves")
+TARGET_BUILTIN(__builtin_ia32_xsavec, "vv*ULLi", "", "xsavec")
+TARGET_BUILTIN(__builtin_ia32_xsavec64, "vv*ULLi", "", "xsavec")
+TARGET_BUILTIN(__builtin_ia32_xsaves, "vv*ULLi", "", "xsaves")
+TARGET_BUILTIN(__builtin_ia32_xsaves64, "vv*ULLi", "", "xsaves")
+
+// ADX
+TARGET_BUILTIN(__builtin_ia32_addcarryx_u32, "UcUcUiUiUi*", "", "adx")
+TARGET_BUILTIN(__builtin_ia32_addcarryx_u64, "UcUcULLiULLiULLi*", "", "adx")
+TARGET_BUILTIN(__builtin_ia32_addcarry_u32, "UcUcUiUiUi*", "", "adx")
+TARGET_BUILTIN(__builtin_ia32_addcarry_u64, "UcUcULLiULLiULLi*", "", "adx")
+TARGET_BUILTIN(__builtin_ia32_subborrow_u32, "UcUcUiUiUi*", "", "adx")
+TARGET_BUILTIN(__builtin_ia32_subborrow_u64, "UcUcULLiULLiULLi*", "", "adx")
+
+// RDSEED
+TARGET_BUILTIN(__builtin_ia32_rdseed16_step, "UiUs*", "", "rdseed")
+TARGET_BUILTIN(__builtin_ia32_rdseed32_step, "UiUi*", "", "rdseed")
+TARGET_BUILTIN(__builtin_ia32_rdseed64_step, "UiULLi*", "", "rdseed")
+
+// BMI
+TARGET_BUILTIN(__builtin_ia32_bextr_u32, "UiUiUi", "", "bmi")
+TARGET_BUILTIN(__builtin_ia32_bextr_u64, "ULLiULLiULLi", "", "bmi")
+
+// BMI2
+TARGET_BUILTIN(__builtin_ia32_bzhi_si, "UiUiUi", "", "bmi2")
+TARGET_BUILTIN(__builtin_ia32_bzhi_di, "ULLiULLiULLi", "", "bmi2")
+TARGET_BUILTIN(__builtin_ia32_pdep_si, "UiUiUi", "", "bmi2")
+TARGET_BUILTIN(__builtin_ia32_pdep_di, "ULLiULLiULLi", "", "bmi2")
+TARGET_BUILTIN(__builtin_ia32_pext_si, "UiUiUi", "", "bmi2")
+TARGET_BUILTIN(__builtin_ia32_pext_di, "ULLiULLiULLi", "", "bmi2")
+
+// TBM
+TARGET_BUILTIN(__builtin_ia32_bextri_u32, "UiUiIUi", "", "tbm")
+TARGET_BUILTIN(__builtin_ia32_bextri_u64, "ULLiULLiIULLi", "", "tbm")
+
+// SHA
+TARGET_BUILTIN(__builtin_ia32_sha1rnds4, "V4iV4iV4iIc", "", "sha")
+TARGET_BUILTIN(__builtin_ia32_sha1nexte, "V4iV4iV4i", "", "sha")
+TARGET_BUILTIN(__builtin_ia32_sha1msg1, "V4iV4iV4i", "", "sha")
+TARGET_BUILTIN(__builtin_ia32_sha1msg2, "V4iV4iV4i", "", "sha")
+TARGET_BUILTIN(__builtin_ia32_sha256rnds2, "V4iV4iV4iV4i", "", "sha")
+TARGET_BUILTIN(__builtin_ia32_sha256msg1, "V4iV4iV4i", "", "sha")
+TARGET_BUILTIN(__builtin_ia32_sha256msg2, "V4iV4iV4i", "", "sha")
+
+// FMA
+TARGET_BUILTIN(__builtin_ia32_vfmaddps, "V4fV4fV4fV4f", "", "fma|fma4")
+TARGET_BUILTIN(__builtin_ia32_vfmaddpd, "V2dV2dV2dV2d", "", "fma|fma4")
+TARGET_BUILTIN(__builtin_ia32_vfmaddss, "V4fV4fV4fV4f", "", "fma|fma4")
+TARGET_BUILTIN(__builtin_ia32_vfmaddsd, "V2dV2dV2dV2d", "", "fma|fma4")
+TARGET_BUILTIN(__builtin_ia32_vfmsubps, "V4fV4fV4fV4f", "", "fma|fma4")
+TARGET_BUILTIN(__builtin_ia32_vfmsubpd, "V2dV2dV2dV2d", "", "fma|fma4")
+TARGET_BUILTIN(__builtin_ia32_vfmsubss, "V4fV4fV4fV4f", "", "fma|fma4")
+TARGET_BUILTIN(__builtin_ia32_vfmsubsd, "V2dV2dV2dV2d", "", "fma|fma4")
+TARGET_BUILTIN(__builtin_ia32_vfnmaddps, "V4fV4fV4fV4f", "", "fma|fma4")
+TARGET_BUILTIN(__builtin_ia32_vfnmaddpd, "V2dV2dV2dV2d", "", "fma|fma4")
+TARGET_BUILTIN(__builtin_ia32_vfnmaddss, "V4fV4fV4fV4f", "", "fma|fma4")
+TARGET_BUILTIN(__builtin_ia32_vfnmaddsd, "V2dV2dV2dV2d", "", "fma|fma4")
+TARGET_BUILTIN(__builtin_ia32_vfnmsubps, "V4fV4fV4fV4f", "", "fma|fma4")
+TARGET_BUILTIN(__builtin_ia32_vfnmsubpd, "V2dV2dV2dV2d", "", "fma|fma4")
+TARGET_BUILTIN(__builtin_ia32_vfnmsubss, "V4fV4fV4fV4f", "", "fma|fma4")
+TARGET_BUILTIN(__builtin_ia32_vfnmsubsd, "V2dV2dV2dV2d", "", "fma|fma4")
+TARGET_BUILTIN(__builtin_ia32_vfmaddsubps, "V4fV4fV4fV4f", "", "fma|fma4")
+TARGET_BUILTIN(__builtin_ia32_vfmaddsubpd, "V2dV2dV2dV2d", "", "fma|fma4")
+TARGET_BUILTIN(__builtin_ia32_vfmsubaddps, "V4fV4fV4fV4f", "", "fma|fma4")
+TARGET_BUILTIN(__builtin_ia32_vfmsubaddpd, "V2dV2dV2dV2d", "", "fma|fma4")
+TARGET_BUILTIN(__builtin_ia32_vfmaddps256, "V8fV8fV8fV8f", "", "fma|fma4")
+TARGET_BUILTIN(__builtin_ia32_vfmaddpd256, "V4dV4dV4dV4d", "", "fma|fma4")
+TARGET_BUILTIN(__builtin_ia32_vfmsubps256, "V8fV8fV8fV8f", "", "fma|fma4")
+TARGET_BUILTIN(__builtin_ia32_vfmsubpd256, "V4dV4dV4dV4d", "", "fma|fma4")
+TARGET_BUILTIN(__builtin_ia32_vfnmaddps256, "V8fV8fV8fV8f", "", "fma|fma4")
+TARGET_BUILTIN(__builtin_ia32_vfnmaddpd256, "V4dV4dV4dV4d", "", "fma|fma4")
+TARGET_BUILTIN(__builtin_ia32_vfnmsubps256, "V8fV8fV8fV8f", "", "fma|fma4")
+TARGET_BUILTIN(__builtin_ia32_vfnmsubpd256, "V4dV4dV4dV4d", "", "fma|fma4")
+TARGET_BUILTIN(__builtin_ia32_vfmaddsubps256, "V8fV8fV8fV8f", "", "fma|fma4")
+TARGET_BUILTIN(__builtin_ia32_vfmaddsubpd256, "V4dV4dV4dV4d", "", "fma|fma4")
+TARGET_BUILTIN(__builtin_ia32_vfmsubaddps256, "V8fV8fV8fV8f", "", "fma|fma4")
+TARGET_BUILTIN(__builtin_ia32_vfmsubaddpd256, "V4dV4dV4dV4d", "", "fma|fma4")
+
+TARGET_BUILTIN(__builtin_ia32_vfmaddpd128_mask, "V2dV2dV2dV2dUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_vfmaddpd128_mask3, "V2dV2dV2dV2dUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_vfmaddpd128_maskz, "V2dV2dV2dV2dUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_vfmaddpd256_mask, "V4dV4dV4dV4dUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_vfmaddpd256_mask3, "V4dV4dV4dV4dUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_vfmaddpd256_maskz, "V4dV4dV4dV4dUc", "", "avx512vl")
+
+TARGET_BUILTIN(__builtin_ia32_vfmaddpd512_mask, "V8dV8dV8dV8dUcIi", "", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_vfmaddpd512_mask3, "V8dV8dV8dV8dUcIi", "", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_vfmaddpd512_maskz, "V8dV8dV8dV8dUcIi", "", "avx512f")
+
+TARGET_BUILTIN(__builtin_ia32_vfmaddps128_mask, "V4fV4fV4fV4fUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_vfmaddps128_mask3, "V4fV4fV4fV4fUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_vfmaddps128_maskz, "V4fV4fV4fV4fUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_vfmaddps256_mask, "V8fV8fV8fV8fUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_vfmaddps256_mask3, "V8fV8fV8fV8fUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_vfmaddps256_maskz, "V8fV8fV8fV8fUc", "", "avx512vl")
+
+TARGET_BUILTIN(__builtin_ia32_vfmaddps512_mask, "V16fV16fV16fV16fUsIi", "", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_vfmaddps512_mask3, "V16fV16fV16fV16fUsIi", "", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_vfmaddps512_maskz, "V16fV16fV16fV16fUsIi", "", "avx512f")
+
+TARGET_BUILTIN(__builtin_ia32_vfmaddsubpd128_mask, "V2dV2dV2dV2dUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_vfmaddsubpd128_mask3, "V2dV2dV2dV2dUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_vfmaddsubpd128_maskz, "V2dV2dV2dV2dUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_vfmaddsubpd256_mask, "V4dV4dV4dV4dUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_vfmaddsubpd256_mask3, "V4dV4dV4dV4dUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_vfmaddsubpd256_maskz, "V4dV4dV4dV4dUc", "", "avx512vl")
+
+TARGET_BUILTIN(__builtin_ia32_vfmaddsubpd512_mask, "V8dV8dV8dV8dUcIi", "", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_vfmaddsubpd512_mask3, "V8dV8dV8dV8dUcIi", "", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_vfmaddsubpd512_maskz, "V8dV8dV8dV8dUcIi", "", "avx512f")
+
+TARGET_BUILTIN(__builtin_ia32_vfmaddsubps128_mask, "V4fV4fV4fV4fUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_vfmaddsubps128_mask3, "V4fV4fV4fV4fUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_vfmaddsubps128_maskz, "V4fV4fV4fV4fUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_vfmaddsubps256_mask, "V8fV8fV8fV8fUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_vfmaddsubps256_mask3, "V8fV8fV8fV8fUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_vfmaddsubps256_maskz, "V8fV8fV8fV8fUc", "", "avx512vl")
+
+TARGET_BUILTIN(__builtin_ia32_vfmaddsubps512_mask, "V16fV16fV16fV16fUsIi", "", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_vfmaddsubps512_mask3, "V16fV16fV16fV16fUsIi", "", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_vfmaddsubps512_maskz, "V16fV16fV16fV16fUsIi", "", "avx512f")
+
+TARGET_BUILTIN(__builtin_ia32_vfmsubpd128_mask3, "V2dV2dV2dV2dUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_vfmsubpd256_mask3, "V4dV4dV4dV4dUc", "", "avx512vl")
+
+TARGET_BUILTIN(__builtin_ia32_vfmsubpd512_mask3, "V8dV8dV8dV8dUcIi", "", "avx512f")
+
+TARGET_BUILTIN(__builtin_ia32_vfmsubps128_mask3, "V4fV4fV4fV4fUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_vfmsubps256_mask3, "V8fV8fV8fV8fUc", "", "avx512vl")
+
+TARGET_BUILTIN(__builtin_ia32_vfmsubps512_mask3, "V16fV16fV16fV16fUsIi", "", "avx512f")
+
+TARGET_BUILTIN(__builtin_ia32_vfmsubaddpd128_mask3, "V2dV2dV2dV2dUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_vfmsubaddpd256_mask3, "V4dV4dV4dV4dUc", "", "avx512vl")
+
+TARGET_BUILTIN(__builtin_ia32_vfmsubaddpd512_mask3, "V8dV8dV8dV8dUcIi", "", "avx512f")
+
+TARGET_BUILTIN(__builtin_ia32_vfmsubaddps128_mask3, "V4fV4fV4fV4fUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_vfmsubaddps256_mask3, "V8fV8fV8fV8fUc", "", "avx512vl")
+
+TARGET_BUILTIN(__builtin_ia32_vfmsubaddps512_mask3, "V16fV16fV16fV16fUsIi", "", "avx512f")
+
+TARGET_BUILTIN(__builtin_ia32_vfnmaddpd128_mask, "V2dV2dV2dV2dUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_vfnmaddpd256_mask, "V4dV4dV4dV4dUc", "", "avx512vl")
+
+TARGET_BUILTIN(__builtin_ia32_vfnmaddpd512_mask, "V8dV8dV8dV8dUcIi", "", "avx512f")
+
+TARGET_BUILTIN(__builtin_ia32_vfnmaddps128_mask, "V4fV4fV4fV4fUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_vfnmaddps256_mask, "V8fV8fV8fV8fUc", "", "avx512vl")
+
+TARGET_BUILTIN(__builtin_ia32_vfnmaddps512_mask, "V16fV16fV16fV16fUsIi", "", "avx512f")
+
+TARGET_BUILTIN(__builtin_ia32_vfnmsubpd128_mask, "V2dV2dV2dV2dUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_vfnmsubpd128_mask3, "V2dV2dV2dV2dUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_vfnmsubpd256_mask, "V4dV4dV4dV4dUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_vfnmsubpd256_mask3, "V4dV4dV4dV4dUc", "", "avx512vl")
+
+TARGET_BUILTIN(__builtin_ia32_vfnmsubpd512_mask, "V8dV8dV8dV8dUcIi", "", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_vfnmsubpd512_mask3, "V8dV8dV8dV8dUcIi", "", "avx512f")
+
+TARGET_BUILTIN(__builtin_ia32_vfnmsubps128_mask, "V4fV4fV4fV4fUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_vfnmsubps128_mask3, "V4fV4fV4fV4fUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_vfnmsubps256_mask, "V8fV8fV8fV8fUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_vfnmsubps256_mask3, "V8fV8fV8fV8fUc", "", "avx512vl")
+
+TARGET_BUILTIN(__builtin_ia32_vfnmsubps512_mask, "V16fV16fV16fV16fUsIi", "", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_vfnmsubps512_mask3, "V16fV16fV16fV16fUsIi", "", "avx512f")
+
+// XOP
+TARGET_BUILTIN(__builtin_ia32_vpmacssww, "V8sV8sV8sV8s", "", "xop")
+TARGET_BUILTIN(__builtin_ia32_vpmacsww, "V8sV8sV8sV8s", "", "xop")
+TARGET_BUILTIN(__builtin_ia32_vpmacsswd, "V4iV8sV8sV4i", "", "xop")
+TARGET_BUILTIN(__builtin_ia32_vpmacswd, "V4iV8sV8sV4i", "", "xop")
+TARGET_BUILTIN(__builtin_ia32_vpmacssdd, "V4iV4iV4iV4i", "", "xop")
+TARGET_BUILTIN(__builtin_ia32_vpmacsdd, "V4iV4iV4iV4i", "", "xop")
+TARGET_BUILTIN(__builtin_ia32_vpmacssdql, "V2LLiV4iV4iV2LLi", "", "xop")
+TARGET_BUILTIN(__builtin_ia32_vpmacsdql, "V2LLiV4iV4iV2LLi", "", "xop")
+TARGET_BUILTIN(__builtin_ia32_vpmacssdqh, "V2LLiV4iV4iV2LLi", "", "xop")
+TARGET_BUILTIN(__builtin_ia32_vpmacsdqh, "V2LLiV4iV4iV2LLi", "", "xop")
+TARGET_BUILTIN(__builtin_ia32_vpmadcsswd, "V4iV8sV8sV4i", "", "xop")
+TARGET_BUILTIN(__builtin_ia32_vpmadcswd, "V4iV8sV8sV4i", "", "xop")
+
+TARGET_BUILTIN(__builtin_ia32_vphaddbw, "V8sV16c", "", "xop")
+TARGET_BUILTIN(__builtin_ia32_vphaddbd, "V4iV16c", "", "xop")
+TARGET_BUILTIN(__builtin_ia32_vphaddbq, "V2LLiV16c", "", "xop")
+TARGET_BUILTIN(__builtin_ia32_vphaddwd, "V4iV8s", "", "xop")
+TARGET_BUILTIN(__builtin_ia32_vphaddwq, "V2LLiV8s", "", "xop")
+TARGET_BUILTIN(__builtin_ia32_vphadddq, "V2LLiV4i", "", "xop")
+TARGET_BUILTIN(__builtin_ia32_vphaddubw, "V8sV16c", "", "xop")
+TARGET_BUILTIN(__builtin_ia32_vphaddubd, "V4iV16c", "", "xop")
+TARGET_BUILTIN(__builtin_ia32_vphaddubq, "V2LLiV16c", "", "xop")
+TARGET_BUILTIN(__builtin_ia32_vphadduwd, "V4iV8s", "", "xop")
+TARGET_BUILTIN(__builtin_ia32_vphadduwq, "V2LLiV8s", "", "xop")
+TARGET_BUILTIN(__builtin_ia32_vphaddudq, "V2LLiV4i", "", "xop")
+TARGET_BUILTIN(__builtin_ia32_vphsubbw, "V8sV16c", "", "xop")
+TARGET_BUILTIN(__builtin_ia32_vphsubwd, "V4iV8s", "", "xop")
+TARGET_BUILTIN(__builtin_ia32_vphsubdq, "V2LLiV4i", "", "xop")
+TARGET_BUILTIN(__builtin_ia32_vpcmov, "V2LLiV2LLiV2LLiV2LLi", "", "xop")
+TARGET_BUILTIN(__builtin_ia32_vpcmov_256, "V4LLiV4LLiV4LLiV4LLi", "", "xop")
+TARGET_BUILTIN(__builtin_ia32_vpperm, "V16cV16cV16cV16c", "", "xop")
+TARGET_BUILTIN(__builtin_ia32_vprotb, "V16cV16cV16c", "", "xop")
+TARGET_BUILTIN(__builtin_ia32_vprotw, "V8sV8sV8s", "", "xop")
+TARGET_BUILTIN(__builtin_ia32_vprotd, "V4iV4iV4i", "", "xop")
+TARGET_BUILTIN(__builtin_ia32_vprotq, "V2LLiV2LLiV2LLi", "", "xop")
+TARGET_BUILTIN(__builtin_ia32_vprotbi, "V16cV16cIc", "", "xop")
+TARGET_BUILTIN(__builtin_ia32_vprotwi, "V8sV8sIc", "", "xop")
+TARGET_BUILTIN(__builtin_ia32_vprotdi, "V4iV4iIc", "", "xop")
+TARGET_BUILTIN(__builtin_ia32_vprotqi, "V2LLiV2LLiIc", "", "xop")
+TARGET_BUILTIN(__builtin_ia32_vpshlb, "V16cV16cV16c", "", "xop")
+TARGET_BUILTIN(__builtin_ia32_vpshlw, "V8sV8sV8s", "", "xop")
+TARGET_BUILTIN(__builtin_ia32_vpshld, "V4iV4iV4i", "", "xop")
+TARGET_BUILTIN(__builtin_ia32_vpshlq, "V2LLiV2LLiV2LLi", "", "xop")
+TARGET_BUILTIN(__builtin_ia32_vpshab, "V16cV16cV16c", "", "xop")
+TARGET_BUILTIN(__builtin_ia32_vpshaw, "V8sV8sV8s", "", "xop")
+TARGET_BUILTIN(__builtin_ia32_vpshad, "V4iV4iV4i", "", "xop")
+TARGET_BUILTIN(__builtin_ia32_vpshaq, "V2LLiV2LLiV2LLi", "", "xop")
+TARGET_BUILTIN(__builtin_ia32_vpcomub, "V16cV16cV16cIc", "", "xop")
+TARGET_BUILTIN(__builtin_ia32_vpcomuw, "V8sV8sV8sIc", "", "xop")
+TARGET_BUILTIN(__builtin_ia32_vpcomud, "V4iV4iV4iIc", "", "xop")
+TARGET_BUILTIN(__builtin_ia32_vpcomuq, "V2LLiV2LLiV2LLiIc", "", "xop")
+TARGET_BUILTIN(__builtin_ia32_vpcomb, "V16cV16cV16cIc", "", "xop")
+TARGET_BUILTIN(__builtin_ia32_vpcomw, "V8sV8sV8sIc", "", "xop")
+TARGET_BUILTIN(__builtin_ia32_vpcomd, "V4iV4iV4iIc", "", "xop")
+TARGET_BUILTIN(__builtin_ia32_vpcomq, "V2LLiV2LLiV2LLiIc", "", "xop")
+TARGET_BUILTIN(__builtin_ia32_vpermil2pd, "V2dV2dV2dV2LLiIc", "", "xop")
+TARGET_BUILTIN(__builtin_ia32_vpermil2pd256, "V4dV4dV4dV4LLiIc", "", "xop")
+TARGET_BUILTIN(__builtin_ia32_vpermil2ps, "V4fV4fV4fV4iIc", "", "xop")
+TARGET_BUILTIN(__builtin_ia32_vpermil2ps256, "V8fV8fV8fV8iIc", "", "xop")
+TARGET_BUILTIN(__builtin_ia32_vfrczss, "V4fV4f", "", "xop")
+TARGET_BUILTIN(__builtin_ia32_vfrczsd, "V2dV2d", "", "xop")
+TARGET_BUILTIN(__builtin_ia32_vfrczps, "V4fV4f", "", "xop")
+TARGET_BUILTIN(__builtin_ia32_vfrczpd, "V2dV2d", "", "xop")
+TARGET_BUILTIN(__builtin_ia32_vfrczps256, "V8fV8f", "", "xop")
+TARGET_BUILTIN(__builtin_ia32_vfrczpd256, "V4dV4d", "", "xop")
+
+TARGET_BUILTIN(__builtin_ia32_xbegin, "i", "", "rtm")
+TARGET_BUILTIN(__builtin_ia32_xend, "v", "", "rtm")
+TARGET_BUILTIN(__builtin_ia32_xabort, "vIc", "", "rtm")
+TARGET_BUILTIN(__builtin_ia32_xtest, "i", "", "rtm")
+
+BUILTIN(__builtin_ia32_rdpmc, "ULLii", "")
+BUILTIN(__builtin_ia32_rdtsc, "ULLi", "")
+BUILTIN(__builtin_ia32_rdtscp, "ULLiUi*", "")
+// PKU
+TARGET_BUILTIN(__builtin_ia32_rdpkru, "Ui", "", "pku")
+TARGET_BUILTIN(__builtin_ia32_wrpkru, "vUi", "", "pku")
+
+// AVX-512
+TARGET_BUILTIN(__builtin_ia32_sqrtpd512_mask, "V8dV8dV8dUcIi", "", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_sqrtps512_mask, "V16fV16fV16fUsIi", "", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_rsqrt14sd, "V2dV2dV2dV2dUc", "", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_rsqrt14ss, "V4fV4fV4fV4fUc", "", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_rsqrt14pd512_mask, "V8dV8dV8dUc", "", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_rsqrt14ps512_mask, "V16fV16fV16fUs", "", "avx512f")
+
+TARGET_BUILTIN(__builtin_ia32_rsqrt28sd_round, "V2dV2dV2dV2dUcIi", "", "avx512er")
+TARGET_BUILTIN(__builtin_ia32_rsqrt28ss_round, "V4fV4fV4fV4fUcIi", "", "avx512er")
+TARGET_BUILTIN(__builtin_ia32_rsqrt28pd_mask, "V8dV8dV8dUcIi", "", "avx512er")
+TARGET_BUILTIN(__builtin_ia32_rsqrt28ps_mask, "V16fV16fV16fUsIi", "", "avx512er")
+
+TARGET_BUILTIN(__builtin_ia32_rcp14sd, "V2dV2dV2dV2dUc", "", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_rcp14ss, "V4fV4fV4fV4fUc", "", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_rcp14pd512_mask, "V8dV8dV8dUc", "", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_rcp14ps512_mask, "V16fV16fV16fUs", "", "avx512f")
+
+TARGET_BUILTIN(__builtin_ia32_rcp28sd_round, "V2dV2dV2dV2dUcIi", "", "avx512er")
+TARGET_BUILTIN(__builtin_ia32_rcp28ss_round, "V4fV4fV4fV4fUcIi", "", "avx512er")
+TARGET_BUILTIN(__builtin_ia32_rcp28pd_mask, "V8dV8dV8dUcIi", "", "avx512er")
+TARGET_BUILTIN(__builtin_ia32_rcp28ps_mask, "V16fV16fV16fUsIi", "", "avx512er")
+TARGET_BUILTIN(__builtin_ia32_exp2pd_mask, "V8dV8dV8dUcIi", "", "avx512er")
+TARGET_BUILTIN(__builtin_ia32_exp2ps_mask, "V16fV16fV16fUsIi", "", "avx512er")
+
+TARGET_BUILTIN(__builtin_ia32_cvttps2dq512_mask, "V16iV16fV16iUsIi", "", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_cvttps2udq512_mask, "V16iV16fV16iUsIi", "", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_cvttpd2dq512_mask, "V8iV8dV8iUcIi", "", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_cvttpd2udq512_mask, "V8iV8dV8iUcIi", "", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_cmpps512_mask, "UsV16fV16fIiUsIi", "", "avx512f")
+
+TARGET_BUILTIN(__builtin_ia32_cmpps256_mask, "UcV8fV8fIiUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_cmpps128_mask, "UcV4fV4fIiUc", "", "avx512vl")
+
+TARGET_BUILTIN(__builtin_ia32_pcmpeqb512_mask, "LLiV64cV64cLLi", "", "avx512bw")
+TARGET_BUILTIN(__builtin_ia32_pcmpeqd512_mask, "sV16iV16is", "", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_pcmpeqq512_mask, "cV8LLiV8LLic", "", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_pcmpeqw512_mask, "iV32sV32si", "", "avx512bw")
+
+TARGET_BUILTIN(__builtin_ia32_pcmpeqb256_mask, "iV32cV32ci", "", "avx512vl,avx512bw")
+TARGET_BUILTIN(__builtin_ia32_pcmpeqd256_mask, "cV8iV8ic", "", "avx512vl,avx512bw")
+TARGET_BUILTIN(__builtin_ia32_pcmpeqq256_mask, "cV4LLiV4LLic", "", "avx512vl,avx512bw")
+TARGET_BUILTIN(__builtin_ia32_pcmpeqw256_mask, "sV16sV16ss", "", "avx512vl,avx512bw")
+TARGET_BUILTIN(__builtin_ia32_pcmpeqb128_mask, "sV16cV16cs", "", "avx512vl,avx512bw")
+TARGET_BUILTIN(__builtin_ia32_pcmpeqd128_mask, "cV4iV4ic", "", "avx512vl,avx512bw")
+TARGET_BUILTIN(__builtin_ia32_pcmpeqq128_mask, "cV2LLiV2LLic", "", "avx512vl,avx512bw")
+TARGET_BUILTIN(__builtin_ia32_pcmpeqw128_mask, "cV8sV8sc", "", "avx512vl,avx512bw")
+
+TARGET_BUILTIN(__builtin_ia32_pcmpgtb512_mask, "LLiV64cV64cLLi", "", "avx512bw")
+TARGET_BUILTIN(__builtin_ia32_pcmpgtd512_mask, "sV16iV16is", "", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_pcmpgtq512_mask, "cV8LLiV8LLic", "", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_pcmpgtw512_mask, "iV32sV32si", "", "avx512bw")
+
+TARGET_BUILTIN(__builtin_ia32_pcmpgtb256_mask, "iV32cV32ci", "", "avx512vl,avx512bw")
+TARGET_BUILTIN(__builtin_ia32_pcmpgtd256_mask, "cV8iV8ic", "", "avx512vl,avx512bw")
+TARGET_BUILTIN(__builtin_ia32_pcmpgtq256_mask, "cV4LLiV4LLic", "", "avx512vl,avx512bw")
+TARGET_BUILTIN(__builtin_ia32_pcmpgtw256_mask, "sV16sV16ss", "", "avx512vl,avx512bw")
+TARGET_BUILTIN(__builtin_ia32_pcmpgtb128_mask, "sV16cV16cs", "", "avx512vl,avx512bw")
+TARGET_BUILTIN(__builtin_ia32_pcmpgtd128_mask, "cV4iV4ic", "", "avx512vl,avx512bw")
+TARGET_BUILTIN(__builtin_ia32_pcmpgtq128_mask, "cV2LLiV2LLic", "", "avx512vl,avx512bw")
+TARGET_BUILTIN(__builtin_ia32_pcmpgtw128_mask, "cV8sV8sc", "", "avx512vl,avx512bw")
+
+TARGET_BUILTIN(__builtin_ia32_cmppd512_mask, "UcV8dV8dIiUcIi", "", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_cmppd256_mask, "UcV4dV4dIiUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_cmppd128_mask, "UcV2dV2dIiUc", "", "avx512vl")
+
+TARGET_BUILTIN(__builtin_ia32_rndscaleps_mask, "V16fV16fIiV16fUsIi", "", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_rndscalepd_mask, "V8dV8dIiV8dUcIi", "", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_cvtps2dq512_mask, "V16iV16fV16iUsIi", "", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_cvtpd2dq512_mask, "V8iV8dV8iUcIi", "", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_cvtps2udq512_mask, "V16iV16fV16iUsIi", "", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_cvtpd2udq512_mask, "V8iV8dV8iUcIi", "", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_minps512_mask, "V16fV16fV16fV16fUsIi", "", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_minpd512_mask, "V8dV8dV8dV8dUcIi", "", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_maxps512_mask, "V16fV16fV16fV16fUsIi", "", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_maxpd512_mask, "V8dV8dV8dV8dUcIi", "", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_cvtdq2ps512_mask, "V16fV16iV16fUsIi", "", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_cvtudq2ps512_mask, "V16fV16iV16fUsIi", "", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_cvtdq2pd512_mask, "V8dV8iV8dUc", "", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_cvtudq2pd512_mask, "V8dV8iV8dUc", "", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_cvtpd2ps512_mask, "V8fV8dV8fUcIi", "", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_vcvtps2ph512_mask, "V16sV16fIiV16sUs", "", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_vcvtph2ps512_mask, "V16fV16sV16fUsIi", "", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_pandd512_mask, "V16iV16iV16iV16iUs", "", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_pandq512_mask, "V8LLiV8LLiV8LLiV8LLiUc", "", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_pord512_mask, "V16iV16iV16iV16iUs", "", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_porq512_mask, "V8LLiV8LLiV8LLiV8LLiUc", "", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_pxord512_mask, "V16iV16iV16iV16iUs", "", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_pxorq512_mask, "V8LLiV8LLiV8LLiV8LLiUc", "", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_pabsd512_mask, "V16iV16iV16iUs", "", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_pabsq512_mask, "V8LLiV8LLiV8LLiUc", "", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_pmaxsd512_mask, "V16iV16iV16iV16iUs", "", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_pmaxsq512_mask, "V8LLiV8LLiV8LLiV8LLiUc", "", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_pmaxud512_mask, "V16iV16iV16iV16iUs", "", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_pmaxuq512_mask, "V8LLiV8LLiV8LLiV8LLiUc", "", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_pminsd512_mask, "V16iV16iV16iV16iUs", "", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_pminsq512_mask, "V8LLiV8LLiV8LLiV8LLiUc", "", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_pminud512_mask, "V16iV16iV16iV16iUs", "", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_pminuq512_mask, "V8LLiV8LLiV8LLiV8LLiUc", "", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_pmuldq512_mask, "V8LLiV16iV16iV8LLiUc", "", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_pmuludq512_mask, "V8LLiV16iV16iV8LLiUc", "", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_blendmd_512_mask, "V16iV16iV16iUs", "", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_blendmq_512_mask, "V8LLiV8LLiV8LLiUc", "", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_blendmps_512_mask, "V16fV16fV16fUs", "", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_blendmpd_512_mask, "V8dV8dV8dUc", "", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_ptestmd512, "UsV16iV16iUs", "", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_ptestmq512, "UcV8LLiV8LLiUc", "", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_pbroadcastd512_gpr_mask, "V16iiV16iUs", "", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_pbroadcastq512_gpr_mask, "V8LLiLLiV8LLiUc", "", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_pbroadcastq512_mem_mask, "V8LLiLLiV8LLiUc", "", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_loaddqusi512_mask, "V16ivC*V16iUs", "", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_loaddqudi512_mask, "V8LLivC*V8LLiUc", "", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_loadups512_mask, "V16fvC*V16fUs", "", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_loadaps512_mask, "V16fvC*V16fUs", "", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_loadupd512_mask, "V8dvC*V8dUc", "", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_loadapd512_mask, "V8dvC*V8dUc", "", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_storedqudi512_mask, "vv*V8LLiUc", "", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_storedqusi512_mask, "vv*V16iUs", "", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_storeupd512_mask, "vv*V8dUc", "", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_storeapd512_mask, "vv*V8dUc", "", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_storeups512_mask, "vv*V16fUs", "", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_storeaps512_mask, "vv*V16fUs", "", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_vpermt2vard512_mask, "V16iV16iV16iV16iUs", "", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_vpermt2varq512_mask, "V8LLiV8LLiV8LLiV8LLiUc", "", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_vpermt2varps512_mask, "V16fV16iV16fV16fUs", "", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_vpermt2varpd512_mask, "V8dV8LLiV8dV8dUc", "", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_alignq512_mask, "V8LLiV8LLiV8LLiIiV8LLiUc", "", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_alignd512_mask, "V16iV16iV16iIiV16iUs", "", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_extractf64x4_mask, "V4dV8dIiV4dUc", "", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_extractf32x4_mask, "V4fV16fIiV4fUc", "", "avx512f")
+
+TARGET_BUILTIN(__builtin_ia32_gathersiv8df, "V8dV8dvC*V8iUcIi", "", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_gathersiv16sf, "V16fV16fvC*UsIi", "", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_gatherdiv8df, "V8dV8dvC*V8LLiUcIi", "", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_gatherdiv16sf, "V8fV8fvC*V8LLiUcIi", "", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_gathersiv8di, "V8LLiV8LLivC*V8iUcIi", "", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_gathersiv16si, "V16iV16ivC*UsIi", "", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_gatherdiv8di, "V8LLiV8LLivC*V8LLiUcIi", "", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_gatherdiv16si, "V8iV8ivC*V8LLiUcIi", "", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_scattersiv8df, "vv*UcV8iV8dIi", "", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_scattersiv16sf, "vv*UsV16iV16fIi", "", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_scatterdiv8df, "vv*UcV8LLiV8dIi", "", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_scatterdiv16sf, "vv*UcV8LLiV8fIi", "", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_scattersiv8di, "vv*UcV8iV8LLiIi", "", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_scattersiv16si, "vv*UsV16iV16iIi", "", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_scatterdiv8di, "vv*UcV8LLiV8LLiIi", "", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_scatterdiv16si, "vv*UcV8LLiV8iIi", "", "avx512f")
+
+TARGET_BUILTIN(__builtin_ia32_gatherpfdpd, "vUcV8ivC*IiIi", "", "avx512pf")
+TARGET_BUILTIN(__builtin_ia32_gatherpfdps, "vUsV16ivC*IiIi", "", "avx512pf")
+TARGET_BUILTIN(__builtin_ia32_gatherpfqpd, "vUcV8LLivC*IiIi", "", "avx512pf")
+TARGET_BUILTIN(__builtin_ia32_gatherpfqps, "vUcV8LLivC*IiIi", "", "avx512pf")
+TARGET_BUILTIN(__builtin_ia32_scatterpfdpd, "vUcV8iv*IiIi", "", "avx512pf")
+TARGET_BUILTIN(__builtin_ia32_scatterpfdps, "vUsV16iv*IiIi", "", "avx512pf")
+TARGET_BUILTIN(__builtin_ia32_scatterpfqpd, "vUcV8LLiv*IiIi", "", "avx512pf")
+TARGET_BUILTIN(__builtin_ia32_scatterpfqps, "vUcV8LLiv*IiIi", "", "avx512pf")
+
+TARGET_BUILTIN(__builtin_ia32_knothi, "UsUs", "", "avx512f")
+
+TARGET_BUILTIN(__builtin_ia32_cmpb128_mask, "UsV16cV16cIiUs", "", "avx512vl,avx512bw")
+TARGET_BUILTIN(__builtin_ia32_cmpd128_mask, "UcV4iV4iIiUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_cmpq128_mask, "UcV2LLiV2LLiIiUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_cmpw128_mask, "UcV8sV8sIiUc", "", "avx512vl,avx512bw")
+TARGET_BUILTIN(__builtin_ia32_cmpb256_mask, "UiV32cV32cIiUi", "", "avx512vl,avx512bw")
+TARGET_BUILTIN(__builtin_ia32_cmpd256_mask, "UcV8iV8iIiUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_cmpq256_mask, "UcV4LLiV4LLiIiUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_cmpw256_mask, "UsV16sV16sIiUs", "", "avx512vl,avx512bw")
+TARGET_BUILTIN(__builtin_ia32_cmpb512_mask, "ULLiV64cV64cIiULLi", "", "avx512bw")
+TARGET_BUILTIN(__builtin_ia32_cmpd512_mask, "UsV16iV16iIiUs", "", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_cmpq512_mask, "UcV8LLiV8LLiIiUc", "", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_cmpw512_mask, "UiV32sV32sIiUi", "", "avx512bw")
+TARGET_BUILTIN(__builtin_ia32_ucmpb128_mask, "UsV16cV16cIiUs", "", "avx512vl,avx512bw")
+TARGET_BUILTIN(__builtin_ia32_ucmpd128_mask, "UcV4iV4iIiUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_ucmpq128_mask, "UcV2LLiV2LLiIiUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_ucmpw128_mask, "UcV8sV8sIiUc", "", "avx512vl,avx512bw")
+TARGET_BUILTIN(__builtin_ia32_ucmpb256_mask, "UiV32cV32cIiUi", "", "avx512vl,avx512bw")
+TARGET_BUILTIN(__builtin_ia32_ucmpd256_mask, "UcV8iV8iIiUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_ucmpq256_mask, "UcV4LLiV4LLiIiUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_ucmpw256_mask, "UsV16sV16sIiUs", "", "avx512vl,avx512bw")
+TARGET_BUILTIN(__builtin_ia32_ucmpb512_mask, "ULLiV64cV64cIiULLi", "", "avx512bw")
+TARGET_BUILTIN(__builtin_ia32_ucmpd512_mask, "UsV16iV16iIiUs", "", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_ucmpq512_mask, "UcV8LLiV8LLiIiUc", "", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_ucmpw512_mask, "UiV32sV32sIiUi", "", "avx512bw")
+
+TARGET_BUILTIN(__builtin_ia32_paddd256_mask, "V8iV8iV8iV8iUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_paddq256_mask, "V4LLiV4LLiV4LLiV4LLiUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_psubd256_mask, "V8iV8iV8iV8iUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_psubq256_mask, "V4LLiV4LLiV4LLiV4LLiUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_paddd128_mask, "V4iV4iV4iV4iUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_paddq128_mask, "V2LLiV2LLiV2LLiV2LLiUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_psubd128_mask, "V4iV4iV4iV4iUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_psubq128_mask, "V2LLiV2LLiV2LLiV2LLiUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_pmuldq256_mask, "V4LLiV8iV8iV4LLiUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_pmuldq128_mask, "V2LLiV4iV4iV2LLiUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_pmuludq256_mask, "V4LLiV8iV8iV4LLiUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_pmuludq128_mask, "V2LLiV4iV4iV2LLiUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_pmulld256_mask, "V8iV8iV8iV8iUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_pmulld128_mask, "V4iV4iV4iV4iUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_pandd256_mask, "V8iV8iV8iV8iUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_pandd128_mask, "V4iV4iV4iV4iUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_pandnd256_mask, "V8iV8iV8iV8iUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_pandnd128_mask, "V4iV4iV4iV4iUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_pord256_mask, "V8iV8iV8iV8iUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_pord128_mask, "V4iV4iV4iV4iUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_pxord256_mask, "V8iV8iV8iV8iUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_pxord128_mask, "V4iV4iV4iV4iUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_pandq256_mask, "V4LLiV4LLiV4LLiV4LLiUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_pandq128_mask, "V2LLiV2LLiV2LLiV2LLiUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_pandnq256_mask, "V4LLiV4LLiV4LLiV4LLiUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_pandnq128_mask, "V2LLiV2LLiV2LLiV2LLiUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_porq256_mask, "V4LLiV4LLiV4LLiV4LLiUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_porq128_mask, "V2LLiV2LLiV2LLiV2LLiUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_pxorq256_mask, "V4LLiV4LLiV4LLiV4LLiUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_pxorq128_mask, "V2LLiV2LLiV2LLiV2LLiUc", "", "avx512vl")
+
+TARGET_BUILTIN(__builtin_ia32_paddb512_mask, "V64cV64cV64cV64cULLi", "", "avx512bw")
+TARGET_BUILTIN(__builtin_ia32_psubb512_mask, "V64cV64cV64cV64cULLi", "", "avx512bw")
+TARGET_BUILTIN(__builtin_ia32_paddw512_mask, "V32sV32sV32sV32sUi", "", "avx512bw")
+TARGET_BUILTIN(__builtin_ia32_psubw512_mask, "V32sV32sV32sV32sUi", "", "avx512bw")
+TARGET_BUILTIN(__builtin_ia32_pmullw512_mask, "V32sV32sV32sV32sUi", "", "avx512bw")
+TARGET_BUILTIN(__builtin_ia32_paddb256_mask, "V32cV32cV32cV32cUi", "", "avx512vl,avx512bw")
+TARGET_BUILTIN(__builtin_ia32_paddw256_mask, "V16sV16sV16sV16sUs", "", "avx512vl,avx512bw")
+TARGET_BUILTIN(__builtin_ia32_psubb256_mask, "V32cV32cV32cV32cUi", "", "avx512vl,avx512bw")
+TARGET_BUILTIN(__builtin_ia32_psubw256_mask, "V16sV16sV16sV16sUs", "", "avx512vl,avx512bw")
+TARGET_BUILTIN(__builtin_ia32_paddb128_mask, "V16cV16cV16cV16cUs", "", "avx512vl,avx512bw")
+TARGET_BUILTIN(__builtin_ia32_paddw128_mask, "V8sV8sV8sV8sUc", "", "avx512vl,avx512bw")
+TARGET_BUILTIN(__builtin_ia32_psubb128_mask, "V16cV16cV16cV16cUs", "", "avx512vl,avx512bw")
+TARGET_BUILTIN(__builtin_ia32_psubw128_mask, "V8sV8sV8sV8sUc", "", "avx512vl,avx512bw")
+TARGET_BUILTIN(__builtin_ia32_pmullw256_mask, "V16sV16sV16sV16sUs", "", "avx512vl,avx512bw")
+TARGET_BUILTIN(__builtin_ia32_pmullw128_mask, "V8sV8sV8sV8sUc", "", "avx512vl,avx512bw")
+
+TARGET_BUILTIN(__builtin_ia32_pandnd512_mask, "V16iV16iV16iV16iUs", "", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_pandnq512_mask, "V8LLiV8LLiV8LLiV8LLiUc", "", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_paddq512_mask, "V8LLiV8LLiV8LLiV8LLiUc", "", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_psubq512_mask, "V8LLiV8LLiV8LLiV8LLiUc", "", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_paddd512_mask, "V16iV16iV16iV16iUs", "", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_psubd512_mask, "V16iV16iV16iV16iUs", "", "avx512f")
+
+TARGET_BUILTIN(__builtin_ia32_pmulld512_mask, "V16iV16iV16iV16iUs", "", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_pmullq512_mask, "V8LLiV8LLiV8LLiV8LLiUc", "", "avx512dq")
+TARGET_BUILTIN(__builtin_ia32_xorpd512_mask, "V8dV8dV8dV8dUc", "", "avx512dq")
+TARGET_BUILTIN(__builtin_ia32_xorps512_mask, "V16fV16fV16fV16fUs", "", "avx512dq")
+TARGET_BUILTIN(__builtin_ia32_orpd512_mask, "V8dV8dV8dV8dUc", "", "avx512dq")
+TARGET_BUILTIN(__builtin_ia32_orps512_mask, "V16fV16fV16fV16fUs", "", "avx512dq")
+TARGET_BUILTIN(__builtin_ia32_andpd512_mask, "V8dV8dV8dV8dUc", "", "avx512dq")
+TARGET_BUILTIN(__builtin_ia32_andps512_mask, "V16fV16fV16fV16fUs", "", "avx512dq")
+TARGET_BUILTIN(__builtin_ia32_andnpd512_mask, "V8dV8dV8dV8dUc", "", "avx512dq")
+TARGET_BUILTIN(__builtin_ia32_andnps512_mask, "V16fV16fV16fV16fUs", "", "avx512dq")
+TARGET_BUILTIN(__builtin_ia32_pmullq256_mask, "V4LLiV4LLiV4LLiV4LLiUc", "", "avx512vl,avx512dq")
+TARGET_BUILTIN(__builtin_ia32_pmullq128_mask, "V2LLiV2LLiV2LLiV2LLiUc", "", "avx512vl,avx512dq")
+TARGET_BUILTIN(__builtin_ia32_andnpd256_mask, "V4dV4dV4dV4dUc", "", "avx512vl,avx512dq")
+TARGET_BUILTIN(__builtin_ia32_andnpd128_mask, "V2dV2dV2dV2dUc", "", "avx512vl,avx512dq")
+TARGET_BUILTIN(__builtin_ia32_andnps256_mask, "V8fV8fV8fV8fUc", "", "avx512vl,avx512dq")
+TARGET_BUILTIN(__builtin_ia32_andnps128_mask, "V4fV4fV4fV4fUc", "", "avx512vl,avx512dq")
+TARGET_BUILTIN(__builtin_ia32_andpd256_mask, "V4dV4dV4dV4dUc", "", "avx512vl,avx512dq")
+TARGET_BUILTIN(__builtin_ia32_andpd128_mask, "V2dV2dV2dV2dUc", "", "avx512vl,avx512dq")
+TARGET_BUILTIN(__builtin_ia32_andps256_mask, "V8fV8fV8fV8fUc", "", "avx512vl,avx512dq")
+TARGET_BUILTIN(__builtin_ia32_andps128_mask, "V4fV4fV4fV4fUc", "", "avx512vl,avx512dq")
+TARGET_BUILTIN(__builtin_ia32_xorpd256_mask, "V4dV4dV4dV4dUc", "", "avx512vl,avx512dq")
+TARGET_BUILTIN(__builtin_ia32_xorpd128_mask, "V2dV2dV2dV2dUc", "", "avx512vl,avx512dq")
+TARGET_BUILTIN(__builtin_ia32_xorps256_mask, "V8fV8fV8fV8fUc", "", "avx512vl,avx512dq")
+TARGET_BUILTIN(__builtin_ia32_xorps128_mask, "V4fV4fV4fV4fUc", "", "avx512vl,avx512dq")
+TARGET_BUILTIN(__builtin_ia32_orpd256_mask, "V4dV4dV4dV4dUc", "", "avx512vl,avx512dq")
+TARGET_BUILTIN(__builtin_ia32_orpd128_mask, "V2dV2dV2dV2dUc", "", "avx512vl,avx512dq")
+TARGET_BUILTIN(__builtin_ia32_orps256_mask, "V8fV8fV8fV8fUc", "", "avx512vl,avx512dq")
+TARGET_BUILTIN(__builtin_ia32_orps128_mask, "V4fV4fV4fV4fUc", "", "avx512vl,avx512dq")
+
+TARGET_BUILTIN(__builtin_ia32_blendmb_512_mask, "V64cV64cV64cULLi", "", "avx512bw")
+TARGET_BUILTIN(__builtin_ia32_blendmw_512_mask, "V32sV32sV32sUi", "", "avx512bw")
+TARGET_BUILTIN(__builtin_ia32_pabsb512_mask, "V64cV64cV64cULLi", "", "avx512bw")
+TARGET_BUILTIN(__builtin_ia32_pabsw512_mask, "V32sV32sV32sUi", "", "avx512bw")
+TARGET_BUILTIN(__builtin_ia32_packssdw512_mask, "V32sV16iV16iV32sUi", "", "avx512bw")
+TARGET_BUILTIN(__builtin_ia32_packsswb512_mask, "V64cV32sV32sV64cULLi", "", "avx512bw")
+TARGET_BUILTIN(__builtin_ia32_packusdw512_mask, "V32sV16iV16iV32sUi", "", "avx512bw")
+TARGET_BUILTIN(__builtin_ia32_packuswb512_mask, "V64cV32sV32sV64cULLi", "", "avx512bw")
+TARGET_BUILTIN(__builtin_ia32_paddsb512_mask, "V64cV64cV64cV64cULLi", "", "avx512bw")
+TARGET_BUILTIN(__builtin_ia32_paddsw512_mask, "V32sV32sV32sV32sUi", "", "avx512bw")
+TARGET_BUILTIN(__builtin_ia32_paddusb512_mask, "V64cV64cV64cV64cULLi", "", "avx512bw")
+TARGET_BUILTIN(__builtin_ia32_paddusw512_mask, "V32sV32sV32sV32sUi", "", "avx512bw")
+TARGET_BUILTIN(__builtin_ia32_pavgb512_mask, "V64cV64cV64cV64cULLi", "", "avx512bw")
+TARGET_BUILTIN(__builtin_ia32_pavgw512_mask, "V32sV32sV32sV32sUi", "", "avx512bw")
+TARGET_BUILTIN(__builtin_ia32_pmaxsb512_mask, "V64cV64cV64cV64cULLi", "", "avx512bw")
+TARGET_BUILTIN(__builtin_ia32_pmaxsw512_mask, "V32sV32sV32sV32sUi", "", "avx512bw")
+TARGET_BUILTIN(__builtin_ia32_pmaxub512_mask, "V64cV64cV64cV64cULLi", "", "avx512bw")
+TARGET_BUILTIN(__builtin_ia32_pmaxuw512_mask, "V32sV32sV32sV32sUi", "", "avx512bw")
+TARGET_BUILTIN(__builtin_ia32_pminsb512_mask, "V64cV64cV64cV64cULLi", "", "avx512bw")
+TARGET_BUILTIN(__builtin_ia32_pminsw512_mask, "V32sV32sV32sV32sUi", "", "avx512bw")
+TARGET_BUILTIN(__builtin_ia32_pminub512_mask, "V64cV64cV64cV64cULLi", "", "avx512bw")
+TARGET_BUILTIN(__builtin_ia32_pminuw512_mask, "V32sV32sV32sV32sUi", "", "avx512bw")
+TARGET_BUILTIN(__builtin_ia32_pshufb512_mask, "V64cV64cV64cV64cULLi", "", "avx512bw")
+TARGET_BUILTIN(__builtin_ia32_psubsb512_mask, "V64cV64cV64cV64cULLi", "", "avx512bw")
+TARGET_BUILTIN(__builtin_ia32_psubsw512_mask, "V32sV32sV32sV32sUi", "", "avx512bw")
+TARGET_BUILTIN(__builtin_ia32_psubusb512_mask, "V64cV64cV64cV64cULLi", "", "avx512bw")
+TARGET_BUILTIN(__builtin_ia32_psubusw512_mask, "V32sV32sV32sV32sUi", "", "avx512bw")
+
+TARGET_BUILTIN(__builtin_ia32_vpermi2varhi512_mask, "V32sV32sV32sV32sUi", "", "avx512bw")
+TARGET_BUILTIN(__builtin_ia32_vpermt2varhi512_mask, "V32sV32sV32sV32sUi", "", "avx512bw")
+TARGET_BUILTIN(__builtin_ia32_vpermt2varhi512_maskz, "V32sV32sV32sV32sUi", "", "avx512bw")
+
+TARGET_BUILTIN(__builtin_ia32_vpconflictdi_512_mask, "V8LLiV8LLiV8LLiUc", "", "avx512cd")
+TARGET_BUILTIN(__builtin_ia32_vpconflictsi_512_mask, "V16iV16iV16iUs", "", "avx512cd")
+TARGET_BUILTIN(__builtin_ia32_vplzcntd_512_mask, "V16iV16iV16iUs", "", "avx512cd")
+TARGET_BUILTIN(__builtin_ia32_vplzcntq_512_mask, "V8LLiV8LLiV8LLiUc", "", "avx512cd")
+
+TARGET_BUILTIN(__builtin_ia32_blendmb_128_mask, "V16cV16cV16cUs", "", "avx512vl,avx512bw")
+TARGET_BUILTIN(__builtin_ia32_blendmb_256_mask, "V32cV32cV32cUi", "", "avx512vl,avx512bw")
+TARGET_BUILTIN(__builtin_ia32_blendmw_128_mask, "V8sV8sV8sUc", "", "avx512vl,avx512bw")
+TARGET_BUILTIN(__builtin_ia32_blendmw_256_mask, "V16sV16sV16sUs", "", "avx512vl,avx512bw")
+TARGET_BUILTIN(__builtin_ia32_pabsb128_mask, "V16cV16cV16cUs", "", "avx512vl,avx512bw")
+TARGET_BUILTIN(__builtin_ia32_pabsb256_mask, "V32cV32cV32cUi", "", "avx512vl,avx512bw")
+TARGET_BUILTIN(__builtin_ia32_pabsw128_mask, "V8sV8sV8sUc", "", "avx512vl,avx512bw")
+TARGET_BUILTIN(__builtin_ia32_pabsw256_mask, "V16sV16sV16sUs", "", "avx512vl,avx512bw")
+TARGET_BUILTIN(__builtin_ia32_packssdw128_mask, "V8sV4iV4iV8sUc", "", "avx512vl,avx512bw")
+TARGET_BUILTIN(__builtin_ia32_packssdw256_mask, "V16sV8iV8iV16sUs", "", "avx512vl,avx512bw")
+TARGET_BUILTIN(__builtin_ia32_packsswb128_mask, "V16cV8sV8sV16cUs", "", "avx512vl,avx512bw")
+TARGET_BUILTIN(__builtin_ia32_packsswb256_mask, "V32cV16sV16sV32cUi", "", "avx512vl,avx512bw")
+TARGET_BUILTIN(__builtin_ia32_packusdw128_mask, "V8sV4iV4iV8sUc", "", "avx512vl,avx512bw")
+TARGET_BUILTIN(__builtin_ia32_packusdw256_mask, "V16sV8iV8iV16sUs", "", "avx512vl,avx512bw")
+TARGET_BUILTIN(__builtin_ia32_packuswb128_mask, "V16cV8sV8sV16cUs", "", "avx512vl,avx512bw")
+TARGET_BUILTIN(__builtin_ia32_packuswb256_mask, "V32cV16sV16sV32cUi", "", "avx512vl,avx512bw")
+TARGET_BUILTIN(__builtin_ia32_paddsb128_mask, "V16cV16cV16cV16cUs", "", "avx512vl,avx512bw")
+TARGET_BUILTIN(__builtin_ia32_paddsb256_mask, "V32cV32cV32cV32cUi", "", "avx512vl,avx512bw")
+TARGET_BUILTIN(__builtin_ia32_paddsw128_mask, "V8sV8sV8sV8sUc", "", "avx512vl,avx512bw")
+TARGET_BUILTIN(__builtin_ia32_paddsw256_mask, "V16sV16sV16sV16sUs", "", "avx512vl,avx512bw")
+TARGET_BUILTIN(__builtin_ia32_paddusb128_mask, "V16cV16cV16cV16cUs", "", "avx512vl,avx512bw")
+TARGET_BUILTIN(__builtin_ia32_paddusb256_mask, "V32cV32cV32cV32cUi", "", "avx512vl,avx512bw")
+TARGET_BUILTIN(__builtin_ia32_paddusw128_mask, "V8sV8sV8sV8sUc", "", "avx512vl,avx512bw")
+TARGET_BUILTIN(__builtin_ia32_paddusw256_mask, "V16sV16sV16sV16sUs", "", "avx512vl,avx512bw")
+TARGET_BUILTIN(__builtin_ia32_pavgb128_mask, "V16cV16cV16cV16cUs", "", "avx512vl,avx512bw")
+TARGET_BUILTIN(__builtin_ia32_pavgb256_mask, "V32cV32cV32cV32cUi", "", "avx512vl,avx512bw")
+TARGET_BUILTIN(__builtin_ia32_pavgw128_mask, "V8sV8sV8sV8sUc", "", "avx512vl,avx512bw")
+TARGET_BUILTIN(__builtin_ia32_pavgw256_mask, "V16sV16sV16sV16sUs", "", "avx512vl,avx512bw")
+TARGET_BUILTIN(__builtin_ia32_pmaxsb128_mask, "V16cV16cV16cV16cUs", "", "avx512vl,avx512bw")
+TARGET_BUILTIN(__builtin_ia32_pmaxsb256_mask, "V32cV32cV32cV32cUi", "", "avx512vl,avx512bw")
+TARGET_BUILTIN(__builtin_ia32_pmaxsw128_mask, "V8sV8sV8sV8sUc", "", "avx512vl,avx512bw")
+TARGET_BUILTIN(__builtin_ia32_pmaxsw256_mask, "V16sV16sV16sV16sUs", "", "avx512vl,avx512bw")
+TARGET_BUILTIN(__builtin_ia32_pmaxub128_mask, "V16cV16cV16cV16cUs", "", "avx512vl,avx512bw")
+TARGET_BUILTIN(__builtin_ia32_pmaxub256_mask, "V32cV32cV32cV32cUi", "", "avx512vl,avx512bw")
+TARGET_BUILTIN(__builtin_ia32_pmaxuw128_mask, "V8sV8sV8sV8sUc", "", "avx512vl,avx512bw")
+TARGET_BUILTIN(__builtin_ia32_pmaxuw256_mask, "V16sV16sV16sV16sUs", "", "avx512vl,avx512bw")
+TARGET_BUILTIN(__builtin_ia32_pminsb128_mask, "V16cV16cV16cV16cUs", "", "avx512vl,avx512bw")
+TARGET_BUILTIN(__builtin_ia32_pminsb256_mask, "V32cV32cV32cV32cUi", "", "avx512vl,avx512bw")
+TARGET_BUILTIN(__builtin_ia32_pminsw128_mask, "V8sV8sV8sV8sUc", "", "avx512vl,avx512bw")
+TARGET_BUILTIN(__builtin_ia32_pminsw256_mask, "V16sV16sV16sV16sUs", "", "avx512vl,avx512bw")
+TARGET_BUILTIN(__builtin_ia32_pminub128_mask, "V16cV16cV16cV16cUs", "", "avx512vl,avx512bw")
+TARGET_BUILTIN(__builtin_ia32_pminub256_mask, "V32cV32cV32cV32cUi", "", "avx512vl,avx512bw")
+TARGET_BUILTIN(__builtin_ia32_pminuw128_mask, "V8sV8sV8sV8sUc", "", "avx512vl,avx512bw")
+TARGET_BUILTIN(__builtin_ia32_pminuw256_mask, "V16sV16sV16sV16sUs", "", "avx512vl,avx512bw")
+TARGET_BUILTIN(__builtin_ia32_pshufb128_mask, "V16cV16cV16cV16cUs", "", "avx512vl,avx512bw")
+TARGET_BUILTIN(__builtin_ia32_pshufb256_mask, "V32cV32cV32cV32cUi", "", "avx512vl,avx512bw")
+TARGET_BUILTIN(__builtin_ia32_psubsb128_mask, "V16cV16cV16cV16cUs", "", "avx512vl,avx512bw")
+TARGET_BUILTIN(__builtin_ia32_psubsb256_mask, "V32cV32cV32cV32cUi", "", "avx512vl,avx512bw")
+TARGET_BUILTIN(__builtin_ia32_psubsw128_mask, "V8sV8sV8sV8sUc", "", "avx512vl,avx512bw")
+TARGET_BUILTIN(__builtin_ia32_psubsw256_mask, "V16sV16sV16sV16sUs", "", "avx512vl,avx512bw")
+TARGET_BUILTIN(__builtin_ia32_psubusb128_mask, "V16cV16cV16cV16cUs", "", "avx512vl,avx512bw")
+TARGET_BUILTIN(__builtin_ia32_psubusb256_mask, "V32cV32cV32cV32cUi", "", "avx512vl,avx512bw")
+TARGET_BUILTIN(__builtin_ia32_psubusw128_mask, "V8sV8sV8sV8sUc", "", "avx512vl,avx512bw")
+TARGET_BUILTIN(__builtin_ia32_psubusw256_mask, "V16sV16sV16sV16sUs", "", "avx512vl,avx512bw")
+
+TARGET_BUILTIN(__builtin_ia32_vpermi2varhi128_mask, "V8sV8sV8sV8sUc", "", "avx512vl,avx512bw")
+TARGET_BUILTIN(__builtin_ia32_vpermi2varhi256_mask, "V16sV16sV16sV16sUs", "", "avx512vl,avx512bw")
+TARGET_BUILTIN(__builtin_ia32_vpermt2varhi128_mask, "V8sV8sV8sV8sUc", "", "avx512vl,avx512bw")
+TARGET_BUILTIN(__builtin_ia32_vpermt2varhi128_maskz, "V8sV8sV8sV8sUc", "", "avx512vl,avx512bw")
+TARGET_BUILTIN(__builtin_ia32_vpermt2varhi256_mask, "V16sV16sV16sV16sUs", "", "avx512vl,avx512bw")
+TARGET_BUILTIN(__builtin_ia32_vpermt2varhi256_maskz, "V16sV16sV16sV16sUs", "", "avx512vl,avx512bw")
+
+TARGET_BUILTIN(__builtin_ia32_pmulhrsw512_mask, "V32sV32sV32sV32sUi", "", "avx512bw")
+TARGET_BUILTIN(__builtin_ia32_pmulhuw512_mask, "V32sV32sV32sV32sUi", "", "avx512bw")
+TARGET_BUILTIN(__builtin_ia32_pmulhw512_mask, "V32sV32sV32sV32sUi", "", "avx512bw")
+
+TARGET_BUILTIN(__builtin_ia32_addpd512_mask, "V8dV8dV8dV8dUcIi", "", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_addps512_mask, "V16fV16fV16fV16fUsIi", "", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_divpd512_mask, "V8dV8dV8dV8dUcIi", "", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_divps512_mask, "V16fV16fV16fV16fUsIi", "", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_mulpd512_mask, "V8dV8dV8dV8dUcIi", "", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_mulps512_mask, "V16fV16fV16fV16fUsIi", "", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_subpd512_mask, "V8dV8dV8dV8dUcIi", "", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_subps512_mask, "V16fV16fV16fV16fUsIi", "", "avx512f")
+
+TARGET_BUILTIN(__builtin_ia32_pmaddubsw512_mask, "V32sV64cV64cV32sUi", "", "avx512bw")
+TARGET_BUILTIN(__builtin_ia32_pmaddwd512_mask, "V16iV32sV32sV16iUs", "", "avx512bw")
+
+TARGET_BUILTIN(__builtin_ia32_addss_round, "V4fV4fV4fV4fUcIi", "", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_divss_round, "V4fV4fV4fV4fUcIi", "", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_mulss_round, "V4fV4fV4fV4fUcIi", "", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_subss_round, "V4fV4fV4fV4fUcIi", "", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_maxss_round, "V4fV4fV4fV4fUcIi", "", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_minss_round, "V4fV4fV4fV4fUcIi", "", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_addsd_round, "V2dV2dV2dV2dUcIi", "", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_divsd_round, "V2dV2dV2dV2dUcIi", "", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_mulsd_round, "V2dV2dV2dV2dUcIi", "", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_subsd_round, "V2dV2dV2dV2dUcIi", "", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_maxsd_round, "V2dV2dV2dV2dUcIi", "", "avx512f")
+TARGET_BUILTIN(__builtin_ia32_minsd_round, "V2dV2dV2dV2dUcIi", "", "avx512f")
+
+TARGET_BUILTIN(__builtin_ia32_addpd128_mask, "V2dV2dV2dV2dUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_addpd256_mask, "V4dV4dV4dV4dUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_addps128_mask, "V4fV4fV4fV4fUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_addps256_mask, "V8fV8fV8fV8fUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_blendmd_128_mask, "V4iV4iV4iUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_blendmd_256_mask, "V8iV8iV8iUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_blendmpd_128_mask, "V2dV2dV2dUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_blendmpd_256_mask, "V4dV4dV4dUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_blendmps_128_mask, "V4fV4fV4fUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_blendmps_256_mask, "V8fV8fV8fUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_blendmq_128_mask, "V2LLiV2LLiV2LLiUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_blendmq_256_mask, "V4LLiV4LLiV4LLiUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_compressdf128_mask, "V2dV2dV2dUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_compressdf256_mask, "V4dV4dV4dUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_compressdi128_mask, "V2LLiV2LLiV2LLiUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_compressdi256_mask, "V4LLiV4LLiV4LLiUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_compresssf128_mask, "V4fV4fV4fUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_compresssf256_mask, "V8fV8fV8fUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_compresssi128_mask, "V4iV4iV4iUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_compresssi256_mask, "V8iV8iV8iUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_compressstoredf128_mask, "vV2d*V2dUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_compressstoredf256_mask, "vV4d*V4dUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_compressstoredi128_mask, "vV2LLi*V2LLiUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_compressstoredi256_mask, "vV4LLi*V4LLiUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_compressstoresf128_mask, "vV4f*V4fUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_compressstoresf256_mask, "vV8f*V8fUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_compressstoresi128_mask, "vV4i*V4iUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_compressstoresi256_mask, "vV8i*V8iUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_cvtdq2pd128_mask, "V2dV4iV2dUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_cvtdq2pd256_mask, "V4dV4iV4dUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_cvtdq2ps128_mask, "V4fV4iV4fUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_cvtdq2ps256_mask, "V8fV8iV8fUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_cvtpd2dq128_mask, "V4iV2dV4iUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_cvtpd2dq256_mask, "V4iV4dV4iUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_cvtpd2ps_mask, "V4fV2dV4fUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_cvtpd2ps256_mask, "V4fV4dV4fUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_cvtpd2udq128_mask, "V4iV2dV4iUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_cvtpd2udq256_mask, "V4iV4dV4iUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_cvtps2dq128_mask, "V4iV4fV4iUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_cvtps2dq256_mask, "V8iV8fV8iUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_cvtps2pd128_mask, "V2dV4fV2dUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_cvtps2pd256_mask, "V4dV4fV4dUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_cvtps2udq128_mask, "V4iV4fV4iUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_cvtps2udq256_mask, "V8iV8fV8iUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_cvttpd2dq128_mask, "V4iV2dV4iUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_cvttpd2dq256_mask, "V4iV4dV4iUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_cvttpd2udq128_mask, "V4iV2dV4iUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_cvttpd2udq256_mask, "V4iV4dV4iUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_cvttps2dq128_mask, "V4iV4fV4iUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_cvttps2dq256_mask, "V8iV8fV8iUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_cvttps2udq128_mask, "V4iV4fV4iUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_cvttps2udq256_mask, "V8iV8fV8iUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_cvtudq2pd128_mask, "V2dV4iV2dUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_cvtudq2pd256_mask, "V4dV4iV4dUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_cvtudq2ps128_mask, "V4fV4iV4fUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_cvtudq2ps256_mask, "V8fV8iV8fUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_divpd_mask, "V2dV2dV2dV2dUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_divpd256_mask, "V4dV4dV4dV4dUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_divps_mask, "V4fV4fV4fV4fUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_divps256_mask, "V8fV8fV8fV8fUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_expanddf128_mask, "V2dV2dV2dUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_expanddf256_mask, "V4dV4dV4dUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_expanddi128_mask, "V2LLiV2LLiV2LLiUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_expanddi256_mask, "V4LLiV4LLiV4LLiUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_expandloaddf128_mask, "V2dV2d*V2dUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_expandloaddf256_mask, "V4dV4d*V4dUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_expandloaddi128_mask, "V4iV2LLi*V2LLiUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_expandloaddi256_mask, "V4LLiV4LLi*V4LLiUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_expandloadsf128_mask, "V4fV4f*V4fUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_expandloadsf256_mask, "V8fV8f*V8fUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_expandloadsi128_mask, "V4iV4i*V4iUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_expandloadsi256_mask, "V8iV8i*V8iUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_expandsf128_mask, "V4fV4fV4fUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_expandsf256_mask, "V8fV8fV8fUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_expandsi128_mask, "V4iV4iV4iUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_expandsi256_mask, "V8iV8iV8iUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_getexppd128_mask, "V2dV2dV2dUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_getexppd256_mask, "V4dV4dV4dUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_getexpps128_mask, "V4fV4fV4fUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_getexpps256_mask, "V8fV8fV8fUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_maxpd_mask, "V2dV2dV2dV2dUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_maxpd256_mask, "V4dV4dV4dV4dUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_maxps_mask, "V4fV4fV4fV4fUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_maxps256_mask, "V8fV8fV8fV8fUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_minpd_mask, "V2dV2dV2dV2dUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_minpd256_mask, "V4dV4dV4dV4dUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_minps_mask, "V4fV4fV4fV4fUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_minps256_mask, "V8fV8fV8fV8fUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_mulpd_mask, "V2dV2dV2dV2dUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_mulpd256_mask, "V4dV4dV4dV4dUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_mulps_mask, "V4fV4fV4fV4fUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_mulps256_mask, "V8fV8fV8fV8fUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_pabsd128_mask, "V4iV4iV4iUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_pabsd256_mask, "V8iV8iV8iUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_pabsq128_mask, "V2LLiV2LLiV2LLiUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_pabsq256_mask, "V4LLiV4LLiV4LLiUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_pmaxsd128_mask, "V4iV4iV4iV4iUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_pmaxsd256_mask, "V8iV8iV8iV8iUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_pmaxsq128_mask, "V2LLiV2LLiV2LLiV2LLiUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_pmaxsq256_mask, "V4LLiV4LLiV4LLiV4LLiUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_pmaxud128_mask, "V4iV4iV4iV4iUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_pmaxud256_mask, "V8iV8iV8iV8iUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_pmaxuq128_mask, "V2LLiV2LLiV2LLiV2LLiUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_pmaxuq256_mask, "V4LLiV4LLiV4LLiV4LLiUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_pminsd128_mask, "V4iV4iV4iV4iUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_pminsd256_mask, "V8iV8iV8iV8iUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_pminsq128_mask, "V2LLiV2LLiV2LLiV2LLiUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_pminsq256_mask, "V4LLiV4LLiV4LLiV4LLiUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_pminud128_mask, "V4iV4iV4iV4iUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_pminud256_mask, "V8iV8iV8iV8iUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_pminuq128_mask, "V2LLiV2LLiV2LLiV2LLiUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_pminuq256_mask, "V4LLiV4LLiV4LLiV4LLiUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_rndscalepd_128_mask, "V2dV2dIiV2dUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_rndscalepd_256_mask, "V4dV4dIiV4dUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_rndscaleps_128_mask, "V4fV4fIiV4fUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_rndscaleps_256_mask, "V8fV8fIiV8fUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_scalefpd128_mask, "V2dV2dV2dV2dUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_scalefpd256_mask, "V4dV4dV4dV4dUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_scalefps128_mask, "V4fV4fV4fV4fUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_scalefps256_mask, "V8fV8fV8fV8fUc", "", "avx512vl")
+
+TARGET_BUILTIN(__builtin_ia32_scatterdiv2df, "vv*UcV2LLiV2dIi", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_scatterdiv2di, "vv*UcV2LLiV2LLiIi", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_scatterdiv4df, "vv*UcV4LLiV4dIi", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_scatterdiv4di, "vv*UcV4LLiV4LLiIi", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_scatterdiv4sf, "vv*UcV2LLiV4fIi", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_scatterdiv4si, "vv*UcV2LLiV4iIi", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_scatterdiv8sf, "vv*UcV4LLiV4fIi", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_scatterdiv8si, "vv*UcV4LLiV4iIi", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_scattersiv2df, "vv*UcV4iV2dIi", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_scattersiv2di, "vv*UcV4iV2LLiIi", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_scattersiv4df, "vv*UcV4iV4dIi", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_scattersiv4di, "vv*UcV4iV4LLiIi", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_scattersiv4sf, "vv*UcV4iV4fIi", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_scattersiv4si, "vv*UcV4iV4iIi", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_scattersiv8sf, "vv*UcV8iV8fIi", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_scattersiv8si, "vv*UcV8iV8iIi", "", "avx512vl")
+
+TARGET_BUILTIN(__builtin_ia32_sqrtpd128_mask, "V2dV2dV2dUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_sqrtpd256_mask, "V4dV4dV4dUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_sqrtps128_mask, "V4fV4fV4fUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_sqrtps256_mask, "V8fV8fV8fUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_subpd128_mask, "V2dV2dV2dV2dUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_subpd256_mask, "V4dV4dV4dV4dUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_subps128_mask, "V4fV4fV4fV4fUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_subps256_mask, "V8fV8fV8fV8fUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_vpermi2vard128_mask, "V4iV4iV4iV4iUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_vpermi2vard256_mask, "V8iV8iV8iV8iUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_vpermi2varpd128_mask, "V2dV2dV2LLiV2dUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_vpermi2varpd256_mask, "V4dV4dV4LLiV4dUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_vpermi2varps128_mask, "V4fV4fV4iV4fUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_vpermi2varps256_mask, "V8fV8fV8iV8fUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_vpermi2varq128_mask, "V2LLiV2LLiV2LLiV2LLiUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_vpermi2varq256_mask, "V4LLiV4LLiV4LLiV4LLiUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_vpermt2vard128_mask, "V4iV4iV4iV4iUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_vpermt2vard128_maskz, "V4iV4iV4iV4iUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_vpermt2vard256_mask, "V8iV8iV8iV8iUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_vpermt2vard256_maskz, "V8iV8iV8iV8iUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_vpermt2varpd128_mask, "V2dV2LLiV2dV2dUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_vpermt2varpd128_maskz, "V2dV2LLiV2dV2dUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_vpermt2varpd256_mask, "V4dV4LLiV4dV4dUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_vpermt2varpd256_maskz, "V4dV4LLiV4dV4dUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_vpermt2varps128_mask, "V4fV4iV4fV4fUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_vpermt2varps128_maskz, "V4fV4iV4fV4fUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_vpermt2varps256_mask, "V8fV8iV8fV8fUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_vpermt2varps256_maskz, "V8fV8iV8fV8fUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_vpermt2varq128_mask, "V2LLiV2LLiV2LLiV2LLiUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_vpermt2varq128_maskz, "V2LLiV2LLiV2LLiV2LLiUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_vpermt2varq256_mask, "V4LLiV4LLiV4LLiV4LLiUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_vpermt2varq256_maskz, "V4LLiV4LLiV4LLiV4LLiUc", "", "avx512vl")
+TARGET_BUILTIN(__builtin_ia32_pmovswb512_mask, "V32cV32sV32cUi", "", "avx512bw")
+TARGET_BUILTIN(__builtin_ia32_pmovuswb512_mask, "V32cV32sV32cUi", "", "avx512bw")
+TARGET_BUILTIN(__builtin_ia32_pmovwb512_mask, "V32cV32sV32cUi", "", "avx512bw")
+TARGET_BUILTIN(__builtin_ia32_punpckhbw512_mask, "V64cV64cV64cV64cULLi", "", "avx512bw")
+TARGET_BUILTIN(__builtin_ia32_punpckhwd512_mask, "V32sV32sV32sV32sUi", "", "avx512bw")
+TARGET_BUILTIN(__builtin_ia32_punpcklbw512_mask, "V64cV64cV64cV64cULLi", "", "avx512bw")
+TARGET_BUILTIN(__builtin_ia32_punpcklwd512_mask, "V32sV32sV32sV32sUi", "", "avx512bw")
+TARGET_BUILTIN(__builtin_ia32_cvtpd2qq128_mask, "V2LLiV2dV2LLiUc", "", "avx512vl,avx512dq")
+TARGET_BUILTIN(__builtin_ia32_cvtpd2qq256_mask, "V4LLiV4dV4LLiUc", "", "avx512vl,avx512dq")
+TARGET_BUILTIN(__builtin_ia32_cvtpd2uqq128_mask, "V2LLiV2dV2LLiUc", "", "avx512vl,avx512dq")
+TARGET_BUILTIN(__builtin_ia32_cvtpd2uqq256_mask, "V4LLiV4dV4LLiUc", "", "avx512vl,avx512dq")
+TARGET_BUILTIN(__builtin_ia32_cvtps2qq128_mask, "V2LLiV4fV2LLiUc", "", "avx512vl,avx512dq")
+TARGET_BUILTIN(__builtin_ia32_cvtps2qq256_mask, "V4LLiV4fV4LLiUc", "", "avx512vl,avx512dq")
+TARGET_BUILTIN(__builtin_ia32_cvtps2uqq128_mask, "V2LLiV4fV2LLiUc", "", "avx512vl,avx512dq")
+TARGET_BUILTIN(__builtin_ia32_cvtps2uqq256_mask, "V4LLiV4fV4LLiUc", "", "avx512vl,avx512dq")
+TARGET_BUILTIN(__builtin_ia32_cvtqq2pd128_mask, "V2dV2LLiV2dUc", "", "avx512vl,avx512dq")
+TARGET_BUILTIN(__builtin_ia32_cvtqq2pd256_mask, "V4dV4LLiV4dUc", "", "avx512vl,avx512dq")
+TARGET_BUILTIN(__builtin_ia32_cvtqq2ps128_mask, "V4fV2LLiV4fUc", "", "avx512vl,avx512dq")
+TARGET_BUILTIN(__builtin_ia32_cvtqq2ps256_mask, "V4fV4LLiV4fUc", "", "avx512vl,avx512dq")
+TARGET_BUILTIN(__builtin_ia32_cvttpd2qq128_mask, "V2LLiV2dV2LLiUc", "", "avx512vl,avx512dq")
+TARGET_BUILTIN(__builtin_ia32_cvttpd2qq256_mask, "V4LLiV4dV4LLiUc", "", "avx512vl,avx512dq")
+TARGET_BUILTIN(__builtin_ia32_cvttpd2uqq128_mask, "V2LLiV2dV2LLiUc", "", "avx512vl,avx512dq")
+TARGET_BUILTIN(__builtin_ia32_cvttpd2uqq256_mask, "V4LLiV4dV4LLiUc", "", "avx512vl,avx512dq")
+TARGET_BUILTIN(__builtin_ia32_cvttps2qq128_mask, "V2LLiV4fV2LLiUc", "", "avx512vl,avx512dq")
+TARGET_BUILTIN(__builtin_ia32_cvttps2qq256_mask, "V4LLiV4fV4LLiUc", "", "avx512vl,avx512dq")
+TARGET_BUILTIN(__builtin_ia32_cvttps2uqq128_mask, "V2LLiV4fV2LLiUc", "", "avx512vl,avx512dq")
+TARGET_BUILTIN(__builtin_ia32_cvttps2uqq256_mask, "V4LLiV4fV4LLiUc", "", "avx512vl,avx512dq")
+TARGET_BUILTIN(__builtin_ia32_cvtuqq2pd128_mask, "V2dV2LLiV2dUc", "", "avx512vl,avx512dq")
+TARGET_BUILTIN(__builtin_ia32_cvtuqq2pd256_mask, "V4dV4LLiV4dUc", "", "avx512vl,avx512dq")
+TARGET_BUILTIN(__builtin_ia32_cvtuqq2ps128_mask, "V4fV2LLiV4fUc", "", "avx512vl,avx512dq")
+TARGET_BUILTIN(__builtin_ia32_cvtuqq2ps256_mask, "V4fV4LLiV4fUc", "", "avx512vl,avx512dq")
+TARGET_BUILTIN(__builtin_ia32_rangepd128_mask, "V2dV2dV2dIiV2dUc", "", "avx512vl,avx512dq")
+TARGET_BUILTIN(__builtin_ia32_rangepd256_mask, "V4dV4dV4dIiV4dUc", "", "avx512vl,avx512dq")
+TARGET_BUILTIN(__builtin_ia32_rangeps128_mask, "V4fV4fV4fIiV4fUc", "", "avx512vl,avx512dq")
+TARGET_BUILTIN(__builtin_ia32_rangeps256_mask, "V8fV8fV8fIiV8fUc", "", "avx512vl,avx512dq")
+TARGET_BUILTIN(__builtin_ia32_reducepd128_mask, "V2dV2dIiV2dUc", "", "avx512vl,avx512dq")
+TARGET_BUILTIN(__builtin_ia32_reducepd256_mask, "V4dV4dIiV4dUc", "", "avx512vl,avx512dq")
+TARGET_BUILTIN(__builtin_ia32_reduceps128_mask, "V4fV4fIiV4fUc", "", "avx512vl,avx512dq")
+TARGET_BUILTIN(__builtin_ia32_reduceps256_mask, "V8fV8fIiV8fUc", "", "avx512vl,avx512dq")
+TARGET_BUILTIN(__builtin_ia32_pmaddubsw128_mask, "V8sV16cV16cV8sUc", "", "avx512vl,avx512bw")
+TARGET_BUILTIN(__builtin_ia32_pmaddubsw256_mask, "V16sV32cV32cV16sUs", "", "avx512vl,avx512bw")
+TARGET_BUILTIN(__builtin_ia32_pmaddwd128_mask, "V4iV8sV8sV4iUc", "", "avx512vl,avx512bw")
+TARGET_BUILTIN(__builtin_ia32_pmaddwd256_mask, "V8iV16sV16sV8iUc", "", "avx512vl,avx512bw")
+TARGET_BUILTIN(__builtin_ia32_pmovswb128_mask, "V16cV8sV16cUc", "", "avx512vl,avx512bw")
+TARGET_BUILTIN(__builtin_ia32_pmovswb256_mask, "V16cV16sV16cUs", "", "avx512vl,avx512bw")
+TARGET_BUILTIN(__builtin_ia32_pmovuswb128_mask, "V16cV8sV16cUc", "", "avx512vl,avx512bw")
+TARGET_BUILTIN(__builtin_ia32_pmovuswb256_mask, "V16cV16sV16cUs", "", "avx512vl,avx512bw")
+TARGET_BUILTIN(__builtin_ia32_pmovwb128_mask, "V16cV8sV16cUc", "", "avx512vl,avx512bw")
+TARGET_BUILTIN(__builtin_ia32_pmovwb256_mask, "V16cV16sV16cUs", "", "avx512vl,avx512bw")
+TARGET_BUILTIN(__builtin_ia32_pmulhrsw128_mask, "V8sV8sV8sV8sUc", "", "avx512vl,avx512bw")
+TARGET_BUILTIN(__builtin_ia32_pmulhrsw256_mask, "V16sV16sV16sV16sUs", "", "avx512vl,avx512bw")
+TARGET_BUILTIN(__builtin_ia32_pmulhuw128_mask, "V8sV8sV8sV8sUc", "", "avx512vl,avx512bw")
+TARGET_BUILTIN(__builtin_ia32_pmulhuw256_mask, "V16sV16sV16sV16sUs", "", "avx512vl,avx512bw")
+TARGET_BUILTIN(__builtin_ia32_pmulhw128_mask, "V8sV8sV8sV8sUc", "", "avx512vl,avx512bw")
+TARGET_BUILTIN(__builtin_ia32_pmulhw256_mask, "V16sV16sV16sV16sUs", "", "avx512vl,avx512bw")
+TARGET_BUILTIN(__builtin_ia32_punpckhbw128_mask, "V16cV16cV16cV16cUs", "", "avx512vl,avx512bw")
+TARGET_BUILTIN(__builtin_ia32_punpckhbw256_mask, "V32cV32cV32cV32cUi", "", "avx512vl,avx512bw")
+TARGET_BUILTIN(__builtin_ia32_punpckhwd128_mask, "V8sV8sV8sV8sUc", "", "avx512vl,avx512bw")
+TARGET_BUILTIN(__builtin_ia32_punpckhwd256_mask, "V16sV16sV16sV16sUs", "", "avx512vl,avx512bw")
+TARGET_BUILTIN(__builtin_ia32_punpcklbw128_mask, "V16cV16cV16cV16cUs", "", "avx512vl,avx512bw")
+TARGET_BUILTIN(__builtin_ia32_punpcklbw256_mask, "V32cV32cV32cV32cUi", "", "avx512vl,avx512bw")
+TARGET_BUILTIN(__builtin_ia32_punpcklwd128_mask, "V8sV8sV8sV8sUc", "", "avx512vl,avx512bw")
+TARGET_BUILTIN(__builtin_ia32_punpcklwd256_mask, "V16sV16sV16sV16sUs", "", "avx512vl,avx512bw")
+TARGET_BUILTIN(__builtin_ia32_cvtpd2qq512_mask, "V8LLiV8dV8LLiUcIi", "", "avx512dq")
+TARGET_BUILTIN(__builtin_ia32_cvtpd2uqq512_mask, "V8LLiV8dV8LLiUcIi", "", "avx512dq")
+TARGET_BUILTIN(__builtin_ia32_cvtps2qq512_mask, "V8LLiV8fV8LLiUcIi", "", "avx512dq")
+TARGET_BUILTIN(__builtin_ia32_cvtps2uqq512_mask, "V8LLiV8fV8LLiUcIi", "", "avx512dq")
+TARGET_BUILTIN(__builtin_ia32_cvtqq2pd512_mask, "V8dV8LLiV8dUcIi", "", "avx512dq")
+TARGET_BUILTIN(__builtin_ia32_cvtqq2ps512_mask, "V8fV8LLiV8fUcIi", "", "avx512dq")
+TARGET_BUILTIN(__builtin_ia32_cvttpd2qq512_mask, "V8LLiV8dV8LLiUcIi", "", "avx512dq")
+TARGET_BUILTIN(__builtin_ia32_cvttpd2uqq512_mask, "V8LLiV8dV8LLiUcIi", "", "avx512dq")
+TARGET_BUILTIN(__builtin_ia32_cvttps2qq512_mask, "V8LLiV8fV8LLiUcIi", "", "avx512dq")
+TARGET_BUILTIN(__builtin_ia32_cvttps2uqq512_mask, "V8LLiV8fV8LLiUcIi", "", "avx512dq")
+TARGET_BUILTIN(__builtin_ia32_cvtuqq2pd512_mask, "V8dV8LLiV8dUcIi", "", "avx512dq")
+TARGET_BUILTIN(__builtin_ia32_cvtuqq2ps512_mask, "V8fV8LLiV8fUcIi", "", "avx512dq")
+TARGET_BUILTIN(__builtin_ia32_rangepd512_mask, "V8dV8dV8dIiV8dUcIi", "", "avx512dq")
+TARGET_BUILTIN(__builtin_ia32_rangeps512_mask, "V16fV16fV16fIiV16fUsIi", "", "avx512dq")
+TARGET_BUILTIN(__builtin_ia32_reducepd512_mask, "V8dV8dIiV8dUcIi", "", "avx512dq")
+TARGET_BUILTIN(__builtin_ia32_reduceps512_mask, "V16fV16fIiV16fUsIi", "", "avx512dq")
+
+#undef BUILTIN
+#undef TARGET_BUILTIN
diff --git a/contrib/llvm/tools/clang/include/clang/Basic/BuiltinsXCore.def b/contrib/llvm/tools/clang/include/clang/Basic/BuiltinsXCore.def
new file mode 100644
index 0000000..672d205
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Basic/BuiltinsXCore.def
@@ -0,0 +1,22 @@
+//===--- BuiltinsXCore.def - XCore 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 XCore-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.
+
+BUILTIN(__builtin_bitrev, "UiUi", "nc")
+BUILTIN(__builtin_getid, "Si", "nc")
+BUILTIN(__builtin_getps, "UiUi", "n")
+BUILTIN(__builtin_setps, "vUiUi", "n")
+
+#undef BUILTIN
diff --git a/contrib/llvm/tools/clang/include/clang/Basic/CapturedStmt.h b/contrib/llvm/tools/clang/include/clang/Basic/CapturedStmt.h
new file mode 100644
index 0000000..c4a289b
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Basic/CapturedStmt.h
@@ -0,0 +1,24 @@
+//===--- CapturedStmt.h - Types for CapturedStmts ---------------*- 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_BASIC_CAPTUREDSTMT_H
+#define LLVM_CLANG_BASIC_CAPTUREDSTMT_H
+
+namespace clang {
+
+/// \brief The different kinds of captured statement.
+enum CapturedRegionKind {
+ CR_Default,
+ CR_OpenMP
+};
+
+} // end namespace clang
+
+#endif // LLVM_CLANG_BASIC_CAPTUREDSTMT_H
diff --git a/contrib/llvm/tools/clang/include/clang/Basic/CharInfo.h b/contrib/llvm/tools/clang/include/clang/Basic/CharInfo.h
new file mode 100644
index 0000000..dd9c554
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Basic/CharInfo.h
@@ -0,0 +1,198 @@
+//===--- clang/Basic/CharInfo.h - Classifying ASCII Characters ------------===//
+//
+// 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_CHARINFO_H
+#define LLVM_CLANG_BASIC_CHARINFO_H
+
+#include "clang/Basic/LLVM.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/Support/Compiler.h"
+#include "llvm/Support/DataTypes.h"
+
+namespace clang {
+namespace charinfo {
+ extern const uint16_t InfoTable[256];
+
+ enum {
+ CHAR_HORZ_WS = 0x0001, // '\t', '\f', '\v'. Note, no '\0'
+ CHAR_VERT_WS = 0x0002, // '\r', '\n'
+ CHAR_SPACE = 0x0004, // ' '
+ CHAR_DIGIT = 0x0008, // 0-9
+ CHAR_XLETTER = 0x0010, // a-f,A-F
+ CHAR_UPPER = 0x0020, // A-Z
+ CHAR_LOWER = 0x0040, // a-z
+ CHAR_UNDER = 0x0080, // _
+ CHAR_PERIOD = 0x0100, // .
+ CHAR_RAWDEL = 0x0200, // {}[]#<>%:;?*+-/^&|~!=,"'
+ CHAR_PUNCT = 0x0400 // `$@()
+ };
+
+ enum {
+ CHAR_XUPPER = CHAR_XLETTER | CHAR_UPPER,
+ CHAR_XLOWER = CHAR_XLETTER | CHAR_LOWER
+ };
+} // end namespace charinfo
+
+/// Returns true if this is an ASCII character.
+LLVM_READNONE static inline bool isASCII(char c) {
+ return static_cast<unsigned char>(c) <= 127;
+}
+
+/// Returns true if this is a valid first character of a C identifier,
+/// which is [a-zA-Z_].
+LLVM_READONLY static inline bool isIdentifierHead(unsigned char c,
+ bool AllowDollar = false) {
+ using namespace charinfo;
+ if (InfoTable[c] & (CHAR_UPPER|CHAR_LOWER|CHAR_UNDER))
+ return true;
+ return AllowDollar && c == '$';
+}
+
+/// Returns true if this is a body character of a C identifier,
+/// which is [a-zA-Z0-9_].
+LLVM_READONLY static inline bool isIdentifierBody(unsigned char c,
+ bool AllowDollar = false) {
+ using namespace charinfo;
+ if (InfoTable[c] & (CHAR_UPPER|CHAR_LOWER|CHAR_DIGIT|CHAR_UNDER))
+ return true;
+ return AllowDollar && c == '$';
+}
+
+/// Returns true if this character is horizontal ASCII whitespace:
+/// ' ', '\\t', '\\f', '\\v'.
+///
+/// Note that this returns false for '\\0'.
+LLVM_READONLY static inline bool isHorizontalWhitespace(unsigned char c) {
+ using namespace charinfo;
+ return (InfoTable[c] & (CHAR_HORZ_WS|CHAR_SPACE)) != 0;
+}
+
+/// Returns true if this character is vertical ASCII whitespace: '\\n', '\\r'.
+///
+/// Note that this returns false for '\\0'.
+LLVM_READONLY static inline bool isVerticalWhitespace(unsigned char c) {
+ using namespace charinfo;
+ return (InfoTable[c] & CHAR_VERT_WS) != 0;
+}
+
+/// Return true if this character is horizontal or vertical ASCII whitespace:
+/// ' ', '\\t', '\\f', '\\v', '\\n', '\\r'.
+///
+/// Note that this returns false for '\\0'.
+LLVM_READONLY static inline bool isWhitespace(unsigned char c) {
+ using namespace charinfo;
+ return (InfoTable[c] & (CHAR_HORZ_WS|CHAR_VERT_WS|CHAR_SPACE)) != 0;
+}
+
+/// Return true if this character is an ASCII digit: [0-9]
+LLVM_READONLY static inline bool isDigit(unsigned char c) {
+ using namespace charinfo;
+ return (InfoTable[c] & CHAR_DIGIT) != 0;
+}
+
+/// Return true if this character is a lowercase ASCII letter: [a-z]
+LLVM_READONLY static inline bool isLowercase(unsigned char c) {
+ using namespace charinfo;
+ return (InfoTable[c] & CHAR_LOWER) != 0;
+}
+
+/// Return true if this character is an uppercase ASCII letter: [A-Z]
+LLVM_READONLY static inline bool isUppercase(unsigned char c) {
+ using namespace charinfo;
+ return (InfoTable[c] & CHAR_UPPER) != 0;
+}
+
+/// Return true if this character is an ASCII letter: [a-zA-Z]
+LLVM_READONLY static inline bool isLetter(unsigned char c) {
+ using namespace charinfo;
+ return (InfoTable[c] & (CHAR_UPPER|CHAR_LOWER)) != 0;
+}
+
+/// Return true if this character is an ASCII letter or digit: [a-zA-Z0-9]
+LLVM_READONLY static inline bool isAlphanumeric(unsigned char c) {
+ using namespace charinfo;
+ return (InfoTable[c] & (CHAR_DIGIT|CHAR_UPPER|CHAR_LOWER)) != 0;
+}
+
+/// Return true if this character is an ASCII hex digit: [0-9a-fA-F]
+LLVM_READONLY static inline bool isHexDigit(unsigned char c) {
+ using namespace charinfo;
+ return (InfoTable[c] & (CHAR_DIGIT|CHAR_XLETTER)) != 0;
+}
+
+/// Return true if this character is an ASCII punctuation character.
+///
+/// Note that '_' is both a punctuation character and an identifier character!
+LLVM_READONLY static inline bool isPunctuation(unsigned char c) {
+ using namespace charinfo;
+ return (InfoTable[c] & (CHAR_UNDER|CHAR_PERIOD|CHAR_RAWDEL|CHAR_PUNCT)) != 0;
+}
+
+/// Return true if this character is an ASCII printable character; that is, a
+/// character that should take exactly one column to print in a fixed-width
+/// terminal.
+LLVM_READONLY static inline bool isPrintable(unsigned char c) {
+ using namespace charinfo;
+ return (InfoTable[c] & (CHAR_UPPER|CHAR_LOWER|CHAR_PERIOD|CHAR_PUNCT|
+ CHAR_DIGIT|CHAR_UNDER|CHAR_RAWDEL|CHAR_SPACE)) != 0;
+}
+
+/// Return true if this is the body character of a C preprocessing number,
+/// which is [a-zA-Z0-9_.].
+LLVM_READONLY static inline bool isPreprocessingNumberBody(unsigned char c) {
+ using namespace charinfo;
+ return (InfoTable[c] &
+ (CHAR_UPPER|CHAR_LOWER|CHAR_DIGIT|CHAR_UNDER|CHAR_PERIOD)) != 0;
+}
+
+/// Return true if this is the body character of a C++ raw string delimiter.
+LLVM_READONLY static inline bool isRawStringDelimBody(unsigned char c) {
+ using namespace charinfo;
+ return (InfoTable[c] & (CHAR_UPPER|CHAR_LOWER|CHAR_PERIOD|
+ CHAR_DIGIT|CHAR_UNDER|CHAR_RAWDEL)) != 0;
+}
+
+
+/// Converts the given ASCII character to its lowercase equivalent.
+///
+/// If the character is not an uppercase character, it is returned as is.
+LLVM_READONLY static inline char toLowercase(char c) {
+ if (isUppercase(c))
+ return c + 'a' - 'A';
+ return c;
+}
+
+/// Converts the given ASCII character to its uppercase equivalent.
+///
+/// If the character is not a lowercase character, it is returned as is.
+LLVM_READONLY static inline char toUppercase(char c) {
+ if (isLowercase(c))
+ return c + 'A' - 'a';
+ return c;
+}
+
+
+/// Return true if this is a valid ASCII identifier.
+///
+/// Note that this is a very simple check; it does not accept '$' or UCNs as
+/// valid identifier characters.
+LLVM_READONLY static inline bool isValidIdentifier(StringRef S) {
+ if (S.empty() || !isIdentifierHead(S[0]))
+ return false;
+
+ for (StringRef::iterator I = S.begin(), E = S.end(); I != E; ++I)
+ if (!isIdentifierBody(*I))
+ return false;
+
+ return true;
+}
+
+} // end namespace clang
+
+#endif
diff --git a/contrib/llvm/tools/clang/include/clang/Basic/CommentNodes.td b/contrib/llvm/tools/clang/include/clang/Basic/CommentNodes.td
new file mode 100644
index 0000000..7bf32b7
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Basic/CommentNodes.td
@@ -0,0 +1,27 @@
+class Comment<bit abstract = 0> {
+ bit Abstract = abstract;
+}
+
+class DComment<Comment base, bit abstract = 0> : Comment<abstract> {
+ Comment Base = base;
+}
+
+def InlineContentComment : Comment<1>;
+ def TextComment : DComment<InlineContentComment>;
+ def InlineCommandComment : DComment<InlineContentComment>;
+ def HTMLTagComment : DComment<InlineContentComment, 1>;
+ def HTMLStartTagComment : DComment<HTMLTagComment>;
+ def HTMLEndTagComment : DComment<HTMLTagComment>;
+
+def BlockContentComment : Comment<1>;
+ def ParagraphComment : DComment<BlockContentComment>;
+ def BlockCommandComment : DComment<BlockContentComment>;
+ def ParamCommandComment : DComment<BlockCommandComment>;
+ def TParamCommandComment : DComment<BlockCommandComment>;
+ def VerbatimBlockComment : DComment<BlockCommandComment>;
+ def VerbatimLineComment : DComment<BlockCommandComment>;
+
+def VerbatimBlockLineComment : Comment;
+
+def FullComment : Comment;
+
diff --git a/contrib/llvm/tools/clang/include/clang/Basic/CommentOptions.h b/contrib/llvm/tools/clang/include/clang/Basic/CommentOptions.h
new file mode 100644
index 0000000..92419f9
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Basic/CommentOptions.h
@@ -0,0 +1,39 @@
+//===--- CommentOptions.h - Options for parsing comments -----*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+///
+/// \file
+/// \brief Defines the clang::CommentOptions interface.
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_BASIC_COMMENTOPTIONS_H
+#define LLVM_CLANG_BASIC_COMMENTOPTIONS_H
+
+#include <string>
+#include <vector>
+
+namespace clang {
+
+/// \brief Options for controlling comment parsing.
+struct CommentOptions {
+ typedef std::vector<std::string> BlockCommandNamesTy;
+
+ /// \brief Command names to treat as block commands in comments.
+ /// Should not include the leading backslash.
+ BlockCommandNamesTy BlockCommandNames;
+
+ /// \brief Treat ordinary comments as documentation comments.
+ bool ParseAllComments;
+
+ CommentOptions() : ParseAllComments(false) { }
+};
+
+} // end namespace clang
+
+#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..723ea54
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Basic/DeclNodes.td
@@ -0,0 +1,88 @@
+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 ExternCContext : 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 TypedefName : DDecl<Type, 1>;
+ def Typedef : DDecl<TypedefName>;
+ def TypeAlias : DDecl<TypedefName>;
+ def ObjCTypeParam : DDecl<TypedefName>;
+ 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 Field : DDecl<Declarator>;
+ def ObjCIvar : DDecl<Field>;
+ def ObjCAtDefsField : DDecl<Field>;
+ def MSProperty : DDecl<Declarator>;
+ def Function : DDecl<Declarator>, DeclContext;
+ def CXXMethod : DDecl<Function>;
+ def CXXConstructor : DDecl<CXXMethod>;
+ def CXXDestructor : DDecl<CXXMethod>;
+ def CXXConversion : DDecl<CXXMethod>;
+ def Var : DDecl<Declarator>;
+ def VarTemplateSpecialization : DDecl<Var>;
+ def VarTemplatePartialSpecialization
+ : DDecl<VarTemplateSpecialization>;
+ 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 VarTemplate : DDecl<RedeclarableTemplate>;
+ def TypeAliasTemplate : DDecl<RedeclarableTemplate>;
+ def TemplateTemplateParm : DDecl<Template>;
+ def BuiltinTemplate : 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 FileScopeAsm : Decl;
+def AccessSpec : Decl;
+def Friend : Decl;
+def FriendTemplate : Decl;
+def StaticAssert : Decl;
+def Block : Decl, DeclContext;
+def Captured : Decl, DeclContext;
+def ClassScopeFunctionSpecialization : Decl;
+def Import : Decl;
+def OMPThreadPrivate : Decl;
+def Empty : Decl;
+
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..1d6c19b
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Basic/Diagnostic.h
@@ -0,0 +1,1414 @@
+//===--- 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.
+//
+//===----------------------------------------------------------------------===//
+///
+/// \file
+/// \brief Defines the Diagnostic-related interfaces.
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_BASIC_DIAGNOSTIC_H
+#define LLVM_CLANG_BASIC_DIAGNOSTIC_H
+
+#include "clang/Basic/DiagnosticIDs.h"
+#include "clang/Basic/DiagnosticOptions.h"
+#include "clang/Basic/SourceLocation.h"
+#include "clang/Basic/Specifiers.h"
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/IntrusiveRefCntPtr.h"
+#include "llvm/ADT/iterator_range.h"
+#include <list>
+#include <vector>
+
+namespace clang {
+ class DeclContext;
+ class DiagnosticBuilder;
+ class DiagnosticConsumer;
+ class DiagnosticErrorTrap;
+ class DiagnosticOptions;
+ class IdentifierInfo;
+ class LangOptions;
+ class Preprocessor;
+ class StoredDiagnostic;
+ namespace tok {
+ enum TokenKind : unsigned short;
+ }
+
+/// \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 Code in the specific range that should be inserted in the insertion
+ /// location.
+ CharSourceRange InsertFromRange;
+
+ /// \brief The actual code to insert at the insertion location, as a
+ /// string.
+ std::string CodeToInsert;
+
+ bool BeforePreviousInsertions;
+
+ /// \brief Empty code modification hint, indicating that no code
+ /// modification is known.
+ FixItHint() : BeforePreviousInsertions(false) { }
+
+ 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,
+ StringRef Code,
+ bool BeforePreviousInsertions = false) {
+ FixItHint Hint;
+ Hint.RemoveRange =
+ CharSourceRange::getCharRange(InsertionLoc, InsertionLoc);
+ Hint.CodeToInsert = Code;
+ Hint.BeforePreviousInsertions = BeforePreviousInsertions;
+ return Hint;
+ }
+
+ /// \brief Create a code modification hint that inserts the given
+ /// code from \p FromRange at a specific location.
+ static FixItHint CreateInsertionFromRange(SourceLocation InsertionLoc,
+ CharSourceRange FromRange,
+ bool BeforePreviousInsertions = false) {
+ FixItHint Hint;
+ Hint.RemoveRange =
+ CharSourceRange::getCharRange(InsertionLoc, InsertionLoc);
+ Hint.InsertFromRange = FromRange;
+ Hint.BeforePreviousInsertions = BeforePreviousInsertions;
+ 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,
+ StringRef Code) {
+ FixItHint Hint;
+ Hint.RemoveRange = RemoveRange;
+ Hint.CodeToInsert = Code;
+ return Hint;
+ }
+
+ static FixItHint CreateReplacement(SourceRange RemoveRange,
+ StringRef Code) {
+ return CreateReplacement(CharSourceRange::getTokenRange(RemoveRange), Code);
+ }
+};
+
+/// \brief Concrete class used by the front-end to report problems and issues.
+///
+/// This massages the diagnostics (e.g. handling things like "report warnings
+/// as errors" and passes them off to the DiagnosticConsumer for reporting to
+/// the user. DiagnosticsEngine is tied to one translation unit and one
+/// SourceManager.
+class DiagnosticsEngine : public RefCountedBase<DiagnosticsEngine> {
+ DiagnosticsEngine(const DiagnosticsEngine &) = delete;
+ void operator=(const DiagnosticsEngine &) = delete;
+
+public:
+ /// \brief The level of the diagnostic, after it has been through mapping.
+ enum Level {
+ Ignored = DiagnosticIDs::Ignored,
+ Note = DiagnosticIDs::Note,
+ Remark = DiagnosticIDs::Remark,
+ Warning = DiagnosticIDs::Warning,
+ Error = DiagnosticIDs::Error,
+ Fatal = DiagnosticIDs::Fatal
+ };
+
+ enum ArgumentKind {
+ ak_std_string, ///< std::string
+ ak_c_string, ///< const char *
+ ak_sint, ///< int
+ ak_uint, ///< unsigned
+ ak_tokenkind, ///< enum TokenKind : unsigned
+ ak_identifierinfo, ///< IdentifierInfo
+ ak_qualtype, ///< QualType
+ ak_declarationname, ///< DeclarationName
+ ak_nameddecl, ///< NamedDecl *
+ ak_nestednamespec, ///< NestedNameSpecifier *
+ ak_declcontext, ///< DeclContext *
+ ak_qualtype_pair, ///< pair<QualType, QualType>
+ ak_attr ///< Attr *
+ };
+
+ /// \brief 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 EnableAllWarnings; // Enable all warnings.
+ bool ErrorsAsFatal; // Treat errors like fatal errors.
+ bool SuppressSystemWarnings; // Suppress warnings in system headers.
+ bool SuppressAllDiagnostics; // Suppress all diagnostics.
+ bool ElideType; // Elide common types of templates.
+ bool PrintTemplateTree; // Print a tree when comparing templates.
+ bool ShowColors; // Color printing is enabled.
+ 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.
+ unsigned ConstexprBacktraceLimit; // Cap on depth of constexpr evaluation
+ // backtrace stack, 0 -> no limit.
+ diag::Severity ExtBehavior; // Map extensions to warnings or errors?
+ IntrusiveRefCntPtr<DiagnosticIDs> Diags;
+ IntrusiveRefCntPtr<DiagnosticOptions> DiagOpts;
+ DiagnosticConsumer *Client;
+ std::unique_ptr<DiagnosticConsumer> Owner;
+ 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::Severity), 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, DiagnosticMapping> DiagMap;
+
+ public:
+ typedef llvm::DenseMap<unsigned, DiagnosticMapping>::iterator iterator;
+ typedef llvm::DenseMap<unsigned, DiagnosticMapping>::const_iterator
+ const_iterator;
+
+ void setMapping(diag::kind Diag, DiagnosticMapping Info) {
+ DiagMap[Diag] = Info;
+ }
+
+ DiagnosticMapping &getOrAddMapping(diag::kind Diag);
+
+ const_iterator begin() const { return DiagMap.begin(); }
+ const_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 sorted 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, getSourceManager());
+ // Make sure that DiagStatePoints is always sorted according to Loc.
+ assert(Loc.isValid() && "Adding invalid loc point");
+ assert(!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, Loc));
+ }
+
+ /// \brief Finds the DiagStatePoint that contains the diagnostic state of
+ /// the given source location.
+ DiagStatePointsTy::iterator GetDiagStatePointForLoc(SourceLocation Loc) const;
+
+ /// \brief Sticky flag set to \c true when an error is emitted.
+ bool ErrorOccurred;
+
+ /// \brief Sticky flag set to \c true when an "uncompilable error" occurs.
+ /// I.e. an error that was not upgraded from a warning by -Werror.
+ bool UncompilableErrorOccurred;
+
+ /// \brief Sticky flag set to \c true when a fatal error is emitted.
+ bool FatalErrorOccurred;
+
+ /// \brief Indicates that an unrecoverable error has occurred.
+ bool UnrecoverableErrorOccurred;
+
+ /// \brief Counts for DiagnosticErrorTrap to check whether an error occurred
+ /// during a parsing section, e.g. during parsing a function.
+ unsigned TrapNumErrorsOccurred;
+ unsigned TrapNumUnrecoverableErrorsOccurred;
+
+ /// \brief 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
+
+ /// \brief 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 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,
+ StringRef Modifier, StringRef Argument,
+ ArrayRef<ArgumentValue> PrevArgs,
+ SmallVectorImpl<char> &Output,
+ void *Cookie,
+ ArrayRef<intptr_t> QualTypeVals);
+ 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;
+
+ /// \brief Optional flag value.
+ ///
+ /// Some flags accept values, for instance: -Wframe-larger-than=<value> and
+ /// -Rpass=<value>. The content of this string is emitted after the flag name
+ /// and '='.
+ std::string FlagValue;
+
+public:
+ explicit DiagnosticsEngine(
+ const IntrusiveRefCntPtr<DiagnosticIDs> &Diags,
+ DiagnosticOptions *DiagOpts,
+ DiagnosticConsumer *client = nullptr,
+ bool ShouldOwnClient = true);
+ ~DiagnosticsEngine();
+
+ const IntrusiveRefCntPtr<DiagnosticIDs> &getDiagnosticIDs() const {
+ return Diags;
+ }
+
+ /// \brief Retrieve the diagnostic options.
+ DiagnosticOptions &getDiagnosticOptions() const { return *DiagOpts; }
+
+ typedef llvm::iterator_range<DiagState::const_iterator> diag_mapping_range;
+
+ /// \brief Get the current set of diagnostic mappings.
+ diag_mapping_range getDiagnosticMappings() const {
+ const DiagState &DS = *GetCurDiagState();
+ return diag_mapping_range(DS.begin(), DS.end());
+ }
+
+ DiagnosticConsumer *getClient() { return Client; }
+ const DiagnosticConsumer *getClient() const { return Client; }
+
+ /// \brief Determine whether this \c DiagnosticsEngine object own its client.
+ bool ownsClient() const { return Owner != nullptr; }
+
+ /// \brief Return the current diagnostic client along with ownership of that
+ /// client.
+ std::unique_ptr<DiagnosticConsumer> takeClient() { return std::move(Owner); }
+
+ bool hasSourceManager() const { return SourceMgr != nullptr; }
+ SourceManager &getSourceManager() const {
+ assert(SourceMgr && "SourceManager not set!");
+ return *SourceMgr;
+ }
+ void setSourceManager(SourceManager *SrcMgr) { SourceMgr = SrcMgr; }
+
+ //===--------------------------------------------------------------------===//
+ // DiagnosticsEngine characterization methods, used by a client to customize
+ // how diagnostics are emitted.
+ //
+
+ /// \brief Copies the current DiagMappings and pushes the new copy
+ /// onto the top of the stack.
+ void pushMappings(SourceLocation Loc);
+
+ /// \brief Pops the current DiagMappings off the top of the stack,
+ /// causing the new top of the stack to be the active mappings.
+ ///
+ /// \returns \c true if the pop happens, \c 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(DiagnosticConsumer *client, bool ShouldOwnClient = true);
+
+ /// \brief 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
+ /// notes to emit along with a given diagnostic.
+ unsigned getTemplateBacktraceLimit() const {
+ return TemplateBacktraceLimit;
+ }
+
+ /// \brief Specify the maximum number of constexpr evaluation
+ /// notes to emit along with a given diagnostic.
+ void setConstexprBacktraceLimit(unsigned Limit) {
+ ConstexprBacktraceLimit = Limit;
+ }
+
+ /// \brief Retrieve the maximum number of constexpr evaluation
+ /// notes to emit along with a given diagnostic.
+ unsigned getConstexprBacktraceLimit() const {
+ return ConstexprBacktraceLimit;
+ }
+
+ /// \brief 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; }
+
+ /// \brief When set to true, any unmapped ignored warnings are no longer
+ /// ignored.
+ ///
+ /// If this and IgnoreAllWarnings are both set, then that one wins.
+ void setEnableAllWarnings(bool Val) { EnableAllWarnings = Val; }
+ bool getEnableAllWarnings() const { return EnableAllWarnings; }
+
+ /// \brief When set to true, any warnings reported are issued as errors.
+ void setWarningsAsErrors(bool Val) { WarningsAsErrors = Val; }
+ bool getWarningsAsErrors() const { return WarningsAsErrors; }
+
+ /// \brief When set to true, any error reported is made a fatal error.
+ void setErrorsAsFatal(bool Val) { ErrorsAsFatal = Val; }
+ bool getErrorsAsFatal() const { return ErrorsAsFatal; }
+
+ /// \brief 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 Set type eliding, to skip outputting same types occurring in
+ /// template types.
+ void setElideType(bool Val = true) { ElideType = Val; }
+ bool getElideType() { return ElideType; }
+
+ /// \brief Set tree printing, to outputting the template difference in a
+ /// tree format.
+ void setPrintTemplateTree(bool Val = false) { PrintTemplateTree = Val; }
+ bool getPrintTemplateTree() { return PrintTemplateTree; }
+
+ /// \brief Set color printing, so the type diffing will inject color markers
+ /// into the output.
+ void setShowColors(bool Val = false) { ShowColors = Val; }
+ bool getShowColors() { return ShowColors; }
+
+ /// \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, so any
+ /// subsequent notes will be suppressed.
+ ///
+ /// This can be used by clients who suppress diagnostics themselves.
+ void setLastDiagnosticIgnored() {
+ if (LastDiagLevel == DiagnosticIDs::Fatal)
+ FatalErrorOccurred = true;
+ LastDiagLevel = DiagnosticIDs::Ignored;
+ }
+
+ /// \brief Determine whether the previous diagnostic was ignored. This can
+ /// be used by clients that want to determine whether notes attached to a
+ /// diagnostic will be suppressed.
+ bool isLastDiagnosticIgnored() const {
+ return LastDiagLevel == DiagnosticIDs::Ignored;
+ }
+
+ /// \brief Controls whether otherwise-unmapped extension diagnostics are
+ /// mapped onto ignore/warning/error.
+ ///
+ /// This corresponds to the GCC -pedantic and -pedantic-errors option.
+ void setExtensionHandlingBehavior(diag::Severity H) { ExtBehavior = H; }
+ diag::Severity getExtensionHandlingBehavior() const { return ExtBehavior; }
+
+ /// \brief 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 setSeverity(diag::kind Diag, diag::Severity Map, SourceLocation Loc);
+
+ /// \brief Change an entire diagnostic group (e.g. "unknown-pragmas") to
+ /// have the specified mapping.
+ ///
+ /// \returns true (and ignores the request) if "Group" was unknown, false
+ /// otherwise.
+ ///
+ /// \param Flavor The flavor of group to affect. -Rfoo does not affect the
+ /// state of the -Wfoo group and vice versa.
+ ///
+ /// \param Loc 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 setSeverityForGroup(diag::Flavor Flavor, StringRef Group,
+ diag::Severity Map,
+ SourceLocation Loc = SourceLocation());
+
+ /// \brief Set the warning-as-error flag for the given diagnostic group.
+ ///
+ /// This function always only operates on the current diagnostic state.
+ ///
+ /// \returns True if the given group is unknown, false otherwise.
+ bool setDiagnosticGroupWarningAsError(StringRef Group, bool Enabled);
+
+ /// \brief Set the error-as-fatal flag for the given diagnostic group.
+ ///
+ /// This function always only operates on the current diagnostic state.
+ ///
+ /// \returns True if the given group is unknown, false otherwise.
+ bool setDiagnosticGroupErrorAsFatal(StringRef Group, bool Enabled);
+
+ /// \brief Add the specified mapping to all diagnostics of the specified
+ /// flavor.
+ ///
+ /// Mainly to be used by -Wno-everything to disable all warnings but allow
+ /// subsequent -W options to enable specific warnings.
+ void setSeverityForAll(diag::Flavor Flavor, diag::Severity Map,
+ SourceLocation Loc = SourceLocation());
+
+ bool hasErrorOccurred() const { return ErrorOccurred; }
+
+ /// \brief Errors that actually prevent compilation, not those that are
+ /// upgraded from a warning by -Werror.
+ bool hasUncompilableErrorOccurred() const {
+ return UncompilableErrorOccurred;
+ }
+ bool hasFatalErrorOccurred() const { return FatalErrorOccurred; }
+
+ /// \brief Determine whether any kind of unrecoverable error has occurred.
+ bool hasUnrecoverableErrorOccurred() const {
+ return FatalErrorOccurred || UnrecoverableErrorOccurred;
+ }
+
+ unsigned getNumWarnings() const { return NumWarnings; }
+
+ void setNumWarnings(unsigned NumWarnings) {
+ this->NumWarnings = NumWarnings;
+ }
+
+ /// \brief Return an ID for a diagnostic with the specified format string and
+ /// level.
+ ///
+ /// If this is the first request for this diagnostic, it is registered and
+ /// created, otherwise the existing ID is returned.
+ ///
+ /// \param FormatString A fixed diagnostic format string that will be hashed
+ /// and mapped to a unique DiagID.
+ template <unsigned N>
+ unsigned getCustomDiagID(Level L, const char (&FormatString)[N]) {
+ return Diags->getCustomDiagID((DiagnosticIDs::Level)L,
+ StringRef(FormatString, N - 1));
+ }
+
+ /// \brief Converts a diagnostic argument (as an intptr_t) into the string
+ /// that represents it.
+ void ConvertArgToString(ArgumentKind Kind, intptr_t Val,
+ StringRef Modifier, StringRef Argument,
+ ArrayRef<ArgumentValue> PrevArgs,
+ SmallVectorImpl<char> &Output,
+ ArrayRef<intptr_t> QualTypeVals) const {
+ ArgToStringFn(Kind, Val, Modifier, Argument, PrevArgs, Output,
+ ArgToStringCookie, QualTypeVals);
+ }
+
+ void SetArgToStringFn(ArgToStringFnTy Fn, void *Cookie) {
+ ArgToStringFn = Fn;
+ ArgToStringCookie = Cookie;
+ }
+
+ /// \brief Note that the prior diagnostic was emitted by some other
+ /// \c DiagnosticsEngine, and we may be attaching a note to that diagnostic.
+ void notePriorDiagnosticFrom(const DiagnosticsEngine &Other) {
+ LastDiagLevel = Other.LastDiagLevel;
+ }
+
+ /// \brief Reset the state of the diagnostic object to its initial
+ /// configuration.
+ void Reset();
+
+ //===--------------------------------------------------------------------===//
+ // DiagnosticsEngine classification and reporting interfaces.
+ //
+
+ /// \brief Determine whether the diagnostic is known to be ignored.
+ ///
+ /// This can be used to opportunistically avoid expensive checks when it's
+ /// known for certain that the diagnostic has been suppressed at the
+ /// specified location \p Loc.
+ ///
+ /// \param Loc The source location we are interested in finding out the
+ /// diagnostic state. Can be null in order to query the latest state.
+ bool isIgnored(unsigned DiagID, SourceLocation Loc) const {
+ return Diags->getDiagnosticSeverity(DiagID, Loc, *this) ==
+ diag::Severity::Ignored;
+ }
+
+ /// \brief Based on the way the client configured the DiagnosticsEngine
+ /// object, classify the specified diagnostic ID into a Level, consumable by
+ /// the DiagnosticConsumer.
+ ///
+ /// To preserve invariant assumptions, this function should not be used to
+ /// influence parse or semantic analysis actions. Instead consider using
+ /// \c isIgnored().
+ ///
+ /// \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);
+ }
+
+ /// \brief Issue the message to the client.
+ ///
+ /// This actually returns an instance of DiagnosticBuilder which emits the
+ /// diagnostics (through @c ProcessDiag) when it is destroyed.
+ ///
+ /// \param DiagID A member of the @c diag::kind enum.
+ /// \param Loc Represents the source location associated with the diagnostic,
+ /// which can be an invalid location if no position information is available.
+ inline DiagnosticBuilder Report(SourceLocation Loc, unsigned DiagID);
+ inline DiagnosticBuilder Report(unsigned DiagID);
+
+ void Report(const StoredDiagnostic &storedDiag);
+
+ /// \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
+ /// DiagnosticsEngine object itself.
+ ///
+ /// \param Arg2 A string argument that will be provided to the
+ /// diagnostic. A copy of this string will be stored in the
+ /// DiagnosticsEngine object itself.
+ void SetDelayedDiagnostic(unsigned DiagID, StringRef Arg1 = "",
+ StringRef Arg2 = "");
+
+ /// \brief Clear out the current diagnostic.
+ void Clear() { CurDiagID = ~0U; }
+
+ /// \brief Return the value associated with this diagnostic flag.
+ StringRef getFlagValue() const { return FlagValue; }
+
+private:
+ /// \brief Report the delayed diagnostic.
+ void ReportDelayed();
+
+ // 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 Diagnostic;
+ friend class PartialDiagnostic;
+ friend class DiagnosticErrorTrap;
+
+ /// \brief The location of the current diagnostic that is in flight.
+ SourceLocation CurDiagLoc;
+
+ /// \brief 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 {
+ /// \brief 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,
+ };
+
+ /// \brief The number of entries in Arguments.
+ signed char NumDiagArgs;
+
+ /// \brief Specifies whether an argument is in DiagArgumentsStr or
+ /// in DiagArguments.
+ ///
+ /// This is an array of ArgumentKind::ArgumentKind enum values, one for each
+ /// argument.
+ unsigned char DiagArgumentsKind[MaxArguments];
+
+ /// \brief Holds the values of each string argument for the current
+ /// diagnostic.
+ ///
+ /// This is only used when the corresponding ArgumentKind is ak_std_string.
+ std::string DiagArgumentsStr[MaxArguments];
+
+ /// \brief 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 interpretation depends on
+ /// exactly what sort of argument kind it is.
+ intptr_t DiagArgumentsVal[MaxArguments];
+
+ /// \brief The list of ranges added to this diagnostic.
+ SmallVector<CharSourceRange, 8> DiagRanges;
+
+ /// \brief If valid, provides a hint with some code to insert, remove,
+ /// or modify at a particular position.
+ SmallVector<FixItHint, 8> DiagFixItHints;
+
+ DiagnosticMapping makeUserMapping(diag::Severity Map, SourceLocation L) {
+ bool isPragma = L.isValid();
+ DiagnosticMapping Mapping =
+ DiagnosticMapping::Make(Map, /*IsUser=*/true, isPragma);
+
+ // If this is a pragma mapping, then set the diagnostic mapping flags so
+ // that we override command line options.
+ if (isPragma) {
+ Mapping.setNoWarningAsError(true);
+ Mapping.setNoErrorAsFatal(true);
+ }
+
+ return Mapping;
+ }
+
+ /// \brief 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);
+ }
+
+ /// @name Diagnostic Emission
+ /// @{
+protected:
+ // Sema requires access to the following functions because the current design
+ // of SFINAE requires it to use its own SemaDiagnosticBuilder, which needs to
+ // access us directly to ensure we minimize the emitted code for the common
+ // Sema::Diag() patterns.
+ friend class Sema;
+
+ /// \brief Emit the current diagnostic and clear the diagnostic state.
+ ///
+ /// \param Force Emit the diagnostic regardless of suppression settings.
+ bool EmitCurrentDiagnostic(bool Force = false);
+
+ unsigned getCurrentDiagID() const { return CurDiagID; }
+
+ SourceLocation getCurrentDiagLoc() const { return CurDiagLoc; }
+
+ /// @}
+
+ 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 {
+ DiagnosticsEngine &Diag;
+ unsigned NumErrors;
+ unsigned NumUnrecoverableErrors;
+
+public:
+ explicit DiagnosticErrorTrap(DiagnosticsEngine &Diag)
+ : Diag(Diag) { reset(); }
+
+ /// \brief Determine whether any errors have occurred since this
+ /// object instance was created.
+ bool hasErrorOccurred() const {
+ return Diag.TrapNumErrorsOccurred > NumErrors;
+ }
+
+ /// \brief Determine whether any unrecoverable errors have occurred since this
+ /// object instance was created.
+ bool hasUnrecoverableErrorOccurred() const {
+ return Diag.TrapNumUnrecoverableErrorsOccurred > NumUnrecoverableErrors;
+ }
+
+ /// \brief Set to initial state of "no errors occurred".
+ void reset() {
+ NumErrors = Diag.TrapNumErrorsOccurred;
+ NumUnrecoverableErrors = Diag.TrapNumUnrecoverableErrorsOccurred;
+ }
+};
+
+//===----------------------------------------------------------------------===//
+// DiagnosticBuilder
+//===----------------------------------------------------------------------===//
+
+/// \brief A little helper class used to produce diagnostics.
+///
+/// This is constructed by the DiagnosticsEngine::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 DiagnosticsEngine *DiagObj = nullptr;
+ mutable unsigned NumArgs = 0;
+
+ /// \brief Status variable indicating if this diagnostic is still active.
+ ///
+ // NOTE: This field is redundant with DiagObj (IsActive iff (DiagObj == 0)),
+ // but LLVM is not currently smart enough to eliminate the null check that
+ // Emit() would end up with if we used that as our status variable.
+ mutable bool IsActive = false;
+
+ /// \brief Flag indicating that this diagnostic is being emitted via a
+ /// call to ForceEmit.
+ mutable bool IsForceEmit = false;
+
+ void operator=(const DiagnosticBuilder &) = delete;
+ friend class DiagnosticsEngine;
+
+ DiagnosticBuilder() = default;
+
+ explicit DiagnosticBuilder(DiagnosticsEngine *diagObj)
+ : DiagObj(diagObj), IsActive(true) {
+ assert(diagObj && "DiagnosticBuilder requires a valid DiagnosticsEngine!");
+ diagObj->DiagRanges.clear();
+ diagObj->DiagFixItHints.clear();
+ }
+
+ friend class PartialDiagnostic;
+
+protected:
+ void FlushCounts() {
+ DiagObj->NumDiagArgs = NumArgs;
+ }
+
+ /// \brief Clear out the current diagnostic.
+ void Clear() const {
+ DiagObj = nullptr;
+ IsActive = false;
+ IsForceEmit = false;
+ }
+
+ /// \brief Determine whether this diagnostic is still active.
+ bool isActive() const { return IsActive; }
+
+ /// \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() {
+ // If this diagnostic is inactive, then its soul was stolen by the copy ctor
+ // (or by a subclass, as in SemaDiagnosticBuilder).
+ if (!isActive()) return false;
+
+ // When emitting diagnostics, we set the final argument count into
+ // the DiagnosticsEngine object.
+ FlushCounts();
+
+ // Process the diagnostic.
+ bool Result = DiagObj->EmitCurrentDiagnostic(IsForceEmit);
+
+ // This diagnostic is dead.
+ Clear();
+
+ return Result;
+ }
+
+public:
+ /// Copy constructor. When copied, this "takes" the diagnostic info from the
+ /// input and neuters it.
+ DiagnosticBuilder(const DiagnosticBuilder &D) {
+ DiagObj = D.DiagObj;
+ IsActive = D.IsActive;
+ IsForceEmit = D.IsForceEmit;
+ D.Clear();
+ NumArgs = D.NumArgs;
+ }
+
+ /// \brief Retrieve an empty diagnostic builder.
+ static DiagnosticBuilder getEmpty() {
+ return DiagnosticBuilder();
+ }
+
+ /// \brief Emits the diagnostic.
+ ~DiagnosticBuilder() {
+ Emit();
+ }
+
+ /// \brief Forces the diagnostic to be emitted.
+ const DiagnosticBuilder &setForceEmit() const {
+ IsForceEmit = true;
+ return *this;
+ }
+
+ /// \brief Conversion of DiagnosticBuilder to bool always returns \c true.
+ ///
+ /// This allows is to be used in boolean error contexts (where \c true is
+ /// used to indicate that an error has occurred), like:
+ /// \code
+ /// return Diag(...);
+ /// \endcode
+ operator bool() const { return true; }
+
+ void AddString(StringRef S) const {
+ assert(isActive() && "Clients must not add to cleared diagnostic!");
+ assert(NumArgs < DiagnosticsEngine::MaxArguments &&
+ "Too many arguments to diagnostic!");
+ DiagObj->DiagArgumentsKind[NumArgs] = DiagnosticsEngine::ak_std_string;
+ DiagObj->DiagArgumentsStr[NumArgs++] = S;
+ }
+
+ void AddTaggedVal(intptr_t V, DiagnosticsEngine::ArgumentKind Kind) const {
+ assert(isActive() && "Clients must not add to cleared diagnostic!");
+ assert(NumArgs < DiagnosticsEngine::MaxArguments &&
+ "Too many arguments to diagnostic!");
+ DiagObj->DiagArgumentsKind[NumArgs] = Kind;
+ DiagObj->DiagArgumentsVal[NumArgs++] = V;
+ }
+
+ void AddSourceRange(const CharSourceRange &R) const {
+ assert(isActive() && "Clients must not add to cleared diagnostic!");
+ DiagObj->DiagRanges.push_back(R);
+ }
+
+ void AddFixItHint(const FixItHint &Hint) const {
+ assert(isActive() && "Clients must not add to cleared diagnostic!");
+ if (!Hint.isNull())
+ DiagObj->DiagFixItHints.push_back(Hint);
+ }
+
+ void addFlagValue(StringRef V) const { DiagObj->FlagValue = V; }
+};
+
+struct AddFlagValue {
+ explicit AddFlagValue(StringRef V) : Val(V) {}
+ StringRef Val;
+};
+
+/// \brief Register a value for the flag in the current diagnostic. This
+/// value will be shown as the suffix "=value" after the flag name. It is
+/// useful in cases where the diagnostic flag accepts values (e.g.,
+/// -Rpass or -Wframe-larger-than).
+inline const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB,
+ const AddFlagValue V) {
+ DB.addFlagValue(V.Val);
+ return DB;
+}
+
+inline const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB,
+ StringRef S) {
+ DB.AddString(S);
+ return DB;
+}
+
+inline const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB,
+ const char *Str) {
+ DB.AddTaggedVal(reinterpret_cast<intptr_t>(Str),
+ DiagnosticsEngine::ak_c_string);
+ return DB;
+}
+
+inline const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB, int I) {
+ DB.AddTaggedVal(I, DiagnosticsEngine::ak_sint);
+ return DB;
+}
+
+// We use enable_if here to prevent that this overload is selected for
+// pointers or other arguments that are implicitly convertible to bool.
+template <typename T>
+inline
+typename std::enable_if<std::is_same<T, bool>::value,
+ const DiagnosticBuilder &>::type
+operator<<(const DiagnosticBuilder &DB, T I) {
+ DB.AddTaggedVal(I, DiagnosticsEngine::ak_sint);
+ return DB;
+}
+
+inline const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB,
+ unsigned I) {
+ DB.AddTaggedVal(I, DiagnosticsEngine::ak_uint);
+ return DB;
+}
+
+inline const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB,
+ tok::TokenKind I) {
+ DB.AddTaggedVal(static_cast<unsigned>(I), DiagnosticsEngine::ak_tokenkind);
+ return DB;
+}
+
+inline const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB,
+ const IdentifierInfo *II) {
+ DB.AddTaggedVal(reinterpret_cast<intptr_t>(II),
+ DiagnosticsEngine::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 std::enable_if<std::is_same<T, DeclContext>::value,
+ const DiagnosticBuilder &>::type
+operator<<(const DiagnosticBuilder &DB, T *DC) {
+ DB.AddTaggedVal(reinterpret_cast<intptr_t>(DC),
+ DiagnosticsEngine::ak_declcontext);
+ return DB;
+}
+
+inline const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB,
+ SourceRange R) {
+ DB.AddSourceRange(CharSourceRange::getTokenRange(R));
+ return DB;
+}
+
+inline const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB,
+ ArrayRef<SourceRange> Ranges) {
+ for (SourceRange R : Ranges)
+ 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;
+}
+
+inline const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB,
+ ArrayRef<FixItHint> Hints) {
+ for (const FixItHint &Hint : Hints)
+ DB.AddFixItHint(Hint);
+ return DB;
+}
+
+/// A nullability kind paired with a bit indicating whether it used a
+/// context-sensitive keyword.
+typedef std::pair<NullabilityKind, bool> DiagNullabilityKind;
+
+const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB,
+ DiagNullabilityKind nullability);
+
+inline DiagnosticBuilder DiagnosticsEngine::Report(SourceLocation Loc,
+ unsigned DiagID) {
+ assert(CurDiagID == ~0U && "Multiple diagnostics in flight at once!");
+ CurDiagLoc = Loc;
+ CurDiagID = DiagID;
+ FlagValue.clear();
+ return DiagnosticBuilder(this);
+}
+
+inline DiagnosticBuilder DiagnosticsEngine::Report(unsigned DiagID) {
+ return Report(SourceLocation(), DiagID);
+}
+
+//===----------------------------------------------------------------------===//
+// Diagnostic
+//===----------------------------------------------------------------------===//
+
+/// A little helper class (which is basically a smart pointer that forwards
+/// info from DiagnosticsEngine) that allows clients to enquire about the
+/// currently in-flight diagnostic.
+class Diagnostic {
+ const DiagnosticsEngine *DiagObj;
+ StringRef StoredDiagMessage;
+public:
+ explicit Diagnostic(const DiagnosticsEngine *DO) : DiagObj(DO) {}
+ Diagnostic(const DiagnosticsEngine *DO, StringRef storedDiagMessage)
+ : DiagObj(DO), StoredDiagMessage(storedDiagMessage) {}
+
+ const DiagnosticsEngine *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; }
+
+ /// \brief Return the kind of the specified index.
+ ///
+ /// Based on the kind of argument, the accessors below can be used to get
+ /// the value.
+ ///
+ /// \pre Idx < getNumArgs()
+ DiagnosticsEngine::ArgumentKind getArgKind(unsigned Idx) const {
+ assert(Idx < getNumArgs() && "Argument index out of range!");
+ return (DiagnosticsEngine::ArgumentKind)DiagObj->DiagArgumentsKind[Idx];
+ }
+
+ /// \brief Return the provided argument string specified by \p Idx.
+ /// \pre getArgKind(Idx) == DiagnosticsEngine::ak_std_string
+ const std::string &getArgStdStr(unsigned Idx) const {
+ assert(getArgKind(Idx) == DiagnosticsEngine::ak_std_string &&
+ "invalid argument accessor!");
+ return DiagObj->DiagArgumentsStr[Idx];
+ }
+
+ /// \brief Return the specified C string argument.
+ /// \pre getArgKind(Idx) == DiagnosticsEngine::ak_c_string
+ const char *getArgCStr(unsigned Idx) const {
+ assert(getArgKind(Idx) == DiagnosticsEngine::ak_c_string &&
+ "invalid argument accessor!");
+ return reinterpret_cast<const char*>(DiagObj->DiagArgumentsVal[Idx]);
+ }
+
+ /// \brief Return the specified signed integer argument.
+ /// \pre getArgKind(Idx) == DiagnosticsEngine::ak_sint
+ int getArgSInt(unsigned Idx) const {
+ assert(getArgKind(Idx) == DiagnosticsEngine::ak_sint &&
+ "invalid argument accessor!");
+ return (int)DiagObj->DiagArgumentsVal[Idx];
+ }
+
+ /// \brief Return the specified unsigned integer argument.
+ /// \pre getArgKind(Idx) == DiagnosticsEngine::ak_uint
+ unsigned getArgUInt(unsigned Idx) const {
+ assert(getArgKind(Idx) == DiagnosticsEngine::ak_uint &&
+ "invalid argument accessor!");
+ return (unsigned)DiagObj->DiagArgumentsVal[Idx];
+ }
+
+ /// \brief Return the specified IdentifierInfo argument.
+ /// \pre getArgKind(Idx) == DiagnosticsEngine::ak_identifierinfo
+ const IdentifierInfo *getArgIdentifier(unsigned Idx) const {
+ assert(getArgKind(Idx) == DiagnosticsEngine::ak_identifierinfo &&
+ "invalid argument accessor!");
+ return reinterpret_cast<IdentifierInfo*>(DiagObj->DiagArgumentsVal[Idx]);
+ }
+
+ /// \brief Return the specified non-string argument in an opaque form.
+ /// \pre getArgKind(Idx) != DiagnosticsEngine::ak_std_string
+ intptr_t getRawArg(unsigned Idx) const {
+ assert(getArgKind(Idx) != DiagnosticsEngine::ak_std_string &&
+ "invalid argument accessor!");
+ return DiagObj->DiagArgumentsVal[Idx];
+ }
+
+ /// \brief Return the number of source ranges associated with this diagnostic.
+ unsigned getNumRanges() const {
+ return DiagObj->DiagRanges.size();
+ }
+
+ /// \pre Idx < getNumRanges()
+ const CharSourceRange &getRange(unsigned Idx) const {
+ assert(Idx < getNumRanges() && "Invalid diagnostic range index!");
+ return DiagObj->DiagRanges[Idx];
+ }
+
+ /// \brief Return an array reference for this diagnostic's ranges.
+ ArrayRef<CharSourceRange> getRanges() const {
+ return DiagObj->DiagRanges;
+ }
+
+ unsigned getNumFixItHints() const {
+ return DiagObj->DiagFixItHints.size();
+ }
+
+ const FixItHint &getFixItHint(unsigned Idx) const {
+ assert(Idx < getNumFixItHints() && "Invalid index!");
+ return DiagObj->DiagFixItHints[Idx];
+ }
+
+ ArrayRef<FixItHint> getFixItHints() const {
+ return DiagObj->DiagFixItHints;
+ }
+
+ /// \brief Format this diagnostic into a string, substituting the
+ /// formal arguments into the %0 slots.
+ ///
+ /// The result is appended onto the \p OutStr array.
+ void FormatDiagnostic(SmallVectorImpl<char> &OutStr) const;
+
+ /// \brief Format the given format-string into the output buffer using the
+ /// arguments stored in this diagnostic.
+ void FormatDiagnostic(const char *DiagStr, const char *DiagEnd,
+ 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;
+ DiagnosticsEngine::Level Level;
+ FullSourceLoc Loc;
+ std::string Message;
+ std::vector<CharSourceRange> Ranges;
+ std::vector<FixItHint> FixIts;
+
+public:
+ StoredDiagnostic() = default;
+ StoredDiagnostic(DiagnosticsEngine::Level Level, const Diagnostic &Info);
+ StoredDiagnostic(DiagnosticsEngine::Level Level, unsigned ID,
+ StringRef Message);
+ StoredDiagnostic(DiagnosticsEngine::Level Level, unsigned ID,
+ StringRef Message, FullSourceLoc Loc,
+ ArrayRef<CharSourceRange> Ranges,
+ ArrayRef<FixItHint> Fixits);
+
+ /// \brief Evaluates true when this object stores a diagnostic.
+ explicit operator bool() const { return Message.size() > 0; }
+
+ unsigned getID() const { return ID; }
+ DiagnosticsEngine::Level getLevel() const { return Level; }
+ const FullSourceLoc &getLocation() const { return Loc; }
+ 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(); }
+
+ ArrayRef<CharSourceRange> getRanges() const {
+ return llvm::makeArrayRef(Ranges);
+ }
+
+
+ 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(); }
+
+ ArrayRef<FixItHint> getFixIts() const {
+ return llvm::makeArrayRef(FixIts);
+ }
+};
+
+/// \brief Abstract interface, implemented by clients of the front-end, which
+/// formats and prints fully processed diagnostics.
+class DiagnosticConsumer {
+protected:
+ unsigned NumWarnings; ///< Number of warnings reported
+ unsigned NumErrors; ///< Number of errors reported
+
+public:
+ DiagnosticConsumer() : NumWarnings(0), NumErrors(0) { }
+
+ unsigned getNumErrors() const { return NumErrors; }
+ unsigned getNumWarnings() const { return NumWarnings; }
+ virtual void clear() { NumWarnings = NumErrors = 0; }
+
+ virtual ~DiagnosticConsumer();
+
+ /// \brief 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().
+ ///
+ /// \param LangOpts The language options for the source file being processed.
+ /// \param PP The preprocessor object being used for the source; this is
+ /// optional, e.g., it may not be present when processing AST source files.
+ virtual void BeginSourceFile(const LangOptions &LangOpts,
+ const Preprocessor *PP = nullptr) {}
+
+ /// \brief 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
+ /// BeginSourceFile() are inaccessible.
+ virtual void EndSourceFile() {}
+
+ /// \brief Callback to inform the diagnostic client that processing of all
+ /// source files has ended.
+ virtual void finish() {}
+
+ /// \brief Indicates whether the diagnostics handled by this
+ /// DiagnosticConsumer should be included in the number of diagnostics
+ /// reported by DiagnosticsEngine.
+ ///
+ /// The default implementation returns true.
+ virtual bool IncludeInDiagnosticCounts() const;
+
+ /// \brief Handle this diagnostic, reporting it to the user or
+ /// capturing it to a log as needed.
+ ///
+ /// The default implementation just keeps track of the total number of
+ /// warnings and errors.
+ virtual void HandleDiagnostic(DiagnosticsEngine::Level DiagLevel,
+ const Diagnostic &Info);
+};
+
+/// \brief A diagnostic client that ignores all diagnostics.
+class IgnoringDiagConsumer : public DiagnosticConsumer {
+ virtual void anchor();
+ void HandleDiagnostic(DiagnosticsEngine::Level DiagLevel,
+ const Diagnostic &Info) override {
+ // Just ignore it.
+ }
+};
+
+/// \brief Diagnostic consumer that forwards diagnostics along to an
+/// existing, already-initialized diagnostic consumer.
+///
+class ForwardingDiagnosticConsumer : public DiagnosticConsumer {
+ DiagnosticConsumer &Target;
+
+public:
+ ForwardingDiagnosticConsumer(DiagnosticConsumer &Target) : Target(Target) {}
+
+ ~ForwardingDiagnosticConsumer() override;
+
+ void HandleDiagnostic(DiagnosticsEngine::Level DiagLevel,
+ const Diagnostic &Info) override;
+ void clear() override;
+
+ bool IncludeInDiagnosticCounts() const override;
+};
+
+// Struct used for sending info about how a type should be printed.
+struct TemplateDiffTypes {
+ intptr_t FromType;
+ intptr_t ToType;
+ unsigned PrintTree : 1;
+ unsigned PrintFromType : 1;
+ unsigned ElideType : 1;
+ unsigned ShowColors : 1;
+ // The printer sets this variable to true if the template diff was used.
+ unsigned TemplateDiffUsed : 1;
+};
+
+/// Special character that the diagnostic printer will use to toggle the bold
+/// attribute. The character itself will be not be printed.
+const char ToggleHighlight = 127;
+
+
+/// ProcessWarningOptions - Initialize the diagnostic client and process the
+/// warning options specified on the command line.
+void ProcessWarningOptions(DiagnosticsEngine &Diags,
+ const DiagnosticOptions &Opts,
+ bool ReportDiags = true);
+
+} // 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..48cbf09
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Basic/Diagnostic.td
@@ -0,0 +1,127 @@
+//===--- 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 severities.
+class Severity<string N> {
+ string Name = N;
+}
+def SEV_Ignored : Severity<"Ignored">;
+def SEV_Remark : Severity<"Remark">;
+def SEV_Warning : Severity<"Warning">;
+def SEV_Error : Severity<"Error">;
+def SEV_Fatal : Severity<"Fatal">;
+
+// Define the diagnostic classes.
+class DiagClass;
+def CLASS_NOTE : DiagClass;
+def CLASS_REMARK : DiagClass;
+def CLASS_WARNING : DiagClass;
+def CLASS_EXTENSION : DiagClass;
+def CLASS_ERROR : DiagClass;
+
+// Responses to a diagnostic in a SFINAE context.
+class SFINAEResponse;
+def SFINAE_SubstitutionFailure : SFINAEResponse;
+def SFINAE_Suppress : SFINAEResponse;
+def SFINAE_Report : SFINAEResponse;
+def SFINAE_AccessControl : SFINAEResponse;
+
+// 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, Severity defaultmapping> {
+ /// Component is specified by the file with a big let directive.
+ string Component = ?;
+ string Text = text;
+ DiagClass Class = DC;
+ SFINAEResponse SFINAE = SFINAE_Suppress;
+ bit AccessControl = 0;
+ bit WarningNoWerror = 0;
+ bit ShowInSystemHeader = 0;
+ Severity DefaultSeverity = defaultmapping;
+ DiagGroup Group;
+ string CategoryName = "";
+}
+
+class SFINAEFailure {
+ SFINAEResponse SFINAE = SFINAE_SubstitutionFailure;
+}
+class NoSFINAE {
+ SFINAEResponse SFINAE = SFINAE_Report;
+}
+class AccessControl {
+ SFINAEResponse SFINAE = SFINAE_AccessControl;
+}
+
+class ShowInSystemHeader {
+ bit ShowInSystemHeader = 1;
+}
+
+class SuppressInSystemHeader {
+ bit ShowInSystemHeader = 0;
+}
+
+// FIXME: ExtWarn and Extension should also be SFINAEFailure by default.
+class Error<string str> : Diagnostic<str, CLASS_ERROR, SEV_Error>, SFINAEFailure {
+ bit ShowInSystemHeader = 1;
+}
+class Warning<string str> : Diagnostic<str, CLASS_WARNING, SEV_Warning>;
+class Remark<string str> : Diagnostic<str, CLASS_REMARK, SEV_Ignored>;
+class Extension<string str> : Diagnostic<str, CLASS_EXTENSION, SEV_Ignored>;
+class ExtWarn<string str> : Diagnostic<str, CLASS_EXTENSION, SEV_Warning>;
+class Note<string str> : Diagnostic<str, CLASS_NOTE, SEV_Fatal/*ignored*/>;
+
+
+class DefaultIgnore { Severity DefaultSeverity = SEV_Ignored; }
+class DefaultWarn { Severity DefaultSeverity = SEV_Warning; }
+class DefaultError { Severity DefaultSeverity = SEV_Error; }
+class DefaultFatal { Severity DefaultSeverity = SEV_Fatal; }
+class DefaultWarnNoWerror {
+ bit WarningNoWerror = 1;
+}
+class DefaultRemark { Severity DefaultSeverity = SEV_Remark; }
+
+// Definitions for Diagnostics.
+include "DiagnosticASTKinds.td"
+include "DiagnosticAnalysisKinds.td"
+include "DiagnosticCommentKinds.td"
+include "DiagnosticCommonKinds.td"
+include "DiagnosticDriverKinds.td"
+include "DiagnosticFrontendKinds.td"
+include "DiagnosticLexKinds.td"
+include "DiagnosticParseKinds.td"
+include "DiagnosticSemaKinds.td"
+include "DiagnosticSerializationKinds.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..0b37030
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticASTKinds.td
@@ -0,0 +1,266 @@
+//==--- 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 {
+
+// Constant expression diagnostics. These (and their users) belong in Sema.
+def note_expr_divide_by_zero : Note<"division by zero">;
+def note_constexpr_invalid_cast : Note<
+ "%select{reinterpret_cast|dynamic_cast|cast that performs the conversions of"
+ " a reinterpret_cast|cast from %1}0 is not allowed in a constant expression">;
+def note_constexpr_invalid_downcast : Note<
+ "cannot cast object of dynamic type %0 to type %1">;
+def note_constexpr_overflow : Note<
+ "value %0 is outside the range of representable values of type %1">;
+def note_constexpr_negative_shift : Note<"negative shift count %0">;
+def note_constexpr_large_shift : Note<
+ "shift count %0 >= width of type %1 (%2 bit%s2)">;
+def note_constexpr_lshift_of_negative : Note<"left shift of negative value %0">;
+def note_constexpr_lshift_discards : Note<"signed left shift discards bits">;
+def note_constexpr_invalid_function : Note<
+ "%select{non-constexpr|undefined}0 %select{function|constructor}1 %2 cannot "
+ "be used in a constant expression">;
+def note_constexpr_no_return : Note<
+ "control reached end of constexpr function">;
+def note_constexpr_virtual_call : Note<
+ "cannot evaluate virtual function call in a constant expression">;
+def note_constexpr_virtual_base : Note<
+ "cannot construct object of type %0 with virtual base class "
+ "in a constant expression">;
+def note_constexpr_nonliteral : Note<
+ "non-literal type %0 cannot be used in a constant expression">;
+def note_constexpr_non_global : Note<
+ "%select{pointer|reference}0 to %select{|subobject of }1"
+ "%select{temporary|%3}2 is not a constant expression">;
+def note_constexpr_uninitialized : Note<
+ "%select{|sub}0object of type %1 is not initialized">;
+def note_constexpr_array_index : Note<"cannot refer to element %0 of "
+ "%select{array of %2 elements|non-array object}1 in a constant expression">;
+def note_constexpr_float_arithmetic : Note<
+ "floating point arithmetic produces %select{an infinity|a NaN}0">;
+def note_constexpr_pointer_subtraction_not_same_array : Note<
+ "subtracted pointers are not elements of the same array">;
+def note_constexpr_pointer_subtraction_zero_size : Note<
+ "subtraction of pointers to type %0 of zero size">;
+def note_constexpr_pointer_comparison_base_classes : Note<
+ "comparison of addresses of subobjects of different base classes "
+ "has unspecified value">;
+def note_constexpr_pointer_comparison_base_field : Note<
+ "comparison of address of base class subobject %0 of class %1 to field %2 "
+ "has unspecified value">;
+def note_constexpr_pointer_comparison_differing_access : Note<
+ "comparison of address of fields %0 and %2 of %4 with differing access "
+ "specifiers (%1 vs %3) has unspecified value">;
+def note_constexpr_compare_virtual_mem_ptr : Note<
+ "comparison of pointer to virtual member function %0 has unspecified value">;
+def note_constexpr_past_end : Note<
+ "dereferenced pointer past the end of %select{|subobject of }0"
+ "%select{temporary|%2}1 is not a constant expression">;
+def note_constexpr_past_end_subobject : Note<
+ "cannot %select{access base class of|access derived class of|access field of|"
+ "access array element of|ERROR|call member function on|"
+ "access real component of|access imaginary component of}0 "
+ "pointer past the end of object">;
+def note_constexpr_null_subobject : Note<
+ "cannot %select{access base class of|access derived class of|access field of|"
+ "access array element of|perform pointer arithmetic on|"
+ "call member function on|access real component of|"
+ "access imaginary component of}0 null pointer">;
+def note_constexpr_var_init_non_constant : Note<
+ "initializer of %0 is not a constant expression">;
+def note_constexpr_typeid_polymorphic : Note<
+ "typeid applied to expression of polymorphic type %0 is "
+ "not allowed in a constant expression">;
+def note_constexpr_void_comparison : Note<
+ "comparison between unequal pointers to void has unspecified result">;
+def note_constexpr_temporary_here : Note<"temporary created here">;
+def note_constexpr_conditional_never_const : Note<
+ "both arms of conditional operator are unable to produce a "
+ "constant expression">;
+def note_constexpr_depth_limit_exceeded : Note<
+ "constexpr evaluation exceeded maximum depth of %0 calls">;
+def note_constexpr_call_limit_exceeded : Note<
+ "constexpr evaluation hit maximum call limit">;
+def note_constexpr_step_limit_exceeded : Note<
+ "constexpr evaluation hit maximum step limit; possible infinite loop?">;
+def note_constexpr_this : Note<
+ "%select{|implicit }0use of 'this' pointer is only allowed within the "
+ "evaluation of a call to a 'constexpr' member function">;
+def note_constexpr_lifetime_ended : Note<
+ "%select{read of|assignment to|increment of|decrement of}0 "
+ "%select{temporary|variable}1 whose lifetime has ended">;
+def note_constexpr_access_uninit : Note<
+ "%select{read of|assignment to|increment of|decrement of}0 "
+ "object outside its lifetime is not allowed in a constant expression">;
+def note_constexpr_use_uninit_reference : Note<
+ "use of reference outside its lifetime "
+ "is not allowed in a constant expression">;
+def note_constexpr_modify_const_type : Note<
+ "modification of object of const-qualified type %0 is not allowed "
+ "in a constant expression">;
+def note_constexpr_access_volatile_type : Note<
+ "%select{read of|assignment to|increment of|decrement of}0 "
+ "volatile-qualified type %1 is not allowed in a constant expression">;
+def note_constexpr_access_volatile_obj : Note<
+ "%select{read of|assignment to|increment of|decrement of}0 volatile "
+ "%select{temporary|object %2|member %2}1 is not allowed in "
+ "a constant expression">;
+def note_constexpr_ltor_mutable : Note<
+ "read of mutable member %0 is not allowed in a constant expression">;
+def note_constexpr_ltor_non_const_int : Note<
+ "read of non-const variable %0 is not allowed in a constant expression">;
+def note_constexpr_ltor_non_constexpr : Note<
+ "read of non-constexpr variable %0 is not allowed in a constant expression">;
+def note_constexpr_access_null : Note<
+ "%select{read of|assignment to|increment of|decrement of}0 "
+ "dereferenced null pointer is not allowed in a constant expression">;
+def note_constexpr_access_past_end : Note<
+ "%select{read of|assignment to|increment of|decrement of}0 "
+ "dereferenced one-past-the-end pointer is not allowed in a constant expression">;
+def note_constexpr_access_inactive_union_member : Note<
+ "%select{read of|assignment to|increment of|decrement of}0 "
+ "member %1 of union with %select{active member %3|no active member}2 "
+ "is not allowed in a constant expression">;
+def note_constexpr_access_static_temporary : Note<
+ "%select{read of|assignment to|increment of|decrement of}0 temporary "
+ "is not allowed in a constant expression outside the expression that "
+ "created the temporary">;
+def note_constexpr_modify_global : Note<
+ "a constant expression cannot modify an object that is visible outside "
+ "that expression">;
+def note_constexpr_stmt_expr_unsupported : Note<
+ "this use of statement expressions is not supported in a "
+ "constant expression">;
+def note_constexpr_calls_suppressed : Note<
+ "(skipping %0 call%s0 in backtrace; use -fconstexpr-backtrace-limit=0 to "
+ "see all)">;
+def note_constexpr_call_here : Note<"in call to '%0'">;
+def note_constexpr_baa_insufficient_alignment : Note<
+ "%select{alignment of|offset of the aligned pointer from}0 the base pointee "
+ "object (%1 %plural{1:byte|:bytes}1) is %select{less than|not a multiple of}0 the "
+ "asserted %2 %plural{1:byte|:bytes}2">;
+def note_constexpr_baa_value_insufficient_alignment : Note<
+ "value of the aligned pointer (%0) is not a multiple of the asserted %1 "
+ "%plural{1:byte|:bytes}1">;
+
+def warn_integer_constant_overflow : Warning<
+ "overflow in expression; result is %0 with type %1">,
+ InGroup<DiagGroup<"integer-overflow">>;
+
+// 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">;
+}
+
+// vtable related.
+let CategoryName = "VTable ABI Issue" in {
+ def err_vftable_ambiguous_component : Error<
+ "ambiguous vftable component for %0 introduced via covariant thunks; "
+ "this is an inherent limitation of the ABI">;
+ def note_covariant_thunk : Note<
+ "covariant thunk required by %0">;
+}
+
+// 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">,
+ InGroup<DiagGroup<"odr">>;
+def note_odr_tag_kind_here: Note<
+ "%0 is a %select{struct|interface|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">;
+
+def err_odr_field_type_inconsistent : Error<
+ "field %0 declared with incompatible types in different "
+ "translation units (%1 vs. %2)">;
+
+// 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..5461212
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticAnalysisKinds.td
@@ -0,0 +1,12 @@
+//==--- 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 {
+
+}
diff --git a/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticCategories.h b/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticCategories.h
new file mode 100644
index 0000000..4dd067b
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticCategories.h
@@ -0,0 +1,26 @@
+//===- DiagnosticCategories.h - Diagnostic Categories Enumerators-*- 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_BASIC_DIAGNOSTICCATEGORIES_H
+#define LLVM_CLANG_BASIC_DIAGNOSTICCATEGORIES_H
+
+namespace clang {
+ namespace diag {
+ enum {
+#define GET_CATEGORY_TABLE
+#define CATEGORY(X, ENUM) ENUM,
+#include "clang/Basic/DiagnosticGroups.inc"
+#undef CATEGORY
+#undef GET_CATEGORY_TABLE
+ DiagCat_NUM_CATEGORIES
+ };
+ } // end namespace diag
+} // end namespace clang
+
+#endif
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..37b8569
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticCategories.td
@@ -0,0 +1,11 @@
+//==--- 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">;
+class CatBackend : DiagCategory<"Backend Issue">;
diff --git a/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticCommentKinds.td b/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticCommentKinds.td
new file mode 100644
index 0000000..ab24582
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticCommentKinds.td
@@ -0,0 +1,172 @@
+//==--- DiagnosticCommentKinds.td - diagnostics related to comments -------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+let Component = "Comment" in {
+let CategoryName = "Documentation Issue" in {
+
+// HTML parsing errors. These are under -Wdocumentation to make sure the user
+// knows that we didn't parse something as they might expect.
+
+def warn_doc_html_start_tag_expected_quoted_string : Warning<
+ "expected quoted string after equals sign">,
+ InGroup<Documentation>, DefaultIgnore;
+
+def warn_doc_html_start_tag_expected_ident_or_greater : Warning<
+ "HTML start tag prematurely ended, expected attribute name or '>'">,
+ InGroup<Documentation>, DefaultIgnore;
+
+def note_doc_html_tag_started_here : Note<
+ "HTML tag started here">;
+
+// HTML semantic errors
+
+def warn_doc_html_end_forbidden : Warning<
+ "HTML end tag '%0' is forbidden">,
+ InGroup<DocumentationHTML>, DefaultIgnore;
+
+def warn_doc_html_end_unbalanced : Warning<
+ "HTML end tag does not match any start tag">,
+ InGroup<DocumentationHTML>, DefaultIgnore;
+
+def warn_doc_html_start_end_mismatch : Warning<
+ "HTML start tag '%0' closed by '%1'">,
+ InGroup<DocumentationHTML>, DefaultIgnore;
+
+def note_doc_html_end_tag : Note<
+ "end tag">;
+
+def warn_doc_html_missing_end_tag : Warning<
+ "HTML tag '%0' requires an end tag">,
+ InGroup<DocumentationHTML>, DefaultIgnore;
+
+// Commands
+
+def warn_doc_block_command_empty_paragraph : Warning<
+ "empty paragraph passed to '%select{\\|@}0%1' command">,
+ InGroup<Documentation>, DefaultIgnore;
+
+def warn_doc_block_command_duplicate : Warning<
+ "duplicated command '%select{\\|@}0%1'">,
+ InGroup<Documentation>, DefaultIgnore;
+
+def note_doc_block_command_previous : Note<
+ "previous command '%select{\\|@}0%1' here">;
+
+def note_doc_block_command_previous_alias : Note<
+ "previous command '%select{\\|@}0%1' (an alias of '\\%2') here">;
+
+// \param command
+
+def warn_doc_param_invalid_direction : Warning<
+ "unrecognized parameter passing direction, "
+ "valid directions are '[in]', '[out]' and '[in,out]'">,
+ InGroup<Documentation>, DefaultIgnore;
+
+def warn_doc_param_spaces_in_direction : Warning<
+ "whitespace is not allowed in parameter passing direction">,
+ InGroup<DocumentationPedantic>, DefaultIgnore;
+
+def warn_doc_param_not_attached_to_a_function_decl : Warning<
+ "'%select{\\|@}0param' command used in a comment that is not attached to "
+ "a function declaration">,
+ InGroup<Documentation>, DefaultIgnore;
+
+def warn_doc_function_method_decl_mismatch : Warning<
+ "'%select{\\|@}0%select{function|functiongroup|method|methodgroup|callback}1' "
+ "command should be used in a comment attached to "
+ "%select{a function|a function|an Objective-C method|an Objective-C method|"
+ "a pointer to function}2 declaration">,
+ InGroup<Documentation>, DefaultIgnore;
+
+def warn_doc_api_container_decl_mismatch : Warning<
+ "'%select{\\|@}0%select{class|interface|protocol|struct|union}1' "
+ "command should not be used in a comment attached to a "
+ "non-%select{class|interface|protocol|struct|union}2 declaration">,
+ InGroup<Documentation>, DefaultIgnore;
+
+def warn_doc_container_decl_mismatch : Warning<
+ "'%select{\\|@}0%select{classdesign|coclass|dependency|helper"
+ "|helperclass|helps|instancesize|ownership|performance|security|superclass}1' "
+ "command should not be used in a comment attached to a non-container declaration">,
+ InGroup<Documentation>, DefaultIgnore;
+
+def warn_doc_param_duplicate : Warning<
+ "parameter '%0' is already documented">,
+ InGroup<Documentation>, DefaultIgnore;
+
+def note_doc_param_previous : Note<
+ "previous documentation">;
+
+def warn_doc_param_not_found : Warning<
+ "parameter '%0' not found in the function declaration">,
+ InGroup<Documentation>, DefaultIgnore;
+
+def note_doc_param_name_suggestion : Note<
+ "did you mean '%0'?">;
+
+// tparam command
+
+def warn_doc_tparam_not_attached_to_a_template_decl : Warning<
+ "'%select{\\|@}0tparam' command used in a comment that is not attached to "
+ "a template declaration">,
+ InGroup<Documentation>, DefaultIgnore;
+
+def warn_doc_tparam_duplicate : Warning<
+ "template parameter '%0' is already documented">,
+ InGroup<Documentation>, DefaultIgnore;
+
+def note_doc_tparam_previous : Note<
+ "previous documentation">;
+
+def warn_doc_tparam_not_found : Warning<
+ "template parameter '%0' not found in the template declaration">,
+ InGroup<Documentation>, DefaultIgnore;
+
+def note_doc_tparam_name_suggestion : Note<
+ "did you mean '%0'?">;
+
+// \returns command
+
+def warn_doc_returns_not_attached_to_a_function_decl : Warning<
+ "'%select{\\|@}0%1' command used in a comment that is not attached to "
+ "a function or method declaration">,
+ InGroup<Documentation>, DefaultIgnore;
+
+def warn_doc_returns_attached_to_a_void_function : Warning<
+ "'%select{\\|@}0%1' command used in a comment that is attached to a "
+ "%select{function returning void|constructor|destructor|"
+ "method returning void}2">,
+ InGroup<Documentation>, DefaultIgnore;
+
+// \deprecated command
+
+def warn_doc_deprecated_not_sync : Warning<
+ "declaration is marked with '\\deprecated' command but does not have "
+ "a deprecation attribute">,
+ InGroup<DocumentationDeprecatedSync>, DefaultIgnore;
+
+def note_add_deprecation_attr : Note<
+ "add a deprecation attribute to the declaration to silence this warning">;
+
+// verbatim block commands
+
+def warn_verbatim_block_end_without_start : Warning<
+ "'%select{\\|@}0%1' command does not terminate a verbatim text block">,
+ InGroup<Documentation>, DefaultIgnore;
+
+def warn_unknown_comment_command_name : Warning<
+ "unknown command tag name">,
+ InGroup<DocumentationUnknownCommand>, DefaultIgnore;
+
+def warn_correct_comment_command_name : Warning<
+ "unknown command tag name '%0'; did you mean '%1'?">,
+ InGroup<DocumentationUnknownCommand>, DefaultIgnore;
+
+} // end of documentation issue category
+} // end of AST component
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..ccc271a
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticCommonKinds.td
@@ -0,0 +1,217 @@
+//==--- 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_declared_at : Note<"declared here">;
+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_possibility : Note<"one possibility">;
+def note_also_found : Note<"also found">;
+
+// Parse && Lex
+
+let CategoryName = "Lexical or Preprocessor Issue" in {
+
+def err_expected_colon_after_setter_name : Error<
+ "method name referenced in property setter attribute "
+ "must end with ':'">;
+def err_expected_string_literal : Error<"expected string literal "
+ "%select{in %1|for diagnostic message in static_assert|"
+ "for optional message in 'availability' attribute}0">;
+def err_invalid_string_udl : Error<
+ "string literal with user-defined suffix cannot be used here">;
+def err_invalid_character_udl : Error<
+ "character literal with user-defined suffix cannot be used here">;
+def err_invalid_numeric_udl : Error<
+ "numeric literal with user-defined suffix cannot be used here">;
+
+}
+
+// Parse && Sema
+
+let CategoryName = "Parse Issue" in {
+
+def err_expected : Error<"expected %0">;
+def err_expected_either : Error<"expected %0 or %1">;
+def err_expected_after : Error<"expected %1 after %0">;
+
+def err_param_redefinition : Error<"redefinition of parameter %0">;
+def warn_method_param_redefinition : Warning<"redefinition of method parameter %0">;
+def warn_method_param_declaration : Warning<"redeclaration of method parameter %0">,
+ InGroup<DuplicateArgDecl>, DefaultIgnore;
+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++11 extension">, InGroup<CXX11>;
+def warn_cxx98_compat_variadic_templates :
+ Warning<"variadic templates are incompatible with C++98">,
+ InGroup<CXX98Compat>, DefaultIgnore;
+def err_default_special_members : Error<
+ "only special member functions may be defaulted">;
+def err_deleted_non_function : Error<
+ "only functions can have deleted definitions">;
+def err_module_not_found : Error<"module '%0' not found">, DefaultFatal;
+def err_module_not_built : Error<"could not build module '%0'">, DefaultFatal;
+def err_module_build_disabled: Error<
+ "module '%0' is needed but has not been provided, and implicit use of module "
+ "files is disabled">, DefaultFatal;
+def err_module_unavailable : Error<
+ "module '%0' %select{is incompatible with|requires}1 feature '%2'">;
+def err_module_header_missing : Error<
+ "%select{|umbrella }0header '%1' not found">;
+def err_module_lock_failure : Error<
+ "could not acquire lock file for module '%0'">, DefaultFatal;
+def err_module_lock_timeout : Error<
+ "timed out waiting to acquire lock file for module '%0'">, DefaultFatal;
+def err_module_cycle : Error<"cyclic dependency in module '%0': %1">,
+ DefaultFatal;
+def note_pragma_entered_here : Note<"#pragma entered here">;
+def note_decl_hiding_tag_type : Note<
+ "%1 %0 is hidden by a non-type declaration of %0 here">;
+def err_attribute_not_type_attr : Error<
+ "%0 attribute cannot be applied to types">;
+def err_enum_template : Error<"enumeration cannot be a template">;
+
+}
+
+let CategoryName = "Nullability Issue" in {
+
+def warn_nullability_duplicate : Warning<
+ "duplicate nullability specifier %0">,
+ InGroup<Nullability>;
+
+def warn_conflicting_nullability_attr_overriding_ret_types : Warning<
+ "conflicting nullability specifier on return types, %0 "
+ "conflicts with existing specifier %1">,
+ InGroup<Nullability>;
+
+def warn_conflicting_nullability_attr_overriding_param_types : Warning<
+ "conflicting nullability specifier on parameter types, %0 "
+ "conflicts with existing specifier %1">,
+ InGroup<Nullability>;
+
+def err_nullability_conflicting : Error<
+ "nullability specifier %0 conflicts with existing specifier %1">;
+
+}
+
+// Sema && Lex
+def ext_c99_longlong : Extension<
+ "'long long' is an extension when C99 mode is not enabled">,
+ InGroup<LongLong>;
+def ext_cxx11_longlong : Extension<
+ "'long long' is a C++11 extension">,
+ InGroup<CXX11LongLong>;
+def warn_cxx98_compat_longlong : Warning<
+ "'long long' is incompatible with C++98">,
+ InGroup<CXX98CompatPedantic>, DefaultIgnore;
+def err_integer_literal_too_large : Error<
+ "integer literal is too large to be represented in any %select{signed |}0"
+ "integer type">;
+def ext_integer_literal_too_large_for_signed : ExtWarn<
+ "integer literal is too large to be represented in a signed integer type, "
+ "interpreting as unsigned">,
+ InGroup<ImplicitlyUnsignedLiteral>;
+def warn_old_implicitly_unsigned_long : Warning<
+ "integer literal is too large to be represented in type 'long', "
+ "interpreting as 'unsigned long' per C89; this literal will "
+ "%select{have type 'long long'|be ill-formed}0 in C99 onwards">,
+ InGroup<C99Compat>;
+def warn_old_implicitly_unsigned_long_cxx : Warning<
+ "integer literal is too large to be represented in type 'long', "
+ "interpreting as 'unsigned long' per C++98; this literal will "
+ "%select{have type 'long long'|be ill-formed}0 in C++11 onwards">,
+ InGroup<CXX11Compat>;
+def ext_old_implicitly_unsigned_long_cxx : ExtWarn<
+ "integer literal is too large to be represented in type 'long' and is "
+ "subject to undefined behavior under C++98, interpreting as 'unsigned long'; "
+ "this literal will %select{have type 'long long'|be ill-formed}0 "
+ "in C++11 onwards">,
+ InGroup<CXX11Compat>;
+
+// SEH
+def err_seh_expected_handler : Error<
+ "expected '__except' or '__finally' block">;
+def err_seh___except_block : Error<
+ "%0 only allowed in __except block or filter expression">;
+def err_seh___except_filter : Error<
+ "%0 only allowed in __except filter expression">;
+def err_seh___finally_block : Error<
+ "%0 only allowed in __finally block">;
+
+// Sema && AST
+def note_invalid_subexpr_in_const_expr : Note<
+ "subexpression not valid in a 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_fpmath : Error<"unknown FP unit '%0'">;
+def err_target_unsupported_fpmath : Error<
+ "the '%0' unit is not supported with this instruction set">;
+def err_target_unsupported_unaligned : Error<
+ "the %0 sub-architecture does not support unaligned accesses">;
+def err_opt_not_valid_with_opt : Error<
+ "option '%0' cannot be specified with '%1'">;
+
+// 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;
+def err_unable_to_rename_temp : Error<
+ "unable to rename temporary '%0' to output file '%1': '%2'">;
+def err_unable_to_make_temp : Error<
+ "unable to make temporary file: %0">;
+
+// Modules
+def err_module_format_unhandled : Error<
+ "no handler registered for module format '%0'">, DefaultFatal;
+
+// TransformActions
+// TODO: Use a custom category name to distinguish rewriter errors.
+def err_mt_message : Error<"[rewriter] %0">, SuppressInSystemHeader;
+def warn_mt_message : Warning<"[rewriter] %0">;
+def note_mt_message : Note<"[rewriter] %0">;
+
+// ARCMigrate
+def warn_arcmt_nsalloc_realloc : Warning<"[rewriter] call returns pointer to GC managed memory; it will become unmanaged in ARC">;
+def err_arcmt_nsinvocation_ownership : Error<"NSInvocation's %0 is not safe to be used with an object with ownership other than __unsafe_unretained">;
+
+// OpenMP
+def err_omp_more_one_clause : Error<
+ "directive '#pragma omp %0' cannot contain more than one '%1' clause%select{| with '%3' name modifier| with 'source' dependence}2">;
+}
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..ce270bf
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticDriverKinds.td
@@ -0,0 +1,226 @@
+//==--- 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_opt_for_target : Error<
+ "unsupported option '%0' for target '%1'">;
+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_stdin_type_clang_cl : Error<
+ "use /Tc or /Tp to set input type for 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_thread_model_for_target : Error<
+ "invalid thread model '%0' in '%1' for this target">;
+def err_drv_invalid_linker_name : Error<
+ "invalid linker name in argument '%0'">;
+def err_drv_invalid_rtlib_name : Error<
+ "invalid runtime library name in argument '%0'">;
+def err_drv_unsupported_rtlib_for_platform : Error<
+ "unsupported runtime library '%0' for platform '%1'">;
+def err_drv_invalid_stdlib_name : Error<
+ "invalid library name in argument '%0'">;
+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_out_file_argument_with_multiple_sources : Error<
+ "cannot specify '%0%1' when compiling multiple source files">;
+def err_no_external_assembler : Error<
+ "there is no external assembler that can be used on this platform">;
+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 value%s1)">;
+def err_drv_invalid_Xarch_argument_with_args : Error<
+ "invalid Xarch argument: '%0', options requiring arguments are unsupported">;
+def err_drv_invalid_Xarch_argument_isdriver : Error<
+ "invalid Xarch argument: '%0', cannot change driver behavior inside Xarch argument">;
+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_no_module_support : Error<
+ "'%0': unable to use module files with this tool">;
+def err_drv_clang_unsupported : Error<
+ "the clang compiler does not support '%0'">;
+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 (use -v to see invocation)">;
+def err_drv_force_crash : Error<
+ "failing because environment variable '%0' is set">;
+def err_drv_invalid_mfloat_abi : Error<
+ "invalid float ABI '%0'">;
+def err_drv_invalid_libcxx_deployment : Error<
+ "invalid deployment target for -stdlib=libc++ (requires %0 or later)">;
+def err_drv_invalid_argument_to_fdebug_prefix_map : Error<
+ "invalid argument '%0' to -fdebug-prefix-map">;
+def err_drv_malformed_sanitizer_blacklist : Error<
+ "malformed sanitizer blacklist: '%0'">;
+
+def err_target_unsupported_arch
+ : Error<"the target architecture '%0' is not supported by the target '%1'">;
+
+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 err_drv_conflicting_deployment_targets : Error<
+ "conflicting deployment targets, both '%0' and '%1' are present in environment">;
+def err_drv_objc_gc_arr : Error<
+ "cannot specify both '-fobjc-arc' and '%0'">;
+def err_arc_unsupported_on_runtime : Error<
+ "-fobjc-arc is not supported on platforms using the legacy runtime">;
+def err_arc_unsupported_on_toolchain : Error< // feel free to generalize this
+ "-fobjc-arc is not supported on versions of OS X prior to 10.6">;
+def err_objc_weak_with_gc : Error<
+ "-fobjc-weak is not supported in Objective-C garbage collection">;
+def err_objc_weak_unsupported : Error<
+ "-fobjc-weak is not supported on the current deployment target">;
+def err_drv_mg_requires_m_or_mm : Error<
+ "option '-MG' requires '-M' or '-MM'">;
+def err_drv_unknown_objc_runtime : Error<
+ "unknown or ill-formed Objective-C runtime '%0'">;
+def err_drv_emit_llvm_link : Error<
+ "-emit-llvm cannot be used when linking">;
+def err_drv_optimization_remark_pattern : Error<
+ "%0 in '%1'">;
+def err_drv_no_neon_modifier : Error<"[no]neon is not accepted as modifier, please use [no]simd instead">;
+def err_drv_invalid_omp_target : Error<"OpenMP target is invalid: '%0'">;
+def err_drv_omp_host_ir_file_not_found : Error<
+ "The provided host compiler IR file '%0' is required to generate code for OpenMP target regions but cannot be found.">;
+
+def warn_O4_is_O3 : Warning<"-O4 is equivalent to -O3">, InGroup<Deprecated>;
+def warn_drv_lto_libpath : Warning<"libLTO.dylib relative to clang installed dir not found; using 'ld' default search path instead">,
+ InGroup<LibLTO>;
+def warn_drv_optimization_value : Warning<"optimization level '%0' is not supported; using '%1%2' instead">,
+ InGroup<InvalidCommandLineArgument>;
+def warn_ignored_gcc_optimization : Warning<"optimization flag '%0' is not supported">,
+ InGroup<IgnoredOptimizationArgument>;
+def warn_c_kext : Warning<
+ "ignoring -fapple-kext which is valid for C++ and Objective-C++ only">;
+def warn_drv_input_file_unused : Warning<
+ "%0: '%1' input unused%select{ when '%3' is present|}2">,
+ InGroup<UnusedCommandLineArgument>;
+def warn_drv_input_file_unused_by_cpp : Warning<
+ "%0: '%1' input unused in cpp mode">,
+ InGroup<UnusedCommandLineArgument>;
+def warn_drv_preprocessed_input_file_unused : Warning<
+ "%0: previously preprocessed input%select{ unused when '%2' is present|}1">,
+ InGroup<UnusedCommandLineArgument>;
+def warn_drv_unused_argument : Warning<
+ "argument unused during compilation: '%0'">,
+ InGroup<UnusedCommandLineArgument>;
+def warn_drv_empty_joined_argument : Warning<
+ "joined argument expects additional value: '%0'">,
+ InGroup<UnusedCommandLineArgument>;
+def warn_drv_clang_unsupported : Warning<
+ "the clang compiler does not support '%0'">;
+def warn_drv_deprecated_arg : Warning<
+ "argument '%0' is deprecated, use '%1' instead">, InGroup<Deprecated>;
+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_overriding_flag_option : Warning<
+ "overriding '%0' option with '%1'">,
+ InGroup<DiagGroup<"overriding-t-option">>;
+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'">;
+def warn_missing_sysroot : Warning<"no such sysroot directory: '%0'">,
+ InGroup<DiagGroup<"missing-sysroot">>;
+def warn_debug_compression_unavailable : Warning<"cannot compress debug sections (zlib not installed)">,
+ InGroup<DiagGroup<"debug-compression-unavailable">>;
+def warn_drv_enabling_rtti_with_exceptions : Warning<
+ "implicitly enabling rtti for exception handling">,
+ InGroup<DiagGroup<"rtti-for-exceptions">>;
+def warn_drv_disabling_vptr_no_rtti_default : Warning<
+ "implicitly disabling vptr sanitizer because rtti wasn't enabled">,
+ InGroup<DiagGroup<"auto-disable-vptr-sanitizer">>;
+
+def note_drv_command_failed_diag_msg : Note<
+ "diagnostic msg: %0">;
+def note_drv_t_option_is_global : Note<
+ "The last /TC or /TP option takes precedence over earlier instances">;
+def note_drv_address_sanitizer_debug_runtime : Note<
+ "AddressSanitizer doesn't support linking with debug runtime libraries yet">;
+
+def err_analyzer_config_no_value : Error<
+ "analyzer-config option '%0' has a key but no value">;
+def err_analyzer_config_multiple_values : Error<
+ "analyzer-config option '%0' should contain only one '='">;
+
+def err_drv_modules_validate_once_requires_timestamp : Error<
+ "option '-fmodules-validate-once-per-build-session' requires "
+ "'-fbuild-session-timestamp=<seconds since Epoch>' or '-fbuild-session-file=<file>'">;
+
+def err_test_module_file_extension_format : Error<
+ "-ftest-module-file-extension argument '%0' is not of the required form "
+ "'blockname:major:minor:hashed:user info'">;
+
+def warn_drv_invoking_fallback : Warning<"falling back to %0">,
+ InGroup<Fallback>;
+
+def warn_target_unsupported_nan2008 : Warning<
+ "ignoring '-mnan=2008' option because the '%0' architecture does not support it">,
+ InGroup<UnsupportedNan>;
+def warn_target_unsupported_nanlegacy : Warning<
+ "ignoring '-mnan=legacy' option because the '%0' architecture does not support it">,
+ InGroup<UnsupportedNan>;
+
+def warn_drv_unable_to_find_directory_expected : Warning<
+ "unable to find %0 directory, expected to be in '%1'">,
+ InGroup<InvalidOrNonExistentDirectory>, DefaultIgnore;
+
+def warn_drv_ps4_force_pic : Warning<
+ "option '%0' was ignored by the PS4 toolchain, using '-fPIC'">,
+ InGroup<OptionIgnored>;
+
+def warn_drv_ps4_sdk_dir : Warning<
+ "environment variable SCE_PS4_SDK_DIR is set, but points to invalid or nonexistent directory '%0'">,
+ InGroup<InvalidOrNonExistentDirectory>;
+
+def err_drv_unsupported_linker : Error<"unsupported value '%0' for -linker option">;
+}
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..033834b
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticFrontendKinds.td
@@ -0,0 +1,219 @@
+//==--- 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.
+//
+//===----------------------------------------------------------------------===//
+
+class BackendInfo : CatBackend, ShowInSystemHeader;
+
+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: %0">;
+def err_fe_error_backend : Error<"error in backend: %0">, DefaultFatal;
+
+def err_fe_inline_asm : Error<"%0">, CatInlineAsm;
+def warn_fe_inline_asm : Warning<"%0">, CatInlineAsm, InGroup<BackendInlineAsm>;
+def note_fe_inline_asm : Note<"%0">, CatInlineAsm;
+def note_fe_inline_asm_here : Note<"instantiated into assembly here">;
+def err_fe_cannot_link_module : Error<"cannot link module '%0': %1">,
+ DefaultFatal;
+
+def warn_fe_frame_larger_than : Warning<"stack frame size of %0 bytes in %q1">,
+ BackendInfo, InGroup<BackendFrameLargerThanEQ>;
+def warn_fe_backend_frame_larger_than: Warning<"%0">,
+ BackendInfo, InGroup<BackendFrameLargerThanEQ>;
+def err_fe_backend_frame_larger_than: Error<"%0">, BackendInfo;
+def note_fe_backend_frame_larger_than: Note<"%0">, BackendInfo;
+
+def warn_fe_backend_plugin: Warning<"%0">, BackendInfo, InGroup<BackendPlugin>;
+def err_fe_backend_plugin: Error<"%0">, BackendInfo;
+def remark_fe_backend_plugin: Remark<"%0">, BackendInfo, InGroup<RemarkBackendPlugin>;
+def note_fe_backend_plugin: Note<"%0">, BackendInfo;
+
+def warn_fe_override_module : Warning<
+ "overriding the module target triple with %0">,
+ InGroup<DiagGroup<"override-module">>;
+
+def remark_fe_backend_optimization_remark : Remark<"%0">, BackendInfo,
+ InGroup<BackendOptimizationRemark>;
+def remark_fe_backend_optimization_remark_missed : Remark<"%0">, BackendInfo,
+ InGroup<BackendOptimizationRemarkMissed>;
+def remark_fe_backend_optimization_remark_analysis : Remark<"%0">, BackendInfo,
+ InGroup<BackendOptimizationRemarkAnalysis>;
+def remark_fe_backend_optimization_remark_analysis_fpcommute : Remark<"%0; "
+ "allow reordering by specifying '#pragma clang loop vectorize(enable)' "
+ "before the loop or by providing the compiler option '-ffast-math'.">,
+ BackendInfo, InGroup<BackendOptimizationRemarkAnalysis>;
+def remark_fe_backend_optimization_remark_analysis_aliasing : Remark<"%0; "
+ "allow reordering by specifying '#pragma clang loop vectorize(enable)' "
+ "before the loop. If the arrays will always be independent specify "
+ "'#pragma clang loop vectorize(assume_safety)' before the loop or provide "
+ "the '__restrict__' qualifier with the independent array arguments. "
+ "Erroneous results will occur if these options are incorrectly applied!">,
+ BackendInfo, InGroup<BackendOptimizationRemarkAnalysis>;
+def warn_fe_backend_optimization_failure : Warning<"%0">, BackendInfo,
+ InGroup<BackendOptimizationFailure>, DefaultWarn;
+def note_fe_backend_optimization_remark_invalid_loc : Note<"could "
+ "not determine the original source location for %0:%1:%2">;
+
+def remark_sanitize_address_insert_extra_padding_accepted : Remark<
+ "-fsanitize-address-field-padding applied to %0">, ShowInSystemHeader,
+ InGroup<SanitizeAddressRemarks>;
+def remark_sanitize_address_insert_extra_padding_rejected : Remark<
+ "-fsanitize-address-field-padding ignored for %0 because it "
+ "%select{is not C++|is packed|is a union|is trivially copyable|"
+ "has trivial destructor|is standard layout|is in a blacklisted file|"
+ "is blacklisted}1">, ShowInSystemHeader,
+ InGroup<SanitizeAddressRemarks>;
+
+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_dependency_file_requires_MT : Error<
+ "-dependency-file requires at least one -MT or -MQ option">;
+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_open_output : Error<
+ "unable to open output 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 warn_fe_cc_log_diagnostics_failure : Warning<
+ "unable to open CC_LOG_DIAGNOSTICS file: %0 (using stderr)">;
+def err_fe_no_pch_in_dir : Error<
+ "no suitable precompiled header file found in directory '%0'">;
+def err_fe_action_not_available : Error<
+ "action %0 not compiled in">;
+
+def warn_fe_serialized_diag_merge_failure : Warning<
+ "unable to merge a subprocess's serialized diagnostics">,
+ InGroup<SerializedDiagnostics>;
+def warn_fe_serialized_diag_failure : Warning<
+ "unable to open file %0 for serializing diagnostics (%1)">,
+ InGroup<SerializedDiagnostics>;
+
+def err_verify_missing_line : Error<
+ "missing or invalid line number following '@' in expected %0">;
+def err_verify_missing_file : Error<
+ "file '%0' could not be located in expected %1">;
+def err_verify_invalid_range : Error<
+ "invalid range following '-' in expected %0">;
+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_missing_regex : Error<
+ "cannot find start of regex ('{{') in %0">;
+def err_verify_inconsistent_diags : Error<
+ "'%0' diagnostics %select{expected|seen}1 but not %select{seen|expected}1: "
+ "%2">;
+def err_verify_invalid_no_diags : Error<
+ "%select{expected|'expected-no-diagnostics'}0 directive cannot follow "
+ "%select{'expected-no-diagnostics' directive|other expected directives}0">;
+def err_verify_no_directives : Error<
+ "no expected directives found: consider use of 'expected-no-diagnostics'">;
+
+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 warn_fixit_no_changes : Note<
+ "FIX-IT detected errors it could not fix; no output will be generated">;
+
+// PCH reader
+def err_relocatable_without_isysroot : Error<
+ "must specify system root with -isysroot when building a relocatable "
+ "PCH file">;
+
+def warn_unknown_diag_option : Warning<
+ "unknown %select{warning|remark}0 option '%1'%select{|; did you mean '%3'?}2">,
+ InGroup<UnknownWarningOption>;
+def warn_unknown_warning_specifier : Warning<
+ "unknown %0 warning specifier: '%1'">,
+ InGroup<UnknownWarningOption>;
+
+def err_unknown_analyzer_checker : Error<
+ "no analyzer checkers are associated with '%0'">;
+def note_suggest_disabling_all_checkers : Note<
+ "use -analyzer-disable-all-checks to disable all static analyzer checkers">;
+
+def warn_incompatible_analyzer_plugin_api : Warning<
+ "checker plugin '%0' is not compatible with this version of the analyzer">,
+ InGroup<DiagGroup<"analyzer-incompatible-plugin"> >;
+def note_incompatible_analyzer_plugin_api : Note<
+ "current API version is '%0', but plugin was compiled with version '%1'">;
+
+def warn_module_config_mismatch : Warning<
+ "module file %0 cannot be loaded due to a configuration mismatch with the current "
+ "compilation">, InGroup<DiagGroup<"module-file-config-mismatch">>, DefaultError;
+def err_module_map_not_found : Error<"module map file '%0' not found">,
+ DefaultFatal;
+def err_missing_module_name : Error<
+ "no module name provided; specify one with -fmodule-name=">,
+ DefaultFatal;
+def err_missing_module : Error<
+ "no module named '%0' declared in module map file '%1'">, DefaultFatal;
+def err_no_submodule : Error<"no submodule named %0 in module '%1'">;
+def err_no_submodule_suggest : Error<
+ "no submodule named %0 in module '%1'; did you mean '%2'?">;
+def warn_missing_submodule : Warning<"missing submodule '%0'">,
+ InGroup<IncompleteUmbrella>;
+def err_module_cannot_create_includes : Error<
+ "cannot create includes file for module %0: %1">;
+def warn_module_config_macro_undef : Warning<
+ "%select{definition|#undef}0 of configuration macro '%1' has no effect on "
+ "the import of '%2'; pass '%select{-D%1=...|-U%1}0' on the command line "
+ "to configure the module">,
+ InGroup<ConfigMacros>;
+def note_module_def_undef_here : Note<
+ "macro was %select{defined|#undef'd}0 here">;
+def remark_module_build : Remark<"building module '%0' as '%1'">,
+ InGroup<ModuleBuild>;
+def remark_module_build_done : Remark<"finished building module '%0'">,
+ InGroup<ModuleBuild>;
+def err_modules_embed_file_not_found :
+ Error<"file '%0' specified by '-fmodules-embed-file=' not found">,
+ DefaultFatal;
+
+def err_test_module_file_extension_version : Error<
+ "test module file extension '%0' has different version (%1.%2) than expected "
+ "(%3.%4)">;
+
+def err_conflicting_module_names : Error<
+ "conflicting module names specified: '-fmodule-name=%0' and "
+ "'-fmodule-implementation-of %1'">;
+
+def err_missing_vfs_overlay_file : Error<
+ "virtual filesystem overlay file '%0' not found">, DefaultFatal;
+def err_invalid_vfs_overlay : Error<
+ "invalid virtual filesystem overlay file '%0'">, DefaultFatal;
+}
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..8e5f57d
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticGroups.td
@@ -0,0 +1,848 @@
+//==--- 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 AbsoluteValue : DiagGroup<"absolute-value">;
+def AddressOfTemporary : DiagGroup<"address-of-temporary">;
+def : DiagGroup<"aggregate-return">;
+def GNUAlignofExpression : DiagGroup<"gnu-alignof-expression">;
+def AmbigMemberTemplate : DiagGroup<"ambiguous-member-template">;
+def GNUAnonymousStruct : DiagGroup<"gnu-anonymous-struct">;
+def GNUAutoType : DiagGroup<"gnu-auto-type">;
+def ArrayBounds : DiagGroup<"array-bounds">;
+def ArrayBoundsPointerArithmetic : DiagGroup<"array-bounds-pointer-arithmetic">;
+def Availability : DiagGroup<"availability">;
+def Section : DiagGroup<"section">;
+def AutoImport : DiagGroup<"auto-import">;
+def CXX14BinaryLiteral : DiagGroup<"c++14-binary-literal">;
+def GNUBinaryLiteral : DiagGroup<"gnu-binary-literal">;
+def GNUCompoundLiteralInitializer : DiagGroup<"gnu-compound-literal-initializer">;
+def BitFieldConstantConversion : DiagGroup<"bitfield-constant-conversion">;
+def BitFieldWidth : DiagGroup<"bitfield-width">;
+def ConstantConversion :
+ DiagGroup<"constant-conversion", [ BitFieldConstantConversion ] >;
+def LiteralConversion : DiagGroup<"literal-conversion">;
+def StringConversion : DiagGroup<"string-conversion">;
+def SignConversion : DiagGroup<"sign-conversion">;
+def PointerBoolConversion : DiagGroup<"pointer-bool-conversion">;
+def UndefinedBoolConversion : DiagGroup<"undefined-bool-conversion">;
+def BoolConversion : DiagGroup<"bool-conversion", [PointerBoolConversion,
+ UndefinedBoolConversion]>;
+def IntConversion : DiagGroup<"int-conversion">;
+def EnumConversion : DiagGroup<"enum-conversion">;
+def FloatConversion : DiagGroup<"float-conversion">;
+def DoublePromotion : DiagGroup<"double-promotion">;
+def EnumTooLarge : DiagGroup<"enum-too-large">;
+def UnsupportedNan : DiagGroup<"unsupported-nan">;
+def NonLiteralNullConversion : DiagGroup<"non-literal-null-conversion">;
+def NullConversion : DiagGroup<"null-conversion">;
+def ImplicitConversionFloatingPointToBool :
+ DiagGroup<"implicit-conversion-floating-point-to-bool">;
+def ObjCLiteralConversion : DiagGroup<"objc-literal-conversion">;
+def BadArrayNewLength : DiagGroup<"bad-array-new-length">;
+def MacroRedefined : DiagGroup<"macro-redefined">;
+def BuiltinMacroRedefined : DiagGroup<"builtin-macro-redefined">;
+def BuiltinRequiresHeader : DiagGroup<"builtin-requires-header">;
+def C99Compat : DiagGroup<"c99-compat">;
+def CXXCompat: DiagGroup<"c++-compat">;
+def ExternCCompat : DiagGroup<"extern-c-compat">;
+def KeywordCompat : DiagGroup<"keyword-compat">;
+def GNUCaseRange : DiagGroup<"gnu-case-range">;
+def CastAlign : DiagGroup<"cast-align">;
+def CastQual : DiagGroup<"cast-qual">;
+def : DiagGroup<"char-align">;
+def Comment : DiagGroup<"comment">;
+def GNUComplexInteger : DiagGroup<"gnu-complex-integer">;
+def GNUConditionalOmittedOperand : DiagGroup<"gnu-conditional-omitted-operand">;
+def ConfigMacros : DiagGroup<"config-macros">;
+def : DiagGroup<"ctor-dtor-privacy">;
+def GNUDesignator : DiagGroup<"gnu-designator">;
+def GNUStringLiteralOperatorTemplate :
+ DiagGroup<"gnu-string-literal-operator-template">;
+
+def DeleteIncomplete : DiagGroup<"delete-incomplete">;
+def DeleteNonVirtualDtor : DiagGroup<"delete-non-virtual-dtor">;
+def AbstractFinalClass : DiagGroup<"abstract-final-class">;
+
+def CXX11CompatDeprecatedWritableStr :
+ DiagGroup<"c++11-compat-deprecated-writable-strings">;
+
+def DeprecatedAttributes : DiagGroup<"deprecated-attributes">;
+def DeprecatedDeclarations : DiagGroup<"deprecated-declarations">;
+def UnavailableDeclarations : DiagGroup<"unavailable-declarations">;
+def PartialAvailability : DiagGroup<"partial-availability">;
+def DeprecatedImplementations :DiagGroup<"deprecated-implementations">;
+def DeprecatedIncrementBool : DiagGroup<"deprecated-increment-bool">;
+def DeprecatedRegister : DiagGroup<"deprecated-register">;
+def DeprecatedWritableStr : DiagGroup<"deprecated-writable-strings",
+ [CXX11CompatDeprecatedWritableStr]>;
+// FIXME: Why is DeprecatedImplementations not in this group?
+def Deprecated : DiagGroup<"deprecated", [DeprecatedAttributes,
+ DeprecatedDeclarations,
+ DeprecatedIncrementBool,
+ DeprecatedRegister,
+ DeprecatedWritableStr]>,
+ DiagCategory<"Deprecations">;
+
+def LibLTO : DiagGroup<"liblto">;
+def : DiagGroup<"disabled-optimization">;
+def : DiagGroup<"discard-qual">;
+def : DiagGroup<"div-by-zero">;
+
+def DocumentationHTML : DiagGroup<"documentation-html">;
+def DocumentationUnknownCommand : DiagGroup<"documentation-unknown-command">;
+def DocumentationPedantic : DiagGroup<"documentation-pedantic",
+ [DocumentationUnknownCommand]>;
+def DocumentationDeprecatedSync : DiagGroup<"documentation-deprecated-sync">;
+def Documentation : DiagGroup<"documentation",
+ [DocumentationHTML,
+ DocumentationDeprecatedSync]>;
+
+def EmptyBody : DiagGroup<"empty-body">;
+def Exceptions : DiagGroup<"exceptions">;
+
+def GNUEmptyInitializer : DiagGroup<"gnu-empty-initializer">;
+def GNUEmptyStruct : DiagGroup<"gnu-empty-struct">;
+def ExtraTokens : DiagGroup<"extra-tokens">;
+def CXX11ExtraSemi : DiagGroup<"c++11-extra-semi">;
+def ExtraSemi : DiagGroup<"extra-semi", [CXX11ExtraSemi]>;
+
+def GNUFlexibleArrayInitializer : DiagGroup<"gnu-flexible-array-initializer">;
+def GNUFlexibleArrayUnionMember : DiagGroup<"gnu-flexible-array-union-member">;
+def GNUFoldingConstant : DiagGroup<"gnu-folding-constant">;
+def FormatExtraArgs : DiagGroup<"format-extra-args">;
+def FormatZeroLength : DiagGroup<"format-zero-length">;
+
+// Warnings for C++1y code which is not compatible with prior C++ standards.
+def CXXPre14Compat : DiagGroup<"c++98-c++11-compat">;
+def CXXPre14CompatPedantic : DiagGroup<"c++98-c++11-compat-pedantic",
+ [CXXPre14Compat]>;
+def CXXPre1zCompat : DiagGroup<"c++98-c++11-c++14-compat">;
+def CXXPre1zCompatPedantic : DiagGroup<"c++98-c++11-c++14-compat-pedantic",
+ [CXXPre1zCompat]>;
+
+def CXX98CompatBindToTemporaryCopy :
+ DiagGroup<"c++98-compat-bind-to-temporary-copy">;
+def CXX98CompatLocalTypeTemplateArgs :
+ DiagGroup<"c++98-compat-local-type-template-args">;
+def CXX98CompatUnnamedTypeTemplateArgs :
+ DiagGroup<"c++98-compat-unnamed-type-template-args">;
+
+def CXX98Compat : DiagGroup<"c++98-compat",
+ [CXX98CompatLocalTypeTemplateArgs,
+ CXX98CompatUnnamedTypeTemplateArgs,
+ CXXPre14Compat,
+ CXXPre1zCompat]>;
+// Warnings for C++11 features which are Extensions in C++98 mode.
+def CXX98CompatPedantic : DiagGroup<"c++98-compat-pedantic",
+ [CXX98Compat,
+ CXX98CompatBindToTemporaryCopy,
+ CXXPre14CompatPedantic,
+ CXXPre1zCompatPedantic]>;
+
+def CXX11Narrowing : DiagGroup<"c++11-narrowing">;
+
+def CXX11WarnOverrideMethod : DiagGroup<"inconsistent-missing-override">;
+
+// Original name of this warning in Clang
+def : DiagGroup<"c++0x-narrowing", [CXX11Narrowing]>;
+
+// Name of this warning in GCC
+def : DiagGroup<"narrowing", [CXX11Narrowing]>;
+
+def CXX11CompatReservedUserDefinedLiteral :
+ DiagGroup<"c++11-compat-reserved-user-defined-literal">;
+def ReservedUserDefinedLiteral :
+ DiagGroup<"reserved-user-defined-literal",
+ [CXX11CompatReservedUserDefinedLiteral]>;
+
+def CXX11Compat : DiagGroup<"c++11-compat",
+ [CXX11Narrowing,
+ CXX11CompatReservedUserDefinedLiteral,
+ CXX11CompatDeprecatedWritableStr,
+ CXXPre14Compat,
+ CXXPre1zCompat]>;
+def : DiagGroup<"c++0x-compat", [CXX11Compat]>;
+def CXX11CompatPedantic : DiagGroup<"c++11-compat-pedantic",
+ [CXXPre14CompatPedantic,
+ CXXPre1zCompatPedantic]>;
+
+def CXX14Compat : DiagGroup<"c++14-compat", [CXXPre1zCompat]>;
+def CXX14CompatPedantic : DiagGroup<"c++14-compat-pedantic",
+ [CXXPre1zCompatPedantic]>;
+
+def CXX1zCompat : DiagGroup<"c++1z-compat", [DeprecatedRegister,
+ DeprecatedIncrementBool]>;
+
+def : DiagGroup<"effc++">;
+def DivZero : DiagGroup<"division-by-zero">;
+def ExitTimeDestructors : DiagGroup<"exit-time-destructors">;
+def FlexibleArrayExtensions : DiagGroup<"flexible-array-extensions">;
+def FourByteMultiChar : DiagGroup<"four-char-constants">;
+def GlobalConstructors : DiagGroup<"global-constructors">;
+def BitwiseOpParentheses: DiagGroup<"bitwise-op-parentheses">;
+def LogicalOpParentheses: DiagGroup<"logical-op-parentheses">;
+def LogicalNotParentheses: DiagGroup<"logical-not-parentheses">;
+def ShiftOpParentheses: DiagGroup<"shift-op-parentheses">;
+def OverloadedShiftOpParentheses: DiagGroup<"overloaded-shift-op-parentheses">;
+def DanglingElse: DiagGroup<"dangling-else">;
+def DanglingField : DiagGroup<"dangling-field">;
+def DistributedObjectModifiers : DiagGroup<"distributed-object-modifiers">;
+def FlagEnum : DiagGroup<"flag-enum">;
+def IncrementBool : DiagGroup<"increment-bool", [DeprecatedIncrementBool]>;
+def InfiniteRecursion : DiagGroup<"infinite-recursion">;
+def GNUImaginaryConstant : DiagGroup<"gnu-imaginary-constant">;
+def IgnoredQualifiers : DiagGroup<"ignored-qualifiers">;
+def : DiagGroup<"import">;
+def GNUIncludeNext : DiagGroup<"gnu-include-next">;
+def IncompatibleMSStruct : DiagGroup<"incompatible-ms-struct">;
+def IncompatiblePointerTypesDiscardsQualifiers
+ : DiagGroup<"incompatible-pointer-types-discards-qualifiers">;
+def IncompatiblePointerTypes
+ : DiagGroup<"incompatible-pointer-types",
+ [IncompatiblePointerTypesDiscardsQualifiers]>;
+def IncompleteUmbrella : DiagGroup<"incomplete-umbrella">;
+def NonModularIncludeInFrameworkModule
+ : DiagGroup<"non-modular-include-in-framework-module">;
+def NonModularIncludeInModule : DiagGroup<"non-modular-include-in-module",
+ [NonModularIncludeInFrameworkModule]>;
+def IncompleteModule : DiagGroup<"incomplete-module",
+ [IncompleteUmbrella, NonModularIncludeInModule]>;
+
+def CXX11InlineNamespace : DiagGroup<"c++11-inline-namespace">;
+def InvalidNoreturn : DiagGroup<"invalid-noreturn">;
+def InvalidSourceEncoding : DiagGroup<"invalid-source-encoding">;
+def KNRPromotedParameter : DiagGroup<"knr-promoted-parameter">;
+def : DiagGroup<"init-self">;
+def : DiagGroup<"inline">;
+def : DiagGroup<"invalid-pch">;
+def GNULabelsAsValue : DiagGroup<"gnu-label-as-value">;
+def LiteralRange : DiagGroup<"literal-range">;
+def LocalTypeTemplateArgs : DiagGroup<"local-type-template-args",
+ [CXX98CompatLocalTypeTemplateArgs]>;
+def RangeLoopAnalysis : DiagGroup<"range-loop-analysis">;
+def ForLoopAnalysis : DiagGroup<"for-loop-analysis">;
+def LoopAnalysis : DiagGroup<"loop-analysis", [ForLoopAnalysis,
+ RangeLoopAnalysis]>;
+def MalformedWarningCheck : DiagGroup<"malformed-warning-check">;
+def Main : DiagGroup<"main">;
+def MainReturnType : DiagGroup<"main-return-type">;
+def MissingBraces : DiagGroup<"missing-braces">;
+def MissingDeclarations: DiagGroup<"missing-declarations">;
+def : DiagGroup<"missing-format-attribute">;
+def : DiagGroup<"missing-include-dirs">;
+def MissingNoreturn : DiagGroup<"missing-noreturn">;
+def MultiChar : DiagGroup<"multichar">;
+def : DiagGroup<"nested-externs">;
+def CXX11LongLong : DiagGroup<"c++11-long-long">;
+def LongLong : DiagGroup<"long-long", [CXX11LongLong]>;
+def ImplicitlyUnsignedLiteral : DiagGroup<"implicitly-unsigned-literal">;
+def MethodSignatures : DiagGroup<"method-signatures">;
+def MismatchedParameterTypes : DiagGroup<"mismatched-parameter-types">;
+def MismatchedReturnTypes : DiagGroup<"mismatched-return-types">;
+def MismatchedTags : DiagGroup<"mismatched-tags">;
+def MissingFieldInitializers : DiagGroup<"missing-field-initializers">;
+def ModuleBuild : DiagGroup<"module-build">;
+def ModuleConflict : DiagGroup<"module-conflict">;
+def ModuleFileExtension : DiagGroup<"module-file-extension">;
+def NewlineEOF : DiagGroup<"newline-eof">;
+def Nullability : DiagGroup<"nullability">;
+def NullabilityDeclSpec : DiagGroup<"nullability-declspec">;
+def NullableToNonNullConversion : DiagGroup<"nullable-to-nonnull-conversion">;
+def NullabilityCompleteness : DiagGroup<"nullability-completeness">;
+def NullArithmetic : DiagGroup<"null-arithmetic">;
+def NullCharacter : DiagGroup<"null-character">;
+def NullDereference : DiagGroup<"null-dereference">;
+def InitializerOverrides : DiagGroup<"initializer-overrides">;
+def NonNull : DiagGroup<"nonnull">;
+def NonPODVarargs : DiagGroup<"non-pod-varargs">;
+def ClassVarargs : DiagGroup<"class-varargs", [NonPODVarargs]>;
+def : DiagGroup<"nonportable-cfstrings">;
+def NonVirtualDtor : DiagGroup<"non-virtual-dtor">;
+def OveralignedType : DiagGroup<"over-aligned">;
+def OldStyleCast : DiagGroup<"old-style-cast">;
+def : DiagGroup<"old-style-definition">;
+def OutOfLineDeclaration : DiagGroup<"out-of-line-declaration">;
+def : DiagGroup<"overflow">;
+def ForwardClassReceiver : DiagGroup<"receiver-forward-class">;
+def MethodAccess : DiagGroup<"objc-method-access">;
+def ObjCReceiver : DiagGroup<"receiver-expr">;
+// FIXME: Remove this when Xcode removes the warning setting.
+def : DiagGroup<"receiver-is-weak">;
+def OperatorNewReturnsNull : DiagGroup<"new-returns-null">;
+def OverlengthStrings : DiagGroup<"overlength-strings">;
+def OverloadedVirtual : DiagGroup<"overloaded-virtual">;
+def PrivateExtern : DiagGroup<"private-extern">;
+def SelTypeCast : DiagGroup<"cast-of-sel-type">;
+def FunctionDefInObjCContainer : DiagGroup<"function-def-in-objc-container">;
+def BadFunctionCast : DiagGroup<"bad-function-cast">;
+def ObjCPropertyImpl : DiagGroup<"objc-property-implementation">;
+def ObjCPropertyNoAttribute : DiagGroup<"objc-property-no-attribute">;
+def ObjCProtocolQualifiers : DiagGroup<"objc-protocol-qualifiers">;
+def ObjCMissingSuperCalls : DiagGroup<"objc-missing-super-calls">;
+def ObjCDesignatedInit : DiagGroup<"objc-designated-initializers">;
+def ObjCRetainBlockProperty : DiagGroup<"objc-noncopy-retain-block-property">;
+def ObjCReadonlyPropertyHasSetter : DiagGroup<"objc-readonly-with-setter-property">;
+def ObjCInvalidIBOutletProperty : DiagGroup<"invalid-iboutlet">;
+def ObjCRootClass : DiagGroup<"objc-root-class">;
+def ObjCPointerIntrospectPerformSelector : DiagGroup<"deprecated-objc-pointer-introspection-performSelector">;
+def ObjCPointerIntrospect : DiagGroup<"deprecated-objc-pointer-introspection", [ObjCPointerIntrospectPerformSelector]>;
+def ObjCMultipleMethodNames : DiagGroup<"objc-multiple-method-names">;
+def DeprecatedObjCIsaUsage : DiagGroup<"deprecated-objc-isa-usage">;
+def ExplicitInitializeCall : DiagGroup<"explicit-initialize-call">;
+def Packed : DiagGroup<"packed">;
+def Padded : DiagGroup<"padded">;
+def PessimizingMove : DiagGroup<"pessimizing-move">;
+def PointerArith : DiagGroup<"pointer-arith">;
+def PoundWarning : DiagGroup<"#warnings">;
+def PoundPragmaMessage : DiagGroup<"#pragma-messages">,
+ DiagCategory<"#pragma message Directive">;
+def : DiagGroup<"pointer-to-int-cast">;
+def : DiagGroup<"redundant-decls">;
+def RedeclaredClassMember : DiagGroup<"redeclared-class-member">;
+def GNURedeclaredEnum : DiagGroup<"gnu-redeclared-enum">;
+def RedundantMove : DiagGroup<"redundant-move">;
+def Register : DiagGroup<"register", [DeprecatedRegister]>;
+def ReturnStackAddress : DiagGroup<"return-stack-address">;
+def ReturnTypeCLinkage : DiagGroup<"return-type-c-linkage">;
+def ReturnType : DiagGroup<"return-type", [ReturnTypeCLinkage]>;
+def BindToTemporaryCopy : DiagGroup<"bind-to-temporary-copy",
+ [CXX98CompatBindToTemporaryCopy]>;
+def SelfAssignmentField : DiagGroup<"self-assign-field">;
+def SelfAssignment : DiagGroup<"self-assign", [SelfAssignmentField]>;
+def SelfMove : DiagGroup<"self-move">;
+def SemiBeforeMethodBody : DiagGroup<"semicolon-before-method-body">;
+def Sentinel : DiagGroup<"sentinel">;
+def MissingMethodReturnType : DiagGroup<"missing-method-return-type">;
+def Shadow : DiagGroup<"shadow">;
+def Shorten64To32 : 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 SizeofArrayArgument : DiagGroup<"sizeof-array-argument">;
+def SizeofArrayDecay : DiagGroup<"sizeof-array-decay">;
+def SizeofPointerMemaccess : DiagGroup<"sizeof-pointer-memaccess">;
+def StaticInInline : DiagGroup<"static-in-inline">;
+def StaticLocalInInline : DiagGroup<"static-local-in-inline">;
+def GNUStaticFloatInit : DiagGroup<"gnu-static-float-init">;
+def StaticFloatInit : DiagGroup<"static-float-init", [GNUStaticFloatInit]>;
+def GNUStatementExpression : DiagGroup<"gnu-statement-expression">;
+def StringCompare : DiagGroup<"string-compare">;
+def StringPlusInt : DiagGroup<"string-plus-int">;
+def StringPlusChar : DiagGroup<"string-plus-char">;
+def StrncatSize : DiagGroup<"strncat-size">;
+def TautologicalOutOfRangeCompare : DiagGroup<"tautological-constant-out-of-range-compare">;
+def TautologicalPointerCompare : DiagGroup<"tautological-pointer-compare">;
+def TautologicalOverlapCompare : DiagGroup<"tautological-overlap-compare">;
+def TautologicalUndefinedCompare : DiagGroup<"tautological-undefined-compare">;
+def TautologicalCompare : DiagGroup<"tautological-compare",
+ [TautologicalOutOfRangeCompare,
+ TautologicalPointerCompare,
+ TautologicalOverlapCompare,
+ TautologicalUndefinedCompare]>;
+def HeaderHygiene : DiagGroup<"header-hygiene">;
+def DuplicateDeclSpecifier : DiagGroup<"duplicate-decl-specifier">;
+def CompareDistinctPointerType : DiagGroup<"compare-distinct-pointer-types">;
+def GNUUnionCast : DiagGroup<"gnu-union-cast">;
+def GNUVariableSizedTypeNotAtEnd : DiagGroup<"gnu-variable-sized-type-not-at-end">;
+def Varargs : DiagGroup<"varargs">;
+
+def Unsequenced : DiagGroup<"unsequenced">;
+// GCC name for -Wunsequenced
+def : DiagGroup<"sequence-point", [Unsequenced]>;
+
+// Preprocessor warnings.
+def AmbiguousMacro : DiagGroup<"ambiguous-macro">;
+def KeywordAsMacro : DiagGroup<"keyword-macro">;
+def ReservedIdAsMacro : DiagGroup<"reserved-id-macro">;
+
+// 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 MethodDuplicate : DiagGroup<"duplicate-method-match">;
+def ObjCCStringFormat : DiagGroup<"cstring-format-directive">;
+def CoveredSwitchDefault : DiagGroup<"covered-switch-default">;
+def SwitchBool : DiagGroup<"switch-bool">;
+def SwitchEnum : DiagGroup<"switch-enum">;
+def Switch : DiagGroup<"switch">;
+def ImplicitFallthroughPerFunction :
+ DiagGroup<"implicit-fallthrough-per-function">;
+def ImplicitFallthrough : DiagGroup<"implicit-fallthrough",
+ [ImplicitFallthroughPerFunction]>;
+def InvalidPPToken : DiagGroup<"invalid-pp-token">;
+def Trigraphs : DiagGroup<"trigraphs">;
+
+def : DiagGroup<"type-limits">;
+def UndefinedReinterpretCast : DiagGroup<"undefined-reinterpret-cast">;
+def ReinterpretBaseClass : DiagGroup<"reinterpret-base-class">;
+def Unicode : DiagGroup<"unicode">;
+def UninitializedMaybe : DiagGroup<"conditional-uninitialized">;
+def UninitializedSometimes : DiagGroup<"sometimes-uninitialized">;
+def UninitializedStaticSelfInit : DiagGroup<"static-self-init">;
+def Uninitialized : DiagGroup<"uninitialized", [UninitializedSometimes,
+ UninitializedStaticSelfInit]>;
+def UnknownPragmas : DiagGroup<"unknown-pragmas">;
+def IgnoredPragmas : DiagGroup<"ignored-pragmas">;
+def Pragmas : DiagGroup<"pragmas", [UnknownPragmas, IgnoredPragmas]>;
+def UnknownWarningOption : DiagGroup<"unknown-warning-option">;
+def NSobjectAttribute : DiagGroup<"NSObject-attribute">;
+def IndependentClassAttribute : DiagGroup<"IndependentClass-attribute">;
+def UnknownAttributes : DiagGroup<"unknown-attributes">;
+def IgnoredAttributes : DiagGroup<"ignored-attributes">;
+def Attributes : DiagGroup<"attributes", [UnknownAttributes,
+ IgnoredAttributes]>;
+def UnknownSanitizers : DiagGroup<"unknown-sanitizers">;
+def UnnamedTypeTemplateArgs : DiagGroup<"unnamed-type-template-args",
+ [CXX98CompatUnnamedTypeTemplateArgs]>;
+def UnsupportedFriend : DiagGroup<"unsupported-friend">;
+def UnusedArgument : DiagGroup<"unused-argument">;
+def UnusedCommandLineArgument : DiagGroup<"unused-command-line-argument">;
+def IgnoredOptimizationArgument : DiagGroup<"ignored-optimization-argument">;
+def InvalidCommandLineArgument : DiagGroup<"invalid-command-line-argument",
+ [IgnoredOptimizationArgument]>;
+def UnusedComparison : DiagGroup<"unused-comparison">;
+def UnusedExceptionParameter : DiagGroup<"unused-exception-parameter">;
+def UnneededInternalDecl : DiagGroup<"unneeded-internal-declaration">;
+def UnneededMemberFunction : DiagGroup<"unneeded-member-function">;
+def UnusedPrivateField : DiagGroup<"unused-private-field">;
+def UnusedFunction : DiagGroup<"unused-function", [UnneededInternalDecl]>;
+def UnusedMemberFunction : DiagGroup<"unused-member-function",
+ [UnneededMemberFunction]>;
+def UnusedLabel : DiagGroup<"unused-label">;
+def UnusedParameter : DiagGroup<"unused-parameter">;
+def UnusedResult : DiagGroup<"unused-result">;
+def PotentiallyEvaluatedExpression : DiagGroup<"potentially-evaluated-expression">;
+def UnevaluatedExpression : DiagGroup<"unevaluated-expression",
+ [PotentiallyEvaluatedExpression]>;
+def UnusedValue : DiagGroup<"unused-value", [UnusedComparison, UnusedResult,
+ UnevaluatedExpression]>;
+def UnusedConstVariable : DiagGroup<"unused-const-variable">;
+def UnusedVariable : DiagGroup<"unused-variable",
+ [UnusedConstVariable]>;
+def UnusedLocalTypedef : DiagGroup<"unused-local-typedef">;
+def UnusedPropertyIvar : DiagGroup<"unused-property-ivar">;
+def UnusedGetterReturnValue : DiagGroup<"unused-getter-return-value">;
+def UsedButMarkedUnused : DiagGroup<"used-but-marked-unused">;
+def UserDefinedLiterals : DiagGroup<"user-defined-literals">;
+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 ARCUnsafeRetainedAssign : DiagGroup<"arc-unsafe-retained-assign">;
+def ARCRetainCycles : DiagGroup<"arc-retain-cycles">;
+def ARCNonPodMemAccess : DiagGroup<"arc-non-pod-memaccess">;
+def AutomaticReferenceCounting : DiagGroup<"arc",
+ [ARCUnsafeRetainedAssign,
+ ARCRetainCycles,
+ ARCNonPodMemAccess]>;
+def ARCRepeatedUseOfWeakMaybe : DiagGroup<"arc-maybe-repeated-use-of-weak">;
+def ARCRepeatedUseOfWeak : DiagGroup<"arc-repeated-use-of-weak",
+ [ARCRepeatedUseOfWeakMaybe]>;
+def ObjCBridge : DiagGroup<"bridge-cast">;
+
+def DeallocInCategory:DiagGroup<"dealloc-in-category">;
+def SelectorTypeMismatch : DiagGroup<"selector-type-mismatch">;
+def Selector : DiagGroup<"selector", [SelectorTypeMismatch]>;
+def Protocol : DiagGroup<"protocol">;
+def AtProtocol : DiagGroup<"at-protocol">;
+def PropertyAccessDotSyntax: DiagGroup<"property-access-dot-syntax">;
+def PropertyAttr : DiagGroup<"property-attribute-mismatch">;
+def SuperSubClassMismatch : DiagGroup<"super-class-method-mismatch">;
+def OverridingMethodMismatch : DiagGroup<"overriding-method-mismatch">;
+def VariadicMacros : DiagGroup<"variadic-macros">;
+def VectorConversion : DiagGroup<"vector-conversion">; // clang specific
+def VexingParse : DiagGroup<"vexing-parse">;
+def VLA : DiagGroup<"vla">;
+def VLAExtension : DiagGroup<"vla-extension">;
+def VolatileRegisterVar : DiagGroup<"volatile-register-var">;
+def Visibility : DiagGroup<"visibility">;
+def ZeroLengthArray : DiagGroup<"zero-length-array">;
+def GNUZeroLineDirective : DiagGroup<"gnu-zero-line-directive">;
+def GNUZeroVariadicMacroArguments : DiagGroup<"gnu-zero-variadic-macro-arguments">;
+def Fallback : DiagGroup<"fallback">;
+
+// This covers both the deprecated case (in C++98)
+// and the extension case (in C++11 onwards).
+def WritableStrings : DiagGroup<"writable-strings", [DeprecatedWritableStr]>;
+
+// GCC calls -Wdeprecated-writable-strings -Wwrite-strings.
+//
+// Bizarrely, this warning flag enables -fconst-strings in C. This is
+// GCC-compatible, but really weird.
+//
+// FIXME: Should this affect C++11 (where this is an error,
+// not just deprecated) or not?
+def GCCWriteStrings : DiagGroup<"write-strings" , [WritableStrings]>;
+
+def CharSubscript : DiagGroup<"char-subscripts">;
+def LargeByValueCopy : DiagGroup<"large-by-value-copy">;
+def DuplicateArgDecl : DiagGroup<"duplicate-method-arg">;
+
+// Unreachable code warning groups.
+//
+// The goal is make -Wunreachable-code on by default, in -Wall, or at
+// least actively used, with more noisy versions of the warning covered
+// under separate flags.
+//
+def UnreachableCodeLoopIncrement : DiagGroup<"unreachable-code-loop-increment">;
+def UnreachableCode : DiagGroup<"unreachable-code",
+ [UnreachableCodeLoopIncrement]>;
+def UnreachableCodeBreak : DiagGroup<"unreachable-code-break">;
+def UnreachableCodeReturn : DiagGroup<"unreachable-code-return">;
+def UnreachableCodeAggressive : DiagGroup<"unreachable-code-aggressive",
+ [UnreachableCode,
+ UnreachableCodeBreak,
+ UnreachableCodeReturn]>;
+
+// Aggregation warning settings.
+
+// Populate -Waddress with warnings from other groups.
+def : DiagGroup<"address", [PointerBoolConversion,
+ StringCompare,
+ TautologicalPointerCompare]>;
+
+// -Widiomatic-parentheses contains warnings about 'idiomatic'
+// missing parentheses; it is off by default. We do not include it
+// in -Wparentheses because most users who use -Wparentheses explicitly
+// do not want these warnings.
+def ParenthesesOnEquality : DiagGroup<"parentheses-equality">;
+def Parentheses : DiagGroup<"parentheses",
+ [LogicalOpParentheses,
+ LogicalNotParentheses,
+ BitwiseOpParentheses,
+ ShiftOpParentheses,
+ OverloadedShiftOpParentheses,
+ ParenthesesOnEquality,
+ DanglingElse]>;
+
+// -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
+// - __null-to-integer conversion warnings are on by default
+def Conversion : DiagGroup<"conversion",
+ [BoolConversion,
+ ConstantConversion,
+ EnumConversion,
+ FloatConversion,
+ Shorten64To32,
+ IntConversion,
+ LiteralConversion,
+ NonLiteralNullConversion, // (1-1)->pointer (etc)
+ NullConversion, // NULL->non-pointer
+ ObjCLiteralConversion,
+ SignConversion,
+ StringConversion]>,
+ DiagCategory<"Value Conversion Issue">;
+
+def Unused : DiagGroup<"unused",
+ [UnusedArgument, UnusedFunction, UnusedLabel,
+ // UnusedParameter, (matches GCC's behavior)
+ // UnusedMemberFunction, (clean-up llvm before enabling)
+ UnusedPrivateField, UnusedLocalTypedef,
+ UnusedValue, UnusedVariable, UnusedPropertyIvar]>,
+ DiagCategory<"Unused Entity Issue">;
+
+// Format settings.
+def FormatInvalidSpecifier : DiagGroup<"format-invalid-specifier">;
+def FormatSecurity : DiagGroup<"format-security">;
+def FormatNonStandard : DiagGroup<"format-non-iso">;
+def FormatY2K : DiagGroup<"format-y2k">;
+def FormatPedantic : DiagGroup<"format-pedantic">;
+def Format : DiagGroup<"format",
+ [FormatExtraArgs, FormatZeroLength, NonNull,
+ FormatSecurity, FormatY2K, FormatInvalidSpecifier]>,
+ DiagCategory<"Format String Issue">;
+def FormatNonLiteral : DiagGroup<"format-nonliteral">;
+def Format2 : DiagGroup<"format=2",
+ [FormatNonLiteral, FormatSecurity, FormatY2K]>;
+
+def TypeSafety : DiagGroup<"type-safety">;
+
+def IntToVoidPointerCast : DiagGroup<"int-to-void-pointer-cast">;
+def IntToPointerCast : DiagGroup<"int-to-pointer-cast",
+ [IntToVoidPointerCast]>;
+
+def Move : DiagGroup<"move", [PessimizingMove, RedundantMove, SelfMove]>;
+
+def Extra : DiagGroup<"extra", [
+ MissingFieldInitializers,
+ IgnoredQualifiers,
+ InitializerOverrides,
+ SemiBeforeMethodBody,
+ MissingMethodReturnType,
+ SignCompare,
+ UnusedParameter
+ ]>;
+
+def Most : DiagGroup<"most", [
+ CharSubscript,
+ Comment,
+ DeleteNonVirtualDtor,
+ Format,
+ Implicit,
+ InfiniteRecursion,
+ MismatchedTags,
+ MissingBraces,
+ Move,
+ MultiChar,
+ Reorder,
+ ReturnType,
+ SelfAssignment,
+ SelfMove,
+ SizeofArrayArgument,
+ SizeofArrayDecay,
+ StringPlusInt,
+ Trigraphs,
+ Uninitialized,
+ UnknownPragmas,
+ Unused,
+ VolatileRegisterVar,
+ ObjCMissingSuperCalls,
+ ObjCDesignatedInit,
+ OverloadedVirtual,
+ PrivateExtern,
+ SelTypeCast,
+ ExternCCompat
+ ]>;
+
+// Thread Safety warnings
+def ThreadSafetyAttributes : DiagGroup<"thread-safety-attributes">;
+def ThreadSafetyAnalysis : DiagGroup<"thread-safety-analysis">;
+def ThreadSafetyPrecise : DiagGroup<"thread-safety-precise">;
+def ThreadSafetyReference : DiagGroup<"thread-safety-reference">;
+def ThreadSafetyNegative : DiagGroup<"thread-safety-negative">;
+def ThreadSafety : DiagGroup<"thread-safety",
+ [ThreadSafetyAttributes,
+ ThreadSafetyAnalysis,
+ ThreadSafetyPrecise,
+ ThreadSafetyReference]>;
+def ThreadSafetyVerbose : DiagGroup<"thread-safety-verbose">;
+def ThreadSafetyBeta : DiagGroup<"thread-safety-beta">;
+
+// Uniqueness Analysis warnings
+def Consumed : DiagGroup<"consumed">;
+
+// Note that putting warnings in -Wall will not disable them by default. If a
+// warning should be active _only_ when -Wall is passed in, mark it as
+// DefaultIgnore in addition to putting it here.
+def All : DiagGroup<"all", [Most, Parentheses, Switch, SwitchBool]>;
+
+// Warnings that should be in clang-cl /w4.
+def : DiagGroup<"CL4", [All, Extra]>;
+
+// Warnings enabled by -pedantic. This is magically filled in by TableGen.
+def Pedantic : DiagGroup<"pedantic">;
+
+// Aliases.
+def : DiagGroup<"", [Extra]>; // -W = -Wextra
+def : DiagGroup<"endif-labels", [ExtraTokens]>; // -Wendif-labels=-Wextra-tokens
+def : DiagGroup<"comments", [Comment]>; // -Wcomments = -Wcomment
+def : DiagGroup<"conversion-null",
+ [NullConversion]>; // -Wconversion-null = -Wnull-conversion
+def : DiagGroup<"bool-conversions",
+ [BoolConversion]>; // -Wbool-conversions = -Wbool-conversion
+def : DiagGroup<"int-conversions",
+ [IntConversion]>; // -Wint-conversions = -Wint-conversion
+def : DiagGroup<"vector-conversions",
+ [VectorConversion]>; // -Wvector-conversions = -Wvector-conversion
+def : DiagGroup<"unused-local-typedefs", [UnusedLocalTypedef]>;
+ // -Wunused-local-typedefs = -Wunused-local-typedef
+
+// 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++11 features as extensions in
+// earlier C++ versions.
+def CXX11 : DiagGroup<"c++11-extensions", [CXX11ExtraSemi, CXX11InlineNamespace,
+ CXX11LongLong]>;
+
+// A warning group for warnings about using C++14 features as extensions in
+// earlier C++ versions.
+def CXX14 : DiagGroup<"c++14-extensions", [CXX14BinaryLiteral]>;
+
+// A warning group for warnings about using C++1z features as extensions in
+// earlier C++ versions.
+def CXX1z : DiagGroup<"c++1z-extensions">;
+
+def : DiagGroup<"c++0x-extensions", [CXX11]>;
+def : DiagGroup<"c++1y-extensions", [CXX14]>;
+
+def DelegatingCtorCycles :
+ DiagGroup<"delegating-ctor-cycles">;
+
+// A warning group for warnings about using C11 features as extensions.
+def C11 : DiagGroup<"c11-extensions">;
+
+// A warning group for warnings about using C99 features as extensions.
+def C99 : DiagGroup<"c99-extensions">;
+
+// A warning group for warnings about GCC extensions.
+def GNU : DiagGroup<"gnu", [GNUAlignofExpression, GNUAnonymousStruct,
+ GNUAutoType,
+ GNUBinaryLiteral, GNUCaseRange,
+ GNUComplexInteger, GNUCompoundLiteralInitializer,
+ GNUConditionalOmittedOperand, GNUDesignator,
+ GNUEmptyInitializer, GNUEmptyStruct,
+ VLAExtension, GNUFlexibleArrayInitializer,
+ GNUFlexibleArrayUnionMember, GNUFoldingConstant,
+ GNUImaginaryConstant, GNUIncludeNext,
+ GNULabelsAsValue,
+ RedeclaredClassMember, GNURedeclaredEnum,
+ GNUStatementExpression, GNUStaticFloatInit,
+ GNUStringLiteralOperatorTemplate,
+ GNUUnionCast, GNUVariableSizedTypeNotAtEnd,
+ ZeroLengthArray, GNUZeroLineDirective,
+ GNUZeroVariadicMacroArguments]>;
+// A warning group for warnings about code that clang accepts but gcc doesn't.
+def GccCompat : DiagGroup<"gcc-compat">;
+
+// Warnings for Microsoft extensions.
+def MicrosoftCharize : DiagGroup<"microsoft-charize">;
+def MicrosoftInclude : DiagGroup<"microsoft-include">;
+def MicrosoftCppMacro : DiagGroup<"microsoft-cpp-macro">;
+def MicrosoftFixedEnum : DiagGroup<"microsoft-fixed-enum">;
+def MicrosoftSealed : DiagGroup<"microsoft-sealed">;
+def MicrosoftUnqualifiedFriend : DiagGroup<"microsoft-unqualified-friend">;
+def MicrosoftExceptionSpec : DiagGroup<"microsoft-exception-spec">;
+def MicrosoftUsingDecl : DiagGroup<"microsoft-using-decl">;
+def MicrosoftMutableReference : DiagGroup<"microsoft-mutable-reference">;
+def MicrosoftPureDefinition : DiagGroup<"microsoft-pure-definition">;
+def MicrosoftUnionMemberReference : DiagGroup<
+ "microsoft-union-member-reference">;
+def MicrosoftExplicitConstructorCall : DiagGroup<
+ "microsoft-explicit-constructor-call">;
+def MicrosoftEnumValue : DiagGroup<"microsoft-enum-value">;
+def MicrosoftDefaultArgRedefinition :
+ DiagGroup<"microsoft-default-arg-redefinition">;
+def MicrosoftTemplate : DiagGroup<"microsoft-template">;
+def MicrosoftRedeclareStatic : DiagGroup<"microsoft-redeclare-static">;
+def MicrosoftEnumForwardReference :
+ DiagGroup<"microsoft-enum-forward-reference">;
+def MicrosoftGoto : DiagGroup<"microsoft-goto">;
+def MicrosoftFlexibleArray : DiagGroup<"microsoft-flexible-array">;
+def MicrosoftExtraQualification : DiagGroup<"microsoft-extra-qualification">;
+def MicrosoftCast : DiagGroup<"microsoft-cast">;
+def MicrosoftConstInit : DiagGroup<"microsoft-const-init">;
+def MicrosoftVoidPseudoDtor : DiagGroup<"microsoft-void-pseudo-dtor">;
+def MicrosoftAnonTag : DiagGroup<"microsoft-anon-tag">;
+def MicrosoftCommentPaste : DiagGroup<"microsoft-comment-paste">;
+def MicrosoftEndOfFile : DiagGroup<"microsoft-end-of-file">;
+// Aliases.
+def : DiagGroup<"msvc-include", [MicrosoftInclude]>;
+ // -Wmsvc-include = -Wmicrosoft-include
+
+// Warnings group for warnings about Microsoft extensions.
+def Microsoft : DiagGroup<"microsoft",
+ [MicrosoftCharize, MicrosoftInclude, MicrosoftCppMacro, MicrosoftFixedEnum,
+ MicrosoftSealed, MicrosoftUnqualifiedFriend, MicrosoftExceptionSpec,
+ MicrosoftUsingDecl, MicrosoftMutableReference, MicrosoftPureDefinition,
+ MicrosoftUnionMemberReference, MicrosoftExplicitConstructorCall,
+ MicrosoftEnumValue, MicrosoftDefaultArgRedefinition, MicrosoftTemplate,
+ MicrosoftRedeclareStatic, MicrosoftEnumForwardReference, MicrosoftGoto,
+ MicrosoftFlexibleArray, MicrosoftExtraQualification, MicrosoftCast,
+ MicrosoftConstInit, MicrosoftVoidPseudoDtor, MicrosoftAnonTag,
+ MicrosoftCommentPaste, MicrosoftEndOfFile]>;
+
+def ObjCNonUnifiedException : DiagGroup<"objc-nonunified-exceptions">;
+
+def ObjCProtocolMethodImpl : DiagGroup<"objc-protocol-method-implementation">;
+
+def ObjCNoPropertyAutoSynthesis : DiagGroup<"objc-property-synthesis">;
+
+// ObjC API warning groups.
+def ObjCRedundantLiteralUse : DiagGroup<"objc-redundant-literal-use">;
+def ObjCRedundantAPIUse : DiagGroup<"objc-redundant-api-use", [
+ ObjCRedundantLiteralUse
+ ]>;
+
+def ObjCCocoaAPI : DiagGroup<"objc-cocoa-api", [
+ ObjCRedundantAPIUse
+ ]>;
+
+def ObjCStringComparison : DiagGroup<"objc-string-compare">;
+def ObjCStringConcatenation : DiagGroup<"objc-string-concatenation">;
+def ObjCLiteralComparison : DiagGroup<"objc-literal-compare", [
+ ObjCStringComparison
+ ]>;
+
+// Inline ASM warnings.
+def ASMOperandWidths : DiagGroup<"asm-operand-widths">;
+def ASM : DiagGroup<"asm", [
+ ASMOperandWidths
+ ]>;
+
+// OpenMP warnings.
+def SourceUsesOpenMP : DiagGroup<"source-uses-openmp">;
+def OpenMPClauses : DiagGroup<"openmp-clauses">;
+def OpenMPLoopForm : DiagGroup<"openmp-loop-form">;
+
+// Backend warnings.
+def BackendInlineAsm : DiagGroup<"inline-asm">;
+def BackendFrameLargerThanEQ : DiagGroup<"frame-larger-than=">;
+def BackendPlugin : DiagGroup<"backend-plugin">;
+def RemarkBackendPlugin : DiagGroup<"remark-backend-plugin">;
+def BackendOptimizationRemark : DiagGroup<"pass">;
+def BackendOptimizationRemarkMissed : DiagGroup<"pass-missed">;
+def BackendOptimizationRemarkAnalysis : DiagGroup<"pass-analysis">;
+def BackendOptimizationFailure : DiagGroup<"pass-failed">;
+
+// Instrumentation based profiling warnings.
+def ProfileInstrOutOfDate : DiagGroup<"profile-instr-out-of-date">;
+def ProfileInstrUnprofiled : DiagGroup<"profile-instr-unprofiled">;
+
+// AddressSanitizer frontent instrumentation remarks.
+def SanitizeAddressRemarks : DiagGroup<"sanitize-address">;
+
+// Issues with serialized diagnostics.
+def SerializedDiagnostics : DiagGroup<"serialized-diagnostics">;
+
+// A warning group for warnings about code that clang accepts when
+// compiling CUDA C/C++ but which is not compatible with the CUDA spec.
+def CudaCompat : DiagGroup<"cuda-compat">;
+
+// A warning group for things that will change semantics in the future.
+def FutureCompat : DiagGroup<"future-compat">;
+
+def InvalidOrNonExistentDirectory : DiagGroup<"invalid-or-nonexistent-directory">;
+
+def OptionIgnored : DiagGroup<"option-ignored">;
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..a675dfa
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticIDs.h
@@ -0,0 +1,287 @@
+//===--- 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.
+//
+//===----------------------------------------------------------------------===//
+///
+/// \file
+/// \brief Defines the Diagnostic IDs-related interfaces.
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_BASIC_DIAGNOSTICIDS_H
+#define LLVM_CLANG_BASIC_DIAGNOSTICIDS_H
+
+#include "clang/Basic/LLVM.h"
+#include "llvm/ADT/IntrusiveRefCntPtr.h"
+#include "llvm/ADT/StringRef.h"
+
+namespace clang {
+ class DiagnosticsEngine;
+ class SourceLocation;
+
+ // Import the diagnostic enums themselves.
+ namespace diag {
+ // Start position for diagnostics.
+ enum {
+ DIAG_START_COMMON = 0,
+ DIAG_START_DRIVER = DIAG_START_COMMON + 300,
+ DIAG_START_FRONTEND = DIAG_START_DRIVER + 100,
+ DIAG_START_SERIALIZATION = DIAG_START_FRONTEND + 100,
+ DIAG_START_LEX = DIAG_START_SERIALIZATION + 120,
+ DIAG_START_PARSE = DIAG_START_LEX + 300,
+ DIAG_START_AST = DIAG_START_PARSE + 500,
+ DIAG_START_COMMENT = DIAG_START_AST + 110,
+ DIAG_START_SEMA = DIAG_START_COMMENT + 100,
+ DIAG_START_ANALYSIS = DIAG_START_SEMA + 3000,
+ DIAG_UPPER_LIMIT = DIAG_START_ANALYSIS + 100
+ };
+
+ class CustomDiagInfo;
+
+ /// \brief 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,CATEGORY,NOWERROR,SHOWINSYSHEADER) ENUM,
+#define COMMONSTART
+#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 Ignore (nothing), Remark (emit a remark), Warning
+ /// (emit a warning) or Error (emit as an error). It allows clients to
+ /// map ERRORs to Error or Fatal (stop emitting diagnostics after this one).
+ enum class Severity {
+ // NOTE: 0 means "uncomputed".
+ Ignored = 1, ///< Do not present this diagnostic, ignore it.
+ Remark = 2, ///< Present this diagnostic as a remark.
+ Warning = 3, ///< Present this diagnostic as a warning.
+ Error = 4, ///< Present this diagnostic as an error.
+ Fatal = 5 ///< Present this diagnostic as a fatal error.
+ };
+
+ /// Flavors of diagnostics we can emit. Used to filter for a particular
+ /// kind of diagnostic (for instance, for -W/-R flags).
+ enum class Flavor {
+ WarningOrError, ///< A diagnostic that indicates a problem or potential
+ ///< problem. Can be made fatal by -Werror.
+ Remark ///< A diagnostic that indicates normal progress through
+ ///< compilation.
+ };
+ }
+
+class DiagnosticMapping {
+ unsigned Severity : 3;
+ unsigned IsUser : 1;
+ unsigned IsPragma : 1;
+ unsigned HasNoWarningAsError : 1;
+ unsigned HasNoErrorAsFatal : 1;
+
+public:
+ static DiagnosticMapping Make(diag::Severity Severity, bool IsUser,
+ bool IsPragma) {
+ DiagnosticMapping Result;
+ Result.Severity = (unsigned)Severity;
+ Result.IsUser = IsUser;
+ Result.IsPragma = IsPragma;
+ Result.HasNoWarningAsError = 0;
+ Result.HasNoErrorAsFatal = 0;
+ return Result;
+ }
+
+ diag::Severity getSeverity() const { return (diag::Severity)Severity; }
+ void setSeverity(diag::Severity Value) { Severity = (unsigned)Value; }
+
+ bool isUser() const { return IsUser; }
+ bool isPragma() const { return IsPragma; }
+
+ bool hasNoWarningAsError() const { return HasNoWarningAsError; }
+ void setNoWarningAsError(bool Value) { HasNoWarningAsError = Value; }
+
+ bool hasNoErrorAsFatal() const { return HasNoErrorAsFatal; }
+ void setNoErrorAsFatal(bool Value) { HasNoErrorAsFatal = Value; }
+};
+
+/// \brief Used for handling and querying diagnostic IDs.
+///
+/// Can be used and shared by multiple Diagnostics for multiple translation units.
+class DiagnosticIDs : public RefCountedBase<DiagnosticIDs> {
+public:
+ /// \brief The level of the diagnostic, after it has been through mapping.
+ enum Level {
+ Ignored, Note, Remark, Warning, Error, Fatal
+ };
+
+private:
+ /// \brief Information for uniquing and looking up custom diags.
+ diag::CustomDiagInfo *CustomDiagInfo;
+
+public:
+ DiagnosticIDs();
+ ~DiagnosticIDs();
+
+ /// \brief Return an ID for a diagnostic with the specified format string and
+ /// level.
+ ///
+ /// If this is the first request for this diagnostic, it is registered and
+ /// created, otherwise the existing ID is returned.
+
+ // FIXME: Replace this function with a create-only facilty like
+ // createCustomDiagIDFromFormatString() to enforce safe usage. At the time of
+ // writing, nearly all callers of this function were invalid.
+ unsigned getCustomDiagID(Level L, StringRef FormatString);
+
+ //===--------------------------------------------------------------------===//
+ // Diagnostic classification and reporting interfaces.
+ //
+
+ /// \brief Given a diagnostic ID, return a description of the issue.
+ StringRef getDescription(unsigned DiagID) const;
+
+ /// \brief Return true if the unmapped diagnostic levelof 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 Return true if the specified diagnostic is mapped to errors by
+ /// default.
+ static bool isDefaultMappingAsError(unsigned DiagID);
+
+ /// \brief Determine whether the given built-in diagnostic ID is a Note.
+ static bool isBuiltinNote(unsigned DiagID);
+
+ /// \brief 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);
+ }
+
+ /// \brief Determine whether the given built-in diagnostic ID is for an
+ /// extension of some sort, and whether it is enabled by default.
+ ///
+ /// 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);
+
+
+ /// \brief 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 StringRef getWarningOptionForDiag(unsigned DiagID);
+
+ /// \brief Return the category number that a specified \p DiagID belongs to,
+ /// or 0 if no category.
+ static unsigned getCategoryNumberForDiag(unsigned DiagID);
+
+ /// \brief Return the number of diagnostic categories.
+ static unsigned getNumberOfCategories();
+
+ /// \brief Given a category ID, return the name of the category.
+ static StringRef getCategoryNameFromID(unsigned CategoryID);
+
+ /// \brief Return true if a given diagnostic falls into an ARC diagnostic
+ /// category.
+ static bool isARCDiagnostic(unsigned DiagID);
+
+ /// \brief Enumeration describing how 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);
+
+ /// \brief Get the set of all diagnostic IDs in the group with the given name.
+ ///
+ /// \param[out] Diags - On return, the diagnostics in the group.
+ /// \returns \c true if the given group is unknown, \c false otherwise.
+ bool getDiagnosticsInGroup(diag::Flavor Flavor, StringRef Group,
+ SmallVectorImpl<diag::kind> &Diags) const;
+
+ /// \brief Get the set of all diagnostic IDs.
+ void getAllDiagnostics(diag::Flavor Flavor,
+ SmallVectorImpl<diag::kind> &Diags) const;
+
+ /// \brief Get the diagnostic option with the closest edit distance to the
+ /// given group name.
+ static StringRef getNearestOption(diag::Flavor Flavor, StringRef Group);
+
+private:
+ /// \brief Classify the specified diagnostic ID into a Level, consumable by
+ /// the DiagnosticClient.
+ ///
+ /// The classification is based on the way the client configured the
+ /// DiagnosticsEngine object.
+ ///
+ /// \param Loc The source location for which 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 DiagnosticsEngine &Diag) const LLVM_READONLY;
+
+ diag::Severity
+ getDiagnosticSeverity(unsigned DiagID, SourceLocation Loc,
+ const DiagnosticsEngine &Diag) const LLVM_READONLY;
+
+ /// \brief Used to report a diagnostic that is finally fully formed.
+ ///
+ /// \returns \c true if the diagnostic was emitted, \c false if it was
+ /// suppressed.
+ bool ProcessDiag(DiagnosticsEngine &Diag) const;
+
+ /// \brief Used to emit a diagnostic that is finally fully formed,
+ /// ignoring suppression.
+ void EmitDiag(DiagnosticsEngine &Diag, Level DiagLevel) const;
+
+ /// \brief Whether the diagnostic may leave the AST in a state where some
+ /// invariants can break.
+ bool isUnrecoverable(unsigned DiagID) const;
+
+ friend class DiagnosticsEngine;
+};
+
+} // 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..ed6ff20
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticLexKinds.td
@@ -0,0 +1,673 @@
+//==--- 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_char_or_string : Warning<
+ "null character(s) preserved in %select{char|string}0 literal">,
+ InGroup<NullCharacter>;
+def null_in_file : Warning<"null character ignored">, InGroup<NullCharacter>;
+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">,
+ InGroup<DiagGroup<"backslash-newline-escape">>;
+
+// Digraphs.
+def warn_cxx98_compat_less_colon_colon : Warning<
+ "'<::' is treated as digraph '<:' (aka '[') followed by ':' in C++98">,
+ InGroup<CXX98Compat>, DefaultIgnore;
+
+// 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_line_comment : Extension<"multi-line // comment">,
+ InGroup<Comment>;
+def ext_line_comment : Extension<
+ "// comments are not allowed in this language">,
+ InGroup<Comment>;
+def ext_no_newline_eof : Extension<"no newline at end of file">,
+ InGroup<NewlineEOF>;
+def warn_no_newline_eof : Warning<"no newline at end of file">,
+ InGroup<NewlineEOF>, DefaultIgnore;
+
+def warn_cxx98_compat_no_newline_eof : Warning<
+ "C++98 requires newline at end of file">,
+ InGroup<CXX98CompatPedantic>, DefaultIgnore;
+
+def ext_dollar_in_identifier : Extension<"'$' in identifier">,
+ InGroup<DiagGroup<"dollar-in-identifier-extension">>;
+def ext_charize_microsoft : Extension<
+ "charizing operator #@ is a Microsoft extension">,
+ InGroup<MicrosoftCharize>;
+def ext_comment_paste_microsoft : Extension<
+ "pasting two '/' tokens into a '//' comment is a Microsoft extension">,
+ InGroup<MicrosoftCommentPaste>;
+def ext_ctrl_z_eof_microsoft : Extension<
+ "treating Ctrl-Z as end-of-file is a Microsoft extension">,
+ InGroup<MicrosoftEndOfFile>;
+
+def ext_token_used : Extension<"extension used">,
+ InGroup<DiagGroup<"language-extension-token">>;
+
+def warn_cxx11_keyword : Warning<"'%0' is a keyword in C++11">,
+ InGroup<CXX11Compat>, DefaultIgnore;
+
+def ext_unterminated_char_or_string : ExtWarn<
+ "missing terminating %select{'|'\"'}0 character">, InGroup<InvalidPPToken>;
+def ext_empty_character : ExtWarn<"empty character constant">,
+ InGroup<InvalidPPToken>;
+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 err_raw_delim_too_long : Error<
+ "raw string delimiter longer than 16 characters"
+ "; use PREFIX( )PREFIX to delimit raw string">;
+def err_invalid_char_raw_delim : Error<
+ "invalid character '%0' character in raw string delimiter"
+ "; use PREFIX( )PREFIX to delimit raw string">;
+def err_unterminated_raw_string : Error<
+ "raw string missing terminating delimiter )%0\"">;
+def warn_cxx98_compat_raw_string_literal : Warning<
+ "raw string literals are incompatible with C++98">,
+ InGroup<CXX98Compat>, DefaultIgnore;
+
+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>;
+
+
+// Unicode and UCNs
+def err_invalid_utf8 : Error<
+ "source file is not valid UTF-8">;
+def err_non_ascii : Error<
+ "non-ASCII characters are not allowed outside of literals and identifiers">;
+def ext_unicode_whitespace : ExtWarn<
+ "treating Unicode character as whitespace">,
+ InGroup<DiagGroup<"unicode-whitespace">>;
+
+def err_hex_escape_no_digits : Error<
+ "\\%0 used with no following hex digits">;
+def warn_ucn_escape_no_digits : Warning<
+ "\\%0 used with no following hex digits; "
+ "treating as '\\' followed by identifier">, InGroup<Unicode>;
+def err_ucn_escape_incomplete : Error<
+ "incomplete universal character name">;
+def warn_ucn_escape_incomplete : Warning<
+ "incomplete universal character name; "
+ "treating as '\\' followed by identifier">, InGroup<Unicode>;
+def note_ucn_four_not_eight : Note<"did you mean to use '\\u'?">;
+
+def err_ucn_escape_basic_scs : Error<
+ "character '%0' cannot be specified by a universal character name">;
+def err_ucn_control_character : Error<
+ "universal character name refers to a control character">;
+def err_ucn_escape_invalid : Error<"invalid universal character">;
+def warn_ucn_escape_surrogate : Warning<
+ "universal character name refers to a surrogate character">,
+ InGroup<Unicode>;
+
+def warn_c99_compat_unicode_id : Warning<
+ "%select{using this character in an identifier|starting an identifier with "
+ "this character}0 is incompatible with C99">,
+ InGroup<C99Compat>, DefaultIgnore;
+def warn_cxx98_compat_unicode_id : Warning<
+ "using this character in an identifier is incompatible with C++98">,
+ InGroup<CXX98Compat>, DefaultIgnore;
+
+def warn_cxx98_compat_literal_ucn_escape_basic_scs : Warning<
+ "specifying character '%0' with a universal character name "
+ "is incompatible with C++98">, InGroup<CXX98Compat>, DefaultIgnore;
+def warn_cxx98_compat_literal_ucn_control_character : Warning<
+ "universal character name referring to a control character "
+ "is incompatible with C++98">, InGroup<CXX98Compat>, DefaultIgnore;
+def warn_ucn_not_valid_in_c89 : Warning<
+ "universal character names are only valid in C99 or C++; "
+ "treating as '\\' followed by identifier">, InGroup<Unicode>;
+def warn_ucn_not_valid_in_c89_literal : ExtWarn<
+ "universal character names are only valid in C99 or C++">, InGroup<Unicode>;
+
+
+// Literal
+def ext_nonstandard_escape : Extension<
+ "use of non-standard escape character '\\%0'">;
+def ext_unknown_escape : ExtWarn<"unknown escape sequence '\\%0'">,
+ InGroup<DiagGroup<"unknown-escape-sequence">>;
+def err_invalid_digit : Error<
+ "invalid digit '%0' in %select{decimal|octal|binary}1 constant">;
+def err_invalid_suffix_constant : Error<
+ "invalid suffix '%0' on %select{integer|floating}1 constant">;
+def warn_cxx11_compat_digit_separator : Warning<
+ "digit separators are incompatible with C++ standards before C++14">,
+ InGroup<CXXPre14Compat>, DefaultIgnore;
+def err_digit_separator_not_between_digits : Error<
+ "digit separator cannot appear at %select{start|end}0 of digit sequence">;
+def warn_extraneous_char_constant : Warning<
+ "extraneous characters in character constant ignored">;
+def warn_char_constant_too_large : Warning<
+ "character constant too long for its type">;
+def err_multichar_utf_character_literal : Error<
+ "Unicode character literals may not contain multiple characters">;
+def err_exponent_has_no_digits : Error<"exponent has no digits">;
+def ext_imaginary_constant : Extension<
+ "imaginary constants are a GNU extension">, InGroup<GNUImaginaryConstant>;
+def err_hexconstant_requires: Error<
+ "hexadecimal floating constants require %select{an exponent|a significand}0">;
+def ext_hexconstant_invalid : Extension<
+ "hexadecimal floating constants are a C99 feature">, InGroup<C99>;
+def ext_binary_literal : Extension<
+ "binary integer literals are a GNU extension">, InGroup<GNUBinaryLiteral>;
+def ext_binary_literal_cxx14 : Extension<
+ "binary integer literals are a C++14 extension">, InGroup<CXX14BinaryLiteral>;
+def warn_cxx11_compat_binary_literal : Warning<
+ "binary integer literals are incompatible with C++ standards before C++14">,
+ InGroup<CXXPre14CompatPedantic>, DefaultIgnore;
+def err_pascal_string_too_long : Error<"Pascal string is too long">;
+def err_escape_too_large : Error<
+ "%select{hex|octal}0 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 err_character_too_large : Error<
+ "character too large for enclosing character literal type">;
+def warn_c99_compat_unicode_literal : Warning<
+ "unicode literals are incompatible with C99">,
+ InGroup<C99Compat>, DefaultIgnore;
+def warn_cxx98_compat_unicode_literal : Warning<
+ "unicode literals are incompatible with C++98">,
+ InGroup<CXX98Compat>, DefaultIgnore;
+def warn_cxx14_compat_u8_character_literal : Warning<
+ "unicode literals are incompatible with C++ standards before C++1z">,
+ InGroup<CXXPre1zCompat>, DefaultIgnore;
+def warn_cxx11_compat_user_defined_literal : Warning<
+ "identifier after literal will be treated as a user-defined literal suffix "
+ "in C++11">, InGroup<CXX11Compat>, DefaultIgnore;
+def warn_cxx11_compat_reserved_user_defined_literal : Warning<
+ "identifier after literal will be treated as a reserved user-defined literal "
+ "suffix in C++11">,
+ InGroup<CXX11CompatReservedUserDefinedLiteral>, DefaultIgnore;
+def ext_reserved_user_defined_literal : ExtWarn<
+ "invalid suffix on literal; C++11 requires a space between literal and "
+ "identifier">, InGroup<ReservedUserDefinedLiteral>, DefaultError;
+def ext_ms_reserved_user_defined_literal : ExtWarn<
+ "invalid suffix on literal; C++11 requires a space between literal and "
+ "identifier">, InGroup<ReservedUserDefinedLiteral>;
+def err_unsupported_string_concat : Error<
+ "unsupported non-standard concatenation of string literals">;
+def err_string_concat_mixed_suffix : Error<
+ "differing user-defined suffixes ('%0' and '%1') in string literal "
+ "concatenation">;
+def err_pp_invalid_udl : Error<
+ "%select{character|integer}0 literal with user-defined suffix "
+ "cannot be used in preprocessor constant expression">;
+def err_bad_string_encoding : Error<
+ "illegal character encoding in string literal">;
+def warn_bad_string_encoding : ExtWarn<
+ "illegal character encoding in string literal">,
+ InGroup<InvalidSourceEncoding>;
+def err_bad_character_encoding : Error<
+ "illegal character encoding in character literal">;
+def warn_bad_character_encoding : ExtWarn<
+ "illegal character encoding in character literal">,
+ InGroup<InvalidSourceEncoding>;
+def err_lexing_string : Error<"failure when lexing a string">;
+
+
+//===----------------------------------------------------------------------===//
+// PTH Diagnostics
+//===----------------------------------------------------------------------===//
+def err_invalid_pth_file : Error<
+ "invalid or corrupt PTH file '%0'">;
+
+//===----------------------------------------------------------------------===//
+// Preprocessor Diagnostics
+//===----------------------------------------------------------------------===//
+
+let CategoryName = "User-Defined Issue" in {
+def pp_hash_warning : Warning<"%0">,
+ InGroup<PoundWarning>, ShowInSystemHeader;
+def err_pp_hash_error : Error<"%0">;
+}
+
+def pp_include_next_in_primary : Warning<
+ "#include_next in primary source file">,
+ InGroup<DiagGroup<"include-next-outside-header">>;
+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">,
+ InGroup<DiagGroup<"include-next-absolute-path">>;
+def ext_c99_whitespace_required_after_macro_name : ExtWarn<
+ "ISO C99 requires whitespace after the macro name">, InGroup<C99>;
+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">,
+ InGroup<DiagGroup<"pragma-once-outside-header">>;
+def pp_pragma_sysheader_in_main_file : Warning<
+ "#pragma system_header ignored in main file">,
+ InGroup<DiagGroup<"pragma-system-header-outside-header">>;
+def pp_poisoning_existing_macro : Warning<"poisoning existing macro">;
+def pp_out_of_date_dependency : Warning<
+ "current file is older than dependency %0">;
+def ext_pp_undef_builtin_macro : ExtWarn<"undefining builtin macro">,
+ InGroup<BuiltinMacroRedefined>;
+def ext_pp_redef_builtin_macro : ExtWarn<"redefining builtin macro">,
+ InGroup<BuiltinMacroRedefined>;
+def pp_disabled_macro_expansion : Warning<
+ "disabled expansion of recursive macro">, DefaultIgnore,
+ InGroup<DiagGroup<"disabled-macro-expansion">>;
+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 warn_pp_ambiguous_macro : Warning<
+ "ambiguous expansion of macro %0">, InGroup<AmbiguousMacro>;
+def note_pp_ambiguous_macro_chosen : Note<
+ "expanding this definition of %0">;
+def note_pp_ambiguous_macro_other : Note<
+ "other definition of %0">;
+def warn_pp_macro_hides_keyword : Extension<
+ "keyword is hidden by macro definition">, InGroup<KeywordAsMacro>;
+def warn_pp_macro_is_reserved_id : Warning<
+ "macro name is a reserved identifier">, DefaultIgnore,
+ InGroup<ReservedIdAsMacro>;
+def warn_pp_objc_macro_redef_ignored : Warning<
+ "ignoring redefinition of Objective-C qualifier macro">,
+ InGroup<DiagGroup<"objc-macro-redefinition">>;
+
+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_to_positive : Warning<
+ "%select{left|right}0 side of operator converted from negative value to "
+ "unsigned: %1">;
+
+def ext_pp_import_directive : Extension<"#import is a language extension">,
+ InGroup<DiagGroup<"import-preprocessor-directive-pedantic">>;
+def err_pp_import_directive_ms : Error<
+ "#import of type library is an unsupported Microsoft feature">;
+def ext_pp_include_search_ms : ExtWarn<
+ "#include resolved using non-portable Microsoft search rules as: %0">,
+ InGroup<MicrosoftInclude>;
+
+def ext_pp_ident_directive : Extension<"#ident is a language extension">;
+def ext_pp_include_next_directive : Extension<
+ "#include_next is a language extension">, InGroup<GNUIncludeNext>;
+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">, InGroup<MacroRedefined>;
+def ext_variadic_macro : Extension<"variadic macros are a C99 feature">,
+ InGroup<VariadicMacros>;
+def warn_cxx98_compat_variadic_macro : Warning<
+ "variadic macros are incompatible with C++98">,
+ InGroup<CXX98CompatPedantic>, DefaultIgnore;
+def ext_named_variadic_macro : Extension<
+ "named variadic macros are a GNU extension">, InGroup<VariadicMacros>;
+def err_embedded_directive : Error<
+ "embedding a #%0 directive within macro arguments is not supported">;
+def ext_embedded_directive : Extension<
+ "embedding a directive within macro arguments has undefined behavior">,
+ InGroup<DiagGroup<"embedded-directive">>;
+def ext_missing_varargs_arg : Extension<
+ "must specify at least one argument for '...' parameter of variadic macro">,
+ InGroup<GNUZeroVariadicMacroArguments>;
+def ext_empty_fnmacro_arg : Extension<
+ "empty macro arguments are a C99 feature">, InGroup<C99>;
+def warn_cxx98_compat_empty_fnmacro_arg : Warning<
+ "empty macro arguments are incompatible with C++98">,
+ InGroup<CXX98CompatPedantic>, DefaultIgnore;
+def note_macro_here : Note<"macro %0 defined here">;
+
+def err_pp_opencl_variadic_macros :
+ Error<"variadic macros not supported in OpenCL">;
+
+def err_pp_invalid_directive : Error<"invalid preprocessing directive">;
+def err_pp_directive_required : Error<
+ "%0 must be used within a preprocessing directive">;
+def err_pp_file_not_found : Error<"'%0' file not found">, DefaultFatal;
+def err_pp_file_not_found_not_fatal : Error<
+ "'%0' file not found with <angled> include; use \"quotes\" instead">;
+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 name must be an identifier">;
+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_expected_rparen : Error<"expected ')' in preprocessor expression">;
+def err_pp_expected_eol : Error<
+ "expected end of line in preprocessor expression">;
+def err_pp_expected_after : Error<"missing %1 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_warning_check_malformed : Error<
+ "builtin warning check macro requires a parenthesized string">;
+def warn_has_warning_invalid_option :
+ ExtWarn<"__has_warning expected option name (e.g. \"-Wundef\")">,
+ InGroup<MalformedWarningCheck>;
+
+def err_pp_identifier_arg_not_identifier : Error<
+ "cannot convert %0 token to an identifier">;
+
+def warn_pragma_include_alias_mismatch_angle :
+ ExtWarn<"angle-bracketed include <%0> cannot be aliased to double-quoted "
+ "include \"%1\"">, InGroup<UnknownPragmas>;
+def warn_pragma_include_alias_mismatch_quote :
+ ExtWarn<"double-quoted include \"%0\" cannot be aliased to angle-bracketed "
+ "include <%1>">, InGroup<UnknownPragmas>;
+def warn_pragma_include_alias_expected :
+ ExtWarn<"pragma include_alias expected '%0'">,
+ InGroup<UnknownPragmas>;
+def warn_pragma_include_alias_expected_filename :
+ ExtWarn<"pragma include_alias expected include filename">,
+ InGroup<UnknownPragmas>;
+
+// - #pragma warning(...)
+def warn_pragma_warning_expected :
+ ExtWarn<"#pragma warning expected '%0'">,
+ InGroup<UnknownPragmas>;
+def warn_pragma_warning_spec_invalid :
+ ExtWarn<"#pragma warning expected 'push', 'pop', 'default', 'disable',"
+ " 'error', 'once', 'suppress', 1, 2, 3, or 4">,
+ InGroup<UnknownPragmas>;
+def warn_pragma_warning_push_level :
+ ExtWarn<"#pragma warning(push, level) requires a level between 0 and 4">,
+ InGroup<UnknownPragmas>;
+def warn_pragma_warning_expected_number :
+ ExtWarn<"#pragma warning expected a warning number">,
+ InGroup<UnknownPragmas>;
+
+def err__Pragma_malformed : Error<
+ "_Pragma takes a parenthesized string literal">;
+def err_pragma_message_malformed : Error<
+ "pragma %select{message|warning|error}0 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">,
+ InGroup<IgnoredPragmas>;
+def warn_pragma_message : Warning<"%0">,
+ InGroup<PoundPragmaMessage>, DefaultWarnNoWerror;
+def err_pragma_message : Error<"%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_eod :
+ ExtWarn<"expected end of directive 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'">, InGroup<IgnoredPragmas>;
+
+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<
+ "token pasting of ',' and __VA_ARGS__ is a GNU extension">, InGroup<GNUZeroVariadicMacroArguments>;
+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 note_suggest_parens_for_macro : Note<
+ "parentheses are required around macro argument containing braced "
+ "initializer list">;
+def note_init_list_at_beginning_of_macro_argument : Note<
+ "cannot use initializer list at the beginning of a macro argument">;
+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 ext_pp_bad_paste_ms : ExtWarn<
+ "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 (aka %1) used as a macro name">;
+def ext_pp_operator_used_as_macro_name : Extension<
+ err_pp_operator_used_as_macro_name.Text>, InGroup<MicrosoftCppMacro>;
+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 ext_pp_line_zero : Extension<
+ "#line directive with zero argument is a GNU extension">,
+ InGroup<GNUZeroLineDirective>;
+def err_pp_line_invalid_filename : Error<
+ "invalid filename for #line directive">;
+def warn_pp_line_decimal : Warning<
+ "%select{#line|GNU line marker}0 directive interprets number as decimal, not octal">;
+def err_pp_line_digit_sequence : Error<
+ "%select{#line|GNU line marker}0 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">;
+def warn_cxx98_compat_pp_line_too_big : Warning<
+ "#line number greater than 32767 is incompatible with C++98">,
+ InGroup<CXX98CompatPedantic>, DefaultIgnore;
+
+def err_pp_visibility_non_macro : Error<"no macro named %0">;
+
+def err_pp_arc_cf_code_audited_syntax : Error<"expected 'begin' or 'end'">;
+def err_pp_double_begin_of_arc_cf_code_audited : Error<
+ "already inside '#pragma clang arc_cf_code_audited'">;
+def err_pp_unmatched_end_of_arc_cf_code_audited : Error<
+ "not currently inside '#pragma clang arc_cf_code_audited'">;
+def err_pp_include_in_arc_cf_code_audited : Error<
+ "cannot #include files inside '#pragma clang arc_cf_code_audited'">;
+def err_pp_eof_in_arc_cf_code_audited : Error<
+ "'#pragma clang arc_cf_code_audited' was not ended within this file">;
+
+def warn_pp_date_time : Warning<
+ "expansion of date or time macro is not reproducible">,
+ ShowInSystemHeader, DefaultIgnore, InGroup<DiagGroup<"date-time">>;
+
+// Module map parsing
+def err_mmap_unknown_token : Error<"skipping stray token">;
+def err_mmap_expected_module : Error<"expected module declaration">;
+def err_mmap_expected_module_name : Error<"expected module name">;
+def err_mmap_expected_lbrace : Error<"expected '{' to start module '%0'">;
+def err_mmap_expected_rbrace : Error<"expected '}'">;
+def note_mmap_lbrace_match : Note<"to match this '{'">;
+def err_mmap_expected_rsquare : Error<"expected ']' to close attribute">;
+def note_mmap_lsquare_match : Note<"to match this ']'">;
+def err_mmap_expected_member : Error<
+ "expected umbrella, header, submodule, or module export">;
+def err_mmap_expected_header : Error<"expected a header name after '%0'">;
+def err_mmap_expected_mmap_file : Error<"expected a module map file name">;
+def err_mmap_module_redefinition : Error<
+ "redefinition of module '%0'">;
+def note_mmap_prev_definition : Note<"previously defined here">;
+def err_mmap_umbrella_dir_not_found : Error<
+ "umbrella directory '%0' not found">;
+def err_mmap_umbrella_clash : Error<
+ "umbrella for module '%0' already covers this directory">;
+def err_mmap_module_id : Error<
+ "expected a module name or '*'">;
+def err_mmap_expected_library_name : Error<
+ "expected %select{library|framework}0 name as a string">;
+def err_mmap_config_macro_submodule : Error<
+ "configuration macros are only allowed in top-level modules">;
+def err_mmap_use_decl_submodule : Error<
+ "use declarations are only allowed in top-level modules">;
+def err_mmap_expected_config_macro : Error<
+ "expected configuration macro name after ','">;
+def err_mmap_expected_conflicts_comma : Error<
+ "expected ',' after conflicting module name">;
+def err_mmap_expected_conflicts_message : Error<
+ "expected a message describing the conflict with '%0'">;
+def err_mmap_missing_module_unqualified : Error<
+ "no module named '%0' visible from '%1'">;
+def err_mmap_missing_module_qualified : Error<
+ "no module named '%0' in '%1'">;
+def err_mmap_top_level_inferred_submodule : Error<
+ "only submodules and framework modules may be inferred with wildcard syntax">;
+def err_mmap_inferred_no_umbrella : Error<
+ "inferred submodules require a module with an umbrella">;
+def err_mmap_inferred_framework_submodule : Error<
+ "inferred submodule cannot be a framework submodule">;
+def err_mmap_explicit_inferred_framework : Error<
+ "inferred framework modules cannot be 'explicit'">;
+def err_mmap_missing_exclude_name : Error<
+ "expected excluded module name">;
+def err_mmap_inferred_redef : Error<
+ "redefinition of inferred submodule">;
+def err_mmap_expected_lbrace_wildcard : Error<
+ "expected '{' to start inferred submodule">;
+def err_mmap_expected_inferred_member : Error<
+ "expected %select{module exclusion with 'exclude'|'export *'}0">;
+def err_mmap_expected_export_wildcard : Error<
+ "only '*' can be exported from an inferred submodule">;
+def err_mmap_explicit_top_level : Error<
+ "'explicit' is not permitted on top-level modules">;
+def err_mmap_nested_submodule_id : Error<
+ "qualified module name can only be used to define modules at the top level">;
+def err_mmap_expected_feature : Error<"expected a feature name">;
+def err_mmap_expected_attribute : Error<"expected an attribute name">;
+def warn_mmap_unknown_attribute : Warning<"unknown attribute '%0'">,
+ InGroup<IgnoredAttributes>;
+
+def warn_auto_module_import : Warning<
+ "treating #%select{include|import|include_next|__include_macros}0 as an "
+ "import of module '%1'">, InGroup<AutoImport>, DefaultIgnore;
+def note_implicit_top_level_module_import_here : Note<
+ "submodule of top-level module '%0' implicitly imported here">;
+def warn_uncovered_module_header : Warning<
+ "umbrella header for module '%0' does not include header '%1'">,
+ InGroup<IncompleteUmbrella>;
+def err_expected_id_building_module : Error<
+ "expected a module name in '__building_module' expression">;
+def warn_use_of_private_header_outside_module : Warning<
+ "use of private header from outside its module: '%0'">,
+ InGroup<DiagGroup<"private-header">>, DefaultError;
+def err_undeclared_use_of_module : Error<
+ "module %0 does not depend on a module exporting '%1'">;
+def warn_non_modular_include_in_framework_module : Warning<
+ "include of non-modular header inside framework module '%0'">,
+ InGroup<NonModularIncludeInFrameworkModule>, DefaultIgnore;
+def warn_non_modular_include_in_module : Warning<
+ "include of non-modular header inside module '%0'">,
+ InGroup<NonModularIncludeInModule>, DefaultIgnore;
+def warn_module_conflict : Warning<
+ "module '%0' conflicts with already-imported module '%1': %2">,
+ InGroup<ModuleConflict>;
+
+def warn_header_guard : Warning<
+ "%0 is used as a header guard here, followed by #define of a different macro">,
+ InGroup<DiagGroup<"header-guard">>;
+def note_header_guard : Note<
+ "%0 is defined here; did you mean %1?">;
+
+let CategoryName = "Nullability Issue" in {
+
+def err_pp_assume_nonnull_syntax : Error<"expected 'begin' or 'end'">;
+def err_pp_double_begin_of_assume_nonnull : Error<
+ "already inside '#pragma clang assume_nonnull'">;
+def err_pp_unmatched_end_of_assume_nonnull : Error<
+ "not currently inside '#pragma clang assume_nonnull'">;
+def err_pp_include_in_assume_nonnull : Error<
+ "cannot #include files inside '#pragma clang assume_nonnull'">;
+def err_pp_eof_in_assume_nonnull : Error<
+ "'#pragma clang assume_nonnull' was not ended within this file">;
+
+}
+
+}
diff --git a/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticOptions.def b/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticOptions.def
new file mode 100644
index 0000000..f4ba6da
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticOptions.def
@@ -0,0 +1,99 @@
+//===--- DiagOptions.def - Diagnostic option 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 diagnostic options. Users of this file
+// must define the DIAGOPT macro to make use of this information.
+// Optionally, the user may also define ENUM_DIAGOPT (for options
+// that have enumeration type and VALUE_DIAGOPT (for options that
+// describe a value rather than a flag). The SEMANTIC_* variants of these macros
+// indicate options that affect the processing of the program, rather than
+// simply the output.
+//
+//===----------------------------------------------------------------------===//
+#ifndef DIAGOPT
+# error Define the DIAGOPT macro to handle language options
+#endif
+
+#ifndef VALUE_DIAGOPT
+# define VALUE_DIAGOPT(Name, Bits, Default) \
+DIAGOPT(Name, Bits, Default)
+#endif
+
+#ifndef ENUM_DIAGOPT
+# define ENUM_DIAGOPT(Name, Type, Bits, Default) \
+DIAGOPT(Name, Bits, Default)
+#endif
+
+#ifndef SEMANTIC_DIAGOPT
+# define SEMANTIC_DIAGOPT(Name, Bits, Default) DIAGOPT(Name, Bits, Default)
+#endif
+
+#ifndef SEMANTIC_VALUE_DIAGOPT
+# define SEMANTIC_VALUE_DIAGOPT(Name, Bits, Default) \
+ VALUE_DIAGOPT(Name, Bits, Default)
+#endif
+
+#ifndef SEMANTIC_ENUM_DIAGOPT
+# define SEMANTIC_ENUM_DIAGOPT(Name, Type, Bits, Default) \
+ ENUM_DIAGOPT(Name, Type, Bits, Default)
+#endif
+
+SEMANTIC_DIAGOPT(IgnoreWarnings, 1, 0) /// -w
+DIAGOPT(NoRewriteMacros, 1, 0) /// -Wno-rewrite-macros
+DIAGOPT(Pedantic, 1, 0) /// -pedantic
+DIAGOPT(PedanticErrors, 1, 0) /// -pedantic-errors
+DIAGOPT(ShowColumn, 1, 1) /// Show column number on diagnostics.
+DIAGOPT(ShowLocation, 1, 1) /// Show source location information.
+DIAGOPT(ShowCarets, 1, 1) /// Show carets in diagnostics.
+DIAGOPT(ShowFixits, 1, 1) /// Show fixit information.
+DIAGOPT(ShowSourceRanges, 1, 0) /// Show source ranges in numeric form.
+DIAGOPT(ShowParseableFixits, 1, 0) /// Show machine parseable fix-its.
+DIAGOPT(ShowPresumedLoc, 1, 0) /// Show presumed location for diagnostics.
+DIAGOPT(ShowOptionNames, 1, 0) /// Show the option name for mappable
+ /// diagnostics.
+DIAGOPT(ShowNoteIncludeStack, 1, 0) /// Show include stacks for notes.
+VALUE_DIAGOPT(ShowCategories, 2, 0) /// Show categories: 0 -> none, 1 -> Number,
+ /// 2 -> Full Name.
+
+ENUM_DIAGOPT(Format, TextDiagnosticFormat, 2, Clang) /// Format for diagnostics:
+
+DIAGOPT(ShowColors, 1, 0) /// Show diagnostics with ANSI color sequences.
+ENUM_DIAGOPT(ShowOverloads, OverloadsShown, 1,
+ Ovl_All) /// Overload candidates to show.
+DIAGOPT(VerifyDiagnostics, 1, 0) /// Check that diagnostics match the expected
+ /// diagnostics, indicated by markers in the
+ /// input source file.
+ENUM_DIAGOPT(VerifyIgnoreUnexpected, DiagnosticLevelMask, 4,
+ DiagnosticLevelMask::None) /// Ignore unexpected diagnostics of
+ /// the specified levels when using
+ /// -verify.
+DIAGOPT(ElideType, 1, 0) /// Elide identical types in template diffing
+DIAGOPT(ShowTemplateTree, 1, 0) /// Print a template tree when diffing
+DIAGOPT(CLFallbackMode, 1, 0) /// Format for clang-cl fallback mode
+
+VALUE_DIAGOPT(ErrorLimit, 32, 0) /// Limit # errors emitted.
+/// Limit depth of macro expansion backtrace.
+VALUE_DIAGOPT(MacroBacktraceLimit, 32, DefaultMacroBacktraceLimit)
+/// Limit depth of instantiation backtrace.
+VALUE_DIAGOPT(TemplateBacktraceLimit, 32, DefaultTemplateBacktraceLimit)
+/// Limit depth of constexpr backtrace.
+VALUE_DIAGOPT(ConstexprBacktraceLimit, 32, DefaultConstexprBacktraceLimit)
+/// Limit number of times to perform spell checking.
+VALUE_DIAGOPT(SpellCheckingLimit, 32, DefaultSpellCheckingLimit)
+
+VALUE_DIAGOPT(TabStop, 32, DefaultTabStop) /// The distance between tab stops.
+/// Column limit for formatting message diagnostics, or 0 if unused.
+VALUE_DIAGOPT(MessageLength, 32, 0)
+
+#undef DIAGOPT
+#undef ENUM_DIAGOPT
+#undef VALUE_DIAGOPT
+#undef SEMANTIC_DIAGOPT
+#undef SEMANTIC_ENUM_DIAGOPT
+#undef SEMANTIC_VALUE_DIAGOPT
diff --git a/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticOptions.h b/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticOptions.h
new file mode 100644
index 0000000..c9b0c5d
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticOptions.h
@@ -0,0 +1,118 @@
+//===--- 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_BASIC_DIAGNOSTICOPTIONS_H
+#define LLVM_CLANG_BASIC_DIAGNOSTICOPTIONS_H
+
+#include "clang/Basic/LLVM.h"
+#include "llvm/ADT/IntrusiveRefCntPtr.h"
+#include <string>
+#include <type_traits>
+#include <vector>
+
+namespace clang {
+
+/// \brief Specifies which overload candidates to display when overload
+/// resolution fails.
+enum OverloadsShown : unsigned {
+ Ovl_All, ///< Show all overloads.
+ Ovl_Best ///< Show just the "best" overload candidates.
+};
+
+/// \brief A bitmask representing the diagnostic levels used by
+/// VerifyDiagnosticConsumer.
+enum class DiagnosticLevelMask : unsigned {
+ None = 0,
+ Note = 1 << 0,
+ Remark = 1 << 1,
+ Warning = 1 << 2,
+ Error = 1 << 3,
+ All = Note | Remark | Warning | Error
+};
+
+inline DiagnosticLevelMask operator~(DiagnosticLevelMask M) {
+ using UT = std::underlying_type<DiagnosticLevelMask>::type;
+ return static_cast<DiagnosticLevelMask>(~static_cast<UT>(M));
+}
+
+inline DiagnosticLevelMask operator|(DiagnosticLevelMask LHS,
+ DiagnosticLevelMask RHS) {
+ using UT = std::underlying_type<DiagnosticLevelMask>::type;
+ return static_cast<DiagnosticLevelMask>(
+ static_cast<UT>(LHS) | static_cast<UT>(RHS));
+}
+
+inline DiagnosticLevelMask operator&(DiagnosticLevelMask LHS,
+ DiagnosticLevelMask RHS) {
+ using UT = std::underlying_type<DiagnosticLevelMask>::type;
+ return static_cast<DiagnosticLevelMask>(
+ static_cast<UT>(LHS) & static_cast<UT>(RHS));
+}
+
+raw_ostream& operator<<(raw_ostream& Out, DiagnosticLevelMask M);
+
+/// \brief Options for controlling the compiler diagnostics engine.
+class DiagnosticOptions : public RefCountedBase<DiagnosticOptions>{
+public:
+ enum TextDiagnosticFormat { Clang, MSVC, Vi };
+
+ // Default values.
+ enum { DefaultTabStop = 8, MaxTabStop = 100,
+ DefaultMacroBacktraceLimit = 6,
+ DefaultTemplateBacktraceLimit = 10,
+ DefaultConstexprBacktraceLimit = 10,
+ DefaultSpellCheckingLimit = 50 };
+
+ // Define simple diagnostic options (with no accessors).
+#define DIAGOPT(Name, Bits, Default) unsigned Name : Bits;
+#define ENUM_DIAGOPT(Name, Type, Bits, Default)
+#include "clang/Basic/DiagnosticOptions.def"
+
+protected:
+ // Define diagnostic options of enumeration type. These are private, and will
+ // have accessors (below).
+#define DIAGOPT(Name, Bits, Default)
+#define ENUM_DIAGOPT(Name, Type, Bits, Default) unsigned Name : Bits;
+#include "clang/Basic/DiagnosticOptions.def"
+
+public:
+ /// \brief The file to log diagnostic output to.
+ std::string DiagnosticLogFile;
+
+ /// \brief The file to serialize diagnostics to (non-appending).
+ std::string DiagnosticSerializationFile;
+
+ /// The list of -W... options used to alter the diagnostic mappings, with the
+ /// prefixes removed.
+ std::vector<std::string> Warnings;
+
+ /// The list of -R... options used to alter the diagnostic mappings, with the
+ /// prefixes removed.
+ std::vector<std::string> Remarks;
+
+public:
+ // Define accessors/mutators for diagnostic options of enumeration type.
+#define DIAGOPT(Name, Bits, Default)
+#define ENUM_DIAGOPT(Name, Type, Bits, Default) \
+ Type get##Name() const { return static_cast<Type>(Name); } \
+ void set##Name(Type Value) { Name = static_cast<unsigned>(Value); }
+#include "clang/Basic/DiagnosticOptions.def"
+
+ DiagnosticOptions() {
+#define DIAGOPT(Name, Bits, Default) Name = Default;
+#define ENUM_DIAGOPT(Name, Type, Bits, Default) set##Name(Default);
+#include "clang/Basic/DiagnosticOptions.def"
+ }
+};
+
+typedef DiagnosticOptions::TextDiagnosticFormat TextDiagnosticFormat;
+
+} // end namespace clang
+
+#endif
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..f8dee2f
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticParseKinds.td
@@ -0,0 +1,985 @@
+//==--- 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 = "Inline Assembly Issue" in {
+def err_asm_empty : Error<"__asm used with no assembly instructions">;
+def err_inline_ms_asm_parsing : Error<"%0">;
+def err_msasm_unsupported_arch : Error<
+ "Unsupported architecture '%0' for MS-style inline assembly">;
+def err_msasm_unable_to_create_target : Error<
+ "MS-style inline assembly is not available: %0">;
+def err_gnu_inline_asm_disabled : Error<
+ "GNU-style inline assembly is disabled">;
+}
+
+let CategoryName = "Parse Issue" in {
+
+def ext_empty_translation_unit : Extension<
+ "ISO C requires a translation unit to contain at least one declaration">,
+ InGroup<DiagGroup<"empty-translation-unit">>;
+def warn_cxx98_compat_top_level_semi : Warning<
+ "extra ';' outside of a function is incompatible with C++98">,
+ InGroup<CXX98CompatPedantic>, DefaultIgnore;
+def ext_extra_semi : Extension<
+ "extra ';' %select{"
+ "outside of a function|"
+ "inside a %1|"
+ "inside instance variable list|"
+ "after member function definition}0">,
+ InGroup<ExtraSemi>;
+def ext_extra_semi_cxx11 : Extension<
+ "extra ';' outside of a function is a C++11 extension">,
+ InGroup<CXX11ExtraSemi>;
+def warn_extra_semi_after_mem_fn_def : Warning<
+ "extra ';' after member function definition">,
+ InGroup<ExtraSemi>, DefaultIgnore;
+
+def ext_thread_before : Extension<"'__thread' before '%0'">;
+def ext_keyword_as_ident : ExtWarn<
+ "keyword '%0' will be made available as an identifier "
+ "%select{here|for the remainder of the translation unit}1">,
+ InGroup<KeywordCompat>;
+
+def ext_nullability : Extension<
+ "type nullability specifier %0 is a Clang extension">,
+ InGroup<DiagGroup<"nullability-extension">>;
+
+def error_empty_enum : Error<"use of empty enum">;
+
+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">, InGroup<C99>;
+def ext_c99_compound_literal : Extension<
+ "compound literals are a C99-specific feature">, InGroup<C99>;
+def ext_enumerator_list_comma_c : Extension<
+ "commas at the end of enumerator lists are a C99-specific "
+ "feature">, InGroup<C99>;
+def ext_enumerator_list_comma_cxx : Extension<
+ "commas at the end of enumerator lists are a C++11 extension">,
+ InGroup<CXX11>;
+def warn_cxx98_compat_enumerator_list_comma : Warning<
+ "commas at the end of enumerator lists are incompatible with C++98">,
+ InGroup<CXX98CompatPedantic>, DefaultIgnore;
+def err_enumerator_list_missing_comma : Error<
+ "missing ',' between enumerators">;
+def err_enumerator_unnamed_no_def : Error<
+ "unnamed enumeration must be a definition">;
+def ext_cxx11_enum_fixed_underlying_type : Extension<
+ "enumeration types with a fixed underlying type are a C++11 extension">,
+ InGroup<CXX11>;
+def ext_c_enum_fixed_underlying_type : Extension<
+ "enumeration types with a fixed underlying type are a Microsoft extension">,
+ InGroup<MicrosoftFixedEnum>;
+def warn_cxx98_compat_enum_fixed_underlying_type : Warning<
+ "enumeration types with a fixed underlying type are incompatible with C++98">,
+ InGroup<CXX98Compat>, DefaultIgnore;
+def warn_cxx98_compat_alignof : Warning<
+ "alignof expressions are incompatible with C++98">,
+ InGroup<CXX98Compat>, DefaultIgnore;
+def ext_alignof_expr : ExtWarn<
+ "%0 applied to an expression is a GNU extension">, InGroup<GNUAlignofExpression>;
+
+def warn_microsoft_dependent_exists : Warning<
+ "dependent %select{__if_not_exists|__if_exists}0 declarations are ignored">,
+ InGroup<DiagGroup<"microsoft-exists">>;
+def warn_microsoft_qualifiers_ignored : Warning<
+ "qualifiers after comma in declarator list are ignored">,
+ InGroup<IgnoredAttributes>;
+
+def ext_c11_generic_selection : Extension<
+ "generic selections are a C11-specific feature">, InGroup<C11>;
+def err_duplicate_default_assoc : Error<
+ "duplicate default generic association">;
+def note_previous_default_assoc : Note<
+ "previous default generic association is here">;
+
+def ext_c11_alignment : Extension<
+ "%0 is a C11-specific feature">, InGroup<C11>;
+
+def ext_c11_noreturn : Extension<
+ "_Noreturn functions are a C11-specific feature">, InGroup<C11>;
+def err_c11_noreturn_misplaced : Error<
+ "'_Noreturn' keyword must precede function declarator">;
+
+def ext_gnu_indirect_goto : Extension<
+ "use of GNU indirect-goto extension">, InGroup<GNULabelsAsValue>;
+def ext_gnu_address_of_label : Extension<
+ "use of GNU address-of-label extension">, InGroup<GNULabelsAsValue>;
+def err_stmtexpr_file_scope : Error<
+ "statement expression not allowed at file scope">;
+def ext_gnu_statement_expr : Extension<
+ "use of GNU statement expression extension">, InGroup<GNUStatementExpression>;
+def ext_gnu_conditional_expr : Extension<
+ "use of GNU ?: conditional expression extension, omitting middle operand">, InGroup<GNUConditionalOmittedOperand>;
+def ext_gnu_empty_initializer : Extension<
+ "use of GNU empty initializer extension">, InGroup<GNUEmptyInitializer>;
+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<GNUCaseRange>;
+
+// Generic errors.
+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_extraneous_closing_brace : Error<"extraneous closing brace ('}')">;
+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 : ExtWarn<
+ "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_at_defs_cxx : Error<"@defs is not supported in Objective-C++">;
+def err_at_in_class : Error<"unexpected '@' in member specification">;
+def err_unexpected_semi : Error<"unexpected ';' before %0">;
+
+def err_expected_fn_body : Error<
+ "expected function body after function declarator">;
+def warn_attribute_on_function_definition : Warning<
+ "GCC does not allow %0 attribute in this position on a function definition">,
+ InGroup<GccCompat>;
+def warn_gcc_attribute_location : Warning<
+ "GCC does not allow an attribute in this position on a function declaration">,
+ InGroup<GccCompat>;
+def warn_attribute_no_decl : Warning<
+ "attribute %0 ignored, because it is not attached to a declaration">,
+ InGroup<IgnoredAttributes>;
+def err_expected_method_body : Error<"expected method body">;
+def err_declspec_after_virtspec : Error<
+ "'%0' qualifier may not appear after the virtual specifier '%1'">;
+def err_invalid_token_after_toplevel_declarator : Error<
+ "expected ';' after top level declarator">;
+def err_invalid_token_after_declarator_suggest_equal : Error<
+ "invalid %0 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_rparen_after : Error<"expected ')' after '%0'">;
+def err_expected_punc : Error<"expected ')' or ',' after '%0'">;
+def err_expected_less_after : Error<"expected '<' after '%0'">;
+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_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 cannot be specified on namespace alias">;
+def err_unexpected_nested_namespace_attribute : Error<
+ "attributes cannot be specified on a nested namespace definition">;
+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 ext_nested_namespace_definition : ExtWarn<
+ "nested namespace definition is a C++1z extension; "
+ "define each namespace separately">, InGroup<CXX1z>;
+def warn_cxx14_compat_nested_namespace_definition : Warning<
+ "nested namespace definition is incompatible with C++ standards before C++1z">,
+ InGroup<CXXPre1zCompat>, DefaultIgnore;
+def err_inline_nested_namespace_definition : Error<
+ "nested namespace definition cannot be 'inline'">;
+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_single_decl_assign_in_for_range : Error<
+ "range-based 'for' statement uses ':', not '='">;
+def warn_missing_selector_name : Warning<
+ "%0 used as the name of the previous parameter rather than as part "
+ "of the selector">,
+ InGroup<DiagGroup<"missing-selector-name">>;
+def note_missing_selector_name : Note<
+ "introduce a parameter name to make %0 part of the selector">;
+def note_force_empty_selector_name : Note<
+ "or insert whitespace before ':' to use %0 as parameter name "
+ "and have an empty entry in the selector">;
+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_asm_operand_wide_string_literal : Error<
+ "cannot use %select{unicode|wide}0 string literal in 'asm'">;
+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_atimport : Error<
+"use of '@import' when modules are disabled">;
+
+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++11 extension">, InGroup<CXX11>;
+def warn_cxx98_compat_rvalue_reference : Warning<
+ "rvalue references are incompatible with C++98">,
+ InGroup<CXX98Compat>, DefaultIgnore;
+def ext_ref_qualifier : ExtWarn<
+ "reference qualifiers on functions are a C++11 extension">, InGroup<CXX11>;
+def warn_cxx98_compat_ref_qualifier : Warning<
+ "reference qualifiers on functions are incompatible with C++98">,
+ InGroup<CXX98Compat>, DefaultIgnore;
+def ext_inline_namespace : ExtWarn<
+ "inline namespaces are a C++11 feature">, InGroup<CXX11InlineNamespace>;
+def warn_cxx98_compat_inline_namespace : Warning<
+ "inline namespaces are incompatible with C++98">,
+ InGroup<CXX98Compat>, DefaultIgnore;
+def ext_generalized_initializer_lists : ExtWarn<
+ "generalized initializer lists are a C++11 extension">,
+ InGroup<CXX11>;
+def warn_cxx98_compat_generalized_initializer_lists : Warning<
+ "generalized initializer lists are incompatible with C++98">,
+ InGroup<CXX98Compat>, DefaultIgnore;
+def err_init_list_bin_op : Error<"initializer list cannot be used on the "
+ "%select{left|right}0 hand side of operator '%1'">;
+def warn_cxx98_compat_trailing_return_type : Warning<
+ "trailing return types are incompatible with C++98">,
+ InGroup<CXX98Compat>, DefaultIgnore;
+def ext_auto_storage_class : ExtWarn<
+ "'auto' storage class specifier is not permitted in C++11, and will not "
+ "be supported in future releases">, InGroup<DiagGroup<"auto-storage-class">>;
+def ext_decltype_auto_type_specifier : ExtWarn<
+ "'decltype(auto)' type specifier is a C++14 extension">, InGroup<CXX14>;
+def warn_cxx11_compat_decltype_auto_type_specifier : Warning<
+ "'decltype(auto)' type specifier is incompatible with C++ standards before "
+ "C++14">, InGroup<CXXPre14Compat>, DefaultIgnore;
+def ext_auto_type : Extension<
+ "'__auto_type' is a GNU extension">,
+ InGroup<GNUAutoType>;
+def ext_for_range : ExtWarn<
+ "range-based for loop is a C++11 extension">, InGroup<CXX11>;
+def warn_cxx98_compat_for_range : Warning<
+ "range-based for loop is incompatible with C++98">,
+ InGroup<CXX98Compat>, DefaultIgnore;
+def err_for_range_identifier : Error<
+ "range-based for loop requires type for loop variable">;
+def err_for_range_expected_decl : Error<
+ "for range declaration must declare a variable">;
+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 warn_cxx98_compat_decltype : Warning<
+ "'decltype' type specifier is incompatible with C++98">,
+ InGroup<CXX98Compat>, DefaultIgnore;
+def err_unexpected_scope_on_base_decltype : Error<
+ "unexpected namespace scope prior to decltype">;
+def err_expected_class_name : Error<"expected class name">;
+def err_expected_class_name_not_template :
+ Error<"'typename' is redundant; base classes are implicitly types">;
+def err_unspecified_vla_size_with_static : Error<
+ "'static' may not be used with an unspecified variable length array size">;
+def err_unspecified_size_with_static : Error<
+ "'static' may not be used without an array size">;
+def err_expected_parentheses_around_typename : Error<
+ "expected parentheses around type name in %0 expression">;
+
+def err_expected_case_before_expression: Error<
+ "expected 'case' keyword before expression">;
+
+// 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_typename_invalid_constexpr : Error<
+ "type name does not allow constexpr specifier to be specified">;
+def err_typename_identifiers_only : Error<
+ "typename is allowed for identifiers only">;
+
+def err_friend_invalid_in_context : Error<
+ "'friend' used outside of class">;
+def err_templated_using_directive_declaration : Error<
+ "cannot template a using %select{directive|declaration}0">;
+def err_unexpected_colon_in_nested_name_spec : Error<
+ "unexpected ':' in nested name specifier; did you mean '::'?">;
+def err_unexpected_token_in_nested_name_spec : Error<
+ "'%0' cannot be a part of nested name specifier; did you mean ':'?">;
+def err_bool_redeclaration : Error<
+ "redeclaration of C++ built-in type 'bool'">;
+def ext_c11_static_assert : Extension<
+ "_Static_assert is a C11-specific feature">, InGroup<C11>;
+def warn_cxx98_compat_static_assert : Warning<
+ "static_assert declarations are incompatible with C++98">,
+ InGroup<CXX98Compat>, DefaultIgnore;
+def err_paren_after_colon_colon : Error<
+ "unexpected parenthesis after '::'">;
+def err_function_definition_not_allowed : Error<
+ "function definition is not allowed here">;
+def err_expected_end_of_enumerator : Error<
+ "expected '= constant-expression' or end of enumerator definition">;
+def err_expected_coloncolon_after_super : Error<
+ "expected '::' after '__super'">;
+
+/// 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 note_objc_container_start : Note<
+ "%select{class|protocol|category|class extension|implementation"
+ "|category implementation}0 started here">;
+def warn_objc_protocol_qualifier_missing_id : Warning<
+ "protocol has no object type specified; defaults to qualified 'id'">;
+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_nsnumber_nonliteral_unary : Error<
+ "@%0 must be followed by a number to form an NSNumber object">;
+def warn_cstyle_param : Warning<
+ "use of C-style parameters in Objective-C method declarations"
+ " is deprecated">, InGroup<DeprecatedDeclarations>;
+
+let CategoryName = "ARC Parse Issue" in {
+def err_arc_bridge_retain : Error<
+ "unknown cast annotation __bridge_retain; did you mean __bridge_retained?">;
+// To be default mapped to an error later.
+def warn_arc_bridge_cast_nonarc : Warning<
+ "'%0' casts have no effect when not using ARC">,
+ InGroup<DiagGroup<"arc-bridge-casts-disallowed-in-nonarc">>;
+}
+
+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_postfix_attribute : Error <
+ "postfix attributes are not allowed on Objective-C directives">;
+def err_objc_postfix_attribute_hint : Error <
+ "postfix attributes are not allowed on Objective-C directives, place"
+ " them in front of '%select{@interface|@protocol}0'">;
+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_expected_objc_container : Error<
+ "'@end' must appear in an Objective-C context">;
+def err_unexpected_protocol_qualifier : Error<
+ "@implementation declaration cannot be protocol qualified">;
+def err_objc_unexpected_atend : Error<
+ "'@end' appears where closing brace '}' is expected">;
+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 note_extra_comma_message_arg : Note<
+ "comma separating Objective-C messaging arguments">;
+
+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_invalid_operator_on_type : Error<
+ "cannot use %select{dot|arrow}0 operator on a type">;
+def err_expected_unqualified_id : Error<
+ "expected %select{identifier|unqualified-id}0">;
+def err_brackets_go_after_unqualified_id : Error<
+ "brackets are not allowed here; to declare an array, "
+ "place the brackets after the %select{identifier|name}0">;
+def err_unexpected_unqualified_id : Error<"type-id cannot have a name">;
+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_init_in_condition : Error<
+ "variable declaration in condition must have an initializer">;
+def err_expected_init_in_condition_lparen : Error<
+ "variable declaration in condition cannot have a parenthesized initializer">;
+def err_extraneous_rparen_in_condition : Error<
+ "extraneous ')' after condition, expected a statement">;
+def warn_dangling_else : Warning<
+ "add explicit braces to avoid dangling else">,
+ InGroup<DanglingElse>;
+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 err_missing_end_of_definition : Error<
+ "missing '}' at end of definition of %q0">;
+def note_missing_end_of_definition_before : Note<
+ "still within definition of %q0 here">;
+def ext_ellipsis_exception_spec : Extension<
+ "exception specification of '...' is a Microsoft extension">,
+ InGroup<MicrosoftExceptionSpec>;
+def err_dynamic_and_noexcept_specification : Error<
+ "cannot have both throw() and noexcept() clause on the same function">;
+def err_except_spec_unparsed : Error<
+ "unexpected end of exception specification">;
+def warn_cxx98_compat_noexcept_decl : Warning<
+ "noexcept specifications are incompatible with C++98">,
+ InGroup<CXX98Compat>, DefaultIgnore;
+def err_expected_catch : Error<"expected catch">;
+def err_using_namespace_in_class : Error<
+ "'using namespace' is not allowed in classes">;
+def err_constructor_bad_name : Error<
+ "missing return type for function %0; did you mean the constructor name %1?">;
+def err_destructor_tilde_identifier : Error<
+ "expected a class name after '~' to name a destructor">;
+def err_destructor_tilde_scope : Error<
+ "'~' in destructor name should be after nested name specifier">;
+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">;
+def err_bracket_depth_exceeded : Error<
+ "bracket nesting level exceeded maximum of %0">, DefaultFatal;
+def note_bracket_depth : Note<
+ "use -fbracket-depth=N to increase maximum nesting level">;
+def err_misplaced_ellipsis_in_declaration : Error<
+ "'...' must %select{immediately precede declared identifier|"
+ "be innermost component of anonymous pack declaration}0">;
+def warn_misplaced_ellipsis_vararg : Warning<
+ "'...' in this location creates a C-style varargs function"
+ "%select{, not a function parameter pack|}0">,
+ InGroup<DiagGroup<"ambiguous-ellipsis">>;
+def note_misplaced_ellipsis_vararg_existing_ellipsis : Note<
+ "preceding '...' declares a function parameter pack">;
+def note_misplaced_ellipsis_vararg_add_ellipsis : Note<
+ "place '...' %select{immediately before declared identifier|here}0 "
+ "to declare a function parameter pack">;
+def note_misplaced_ellipsis_vararg_add_comma : Note<
+ "insert ',' before '...' to silence this warning">;
+def ext_abstract_pack_declarator_parens : ExtWarn<
+ "ISO C++11 requires a parenthesized pack declaration to have a name">,
+ InGroup<DiagGroup<"anonymous-pack-parens">>;
+def err_function_is_not_record : Error<
+ "unexpected %0 in function call; perhaps remove the %0?">;
+def err_super_in_using_declaration : Error<
+ "'__super' cannot be used with a using declaration">;
+
+// C++ derived classes
+def err_dup_virtual : Error<"duplicate 'virtual' in base specifier">;
+
+// C++ operator overloading
+def err_literal_operator_string_prefix : Error<
+ "string literal after 'operator' cannot have an encoding prefix">;
+def err_literal_operator_string_not_empty : Error<
+ "string literal after 'operator' must be '\"\"'">;
+def warn_cxx98_compat_literal_operator : Warning<
+ "literal operators are incompatible with C++98">,
+ InGroup<CXX98Compat>, DefaultIgnore;
+
+// Classes.
+def err_anon_type_definition : Error<
+ "declaration of anonymous %0 must be a definition">;
+def err_default_delete_in_multiple_declaration : Error<
+ "'= %select{default|delete}0' is a function definition and must occur in a "
+ "standalone declaration">;
+
+def warn_cxx98_compat_noexcept_expr : Warning<
+ "noexcept expressions are incompatible with C++98">,
+ InGroup<CXX98Compat>, DefaultIgnore;
+def warn_cxx98_compat_nullptr : Warning<
+ "'nullptr' is incompatible with C++98">, InGroup<CXX98Compat>, DefaultIgnore;
+
+def warn_cxx14_compat_attribute : Warning<
+ "attributes on %select{a namespace|an enumerator}0 declaration are "
+ "incompatible with C++ standards before C++1z">,
+ InGroup<CXXPre1zCompat>, DefaultIgnore;
+def warn_cxx98_compat_alignas : Warning<"'alignas' is incompatible with C++98">,
+ InGroup<CXX98Compat>, DefaultIgnore;
+def warn_cxx98_compat_attribute : Warning<
+ "C++11 attribute syntax is incompatible with C++98">,
+ InGroup<CXX98Compat>, DefaultIgnore;
+def err_cxx11_attribute_forbids_arguments : Error<
+ "attribute %0 cannot have an argument list">;
+def err_attribute_requires_arguments : Error<
+ "parentheses must be omitted if %0 attribute's argument list is empty">;
+def err_cxx11_attribute_forbids_ellipsis : Error<
+ "attribute '%0' cannot be used as an attribute pack">;
+def err_cxx11_attribute_repeated : Error<
+ "attribute %0 cannot appear multiple times in an attribute specifier">;
+def err_attributes_not_allowed : Error<"an attribute list cannot appear here">;
+def err_l_square_l_square_not_attribute : Error<
+ "C++11 only allows consecutive left square brackets when "
+ "introducing an attribute">;
+def err_ms_declspec_type : Error<
+ "__declspec attributes must be an identifier or string literal">;
+def err_ms_property_no_getter_or_putter : Error<
+ "property does not specify a getter or a putter">;
+def err_ms_property_unknown_accessor : Error<
+ "expected 'get' or 'put' in property declaration">;
+def err_ms_property_has_set_accessor : Error<
+ "putter for property must be specified as 'put', not 'set'">;
+def err_ms_property_missing_accessor_kind : Error<
+ "missing 'get=' or 'put='">;
+def err_ms_property_expected_equal : Error<
+ "expected '=' after '%0'">;
+def err_ms_property_duplicate_accessor : Error<
+ "property declaration specifies '%0' accessor twice">;
+def err_ms_property_expected_accessor_name : Error<
+ "expected name of accessor method">;
+def err_ms_property_expected_comma_or_rparen : Error<
+ "expected ',' or ')' at end of property accessor list">;
+def err_ms_property_initializer : Error<
+ "property declaration cannot have an in-class initializer">;
+
+/// 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_class_on_template_template_param : Error<
+ "template template parameter requires 'class' after the parameter list">;
+def ext_template_template_param_typename : ExtWarn<
+ "template template parameter using 'typename' is a C++1z extension">,
+ InGroup<CXX1z>;
+def warn_cxx14_compat_template_template_param_typename : Warning<
+ "template template parameter using 'typename' is "
+ "incompatible with C++ standards before C++1z">,
+ InGroup<CXXPre1zCompat>, DefaultIgnore;
+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 variable template|<unused>}1">;
+def err_id_after_template_in_nested_name_spec : Error<
+ "expected template name after 'template' keyword in nested name specifier">;
+def err_two_right_angle_brackets_need_space : Error<
+ "a space is required between consecutive right angle brackets (use '> >')">;
+def err_right_angle_bracket_equal_needs_space : Error<
+ "a space is required between a right angle bracket and an equals sign "
+ "(use '> =')">;
+def warn_cxx11_right_shift_in_template_arg : Warning<
+ "use of right-shift operator ('>>') in template argument will require "
+ "parentheses in C++11">, InGroup<CXX11Compat>;
+def warn_cxx98_compat_two_right_angle_brackets : Warning<
+ "consecutive right angle brackets are incompatible with C++98 (use '> >')">,
+ InGroup<CXX98Compat>, DefaultIgnore;
+def err_templated_invalid_declaration : Error<
+ "a static_assert declaration cannot be a template">;
+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_template_defn_explicit_instantiation : Error<
+ "%select{function|class|variable}0 cannot be defined in an explicit instantiation; if this "
+ "declaration is meant to be a %select{function|class|variable}0 definition, remove the 'template' keyword">;
+def err_friend_explicit_instantiation : Error<
+ "friend cannot be declared in an explicit instantiation; if this "
+ "declaration is meant to be a friend declaration, remove the 'template' keyword">;
+def err_explicit_instantiation_enum : Error<
+ "enumerations cannot be explicitly instantiated">;
+def err_expected_template_parameter : Error<"expected template parameter">;
+
+def err_missing_dependent_template_keyword : Error<
+ "use 'template' keyword to treat '%0' as a dependent template name">;
+def warn_missing_dependent_template_keyword : ExtWarn<
+ "use 'template' keyword to treat '%0' as a dependent template name">;
+
+def ext_extern_template : Extension<
+ "extern templates are a C++11 extension">, InGroup<CXX11>;
+def warn_cxx98_compat_extern_template : Warning<
+ "extern templates are incompatible with C++98">,
+ InGroup<CXX98CompatPedantic>, DefaultIgnore;
+def warn_static_inline_explicit_inst_ignored : Warning<
+ "ignoring '%select{static|inline}0' keyword on explicit template "
+ "instantiation">, InGroup<DiagGroup<"static-inline-explicit-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_type_names_constructor : Error<
+ "qualified reference to %0 is a constructor name rather than a "
+ "%select{template name|type}1 wherever a constructor can be declared">;
+
+def err_expected_qualified_after_typename : Error<
+ "expected a qualified name after 'typename'">;
+def warn_expected_qualified_after_typename : ExtWarn<
+ "expected a qualified name after 'typename'">;
+
+def err_typename_refers_to_non_type_template : Error<
+ "typename specifier refers to a non-type 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 %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 ext_fold_expression : ExtWarn<
+ "pack fold expression is a C++1z extension">,
+ InGroup<CXX1z>;
+def warn_cxx14_compat_fold_expression : Warning<
+ "pack fold expression is incompatible with C++ standards before C++1z">,
+ InGroup<CXXPre1zCompat>, DefaultIgnore;
+def err_expected_fold_operator : Error<
+ "expected a foldable binary operator in fold expression">;
+def err_fold_operator_mismatch : Error<
+ "operators in fold expression must be the same">;
+
+def err_ctor_init_missing_comma : Error<
+ "missing ',' between base or member initializers">;
+
+// C++ declarations
+def err_friend_decl_defines_type : Error<
+ "cannot define a type in a friend declaration">;
+def err_missing_whitespace_digraph : Error<
+ "found '<::' after a "
+ "%select{template name|const_cast|dynamic_cast|reinterpret_cast|static_cast}0"
+ " which forms the digraph '<:' (aka '[') and a ':', did you mean '< ::'?">;
+
+def ext_defaulted_deleted_function : ExtWarn<
+ "%select{defaulted|deleted}0 function definitions are a C++11 extension">,
+ InGroup<CXX11>;
+def warn_cxx98_compat_defaulted_deleted_function : Warning<
+ "%select{defaulted|deleted}0 function definitions are incompatible with C++98">,
+ InGroup<CXX98Compat>, DefaultIgnore;
+
+// C++11 in-class member initialization
+def ext_nonstatic_member_init : ExtWarn<
+ "in-class initialization of non-static data member is a C++11 extension">,
+ InGroup<CXX11>;
+def warn_cxx98_compat_nonstatic_member_init : Warning<
+ "in-class initialization of non-static data members is incompatible with C++98">,
+ InGroup<CXX98Compat>, DefaultIgnore;
+def err_bitfield_member_init: Error<
+ "bitfield member cannot have an in-class initializer">;
+def err_incomplete_array_member_init: Error<
+ "array bound cannot be deduced from an in-class initializer">;
+
+// C++11 alias-declaration
+def ext_alias_declaration : ExtWarn<
+ "alias declarations are a C++11 extension">, InGroup<CXX11>;
+def warn_cxx98_compat_alias_declaration : Warning<
+ "alias declarations are incompatible with C++98">,
+ InGroup<CXX98Compat>, DefaultIgnore;
+def err_alias_declaration_not_identifier : Error<
+ "name defined in alias declaration must be an identifier">;
+def err_alias_declaration_specialization : Error<
+ "%select{partial specialization|explicit specialization|explicit instantiation}0 of alias templates is not permitted">;
+
+// C++11 override control
+def ext_override_control_keyword : ExtWarn<
+ "'%0' keyword is a C++11 extension">, InGroup<CXX11>;
+def warn_cxx98_compat_override_control_keyword : Warning<
+ "'%0' keyword is incompatible with C++98">,
+ InGroup<CXX98Compat>, DefaultIgnore;
+def err_override_control_interface : Error<
+ "'%0' keyword not permitted with interface types">;
+def ext_ms_sealed_keyword : ExtWarn<
+ "'sealed' keyword is a Microsoft extension">,
+ InGroup<MicrosoftSealed>;
+
+def err_access_specifier_interface : Error<
+ "interface types cannot specify '%select{private|protected}0' access">;
+
+def err_duplicate_virt_specifier : Error<
+ "class member already marked '%0'">;
+
+def err_scoped_enum_missing_identifier : Error<
+ "scoped enumeration requires a name">;
+def ext_scoped_enum : ExtWarn<
+ "scoped enumerations are a C++11 extension">, InGroup<CXX11>;
+def warn_cxx98_compat_scoped_enum : Warning<
+ "scoped enumerations are incompatible with C++98">,
+ InGroup<CXX98Compat>, DefaultIgnore;
+
+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">;
+
+// C++11 lambda expressions
+def err_expected_comma_or_rsquare : Error<
+ "expected ',' or ']' in lambda capture list">;
+def err_this_captured_by_reference : Error<
+ "'this' cannot be captured by reference">;
+def err_expected_capture : Error<
+ "expected variable name or 'this' in lambda capture list">;
+def err_expected_lambda_body : Error<"expected body of lambda expression">;
+def warn_cxx98_compat_lambda : Warning<
+ "lambda expressions are incompatible with C++98">,
+ InGroup<CXX98Compat>, DefaultIgnore;
+def err_lambda_missing_parens : Error<
+ "lambda requires '()' before %select{'mutable'|return type|"
+ "attribute specifier}0">;
+
+// Availability attribute
+def err_expected_version : Error<
+ "expected a version of the form 'major[.minor[.subminor]]'">;
+def warn_expected_consistent_version_separator : Warning<
+ "use same version number separators '_' or '.'; as in "
+ "'major[.minor[.subminor]]'">, InGroup<Availability>;
+def err_zero_version : Error<
+ "version number must have non-zero major, minor, or sub-minor version">;
+def err_availability_expected_platform : Error<
+ "expected a platform name, e.g., 'macosx'">;
+
+// objc_bridge_related attribute
+def err_objcbridge_related_expected_related_class : Error<
+ "expected a related ObjectiveC class name, e.g., 'NSColor'">;
+def err_objcbridge_related_selector_name : Error<
+ "expected a class method selector with single argument, e.g., 'colorWithCGColor:'">;
+
+def err_availability_expected_change : Error<
+ "expected 'introduced', 'deprecated', or 'obsoleted'">;
+def err_availability_unknown_change : Error<
+ "%0 is not an availability stage; use 'introduced', 'deprecated', or "
+ "'obsoleted'">;
+def err_availability_redundant : Error<
+ "redundant %0 availability change; only the last specified change will "
+ "be used">;
+def warn_availability_and_unavailable : Warning<
+ "'unavailable' availability overrides all other availability information">,
+ InGroup<Availability>;
+
+// Type safety attributes
+def err_type_safety_unknown_flag : Error<
+ "invalid comparison flag %0; use 'layout_compatible' or 'must_be_null'">;
+
+// Type traits
+def err_type_trait_arity : Error<
+ "type trait requires %0%select{| or more}1 argument%select{|s}2; have "
+ "%3 argument%s3">;
+
+// Language specific pragmas
+// - Generic warnings
+def warn_pragma_expected_lparen : Warning<
+ "missing '(' after '#pragma %0' - ignoring">, InGroup<IgnoredPragmas>;
+def warn_pragma_expected_rparen : Warning<
+ "missing ')' after '#pragma %0' - ignoring">, InGroup<IgnoredPragmas>;
+def warn_pragma_expected_identifier : Warning<
+ "expected identifier in '#pragma %0' - ignored">, InGroup<IgnoredPragmas>;
+def warn_pragma_expected_section_name : Warning<
+ "expected a string literal for the section name in '#pragma %0' - ignored">,
+ InGroup<IgnoredPragmas>;
+def warn_pragma_expected_section_push_pop_or_name : Warning<
+ "expected push, pop or a string literal for the section name in '#pragma %0' - ignored">,
+ InGroup<IgnoredPragmas>;
+def warn_pragma_expected_section_label_or_name : Warning<
+ "expected a stack label or a string literal for the section name in '#pragma %0' - ignored">,
+ InGroup<IgnoredPragmas>;
+def warn_pragma_expected_init_seg : Warning<
+ "expected 'compiler', 'lib', 'user', or a string literal for the section name in '#pragma %0' - ignored">,
+ InGroup<IgnoredPragmas>;
+def warn_pragma_expected_integer : Warning<
+ "expected integer between %0 and %1 inclusive in '#pragma %2' - ignored">,
+ InGroup<IgnoredPragmas>;
+def warn_pragma_ms_struct : Warning<
+ "incorrect use of '#pragma ms_struct on|off' - ignored">,
+ InGroup<IgnoredPragmas>;
+def warn_pragma_extra_tokens_at_eol : Warning<
+ "extra tokens at end of '#pragma %0' - ignored">,
+ InGroup<IgnoredPragmas>;
+def warn_pragma_expected_punc : Warning<
+ "expected ')' or ',' in '#pragma %0'">, InGroup<IgnoredPragmas>;
+def warn_pragma_expected_non_wide_string : Warning<
+ "expected non-wide string literal in '#pragma %0'">, InGroup<IgnoredPragmas>;
+// - Generic errors
+def err_pragma_missing_argument : Error<
+ "missing argument to '#pragma %0'%select{|; expected %2}1">;
+// - #pragma options
+def warn_pragma_options_expected_align : Warning<
+ "expected 'align' following '#pragma options' - ignored">,
+ InGroup<IgnoredPragmas>;
+def warn_pragma_align_expected_equal : Warning<
+ "expected '=' following '#pragma %select{align|options align}0' - ignored">,
+ InGroup<IgnoredPragmas>;
+def warn_pragma_align_invalid_option : Warning<
+ "invalid alignment option in '#pragma %select{align|options align}0' - ignored">,
+ InGroup<IgnoredPragmas>;
+// - #pragma pack
+def warn_pragma_unsupported_action : Warning<
+ "known but unsupported action '%1' for '#pragma %0' - ignored">,
+ InGroup<IgnoredPragmas>;
+def warn_pragma_invalid_specific_action : Warning<
+ "unknown action '%1' for '#pragma %0' - ignored">,
+ InGroup<IgnoredPragmas>;
+def warn_pragma_expected_action_or_r_paren : Warning<
+ "expected action or ')' in '#pragma %0' - ignored">,
+ InGroup<IgnoredPragmas>;
+def warn_pragma_invalid_action : Warning<
+ "unknown action for '#pragma %0' - ignored">,
+ InGroup<IgnoredPragmas>;
+def warn_pragma_pack_malformed : Warning<
+ "expected integer or identifier in '#pragma pack' - ignored">,
+ InGroup<IgnoredPragmas>;
+// - #pragma unused
+def warn_pragma_unused_expected_var : Warning<
+ "expected '#pragma unused' argument to be a variable name">,
+ InGroup<IgnoredPragmas>;
+// - #pragma init_seg
+def warn_pragma_init_seg_unsupported_target : Warning<
+ "'#pragma init_seg' is only supported when targeting a "
+ "Microsoft environment">,
+ InGroup<IgnoredPragmas>;
+// - #pragma fp_contract
+def err_pragma_fp_contract_scope : Error<
+ "'#pragma fp_contract' can only appear at file scope or at the start of a "
+ "compound statement">;
+// - #pragma comment
+def err_pragma_comment_malformed : Error<
+ "pragma comment requires parenthesized identifier and optional string">;
+def err_pragma_comment_unknown_kind : Error<"unknown kind of pragma comment">;
+// PS4 recognizes only #pragma comment(lib)
+def warn_pragma_comment_ignored : Warning<"'#pragma comment %0' ignored">,
+ InGroup<IgnoredPragmas>;
+// - #pragma detect_mismatch
+def err_pragma_detect_mismatch_malformed : Error<
+ "pragma detect_mismatch is malformed; it requires two comma-separated "
+ "string literals">;
+// - #pragma pointers_to_members
+def err_pragma_pointers_to_members_unknown_kind : Error<
+ "unexpected %0, expected to see one of %select{|'best_case', 'full_generality', }1"
+ "'single_inheritance', 'multiple_inheritance', or 'virtual_inheritance'">;
+// - #pragma clang optimize on/off
+def err_pragma_optimize_invalid_argument : Error<
+ "unexpected argument '%0' to '#pragma clang optimize'; "
+ "expected 'on' or 'off'">;
+def err_pragma_optimize_extra_argument : Error<
+ "unexpected extra argument '%0' to '#pragma clang optimize'">;
+
+// OpenCL EXTENSION pragma (OpenCL 1.1 [9.1])
+def warn_pragma_expected_colon : Warning<
+ "missing ':' after %0 - ignoring">, InGroup<IgnoredPragmas>;
+def warn_pragma_expected_enable_disable : Warning<
+ "expected 'enable' or 'disable' - ignoring">, InGroup<IgnoredPragmas>;
+def warn_pragma_unknown_extension : Warning<
+ "unknown OpenCL extension %0 - ignoring">, InGroup<IgnoredPragmas>;
+
+// OpenCL error
+def err_opencl_taking_function_address_parser : Error<
+ "taking address of function is not allowed">;
+
+// OpenMP support.
+def warn_pragma_omp_ignored : Warning<
+ "unexpected '#pragma omp ...' in program">, InGroup<SourceUsesOpenMP>, DefaultIgnore;
+def warn_omp_extra_tokens_at_eol : Warning<
+ "extra tokens at the end of '#pragma omp %0' are ignored">,
+ InGroup<ExtraTokens>;
+def warn_pragma_expected_colon_r_paren : Warning<
+ "missing ':' or ')' after %0 - ignoring">, InGroup<IgnoredPragmas>;
+def err_omp_unknown_directive : Error<
+ "expected an OpenMP directive">;
+def err_omp_unexpected_directive : Error<
+ "unexpected OpenMP directive '#pragma omp %0'">;
+def err_omp_expected_punc : Error<
+ "expected ',' or ')' in '%0' %select{clause|directive}1">;
+def err_omp_unexpected_clause : Error<
+ "unexpected OpenMP clause '%0' in directive '#pragma omp %1'">;
+def err_omp_immediate_directive : Error<
+ "'#pragma omp %0' %select{|with '%2' clause }1cannot be an immediate substatement">;
+def err_omp_expected_identifier_for_critical : Error<
+ "expected identifier specifying the name of the 'omp critical' directive">;
+def err_omp_unknown_map_type : Error<
+ "incorrect map type, expected one of 'to', 'from', 'tofrom', 'alloc', 'release', or 'delete'">;
+def err_omp_unknown_map_type_modifier : Error<
+ "incorrect map type modifier, expected 'always'">;
+def err_omp_map_type_missing : Error<
+ "missing map type">;
+
+// Pragma loop support.
+def err_pragma_loop_missing_argument : Error<
+ "missing argument; expected %select{an integer value|"
+ "'enable', %select{'assume_safety'|'full'}1 or 'disable'}0">;
+def err_pragma_loop_invalid_option : Error<
+ "%select{invalid|missing}0 option%select{ %1|}0; expected vectorize, "
+ "vectorize_width, interleave, interleave_count, unroll, or unroll_count">;
+def err_pragma_invalid_keyword : Error<
+ "invalid argument; expected 'enable', %select{'assume_safety'|'full'}0 or 'disable'">;
+
+// Pragma unroll support.
+def warn_pragma_unroll_cuda_value_in_parens : Warning<
+ "argument to '#pragma unroll' should not be in parentheses in CUDA C/C++">,
+ InGroup<CudaCompat>;
+} // end of Parse Issue category.
+
+let CategoryName = "Modules Issue" in {
+def err_module_expected_ident : Error<
+ "expected a module name after module import">;
+def err_module_expected_semi : Error<
+ "expected ';' after module name">;
+def err_missing_before_module_end : Error<"expected %0 at end of module">;
+}
+
+let CategoryName = "Generics Issue" in {
+
+def err_objc_expected_type_parameter : Error<
+ "expected type parameter name">;
+
+def err_objc_parameterized_implementation : Error<
+ "@implementation cannot have type parameters">;
+
+def err_objc_type_args_after_protocols : Error<
+ "protocol qualifiers must precede type arguments">;
+}
+
+let CategoryName = "Coroutines Issue" in {
+def err_for_co_await_not_range_for : Error<
+ "'co_await' modifier can only be applied to range-based for loop">;
+}
+
+} // 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..59f5095
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -0,0 +1,8221 @@
+
+//==--- 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 {
+
+def note_previous_decl : Note<"%0 declared here">;
+def note_entity_declared_at : Note<"%0 declared here">;
+def note_callee_decl : Note<"%0 declared here">;
+def note_defined_here : Note<"%0 defined here">;
+
+// For loop analysis
+def warn_variables_not_in_loop_body : Warning<
+ "variable%select{s| %1|s %1 and %2|s %1, %2, and %3|s %1, %2, %3, and %4}0 "
+ "used in loop condition not modified in loop body">,
+ InGroup<ForLoopAnalysis>, DefaultIgnore;
+def warn_redundant_loop_iteration : Warning<
+ "variable %0 is %select{decremented|incremented}1 both in the loop header "
+ "and in the loop body">,
+ InGroup<ForLoopAnalysis>, DefaultIgnore;
+def note_loop_iteration_here : Note<"%select{decremented|incremented}0 here">;
+
+def warn_for_range_const_reference_copy : Warning<
+ "loop variable %0 "
+ "%diff{has type $ but is initialized with type $"
+ "| is initialized with a value of a different type}1,2 resulting in a copy">,
+ InGroup<RangeLoopAnalysis>, DefaultIgnore;
+def note_use_type_or_non_reference : Note<
+ "use non-reference type %0 to keep the copy or type %1 to prevent copying">;
+def warn_for_range_variable_always_copy : Warning<
+ "loop variable %0 is always a copy because the range of type %1 does not "
+ "return a reference">,
+ InGroup<RangeLoopAnalysis>, DefaultIgnore;
+def note_use_non_reference_type : Note<"use non-reference type %0">;
+def warn_for_range_copy : Warning<
+ "loop variable %0 of type %1 creates a copy from type %2">,
+ InGroup<RangeLoopAnalysis>, DefaultIgnore;
+def note_use_reference_type : Note<"use reference type %0 to prevent copying">;
+
+def warn_duplicate_enum_values : Warning<
+ "element %0 has been implicitly assigned %1 which another element has "
+ "been assigned">, InGroup<DiagGroup<"duplicate-enum">>, DefaultIgnore;
+def note_duplicate_element : Note<"element %0 also has value %1">;
+
+// Absolute value functions
+def warn_unsigned_abs : Warning<
+ "taking the absolute value of unsigned type %0 has no effect">,
+ InGroup<AbsoluteValue>;
+def note_remove_abs : Note<
+ "remove the call to '%0' since unsigned values cannot be negative">;
+def warn_abs_too_small : Warning<
+ "absolute value function %0 given an argument of type %1 but has parameter "
+ "of type %2 which may cause truncation of value">, InGroup<AbsoluteValue>;
+def warn_wrong_absolute_value_type : Warning<
+ "using %select{integer|floating point|complex}1 absolute value function %0 "
+ "when argument is of %select{integer|floating point|complex}2 type">,
+ InGroup<AbsoluteValue>;
+def note_replace_abs_function : Note<"use function '%0' instead">;
+def warn_pointer_abs : Warning<
+ "taking the absolute value of %select{pointer|function|array}0 type %1 is suspicious">,
+ InGroup<AbsoluteValue>;
+
+def warn_infinite_recursive_function : Warning<
+ "all paths through this function will call itself">,
+ InGroup<InfiniteRecursion>, DefaultIgnore;
+
+// Constant expressions
+def err_expr_not_ice : Error<
+ "expression is not an %select{integer|integral}0 constant expression">;
+def ext_expr_not_ice : Extension<
+ "expression is not an %select{integer|integral}0 constant expression; "
+ "folding it to a constant is a GNU extension">, InGroup<GNUFoldingConstant>;
+def err_typecheck_converted_constant_expression : Error<
+ "value of type %0 is not implicitly convertible to %1">;
+def err_typecheck_converted_constant_expression_disallowed : Error<
+ "conversion from %0 to %1 is not allowed in a converted constant expression">;
+def err_typecheck_converted_constant_expression_indirect : Error<
+ "conversion from %0 to %1 in converted constant expression would "
+ "bind reference to a temporary">;
+def err_expr_not_cce : Error<
+ "%select{case value|enumerator value|non-type template argument|array size}0 "
+ "is not a constant expression">;
+def ext_cce_narrowing : ExtWarn<
+ "%select{case value|enumerator value|non-type template argument|array size}0 "
+ "%select{cannot be narrowed from type %2 to %3|"
+ "evaluates to %2, which cannot be narrowed to type %3}1">,
+ InGroup<CXX11Narrowing>, DefaultError, SFINAEFailure;
+def err_ice_not_integral : Error<
+ "integral constant expression must have integral or unscoped enumeration "
+ "type, not %0">;
+def err_ice_incomplete_type : Error<
+ "integral constant expression has incomplete class type %0">;
+def err_ice_explicit_conversion : Error<
+ "integral constant expression requires explicit conversion from %0 to %1">;
+def note_ice_conversion_here : Note<
+ "conversion to %select{integral|enumeration}0 type %1 declared here">;
+def err_ice_ambiguous_conversion : Error<
+ "ambiguous conversion from type %0 to an integral or unscoped "
+ "enumeration type">;
+def err_ice_too_large : Error<
+ "integer constant expression evaluates to value %0 that cannot be "
+ "represented in a %1-bit %select{signed|unsigned}2 integer type">;
+def err_expr_not_string_literal : Error<"expression is not a string literal">;
+
+// Semantic analysis of constant literals.
+def ext_predef_outside_function : Warning<
+ "predefined identifier is only valid inside function">,
+ InGroup<DiagGroup<"predefined-identifier-outside-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>;
+def warn_double_const_requires_fp64 : Warning<
+ "double precision constant requires cl_khr_fp64, casting to single precision">;
+
+// C99 variable-length arrays
+def ext_vla : Extension<"variable length arrays are a C99 feature">,
+ InGroup<VLAExtension>;
+def warn_vla_used : Warning<"variable length array used">,
+ InGroup<VLA>, DefaultIgnore;
+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 cannot have 'static' storage duration">;
+def err_vla_decl_has_extern_linkage : Error<
+ "variable length array declaration cannot have 'extern' linkage">;
+def ext_vla_folded_to_constant : Extension<
+ "variable length array folded to constant array as an extension">, InGroup<GNUFoldingConstant>;
+
+// 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">, InGroup<C99>;
+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<GNUFlexibleArrayInitializer>;
+
+// Declarations.
+def ext_duplicate_declspec : ExtWarn<"duplicate '%0' declaration specifier">,
+ InGroup<DuplicateDeclSpecifier>;
+def warn_duplicate_declspec : Warning<"duplicate '%0' declaration specifier">,
+ InGroup<DuplicateDeclSpecifier>;
+def ext_plain_complex : ExtWarn<
+ "plain '_Complex' requires a type specifier; assuming '_Complex double'">;
+def ext_integer_complex : Extension<
+ "complex integer types are a GNU extension">, InGroup<GNUComplexInteger>;
+
+def err_invalid_sign_spec : Error<"'%0' cannot be signed or unsigned">;
+def err_invalid_width_spec : Error<
+ "'%select{|short|long|long long}0 %1' is invalid">;
+def err_invalid_complex_spec : Error<"'_Complex %0' is invalid">;
+def err_friend_decl_spec : Error<"'%0' is invalid in friend declarations">;
+
+def ext_auto_type_specifier : ExtWarn<
+ "'auto' type specifier is a C++11 extension">, InGroup<CXX11>;
+def warn_auto_storage_class : Warning<
+ "'auto' storage class specifier is redundant and incompatible with C++11">,
+ InGroup<CXX11Compat>, DefaultIgnore;
+
+def warn_deprecated_register : Warning<
+ "'register' storage class specifier is deprecated "
+ "and incompatible with C++1z">, InGroup<DeprecatedRegister>;
+def ext_register_storage_class : ExtWarn<
+ "ISO C++1z does not allow 'register' storage class specifier">,
+ DefaultError, InGroup<Register>;
+
+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_bool_decl_spec : Error<
+ "cannot use '%0' with '__vector bool'">;
+def err_invalid_vector_long_decl_spec : Error<
+ "cannot use 'long' with '__vector'">;
+def err_invalid_vector_float_decl_spec : Error<
+ "cannot use 'float' with '__vector'">;
+def err_invalid_vector_double_decl_spec : Error <
+ "use of 'double' with '__vector' requires VSX support to be enabled "
+ "(available on POWER7 or later)">;
+def err_invalid_vector_long_long_decl_spec : Error <
+ "use of 'long long' with '__vector bool' requires VSX support (available on "
+ "POWER7 or later) or extended Altivec support (available on POWER8 or later) "
+ "to be enabled">;
+def err_invalid_vector_long_double_decl_spec : Error<
+ "cannot use 'long double' with '__vector'">;
+def warn_vector_long_decl_spec_combination : Warning<
+ "Use of 'long' with '__vector' is deprecated">, InGroup<Deprecated>;
+
+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_redeclaration_different_type : Error<
+ "redeclaration of %0 with a different type%diff{: $ vs $|}1,2">;
+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_mips_interrupt_attribute : Warning<
+ "MIPS 'interrupt' attribute only applies to functions that have "
+ "%select{no parameters|a 'void' return type}0">,
+ InGroup<IgnoredAttributes>;
+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_local_typedef : Warning<
+ "unused %select{typedef|type alias}0 %1">,
+ InGroup<UnusedLocalTypedef>, DefaultIgnore;
+def warn_unused_property_backing_ivar :
+ Warning<"ivar %0 which backs the property is not "
+ "referenced in this property's accessor">,
+ InGroup<UnusedPropertyIvar>, DefaultIgnore;
+def warn_unused_const_variable : Warning<"unused variable %0">,
+ InGroup<UnusedConstVariable>, 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">,
+ InGroup<Visibility>;
+def warn_redefinition_in_param_list : Warning<
+ "redefinition of %0 will not be visible outside of this function">,
+ InGroup<Visibility>;
+def warn_empty_parens_are_function_decl : Warning<
+ "empty parentheses interpreted as a function declaration">,
+ InGroup<VexingParse>;
+def warn_parens_disambiguated_as_function_declaration : Warning<
+ "parentheses were disambiguated as a function declaration">,
+ InGroup<VexingParse>;
+def note_additional_parens_for_variable_declaration : Note<
+ "add a pair of parentheses to declare a variable">;
+def note_empty_parens_function_call : Note<
+ "change this ',' to a ';' to call %0">;
+def note_empty_parens_default_ctor : Note<
+ "remove parentheses to declare a variable">;
+def note_empty_parens_zero_initialize : Note<
+ "replace parentheses with an initializer to declare a variable">;
+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_unneeded_internal_decl : Warning<
+ "%select{function|variable}0 %1 is not needed and will not be emitted">,
+ InGroup<UnneededInternalDecl>, DefaultIgnore;
+def warn_unneeded_static_internal_decl : Warning<
+ "'static' function %0 declared in header file "
+ "should be declared 'static inline'">,
+ InGroup<UnneededInternalDecl>, DefaultIgnore;
+def warn_unneeded_member_function : Warning<
+ "member function %0 is not needed and will not be emitted">,
+ InGroup<UnneededMemberFunction>, DefaultIgnore;
+def warn_unused_private_field: Warning<"private field %0 is not used">,
+ InGroup<UnusedPrivateField>, 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_return_value_udt: Warning<
+ "%0 has C-linkage specified, but returns user-defined type %1 which is "
+ "incompatible with C">, InGroup<ReturnTypeCLinkage>;
+def warn_return_value_udt_incomplete: Warning<
+ "%0 has C-linkage specified, but returns incomplete type %1 which could be "
+ "incompatible with C">, InGroup<ReturnTypeCLinkage>;
+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 note_function_suggestion : Note<"did you mean %0?">;
+
+def err_ellipsis_first_param : Error<
+ "ISO C requires a named parameter before '...'">;
+def err_declarator_need_ident : Error<"declarator requires an identifier">;
+def err_language_linkage_spec_unknown : Error<"unknown linkage language">;
+def err_language_linkage_spec_not_ascii : Error<
+ "string literal in language linkage specifier cannot have an "
+ "encoding-prefix">;
+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 err_noreturn_non_function : Error<
+ "'_Noreturn' 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, cannot inherit constructors">;
+def err_using_decl_constructor_conflict : Error<
+ "cannot 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 warn_using_decl_constructor_ellipsis : Warning<
+ "inheriting constructor does not inherit ellipsis">,
+ InGroup<DiagGroup<"inherited-variadic-ctor">>;
+def note_using_decl_constructor_ellipsis : Note<
+ "constructor declared with ellipsis here">;
+def err_using_decl_can_not_refer_to_class_member : Error<
+ "using declaration cannot refer to class member">;
+def note_using_decl_class_member_workaround : Note<
+ "use %select{an alias declaration|a typedef declaration|a reference}0 "
+ "instead">;
+def err_using_decl_can_not_refer_to_namespace : Error<
+ "using declaration cannot refer to namespace">;
+def err_using_decl_constructor : Error<
+ "using declaration cannot refer to a constructor">;
+def warn_cxx98_compat_using_decl_constructor : Warning<
+ "inheriting constructors are incompatible with C++98">,
+ InGroup<CXX98Compat>, DefaultIgnore;
+def err_using_decl_destructor : Error<
+ "using declaration cannot refer to a destructor">;
+def err_using_decl_template_id : Error<
+ "using declaration cannot 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 err_access_decl : Error<
+ "ISO C++11 does not allow access declarations; "
+ "use using declarations instead">;
+def warn_exception_spec_deprecated : Warning<
+ "dynamic exception specifications are deprecated">,
+ InGroup<Deprecated>, DefaultIgnore;
+def note_exception_spec_deprecated : Note<"use '%0' instead">;
+def warn_deprecated_copy_operation : Warning<
+ "definition of implicit copy %select{constructor|assignment operator}1 "
+ "for %0 is deprecated because it has a user-declared "
+ "%select{copy %select{assignment operator|constructor}1|destructor}2">,
+ InGroup<Deprecated>, DefaultIgnore;
+
+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 warn_exit_time_destructor : Warning<
+ "declaration requires an exit-time destructor">,
+ InGroup<ExitTimeDestructors>, DefaultIgnore;
+
+def err_invalid_thread : Error<
+ "'%0' is only allowed on variable declarations">;
+def err_thread_non_global : Error<
+ "'%0' variables must have global storage">;
+def err_thread_unsupported : Error<
+ "thread-local storage is not supported 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<
+ "%select{function|method}0 %1 could be declared with attribute 'noreturn'">,
+ InGroup<MissingNoreturn>, DefaultIgnore;
+def warn_suggest_noreturn_block : Warning<
+ "block could be declared with attribute 'noreturn'">,
+ InGroup<MissingNoreturn>, DefaultIgnore;
+
+// Unreachable code.
+def warn_unreachable : Warning<
+ "code will never be executed">,
+ InGroup<UnreachableCode>, DefaultIgnore;
+def warn_unreachable_break : Warning<
+ "'break' will never be executed">,
+ InGroup<UnreachableCodeBreak>, DefaultIgnore;
+def warn_unreachable_return : Warning<
+ "'return' will never be executed">,
+ InGroup<UnreachableCodeReturn>, DefaultIgnore;
+def warn_unreachable_loop_increment : Warning<
+ "loop will run at most once (loop increment never executed)">,
+ InGroup<UnreachableCodeLoopIncrement>, DefaultIgnore;
+def note_unreachable_silence : Note<
+ "silence by adding parentheses to mark code as explicitly dead">;
+
+/// Built-in functions.
+def ext_implicit_lib_function_decl : ExtWarn<
+ "implicitly declaring library function '%0' with type %1">,
+ InGroup<ImplicitFunctionDeclare>;
+def note_include_header_or_declare : Note<
+ "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_sysheader : Warning<
+ "declaration of built-in function '%1' requires inclusion of the header <%0>">,
+ InGroup<BuiltinRequiresHeader>;
+def warn_redecl_library_builtin : Warning<
+ "incompatible redeclaration of library function %0">,
+ InGroup<DiagGroup<"incompatible-library-redeclaration">>;
+def err_builtin_definition : Error<"definition of builtin function %0">;
+def err_arm_invalid_specialreg : Error<"invalid special register for builtin">;
+def err_invalid_cpu_supports : Error<"invalid cpu feature string for builtin">;
+def err_builtin_needs_feature : Error<"%0 needs target feature %1">;
+def err_function_needs_feature
+ : Error<"always_inline function %1 requires target feature '%2', but would "
+ "be inlined into function %0 that is compiled without support for "
+ "'%2'">;
+def warn_builtin_unknown : Warning<"use of unknown builtin %0">,
+ InGroup<ImplicitFunctionDeclare>, DefaultError;
+def warn_dyn_class_memaccess : Warning<
+ "%select{destination for|source of|first operand of|second operand of}0 this "
+ "%1 call is a pointer to %select{|class containing a }2dynamic class %3; "
+ "vtable pointer will be %select{overwritten|copied|moved|compared}4">,
+ InGroup<DiagGroup<"dynamic-class-memaccess">>;
+def note_bad_memaccess_silence : Note<
+ "explicitly cast the pointer to silence this warning">;
+def warn_sizeof_pointer_expr_memaccess : Warning<
+ "'%0' call operates on objects of type %1 while the size is based on a "
+ "different type %2">,
+ InGroup<SizeofPointerMemaccess>;
+def warn_sizeof_pointer_expr_memaccess_note : Note<
+ "did you mean to %select{dereference the argument to 'sizeof' (and multiply "
+ "it by the number of elements)|remove the addressof in the argument to "
+ "'sizeof' (and multiply it by the number of elements)|provide an explicit "
+ "length}0?">;
+def warn_sizeof_pointer_type_memaccess : Warning<
+ "argument to 'sizeof' in %0 call is the same pointer type %1 as the "
+ "%select{destination|source}2; expected %3 or an explicit length">,
+ InGroup<SizeofPointerMemaccess>;
+def warn_strlcpycat_wrong_size : Warning<
+ "size argument in %0 call appears to be size of the source; "
+ "expected the size of the destination">,
+ InGroup<DiagGroup<"strlcpy-strlcat-size">>;
+def note_strlcpycat_wrong_size : Note<
+ "change size argument to be the size of the destination">;
+def warn_memsize_comparison : Warning<
+ "size argument in %0 call is a comparison">,
+ InGroup<DiagGroup<"memsize-comparison">>;
+def note_memsize_comparison_paren : Note<
+ "did you mean to compare the result of %0 instead?">;
+def note_memsize_comparison_cast_silence : Note<
+ "explicitly cast the argument to size_t to silence this warning">;
+
+def warn_strncat_large_size : Warning<
+ "the value of the size argument in 'strncat' is too large, might lead to a "
+ "buffer overflow">, InGroup<StrncatSize>;
+def warn_strncat_src_size : Warning<"size argument in 'strncat' call appears "
+ "to be size of the source">, InGroup<StrncatSize>;
+def warn_strncat_wrong_size : Warning<
+ "the value of the size argument to 'strncat' is wrong">, InGroup<StrncatSize>;
+def note_strncat_wrong_size : Note<
+ "change the argument to be the free space in the destination buffer minus "
+ "the terminating null byte">;
+
+def warn_assume_side_effects : Warning<
+ "the argument to %0 has side effects that will be discarded">,
+ InGroup<DiagGroup<"assume">>;
+
+def warn_memcpy_chk_overflow : Warning<
+ "%0 will always overflow destination buffer">,
+ InGroup<DiagGroup<"builtin-memcpy-chk-size">>;
+
+/// main()
+// static main() is not an error in C, just in C++.
+def warn_static_main : Warning<"'main' should not be declared static">,
+ InGroup<Main>;
+def err_static_main : Error<"'main' is not allowed to be declared static">;
+def err_inline_main : Error<"'main' is not allowed to be declared inline">;
+def ext_variadic_main : ExtWarn<
+ "'main' is not allowed to be declared variadic">, InGroup<Main>;
+def ext_noreturn_main : ExtWarn<
+ "'main' is not allowed to be declared _Noreturn">, InGroup<Main>;
+def note_main_remove_noreturn : Note<"remove '_Noreturn'">;
+def err_constexpr_main : Error<
+ "'main' is not allowed to be declared constexpr">;
+def err_deleted_main : Error<"'main' is not allowed to be deleted">;
+def err_mainlike_template_decl : Error<"%0 cannot be a template">;
+def err_main_returns_nonint : Error<"'main' must return 'int'">;
+def ext_main_returns_nonint : ExtWarn<"return type of 'main' is not 'int'">,
+ InGroup<MainReturnType>;
+def note_main_change_return_type : Note<"change return type to '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">,
+ InGroup<Main>;
+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">;
+def err_main_global_variable :
+ Error<"main cannot be declared as global variable">;
+def warn_main_redefined : Warning<"variable named 'main' with external linkage "
+ "has undefined behavior">, InGroup<Main>;
+def ext_main_used : Extension<
+ "ISO C++ does not allow 'main' to be used by a program">, InGroup<Main>;
+
+/// parser diagnostics
+def ext_no_declarators : ExtWarn<"declaration does not declare anything">,
+ InGroup<MissingDeclarations>;
+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_typedef_changes_linkage : Error<"unsupported: typedef changes linkage"
+ " of anonymous type, but linkage was already computed">;
+def note_typedef_changes_linkage : Note<"use a tag name here to establish "
+ "linkage prior to definition">;
+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 err_parameters_retval_cannot_have_fp16_type : Error<
+ "%select{parameters|function return value}0 cannot have __fp16 type; did you forget * ?">;
+def err_opencl_half_load_store : Error<
+ "%select{loading directly from|assigning directly to}0 pointer to type %1 is not allowed">;
+def err_opencl_cast_to_half : Error<"casting to type %0 is not allowed">;
+def err_opencl_half_declaration : Error<
+ "declaring variable of type %0 is not allowed">;
+def err_opencl_half_param : Error<
+ "declaring function parameter of type %0 is not allowed; did you forget * ?">;
+def err_opencl_half_return : Error<
+ "declaring function return value of type %0 is not allowed; did you forget * ?">;
+def warn_enum_value_overflow : Warning<"overflow in enumeration value">;
+def warn_pragma_options_align_reset_failed : Warning<
+ "#pragma options align=reset failed: %0">,
+ InGroup<IgnoredPragmas>;
+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'">,
+ InGroup<IgnoredPragmas>;
+// Follow the Microsoft 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_pop_failed : Warning<"#pragma %0(pop, ...) failed: %1">,
+ InGroup<IgnoredPragmas>;
+def warn_cxx_ms_struct :
+ Warning<"ms_struct may not produce Microsoft-compatible layouts for classes "
+ "with base classes or virtual functions">,
+ DefaultError, InGroup<IncompatibleMSStruct>;
+def err_section_conflict : Error<"%0 causes a section type conflict with %1">;
+def err_no_base_classes : Error<"invalid use of '__super', %0 has no base classes">;
+def err_invalid_super_scope : Error<"invalid use of '__super', "
+ "this keyword can only be used inside class or member function scope">;
+def err_super_in_lambda_unsupported : Error<
+ "use of '__super' inside a lambda is unsupported">;
+
+def warn_pragma_unused_undeclared_var : Warning<
+ "undeclared variable %0 used as an argument for '#pragma unused'">,
+ InGroup<IgnoredPragmas>;
+def warn_pragma_unused_expected_var_arg : Warning<
+ "only variables can be arguments to '#pragma unused'">,
+ InGroup<IgnoredPragmas>;
+def err_pragma_push_visibility_mismatch : Error<
+ "#pragma visibility push with no matching #pragma visibility pop">;
+def note_surrounding_namespace_ends_here : Note<
+ "surrounding namespace with visibility attribute ends here">;
+def err_pragma_pop_visibility_mismatch : Error<
+ "#pragma visibility pop with no matching #pragma visibility push">;
+def note_surrounding_namespace_starts_here : Note<
+ "surrounding namespace with visibility attribute starts here">;
+def err_pragma_loop_invalid_argument_type : Error<
+ "invalid argument of type %0; expected an integer type">;
+def err_pragma_loop_invalid_argument_value : Error<
+ "%select{invalid value '%0'; must be positive|value '%0' is too large}1">;
+def err_pragma_loop_compatibility : Error<
+ "%select{incompatible|duplicate}0 directives '%1' and '%2'">;
+def err_pragma_loop_precedes_nonloop : Error<
+ "expected a for, while, or do-while loop to follow '%0'">;
+
+/// 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_forward_superclass : Error<
+ "attempting to use the forward class %0 as 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 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_atprotocol_protocol : Warning<
+ "@protocol is using a forward protocol declaration of %0">, InGroup<AtProtocol>;
+def warn_readonly_property : Warning<
+ "attribute 'readonly' of property %0 restricts attribute "
+ "'readwrite' of property inherited from %1">,
+ InGroup<PropertyAttr>;
+
+def warn_property_attribute : Warning<
+ "'%1' attribute on property %0 does not match the property inherited from %2">,
+ InGroup<PropertyAttr>;
+def warn_property_types_are_incompatible : Warning<
+ "property type %0 is incompatible with type %1 inherited from %2">,
+ InGroup<DiagGroup<"incompatible-property-type">>;
+def warn_protocol_property_mismatch : Warning<
+ "property of type %0 was selected for synthesis">,
+ InGroup<DiagGroup<"protocol-property-synthesis-ambiguity">>;
+def err_undef_interface : Error<"cannot find interface declaration for %0">;
+def err_category_forward_interface : Error<
+ "cannot define %select{category|class extension}0 for undefined class %1">;
+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 note_while_in_implementation : Note<
+ "detected while default synthesizing properties in class implementation">;
+def note_class_declared : Note<
+ "class is declared here">;
+def note_receiver_class_declared : Note<
+ "receiver is instance of class declared here">;
+def note_receiver_expr_here : Note<
+ "receiver expression is here">;
+def note_receiver_is_id : Note<
+ "receiver is treated with 'id' type for purpose of method lookup">;
+def note_suppressed_class_declare : Note<
+ "class with specified objc_requires_property_definitions attribute is declared here">;
+def err_objc_root_class_subclass : Error<
+ "objc_root_class attribute may only be specified on a root class declaration">;
+def warn_objc_root_class_missing : Warning<
+ "class %0 defined without specifying a base class">,
+ InGroup<ObjCRootClass>;
+def note_objc_needs_superclass : Note<
+ "add a super class to fix this problem">;
+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%diff{: $ vs $|}1,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_inconsistent_ivar_count : Error<
+ "inconsistent number of instance variables specified">;
+def warn_undef_method_impl : Warning<"method definition for %0 not found">,
+ InGroup<DiagGroup<"incomplete-implementation">>;
+
+def warn_conflicting_overriding_ret_types : Warning<
+ "conflicting return type in "
+ "declaration of %0%diff{: $ vs $|}1,2">,
+ InGroup<OverridingMethodMismatch>, DefaultIgnore;
+
+def warn_conflicting_ret_types : Warning<
+ "conflicting return type in "
+ "implementation of %0%diff{: $ vs $|}1,2">,
+ InGroup<MismatchedReturnTypes>;
+
+def warn_conflicting_overriding_ret_type_modifiers : Warning<
+ "conflicting distributed object modifiers on return type "
+ "in declaration of %0">,
+ InGroup<OverridingMethodMismatch>, DefaultIgnore;
+
+def warn_conflicting_ret_type_modifiers : Warning<
+ "conflicting distributed object modifiers on return type "
+ "in implementation of %0">,
+ InGroup<DistributedObjectModifiers>;
+
+def warn_non_covariant_overriding_ret_types : Warning<
+ "conflicting return type in "
+ "declaration of %0: %1 vs %2">,
+ InGroup<OverridingMethodMismatch>, DefaultIgnore;
+
+def warn_non_covariant_ret_types : Warning<
+ "conflicting return type in "
+ "implementation of %0: %1 vs %2">,
+ InGroup<MethodSignatures>, DefaultIgnore;
+
+def warn_conflicting_overriding_param_types : Warning<
+ "conflicting parameter types in "
+ "declaration of %0%diff{: $ vs $|}1,2">,
+ InGroup<OverridingMethodMismatch>, DefaultIgnore;
+
+def warn_conflicting_param_types : Warning<
+ "conflicting parameter types in "
+ "implementation of %0%diff{: $ vs $|}1,2">,
+ InGroup<MismatchedParameterTypes>;
+
+def warn_conflicting_param_modifiers : Warning<
+ "conflicting distributed object modifiers on parameter type "
+ "in implementation of %0">,
+ InGroup<DistributedObjectModifiers>;
+
+def warn_conflicting_overriding_param_modifiers : Warning<
+ "conflicting distributed object modifiers on parameter type "
+ "in declaration of %0">,
+ InGroup<OverridingMethodMismatch>, DefaultIgnore;
+
+def warn_non_contravariant_overriding_param_types : Warning<
+ "conflicting parameter types in "
+ "declaration of %0: %1 vs %2">,
+ InGroup<OverridingMethodMismatch>, DefaultIgnore;
+
+def warn_non_contravariant_param_types : Warning<
+ "conflicting parameter types in "
+ "implementation of %0: %1 vs %2">,
+ InGroup<MethodSignatures>, DefaultIgnore;
+
+def warn_conflicting_overriding_variadic :Warning<
+ "conflicting variadic declaration of method and its "
+ "implementation">,
+ InGroup<OverridingMethodMismatch>, DefaultIgnore;
+
+def warn_conflicting_variadic :Warning<
+ "conflicting variadic declaration of method and its "
+ "implementation">;
+
+def warn_category_method_impl_match:Warning<
+ "category is implementing a method which will also be implemented"
+ " by its primary class">, InGroup<ObjCProtocolMethodImpl>;
+
+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">,
+ InGroup<ObjCMultipleMethodNames>;
+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 not_conv_function_declared_at : Note<"type conversion function declared here">;
+def note_method_declared_at : Note<"method %0 declared here">;
+def note_property_attribute : Note<"property %0 is declared "
+ "%select{deprecated|unavailable|partial}1 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_duplicate_method_decl :
+ Warning<"multiple declarations of method %0 found and ignored">,
+ InGroup<MethodDuplicate>, DefaultIgnore;
+def warn_objc_cdirective_format_string :
+ Warning<"using %0 directive in %select{NSString|CFString}1 "
+ "which is being passed as a formatting argument to the formatting "
+ "%select{method|CFfunction}2">,
+ InGroup<ObjCCStringFormat>, DefaultIgnore;
+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">,
+ InGroup<ObjCPropertyNoAttribute>;
+def warn_objc_isa_use : Warning<
+ "direct access to Objective-C's isa is deprecated in favor of "
+ "object_getClass()">, InGroup<DeprecatedObjCIsaUsage>;
+def warn_objc_isa_assign : Warning<
+ "assignment to Objective-C's isa is deprecated in favor of "
+ "object_setClass()">, InGroup<DeprecatedObjCIsaUsage>;
+def warn_objc_pointer_masking : Warning<
+ "bitmasking for introspection of Objective-C object pointers is strongly "
+ "discouraged">,
+ InGroup<ObjCPointerIntrospect>;
+def warn_objc_pointer_masking_performSelector : Warning<warn_objc_pointer_masking.Text>,
+ InGroup<ObjCPointerIntrospectPerformSelector>;
+def warn_objc_property_default_assign_on_object : Warning<
+ "default property attribute 'assign' not appropriate for non-GC object">,
+ InGroup<ObjCPropertyNoAttribute>;
+def warn_property_attr_mismatch : Warning<
+ "property attribute in class extension does not match the primary class">,
+ InGroup<PropertyAttr>;
+def warn_property_implicitly_mismatched : Warning <
+ "primary property declaration is implicitly strong while redeclaration "
+ "in class extension is weak">,
+ InGroup<DiagGroup<"objc-property-implicit-mismatch">>;
+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_objc_property_retain_of_block : Warning<
+ "retain'ed block property does not copy the block "
+ "- use copy attribute instead">, InGroup<ObjCRetainBlockProperty>;
+def warn_objc_readonly_property_has_setter : Warning<
+ "setter cannot be specified for a readonly property">,
+ InGroup<ObjCReadonlyPropertyHasSetter>;
+def warn_atomic_property_rule : Warning<
+ "writable atomic property %0 cannot pair a synthesized %select{getter|setter}1 "
+ "with a user defined %select{getter|setter}2">,
+ InGroup<DiagGroup<"atomic-property-with-user-defined-accessor">>;
+def note_atomic_property_fixup_suggest : Note<"setter and getter must both be "
+ "synthesized, or both be user defined,or the property must be nonatomic">;
+def err_atomic_property_nontrivial_assign_op : Error<
+ "atomic property of reference type %0 cannot have non-trivial assignment"
+ " operator">;
+def warn_cocoa_naming_owned_rule : Warning<
+ "property follows Cocoa naming"
+ " convention for returning 'owned' objects">,
+ InGroup<DiagGroup<"objc-property-matches-cocoa-ownership-rule">>;
+def err_cocoa_naming_owned_rule : Error<
+ "property follows Cocoa naming"
+ " convention for returning 'owned' objects">;
+def note_cocoa_naming_declare_family : Note<
+ "explicitly declare getter %objcinstance0 with '%1' to return an 'unowned' "
+ "object">;
+def warn_auto_synthesizing_protocol_property :Warning<
+ "auto property synthesis will not synthesize property %0"
+ " declared in protocol %1">,
+ InGroup<DiagGroup<"objc-protocol-property-synthesis">>;
+def warn_no_autosynthesis_shared_ivar_property : Warning <
+ "auto property synthesis will not synthesize property "
+ "%0 because it cannot share an ivar with another synthesized property">,
+ InGroup<ObjCNoPropertyAutoSynthesis>;
+def warn_no_autosynthesis_property : Warning<
+ "auto property synthesis will not synthesize property "
+ "%0 because it is 'readwrite' but it will be synthesized 'readonly' "
+ "via another property">,
+ InGroup<ObjCNoPropertyAutoSynthesis>;
+def warn_autosynthesis_property_in_superclass : Warning<
+ "auto property synthesis will not synthesize property "
+ "%0; it will be implemented by its superclass, use @dynamic to "
+ "acknowledge intention">,
+ InGroup<ObjCNoPropertyAutoSynthesis>;
+def warn_autosynthesis_property_ivar_match :Warning<
+ "autosynthesized property %0 will use %select{|synthesized}1 instance variable "
+ "%2, not existing instance variable %3">,
+ InGroup<DiagGroup<"objc-autosynthesis-property-ivar-name-match">>;
+def warn_missing_explicit_synthesis : Warning <
+ "auto property synthesis is synthesizing property not explicitly synthesized">,
+ InGroup<DiagGroup<"objc-missing-property-synthesis">>, DefaultIgnore;
+def warn_property_getter_owning_mismatch : Warning<
+ "property declared as returning non-retained objects"
+ "; getter returning retained objects">;
+def warn_property_redecl_getter_mismatch : Warning<
+ "getter name mismatch between property redeclaration (%1) and its original "
+ "declaration (%0)">, InGroup<PropertyAttr>;
+def error_property_setter_ambiguous_use : Error<
+ "synthesized properties %0 and %1 both claim setter %2 -"
+ " use of this setter will cause unexpected behavior">;
+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 class extension %0"
+ " (attribute must be 'readwrite', while its primary must be 'readonly')">;
+def err_type_mismatch_continuation_class : Error<
+ "type of property %0 in class extension does not match "
+ "property type in primary class">;
+def err_use_continuation_class_redeclaration_readwrite : Error<
+ "illegal redeclaration of 'readwrite' property in class extension %0"
+ " (perhaps you intended this to be a 'readwrite' redeclaration of a "
+ "'readonly' public property?)">;
+def err_continuation_class : Error<"class extension 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 or one of "
+ "its extensions">;
+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 note_protocol_property_declare : Note<
+ "it could also be property of type %0 declared here">;
+def note_property_synthesize : Note<
+ "property synthesized 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"
+ " instance variable or must explicitly name an instance variable">;
+def err_arc_perform_selector_retains : Error<
+ "performSelector names a selector which retains the object">;
+def warn_arc_perform_selector_leaks : Warning<
+ "performSelector may cause a leak because its selector is unknown">,
+ InGroup<DiagGroup<"arc-performSelector-leaks">>;
+def warn_dealloc_in_category : Warning<
+"-dealloc is being overridden in a category">,
+InGroup<DeallocInCategory>;
+def err_gc_weak_property_strong_type : Error<
+ "weak attribute declared on a __strong type property in GC mode">;
+def warn_arc_repeated_use_of_weak : Warning <
+ "weak %select{variable|property|implicit property|instance variable}0 %1 is "
+ "accessed multiple times in this %select{function|method|block|lambda}2 "
+ "but may be unpredictably set to nil; assign to a strong variable to keep "
+ "the object alive">,
+ InGroup<ARCRepeatedUseOfWeak>, DefaultIgnore;
+def warn_implicitly_retains_self : Warning <
+ "block implicitly retains 'self'; explicitly mention 'self' to indicate "
+ "this is intended behavior">,
+ InGroup<DiagGroup<"implicit-retain-self">>, DefaultIgnore;
+def warn_arc_possible_repeated_use_of_weak : Warning <
+ "weak %select{variable|property|implicit property|instance variable}0 %1 may "
+ "be accessed multiple times in this %select{function|method|block|lambda}2 "
+ "and may be unpredictably set to nil; assign to a strong variable to keep "
+ "the object alive">,
+ InGroup<ARCRepeatedUseOfWeakMaybe>, DefaultIgnore;
+def note_arc_weak_also_accessed_here : Note<
+ "also accessed here">;
+def err_incomplete_synthesized_property : Error<
+ "cannot synthesize property %0 with incomplete type %1">;
+
+def error_property_ivar_type : Error<
+ "type of property %0 (%1) does not match type of instance variable %2 (%3)">;
+def error_property_accessor_type : Error<
+ "type of property %0 (%1) does not match type of accessor %2 (%3)">;
+def error_ivar_in_superclass_use : Error<
+ "property %0 attempting to use instance variable %1 declared in super class %2">;
+def error_weak_property : Error<
+ "existing instance variable %1 for __weak property %0 must be __weak">;
+def error_strong_property : Error<
+ "existing instance variable %1 for strong property %0 may not be __weak">;
+def error_dynamic_property_ivar_decl : Error<
+ "dynamic property cannot have instance variable specification">;
+def error_duplicate_ivar_use : Error<
+ "synthesized properties %0 and %1 both claim instance variable %2">;
+def error_property_implemented : Error<"property %0 is already implemented">;
+def warn_objc_missing_super_call : Warning<
+ "method possibly missing a [super %0] call">,
+ InGroup<ObjCMissingSuperCalls>;
+def error_dealloc_bad_result_type : Error<
+ "dealloc return type must be correctly specified as 'void' under ARC, "
+ "instead of %0">;
+def warn_undeclared_selector : Warning<
+ "undeclared selector %0">, InGroup<UndeclaredSelector>, DefaultIgnore;
+def warn_undeclared_selector_with_typo : Warning<
+ "undeclared selector %0; did you mean %1?">,
+ InGroup<UndeclaredSelector>, DefaultIgnore;
+def warn_implicit_atomic_property : Warning<
+ "property is assumed atomic by default">, InGroup<ImplicitAtomic>, DefaultIgnore;
+def note_auto_readonly_iboutlet_fixup_suggest : Note<
+ "property should be changed to be readwrite">;
+def warn_auto_readonly_iboutlet_property : Warning<
+ "readonly IBOutlet property %0 when auto-synthesized may "
+ "not work correctly with 'nib' loader">,
+ InGroup<DiagGroup<"readonly-iboutlet-property">>;
+def warn_auto_implicit_atomic_property : Warning<
+ "property is assumed atomic when auto-synthesizing the property">,
+ InGroup<ImplicitAtomic>, DefaultIgnore;
+def warn_unimplemented_selector: Warning<
+ "no method with selector %0 is implemented in this translation unit">,
+ InGroup<Selector>, DefaultIgnore;
+def warn_unimplemented_protocol_method : Warning<
+ "method %0 in protocol %1 not implemented">, InGroup<Protocol>;
+def warning_multiple_selectors: Warning<
+ "several methods with selector %0 of mismatched types are found "
+ "for the @selector expression">,
+ InGroup<SelectorTypeMismatch>, DefaultIgnore;
+
+def err_objc_kindof_nonobject : Error<
+ "'__kindof' specifier cannot be applied to non-object type %0">;
+def err_objc_kindof_wrong_position : Error<
+ "'__kindof' type specifier must precede the declarator">;
+
+// 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%select{ %1|}0">;
+def ext_static_assert_no_message : ExtWarn<
+ "static_assert with no message is a C++1z extension">, InGroup<CXX1z>;
+def warn_cxx14_compat_static_assert_no_message : Warning<
+ "static_assert with no message is incompatible with C++ standards before C++1z">,
+ DefaultIgnore, InGroup<CXXPre1zCompat>;
+
+def warn_inline_namespace_reopened_noninline : Warning<
+ "inline namespace cannot be reopened as a non-inline namespace">;
+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<
+ "befriending enumeration type %0 is a C++11 extension">, InGroup<CXX11>;
+def warn_cxx98_compat_enum_friend : Warning<
+ "befriending enumeration type %0 is incompatible with C++98">,
+ InGroup<CXX98Compat>, DefaultIgnore;
+def ext_nonclass_type_friend : ExtWarn<
+ "non-class friend type %0 is a C++11 extension">, InGroup<CXX11>;
+def warn_cxx98_compat_nonclass_type_friend : Warning<
+ "non-class friend type %0 is incompatible with C++98">,
+ InGroup<CXX98Compat>, DefaultIgnore;
+def err_friend_is_member : Error<
+ "friends cannot be members of the declaring class">;
+def warn_cxx98_compat_friend_is_member : Warning<
+ "friend declaration naming a member of the declaring class is incompatible "
+ "with C++98">, InGroup<CXX98Compat>, DefaultIgnore;
+def ext_unelaborated_friend_type : ExtWarn<
+ "unelaborated friend declaration is a C++11 extension; specify "
+ "'%select{struct|interface|union|class|enum}0' to befriend %1">,
+ InGroup<CXX11>;
+def warn_cxx98_compat_unelaborated_friend_type : Warning<
+ "befriending %1 without '%select{struct|interface|union|class|enum}0' "
+ "keyword is incompatible with C++98">, InGroup<CXX98Compat>, DefaultIgnore;
+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_no_matching_local_friend_suggest : Error<
+ "no matching function %0 found in local scope; did you mean %3?">;
+def err_partial_specialization_friend : Error<
+ "partial specialization cannot be declared as a friend">;
+def err_qualified_friend_def : Error<
+ "friend function definition cannot be qualified with '%0'">;
+def err_friend_def_in_local_class : Error<
+ "friend function cannot be defined in a local class">;
+def err_friend_not_first_in_declaration : Error<
+ "'friend' must appear first in a non-function declaration">;
+def err_using_decl_friend : Error<
+ "cannot befriend target of using declaration">;
+def warn_template_qualified_friend_unsupported : Warning<
+ "dependent nested name specifier '%0' for friend class declaration is "
+ "not supported; turning off access control for %1">,
+ InGroup<UnsupportedFriend>;
+def warn_template_qualified_friend_ignored : Warning<
+ "dependent nested name specifier '%0' for friend template declaration is "
+ "not supported; ignoring this friend declaration">,
+ InGroup<UnsupportedFriend>;
+def ext_friend_tag_redecl_outside_namespace : ExtWarn<
+ "unqualified friend declaration referring to type outside of the nearest "
+ "enclosing namespace is a Microsoft extension; add a nested name specifier">,
+ InGroup<MicrosoftUnqualifiedFriend>;
+def err_pure_friend : Error<"friend declaration cannot have a pure-specifier">;
+
+def err_invalid_member_in_interface : Error<
+ "%select{data member |non-public member function |static member function |"
+ "user-declared constructor|user-declared destructor|operator |"
+ "nested class }0%1 is not permitted within an interface type">;
+def err_invalid_base_in_interface : Error<
+ "interface type cannot inherit from "
+ "%select{'struct|non-public 'interface|'class}0 %1'">;
+
+def err_abstract_type_in_decl : Error<
+ "%select{return|parameter|variable|field|instance variable|"
+ "synthesized instance variable}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_capture_of_abstract_type : Error<
+ "by-copy capture of value of abstract type %0">;
+def err_capture_of_incomplete_type : Error<
+ "by-copy capture of variable %0 with incomplete type %1">;
+def err_capture_default_non_local : Error<
+ "non-local lambda expression cannot have a capture-default">;
+
+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 cannot be defined in a type specifier">;
+def err_type_defined_in_result_type : Error<
+ "%0 cannot be defined in the result type of a function">;
+def err_type_defined_in_param_type : Error<
+ "%0 cannot be defined in a parameter type">;
+def err_type_defined_in_alias_template : Error<
+ "%0 cannot be defined in a type alias template">;
+def err_type_defined_in_condition : Error<
+ "%0 cannot be defined in a condition">;
+
+def note_pure_virtual_function : Note<
+ "unimplemented pure virtual method %0 in %1">;
+
+def note_pure_qualified_call_kext : Note<
+ "qualified call to %0::%1 is treated as a virtual call to %1 due to -fapple-kext">;
+
+def err_deleted_decl_not_first : Error<
+ "deleted definition must be first declaration">;
+
+def err_deleted_override : Error<
+ "deleted function %0 cannot override a non-deleted function">;
+
+def err_non_deleted_override : Error<
+ "non-deleted function %0 cannot override a deleted function">;
+
+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 warn_weak_template_vtable : Warning<
+ "explicit template instantiation %0 will emit a vtable in every "
+ "translation unit">,
+ InGroup<DiagGroup<"weak-template-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 %select{typedefs|type aliases}0">;
+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_rref_in_exception_spec : Error<
+ "rvalue reference type %0 is not allowed in exception specification">;
+def err_mismatched_exception_spec : Error<
+ "exception specification in declaration does not match previous declaration">;
+def ext_mismatched_exception_spec : ExtWarn<err_mismatched_exception_spec.Text>,
+ InGroup<MicrosoftExceptionSpec>;
+def err_override_exception_spec : Error<
+ "exception specification of overriding function is more lax than "
+ "base version">;
+def ext_override_exception_spec : ExtWarn<err_override_exception_spec.Text>,
+ InGroup<MicrosoftExceptionSpec>;
+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 err_missing_exception_specification : Error<
+ "%0 is missing exception specification '%1'">;
+def ext_missing_exception_specification : ExtWarn<
+ err_missing_exception_specification.Text>,
+ InGroup<DiagGroup<"missing-exception-spec">>;
+def ext_ms_missing_exception_specification : ExtWarn<
+ err_missing_exception_specification.Text>,
+ InGroup<MicrosoftExceptionSpec>;
+def err_noexcept_needs_constant_expression : Error<
+ "argument to noexcept specifier must be a constant expression">;
+def err_exception_spec_not_parsed : Error<
+ "exception specification is not available until end of class definition">;
+
+// 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 ext_ms_using_declaration_inaccessible : ExtWarn<
+ "using declaration referring to inaccessible member '%0' (which refers "
+ "to accessible member '%1') is a Microsoft compatibility extension">,
+ AccessControl, InGroup<MicrosoftUsingDecl>;
+def err_access_ctor : Error<
+ "calling a %select{private|protected}0 constructor of class %2">,
+ AccessControl;
+def ext_rvalue_to_reference_access_ctor : Extension<
+ "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_ctor : Error<
+ // The ERRORs represent other special members that aren't constructors, in
+ // hopes that someone will bother noticing and reporting if they appear
+ "%select{base class|inherited virtual base class}0 %1 has %select{private|"
+ "protected}3 %select{default |copy |move |*ERROR* |*ERROR* "
+ "|*ERROR*|}2constructor">, AccessControl;
+def err_access_field_ctor : Error<
+ // The ERRORs represent other special members that aren't constructors, in
+ // hopes that someone will bother noticing and reporting if they appear
+ "field of type %0 has %select{private|protected}2 "
+ "%select{default |copy |move |*ERROR* |*ERROR* |*ERROR* |}1constructor">,
+ AccessControl;
+def err_access_friend_function : Error<
+ "friend function %1 is a %select{private|protected}0 member of %3">,
+ 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 %1 has "
+ "%select{private|protected}2 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_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 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_noobject : Note<
+ "must name member using the type of the current context %0">;
+def note_access_protected_restricted_ctordtor : Note<
+ "protected %select{constructor|destructor}0 can only be used to "
+ "%select{construct|destroy}0 a base class subobject">;
+def note_access_protected_restricted_object : Note<
+ "can only access this member on an object of type %0">;
+def warn_cxx98_compat_sfinae_access_control : Warning<
+ "substitution failure due to access control is incompatible with C++98">,
+ InGroup<CXX98Compat>, DefaultIgnore, NoSFINAE;
+
+// 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">;
+def warn_cxx98_compat_enum_nested_name_spec : Warning<
+ "enumeration type in nested name specifier is incompatible with C++98">,
+ InGroup<CXX98Compat>, DefaultIgnore;
+def err_nested_name_spec_is_not_class : Error<
+ "%0 cannot appear before '::' because it is not a class"
+ "%select{ or namespace|, namespace, or enumeration}1; did you mean ':'?">;
+def ext_nested_name_spec_is_enum : ExtWarn<
+ "use of enumeration in a nested name specifier is a C++11 extension">,
+ InGroup<CXX11>;
+
+// 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 ext_mutable_reference : ExtWarn<
+ "'mutable' on a reference type is a Microsoft extension">,
+ InGroup<MicrosoftMutableReference>;
+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_in_union : Error<
+ "unions cannot have virtual functions">;
+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' cannot 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_storage_class_for_static_member : Error<
+ "static data member definition cannot specify a storage class">;
+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_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 ext_pure_function_definition : ExtWarn<
+ "function definition with pure-specifier is a Microsoft extension">,
+ InGroup<MicrosoftPureDefinition>;
+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 warn_call_to_pure_virtual_member_function_from_ctor_dtor : Warning<
+ "call to pure virtual member function %0 has undefined behavior; "
+ "overrides of %0 in subclasses are not available in the "
+ "%select{constructor|destructor}1 of %2">;
+
+def note_member_declared_at : Note<"member is declared here">;
+def note_ivar_decl : Note<"instance variable is declared here">;
+def note_bitfield_decl : Note<"bit-field is declared here">;
+def note_implicit_param_decl : Note<"%0 is an implicit parameter">;
+def note_member_synthesized_at : Note<
+ "implicit %select{default constructor|copy constructor|move constructor|copy "
+ "assignment operator|move assignment operator|destructor}0 for %1 first "
+ "required here">;
+def note_inhctor_synthesized_at : Note<
+ "inheriting constructor for %0 first required here">;
+def err_missing_default_ctor : Error<
+ "%select{|implicit default |inheriting }0constructor for %1 must explicitly "
+ "initialize the %select{base class|member}2 %3 which does not have a default "
+ "constructor">;
+def note_due_to_dllexported_class : Note<
+ "due to '%0' being dllexported%select{|; try compiling in C++11 mode}1">;
+
+def err_illegal_union_or_anon_struct_member : Error<
+ "%select{anonymous struct|union}0 member %1 has a non-trivial "
+ "%select{constructor|copy constructor|move constructor|copy assignment "
+ "operator|move assignment operator|destructor}2">;
+def warn_cxx98_compat_nontrivial_union_or_anon_struct_member : Warning<
+ "%select{anonymous struct|union}0 member %1 with a non-trivial "
+ "%select{constructor|copy constructor|move constructor|copy assignment "
+ "operator|move assignment operator|destructor}2 is incompatible with C++98">,
+ InGroup<CXX98Compat>, DefaultIgnore;
+
+def note_nontrivial_virtual_dtor : Note<
+ "destructor for %0 is not trivial because it is virtual">;
+def note_nontrivial_has_virtual : Note<
+ "because type %0 has a virtual %select{member function|base class}1">;
+def note_nontrivial_no_def_ctor : Note<
+ "because %select{base class of |field of |}0type %1 has no "
+ "default constructor">;
+def note_user_declared_ctor : Note<
+ "implicit default constructor suppressed by user-declared constructor">;
+def note_nontrivial_no_copy : Note<
+ "because no %select{<<ERROR>>|constructor|constructor|assignment operator|"
+ "assignment operator|<<ERROR>>}2 can be used to "
+ "%select{<<ERROR>>|copy|move|copy|move|<<ERROR>>}2 "
+ "%select{base class|field|an object}0 of type %3">;
+def note_nontrivial_user_provided : Note<
+ "because %select{base class of |field of |}0type %1 has a user-provided "
+ "%select{default constructor|copy constructor|move constructor|"
+ "copy assignment operator|move assignment operator|destructor}2">;
+def note_nontrivial_in_class_init : Note<
+ "because field %0 has an initializer">;
+def note_nontrivial_param_type : Note<
+ "because its parameter is %diff{of type $, not $|of the wrong type}2,3">;
+def note_nontrivial_default_arg : Note<"because it has a default argument">;
+def note_nontrivial_variadic : Note<"because it is a variadic function">;
+def note_nontrivial_subobject : Note<
+ "because the function selected to %select{construct|copy|move|copy|move|"
+ "destroy}2 %select{base class|field}0 of type %1 is not trivial">;
+def note_nontrivial_objc_ownership : Note<
+ "because type %0 has a member with %select{no|no|__strong|__weak|"
+ "__autoreleasing}1 ownership">;
+
+def err_static_data_member_not_allowed_in_anon_struct : Error<
+ "static data member %0 not allowed in anonymous struct">;
+def ext_static_data_member_in_union : ExtWarn<
+ "static data member %0 in union is a C++11 extension">, InGroup<CXX11>;
+def warn_cxx98_compat_static_data_member_in_union : Warning<
+ "static data member %0 in union is incompatible with C++98">,
+ InGroup<CXX98Compat>, DefaultIgnore;
+def ext_union_member_of_reference_type : ExtWarn<
+ "union member %0 has reference type %1, which is a Microsoft extension">,
+ InGroup<MicrosoftUnionMemberReference>;
+def err_union_member_of_reference_type : Error<
+ "union member %0 has reference type %1">;
+def ext_anonymous_struct_union_qualified : Extension<
+ "anonymous %select{struct|union}0 cannot be '%1'">;
+def err_different_return_type_for_overriding_virtual_function : Error<
+ "virtual function %0 has a different return type "
+ "%diff{($) than the function it overrides (which has return type $)|"
+ "than the function it overrides}1,2">;
+def note_overridden_virtual_function : Note<
+ "overridden virtual function is here">;
+def err_conflicting_overriding_cc_attributes : Error<
+ "virtual function %0 has different calling convention attributes "
+ "%diff{($) than the function it overrides (which has calling convention $)|"
+ "than the function it overrides}1,2">;
+
+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|interface|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<MicrosoftExplicitConstructorCall>;
+
+// 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 %select{typedef|type alias}1 %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_dtor_not_a_type : Error<
+ "identifier %0 in object destruction expression does not name a type">;
+def err_destructor_expr_type_mismatch : Error<
+ "destructor type %0 in object destruction expression does not match the "
+ "type %1 of the object being destroyed">;
+def note_destructor_type_here : Note<
+ "type %0 is declared here">;
+
+def err_destructor_template : Error<
+ "destructor cannot be declared as a template">;
+
+// 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 constructor delegation|a vector element|a block element|a "
+ "complex element|a lambda capture|a compound literal initializer|a "
+ "related result|a parameter of CF audited function}0 "
+ "%diff{of type $ with an %select{rvalue|lvalue}2 of type $|"
+ "with an %select{rvalue|lvalue}2 of incompatible type}1,3"
+ "%select{|: different classes%diff{ ($ vs $)|}5,6"
+ "|: different number of parameters (%5 vs %6)"
+ "|: type mismatch at %ordinal5 parameter%diff{ ($ vs $)|}6,7"
+ "|: different return type%diff{ ($ vs $)|}5,6"
+ "|: different qualifiers ("
+ "%select{none|const|restrict|const and restrict|volatile|const and volatile|"
+ "volatile and restrict|const, volatile, and restrict}5 vs "
+ "%select{none|const|restrict|const and restrict|volatile|const and volatile|"
+ "volatile and restrict|const, volatile, and restrict}6)}4">;
+
+def err_lvalue_to_rvalue_ref : Error<"rvalue reference %diff{to type $ cannot "
+ "bind to lvalue of type $|cannot bind to incompatible lvalue}0,1">;
+def err_lvalue_reference_bind_to_initlist : Error<
+ "%select{non-const|volatile}0 lvalue reference to type %1 cannot bind to an "
+ "initializer list temporary">;
+def err_lvalue_reference_bind_to_temporary : Error<
+ "%select{non-const|volatile}0 lvalue reference %diff{to type $ cannot bind "
+ "to a temporary of type $|cannot bind to incompatible temporary}1,2">;
+def err_lvalue_reference_bind_to_unrelated : Error<
+ "%select{non-const|volatile}0 lvalue reference "
+ "%diff{to type $ cannot bind to a value of unrelated type $|"
+ "cannot bind to a value of unrelated type}1,2">;
+def err_reference_bind_drops_quals : Error<
+ "binding value %diff{of type $ to reference to type $|to reference}0,1 "
+ "drops %select{<<ERROR>>|'const'|'restrict'|'const' and 'restrict'|"
+ "'volatile'|'const' and 'volatile'|'restrict' and 'volatile'|"
+ "'const', 'restrict', and 'volatile'}2 qualifier%plural{1:|2:|4:|:s}2">;
+def err_reference_bind_failed : Error<
+ "reference %diff{to type $ could not bind to an %select{rvalue|lvalue}1 of "
+ "type $|could not bind to %select{rvalue|lvalue}1 of incompatible type}0,2">;
+def err_reference_bind_init_list : Error<
+ "reference to type %0 cannot bind to an initializer list">;
+def warn_temporary_array_to_pointer_decay : Warning<
+ "pointer is initialized by a temporary array, which will be destroyed at the "
+ "end of the full-expression">,
+ InGroup<DiagGroup<"address-of-array-temporary">>;
+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_bind_to_bitfield : Error<
+ "%select{non-const|volatile}0 reference cannot bind to "
+ "bit-field%select{| %1}2">;
+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_reference_without_init : Error<
+ "reference to type %0 requires an initializer">;
+def note_value_initialization_here : Note<
+ "in value-initialization of type %0 here">;
+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 %0 is uninitialized when used here">,
+ InGroup<Uninitialized>;
+def warn_base_class_is_uninit : Warning<
+ "base class %0 is uninitialized when used here to access %q1">,
+ InGroup<Uninitialized>;
+def warn_reference_field_is_uninit : Warning<
+ "reference %0 is not yet bound to a value when used here">,
+ InGroup<Uninitialized>;
+def note_uninit_in_this_constructor : Note<
+ "during field initialization in %select{this|the implicit default}0 "
+ "constructor">;
+def warn_static_self_reference_in_init : Warning<
+ "static variable %0 is suspiciously used within its own initialization">,
+ InGroup<UninitializedStaticSelfInit>;
+def warn_uninit_self_reference_in_init : Warning<
+ "variable %0 is uninitialized when used within its own initialization">,
+ InGroup<Uninitialized>;
+def warn_uninit_self_reference_in_reference_init : Warning<
+ "reference %0 is not yet bound to a value when used within its own"
+ " initialization">,
+ InGroup<Uninitialized>;
+def warn_uninit_var : Warning<
+ "variable %0 is uninitialized when %select{used here|captured by block}1">,
+ InGroup<Uninitialized>, DefaultIgnore;
+def warn_sometimes_uninit_var : Warning<
+ "variable %0 is %select{used|captured}1 uninitialized whenever "
+ "%select{'%3' condition is %select{true|false}4|"
+ "'%3' loop %select{is entered|exits because its condition is false}4|"
+ "'%3' loop %select{condition is true|exits because its condition is false}4|"
+ "switch %3 is taken|"
+ "its declaration is reached|"
+ "%3 is called}2">,
+ InGroup<UninitializedSometimes>, DefaultIgnore;
+def warn_maybe_uninit_var : Warning<
+ "variable %0 may be uninitialized when "
+ "%select{used here|captured by block}1">,
+ InGroup<UninitializedMaybe>, DefaultIgnore;
+def note_uninit_var_def : Note<"variable %0 is declared here">;
+def note_uninit_var_use : Note<
+ "%select{uninitialized use occurs|variable is captured by block}0 here">;
+def warn_uninit_byref_blockvar_captured_by_block : Warning<
+ "block pointer variable %0 is uninitialized when captured by block">,
+ InGroup<Uninitialized>, DefaultIgnore;
+def note_block_var_fixit_add_initialization : Note<
+ "did you mean to use __block %0?">;
+def note_in_omitted_aggregate_initializer : Note<
+ "in implicit initialization of %select{array element %1|field %1}0 "
+ "with omitted initializer">;
+def note_in_reference_temporary_list_initializer : Note<
+ "in initialization of temporary of type %0 created to "
+ "list-initialize this reference">;
+def note_var_fixit_add_initialization : Note<
+ "initialize the variable %0 to silence this warning">;
+def note_uninit_fixit_remove_cond : Note<
+ "remove the %select{'%1' if its condition|condition if it}0 "
+ "is always %select{false|true}2">;
+def err_init_incomplete_type : Error<"initialization of incomplete type %0">;
+
+def warn_unsequenced_mod_mod : Warning<
+ "multiple unsequenced modifications to %0">, InGroup<Unsequenced>;
+def warn_unsequenced_mod_use : Warning<
+ "unsequenced modification and access to %0">, InGroup<Unsequenced>;
+
+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|capturing value}0 of type %1">;
+def ext_rvalue_to_reference_temp_copy_no_viable : Extension<
+ "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|capturing value}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|capturing value}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|"
+ "capturing value}0 of type %1 invokes deleted constructor">;
+def err_temp_copy_incomplete : Error<
+ "copying a temporary object of incomplete type %0">;
+def warn_cxx98_compat_temp_copy : Warning<
+ "%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}1 "
+ "of type %2 when binding a reference to a temporary would %select{invoke "
+ "an inaccessible constructor|find no viable constructor|find ambiguous "
+ "constructors|invoke a deleted constructor}0 in C++98">,
+ InGroup<CXX98CompatBindToTemporaryCopy>, DefaultIgnore;
+def err_selected_explicit_constructor : Error<
+ "chosen constructor is explicit in copy-initialization">;
+def note_constructor_declared_here : Note<
+ "constructor declared here">;
+
+// C++11 decltype
+def err_decltype_in_declarator : Error<
+ "'decltype' cannot be used to name a declaration">;
+
+// C++11 auto
+def warn_cxx98_compat_auto_type_specifier : Warning<
+ "'auto' type specifier is incompatible with C++98">,
+ InGroup<CXX98Compat>, DefaultIgnore;
+def err_auto_variable_cannot_appear_in_own_initializer : Error<
+ "variable %0 declared with %select{'auto'|'decltype(auto)'|'__auto_type'}1 "
+ "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<
+ "%select{'auto'|'decltype(auto)'|'__auto_type'}0 not allowed "
+ "%select{in function prototype"
+ "|in non-static struct member|in struct member"
+ "|in non-static union member|in union member"
+ "|in non-static class member|in interface member"
+ "|in exception declaration|in template parameter|in block literal"
+ "|in template argument|in typedef|in type alias|in function return type"
+ "|in conversion function type|here|in lambda parameter"
+ "|in type allocated by 'new'|in K&R-style function parameter}1">;
+def err_auto_not_allowed_var_inst : Error<
+ "'auto' variable template instantiation is not allowed">;
+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_new_list_init : Error<
+ "new expression for type %0 cannot use list-initialization">;
+def err_auto_var_init_no_expression : Error<
+ "initializer for variable %0 with type %1 is empty">;
+def err_auto_var_init_multiple_expressions : Error<
+ "initializer for variable %0 with type %1 contains multiple expressions">;
+def err_auto_var_init_paren_braces : Error<
+ "cannot deduce type for variable %1 with type %2 from "
+ "%select{parenthesized|nested}0 initializer list">;
+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; deduced return types are a "
+ "C++14 extension">;
+def err_deduced_return_type : Error<
+ "deduced return types are a C++14 extension">;
+def err_trailing_return_without_auto : Error<
+ "function with trailing return type must specify return type 'auto', not %0">;
+def err_trailing_return_in_parens : Error<
+ "trailing return type may not be nested within parentheses">;
+def err_auto_var_deduction_failure : Error<
+ "variable %0 with type %1 has incompatible initializer of type %2">;
+def err_auto_var_deduction_failure_from_init_list : Error<
+ "cannot deduce actual type for variable %0 with type %1 from initializer list">;
+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<
+ "'%select{auto|decltype(auto)|__auto_type}0' deduced as %1 in declaration "
+ "of %2 and deduced as %3 in declaration of %4">;
+def err_implied_std_initializer_list_not_found : Error<
+ "cannot deduce type of initializer list because std::initializer_list was "
+ "not found; include <initializer_list>">;
+def err_malformed_std_initializer_list : Error<
+ "std::initializer_list must be a class template with a single type parameter">;
+def warn_dangling_std_initializer_list : Warning<
+ "array backing the initializer list will be destroyed at the end of "
+ "%select{the full-expression|the constructor}0">,
+ InGroup<DiagGroup<"dangling-initializer-list">>;
+def err_auto_init_list_from_c : Error<
+ "cannot use __auto_type with initializer list in C">;
+def err_auto_bitfield : Error<
+ "cannot pass bit-field as __auto_type initializer in C">;
+
+// C++1y decltype(auto) type
+def err_decltype_auto_cannot_be_combined : Error<
+ "'decltype(auto)' cannot be combined with other type specifiers">;
+def err_decltype_auto_function_declarator_not_declaration : Error<
+ "'decltype(auto)' can only be used as a return type "
+ "in a function declaration">;
+def err_decltype_auto_compound_type : Error<
+ "cannot form %select{pointer to|reference to|array of}0 'decltype(auto)'">;
+def err_decltype_auto_initializer_list : Error<
+ "cannot deduce 'decltype(auto)' from initializer list">;
+
+// C++1y deduced return types
+def err_auto_fn_deduction_failure : Error<
+ "cannot deduce return type %0 from returned value of type %1">;
+def err_auto_fn_different_deductions : Error<
+ "'%select{auto|decltype(auto)}0' in return type deduced as %1 here but "
+ "deduced as %2 in earlier return statement">;
+def err_auto_fn_used_before_defined : Error<
+ "function %0 with deduced return type cannot be used before it is defined">;
+def err_auto_fn_no_return_but_not_auto : Error<
+ "cannot deduce return type %0 for function with no return statements">;
+def err_auto_fn_return_void_but_not_auto : Error<
+ "cannot deduce return type %0 from omitted return expression">;
+def err_auto_fn_return_init_list : Error<
+ "cannot deduce return type from initializer list">;
+def err_auto_fn_virtual : Error<
+ "function with deduced return type cannot be virtual">;
+
+// C++11 override control
+def override_keyword_only_allowed_on_virtual_member_functions : Error<
+ "only virtual member functions can be marked '%0'">;
+def override_keyword_hides_virtual_member_function : Error<
+ "non-virtual member function marked '%0' hides virtual member "
+ "%select{function|functions}1">;
+def err_function_marked_override_not_overriding : Error<
+ "%0 marked 'override' but does not override any member functions">;
+def warn_function_marked_not_override_overriding : Warning <
+ "%0 overrides a member function but is not marked 'override'">,
+ InGroup<CXX11WarnOverrideMethod>;
+def err_class_marked_final_used_as_base : Error<
+ "base %0 is marked '%select{final|sealed}1'">;
+def warn_abstract_final_class : Warning<
+ "abstract class is marked '%select{final|sealed}0'">, InGroup<AbstractFinalClass>;
+
+// C++11 attributes
+def err_repeat_attribute : Error<"%0 attribute cannot be repeated">;
+
+// C++11 final
+def err_final_function_overridden : Error<
+ "declaration of %0 overrides a '%select{final|sealed}1' function">;
+
+// C++11 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<MicrosoftEnumValue>;
+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">;
+def err_enum_class_reference : Error<
+ "reference to %select{|scoped }0enumeration must use 'enum' "
+ "not 'enum class'">;
+def err_only_enums_have_underlying_types : Error<
+ "only enumeration types have underlying types">;
+def err_underlying_type_of_incomplete_enum : Error<
+ "cannot determine underlying type of incomplete enumeration type %0">;
+
+// C++11 delegating constructors
+def err_delegating_ctor : Error<
+ "delegating constructors are permitted only in C++11">;
+def warn_cxx98_compat_delegating_ctor : Warning<
+ "delegating constructors are incompatible with C++98">,
+ InGroup<CXX98Compat>, DefaultIgnore;
+def err_delegating_initializer_alone : Error<
+ "an initializer for a delegating constructor must appear alone">;
+def warn_delegating_ctor_cycle : Warning<
+ "constructor for %0 creates a delegation cycle">, DefaultError,
+ InGroup<DelegatingCtorCycles>;
+def note_it_delegates_to : Note<"it delegates to">;
+def note_which_delegates_to : Note<"which delegates to">;
+
+// C++11 range-based for loop
+def err_for_range_decl_must_be_var : Error<
+ "for range declaration must declare a variable">;
+def err_for_range_storage_class : Error<
+ "loop variable %0 may not be declared %select{'extern'|'static'|"
+ "'__private_extern__'|'auto'|'register'|'constexpr'}1">;
+def err_type_defined_in_for_range : Error<
+ "types may not be defined in a for range declaration">;
+def err_for_range_deduction_failure : Error<
+ "cannot use type %0 as a range">;
+def err_for_range_incomplete_type : Error<
+ "cannot use incomplete type %0 as a range">;
+def err_for_range_iter_deduction_failure : Error<
+ "cannot use type %0 as an iterator">;
+def err_for_range_member_begin_end_mismatch : Error<
+ "range type %0 has '%select{begin|end}1' member but no '%select{end|begin}1' member">;
+def err_for_range_begin_end_types_differ : Error<
+ "'begin' and 'end' must return the same type (got %0 and %1)">;
+def note_in_for_range: Note<
+ "when looking up '%select{begin|end}0' function for range expression "
+ "of type %1">;
+def err_for_range_invalid: Error<
+ "invalid range expression of type %0; no viable '%select{begin|end}1' "
+ "function available">;
+def err_range_on_array_parameter : Error<
+ "cannot build range expression with array function parameter %0 since "
+ "parameter with array type %1 is treated as pointer type %2">;
+def err_for_range_dereference : Error<
+ "invalid range expression of type %0; did you mean to dereference it "
+ "with '*'?">;
+def note_for_range_invalid_iterator : Note <
+ "in implicit call to 'operator%select{!=|*|++}0' for iterator of type %1">;
+def note_for_range_begin_end : Note<
+ "selected '%select{begin|end}0' %select{function|template }1%2 with iterator type %3">;
+
+// C++11 constexpr
+def warn_cxx98_compat_constexpr : Warning<
+ "'constexpr' specifier is incompatible with C++98">,
+ InGroup<CXX98Compat>, DefaultIgnore;
+// FIXME: Maybe this should also go in -Wc++14-compat?
+def warn_cxx14_compat_constexpr_not_const : Warning<
+ "'constexpr' non-static member function will not be implicitly 'const' "
+ "in C++14; add 'const' to avoid a change in behavior">,
+ InGroup<DiagGroup<"constexpr-not-const">>;
+def err_invalid_constexpr : Error<
+ "%select{function parameter|typedef|non-static data member}0 "
+ "cannot be constexpr">;
+def err_invalid_constexpr_member : Error<"non-static data member cannot be "
+ "constexpr%select{; did you intend to make it %select{const|static}0?|}1">;
+def err_constexpr_tag : Error<
+ "%select{class|struct|interface|union|enum}0 cannot be marked constexpr">;
+def err_constexpr_dtor : Error<"destructor cannot be marked constexpr">;
+def err_constexpr_no_declarators : Error<
+ "constexpr can only be used in variable and function declarations">;
+def err_invalid_constexpr_var_decl : Error<
+ "constexpr variable declaration must be a definition">;
+def err_constexpr_static_mem_var_requires_init : Error<
+ "declaration of constexpr static data member %0 requires an initializer">;
+def err_constexpr_var_non_literal : Error<
+ "constexpr variable cannot have non-literal type %0">;
+def err_constexpr_var_requires_const_init : Error<
+ "constexpr variable %0 must be initialized by a constant expression">;
+def err_constexpr_redecl_mismatch : Error<
+ "%select{non-constexpr declaration of %0 follows constexpr declaration"
+ "|constexpr declaration of %0 follows non-constexpr declaration}1">;
+def err_constexpr_virtual : Error<"virtual function cannot be constexpr">;
+def err_constexpr_virtual_base : Error<
+ "constexpr %select{member function|constructor}0 not allowed in "
+ "%select{struct|interface|class}1 with virtual base "
+ "%plural{1:class|:classes}2">;
+def note_non_literal_incomplete : Note<
+ "incomplete type %0 is not a literal type">;
+def note_non_literal_virtual_base : Note<"%select{struct|interface|class}0 "
+ "with virtual base %plural{1:class|:classes}1 is not a literal type">;
+def note_constexpr_virtual_base_here : Note<"virtual base class declared here">;
+def err_constexpr_non_literal_return : Error<
+ "constexpr function's return type %0 is not a literal type">;
+def err_constexpr_non_literal_param : Error<
+ "constexpr %select{function|constructor}1's %ordinal0 parameter type %2 is "
+ "not a literal type">;
+def err_constexpr_body_invalid_stmt : Error<
+ "statement not allowed in constexpr %select{function|constructor}0">;
+def ext_constexpr_body_invalid_stmt : ExtWarn<
+ "use of this statement in a constexpr %select{function|constructor}0 "
+ "is a C++14 extension">, InGroup<CXX14>;
+def warn_cxx11_compat_constexpr_body_invalid_stmt : Warning<
+ "use of this statement in a constexpr %select{function|constructor}0 "
+ "is incompatible with C++ standards before C++14">,
+ InGroup<CXXPre14Compat>, DefaultIgnore;
+def ext_constexpr_type_definition : ExtWarn<
+ "type definition in a constexpr %select{function|constructor}0 "
+ "is a C++14 extension">, InGroup<CXX14>;
+def warn_cxx11_compat_constexpr_type_definition : Warning<
+ "type definition in a constexpr %select{function|constructor}0 "
+ "is incompatible with C++ standards before C++14">,
+ InGroup<CXXPre14Compat>, DefaultIgnore;
+def err_constexpr_vla : Error<
+ "variably-modified type %0 cannot be used in a constexpr "
+ "%select{function|constructor}1">;
+def ext_constexpr_local_var : ExtWarn<
+ "variable declaration in a constexpr %select{function|constructor}0 "
+ "is a C++14 extension">, InGroup<CXX14>;
+def warn_cxx11_compat_constexpr_local_var : Warning<
+ "variable declaration in a constexpr %select{function|constructor}0 "
+ "is incompatible with C++ standards before C++14">,
+ InGroup<CXXPre14Compat>, DefaultIgnore;
+def err_constexpr_local_var_static : Error<
+ "%select{static|thread_local}1 variable not permitted in a constexpr "
+ "%select{function|constructor}0">;
+def err_constexpr_local_var_non_literal_type : Error<
+ "variable of non-literal type %1 cannot be defined in a constexpr "
+ "%select{function|constructor}0">;
+def err_constexpr_local_var_no_init : Error<
+ "variables defined in a constexpr %select{function|constructor}0 must be "
+ "initialized">;
+def ext_constexpr_function_never_constant_expr : ExtWarn<
+ "constexpr %select{function|constructor}0 never produces a "
+ "constant expression">, InGroup<DiagGroup<"invalid-constexpr">>, DefaultError;
+def err_enable_if_never_constant_expr : Error<
+ "'enable_if' attribute expression never produces a constant expression">;
+def err_constexpr_body_no_return : Error<
+ "no return statement in constexpr function">;
+def err_constexpr_return_missing_expr : Error<
+ "non-void constexpr function %0 should return a value">;
+def warn_cxx11_compat_constexpr_body_no_return : Warning<
+ "constexpr function with no return statements is incompatible with C++ "
+ "standards before C++14">, InGroup<CXXPre14Compat>, DefaultIgnore;
+def ext_constexpr_body_multiple_return : ExtWarn<
+ "multiple return statements in constexpr function is a C++14 extension">,
+ InGroup<CXX14>;
+def warn_cxx11_compat_constexpr_body_multiple_return : Warning<
+ "multiple return statements in constexpr function "
+ "is incompatible with C++ standards before C++14">,
+ InGroup<CXXPre14Compat>, DefaultIgnore;
+def note_constexpr_body_previous_return : Note<
+ "previous return statement is here">;
+def err_constexpr_function_try_block : Error<
+ "function try block not allowed in constexpr %select{function|constructor}0">;
+def err_constexpr_union_ctor_no_init : Error<
+ "constexpr union constructor does not initialize any member">;
+def err_constexpr_ctor_missing_init : Error<
+ "constexpr constructor must initialize all members">;
+def note_constexpr_ctor_missing_init : Note<
+ "member not initialized by constructor">;
+def note_non_literal_no_constexpr_ctors : Note<
+ "%0 is not literal because it is not an aggregate and has no constexpr "
+ "constructors other than copy or move constructors">;
+def note_non_literal_base_class : Note<
+ "%0 is not literal because it has base class %1 of non-literal type">;
+def note_non_literal_field : Note<
+ "%0 is not literal because it has data member %1 of "
+ "%select{non-literal|volatile}3 type %2">;
+def note_non_literal_user_provided_dtor : Note<
+ "%0 is not literal because it has a user-provided destructor">;
+def note_non_literal_nontrivial_dtor : Note<
+ "%0 is not literal because it has a non-trivial destructor">;
+def warn_private_extern : Warning<
+ "use of __private_extern__ on a declaration may not produce external symbol "
+ "private to the linkage unit and is deprecated">, InGroup<PrivateExtern>;
+def note_private_extern : Note<
+ "use __attribute__((visibility(\"hidden\"))) attribute instead">;
+
+// C++ Concepts TS
+def err_concept_wrong_decl_kind : Error<
+ "'concept' can only appear on the definition of a function template or variable template">;
+def err_concept_decls_may_only_appear_in_namespace_scope : Error<
+ "concept declarations may only appear in namespace scope">;
+def err_function_concept_not_defined : Error<
+ "function concept declaration must be a definition">;
+def err_var_concept_not_initialized : Error<
+ "variable concept declaration must be initialized">;
+def err_function_concept_exception_spec : Error<
+ "function concept cannot have exception specification">;
+def err_concept_decl_invalid_specifiers : Error<
+ "%select{variable|function}0 concept cannot be declared "
+ "'%select{thread_local|inline|friend|constexpr}1'">;
+def err_function_concept_with_params : Error<
+ "function concept cannot have any parameters">;
+
+// C++11 char16_t/char32_t
+def warn_cxx98_compat_unicode_type : Warning<
+ "'%0' type specifier is incompatible with C++98">,
+ InGroup<CXX98Compat>, DefaultIgnore;
+
+// __make_integer_seq
+def err_integer_sequence_negative_length : Error<
+ "integer sequences must have non-negative sequence length">;
+def err_integer_sequence_integral_element_type : Error<
+ "integer sequences must have integral element type">;
+
+// Objective-C++
+def err_objc_decls_may_only_appear_in_global_scope : Error<
+ "Objective-C declarations may only appear in global scope">;
+def warn_auto_var_is_id : Warning<
+ "'auto' deduced as 'id' in declaration of %0">,
+ InGroup<DiagGroup<"auto-var-id">>;
+
+// Attributes
+def err_nsobject_attribute : Error<
+ "'NSObject' attribute is for pointer types only">;
+def err_attributes_are_not_compatible : Error<
+ "%0 and %1 attributes are not compatible">;
+def err_attribute_wrong_number_arguments : Error<
+ "%0 attribute %plural{0:takes no arguments|1:takes one argument|"
+ ":requires exactly %1 arguments}1">;
+def err_attribute_too_many_arguments : Error<
+ "%0 attribute takes no more than %1 argument%s1">;
+def err_attribute_too_few_arguments : Error<
+ "%0 attribute takes at least %1 argument%s1">;
+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 warn_unsupported_target_attribute
+ : Warning<"Ignoring unsupported '%0' in the target attribute string">,
+ InGroup<IgnoredAttributes>;
+def err_attribute_unsupported
+ : Error<"%0 attribute is not supported for this target">;
+// The err_*_attribute_argument_not_int are seperate because they're used by
+// VerifyIntegerConstantExpression.
+def err_aligned_attribute_argument_not_int : Error<
+ "'aligned' attribute requires integer constant">;
+def err_align_value_attribute_argument_not_int : Error<
+ "'align_value' attribute requires integer constant">;
+def err_alignas_attribute_wrong_decl_type : Error<
+ "%0 attribute cannot be applied to a %select{function parameter|"
+ "variable with 'register' storage class|'catch' variable|bit-field}1">;
+def err_alignas_missing_on_definition : Error<
+ "%0 must be specified on definition if it is specified on any declaration">;
+def note_alignas_on_declaration : Note<"declared with %0 attribute here">;
+def err_alignas_mismatch : Error<
+ "redeclaration has different alignment requirement (%1 vs %0)">;
+def err_alignas_underaligned : Error<
+ "requested alignment is less than minimum alignment of %1 for type %0">;
+def err_attribute_argument_n_type : Error<
+ "%0 attribute requires parameter %1 to be %select{int or bool|an integer "
+ "constant|a string|an identifier}2">;
+def err_attribute_argument_type : Error<
+ "%0 attribute requires %select{int or bool|an integer "
+ "constant|a string|an identifier}1">;
+def err_attribute_argument_outof_range : Error<
+ "%0 attribute requires integer constant between %1 and %2 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_vec_type_hint : Error<
+ "invalid attribute argument %0 - expecting a vector or vectorizable scalar type">;
+def err_attribute_argument_out_of_bounds : Error<
+ "%0 attribute parameter %1 is out of bounds">;
+def err_attribute_only_once_per_parameter : Error<
+ "%0 attribute can only be applied once per parameter">;
+def err_attribute_uuid_malformed_guid : Error<
+ "uuid attribute contains a malformed GUID">;
+def warn_attribute_pointers_only : Warning<
+ "%0 attribute only applies to%select{| constant}1 pointer arguments">,
+ InGroup<IgnoredAttributes>;
+def err_attribute_pointers_only : Error<warn_attribute_pointers_only.Text>;
+def warn_attribute_return_pointers_only : Warning<
+ "%0 attribute only applies to return values that are pointers">,
+ InGroup<IgnoredAttributes>;
+def warn_attribute_return_pointers_refs_only : Warning<
+ "%0 attribute only applies to return values that are pointers or references">,
+ InGroup<IgnoredAttributes>;
+def warn_attribute_pointer_or_reference_only : Warning<
+ "%0 attribute only applies to a pointer or reference (%1 is invalid)">,
+ InGroup<IgnoredAttributes>;
+def err_attribute_no_member_pointers : Error<
+ "%0 attribute cannot be used with pointers to members">;
+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 %select{pointer|integer}1 arguments">;
+def err_ownership_returns_index_mismatch : Error<
+ "'ownership_returns' attribute index does not match; here it is %0">;
+def note_ownership_returns_index_mismatch : Note<
+ "declared with index %0 here">;
+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_init_method_bad_return_type : Error<
+ "init methods must return an object pointer type, not %0">;
+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_attribute_size_too_large : Error<"vector size too large">;
+def err_typecheck_vector_not_convertable : Error<
+ "cannot convert between vector values of different size (%0 and %1)">;
+def err_typecheck_vector_not_convertable_non_scalar : Error<
+ "cannot convert between vector and non-scalar values (%0 and %1)">;
+def err_typecheck_vector_lengths_not_equal : Error<
+ "vector operands do not have the same number of elements (%0 and %1)">;
+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_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_attribute_address_function_type : Error<
+ "function type may not be qualified with an address space">;
+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_field_with_address_space : Error<
+ "field may not be qualified with an address space">;
+def err_attr_objc_ownership_redundant : Error<
+ "the type %0 is already explicitly ownership-qualified">;
+def err_invalid_nsnumber_type : Error<
+ "%0 is not a valid literal type for NSNumber">;
+def err_objc_illegal_boxed_expression_type : Error<
+ "illegal type %0 used in a boxed expression">;
+def err_objc_non_trivially_copyable_boxed_expression_type : Error<
+ "non-trivially copyable type %0 cannot be used in a boxed expression">;
+def err_objc_incomplete_boxed_expression_type : Error<
+ "incomplete type %0 used in a boxed expression">;
+def err_undeclared_objc_literal_class : Error<
+ "definition of class %0 must be available to use Objective-C "
+ "%select{array literals|dictionary literals|numeric literals|boxed expressions|"
+ "string literals}1">;
+def err_undeclared_boxing_method : Error<
+ "declaration of %0 is missing in %1 class">;
+def err_objc_literal_method_sig : Error<
+ "literal construction method %0 has incompatible signature">;
+def note_objc_literal_method_param : Note<
+ "%select{first|second|third}0 parameter has unexpected type %1 "
+ "(should be %2)">;
+def note_objc_literal_method_return : Note<
+ "method returns unexpected type %0 (should be an object type)">;
+def err_invalid_collection_element : Error<
+ "collection element of type %0 is not an Objective-C object">;
+def err_box_literal_collection : Error<
+ "%select{string|character|boolean|numeric}0 literal must be prefixed by '@' "
+ "in a collection">;
+def warn_objc_literal_comparison : Warning<
+ "direct comparison of %select{an array literal|a dictionary literal|"
+ "a numeric literal|a boxed expression|}0 has undefined behavior">,
+ InGroup<ObjCLiteralComparison>;
+def err_missing_atsign_prefix : Error<
+ "string literal must be prefixed by '@' ">;
+def warn_objc_string_literal_comparison : Warning<
+ "direct comparison of a string literal has undefined behavior">,
+ InGroup<ObjCStringComparison>;
+def warn_concatenated_nsarray_literal : Warning<
+ "concatenated NSString literal for an NSArray expression - "
+ "possibly missing a comma">,
+ InGroup<ObjCStringConcatenation>;
+def note_objc_literal_comparison_isequal : Note<
+ "use 'isEqual:' instead">;
+def warn_objc_collection_literal_element : Warning<
+ "object of type %0 is not compatible with "
+ "%select{array element type|dictionary key type|dictionary value type}1 %2">,
+ InGroup<ObjCLiteralConversion>;
+
+def err_attribute_argument_is_zero : Error<
+ "%0 attribute must be greater than 0">;
+def warn_attribute_argument_n_negative : Warning<
+ "%0 attribute parameter %1 is negative and will be ignored">,
+ InGroup<CudaCompat>;
+def err_property_function_in_objc_container : Error<
+ "use of Objective-C property in function nested in Objective-C "
+ "container not supported, move function outside its container">;
+
+let CategoryName = "Cocoa API Issue" in {
+def warn_objc_redundant_literal_use : Warning<
+ "using %0 with a literal is redundant">, InGroup<ObjCRedundantLiteralUse>;
+}
+
+def err_attr_tlsmodel_arg : Error<"tls_model must be \"global-dynamic\", "
+ "\"local-dynamic\", \"initial-exec\" or \"local-exec\"">;
+
+def err_tls_var_aligned_over_maximum : Error<
+ "alignment (%0) of thread-local variable %1 is greater than the maximum supported "
+ "alignment (%2) for a thread-local variable on this target">;
+
+def err_only_annotate_after_access_spec : Error<
+ "access specifier can only have annotation attributes">;
+
+def err_attribute_section_invalid_for_target : Error<
+ "argument to 'section' attribute is not valid for this target: %0">;
+def warn_mismatched_section : Warning<
+ "section does not match previous declaration">, InGroup<Section>;
+
+def err_anonymous_property: Error<
+ "anonymous property is not supported">;
+def err_property_is_variably_modified : Error<
+ "property %0 has a variably modified type">;
+def err_no_accessor_for_property : Error<
+ "no %select{getter|setter}0 defined for property %1">;
+def error_cannot_find_suitable_accessor : Error<
+ "cannot find suitable %select{getter|setter}0 for property %1">;
+
+def err_alignment_not_power_of_two : Error<
+ "requested alignment is not a power of 2">;
+def err_alignment_dependent_typedef_name : Error<
+ "requested alignment is dependent but declaration is not dependent">;
+
+def err_attribute_aligned_too_great : Error<
+ "requested alignment must be %0 bytes or smaller">;
+def warn_redeclaration_without_attribute_prev_attribute_ignored : Warning<
+ "%q0 redeclared without %1 attribute: previous %1 ignored">,
+ InGroup<DiagGroup<"inconsistent-dllimport">>;
+def warn_dllimport_dropped_from_inline_function : Warning<
+ "%q0 redeclared inline; %1 attribute ignored">,
+ InGroup<IgnoredAttributes>;
+def warn_attribute_ignored : Warning<"%0 attribute ignored">,
+ InGroup<IgnoredAttributes>;
+def warn_attribute_ignored_on_inline :
+ Warning<"%0 attribute ignored on inline function">,
+ InGroup<IgnoredAttributes>;
+def warn_attribute_after_definition_ignored : Warning<
+ "attribute %0 after definition is ignored">,
+ InGroup<IgnoredAttributes>;
+def warn_unknown_attribute_ignored : Warning<
+ "unknown attribute %0 ignored">, InGroup<UnknownAttributes>;
+def warn_cxx11_gnu_attribute_on_type : Warning<
+ "attribute %0 ignored, because it cannot be applied to a type">,
+ InGroup<IgnoredAttributes>;
+def warn_unhandled_ms_attribute_ignored : Warning<
+ "__declspec attribute %0 is not supported">,
+ InGroup<IgnoredAttributes>;
+def err_attribute_invalid_on_stmt : Error<
+ "%0 attribute cannot be applied to a statement">;
+def warn_declspec_attribute_ignored : Warning<
+ "attribute %0 is ignored, place it after "
+ "\"%select{class|struct|interface|union|enum}1\" to apply attribute to "
+ "type declaration">, InGroup<IgnoredAttributes>;
+def warn_attribute_precede_definition : Warning<
+ "attribute declaration must precede definition">,
+ InGroup<IgnoredAttributes>;
+def warn_attribute_void_function_method : Warning<
+ "attribute %0 cannot be applied to "
+ "%select{functions|Objective-C method}1 without return value">,
+ InGroup<IgnoredAttributes>;
+def warn_attribute_weak_on_field : Warning<
+ "__weak attribute cannot be specified on a field declaration">,
+ InGroup<IgnoredAttributes>;
+def warn_gc_attribute_weak_on_local : Warning<
+ "Objective-C GC does not allow weak variables on the stack">,
+ InGroup<IgnoredAttributes>;
+def warn_nsobject_attribute : Warning<
+ "'NSObject' attribute may be put on a typedef only; attribute is ignored">,
+ InGroup<NSobjectAttribute>;
+def warn_independentclass_attribute : Warning<
+ "'objc_independent_class' attribute may be put on a typedef only; "
+ "attribute is ignored">,
+ InGroup<IndependentClassAttribute>;
+def warn_ptr_independentclass_attribute : Warning<
+ "'objc_independent_class' attribute may be put on Objective-C object "
+ "pointer type only; attribute is ignored">,
+ InGroup<IndependentClassAttribute>;
+def warn_attribute_weak_on_local : Warning<
+ "__weak attribute cannot be specified on an automatic variable when ARC "
+ "is not enabled">,
+ InGroup<IgnoredAttributes>;
+def warn_weak_identifier_undeclared : Warning<
+ "weak identifier %0 never declared">;
+def err_attribute_weak_static : Error<
+ "weak declaration cannot have internal linkage">;
+def err_attribute_selectany_non_extern_data : Error<
+ "'selectany' can only be applied to data items with external linkage">;
+def err_declspec_thread_on_thread_variable : Error<
+ "'__declspec(thread)' applied to variable that already has a "
+ "thread-local storage specifier">;
+def err_attribute_dll_not_extern : Error<
+ "%q0 must have external linkage when declared %q1">;
+def err_attribute_dll_thread_local : Error<
+ "%q0 cannot be thread local when declared %q1">;
+def err_attribute_dll_lambda : Error<
+ "lambda cannot be declared %0">;
+def warn_attribute_invalid_on_definition : Warning<
+ "'%0' attribute cannot be specified on a definition">,
+ InGroup<IgnoredAttributes>;
+def err_attribute_dll_redeclaration : Error<
+ "redeclaration of %q0 cannot add %q1 attribute">;
+def warn_attribute_dll_redeclaration : Warning<
+ "redeclaration of %q0 should not add %q1 attribute">,
+ InGroup<DiagGroup<"dll-attribute-on-redeclaration">>;
+def err_attribute_dllimport_function_definition : Error<
+ "dllimport cannot be applied to non-inline function definition">;
+def err_attribute_dll_deleted : Error<
+ "attribute %q0 cannot be applied to a deleted function">;
+def err_attribute_dllimport_data_definition : Error<
+ "definition of dllimport data">;
+def err_attribute_dllimport_static_field_definition : Error<
+ "definition of dllimport static field not allowed">;
+def warn_attribute_dllimport_static_field_definition : Warning<
+ "definition of dllimport static field">,
+ InGroup<DiagGroup<"dllimport-static-field-def">>;
+def warn_attribute_dllexport_explicit_instantiation_decl : Warning<
+ "explicit instantiation declaration should not be 'dllexport'">,
+ InGroup<DiagGroup<"dllexport-explicit-instantiation-decl">>;
+def warn_invalid_initializer_from_system_header : Warning<
+ "invalid constructor form class in system header, should not be explicit">,
+ InGroup<DiagGroup<"invalid-initializer-from-system-header">>;
+def note_used_in_initialization_here : Note<"used in initialization here">;
+def err_attribute_dll_member_of_dll_class : Error<
+ "attribute %q0 cannot be applied to member of %q1 class">;
+def warn_attribute_dll_instantiated_base_class : Warning<
+ "propagating dll attribute to %select{already instantiated|explicitly specialized}0 "
+ "base class template without dll attribute is not supported">,
+ InGroup<DiagGroup<"unsupported-dll-base-class-template">>, DefaultIgnore;
+def err_attribute_dll_ambiguous_default_ctor : Error<
+ "'__declspec(dllexport)' cannot be applied to more than one default constructor in %0">;
+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 err_alias_to_undefined : Error<
+ "alias must point to a defined variable or function">;
+def warn_alias_to_weak_alias : Warning<
+ "alias will always resolve to %0 even if weak definition of alias %1 is overridden">,
+ InGroup<IgnoredAttributes>;
+def warn_alias_with_section : Warning<
+ "alias will not be in section '%0' but in the same section as the aliasee">,
+ InGroup<IgnoredAttributes>;
+def err_duplicate_mangled_name : Error<
+ "definition with same mangled name as another definition">;
+def err_cyclic_alias : Error<
+ "alias definition is part of a cycle">;
+def warn_attribute_wrong_decl_type : Warning<
+ "%0 attribute only applies to %select{functions|unions|"
+ "variables and functions|functions and methods|parameters|"
+ "functions, methods and blocks|functions, methods, and classes|"
+ "functions, methods, and parameters|classes|enums|variables|methods|"
+ "variables, functions and labels|fields and global variables|structs|"
+ "variables and typedefs|thread-local variables|"
+ "variables and fields|variables, data members and tag types|"
+ "types and namespaces|Objective-C interfaces|methods and properties|"
+ "struct or union|struct, union or class|types|"
+ "Objective-C instance methods|init methods of interface or class extension declarations|"
+ "variables, functions and classes|Objective-C protocols|"
+ "functions and global variables|structs, unions, and typedefs|structs and typedefs|"
+ "interface or protocol declarations|kernel functions|non-K&R-style functions}1">,
+ InGroup<IgnoredAttributes>;
+def err_attribute_wrong_decl_type : Error<warn_attribute_wrong_decl_type.Text>;
+def warn_type_attribute_wrong_type : Warning<
+ "'%0' only applies to %select{function|pointer|"
+ "Objective-C object or block pointer}1 types; type here is %2">,
+ InGroup<IgnoredAttributes>;
+def warn_incomplete_encoded_type : Warning<
+ "encoding of %0 type is incomplete because %1 component has unknown encoding">,
+ InGroup<DiagGroup<"encode-type">>;
+def warn_attribute_requires_functions_or_static_globals : Warning<
+ "%0 only applies to variables with static storage duration and functions">,
+ InGroup<IgnoredAttributes>;
+def warn_gnu_inline_attribute_requires_inline : Warning<
+ "'gnu_inline' attribute requires function to be marked 'inline',"
+ " attribute ignored">,
+ InGroup<IgnoredAttributes>;
+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 warn_cconv_ignored : Warning<
+ "calling convention %0 ignored for this target">, InGroup<IgnoredAttributes>;
+def err_cconv_knr : Error<
+ "function with no prototype cannot use the %0 calling convention">;
+def warn_cconv_knr : Warning<
+ err_cconv_knr.Text>,
+ InGroup<DiagGroup<"missing-prototype-for-cc">>;
+def err_cconv_varargs : Error<
+ "variadic function cannot use %0 calling convention">;
+def warn_cconv_varargs : Warning<
+ "%0 calling convention ignored on variadic function">,
+ InGroup<IgnoredAttributes>;
+def warn_cconv_structors : Warning<
+ "%0 calling convention ignored on constructor/destructor">,
+ InGroup<IgnoredAttributes>;
+def err_regparm_mismatch : Error<"function declared with regparm(%0) "
+ "attribute was previously declared "
+ "%plural{0:without the regparm|:with the regparm(%1)}1 attribute">;
+def err_returns_retained_mismatch : Error<
+ "function declared with the ns_returns_retained attribute "
+ "was previously declared without the ns_returns_retained attribute">;
+def err_objc_precise_lifetime_bad_type : Error<
+ "objc_precise_lifetime only applies to retainable types; type here is %0">;
+def warn_objc_precise_lifetime_meaningless : Error<
+ "objc_precise_lifetime is not meaningful for "
+ "%select{__unsafe_unretained|__autoreleasing}0 objects">;
+def err_invalid_pcs : Error<"invalid PCS type">;
+def warn_attribute_not_on_decl : Warning<
+ "%0 attribute ignored when parsing type">, InGroup<IgnoredAttributes>;
+def err_base_specifier_attribute : Error<
+ "%0 attribute cannot be applied to a base specifier">;
+def err_invalid_attribute_on_virtual_function : Error<
+ "%0 attribute cannot be applied to virtual functions">;
+
+// Availability attribute
+def warn_availability_unknown_platform : Warning<
+ "unknown platform %0 in availability macro">, InGroup<Availability>;
+def warn_availability_version_ordering : Warning<
+ "feature cannot be %select{introduced|deprecated|obsoleted}0 in %1 version "
+ "%2 before it was %select{introduced|deprecated|obsoleted}3 in version %4; "
+ "attribute ignored">, InGroup<Availability>;
+def warn_mismatched_availability: Warning<
+ "availability does not match previous declaration">, InGroup<Availability>;
+def warn_mismatched_availability_override : Warning<
+ "%select{|overriding }4method %select{introduced after|"
+ "deprecated before|obsoleted before}0 "
+ "%select{the protocol method it implements|overridden method}4 "
+ "on %1 (%2 vs. %3)">, InGroup<Availability>;
+def warn_mismatched_availability_override_unavail : Warning<
+ "%select{|overriding }1method cannot be unavailable on %0 when "
+ "%select{the protocol method it implements|its overridden method}1 is "
+ "available">,
+ InGroup<Availability>;
+def note_overridden_method : Note<
+ "overridden method is here">;
+def note_protocol_method : Note<
+ "protocol method is here">;
+
+// Thread Safety Attributes
+def warn_invalid_capability_name : Warning<
+ "invalid capability name '%0'; capability name must be 'mutex' or 'role'">,
+ InGroup<ThreadSafetyAttributes>, DefaultIgnore;
+def warn_thread_attribute_ignored : Warning<
+ "ignoring %0 attribute because its argument is invalid">,
+ InGroup<ThreadSafetyAttributes>, DefaultIgnore;
+def warn_thread_attribute_argument_not_lockable : Warning<
+ "%0 attribute requires arguments whose type is annotated "
+ "with 'capability' attribute; type here is %1">,
+ InGroup<ThreadSafetyAttributes>, DefaultIgnore;
+def warn_thread_attribute_decl_not_lockable : Warning<
+ "%0 attribute can only be applied in a context annotated "
+ "with 'capability(\"mutex\")' attribute">,
+ InGroup<ThreadSafetyAttributes>, DefaultIgnore;
+def warn_thread_attribute_decl_not_pointer : Warning<
+ "%0 only applies to pointer types; type here is %1">,
+ InGroup<ThreadSafetyAttributes>, DefaultIgnore;
+def err_attribute_argument_out_of_range : Error<
+ "%0 attribute parameter %1 is out of bounds: "
+ "%plural{0:no parameters to index into|"
+ "1:can only be 1, since there is one parameter|"
+ ":must be between 1 and %2}2">;
+
+// Thread Safety Analysis
+def warn_unlock_but_no_lock : Warning<"releasing %0 '%1' that was not held">,
+ InGroup<ThreadSafetyAnalysis>, DefaultIgnore;
+def warn_unlock_kind_mismatch : Warning<
+ "releasing %0 '%1' using %select{shared|exclusive}2 access, expected "
+ "%select{shared|exclusive}3 access">,
+ InGroup<ThreadSafetyAnalysis>, DefaultIgnore;
+def warn_double_lock : Warning<"acquiring %0 '%1' that is already held">,
+ InGroup<ThreadSafetyAnalysis>, DefaultIgnore;
+def warn_no_unlock : Warning<
+ "%0 '%1' is still held at the end of function">,
+ InGroup<ThreadSafetyAnalysis>, DefaultIgnore;
+def warn_expecting_locked : Warning<
+ "expecting %0 '%1' to be held at the end of function">,
+ InGroup<ThreadSafetyAnalysis>, DefaultIgnore;
+// FIXME: improve the error message about locks not in scope
+def warn_lock_some_predecessors : Warning<
+ "%0 '%1' is not held on every path through here">,
+ InGroup<ThreadSafetyAnalysis>, DefaultIgnore;
+def warn_expecting_lock_held_on_loop : Warning<
+ "expecting %0 '%1' to be held at start of each loop">,
+ InGroup<ThreadSafetyAnalysis>, DefaultIgnore;
+def note_locked_here : Note<"%0 acquired here">;
+def warn_lock_exclusive_and_shared : Warning<
+ "%0 '%1' is acquired exclusively and shared in the same scope">,
+ InGroup<ThreadSafetyAnalysis>, DefaultIgnore;
+def note_lock_exclusive_and_shared : Note<
+ "the other acquisition of %0 '%1' is here">;
+def warn_variable_requires_any_lock : Warning<
+ "%select{reading|writing}1 variable '%0' requires holding "
+ "%select{any mutex|any mutex exclusively}1">,
+ InGroup<ThreadSafetyAnalysis>, DefaultIgnore;
+def warn_var_deref_requires_any_lock : Warning<
+ "%select{reading|writing}1 the value pointed to by '%0' requires holding "
+ "%select{any mutex|any mutex exclusively}1">,
+ InGroup<ThreadSafetyAnalysis>, DefaultIgnore;
+def warn_fun_excludes_mutex : Warning<
+ "cannot call function '%1' while %0 '%2' is held">,
+ InGroup<ThreadSafetyAnalysis>, DefaultIgnore;
+def warn_cannot_resolve_lock : Warning<
+ "cannot resolve lock expression">,
+ InGroup<ThreadSafetyAnalysis>, DefaultIgnore;
+def warn_acquired_before : Warning<
+ "%0 '%1' must be acquired before '%2'">,
+ InGroup<ThreadSafetyAnalysis>, DefaultIgnore;
+def warn_acquired_before_after_cycle : Warning<
+ "Cycle in acquired_before/after dependencies, starting with '%0'">,
+ InGroup<ThreadSafetyAnalysis>, DefaultIgnore;
+
+
+// Thread safety warnings negative capabilities
+def warn_acquire_requires_negative_cap : Warning<
+ "acquiring %0 '%1' requires negative capability '%2'">,
+ InGroup<ThreadSafetyNegative>, DefaultIgnore;
+
+// Thread safety warnings on pass by reference
+def warn_guarded_pass_by_reference : Warning<
+ "passing variable '%1' by reference requires holding %0 "
+ "%select{'%2'|'%2' exclusively}3">,
+ InGroup<ThreadSafetyReference>, DefaultIgnore;
+def warn_pt_guarded_pass_by_reference : Warning<
+ "passing the value that '%1' points to by reference requires holding %0 "
+ "%select{'%2'|'%2' exclusively}3">,
+ InGroup<ThreadSafetyReference>, DefaultIgnore;
+
+// Imprecise thread safety warnings
+def warn_variable_requires_lock : Warning<
+ "%select{reading|writing}3 variable '%1' requires holding %0 "
+ "%select{'%2'|'%2' exclusively}3">,
+ InGroup<ThreadSafetyAnalysis>, DefaultIgnore;
+def warn_var_deref_requires_lock : Warning<
+ "%select{reading|writing}3 the value pointed to by '%1' requires "
+ "holding %0 %select{'%2'|'%2' exclusively}3">,
+ InGroup<ThreadSafetyAnalysis>, DefaultIgnore;
+def warn_fun_requires_lock : Warning<
+ "calling function '%1' requires holding %0 %select{'%2'|'%2' exclusively}3">,
+ InGroup<ThreadSafetyAnalysis>, DefaultIgnore;
+
+// Precise thread safety warnings
+def warn_variable_requires_lock_precise :
+ Warning<warn_variable_requires_lock.Text>,
+ InGroup<ThreadSafetyPrecise>, DefaultIgnore;
+def warn_var_deref_requires_lock_precise :
+ Warning<warn_var_deref_requires_lock.Text>,
+ InGroup<ThreadSafetyPrecise>, DefaultIgnore;
+def warn_fun_requires_lock_precise :
+ Warning<warn_fun_requires_lock.Text>,
+ InGroup<ThreadSafetyPrecise>, DefaultIgnore;
+def note_found_mutex_near_match : Note<"found near match '%0'">;
+
+// Verbose thread safety warnings
+def warn_thread_safety_verbose : Warning<"Thread safety verbose warning.">,
+ InGroup<ThreadSafetyVerbose>, DefaultIgnore;
+def note_thread_warning_in_fun : Note<"Thread warning in function '%0'">;
+def note_guarded_by_declared_here : Note<"Guarded_by declared here.">;
+
+// Dummy warning that will trigger "beta" warnings from the analysis if enabled.
+def warn_thread_safety_beta : Warning<"Thread safety beta warning.">,
+ InGroup<ThreadSafetyBeta>, DefaultIgnore;
+
+// Consumed warnings
+def warn_use_in_invalid_state : Warning<
+ "invalid invocation of method '%0' on object '%1' while it is in the '%2' "
+ "state">, InGroup<Consumed>, DefaultIgnore;
+def warn_use_of_temp_in_invalid_state : Warning<
+ "invalid invocation of method '%0' on a temporary object while it is in the "
+ "'%1' state">, InGroup<Consumed>, DefaultIgnore;
+def warn_attr_on_unconsumable_class : Warning<
+ "consumed analysis attribute is attached to member of class '%0' which isn't "
+ "marked as consumable">, InGroup<Consumed>, DefaultIgnore;
+def warn_return_typestate_for_unconsumable_type : Warning<
+ "return state set for an unconsumable type '%0'">, InGroup<Consumed>,
+ DefaultIgnore;
+def warn_return_typestate_mismatch : Warning<
+ "return value not in expected state; expected '%0', observed '%1'">,
+ InGroup<Consumed>, DefaultIgnore;
+def warn_loop_state_mismatch : Warning<
+ "state of variable '%0' must match at the entry and exit of loop">,
+ InGroup<Consumed>, DefaultIgnore;
+def warn_param_return_typestate_mismatch : Warning<
+ "parameter '%0' not in expected state when the function returns: expected "
+ "'%1', observed '%2'">, InGroup<Consumed>, DefaultIgnore;
+def warn_param_typestate_mismatch : Warning<
+ "argument not in expected state; expected '%0', observed '%1'">,
+ InGroup<Consumed>, DefaultIgnore;
+
+// no_sanitize attribute
+def warn_unknown_sanitizer_ignored : Warning<
+ "unknown sanitizer '%0' ignored">, InGroup<UnknownSanitizers>;
+
+def warn_impcast_vector_scalar : Warning<
+ "implicit conversion turns vector to scalar: %0 to %1">,
+ InGroup<Conversion>, DefaultIgnore;
+def warn_impcast_complex_scalar : Warning<
+ "implicit conversion discards imaginary component: %0 to %1">,
+ InGroup<Conversion>, DefaultIgnore;
+def warn_impcast_float_precision : Warning<
+ "implicit conversion loses floating-point precision: %0 to %1">,
+ InGroup<Conversion>, DefaultIgnore;
+def warn_impcast_double_promotion : Warning<
+ "implicit conversion increases floating-point precision: %0 to %1">,
+ InGroup<DoublePromotion>, DefaultIgnore;
+def warn_impcast_float_integer : Warning<
+ "implicit conversion turns floating-point number into integer: %0 to %1">,
+ InGroup<FloatConversion>, DefaultIgnore;
+def warn_impcast_integer_sign : Warning<
+ "implicit conversion changes signedness: %0 to %1">,
+ InGroup<SignConversion>, DefaultIgnore;
+def warn_impcast_integer_sign_conditional : Warning<
+ "operand of ? changes signedness: %0 to %1">,
+ InGroup<SignConversion>, DefaultIgnore;
+def warn_impcast_integer_precision : Warning<
+ "implicit conversion loses integer precision: %0 to %1">,
+ InGroup<Conversion>, DefaultIgnore;
+def warn_impcast_integer_64_32 : Warning<
+ "implicit conversion loses integer precision: %0 to %1">,
+ InGroup<Shorten64To32>, DefaultIgnore;
+def warn_impcast_integer_precision_constant : Warning<
+ "implicit conversion from %2 to %3 changes value from %0 to %1">,
+ InGroup<ConstantConversion>;
+def warn_impcast_bitfield_precision_constant : Warning<
+ "implicit truncation from %2 to bitfield changes value from %0 to %1">,
+ InGroup<BitFieldConstantConversion>;
+def warn_impcast_literal_float_to_integer : Warning<
+ "implicit conversion from %0 to %1 changes value from %2 to %3">,
+ InGroup<LiteralConversion>;
+def warn_impcast_string_literal_to_bool : Warning<
+ "implicit conversion turns string literal into bool: %0 to %1">,
+ InGroup<StringConversion>, DefaultIgnore;
+def warn_impcast_different_enum_types : Warning<
+ "implicit conversion from enumeration type %0 to different enumeration type "
+ "%1">, InGroup<EnumConversion>;
+def warn_impcast_bool_to_null_pointer : Warning<
+ "initialization of pointer of type %0 to null from a constant boolean "
+ "expression">, InGroup<BoolConversion>;
+def warn_non_literal_null_pointer : Warning<
+ "expression which evaluates to zero treated as a null pointer constant of "
+ "type %0">, InGroup<NonLiteralNullConversion>;
+def warn_impcast_null_pointer_to_integer : Warning<
+ "implicit conversion of %select{NULL|nullptr}0 constant to %1">,
+ InGroup<NullConversion>;
+def warn_impcast_floating_point_to_bool : Warning<
+ "implicit conversion turns floating-point number into bool: %0 to %1">,
+ InGroup<ImplicitConversionFloatingPointToBool>;
+def ext_ms_impcast_fn_obj : ExtWarn<
+ "implicit conversion between pointer-to-function and pointer-to-object is a "
+ "Microsoft extension">, InGroup<MicrosoftCast>;
+
+def warn_impcast_pointer_to_bool : Warning<
+ "address of%select{| function| array}0 '%1' will always evaluate to "
+ "'true'">,
+ InGroup<PointerBoolConversion>;
+def warn_cast_nonnull_to_bool : Warning<
+ "nonnull %select{function call|parameter}0 '%1' will evaluate to "
+ "'true' on first encounter">,
+ InGroup<PointerBoolConversion>;
+def warn_this_bool_conversion : Warning<
+ "'this' pointer cannot be null in well-defined C++ code; pointer may be "
+ "assumed to always convert to true">, InGroup<UndefinedBoolConversion>;
+def warn_address_of_reference_bool_conversion : Warning<
+ "reference cannot be bound to dereferenced null pointer in well-defined C++ "
+ "code; pointer may be assumed to always convert to true">,
+ InGroup<UndefinedBoolConversion>;
+
+def warn_null_pointer_compare : Warning<
+ "comparison of %select{address of|function|array}0 '%1' %select{not |}2"
+ "equal to a null pointer is always %select{true|false}2">,
+ InGroup<TautologicalPointerCompare>;
+def warn_nonnull_expr_compare : Warning<
+ "comparison of nonnull %select{function call|parameter}0 '%1' "
+ "%select{not |}2equal to a null pointer is '%select{true|false}2' on first "
+ "encounter">,
+ InGroup<TautologicalPointerCompare>;
+def warn_this_null_compare : Warning<
+ "'this' pointer cannot be null in well-defined C++ code; comparison may be "
+ "assumed to always evaluate to %select{true|false}0">,
+ InGroup<TautologicalUndefinedCompare>;
+def warn_address_of_reference_null_compare : Warning<
+ "reference cannot be bound to dereferenced null pointer in well-defined C++ "
+ "code; comparison may be assumed to always evaluate to "
+ "%select{true|false}0">,
+ InGroup<TautologicalUndefinedCompare>;
+def note_reference_is_return_value : Note<"%0 returns a reference">;
+
+def note_function_warning_silence : Note<
+ "prefix with the address-of operator to silence this warning">;
+def note_function_to_function_call : Note<
+ "suffix with parentheses to turn this into a function call">;
+def warn_impcast_objective_c_literal_to_bool : Warning<
+ "implicit boolean conversion of Objective-C object literal always "
+ "evaluates to true">,
+ InGroup<ObjCLiteralConversion>;
+
+def warn_cast_align : Warning<
+ "cast from %0 to %1 increases required alignment from %2 to %3">,
+ InGroup<CastAlign>, DefaultIgnore;
+def warn_old_style_cast : Warning<
+ "use of old-style cast">, InGroup<OldStyleCast>, DefaultIgnore;
+
+// Separate between casts to void* and non-void* pointers.
+// Some APIs use (abuse) void* for something like a user context,
+// and often that value is an integer even if it isn't a pointer itself.
+// Having a separate warning flag allows users to control the warning
+// for their workflow.
+def warn_int_to_pointer_cast : Warning<
+ "cast to %1 from smaller integer type %0">,
+ InGroup<IntToPointerCast>;
+def warn_int_to_void_pointer_cast : Warning<
+ "cast to %1 from smaller integer type %0">,
+ InGroup<IntToVoidPointerCast>;
+
+def warn_attribute_packed_for_bitfield : Warning<
+ "'packed' attribute was ignored on bit-fields with single-byte alignment "
+ "in older versions of GCC and Clang">,
+ InGroup<DiagGroup<"attribute-packed-for-bitfield">>;
+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">,
+ InGroup<IgnoredAttributes>;
+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">,
+ InGroup<IgnoredAttributes>;
+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">,
+ InGroup<IgnoredAttributes>;
+def warn_transparent_union_attribute_zero_fields : Warning<
+ "transparent union definition must contain at least one field; "
+ "transparent_union attribute ignored">,
+ InGroup<IgnoredAttributes>;
+def warn_attribute_type_not_supported : Warning<
+ "%0 attribute argument not supported: %1">,
+ InGroup<IgnoredAttributes>;
+def warn_attribute_unknown_visibility : Warning<"unknown visibility %0">,
+ InGroup<IgnoredAttributes>;
+def warn_attribute_protected_visibility :
+ Warning<"target does not support 'protected' visibility; using 'default'">,
+ InGroup<DiagGroup<"unsupported-visibility">>;
+def err_mismatched_visibility: Error<"visibility does not match previous declaration">;
+def note_previous_attribute : Note<"previous attribute is here">;
+def note_conflicting_attribute : Note<"conflicting attribute is here">;
+def note_attribute : Note<"attribute is here">;
+def err_mismatched_ms_inheritance : Error<
+ "inheritance model does not match %select{definition|previous declaration}0">;
+def warn_ignored_ms_inheritance : Warning<
+ "inheritance model ignored on %select{primary template|partial specialization}0">,
+ InGroup<IgnoredAttributes>;
+def note_previous_ms_inheritance : Note<
+ "previous inheritance model specified here">;
+def err_machine_mode : Error<"%select{unknown|unsupported}0 machine mode %1">;
+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 warn_vector_mode_deprecated : Warning<
+ "specifying vector types with the 'mode' attribute is deprecated; "
+ "use the 'vector_size' attribute instead">,
+ InGroup<DeprecatedAttributes>;
+def err_complex_mode_vector_type : Error<
+ "type of machine mode does not support base vector types">;
+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">,
+ InGroup<IgnoredAttributes>;
+def warn_attribute_nonnull_parm_no_args : Warning<
+ "'nonnull' attribute when used on parameters takes no arguments">,
+ InGroup<IgnoredAttributes>;
+def warn_attribute_sentinel_named_arguments : Warning<
+ "'sentinel' attribute requires named arguments">,
+ InGroup<IgnoredAttributes>;
+def warn_attribute_sentinel_not_variadic : Warning<
+ "'sentinel' attribute only supported for variadic %select{functions|blocks}0">,
+ InGroup<IgnoredAttributes>;
+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 warn_cleanup_ext : Warning<
+ "GCC does not allow the 'cleanup' attribute argument to be anything other "
+ "than a simple identifier">,
+ InGroup<GccCompat>;
+def err_attribute_cleanup_arg_not_function : Error<
+ "'cleanup' argument %select{|%1 |%1 }0is not a %select{||single }0function">;
+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 "
+ "%diff{type $ which is incompatible with type $|incompatible type}1,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">;
+def err_attribute_not_supported_in_lang : Error<
+ "%0 attribute is not supported in %select{C|C++|Objective-C}1">;
+
+
+// Clang-Specific Attributes
+def warn_attribute_iboutlet : Warning<
+ "%0 attribute can only be applied to instance variables or properties">,
+ InGroup<IgnoredAttributes>;
+def err_iboutletcollection_type : Error<
+ "invalid type %0 as argument of iboutletcollection attribute">;
+def err_iboutletcollection_builtintype : Error<
+ "type argument of iboutletcollection attribute cannot be a builtin type">;
+def warn_iboutlet_object_type : Warning<
+ "%select{instance variable|property}2 with %0 attribute must "
+ "be an object type (invalid %1)">, InGroup<ObjCInvalidIBOutletProperty>;
+def warn_iboutletcollection_property_assign : Warning<
+ "IBOutletCollection properties should be copy/strong and not assign">,
+ InGroup<ObjCInvalidIBOutletProperty>;
+
+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|properties}1 that "
+ "return %select{an Objective-C object|a pointer|a non-retainable pointer}2">,
+ InGroup<IgnoredAttributes>;
+def warn_ns_attribute_wrong_parameter_type : Warning<
+ "%0 attribute only applies to "
+ "%select{Objective-C object|pointer|pointer-to-CF-pointer}1 parameters">,
+ InGroup<IgnoredAttributes>;
+def warn_objc_requires_super_protocol : Warning<
+ "%0 attribute cannot be applied to %select{methods in protocols|dealloc}1">,
+ InGroup<DiagGroup<"requires-super-attribute">>;
+def note_protocol_decl : Note<
+ "protocol is declared here">;
+def note_protocol_decl_undefined : Note<
+ "protocol %0 has no definition">;
+
+// objc_designated_initializer attribute diagnostics.
+def warn_objc_designated_init_missing_super_call : Warning<
+ "designated initializer missing a 'super' call to a designated initializer of the super class">,
+ InGroup<ObjCDesignatedInit>;
+def note_objc_designated_init_marked_here : Note<
+ "method marked as designated initializer of the class here">;
+def warn_objc_designated_init_non_super_designated_init_call : Warning<
+ "designated initializer should only invoke a designated initializer on 'super'">,
+ InGroup<ObjCDesignatedInit>;
+def warn_objc_designated_init_non_designated_init_call : Warning<
+ "designated initializer invoked a non-designated initializer">,
+ InGroup<ObjCDesignatedInit>;
+def warn_objc_secondary_init_super_init_call : Warning<
+ "convenience initializer should not invoke an initializer on 'super'">,
+ InGroup<ObjCDesignatedInit>;
+def warn_objc_secondary_init_missing_init_call : Warning<
+ "convenience initializer missing a 'self' call to another initializer">,
+ InGroup<ObjCDesignatedInit>;
+def warn_objc_implementation_missing_designated_init_override : Warning<
+ "method override for the designated initializer of the superclass %objcinstance0 not found">,
+ InGroup<ObjCDesignatedInit>;
+
+// objc_bridge attribute diagnostics.
+def err_objc_attr_not_id : Error<
+ "parameter of %0 attribute must be a single name of an Objective-C %select{class|protocol}1">;
+def err_objc_attr_typedef_not_id : Error<
+ "parameter of %0 attribute must be 'id' when used on a typedef">;
+def err_objc_attr_typedef_not_void_pointer : Error<
+ "'objc_bridge(id)' is only allowed on structs and typedefs of void pointers">;
+def err_objc_cf_bridged_not_interface : Error<
+ "CF object of type %0 is bridged to %1, which is not an Objective-C class">;
+def err_objc_ns_bridged_invalid_cfobject : Error<
+ "ObjectiveC object of type %0 is bridged to %1, which is not valid CF object">;
+def warn_objc_invalid_bridge : Warning<
+ "%0 bridges to %1, not %2">, InGroup<ObjCBridge>;
+def warn_objc_invalid_bridge_to_cf : Warning<
+ "%0 cannot bridge to %1">, InGroup<ObjCBridge>;
+
+// objc_bridge_related attribute diagnostics.
+def err_objc_bridged_related_invalid_class : Error<
+ "could not find Objective-C class %0 to convert %1 to %2">;
+def err_objc_bridged_related_invalid_class_name : Error<
+ "%0 must be name of an Objective-C class to be able to convert %1 to %2">;
+def err_objc_bridged_related_known_method : Error<
+ "%0 must be explicitly converted to %1; use %select{%objcclass2|%objcinstance2}3 "
+ "method for this conversion">;
+
+def err_objc_attr_protocol_requires_definition : Error<
+ "attribute %0 can only be applied to @protocol definitions, not forward declarations">;
+
+// 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_default_argument : Error<
+ "C does not support default arguments">;
+def err_param_default_argument_redefinition : Error<
+ "redefinition of default argument">;
+def ext_param_default_argument_redefinition : ExtWarn<
+ err_param_default_argument_redefinition.Text>,
+ InGroup<MicrosoftDefaultArgRedefinition>;
+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_param_default_argument_on_parameter_pack : Error<
+ "parameter pack cannot have a default argument">;
+def err_uninitialized_member_for_assign : Error<
+ "cannot define the implicit copy assignment operator for %0, because "
+ "non-static %select{reference|const}1 member %2 cannot use copy "
+ "assignment operator">;
+def err_uninitialized_member_in_ctor : Error<
+ "%select{|implicit default |inheriting }0constructor for %1 must explicitly "
+ "initialize the %select{reference|const}2 member %3">;
+def err_default_arg_makes_ctor_special : Error<
+ "addition of default argument on redeclaration makes this constructor a "
+ "%select{default|copy|move}0 constructor">;
+
+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<
+ "%diff{promoted type $ of K&R function parameter is not compatible with the "
+ "parameter type $|promoted type of K&R function parameter is not compatible "
+ "with parameter type}0,1 declared in a previous prototype">,
+ InGroup<KNRPromotedParameter>;
+
+
+// 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%2">;
+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%2">;
+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 move constructor|"
+ "is the implicit copy assignment operator|"
+ "is the implicit move assignment operator|"
+ "is an inherited constructor}0%1"
+ "%select{| has different class%diff{ (expected $ but has $)|}3,4"
+ "| has different number of parameters (expected %3 but has %4)"
+ "| has type mismatch at %ordinal3 parameter"
+ "%diff{ (expected $ but has $)|}4,5"
+ "| has different return type%diff{ ($ expected but has $)|}3,4"
+ "| has different qualifiers (expected "
+ "%select{none|const|restrict|const and restrict|volatile|const and volatile"
+ "|volatile and restrict|const, volatile, and restrict}3 but found "
+ "%select{none|const|restrict|const and restrict|volatile|const and volatile"
+ "|volatile and restrict|const, volatile, and restrict}4)}2">;
+
+def note_ovl_candidate_inherited_constructor : Note<"inherited from here">;
+def note_ovl_candidate_illegal_constructor : Note<
+ "candidate %select{constructor|template}0 ignored: "
+ "instantiation %select{takes|would take}0 its own class type by value">;
+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%diff{ ($ vs. $)|}2,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: cannot deduce a type for %0 that would "
+ "make %2 equal %1">;
+def note_ovl_candidate_substitution_failure : Note<
+ "candidate template ignored: substitution failure%0%1">;
+def note_ovl_candidate_disabled_by_enable_if : Note<
+ "candidate template ignored: disabled by %0%1">;
+def note_ovl_candidate_has_pass_object_size_params: Note<
+ "candidate address cannot be taken because parameter %0 has "
+ "pass_object_size attribute">;
+def note_ovl_candidate_disabled_by_enable_if_attr : Note<
+ "candidate disabled: %0">;
+def err_addrof_function_disabled_by_enable_if_attr : Error<
+ "cannot take address of function %0 becuase it has one or more "
+ "non-tautological enable_if conditions">;
+def note_addrof_ovl_candidate_disabled_by_enable_if_attr : Note<
+ "candidate function made ineligible by enable_if">;
+def note_ovl_candidate_failed_overload_resolution : Note<
+ "candidate template ignored: couldn't resolve reference to overloaded "
+ "function %0">;
+def note_ovl_candidate_deduced_mismatch : Note<
+ "candidate template ignored: deduced type "
+ "%diff{$ of %ordinal0 parameter does not match adjusted type $ of argument"
+ "|of %ordinal0 parameter does not match adjusted type of argument}1,2%3">;
+def note_ovl_candidate_non_deduced_mismatch : Note<
+ "candidate template ignored: could not match %diff{$ against $|types}0,1">;
+// This note is needed because the above note would sometimes print two
+// different types with the same name. Remove this note when the above note
+// can handle that case properly.
+def note_ovl_candidate_non_deduced_mismatch_qualified : Note<
+ "candidate template ignored: could not match %q0 against %q1">;
+
+// 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)|"
+ "constructor (the implicit move constructor)|"
+ "function (the implicit copy assignment operator)|"
+ "function (the implicit move 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_arity_one : Note<"candidate "
+ "%select{function|function|constructor|function|function|constructor|"
+ "constructor (the implicit default constructor)|"
+ "constructor (the implicit copy constructor)|"
+ "constructor (the implicit move constructor)|"
+ "function (the implicit copy assignment operator)|"
+ "function (the implicit move assignment operator)|"
+ "constructor (inherited)}0 %select{|template }1not viable: "
+ "%select{requires at least|allows at most single|requires single}2 "
+ "argument %3, but %plural{0:no|:%4}4 arguments were provided">;
+
+def note_ovl_candidate_deleted : Note<
+ "candidate %select{function|function|constructor|"
+ "function |function |constructor |"
+ "constructor (the implicit default constructor)|"
+ "constructor (the implicit copy constructor)|"
+ "constructor (the implicit move constructor)|"
+ "function (the implicit copy assignment operator)|"
+ "function (the implicit move assignment operator)|"
+ "constructor (inherited)}0%1 has been "
+ "%select{explicitly made unavailable|explicitly deleted|"
+ "implicitly 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)|"
+ "constructor (the implicit move constructor)|"
+ "function (the implicit copy assignment operator)|"
+ "function (the implicit move assignment operator)|"
+ "constructor (inherited)}0%1 "
+ "not viable: cannot convert argument of incomplete type "
+ "%diff{$ to $|to parameter type}2,3">;
+def note_ovl_candidate_bad_list_argument : Note<"candidate "
+ "%select{function|function|constructor|"
+ "function |function |constructor |"
+ "constructor (the implicit default constructor)|"
+ "constructor (the implicit copy constructor)|"
+ "constructor (the implicit move constructor)|"
+ "function (the implicit copy assignment operator)|"
+ "function (the implicit move assignment operator)|"
+ "constructor (inherited)}0%1 "
+ "not viable: cannot convert initializer list argument 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)|"
+ "constructor (the implicit move constructor)|"
+ "function (the implicit copy assignment operator)|"
+ "function (the implicit move 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)|"
+ "constructor (the implicit move constructor)|"
+ "function (the implicit copy assignment operator)|"
+ "function (the implicit move assignment operator)|"
+ "constructor (inherited)}0%1"
+ " not viable: no known conversion "
+ "%diff{from $ to $|from argument type to parameter type}2,3 for "
+ "%select{%ordinal5 argument|object argument}4"
+ "%select{|; dereference the argument with *|"
+ "; take the address of the argument with &|"
+ "; remove *|"
+ "; remove &}6">;
+def note_ovl_candidate_bad_arc_conv : Note<"candidate "
+ "%select{function|function|constructor|"
+ "function |function |constructor |"
+ "constructor (the implicit default constructor)|"
+ "constructor (the implicit copy constructor)|"
+ "constructor (the implicit move constructor)|"
+ "function (the implicit copy assignment operator)|"
+ "function (the implicit move assignment operator)|"
+ "constructor (inherited)}0%1"
+ " not viable: cannot implicitly convert argument "
+ "%diff{of type $ to $|type to parameter type}2,3 for "
+ "%select{%ordinal5 argument|object argument}4 under ARC">;
+def note_ovl_candidate_bad_lvalue : Note<"candidate "
+ "%select{function|function|constructor|"
+ "function |function |constructor |"
+ "constructor (the implicit default constructor)|"
+ "constructor (the implicit copy constructor)|"
+ "constructor (the implicit move constructor)|"
+ "function (the implicit copy assignment operator)|"
+ "function (the implicit move assignment operator)|"
+ "constructor (inherited)}0%1"
+ " not viable: expects an l-value for "
+ "%select{%ordinal3 argument|object argument}2">;
+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)|"
+ "constructor (the implicit move constructor)|"
+ "function (the implicit copy assignment operator)|"
+ "function (the implicit move 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_gc : Note<"candidate "
+ "%select{function|function|constructor|"
+ "function |function |constructor |"
+ "constructor (the implicit default constructor)|"
+ "constructor (the implicit copy constructor)|"
+ "constructor (the implicit move constructor)|"
+ "function (the implicit copy assignment operator)|"
+ "function (the implicit move assignment operator)|"
+ "constructor (inherited)}0%1 not viable: "
+ "%select{%ordinal6|'this'}5 argument (%2) has %select{no|__weak|__strong}3 "
+ "ownership, but parameter has %select{no|__weak|__strong}4 ownership">;
+def note_ovl_candidate_bad_ownership : Note<"candidate "
+ "%select{function|function|constructor|"
+ "function |function |constructor |"
+ "constructor (the implicit default constructor)|"
+ "constructor (the implicit copy constructor)|"
+ "constructor (the implicit move constructor)|"
+ "function (the implicit copy assignment operator)|"
+ "function (the implicit move assignment operator)|"
+ "constructor (inherited)}0%1 not viable: "
+ "%select{%ordinal6|'this'}5 argument (%2) has "
+ "%select{no|__unsafe_unretained|__strong|__weak|__autoreleasing}3 ownership,"
+ " but parameter has %select{no|__unsafe_unretained|__strong|__weak|"
+ "__autoreleasing}4 ownership">;
+def note_ovl_candidate_bad_cvr_this : Note<"candidate "
+ "%select{|function|||function|||||"
+ "function (the implicit copy assignment operator)|"
+ "function (the implicit move 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)|"
+ "constructor (the implicit move constructor)|"
+ "function (the implicit copy assignment operator)|"
+ "function (the implicit move 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)|"
+ "constructor (the implicit move constructor)|"
+ "function (the implicit copy assignment operator)|"
+ "function (the implicit move 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_ovl_candidate_bad_target : Note<
+ "candidate %select{function|function|constructor|"
+ "function |function |constructor |"
+ "constructor (the implicit default constructor)|"
+ "constructor (the implicit copy constructor)|"
+ "constructor (the implicit move constructor)|"
+ "function (the implicit copy assignment operator)|"
+ "function (the implicit move assignment operator)|"
+ "constructor (inherited)}0 not viable: call to "
+ "%select{__device__|__global__|__host__|__host__ __device__|invalid}1 function from"
+ " %select{__device__|__global__|__host__|__host__ __device__|invalid}2 function">;
+def note_implicit_member_target_infer_collision : Note<
+ "implicit %select{"
+ "default constructor|"
+ "copy constructor|"
+ "move constructor|"
+ "copy assignment operator|"
+ "move assignment operator|"
+ "destructor}0 inferred target collision: call to both "
+ "%select{__device__|__global__|__host__|__host__ __device__}1 and "
+ "%select{__device__|__global__|__host__|__host__ __device__}2 members">;
+
+def note_ambiguous_type_conversion: Note<
+ "because of ambiguity in conversion %diff{of $ to $|between types}0,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_deleted_special_init : Error<
+ "call to implicitly-deleted %select{default constructor|copy constructor|"
+ "move constructor|copy assignment operator|move assignment operator|"
+ "destructor|function}0 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 note_assign_lhs_incomplete : Note<"type %0 is incomplete">;
+def err_ovl_deleted_oper : Error<
+ "overload resolution selected %select{unavailable|deleted}0 operator '%1'%2">;
+def err_ovl_deleted_special_oper : Error<
+ "object of type %0 cannot be %select{constructed|copied|moved|assigned|"
+ "assigned|destroyed}1 because its %select{default constructor|"
+ "copy constructor|move constructor|copy assignment operator|"
+ "move assignment operator|destructor}1 is implicitly deleted">;
+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<
+ "reference to overloaded function could not be resolved; "
+ "did you mean to call it%select{| with no arguments}0?">;
+def err_bound_member_function : Error<
+ "reference to non-static member function must be called"
+ "%select{|; did you mean to call it with no arguments?}0">;
+def note_possible_target_of_call : Note<"possible target for call">;
+
+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%2">;
+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<
+ "cannot form member pointer of type %0 without '&' and class name">;
+
+// C++11 Literal Operators
+def err_ovl_no_viable_literal_operator : Error<
+ "no matching literal operator for call to %0"
+ "%select{| with argument of type %2| with arguments of types %2 and %3}1"
+ "%select{| or 'const char *'}4"
+ "%select{|, and no matching literal operator template}5">;
+
+// 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_inside_local_class : Error<
+ "templates cannot be declared inside of a local class">;
+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++11 extension">,
+ InGroup<CXX11>;
+def warn_cxx98_compat_template_parameter_default_in_function_template : Warning<
+ "default template arguments for a function template are incompatible with C++98">,
+ InGroup<CXX98Compat>, DefaultIgnore;
+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 ext_variable_template : ExtWarn<"variable templates are a C++14 extension">,
+ InGroup<CXX14>;
+def warn_cxx11_compat_variable_template : Warning<
+ "variable templates are incompatible with C++ standards before C++14">,
+ InGroup<CXXPre14Compat>, DefaultIgnore;
+def err_template_variable_noparams : Error<
+ "extraneous 'template<>' in declaration of variable %0">;
+def err_template_member : Error<"member %0 declared as a template">;
+def err_template_member_noparams : Error<
+ "extraneous 'template<>' in declaration of member %0">;
+def err_template_tag_noparams : Error<
+ "extraneous 'template<>' in declaration of %0 %1">;
+def err_template_decl_ref : Error<
+ "cannot refer to %select{class|variable}0 template %1 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 err_template_arg_must_be_type : Error<
+ "template argument for template type parameter must be a type">;
+def err_template_arg_must_be_type_suggest : Error<
+ "template argument for template type parameter must be a type; "
+ "did you forget 'typename'?">;
+def ext_ms_template_type_arg_missing_typename : ExtWarn<
+ "template argument for template type parameter must be a type; "
+ "omitted 'typename' is a Microsoft extension">,
+ InGroup<MicrosoftTemplate>;
+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 function type %0">;
+def err_template_arg_must_be_template : Error<
+ "template argument for template template parameter must be a class template%select{| or type alias template}0">;
+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 warn_cxx98_compat_template_arg_local_type : Warning<
+ "local type %0 as template argument is incompatible with C++98">,
+ InGroup<CXX98CompatLocalTypeTemplateArgs>, DefaultIgnore;
+def warn_cxx98_compat_template_arg_unnamed_type : Warning<
+ "unnamed type as template argument is incompatible with C++98">,
+ InGroup<CXX98CompatUnnamedTypeTemplateArgs>, DefaultIgnore;
+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_template_arg_not_address_constant : Error<
+ "non-type template argument of type %0 is not a constant expression">;
+def warn_cxx98_compat_template_arg_null : Warning<
+ "use of null pointer as non-type template argument is incompatible with "
+ "C++98">, InGroup<CXX98Compat>, DefaultIgnore;
+def err_template_arg_untyped_null_constant : Error<
+ "null non-type template argument must be cast to template parameter type %0">;
+def err_template_arg_wrongtype_null_constant : Error<
+ "null non-type template argument of type %0 does not match template parameter "
+ "of type %1">;
+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%diff{ ($ vs $)|}0,1">;
+def err_non_type_template_arg_subobject : Error<
+ "non-type template argument refers to subobject '%0'">;
+def err_non_type_template_arg_addr_label_diff : Error<
+ "template argument / label address difference / what did you expect?">;
+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 "
+ "%diff{$ cannot bind to template argument of type $"
+ "|cannot bind to template of incompatible argument type}0,1">;
+def err_template_arg_ref_bind_ignores_quals : Error<
+ "reference binding of non-type template parameter "
+ "%diff{of type $ to template argument of type $|to template argument}0,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_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_object_no_linkage : Error<
+ "non-type template argument refers to %select{function|object}0 %1 that "
+ "does not have linkage">;
+def warn_cxx98_compat_template_arg_object_internal : Warning<
+ "non-type template argument referring to %select{function|object}0 %1 with "
+ "internal linkage is incompatible with C++98">,
+ InGroup<CXX98Compat>, DefaultIgnore;
+def ext_template_arg_object_internal : ExtWarn<
+ "non-type template argument referring to %select{function|object}0 %1 with "
+ "internal linkage is a C++11 extension">, InGroup<CXX11>;
+def err_template_arg_thread_local : Error<
+ "non-type template argument refers to thread-local object">;
+def note_template_arg_internal_object : Note<
+ "non-type template argument refers to %select{function|object}0 here">;
+def note_template_arg_refers_here : Note<
+ "non-type 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 err_template_arg_member_ptr_base_derived_not_supported : Error<
+ "sorry, non-type template argument of pointer-to-member type %1 that refers "
+ "to member %q0 of a different class is not supported yet">;
+def ext_template_arg_extra_parens : ExtWarn<
+ "address non-type template argument cannot be surrounded by parentheses">;
+def warn_cxx98_compat_template_arg_extra_parens : Warning<
+ "redundant parentheses surrounding address non-type template argument are "
+ "incompatible with C++98">, InGroup<CXX98Compat>, DefaultIgnore;
+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">;
+def ext_ms_deref_template_argument: ExtWarn<
+ "non-type template argument containing a dereference operation is a "
+ "Microsoft extension">, InGroup<MicrosoftTemplate>;
+def ext_ms_delayed_template_argument: ExtWarn<
+ "using the undeclared type %0 as a default template argument is a "
+ "Microsoft extension">, InGroup<MicrosoftTemplate>;
+
+// C++ template specialization
+def err_template_spec_unknown_kind : Error<
+ "can only provide an explicit specialization for a class template, function "
+ "template, variable template, or a member function, static data member, "
+ "%select{or member class|member class, or member enumeration}0 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|variable template|"
+ "variable template partial|function template|member function|"
+ "static data member|member class|member enumeration}0 "
+ "specialization of %1 must originally be declared in the global scope">;
+def err_template_spec_decl_out_of_scope : Error<
+ "%select{class template|class template partial|variable template|"
+ "variable template partial|function template|member "
+ "function|static data member|member class|member enumeration}0 "
+ "specialization of %1 must originally be declared in namespace %2">;
+def ext_template_spec_decl_out_of_scope : ExtWarn<
+ "first declaration of %select{class template|class template partial|"
+ "variable template|variable template partial|"
+ "function template|member function|static data member|member class|"
+ "member enumeration}0 specialization of %1 outside namespace %2 is a "
+ "C++11 extension">, InGroup<CXX11>;
+def warn_cxx98_compat_template_spec_decl_out_of_scope : Warning<
+ "%select{class template|class template partial|variable template|"
+ "variable template partial|function template|member "
+ "function|static data member|member class|member enumeration}0 "
+ "specialization of %1 outside namespace %2 is incompatible with C++98">,
+ InGroup<CXX98Compat>, DefaultIgnore;
+def err_template_spec_redecl_out_of_scope : Error<
+ "%select{class template|class template partial|variable template|"
+ "variable template partial|function template|member "
+ "function|static data member|member class|member enumeration}0 "
+ "specialization of %1 not in a namespace enclosing %2">;
+def ext_ms_template_spec_redecl_out_of_scope: ExtWarn<
+ "%select{class template|class template partial|variable template|"
+ "variable template partial|function template|member "
+ "function|static data member|member class|member enumeration}0 "
+ "specialization of %1 outside namespace enclosing %2 "
+ "is a Microsoft extension">, InGroup<MicrosoftTemplate>;
+def err_template_spec_redecl_global_scope : Error<
+ "%select{class template|class template partial|variable template|"
+ "variable template partial|function template|member "
+ "function|static data member|member class|member enumeration}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">;
+def err_function_specialization_in_class : Error<
+ "cannot specialize a function %0 within class scope">;
+def ext_function_specialization_in_class : ExtWarn<
+ "explicit specialization of %0 within class scope is a Microsoft extension">,
+ InGroup<MicrosoftTemplate>;
+def ext_explicit_specialization_storage_class : ExtWarn<
+ "explicit specialization cannot have a storage class">;
+def err_explicit_specialization_inconsistent_storage_class : Error<
+ "explicit specialization has extraneous, inconsistent storage class "
+ "'%select{none|extern|static|__private_extern__|auto|register}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_alias_template_extra_headers : Error<
+ "extraneous template parameter list in alias template declaration">;
+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">;
+def err_specialize_member_of_template : Error<
+ "cannot specialize %select{|(with 'template<>') }0a member of an "
+ "unspecialized template">;
+
+// 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 note_dependent_non_type_default_arg_in_partial_spec : Note<
+ "template parameter is used in default argument declared here">;
+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<
+ "%select{class|variable}0 template partial specialization does not "
+ "specialize any template argument; to %select{declare|define}1 the "
+ "primary template, remove the template argument list">;
+def warn_partial_specs_not_deducible : Warning<
+ "%select{class|variable}0 template partial specialization contains "
+ "%select{a template parameter|template parameters}1 that cannot 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++ Variable Template Partial Specialization
+def err_var_partial_spec_redeclared : Error<
+ "variable template partial specialization %0 cannot be redefined">;
+def note_var_prev_partial_spec_here : Note<
+ "previous declaration of variable template partial specialization is here">;
+def err_var_spec_no_template : Error<
+ "no variable template matches%select{| partial}0 specialization">;
+def err_var_spec_no_template_but_method : Error<
+ "no variable template matches specialization; "
+ "did you mean to use %0 as function template instead?">;
+
+// 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_within_definition : Error<
+ "%select{implicit|explicit}0 instantiation of template %1 within its"
+ " own definition">;
+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_was_here : Note<
+ "class template %0 was instantiated here">;
+def note_template_class_explicit_specialization_was_here : Note<
+ "class template %0 was explicitly specialized here">;
+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_template_variable_def_here : Note<
+ "in instantiation of variable template specialization %q0 requested here">;
+def note_template_enum_def_here : Note<
+ "in instantiation of enumeration %q0 requested here">;
+def note_template_nsdmi_here : Note<
+ "in instantiation of default member initializer %q0 requested here">;
+def note_template_type_alias_instantiation_here : Note<
+ "in instantiation of template type alias %0 requested here">;
+def note_template_exception_spec_instantiation_here : Note<
+ "in instantiation of exception specification for %0 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 ext_explicit_instantiation_duplicate : ExtWarn<
+ "duplicate explicit instantiation of %0 ignored as a Microsoft extension">,
+ InGroup<MicrosoftTemplate>;
+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++11 extension)">,
+ InGroup<CXX11>;
+def warn_cxx98_compat_explicit_instantiation_after_specialization : Warning<
+ "explicit instantiation of %0 that occurs after an explicit "
+ "specialization is incompatible with C++98">,
+ InGroup<CXX98CompatPedantic>, DefaultIgnore;
+def note_previous_template_specialization : Note<
+ "previous template specialization is here">;
+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<CXX11Compat>, DefaultIgnore;
+def warn_explicit_instantiation_must_be_global_0x : Warning<
+ "explicit instantiation of %0 must occur at global scope">,
+ InGroup<CXX11Compat>, DefaultIgnore;
+
+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_storage_class : Error<
+ "explicit instantiation cannot have a storage class">;
+def err_explicit_instantiation_not_known : Error<
+ "explicit instantiation of %0 does not refer to a function template, "
+ "variable 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 warn_explicit_instantiation_inline_0x : Warning<
+ "explicit instantiation cannot be 'inline'">, InGroup<CXX11Compat>,
+ DefaultIgnore;
+def err_explicit_instantiation_constexpr : Error<
+ "explicit instantiation cannot be 'constexpr'">;
+def ext_explicit_instantiation_without_qualified_id : Extension<
+ "qualifier in explicit instantiation of %q0 requires a template-id "
+ "(a typedef is not permitted)">;
+def err_explicit_instantiation_without_template_id : Error<
+ "explicit instantiation of %q0 must specify a template argument list">;
+def err_explicit_instantiation_unqualified_wrong_namespace : Error<
+ "explicit instantiation of %q0 must occur in namespace %1">;
+def warn_explicit_instantiation_unqualified_wrong_namespace_0x : Warning<
+ "explicit instantiation of %q0 must occur in namespace %1">,
+ InGroup<CXX11Compat>, DefaultIgnore;
+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_undefined_var_template : Error<
+ "explicit instantiation of undefined variable template %q0">;
+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">;
+def err_invalid_var_template_spec_type : Error<"type %2 "
+ "of %select{explicit instantiation|explicit specialization|"
+ "partial specialization|redeclaration}0 of %1 does not match"
+ " expected type %3">;
+def err_mismatched_exception_spec_explicit_instantiation : Error<
+ "exception specification in explicit instantiation does not match "
+ "instantiated one">;
+def ext_mismatched_exception_spec_explicit_instantiation : ExtWarn<
+ err_mismatched_exception_spec_explicit_instantiation.Text>,
+ InGroup<MicrosoftExceptionSpec>;
+
+// C++ typename-specifiers
+def err_typename_nested_not_found : Error<"no type named %0 in %1">;
+def err_typename_nested_not_found_enable_if : Error<
+ "no type named 'type' in %0; 'enable_if' cannot be used to disable "
+ "this declaration">;
+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_missing : ExtWarn<
+ "missing 'typename' prior to dependent type name '%0%1'">,
+ InGroup<DiagGroup<"typename-missing">>;
+def ext_typename_outside_of_template : ExtWarn<
+ "'typename' occurs outside of a template">, InGroup<CXX11>;
+def warn_cxx98_compat_typename_outside_of_template : Warning<
+ "use of 'typename' outside of a template is incompatible with C++98">,
+ InGroup<CXX98Compat>, DefaultIgnore;
+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_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<CXX11>;
+def warn_cxx98_compat_template_outside_of_template : Warning<
+ "use of 'template' keyword outside of a template is incompatible with C++98">,
+ InGroup<CXX98Compat>, DefaultIgnore;
+
+def err_non_type_template_in_nested_name_specifier : Error<
+ "qualified name refers into a specialization of %select{function|variable}0 "
+ "template %1">;
+def err_template_id_not_a_type : Error<
+ "template name refers to non-type template %0">;
+def note_template_declared_here : Note<
+ "%select{function template|class template|variable template"
+ "|type alias template|template template parameter}0 "
+ "%1 declared here">;
+def err_alias_template_expansion_into_fixed_list : Error<
+ "pack expansion used as argument for non-pack parameter of alias template">;
+def note_parameter_type : Note<
+ "parameter of type %0 is declared here">;
+
+// C++11 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 : 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|"
+ "__if_exists name|__if_not_exists name|lambda|block}0 contains"
+ "%plural{0: an|:}1 unexpanded parameter pack"
+ "%plural{0:|1: %2|2:s %2 and %3|:s %2, %3, ...}1">;
+
+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_fold_expression_packs_both_sides : Error<
+ "binary fold expression has unexpanded parameter packs in both operands">;
+def err_fold_expression_empty : Error<
+ "unary fold expression has empty expansion for operator '%0' "
+ "with no fallback value">;
+def err_fold_expression_bad_operand : Error<
+ "expression not permitted as operand of fold expression">;
+
+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 ext_undeclared_unqual_id_with_dependent_base : ExtWarn<
+ "use of undeclared identifier %0; "
+ "unqualified lookup into dependent bases of class template %1 is a Microsoft extension">,
+ InGroup<MicrosoftTemplate>;
+def ext_found_via_dependent_bases_lookup : ExtWarn<"use of identifier %0 "
+ "found via unqualified lookup into dependent bases of class templates is a "
+ "Microsoft extension">, InGroup<MicrosoftTemplate>;
+def note_dependent_var_use : Note<"must qualify identifier to find this "
+ "declaration in dependent base class">;
+def err_not_found_by_two_phase_lookup : Error<"call to function %0 that is neither "
+ "visible in the template definition nor found by argument-dependent lookup">;
+def note_not_found_by_two_phase_lookup : Note<"%0 should be declared prior to the "
+ "call site%select{| or in %2| or in an associated namespace of one of its arguments}1">;
+def err_undeclared_use : Error<"use of undeclared %0">;
+def warn_partial_availability : Warning<"%0 is only available conditionally">,
+ InGroup<PartialAvailability>, DefaultIgnore;
+def note_partial_availability_silence : Note<
+ "explicitly redeclare %0 to silence this warning">;
+def warn_partial_message : Warning<"%0 is partial: %1">,
+ InGroup<PartialAvailability>, DefaultIgnore;
+def warn_partial_fwdclass_message : Warning<
+ "%0 may be partial because the receiver type is unknown">,
+ InGroup<PartialAvailability>, DefaultIgnore;
+def warn_deprecated : Warning<"%0 is deprecated">,
+ InGroup<DeprecatedDeclarations>;
+def warn_property_method_deprecated :
+ Warning<"property access is using %0 method which is deprecated">,
+ InGroup<DeprecatedDeclarations>;
+def warn_deprecated_message : Warning<"%0 is deprecated: %1">,
+ InGroup<DeprecatedDeclarations>;
+def warn_deprecated_anonymous_namespace : Warning<
+ "'deprecated' attribute on anonymous namespace ignored">,
+ InGroup<IgnoredAttributes>;
+def warn_deprecated_fwdclass_message : Warning<
+ "%0 may be deprecated because the 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_property_method_unavailable :
+ Error<"property access is using %0 method which is unavailable">;
+def err_unavailable_message : Error<"%0 is unavailable: %1">;
+def warn_unavailable_fwdclass_message : Warning<
+ "%0 may be unavailable because the receiver type is unknown">,
+ InGroup<UnavailableDeclarations>;
+def note_availability_specified_here : Note<
+ "%0 has been explicitly marked "
+ "%select{unavailable|deleted|deprecated|partial}1 here">;
+def note_implicitly_deleted : Note<
+ "explicitly defaulted function was implicitly deleted here">;
+def note_inherited_deleted_here : Note<
+ "deleted constructor was inherited here">;
+def note_cannot_inherit : Note<
+ "constructor cannot be inherited">;
+def warn_not_enough_argument : Warning<
+ "not enough variable arguments in %0 declaration to fit a sentinel">,
+ InGroup<Sentinel>;
+def warn_missing_sentinel : Warning <
+ "missing sentinel in %select{function call|method dispatch|block call}0">,
+ InGroup<Sentinel>;
+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 note_declaration_not_a_prototype : Note<
+ "this declaration is not a prototype; add 'void' to make it a prototype for a zero-parameter function">;
+def warn_missing_variable_declarations : Warning<
+ "no previous extern declaration for non-static variable %0">,
+ InGroup<DiagGroup<"missing-variable-declarations">>, DefaultIgnore;
+def err_static_data_member_reinitialization :
+ Error<"static data member %0 already has an initializer">;
+def err_redefinition : Error<"redefinition of %0">;
+def err_alias_after_tentative :
+ Error<"alias definition of %0 after tentative definition">;
+def err_alias_is_definition :
+ Error<"definition %0 cannot also be an alias">;
+def err_definition_of_implicitly_declared_member : Error<
+ "definition of implicitly declared %select{default constructor|copy "
+ "constructor|move constructor|copy assignment operator|move assignment "
+ "operator|destructor|function}1">;
+def err_definition_of_explicitly_defaulted_member : Error<
+ "definition of explicitly defaulted %select{default constructor|copy "
+ "constructor|move constructor|copy assignment operator|move assignment "
+ "operator|destructor}0">;
+def err_redefinition_extern_inline : Error<
+ "redefinition of a 'extern inline' function %0 is not supported in "
+ "%select{C99 mode|C++}1">;
+
+def note_deleted_dtor_no_operator_delete : Note<
+ "virtual destructor requires an unambiguous, accessible 'operator delete'">;
+def note_deleted_special_member_class_subobject : Note<
+ "%select{default constructor|copy constructor|move constructor|"
+ "copy assignment operator|move assignment operator|destructor}0 of "
+ "%1 is implicitly deleted because "
+ "%select{base class %3|%select{||||variant }4field %3}2 has "
+ "%select{no|a deleted|multiple|an inaccessible|a non-trivial}4 "
+ "%select{%select{default constructor|copy constructor|move constructor|copy "
+ "assignment operator|move assignment operator|destructor}0|destructor}5"
+ "%select{||s||}4">;
+def note_deleted_default_ctor_uninit_field : Note<
+ "default constructor of %0 is implicitly deleted because field %1 of "
+ "%select{reference|const-qualified}3 type %2 would not be initialized">;
+def note_deleted_default_ctor_all_const : Note<
+ "default constructor of %0 is implicitly deleted because all "
+ "%select{data members|data members of an anonymous union member}1"
+ " are const-qualified">;
+def note_deleted_copy_ctor_rvalue_reference : Note<
+ "copy constructor of %0 is implicitly deleted because field %1 is of "
+ "rvalue reference type %2">;
+def note_deleted_copy_user_declared_move : Note<
+ "copy %select{constructor|assignment operator}0 is implicitly deleted because"
+ " %1 has a user-declared move %select{constructor|assignment operator}2">;
+def note_deleted_assign_field : Note<
+ "%select{copy|move}0 assignment operator of %1 is implicitly deleted "
+ "because field %2 is of %select{reference|const-qualified}4 type %3">;
+
+// These should be errors.
+def warn_undefined_internal : Warning<
+ "%select{function|variable}0 %q1 has internal linkage but is not defined">,
+ InGroup<DiagGroup<"undefined-internal">>;
+def warn_undefined_inline : Warning<"inline function %q0 is not defined">,
+ InGroup<DiagGroup<"undefined-inline">>;
+def note_used_here : Note<"used here">;
+
+def err_internal_linkage_redeclaration : Error<
+ "'internal_linkage' attribute does not appear on the first declaration of %0">;
+def warn_internal_linkage_local_storage : Warning<
+ "'internal_linkage' attribute on a non-static local variable is ignored">,
+ InGroup<IgnoredAttributes>;
+
+def ext_internal_in_extern_inline : ExtWarn<
+ "static %select{function|variable}0 %1 is used in an inline function with "
+ "external linkage">, InGroup<StaticInInline>;
+def ext_internal_in_extern_inline_quiet : Extension<
+ "static %select{function|variable}0 %1 is used in an inline function with "
+ "external linkage">, InGroup<StaticInInline>;
+def warn_static_local_in_extern_inline : Warning<
+ "non-constant static local variable in inline function may be different "
+ "in different files">, InGroup<StaticLocalInInline>;
+def note_convert_inline_to_static : Note<
+ "use 'static' to give inline function %0 internal linkage">;
+
+def ext_redefinition_of_typedef : ExtWarn<
+ "redefinition of typedef %0 is a C11 feature">,
+ InGroup<DiagGroup<"typedef-redefinition"> >;
+def err_redefinition_variably_modified_typedef : Error<
+ "redefinition of %select{typedef|type alias}0 for variably-modified type %1">;
+
+def err_inline_decl_follows_def : Error<
+ "inline declaration of %0 follows non-inline definition">;
+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_different_language_linkage : Error<
+ "declaration of %0 has a different language linkage">;
+def ext_retained_language_linkage : Extension<
+ "friend function %0 retaining previous language linkage is an extension">,
+ InGroup<DiagGroup<"retained-language-linkage">>;
+def err_extern_c_global_conflict : Error<
+ "declaration of %1 %select{with C language linkage|in global scope}0 "
+ "conflicts with declaration %select{in global scope|with C language linkage}0">;
+def note_extern_c_global_conflict : Note<
+ "declared %select{in global scope|with C language linkage}0 here">;
+def warn_weak_import : Warning <
+ "an already-declared variable is made a weak_import declaration %0">;
+def ext_static_non_static : Extension<
+ "redeclaring non-static %0 as static is a Microsoft extension">,
+ InGroup<MicrosoftRedeclareStatic>;
+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_thread_thread_different_kind : Error<
+ "thread-local declaration of %0 with %select{static|dynamic}1 initialization "
+ "follows declaration with %select{dynamic|static}1 initialization">;
+def err_redefinition_different_type : Error<
+ "redefinition of %0 with a different type%diff{: $ vs $|}1,2">;
+def err_redefinition_different_kind : Error<
+ "redefinition of %0 as different kind of symbol">;
+def err_redefinition_different_namespace_alias : Error<
+ "redefinition of %0 as an alias for a different namespace">;
+def note_previous_namespace_alias : Note<
+ "previously defined as an alias for %0">;
+def warn_forward_class_redefinition : Warning<
+ "redefinition of forward class %0 of a typedef name of an object type is ignored">,
+ InGroup<DiagGroup<"objc-forward-class-redefinition">>;
+def err_redefinition_different_typedef : Error<
+ "%select{typedef|type alias|type alias template}0 "
+ "redefinition with different types%diff{ ($ vs $)|}1,2">;
+def err_tag_reference_non_tag : Error<
+ "elaborated type refers to %select{a non-tag type|a typedef|a type alias|a template|a type alias template}0">;
+def err_tag_reference_conflict : Error<
+ "implicit declaration introduced by elaborated type conflicts with "
+ "%select{a declaration|a typedef|a type alias|a template}0 of the same name">;
+def err_dependent_tag_decl : Error<
+ "%select{declaration|definition}0 of "
+ "%select{struct|interface|union|class|enum}1 in a dependent scope">;
+def err_tag_definition_of_typedef : Error<
+ "definition of type %0 conflicts with %select{typedef|type alias}1 of the same name">;
+def err_conflicting_types : Error<"conflicting types for %0">;
+def err_different_pass_object_size_params : Error<
+ "conflicting pass_object_size attributes on parameters">;
+def err_late_asm_label_name : Error<
+ "cannot apply asm label to %select{variable|function}0 after its first use">;
+def err_different_asm_label : Error<"conflicting asm label">;
+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|interface|class}0%select{| template}1 %2 was previously "
+ "declared as a %select{struct|interface|class}3%select{| template}1">,
+ InGroup<MismatchedTags>, DefaultIgnore;
+def warn_struct_class_previous_tag_mismatch : Warning<
+ "%2 defined as %select{a struct|an interface|a class}0%select{| template}1 "
+ "here but previously declared as "
+ "%select{a struct|an interface|a class}3%select{| template}1">,
+ InGroup<MismatchedTags>, DefaultIgnore;
+def note_struct_class_suggestion : Note<
+ "did you mean %select{struct|interface|class}0 here?">;
+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<MicrosoftEnumForwardReference>;
+def ext_forward_ref_enum_def : Extension<
+ "redeclaration of already-defined enum %0 is a GNU extension">,
+ InGroup<GNURedeclaredEnum>;
+
+def err_redefinition_of_enumerator : Error<"redefinition of enumerator %0">;
+def err_duplicate_member : Error<"duplicate member %0">;
+def err_misplaced_ivar : Error<
+ "instance variables may not be placed in %select{categories|class extension}0">;
+def warn_ivars_in_interface : Warning<
+ "declaration of instance variables in the interface is deprecated">,
+ InGroup<DiagGroup<"objc-interface-ivars">>, DefaultIgnore;
+def ext_enum_value_not_int : Extension<
+ "ISO C restricts enumerator values to range of 'int' (%0 is too "
+ "%select{small|large}1)">;
+def ext_enum_too_large : ExtWarn<
+ "enumeration values exceed range of largest integer">, InGroup<EnumTooLarge>;
+def ext_enumerator_increment_too_large : ExtWarn<
+ "incremented enumerator value %0 is not representable in the "
+ "largest integer type">, InGroup<EnumTooLarge>;
+def warn_flag_enum_constant_out_of_range : Warning<
+ "enumeration value %0 is out of range of flags in enumeration type %1">,
+ InGroup<FlagEnum>;
+
+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 cannot 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)">;
+def warn_array_new_too_large : Warning<"array is too large (%0 elements)">,
+ // FIXME PR11644: ", will throw std::bad_array_new_length at runtime"
+ InGroup<BadArrayNewLength>;
+
+// -Wpadded, -Wpacked
+def warn_padded_struct_field : Warning<
+ "padding %select{struct|interface|class}0 %1 with %2 "
+ "%select{byte|bit}3%s2 to align %4">,
+ InGroup<Padded>, DefaultIgnore;
+def warn_padded_struct_anon_field : Warning<
+ "padding %select{struct|interface|class}0 %1 with %2 "
+ "%select{byte|bit}3%s2 to align anonymous bit-field">,
+ InGroup<Padded>, DefaultIgnore;
+def warn_padded_struct_size : Warning<
+ "padding size of %0 with %1 %select{byte|bit}2%s1 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_negative_array_new_size : Warning<"array size is negative">,
+ // FIXME PR11644: ", will throw std::bad_array_new_length at runtime"
+ InGroup<BadArrayNewLength>;
+def warn_typecheck_function_qualifiers_ignored : Warning<
+ "'%0' qualifier on function type %1 has no effect">,
+ InGroup<IgnoredQualifiers>;
+def warn_typecheck_function_qualifiers_unspecified : Warning<
+ "'%0' qualifier on function type %1 has unspecified behavior">;
+def warn_typecheck_reference_qualifiers : Warning<
+ "'%0' qualifier on reference type %1 has no effect">,
+ InGroup<IgnoredQualifiers>;
+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">, InGroup<ZeroLengthArray>;
+def err_typecheck_zero_array_size : Error<
+ "zero-length arrays are not permitted in C++">;
+def warn_typecheck_zero_static_array_size : Warning<
+ "'static' has no effect on zero-length arrays">,
+ InGroup<ArrayBounds>;
+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 ext_aggregate_init_not_constant : Extension<
+ "initializer for aggregate is not a compile-time constant">, InGroup<C99>;
+def err_local_cant_init : Error<
+ "'__local' variable cannot have an initializer">;
+def err_block_extern_cant_init : Error<
+ "'extern' variable cannot have an initializer">;
+def warn_extern_init : Warning<"'extern' variable has an initializer">,
+ InGroup<DiagGroup<"extern-initializer">>;
+def err_variable_object_no_init : Error<
+ "variable-sized object may not be initialized">;
+def err_excess_initializers : Error<
+ "excess elements in %select{array|vector|scalar|union|struct}0 initializer">;
+def ext_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 ext_excess_initializers_in_char_array_initializer : ExtWarn<
+ "excess elements in char array initializer">;
+def err_initializer_string_for_char_array_too_long : Error<
+ "initializer-string for char array is too long">;
+def ext_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">, InGroup<DiagGroup<"braced-scalar-init">>;
+def ext_many_braces_around_scalar_init : ExtWarn<
+ "too many braces around scalar initializer">,
+ InGroup<DiagGroup<"many-braces-around-scalar-init">>;
+def ext_complex_component_init : Extension<
+ "complex initialization specifying real and imaginary components "
+ "is an extension">, InGroup<DiagGroup<"complex-component-init">>;
+def err_empty_scalar_initializer : Error<"scalar initializer cannot be empty">;
+def warn_cxx98_compat_empty_scalar_initializer : Warning<
+ "scalar initialized from empty initializer list is incompatible with C++98">,
+ InGroup<CXX98Compat>, DefaultIgnore;
+def warn_cxx98_compat_reference_list_init : Warning<
+ "reference initialized from initializer list is incompatible with C++98">,
+ InGroup<CXX98Compat>, DefaultIgnore;
+def warn_cxx98_compat_initializer_list_init : Warning<
+ "initialization of initializer_list object is incompatible with C++98">,
+ InGroup<CXX98Compat>, DefaultIgnore;
+def warn_cxx98_compat_ctor_list_init : Warning<
+ "constructor call from initializer list is incompatible with C++98">,
+ InGroup<CXX98Compat>, DefaultIgnore;
+def err_illegal_initializer : Error<
+ "illegal initializer (only variables can be initialized)">;
+def err_illegal_initializer_type : Error<"illegal initializer type %0">;
+def ext_init_list_type_narrowing : ExtWarn<
+ "type %0 cannot be narrowed to %1 in initializer list">,
+ InGroup<CXX11Narrowing>, DefaultError, SFINAEFailure;
+def ext_init_list_variable_narrowing : ExtWarn<
+ "non-constant-expression cannot be narrowed from type %0 to %1 in "
+ "initializer list">, InGroup<CXX11Narrowing>, DefaultError, SFINAEFailure;
+def ext_init_list_constant_narrowing : ExtWarn<
+ "constant expression evaluates to %0 which cannot be narrowed to type %1">,
+ InGroup<CXX11Narrowing>, DefaultError, SFINAEFailure;
+def warn_init_list_type_narrowing : Warning<
+ "type %0 cannot be narrowed to %1 in initializer list in C++11">,
+ InGroup<CXX11Narrowing>, DefaultIgnore;
+def warn_init_list_variable_narrowing : Warning<
+ "non-constant-expression cannot be narrowed from type %0 to %1 in "
+ "initializer list in C++11">,
+ InGroup<CXX11Narrowing>, DefaultIgnore;
+def warn_init_list_constant_narrowing : Warning<
+ "constant expression evaluates to %0 which cannot be narrowed to type %1 in "
+ "C++11">,
+ InGroup<CXX11Narrowing>, DefaultIgnore;
+def note_init_list_narrowing_silence : Note<
+ "insert an explicit cast to silence this issue">;
+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_width : Error<
+ "width of bit-field %0 (%1 bits) exceeds %select{width|size}2 "
+ "of its type (%3 bit%s3)">;
+def err_anon_bitfield_width_exceeds_type_width : Error<
+ "width of anonymous bit-field (%0 bits) exceeds %select{width|size}1 "
+ "of its type (%2 bit%s2)">;
+def err_incorrect_number_of_vector_initializers : Error<
+ "number of elements must be either one or match the size of the vector">;
+
+// Used by C++ which allows bit-fields that are wider than the type.
+def warn_bitfield_width_exceeds_type_width: Warning<
+ "width of bit-field %0 (%1 bits) exceeds the width of its type; value will "
+ "be truncated to %2 bit%s2">, InGroup<BitFieldWidth>;
+def warn_anon_bitfield_width_exceeds_type_width : Warning<
+ "width of anonymous bit-field (%0 bits) exceeds width of its type; value "
+ "will be truncated to %1 bit%s1">, InGroup<BitFieldWidth>;
+
+def warn_missing_braces : Warning<
+ "suggest braces around initialization of subobject">,
+ InGroup<MissingBraces>, DefaultIgnore;
+
+def err_redefinition_of_label : Error<"redefinition of label %0">;
+def err_undeclared_label_use : Error<"use of undeclared label %0">;
+def err_goto_ms_asm_label : Error<
+ "cannot jump from this goto statement to label %0 inside an inline assembly block">;
+def note_goto_ms_asm_label : Note<
+ "inline assembly label %0 declared here">;
+def warn_unused_label : Warning<"unused label %0">,
+ InGroup<UnusedLabel>, DefaultIgnore;
+
+def err_goto_into_protected_scope : Error<
+ "cannot jump from this goto statement to its label">;
+def ext_goto_into_protected_scope : ExtWarn<
+ "jump from this goto statement to its label is a Microsoft extension">,
+ InGroup<MicrosoftGoto>;
+def warn_cxx98_compat_goto_into_protected_scope : Warning<
+ "jump from this goto statement to its label is incompatible with C++98">,
+ InGroup<CXX98Compat>, DefaultIgnore;
+def err_switch_into_protected_scope : Error<
+ "cannot jump from switch statement to this case label">;
+def warn_cxx98_compat_switch_into_protected_scope : Warning<
+ "jump from switch statement to this case label is incompatible with C++98">,
+ InGroup<CXX98Compat>, DefaultIgnore;
+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<
+ "cannot jump from this indirect goto statement to one of its possible targets">;
+def warn_cxx98_compat_indirect_goto_in_protected_scope : Warning<
+ "jump from this indirect goto statement to one of its possible targets "
+ "is incompatible with C++98">, InGroup<CXX98Compat>, DefaultIgnore;
+def note_indirect_goto_target : Note<
+ "possible target of indirect goto statement">;
+def note_protected_by_variable_init : Note<
+ "jump bypasses variable initialization">;
+def note_protected_by_variable_nontriv_destructor : Note<
+ "jump bypasses variable with a non-trivial destructor">;
+def note_protected_by_variable_non_pod : Note<
+ "jump bypasses initialization of non-POD variable">;
+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_type_alias : Note<
+ "jump bypasses initialization of VLA type alias">;
+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_objc_autoreleasepool : Note<
+ "jump bypasses auto release push of @autoreleasepool 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_seh_try : Note<
+ "jump bypasses initialization of __try block">;
+def note_protected_by_seh_except : Note<
+ "jump bypasses initialization of __except block">;
+def note_protected_by_seh_finally : Note<
+ "jump bypasses initialization of __finally block">;
+def note_protected_by___block : Note<
+ "jump bypasses setup of __block variable">;
+def note_protected_by_objc_strong_init : Note<
+ "jump bypasses initialization of __strong variable">;
+def note_protected_by_objc_weak_init : Note<
+ "jump bypasses initialization of __weak variable">;
+def note_enters_block_captures_cxx_obj : Note<
+ "jump enters lifetime of block which captures a destructible C++ object">;
+def note_enters_block_captures_strong : Note<
+ "jump enters lifetime of block which strongly captures a variable">;
+def note_enters_block_captures_weak : Note<
+ "jump enters lifetime of block which weakly captures a 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_temporary_dtor : Note<
+ "jump exits scope of lifetime-extended temporary 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 note_exits_seh_try : Note<
+ "jump exits __try block">;
+def note_exits_seh_except : Note<
+ "jump exits __except block">;
+def note_exits_seh_finally : Note<
+ "jump exits __finally block">;
+def note_exits_objc_autoreleasepool : Note<
+ "jump exits autoreleasepool block">;
+def note_exits_objc_strong : Note<
+ "jump exits scope of __strong variable">;
+def note_exits_objc_weak : Note<
+ "jump exits scope of __weak variable">;
+def note_exits_block_captures_cxx_obj : Note<
+ "jump exits lifetime of block which captures a destructible C++ object">;
+def note_exits_block_captures_strong : Note<
+ "jump exits lifetime of block which strongly captures a variable">;
+def note_exits_block_captures_weak : Note<
+ "jump exits lifetime of block which weakly captures a variable">;
+
+def err_func_returning_qualified_void : ExtWarn<
+ "function cannot return qualified void type %0">,
+ InGroup<DiagGroup<"qualified-void-return-type">>;
+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<GNUVariableSizedTypeNotAtEnd>;
+
+def ext_c99_flexible_array_member : Extension<
+ "flexible array members are a C99 feature">, InGroup<C99>;
+def err_flexible_array_virtual_base : Error<
+ "flexible array member %0 not allowed in "
+ "%select{struct|interface|union|class|enum}1 which has a virtual base class">;
+def err_flexible_array_empty_aggregate : Error<
+ "flexible array member %0 not allowed in otherwise empty "
+ "%select{struct|interface|union|class|enum}1">;
+def err_flexible_array_has_nontrivial_dtor : Error<
+ "flexible array member %0 of type %1 with non-trivial destruction">;
+def ext_flexible_array_in_struct : Extension<
+ "%0 may not be nested in a struct due to flexible array member">,
+ InGroup<FlexibleArrayExtensions>;
+def ext_flexible_array_in_array : Extension<
+ "%0 may not be used as an array element due to flexible array member">,
+ InGroup<FlexibleArrayExtensions>;
+def err_flexible_array_init : Error<
+ "initialization of flexible array member is not allowed">;
+def ext_flexible_array_empty_aggregate_ms : Extension<
+ "flexible array member %0 in otherwise empty "
+ "%select{struct|interface|union|class|enum}1 is a Microsoft extension">,
+ InGroup<MicrosoftFlexibleArray>;
+def err_flexible_array_union : Error<
+ "flexible array member %0 in a union is not allowed">;
+def ext_flexible_array_union_ms : Extension<
+ "flexible array member %0 in a union is a Microsoft extension">,
+ InGroup<MicrosoftFlexibleArray>;
+def ext_flexible_array_empty_aggregate_gnu : Extension<
+ "flexible array member %0 in otherwise empty "
+ "%select{struct|interface|union|class|enum}1 is a GNU extension">,
+ InGroup<GNUEmptyStruct>;
+def ext_flexible_array_union_gnu : Extension<
+ "flexible array member %0 in a union is a GNU extension">, InGroup<GNUFlexibleArrayUnionMember>;
+
+let CategoryName = "ARC Semantic Issue" in {
+
+// ARC-mode diagnostics.
+
+let CategoryName = "ARC Weak References" in {
+
+def err_arc_weak_no_runtime : Error<
+ "cannot create __weak reference because the current deployment target "
+ "does not support weak references">;
+def err_arc_weak_disabled : Error<
+ "cannot create __weak reference in file using manual reference counting">;
+def err_synthesizing_arc_weak_property_disabled : Error<
+ "cannot synthesize weak property in file using manual reference counting">;
+def err_synthesizing_arc_weak_property_no_runtime : Error<
+ "cannot synthesize weak property because the current deployment target "
+ "does not support weak references">;
+def err_arc_unsupported_weak_class : Error<
+ "class is incompatible with __weak references">;
+def err_arc_weak_unavailable_assign : Error<
+ "assignment of a weak-unavailable object to a __weak object">;
+def err_arc_weak_unavailable_property : Error<
+ "synthesizing __weak instance variable of type %0, which does not "
+ "support weak references">;
+def note_implemented_by_class : Note<
+ "when implemented by class %0">;
+def err_arc_convesion_of_weak_unavailable : Error<
+ "%select{implicit conversion|cast}0 of weak-unavailable object of type %1 to"
+ " a __weak object of type %2">;
+
+} // end "ARC Weak References" category
+
+let CategoryName = "ARC Restrictions" in {
+
+def err_unavailable_in_arc : Error<
+ "%0 is unavailable in ARC">;
+def note_arc_forbidden_type : Note<
+ "declaration uses type that is ill-formed in ARC">;
+def note_performs_forbidden_arc_conversion : Note<
+ "inline function performs a conversion which is forbidden in ARC">;
+def note_arc_init_returns_unrelated : Note<
+ "init method must return a type related to its receiver type">;
+def note_arc_weak_disabled : Note<
+ "declaration uses __weak, but ARC is disabled">;
+def note_arc_weak_no_runtime : Note<"declaration uses __weak, which "
+ "the current deployment target does not support">;
+def note_arc_field_with_ownership : Note<
+ "field has non-trivial ownership qualification">;
+
+def err_arc_illegal_explicit_message : Error<
+ "ARC forbids explicit message send of %0">;
+def err_arc_unused_init_message : Error<
+ "the result of a delegate init call must be immediately returned "
+ "or assigned to 'self'">;
+def err_arc_mismatched_cast : Error<
+ "%select{implicit conversion|cast}0 of "
+ "%select{%2|a non-Objective-C pointer type %2|a block pointer|"
+ "an Objective-C pointer|an indirect pointer to an Objective-C pointer}1"
+ " to %3 is disallowed with ARC">;
+def err_arc_nolifetime_behavior : Error<
+ "explicit ownership qualifier on cast result has no effect">;
+def err_arc_objc_object_in_tag : Error<
+ "ARC forbids %select{Objective-C objects|blocks}0 in "
+ "%select{struct|interface|union|<<ERROR>>|enum}1">;
+def err_arc_objc_property_default_assign_on_object : Error<
+ "ARC forbids synthesizing a property of an Objective-C object "
+ "with unspecified ownership or storage attribute">;
+def err_arc_illegal_selector : Error<
+ "ARC forbids use of %0 in a @selector">;
+def err_arc_illegal_method_def : Error<
+ "ARC forbids %select{implementation|synthesis}0 of %1">;
+def warn_arc_strong_pointer_objc_pointer : Warning<
+ "method parameter of type %0 with no explicit ownership">,
+ InGroup<DiagGroup<"explicit-ownership-type">>, DefaultIgnore;
+
+} // end "ARC Restrictions" category
+
+def err_arc_lost_method_convention : Error<
+ "method was declared as %select{an 'alloc'|a 'copy'|an 'init'|a 'new'}0 "
+ "method, but its implementation doesn't match because %select{"
+ "its result type is not an object pointer|"
+ "its result type is unrelated to its receiver type}1">;
+def note_arc_lost_method_convention : Note<"declaration in interface">;
+def err_arc_gained_method_convention : Error<
+ "method implementation does not match its declaration">;
+def note_arc_gained_method_convention : Note<
+ "declaration in interface is not in the '%select{alloc|copy|init|new}0' "
+ "family because %select{its result type is not an object pointer|"
+ "its result type is unrelated to its receiver type}1">;
+def err_typecheck_arc_assign_self : Error<
+ "cannot assign to 'self' outside of a method in the init family">;
+def err_typecheck_arc_assign_self_class_method : Error<
+ "cannot assign to 'self' in a class method">;
+def err_typecheck_arr_assign_enumeration : Error<
+ "fast enumeration variables cannot be modified in ARC by default; "
+ "declare the variable __strong to allow this">;
+def warn_arc_retained_assign : Warning<
+ "assigning retained object to %select{weak|unsafe_unretained}0 "
+ "%select{property|variable}1"
+ "; object will be released after assignment">,
+ InGroup<ARCUnsafeRetainedAssign>;
+def warn_arc_retained_property_assign : Warning<
+ "assigning retained object to unsafe property"
+ "; object will be released after assignment">,
+ InGroup<ARCUnsafeRetainedAssign>;
+def warn_arc_literal_assign : Warning<
+ "assigning %select{array literal|dictionary literal|numeric literal|boxed expression|<should not happen>|block literal}0"
+ " to a weak %select{property|variable}1"
+ "; object will be released after assignment">,
+ InGroup<ARCUnsafeRetainedAssign>;
+def err_arc_new_array_without_ownership : Error<
+ "'new' cannot allocate an array of %0 with no explicit ownership">;
+def err_arc_autoreleasing_var : Error<
+ "%select{__block variables|global variables|fields|instance variables}0 cannot have "
+ "__autoreleasing ownership">;
+def err_arc_autoreleasing_capture : Error<
+ "cannot capture __autoreleasing variable in a "
+ "%select{block|lambda by copy}0">;
+def err_arc_thread_ownership : Error<
+ "thread-local variable has non-trivial ownership: type is %0">;
+def err_arc_indirect_no_ownership : Error<
+ "%select{pointer|reference}1 to non-const type %0 with no explicit ownership">;
+def err_arc_array_param_no_ownership : Error<
+ "must explicitly describe intended ownership of an object array parameter">;
+def err_arc_pseudo_dtor_inconstant_quals : Error<
+ "pseudo-destructor destroys object of type %0 with inconsistently-qualified "
+ "type %1">;
+def err_arc_init_method_unrelated_result_type : Error<
+ "init methods must return a type related to the receiver type">;
+def err_arc_nonlocal_writeback : Error<
+ "passing address of %select{non-local|non-scalar}0 object to "
+ "__autoreleasing parameter for write-back">;
+def err_arc_method_not_found : Error<
+ "no known %select{instance|class}1 method for selector %0">;
+def err_arc_receiver_forward_class : Error<
+ "receiver %0 for class message is a forward declaration">;
+def err_arc_may_not_respond : Error<
+ "no visible @interface for %0 declares the selector %1">;
+def err_arc_receiver_forward_instance : Error<
+ "receiver type %0 for instance message is a forward declaration">;
+def warn_receiver_forward_instance : Warning<
+ "receiver type %0 for instance message is a forward declaration">,
+ InGroup<ForwardClassReceiver>, DefaultIgnore;
+def err_arc_collection_forward : Error<
+ "collection expression type %0 is a forward declaration">;
+def err_arc_multiple_method_decl : Error<
+ "multiple methods named %0 found with mismatched result, "
+ "parameter type or attributes">;
+def warn_arc_lifetime_result_type : Warning<
+ "ARC %select{unused|__unsafe_unretained|__strong|__weak|__autoreleasing}0 "
+ "lifetime qualifier on return type is ignored">,
+ InGroup<IgnoredQualifiers>;
+
+let CategoryName = "ARC Retain Cycle" in {
+
+def warn_arc_retain_cycle : Warning<
+ "capturing %0 strongly in this block is likely to lead to a retain cycle">,
+ InGroup<ARCRetainCycles>;
+def note_arc_retain_cycle_owner : Note<
+ "block will be retained by %select{the captured object|an object strongly "
+ "retained by the captured object}0">;
+
+} // end "ARC Retain Cycle" category
+
+def warn_arc_object_memaccess : Warning<
+ "%select{destination for|source of}0 this %1 call is a pointer to "
+ "ownership-qualified type %2">, InGroup<ARCNonPodMemAccess>;
+
+let CategoryName = "ARC and @properties" in {
+
+def err_arc_strong_property_ownership : Error<
+ "existing instance variable %1 for strong property %0 may not be "
+ "%select{|__unsafe_unretained||__weak}2">;
+def err_arc_assign_property_ownership : Error<
+ "existing instance variable %1 for property %0 with %select{unsafe_unretained|assign}2 "
+ "attribute must be __unsafe_unretained">;
+def err_arc_inconsistent_property_ownership : Error<
+ "%select{|unsafe_unretained|strong|weak}1 property %0 may not also be "
+ "declared %select{|__unsafe_unretained|__strong|__weak|__autoreleasing}2">;
+
+} // end "ARC and @properties" category
+
+def err_arc_atomic_ownership : Error<
+ "cannot perform atomic operation on a pointer to type %0: type has "
+ "non-trivial ownership">;
+
+let CategoryName = "ARC Casting Rules" in {
+
+def err_arc_bridge_cast_incompatible : Error<
+ "incompatible types casting %0 to %1 with a %select{__bridge|"
+ "__bridge_transfer|__bridge_retained}2 cast">;
+def err_arc_bridge_cast_wrong_kind : Error<
+ "cast of %select{Objective-C|block|C}0 pointer type %1 to "
+ "%select{Objective-C|block|C}2 pointer type %3 cannot use %select{__bridge|"
+ "__bridge_transfer|__bridge_retained}4">;
+def err_arc_cast_requires_bridge : Error<
+ "%select{cast|implicit conversion}0 of %select{Objective-C|block|C}1 "
+ "pointer type %2 to %select{Objective-C|block|C}3 pointer type %4 "
+ "requires a bridged cast">;
+def note_arc_bridge : Note<
+ "use __bridge to convert directly (no change in ownership)">;
+def note_arc_cstyle_bridge : Note<
+ "use __bridge with C-style cast to convert directly (no change in ownership)">;
+def note_arc_bridge_transfer : Note<
+ "use %select{__bridge_transfer|CFBridgingRelease call}1 to transfer "
+ "ownership of a +1 %0 into ARC">;
+def note_arc_cstyle_bridge_transfer : Note<
+ "use __bridge_transfer with C-style cast to transfer "
+ "ownership of a +1 %0 into ARC">;
+def note_arc_bridge_retained : Note<
+ "use %select{__bridge_retained|CFBridgingRetain call}1 to make an "
+ "ARC object available as a +1 %0">;
+def note_arc_cstyle_bridge_retained : Note<
+ "use __bridge_retained with C-style cast to make an "
+ "ARC object available as a +1 %0">;
+
+} // ARC Casting category
+
+} // ARC category name
+
+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_static_outside_prototype : Error<
+ "%0 used in array declarator outside of function prototype">;
+def err_array_static_not_outermost : Error<
+ "%0 used in non-outermost array type derivation">;
+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_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_func_def_incomplete_result : Error<
+ "incomplete result type %0 in function definition">;
+def err_atomic_specifier_bad_type : Error<
+ "_Atomic cannot be applied to "
+ "%select{incomplete |array |function |reference |atomic |qualified |}0type "
+ "%1 %select{||||||which is not trivially copyable}0">;
+
+// Expressions.
+def ext_sizeof_alignof_function_type : Extension<
+ "invalid application of '%select{sizeof|alignof|vec_step}0' to a "
+ "function type">, InGroup<PointerArith>;
+def ext_sizeof_alignof_void_type : Extension<
+ "invalid application of '%select{sizeof|alignof|vec_step}0' to a void "
+ "type">, InGroup<PointerArith>;
+def err_opencl_sizeof_alignof_type : Error<
+ "invalid application of '%select{sizeof|alignof|vec_step|__builtin_omp_required_simd_align}0' to a void type">;
+def err_sizeof_alignof_incomplete_type : Error<
+ "invalid application of '%select{sizeof|alignof|vec_step|__builtin_omp_required_simd_align}0' to an "
+ "incomplete type %1">;
+def err_sizeof_alignof_function_type : Error<
+ "invalid application of '%select{sizeof|alignof|vec_step|__builtin_omp_required_simd_align}0' to a "
+ "function type">;
+def err_openmp_default_simd_align_expr : Error<
+ "invalid application of '__builtin_omp_required_simd_align' to an expression, only type is allowed">;
+def err_sizeof_alignof_typeof_bitfield : Error<
+ "invalid application of '%select{sizeof|alignof|typeof}0' to bit-field">;
+def err_alignof_member_of_incomplete_type : Error<
+ "invalid application of 'alignof' to a field of a class still being defined">;
+def err_vecstep_non_scalar_vector_type : Error<
+ "'vec_step' requires built-in scalar or vector type, %0 invalid">;
+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">,
+ InGroup<DiagGroup<"extended-offsetof">>;
+def ext_offsetof_non_pod_type : ExtWarn<"offset of on non-POD type %0">,
+ InGroup<InvalidOffsetof>;
+def ext_offsetof_non_standardlayout_type : ExtWarn<
+ "offset of on non-standard-layout type %0">, InGroup<InvalidOffsetof>;
+def err_offsetof_bitfield : Error<"cannot compute offset of bit-field %0">;
+def err_offsetof_field_of_virtual_base : Error<
+ "invalid application of 'offsetof' to a field of a virtual base">;
+def warn_sub_ptr_zero_size_types : Warning<
+ "subtraction of pointers to type %0 of zero size has undefined behavior">,
+ InGroup<PointerArith>;
+
+def warn_floatingpoint_eq : Warning<
+ "comparing floating point with == or != is unsafe">,
+ InGroup<DiagGroup<"float-equal">>, DefaultIgnore;
+
+def warn_remainder_division_by_zero : Warning<
+ "%select{remainder|division}0 by zero is undefined">,
+ InGroup<DivZero>;
+def warn_shift_lhs_negative : Warning<"shifting a negative signed value is undefined">,
+ InGroup<DiagGroup<"shift-negative-value">>;
+def warn_shift_negative : Warning<"shift count is negative">,
+ InGroup<DiagGroup<"shift-count-negative">>;
+def warn_shift_gt_typewidth : Warning<"shift count >= width of type">,
+ InGroup<DiagGroup<"shift-count-overflow">>;
+def warn_shift_result_gt_typewidth : Warning<
+ "signed shift result (%0) requires %1 bits to represent, but %2 only has "
+ "%3 bits">, InGroup<DiagGroup<"shift-overflow">>;
+def warn_shift_result_sets_sign_bit : Warning<
+ "signed shift result (%0) sets the sign bit of the shift expression's "
+ "type (%1) and becomes negative">,
+ InGroup<DiagGroup<"shift-sign-overflow">>, DefaultIgnore;
+
+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_silence : Note<
+ "place parentheses around the '%0' expression to silence this warning">;
+
+def warn_precedence_conditional : Warning<
+ "operator '?:' has lower precedence than '%0'; '%0' will be evaluated first">,
+ InGroup<Parentheses>;
+def note_precedence_conditional_first : Note<
+ "place parentheses around the '?:' expression to evaluate it first">;
+
+def warn_logical_instead_of_bitwise : Warning<
+ "use of logical '%0' with constant operand">,
+ InGroup<DiagGroup<"constant-logical-operand">>;
+def note_logical_instead_of_bitwise_change_operator : Note<
+ "use '%0' for a bitwise operation">;
+def note_logical_instead_of_bitwise_remove_constant : Note<
+ "remove constant to silence this warning">;
+
+def warn_bitwise_op_in_bitwise_op : Warning<
+ "'%0' within '%1'">, InGroup<BitwiseOpParentheses>;
+
+def warn_logical_and_in_logical_or : Warning<
+ "'&&' within '||'">, InGroup<LogicalOpParentheses>;
+
+def warn_overloaded_shift_in_comparison :Warning<
+ "overloaded operator %select{>>|<<}0 has higher precedence than "
+ "comparison operator">,
+ InGroup<OverloadedShiftOpParentheses>;
+def note_evaluate_comparison_first :Note<
+ "place parentheses around comparison expression to evaluate it first">;
+
+def warn_addition_in_bitshift : Warning<
+ "operator '%0' has lower precedence than '%1'; "
+ "'%1' will be evaluated first">, InGroup<ShiftOpParentheses>;
+
+def warn_self_assignment : Warning<
+ "explicitly assigning value of variable of type %0 to itself">,
+ InGroup<SelfAssignment>, DefaultIgnore;
+def warn_self_move : Warning<
+ "explicitly moving variable of type %0 to itself">,
+ InGroup<SelfMove>, DefaultIgnore;
+
+def warn_redundant_move_on_return : Warning<
+ "redundant move in return statement">,
+ InGroup<RedundantMove>, DefaultIgnore;
+def warn_pessimizing_move_on_return : Warning<
+ "moving a local object in a return statement prevents copy elision">,
+ InGroup<PessimizingMove>, DefaultIgnore;
+def warn_pessimizing_move_on_initialization : Warning<
+ "moving a temporary object prevents copy elision">,
+ InGroup<PessimizingMove>, DefaultIgnore;
+def note_remove_move : Note<"remove std::move call here">;
+
+def warn_string_plus_int : Warning<
+ "adding %0 to a string does not append to the string">,
+ InGroup<StringPlusInt>;
+def warn_string_plus_char : Warning<
+ "adding %0 to a string pointer does not append to the string">,
+ InGroup<StringPlusChar>;
+def note_string_plus_scalar_silence : Note<
+ "use array indexing to silence this warning">;
+
+def warn_sizeof_array_param : Warning<
+ "sizeof on array function parameter will return size of %0 instead of %1">,
+ InGroup<SizeofArrayArgument>;
+
+def warn_sizeof_array_decay : Warning<
+ "sizeof on pointer operation will return size of %0 instead of %1">,
+ InGroup<SizeofArrayDecay>;
+
+def err_sizeof_nonfragile_interface : Error<
+ "application of '%select{alignof|sizeof}1' to interface %0 is "
+ "not supported on this architecture and platform">;
+def err_atdef_nonfragile_interface : Error<
+ "use of @defs is not supported on this architecture and platform">;
+def err_subscript_nonfragile_interface : Error<
+ "subscript requires size of interface %0, which is not constant for "
+ "this architecture and platform">;
+
+def err_arithmetic_nonfragile_interface : Error<
+ "arithmetic on pointer to interface %0, which is not a constant size for "
+ "this architecture and platform">;
+
+
+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_dereference_incomplete_type : Error<
+ "dereference of pointer to incomplete type %0">;
+def ext_gnu_subscript_void_type : Extension<
+ "subscript of a pointer to void is a GNU extension">, InGroup<PointerArith>;
+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 error_arc_weak_ivar_access : Error<
+ "dereferencing a __weak pointer is not allowed due to possible "
+ "null value caused by race condition, assign it to strong variable first">;
+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; did you mean to use '%select{->|.}1'?">;
+def note_typecheck_member_reference_suggestion : Note<
+ "did you mean to use '.' instead?">;
+def note_member_reference_arrow_from_operator_arrow : Note<
+ "'->' applied to return value of the operator->() declared here">;
+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 a function; perhaps you meant to call "
+ "it%select{| with no arguments}0?">;
+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_no_member_overloaded_arrow : Error<
+ "no member named %0 in %1; did you mean to use '->' instead of '.'?">;
+
+def err_member_not_yet_instantiated : Error<
+ "no member %0 in %1; it has not yet been instantiated">;
+def note_non_instantiated_member_here : Note<
+ "not-yet-instantiated member is declared here">;
+
+def err_enumerator_does_not_exist : Error<
+ "enumerator %0 does not exist in instantiation of %1">;
+def note_enum_specialized_here : Note<
+ "enum %0 was explicitly specialized here">;
+
+def err_member_redeclared : Error<"class member cannot be redeclared">;
+def ext_member_redeclared : ExtWarn<"class member cannot be redeclared">,
+ InGroup<RedeclaredClassMember>;
+def err_member_redeclared_in_instantiation : Error<
+ "multiple overloads of %0 instantiate to the same signature %1">;
+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_decl_does_not_match : Error<
+ "out-of-line %select{declaration|definition}2 of %0 "
+ "does not match any declaration in %1">;
+def err_friend_decl_with_def_arg_must_be_def : Error<
+ "friend declaration specifying a default argument must be a definition">;
+def err_friend_decl_with_def_arg_redeclared : Error<
+ "friend declaration specifying a default argument must be the only declaration">;
+def err_friend_decl_does_not_match : Error<
+ "friend declaration of %0 does not match any declaration in %1">;
+def err_member_decl_does_not_match_suggest : Error<
+ "out-of-line %select{declaration|definition}2 of %0 "
+ "does not match any declaration in %1; did you mean %3?">;
+def err_member_def_does_not_match_ret_type : Error<
+ "return type of out-of-line definition of %q0 differs from "
+ "that in the declaration">;
+def err_nonstatic_member_out_of_line : Error<
+ "non-static data member defined out-of-line">;
+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 err_member_extra_qualification : Error<
+ "extra qualification on member %0">;
+def warn_member_extra_qualification : Warning<
+ err_member_extra_qualification.Text>, InGroup<MicrosoftExtraQualification>;
+def warn_namespace_member_extra_qualification : Warning<
+ "extra qualification on member %0">,
+ InGroup<DiagGroup<"extra-qualification">>;
+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 note_member_def_close_const_match : Note<
+ "member declaration does not match because "
+ "it %select{is|is not}0 const qualified">;
+def note_member_def_close_param_match : Note<
+ "type of %ordinal0 parameter of member declaration does not match definition"
+ "%diff{ ($ vs $)|}1,2">;
+def note_local_decl_close_match : Note<"local declaration nearly matches">;
+def note_local_decl_close_param_match : Note<
+ "type of %ordinal0 parameter of local declaration does not match definition"
+ "%diff{ ($ vs $)|}1,2">;
+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_expect_int : Error<
+ "used type %0 where integer is required">;
+def err_typecheck_arithmetic_incomplete_type : Error<
+ "arithmetic on a pointer to an incomplete type %0">;
+def err_typecheck_pointer_arith_function_type : Error<
+ "arithmetic on%select{ a|}0 pointer%select{|s}0 to%select{ the|}2 "
+ "function type%select{|s}2 %1%select{| and %3}2">;
+def err_typecheck_pointer_arith_void_type : Error<
+ "arithmetic on%select{ a|}0 pointer%select{|s}0 to void">;
+def err_typecheck_decl_incomplete_type : Error<
+ "variable has incomplete type %0">;
+def err_typecheck_decl_incomplete_type___float128 : Error<
+ "support for type '__float128' is not yet implemented">;
+def ext_typecheck_decl_incomplete_type : ExtWarn<
+ "tentative definition of variable with internal linkage has incomplete non-array type %0">,
+ InGroup<DiagGroup<"tentative-definition-incomplete-type">>;
+def err_tentative_def_incomplete_type : Error<
+ "tentative definition has 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| or wide string literal}0">;
+def err_array_init_narrow_string_into_wchar : Error<
+ "initializing wide char array with non-wide string literal">;
+def err_array_init_wide_string_into_char : Error<
+ "initializing char array with wide string literal">;
+def err_array_init_incompat_wide_string_into_wchar : Error<
+ "initializing wide char array with incompatible wide string literal">;
+def err_array_init_different_type : Error<
+ "cannot initialize array %diff{of type $ with array of type $|"
+ "with different type of array}0,1">;
+def err_array_init_non_constant_array : Error<
+ "cannot initialize array %diff{of type $ with non-constant array of type $|"
+ "with different type of array}0,1">;
+def ext_array_init_copy : Extension<
+ "initialization of an array "
+ "%diff{of type $ from a compound literal of type $|"
+ "from a compound literal}0,1 is a GNU extension">, InGroup<GNUCompoundLiteralInitializer>;
+// This is intentionally not disabled by -Wno-gnu.
+def ext_array_init_parens : ExtWarn<
+ "parenthesized initialization of a member array is a GNU extension">,
+ InGroup<DiagGroup<"gnu-array-member-paren-init">>, DefaultError;
+def warn_deprecated_string_literal_conversion : Warning<
+ "conversion from string literal to %0 is deprecated">,
+ InGroup<CXX11CompatDeprecatedWritableStr>;
+def ext_deprecated_string_literal_conversion : ExtWarn<
+ "ISO C++11 does not allow conversion from string literal to %0">,
+ InGroup<WritableStrings>, SFINAEFailure;
+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 warn_standalone_specifier : Warning<"'%0' ignored on this declaration">,
+ InGroup<MissingDeclarations>;
+def ext_standalone_specifier : ExtWarn<"'%0' is not permitted on a declaration "
+ "of a type">, InGroup<MissingDeclarations>;
+def err_standalone_class_nested_name_specifier : Error<
+ "forward declaration of %select{class|struct|interface|union|enum}0 cannot "
+ "have a nested name specifier">;
+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 %select{bit-field"
+ "|vector element|property expression|register variable}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_address_of_function_with_pass_object_size_params: Error<
+ "cannot take address of function %0 because parameter %1 has "
+ "pass_object_size attribute">;
+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_addrof_function : Error<
+ "extra '&' taking address of overloaded function">;
+def err_typecheck_invalid_lvalue_addrof : Error<
+ "cannot take the address of an rvalue of type %0">;
+def ext_typecheck_addrof_temporary : ExtWarn<
+ "taking the address of a temporary object of type %0">,
+ InGroup<DiagGroup<"address-of-temporary">>, DefaultError;
+def err_typecheck_addrof_temporary : Error<
+ "taking the address of a temporary object of type %0">;
+def err_typecheck_addrof_dtor : Error<
+ "taking the address of a destructor">;
+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 ext_typecheck_indirection_through_void_pointer : ExtWarn<
+ "ISO C++ does not allow indirection on operand of type %0">,
+ InGroup<DiagGroup<"void-ptr-dereference">>;
+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 warn_pointer_indirection_from_incompatible_type : Warning<
+ "dereference of type %1 that was reinterpret_cast from type %0 has undefined "
+ "behavior">,
+ InGroup<UndefinedReinterpretCast>, DefaultIgnore;
+
+def err_objc_object_assignment : Error<
+ "cannot assign to class object (%0 invalid)">;
+def err_typecheck_invalid_operands : Error<
+ "invalid operands to binary expression (%0 and %1)">;
+def err_typecheck_sub_ptr_compatible : Error<
+ "%diff{$ and $ are not pointers to compatible types|"
+ "pointers to incompatible types}0,1">;
+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%diff{ ($ and $)|}0,1">,
+ InGroup<CompareDistinctPointerType>;
+def ext_typecheck_cond_incompatible_operands : ExtWarn<
+ "incompatible operand types (%0 and %1)">;
+def err_cond_voidptr_arc : Error <
+ "operands to conditional of types%diff{ $ and $|}0,1 are incompatible "
+ "in ARC mode">;
+def err_typecheck_comparison_of_distinct_pointers : Error<
+ "comparison of distinct pointer types%diff{ ($ and $)|}0,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">, InGroup<CompareDistinctPointerType>;
+def err_typecheck_op_on_nonoverlapping_address_space_pointers : Error<
+ "%select{comparison between %diff{ ($ and $)|}0,1"
+ "|arithmetic operation with operands of type %diff{ ($ and $)|}0,1}2"
+ " which are pointers to non-overlapping address spaces">;
+
+def err_typecheck_assign_const : Error<
+ "%select{"
+ "cannot assign to return value because function %1 returns a const value|"
+ "cannot assign to variable %1 with const-qualified type %2|"
+ "cannot assign to %select{non-|}1static data member %2 "
+ "with const-qualified type %3|"
+ "cannot assign to non-static data member within const member function %1|"
+ "read-only variable is not assignable}0">;
+
+def note_typecheck_assign_const : Note<
+ "%select{"
+ "function %1 which returns const-qualified type %2 declared here|"
+ "variable %1 declared const here|"
+ "%select{non-|}1static data member %2 declared const here|"
+ "member function %q1 is declared const here}0">;
+
+def warn_mixed_sign_comparison : Warning<
+ "comparison of 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_out_of_range_compare : Warning<
+ "comparison of %select{constant %0|true|false}1 with "
+ "%select{expression of type %2|boolean expression}3 is always "
+ "%select{false|true}4">, InGroup<TautologicalOutOfRangeCompare>;
+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"
+ "%diff{ ($ and $)|}0,1">,
+ InGroup<DiagGroup<"enum-compare">>;
+def warn_null_in_arithmetic_operation : Warning<
+ "use of NULL in arithmetic operation">,
+ InGroup<NullArithmetic>;
+def warn_null_in_comparison_operation : Warning<
+ "comparison between NULL and non-pointer "
+ "%select{(%1 and NULL)|(NULL and %1)}0">,
+ InGroup<NullArithmetic>;
+def err_shift_rhs_only_vector : Error<
+ "requested shift is a vector of type %0 but the first operand is not a "
+ "vector (%1)">;
+
+def warn_logical_not_on_lhs_of_comparison : Warning<
+ "logical not is only applied to the left hand side of this comparison">,
+ InGroup<LogicalNotParentheses>;
+def note_logical_not_fix : Note<
+ "add parentheses after the '!' to evaluate the comparison first">;
+def note_logical_not_silence_with_parens : Note<
+ "add parentheses around left hand side expression to silence this warning">;
+
+def err_invalid_this_use : Error<
+ "invalid use of 'this' outside of a non-static member function">;
+def err_this_static_member_func : Error<
+ "'this' cannot be%select{| implicitly}0 used in a static member function "
+ "declaration">;
+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<
+ "%select{static |non-}0member function %select{of type %2 |}1"
+ "cannot have '%3' qualifier">;
+def err_compound_qualified_function_type : Error<
+ "%select{block pointer|pointer|reference}0 to function type %select{%2 |}1"
+ "cannot have '%3' qualifier">;
+
+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 non-static data member %0">;
+def err_nested_non_static_member_use : Error<
+ "%select{call to non-static member function|use of non-static data member}0 "
+ "%2 of %1 from nested type %3">;
+def warn_cxx98_compat_non_static_member_use : Warning<
+ "use of non-static data member %0 in an unevaluated context is "
+ "incompatible with C++98">, InGroup<CXX98Compat>, DefaultIgnore;
+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_value_init_for_array_type : Error<
+ "array types cannot be value-initialized">;
+def err_value_init_for_function_type : Error<
+ "function 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_flexarray_type : Error<
+ "cannot refer to declaration of structure variable with flexible array member "
+ "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_invalid_property_name : Error<
+ "%0 is not a valid property name (accessing an object of type %1)">;
+def err_getter_not_found : Error<
+ "no getter method for read from property">;
+def err_objc_subscript_method_not_found : Error<
+ "expected method to %select{read|write}1 %select{dictionary|array}2 element not "
+ "found on object of type %0">;
+def err_objc_subscript_index_type : Error<
+ "method index parameter type %0 is not integral type">;
+def err_objc_subscript_key_type : Error<
+ "method key parameter type %0 is not object type">;
+def err_objc_subscript_dic_object_type : Error<
+ "method object parameter type %0 is not object type">;
+def err_objc_subscript_object_type : Error<
+ "cannot assign to this %select{dictionary|array}1 because assigning method's "
+ "2nd parameter of type %0 is not an Objective-C pointer type">;
+def err_objc_subscript_base_type : Error<
+ "%select{dictionary|array}1 subscript base type %0 is not an Objective-C object">;
+def err_objc_multiple_subscript_type_conversion : Error<
+ "indexing expression is invalid because subscript type %0 has "
+ "multiple type conversion functions">;
+def err_objc_subscript_type_conversion : Error<
+ "indexing expression is invalid because subscript type %0 is not an integral"
+ " or Objective-C pointer type">;
+def err_objc_subscript_pointer : Error<
+ "indexing expression is invalid because subscript type %0 is not an"
+ " Objective-C pointer">;
+def err_objc_indexing_method_result_type : Error<
+ "method for accessing %select{dictionary|array}1 element must have Objective-C"
+ " object return type instead of %0">;
+def err_objc_index_incomplete_class_type : Error<
+ "Objective-C index expression has incomplete class type %0">;
+def err_illegal_container_subscripting_op : Error<
+ "illegal operation on Objective-C container subscripting">;
+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 declaration of class here">;
+def err_duplicate_property : Error<
+ "property has a previous declaration">;
+def ext_gnu_void_ptr : Extension<
+ "arithmetic on%select{ a|}0 pointer%select{|s}0 to void is a GNU extension">,
+ InGroup<PointerArith>;
+def ext_gnu_ptr_func_arith : Extension<
+ "arithmetic on%select{ a|}0 pointer%select{|s}0 to%select{ the|}2 function "
+ "type%select{|s}2 %1%select{| and %3}2 is a GNU extension">,
+ InGroup<PointerArith>;
+def error_readonly_message_assignment : Error<
+ "assigning to 'readonly' return result of an Objective-C message 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 err_nosetter_property_assignment : Error<
+ "%select{assignment to readonly property|"
+ "no setter method %1 for assignment to property}0">;
+def err_nosetter_property_incdec : Error<
+ "%select{%select{increment|decrement}1 of readonly property|"
+ "no setter method %2 for %select{increment|decrement}1 of property}0">;
+def err_nogetter_property_compound_assignment : Error<
+ "a getter method is needed to perform a compound assignment on a property">;
+def err_nogetter_property_incdec : Error<
+ "no getter method %1 for %select{increment|decrement}0 of property">;
+def error_no_subobject_property_setting : Error<
+ "expression is not assignable">;
+def err_qualified_objc_access : Error<
+ "%select{property|instance variable}0 access cannot be qualified with '%1'">;
+
+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">,
+ InGroup<MethodAccess>;
+def warn_class_method_not_found : Warning<
+ "class method %objcclass0 not found (return type defaults to 'id')">,
+ InGroup<MethodAccess>;
+def warn_instance_method_on_class_found : Warning<
+ "instance method %0 found instead of class method %1">,
+ InGroup<MethodAccess>;
+def warn_inst_method_not_found : Warning<
+ "instance method %objcinstance0 not found (return type defaults to 'id')">,
+ InGroup<MethodAccess>;
+def warn_instance_method_not_found_with_typo : Warning<
+ "instance method %objcinstance0 not found (return type defaults to 'id')"
+ "; did you mean %objcinstance2?">, InGroup<MethodAccess>;
+def warn_class_method_not_found_with_typo : Warning<
+ "class method %objcclass0 not found (return type defaults to 'id')"
+ "; did you mean %objcclass2?">, InGroup<MethodAccess>;
+def error_method_not_found_with_typo : Error<
+ "%select{instance|class}1 method %0 not found "
+ "; did you mean %2?">;
+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_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'">,InGroup<ObjCReceiver>;
+def err_bad_receiver_type : Error<"bad receiver type %0">;
+def err_incomplete_receiver_type : Error<"incomplete 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 '%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 warn_objc_pointer_cxx_catch_fragile : Warning<
+ "cannot catch an exception thrown with @throw in C++ in the non-unified "
+ "exception model">, InGroup<ObjCNonUnifiedException>;
+def err_objc_object_catch : Error<
+ "cannot catch an Objective-C object by value">;
+def err_incomplete_type_objc_at_encode : Error<
+ "'@encode' of incomplete type %0">;
+def warn_objc_circular_container : Warning<
+ "adding '%0' to '%1' might cause circular dependency in container">,
+ InGroup<DiagGroup<"objc-circular-container">>;
+def note_objc_circular_container_declared_here : Note<"'%0' declared here">;
+
+def warn_setter_getter_impl_required : Warning<
+ "property %0 requires method %1 to be defined - "
+ "use @synthesize, @dynamic or provide a method implementation "
+ "in this class implementation">,
+ InGroup<ObjCPropertyImpl>;
+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 this category">,
+ InGroup<ObjCPropertyImpl>;
+def note_parameter_named_here : Note<
+ "passing argument to parameter %0 here">;
+def note_parameter_here : Note<
+ "passing argument to parameter here">;
+def note_method_return_type_change : Note<
+ "compiler has implicitly changed method %0 return type">;
+
+// 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 warn_reinterpret_different_from_static : Warning<
+ "'reinterpret_cast' %select{from|to}3 class %0 %select{to|from}3 its "
+ "%select{virtual base|base at non-zero offset}2 %1 behaves differently from "
+ "'static_cast'">, InGroup<ReinterpretBaseClass>;
+def note_reinterpret_updowncast_use_static: Note<
+ "use 'static_cast' to adjust the pointer correctly while "
+ "%select{upcasting|downcasting}0">;
+
+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_unrelated_class : Error<
+ "%select{const_cast|static_cast|reinterpret_cast|dynamic_cast|C-style cast|"
+ "functional-style cast}0 from %1 to %2, which are not related by "
+ "inheritance, is not allowed">;
+def note_type_incomplete : Note<"%0 is incomplete">;
+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_bitfield : Error<
+ "%select{const_cast|static_cast|reinterpret_cast|dynamic_cast|C-style cast|"
+ "functional-style cast}0 from bit-field lvalue to reference type %2">;
+def err_bad_cxx_cast_qualifiers_away : Error<
+ "%select{const_cast|static_cast|reinterpret_cast|dynamic_cast|C-style cast|"
+ "functional-style cast}0 from %1 to %2 casts away qualifiers">;
+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 ext_ms_cast_fn_obj : ExtWarn<
+ "static_cast between pointer-to-function and pointer-to-object is a "
+ "Microsoft extension">, InGroup<MicrosoftCast>;
+def warn_cxx98_compat_cast_fn_obj : Warning<
+ "cast between pointer-to-function and pointer-to-object is incompatible with C++98">,
+ InGroup<CXX98CompatPedantic>, DefaultIgnore;
+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_reinterpret_cast_reference : Error<
+ "reinterpret_cast of a %0 to %1 needs its address, which is not allowed">;
+def warn_undefined_reinterpret_cast : Warning<
+ "reinterpret_cast from %0 to %1 has undefined behavior">,
+ InGroup<UndefinedReinterpretCast>, DefaultIgnore;
+
+// 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_ms___leave_not_in___try : Error<
+ "'__leave' statement not in __try block">;
+def err_uuidof_without_guid : Error<
+ "cannot call operator __uuidof on a type with no GUID">;
+def err_uuidof_with_multiple_guids : Error<
+ "cannot call operator __uuidof on a type with multiple GUIDs">;
+def err_incomplete_typeid : Error<"'typeid' of incomplete type %0">;
+def err_variably_modified_typeid : Error<"'typeid' of variably modified 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 %select{|unscoped }0"
+ "enumeration type, not %1">;
+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++11 extension">,
+ InGroup<CXX11>;
+def warn_cxx98_compat_array_size_conversion : Warning<
+ "implicit conversion from array size expression of type %0 to "
+ "%select{integral|enumeration}1 type %2 is incompatible with C++98">,
+ InGroup<CXX98CompatPedantic>, DefaultIgnore;
+def err_address_space_qualified_new : Error<
+ "'new' cannot allocate objects of type %0 in address space '%1'">;
+def err_address_space_qualified_delete : Error<
+ "'delete' cannot delete objects of type %0 in address space '%1'">;
+
+def err_default_init_const : Error<
+ "default initialization of an object of const type %0"
+ "%select{| without a user-provided default constructor}1">;
+def ext_default_init_const : ExtWarn<
+ "default initialization of an object of const type %0"
+ "%select{| without a user-provided default constructor}1 "
+ "is a Microsoft extension">,
+ InGroup<MicrosoftConstInit>;
+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">,
+ InGroup<DeleteIncomplete>;
+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 behavior">,
+ InGroup<DeleteIncomplete>;
+def err_delete_incomplete_class_type : Error<
+ "deleting incomplete class type %0; no conversions to pointer type">;
+def err_delete_explicit_conversion : Error<
+ "converting delete expression from type %0 to type %1 invokes an explicit "
+ "conversion function">;
+def note_delete_conversion : Note<"conversion to pointer type %0">;
+def warn_delete_array_type : Warning<
+ "'delete' applied to a pointer-to-array type %0 treated as 'delete[]'">;
+def warn_mismatched_delete_new : Warning<
+ "'delete%select{|[]}0' applied to a pointer that was allocated with "
+ "'new%select{[]|}0'; did you mean 'delete%select{[]|}0'?">,
+ InGroup<DiagGroup<"mismatched-new-delete">>;
+def note_allocated_here : Note<"allocated with 'new%select{[]|}0' here">;
+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 and "
+ "incompatible with C++1z">, InGroup<DeprecatedIncrementBool>;
+def ext_increment_bool : ExtWarn<
+ "ISO C++1z does not allow incrementing expression of type bool">,
+ DefaultError, InGroup<IncrementBool>;
+def err_increment_decrement_enum : Error<
+ "cannot %select{decrement|increment}0 expression of enum type %1">;
+def err_catch_incomplete_ptr : Error<
+ "cannot catch pointer to incomplete type %0">;
+def err_catch_incomplete_ref : Error<
+ "cannot catch 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_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">,
+ InGroup<Exceptions>;
+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 err_seh_try_outside_functions : Error<
+ "cannot use SEH '__try' in blocks, captured regions, or Obj-C method decls">;
+def err_mixing_cxx_try_seh_try : Error<
+ "cannot use C++ 'try' in the same function as SEH '__try'">;
+def err_seh_try_unsupported : Error<
+ "SEH '__try' is not supported on this target">;
+def note_conflicting_try_here : Note<
+ "conflicting %0 here">;
+def warn_jump_out_of_seh_finally : Warning<
+ "jump out of __finally block has undefined behavior">,
+ InGroup<DiagGroup<"jump-seh-finally">>;
+def warn_non_virtual_dtor : Warning<
+ "%0 has virtual functions but non-virtual destructor">,
+ InGroup<NonVirtualDtor>, DefaultIgnore;
+def warn_delete_non_virtual_dtor : Warning<
+ "delete called on non-final %0 that has virtual functions "
+ "but non-virtual destructor">,
+ InGroup<DeleteNonVirtualDtor>, DefaultIgnore;
+def warn_delete_abstract_non_virtual_dtor : Warning<
+ "delete called on %0 that is abstract but has non-virtual destructor">,
+ InGroup<DeleteNonVirtualDtor>;
+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"
+ "%select{|: different classes%diff{ ($ vs $)|}2,3"
+ "|: different number of parameters (%2 vs %3)"
+ "|: type mismatch at %ordinal2 parameter%diff{ ($ vs $)|}3,4"
+ "|: different return type%diff{ ($ vs $)|}2,3"
+ "|: different qualifiers ("
+ "%select{none|const|restrict|const and restrict|volatile|const and volatile|"
+ "volatile and restrict|const, volatile, and restrict}2 vs "
+ "%select{none|const|restrict|const and restrict|volatile|const and volatile|"
+ "volatile and restrict|const, volatile, and restrict}3)}1">;
+def warn_using_directive_in_header : Warning<
+ "using namespace directive in global context in header">,
+ InGroup<HeaderHygiene>, DefaultIgnore;
+def warn_overaligned_type : Warning<
+ "type %0 requires %1 bytes of alignment and the default allocator only "
+ "guarantees %2 bytes">,
+ InGroup<OveralignedType>, DefaultIgnore;
+
+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; "
+ "%diff{$ can be converted to $ and vice versa|"
+ "types can be convert to each other}0,1">;
+def err_conditional_ambiguous_ovl : Error<
+ "conditional expression is ambiguous; %diff{$ and $|types}0,1 "
+ "can be converted to several common types">;
+def err_conditional_vector_size : Error<
+ "vector condition type %0 and result type %1 do not have the same number "
+ "of elements">;
+def err_conditional_vector_element_size : Error<
+ "vector condition type %0 and result type %1 do not have elements of the "
+ "same size">;
+
+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 warn_cdtor_function_try_handler_mem_expr : Warning<
+ "cannot refer to a non-static member from the handler of a "
+ "%select{constructor|destructor}0 function try block">, InGroup<Exceptions>;
+
+let CategoryName = "Lambda Issue" in {
+ def err_capture_more_than_once : Error<
+ "%0 can appear only once in a capture list">;
+ def err_reference_capture_with_reference_default : Error<
+ "'&' cannot precede a capture when the capture default is '&'">;
+ def err_this_capture_with_copy_default : Error<
+ "'this' cannot be explicitly captured when the capture default is '='">;
+ def err_copy_capture_with_copy_default : Error<
+ "'&' must precede a capture when the capture default is '='">;
+ def err_capture_does_not_name_variable : Error<
+ "%0 in capture list does not name a variable">;
+ def err_capture_non_automatic_variable : Error<
+ "%0 cannot be captured because it does not have automatic storage "
+ "duration">;
+ def err_this_capture : Error<
+ "'this' cannot be %select{implicitly |}0captured in this context">;
+ def err_lambda_capture_anonymous_var : Error<
+ "unnamed variable cannot be implicitly captured in a lambda expression">;
+ def err_lambda_capture_flexarray_type : Error<
+ "variable %0 with flexible array member cannot be captured in "
+ "a lambda expression">;
+ def err_lambda_impcap : Error<
+ "variable %0 cannot be implicitly captured in a lambda with no "
+ "capture-default specified">;
+ def note_lambda_decl : Note<"lambda expression begins here">;
+ def err_lambda_unevaluated_operand : Error<
+ "lambda expression in an unevaluated operand">;
+ def err_lambda_in_constant_expression : Error<
+ "a lambda expression may not appear inside of a constant expression">;
+ def err_lambda_return_init_list : Error<
+ "cannot deduce lambda return type from initializer list">;
+ def err_lambda_capture_default_arg : Error<
+ "lambda expression in default argument cannot capture any entity">;
+ def err_lambda_incomplete_result : Error<
+ "incomplete result type %0 in lambda expression">;
+ def err_noreturn_lambda_has_return_expr : Error<
+ "lambda declared 'noreturn' should not return">;
+ def warn_maybe_falloff_nonvoid_lambda : Warning<
+ "control may reach end of non-void lambda">,
+ InGroup<ReturnType>;
+ def warn_falloff_nonvoid_lambda : Warning<
+ "control reaches end of non-void lambda">,
+ InGroup<ReturnType>;
+ def err_access_lambda_capture : Error<
+ // The ERRORs represent other special members that aren't constructors, in
+ // hopes that someone will bother noticing and reporting if they appear
+ "capture of variable '%0' as type %1 calls %select{private|protected}3 "
+ "%select{default |copy |move |*ERROR* |*ERROR* |*ERROR* |}2constructor">,
+ AccessControl;
+ def note_lambda_to_block_conv : Note<
+ "implicit capture of lambda object due to conversion to block pointer "
+ "here">;
+
+ // C++14 lambda init-captures.
+ def warn_cxx11_compat_init_capture : Warning<
+ "initialized lambda captures are incompatible with C++ standards "
+ "before C++14">, InGroup<CXXPre14Compat>, DefaultIgnore;
+ def ext_init_capture : ExtWarn<
+ "initialized lambda captures are a C++14 extension">, InGroup<CXX14>;
+ def err_init_capture_no_expression : Error<
+ "initializer missing for lambda capture %0">;
+ def err_init_capture_multiple_expressions : Error<
+ "initializer for lambda capture %0 contains multiple expressions">;
+ def err_init_capture_paren_braces : Error<
+ "cannot deduce type for lambda capture %1 from "
+ "%select{parenthesized|nested}0 initializer list">;
+ def err_init_capture_deduction_failure : Error<
+ "cannot deduce type for lambda capture %0 from initializer of type %2">;
+ def err_init_capture_deduction_failure_from_init_list : Error<
+ "cannot deduce type for lambda capture %0 from initializer list">;
+}
+
+def err_return_in_captured_stmt : Error<
+ "cannot return from %0">;
+def err_capture_block_variable : Error<
+ "__block variable %0 cannot be captured in a "
+ "%select{lambda expression|captured statement}1">;
+
+def err_operator_arrow_circular : Error<
+ "circular pointer delegation detected">;
+def err_operator_arrow_depth_exceeded : Error<
+ "use of 'operator->' on type %0 would invoke a sequence of more than %1 "
+ "'operator->' calls">;
+def note_operator_arrow_here : Note<
+ "'operator->' declared here produces an object of type %0">;
+def note_operator_arrows_suppressed : Note<
+ "(skipping %0 'operator->'%s0 in backtrace)">;
+def note_operator_arrow_depth : Note<
+ "use -foperator-arrow-depth=N to increase 'operator->' limit">;
+
+def err_pseudo_dtor_base_not_scalar : Error<
+ "object expression of non-scalar type %0 cannot be used in a "
+ "pseudo-destructor expression">;
+def ext_pseudo_dtor_on_void : ExtWarn<
+ "pseudo-destructors on type void are a Microsoft extension">,
+ InGroup<MicrosoftVoidPseudoDtor>;
+def err_pseudo_dtor_type_mismatch : Error<
+ "the type of object expression "
+ "%diff{($) does not match the type being destroyed ($)|"
+ "does not match the type being destroyed}0,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<
+ "reference to %select{destructor|pseudo-destructor}0 must be called"
+ "%select{|; did you mean to call it with no arguments?}1">;
+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_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_typecheck_bool_condition : Error<
+ "value of type %0 is not contextually convertible to 'bool'">;
+def err_typecheck_ambiguous_condition : Error<
+ "conversion %diff{from $ to $|between types}0,1 is ambiguous">;
+def err_typecheck_nonviable_condition : Error<
+ "no viable conversion%select{%diff{ from $ to $|}1,2|"
+ "%diff{ from returned value of type $ to function return type $|}1,2}0">;
+def err_typecheck_nonviable_condition_incomplete : Error<
+ "no viable conversion%diff{ from $ to incomplete type $|}0,1">;
+def err_typecheck_deleted_function : Error<
+ "conversion function %diff{from $ to $|between types}0,1 "
+ "invokes a deleted function">;
+
+def err_expected_class_or_namespace : Error<"%0 is not a class"
+ "%select{ or namespace|, namespace, or enumeration}1">;
+def err_invalid_declarator_scope : Error<"cannot define or redeclare %0 here "
+ "because namespace %1 does not enclose namespace %2">;
+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_invalid_declarator_in_block : Error<
+ "definition or redeclaration of %0 not allowed inside a block">;
+def err_not_tag_in_scope : Error<
+ "no %select{struct|interface|union|class|enum}0 named %1 in %2">;
+
+def err_no_typeid_with_fno_rtti : Error<
+ "cannot use typeid with -fno-rtti">;
+def err_no_dynamic_cast_with_fno_rtti : Error<
+ "cannot use dynamic_cast with -fno-rtti">;
+
+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_incomplete_object_call : Error<
+ "incomplete type in call to object of type %0">;
+
+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<ParenthesesOnEquality>;
+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">;
+
+// 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{%diff{assigning to $ from incompatible type $|"
+ "assigning to type from incompatible type}0,1"
+ "|%diff{passing $ to parameter of incompatible type $|"
+ "passing type to parameter of incompatible type}0,1"
+ "|%diff{returning $ from a function with incompatible result type $|"
+ "returning type from a function with incompatible result type}0,1"
+ "|%diff{converting $ to incompatible type $|"
+ "converting type to incompatible type}0,1"
+ "|%diff{initializing $ with an expression of incompatible type $|"
+ "initializing type with an expression of incompatible type}0,1"
+ "|%diff{sending $ to parameter of incompatible type $|"
+ "sending type to parameter of incompatible type}0,1"
+ "|%diff{casting $ to incompatible type $|"
+ "casting type to incompatible type}0,1}2"
+ "%select{|; dereference with *|"
+ "; take the address with &|"
+ "; remove *|"
+ "; remove &}3"
+ "%select{|: different classes%diff{ ($ vs $)|}5,6"
+ "|: different number of parameters (%5 vs %6)"
+ "|: type mismatch at %ordinal5 parameter%diff{ ($ vs $)|}6,7"
+ "|: different return type%diff{ ($ vs $)|}5,6"
+ "|: different qualifiers ("
+ "%select{none|const|restrict|const and restrict|volatile|const and volatile|"
+ "volatile and restrict|const, volatile, and restrict}5 vs "
+ "%select{none|const|restrict|const and restrict|volatile|const and volatile|"
+ "volatile and restrict|const, volatile, and restrict}6)}4">;
+def err_typecheck_missing_return_type_incompatible : Error<
+ "%diff{return type $ must match previous return type $|"
+ "return type must match previous return type}0,1 when %select{block "
+ "literal|lambda expression}2 has unspecified explicit return type">;
+
+def not_incomplete_class_and_qualified_id : Note<
+ "conformance of forward class %0 to protocol %1 can not be confirmed">;
+def warn_incompatible_qualified_id : Warning<
+ "%select{%diff{assigning to $ from incompatible type $|"
+ "assigning to type from incompatible type}0,1"
+ "|%diff{passing $ to parameter of incompatible type $|"
+ "passing type to parameter of incompatible type}0,1"
+ "|%diff{returning $ from a function with incompatible result type $|"
+ "returning type from a function with incompatible result type}0,1"
+ "|%diff{converting $ to incompatible type $|"
+ "converting type to incompatible type}0,1"
+ "|%diff{initializing $ with an expression of incompatible type $|"
+ "initializing type with an expression of incompatible type}0,1"
+ "|%diff{sending $ to parameter of incompatible type $|"
+ "sending type to parameter of incompatible type}0,1"
+ "|%diff{casting $ to incompatible type $|"
+ "casting type to incompatible type}0,1}2">;
+def ext_typecheck_convert_pointer_int : ExtWarn<
+ "incompatible pointer to integer conversion "
+ "%select{%diff{assigning to $ from $|assigning to different types}0,1"
+ "|%diff{passing $ to parameter of type $|"
+ "passing to parameter of different type}0,1"
+ "|%diff{returning $ from a function with result type $|"
+ "returning from function with different return type}0,1"
+ "|%diff{converting $ to type $|converting between types}0,1"
+ "|%diff{initializing $ with an expression of type $|"
+ "initializing with expression of different type}0,1"
+ "|%diff{sending $ to parameter of type $|"
+ "sending to parameter of different type}0,1"
+ "|%diff{casting $ to type $|casting between types}0,1}2"
+ "%select{|; dereference with *|"
+ "; take the address with &|"
+ "; remove *|"
+ "; remove &}3">,
+ InGroup<IntConversion>;
+def ext_typecheck_convert_int_pointer : ExtWarn<
+ "incompatible integer to pointer conversion "
+ "%select{%diff{assigning to $ from $|assigning to different types}0,1"
+ "|%diff{passing $ to parameter of type $|"
+ "passing to parameter of different type}0,1"
+ "|%diff{returning $ from a function with result type $|"
+ "returning from function with different return type}0,1"
+ "|%diff{converting $ to type $|converting between types}0,1"
+ "|%diff{initializing $ with an expression of type $|"
+ "initializing with expression of different type}0,1"
+ "|%diff{sending $ to parameter of type $|"
+ "sending to parameter of different type}0,1"
+ "|%diff{casting $ to type $|casting between types}0,1}2"
+ "%select{|; dereference with *|"
+ "; take the address with &|"
+ "; remove *|"
+ "; remove &}3">,
+ InGroup<IntConversion>;
+def ext_typecheck_convert_pointer_void_func : Extension<
+ "%select{%diff{assigning to $ from $|assigning to different types}0,1"
+ "|%diff{passing $ to parameter of type $|"
+ "passing to parameter of different type}0,1"
+ "|%diff{returning $ from a function with result type $|"
+ "returning from function with different return type}0,1"
+ "|%diff{converting $ to type $|converting between types}0,1"
+ "|%diff{initializing $ with an expression of type $|"
+ "initializing with expression of different type}0,1"
+ "|%diff{sending $ to parameter of type $|"
+ "sending to parameter of different type}0,1"
+ "|%diff{casting $ to type $|casting between types}0,1}2"
+ " converts between void pointer and function pointer">;
+def ext_typecheck_convert_incompatible_pointer_sign : ExtWarn<
+ "%select{%diff{assigning to $ from $|assigning to different types}0,1"
+ "|%diff{passing $ to parameter of type $|"
+ "passing to parameter of different type}0,1"
+ "|%diff{returning $ from a function with result type $|"
+ "returning from function with different return type}0,1"
+ "|%diff{converting $ to type $|converting between types}0,1"
+ "|%diff{initializing $ with an expression of type $|"
+ "initializing with expression of different type}0,1"
+ "|%diff{sending $ to parameter of type $|"
+ "sending to parameter of different type}0,1"
+ "|%diff{casting $ to type $|casting between types}0,1}2"
+ " converts between pointers to integer types with different sign">,
+ InGroup<DiagGroup<"pointer-sign">>;
+def ext_typecheck_convert_incompatible_pointer : ExtWarn<
+ "incompatible pointer types "
+ "%select{%diff{assigning to $ from $|assigning to different types}0,1"
+ "|%diff{passing $ to parameter of type $|"
+ "passing to parameter of different type}0,1"
+ "|%diff{returning $ from a function with result type $|"
+ "returning from function with different return type}0,1"
+ "|%diff{converting $ to type $|converting between types}0,1"
+ "|%diff{initializing $ with an expression of type $|"
+ "initializing with expression of different type}0,1"
+ "|%diff{sending $ to parameter of type $|"
+ "sending to parameter of different type}0,1"
+ "|%diff{casting $ to type $|casting between types}0,1}2"
+ "%select{|; dereference with *|"
+ "; take the address with &|"
+ "; remove *|"
+ "; remove &}3">,
+ InGroup<IncompatiblePointerTypes>;
+def ext_typecheck_convert_discards_qualifiers : ExtWarn<
+ "%select{%diff{assigning to $ from $|assigning to different types}0,1"
+ "|%diff{passing $ to parameter of type $|"
+ "passing to parameter of different type}0,1"
+ "|%diff{returning $ from a function with result type $|"
+ "returning from function with different return type}0,1"
+ "|%diff{converting $ to type $|converting between types}0,1"
+ "|%diff{initializing $ with an expression of type $|"
+ "initializing with expression of different type}0,1"
+ "|%diff{sending $ to parameter of type $|"
+ "sending to parameter of different type}0,1"
+ "|%diff{casting $ to type $|casting between types}0,1}2"
+ " discards qualifiers">,
+ InGroup<IncompatiblePointerTypesDiscardsQualifiers>;
+def ext_nested_pointer_qualifier_mismatch : ExtWarn<
+ "%select{%diff{assigning to $ from $|assigning to different types}0,1"
+ "|%diff{passing $ to parameter of type $|"
+ "passing to parameter of different type}0,1"
+ "|%diff{returning $ from a function with result type $|"
+ "returning from function with different return type}0,1"
+ "|%diff{converting $ to type $|converting between types}0,1"
+ "|%diff{initializing $ with an expression of type $|"
+ "initializing with expression of different type}0,1"
+ "|%diff{sending $ to parameter of type $|"
+ "sending to parameter of different type}0,1"
+ "|%diff{casting $ to type $|casting between types}0,1}2"
+ " discards qualifiers in nested pointer types">,
+ InGroup<IncompatiblePointerTypesDiscardsQualifiers>;
+def warn_incompatible_vectors : Warning<
+ "incompatible vector types "
+ "%select{%diff{assigning to $ from $|assigning to different types}0,1"
+ "|%diff{passing $ to parameter of type $|"
+ "passing to parameter of different type}0,1"
+ "|%diff{returning $ from a function with result type $|"
+ "returning from function with different return type}0,1"
+ "|%diff{converting $ to type $|converting between types}0,1"
+ "|%diff{initializing $ with an expression of type $|"
+ "initializing with expression of different type}0,1"
+ "|%diff{sending $ to parameter of type $|"
+ "sending to parameter of different type}0,1"
+ "|%diff{casting $ to type $|casting between types}0,1}2">,
+ InGroup<VectorConversion>, DefaultIgnore;
+def err_int_to_block_pointer : Error<
+ "invalid block pointer conversion "
+ "%select{%diff{assigning to $ from $|assigning to different types}0,1"
+ "|%diff{passing $ to parameter of type $|"
+ "passing to parameter of different type}0,1"
+ "|%diff{returning $ from a function with result type $|"
+ "returning from function with different return type}0,1"
+ "|%diff{converting $ to type $|converting between types}0,1"
+ "|%diff{initializing $ with an expression of type $|"
+ "initializing with expression of different type}0,1"
+ "|%diff{sending $ to parameter of type $|"
+ "sending to parameter of different type}0,1"
+ "|%diff{casting $ to type $|casting between types}0,1}2">;
+def err_typecheck_convert_incompatible_block_pointer : Error<
+ "incompatible block pointer types "
+ "%select{%diff{assigning to $ from $|assigning to different types}0,1"
+ "|%diff{passing $ to parameter of type $|"
+ "passing to parameter of different type}0,1"
+ "|%diff{returning $ from a function with result type $|"
+ "returning from function with different return type}0,1"
+ "|%diff{converting $ to type $|converting between types}0,1"
+ "|%diff{initializing $ with an expression of type $|"
+ "initializing with expression of different type}0,1"
+ "|%diff{sending $ to parameter of type $|"
+ "sending to parameter of different type}0,1"
+ "|%diff{casting $ to type $|casting between types}0,1}2">;
+def err_typecheck_incompatible_address_space : Error<
+ "%select{%diff{assigning $ to $|assigning to different types}1,0"
+ "|%diff{passing $ to parameter of type $|"
+ "passing to parameter of different type}0,1"
+ "|%diff{returning $ from a function with result type $|"
+ "returning from function with different return type}0,1"
+ "|%diff{converting $ to type $|converting between types}0,1"
+ "|%diff{initializing $ with an expression of type $|"
+ "initializing with expression of different type}0,1"
+ "|%diff{sending $ to parameter of type $|"
+ "sending to parameter of different type}0,1"
+ "|%diff{casting $ to type $|casting between types}0,1}2"
+ " changes address space of pointer">;
+def err_typecheck_incompatible_ownership : Error<
+ "%select{%diff{assigning $ to $|assigning to different types}1,0"
+ "|%diff{passing $ to parameter of type $|"
+ "passing to parameter of different type}0,1"
+ "|%diff{returning $ from a function with result type $|"
+ "returning from function with different return type}0,1"
+ "|%diff{converting $ to type $|converting between types}0,1"
+ "|%diff{initializing $ with an expression of type $|"
+ "initializing with expression of different type}0,1"
+ "|%diff{sending $ to parameter of type $|"
+ "sending to parameter of different type}0,1"
+ "|%diff{casting $ to type $|casting between types}0,1}2"
+ " changes retain/release properties of pointer">;
+def err_typecheck_comparison_of_distinct_blocks : Error<
+ "comparison of distinct block types%diff{ ($ and $)|}0,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_lambda_decl_ref_not_modifiable_lvalue : Error<
+ "cannot assign to a variable captured by copy in a non-mutable lambda">;
+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 err_call_incomplete_argument : Error<
+ "argument type %0 is incomplete">;
+def err_typecheck_call_too_few_args : Error<
+ "too few %select{|||execution configuration }0arguments to "
+ "%select{function|block|method|kernel function}0 call, "
+ "expected %1, have %2">;
+def err_typecheck_call_too_few_args_one : Error<
+ "too few %select{|||execution configuration }0arguments to "
+ "%select{function|block|method|kernel function}0 call, "
+ "single argument %1 was not specified">;
+def err_typecheck_call_too_few_args_at_least : Error<
+ "too few %select{|||execution configuration }0arguments to "
+ "%select{function|block|method|kernel function}0 call, "
+ "expected at least %1, have %2">;
+def err_typecheck_call_too_few_args_at_least_one : Error<
+ "too few %select{|||execution configuration }0arguments to "
+ "%select{function|block|method|kernel function}0 call, "
+ "at least argument %1 must be specified">;
+def err_typecheck_call_too_few_args_suggest : Error<
+ "too few %select{|||execution configuration }0arguments to "
+ "%select{function|block|method|kernel function}0 call, "
+ "expected %1, have %2; did you mean %3?">;
+def err_typecheck_call_too_few_args_at_least_suggest : Error<
+ "too few %select{|||execution configuration }0arguments to "
+ "%select{function|block|method|kernel function}0 call, "
+ "expected at least %1, have %2; did you mean %3?">;
+def err_typecheck_call_too_many_args : Error<
+ "too many %select{|||execution configuration }0arguments to "
+ "%select{function|block|method|kernel function}0 call, "
+ "expected %1, have %2">;
+def err_typecheck_call_too_many_args_one : Error<
+ "too many %select{|||execution configuration }0arguments to "
+ "%select{function|block|method|kernel function}0 call, "
+ "expected single argument %1, have %2 arguments">;
+def err_typecheck_call_too_many_args_at_most : Error<
+ "too many %select{|||execution configuration }0arguments to "
+ "%select{function|block|method|kernel function}0 call, "
+ "expected at most %1, have %2">;
+def err_typecheck_call_too_many_args_at_most_one : Error<
+ "too many %select{|||execution configuration }0arguments to "
+ "%select{function|block|method|kernel function}0 call, "
+ "expected at most single argument %1, have %2 arguments">;
+def err_typecheck_call_too_many_args_suggest : Error<
+ "too many %select{|||execution configuration }0arguments to "
+ "%select{function|block|method|kernel function}0 call, "
+ "expected %1, have %2; did you mean %3?">;
+def err_typecheck_call_too_many_args_at_most_suggest : Error<
+ "too many %select{|||execution configuration }0arguments to "
+ "%select{function|block|method|kernel function}0 call, "
+ "expected at most %1, have %2; did you mean %3?">;
+
+def err_arc_typecheck_convert_incompatible_pointer : Error<
+ "incompatible pointer types passing retainable parameter of type %0"
+ "to a CF function expecting %1 type">;
+
+def err_builtin_fn_use : Error<"builtin functions must be directly called">;
+
+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<
+ "address argument to atomic builtin must be a pointer (%0 invalid)">;
+def err_atomic_builtin_must_be_pointer_intptr : Error<
+ "address argument to atomic builtin must be a pointer to integer or pointer"
+ " (%0 invalid)">;
+def err_atomic_builtin_must_be_pointer_intfltptr : Error<
+ "address argument to atomic builtin must be a pointer to integer,"
+ " floating-point or pointer (%0 invalid)">;
+def err_atomic_builtin_pointer_size : Error<
+ "address argument to atomic builtin must be a pointer to 1,2,4,8 or 16 byte "
+ "type (%0 invalid)">;
+def err_atomic_exclusive_builtin_pointer_size : Error<
+ "address argument to load or store exclusive builtin must be a pointer to"
+ " 1,2,4 or 8 byte type (%0 invalid)">;
+def err_atomic_op_needs_atomic : Error<
+ "address argument to atomic operation must be a pointer to _Atomic "
+ "type (%0 invalid)">;
+def err_atomic_op_needs_non_const_atomic : Error<
+ "address argument to atomic operation must be a pointer to non-const _Atomic "
+ "type (%0 invalid)">;
+def err_atomic_op_needs_non_const_pointer : Error<
+ "address argument to atomic operation must be a pointer to non-const "
+ "type (%0 invalid)">;
+def err_atomic_op_needs_trivial_copy : Error<
+ "address argument to atomic operation must be a pointer to a "
+ "trivially-copyable type (%0 invalid)">;
+def err_atomic_op_needs_atomic_int_or_ptr : Error<
+ "address argument to atomic operation must be a pointer to %select{|atomic }0"
+ "integer or pointer (%1 invalid)">;
+def err_atomic_op_bitwise_needs_atomic_int : Error<
+ "address argument to bitwise atomic operation must be a pointer to "
+ "%select{|atomic }0integer (%1 invalid)">;
+def warn_atomic_op_has_invalid_memory_order : Warning<
+ "memory order argument to atomic operation is invalid">,
+ InGroup<DiagGroup<"atomic-memory-ordering">>;
+
+def err_overflow_builtin_must_be_int : Error<
+ "operand argument to overflow builtin must be an integer (%0 invalid)">;
+def err_overflow_builtin_must_be_ptr_int : Error<
+ "result argument to overflow builtin must be a pointer "
+ "to a non-const integer (%0 invalid)">;
+
+def err_atomic_load_store_uses_lib : Error<
+ "atomic %select{load|store}0 requires runtime support that is not "
+ "available for this target">;
+
+def err_nontemporal_builtin_must_be_pointer : Error<
+ "address argument to nontemporal builtin must be a pointer (%0 invalid)">;
+def err_nontemporal_builtin_must_be_pointer_intfltptr_or_vector : Error<
+ "address argument to nontemporal builtin must be a pointer to integer, float, "
+ "pointer, or a vector of such types (%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_kern_call_not_global_function : Error<
+ "kernel call to non-global function %0">;
+def err_global_call_not_config : Error<
+ "call to global function %0 not configured">;
+def err_ref_bad_target : Error<
+ "reference to %select{__device__|__global__|__host__|__host__ __device__}0 "
+ "function %1 in %select{__device__|__global__|__host__|__host__ __device__}2 function">;
+def warn_host_calls_from_host_device : Warning<
+ "calling __host__ function %0 from __host__ __device__ function %1 can lead to runtime errors">,
+ InGroup<CudaCompat>;
+
+def warn_non_pod_vararg_with_format_string : Warning<
+ "cannot pass %select{non-POD|non-trivial}0 object of type %1 to variadic "
+ "%select{function|block|method|constructor}2; expected type from format "
+ "string was %3">, InGroup<NonPODVarargs>, DefaultError;
+// The arguments to this diagnostic should match the warning above.
+def err_cannot_pass_objc_interface_to_vararg_format : Error<
+ "cannot pass object with interface type %1 by value to variadic "
+ "%select{function|block|method|constructor}2; expected type from format "
+ "string was %3">;
+
+def err_cannot_pass_objc_interface_to_vararg : Error<
+ "cannot pass object with interface type %0 by value through variadic "
+ "%select{function|block|method|constructor}1">;
+def warn_cannot_pass_non_pod_arg_to_vararg : Warning<
+ "cannot pass object of %select{non-POD|non-trivial}0 type %1 through variadic"
+ " %select{function|block|method|constructor}2; call will abort at runtime">,
+ InGroup<NonPODVarargs>, DefaultError;
+def warn_cxx98_compat_pass_non_pod_arg_to_vararg : Warning<
+ "passing object of trivial but non-POD type %0 through variadic"
+ " %select{function|block|method|constructor}1 is incompatible with C++98">,
+ InGroup<CXX98Compat>, DefaultIgnore;
+def warn_pass_class_arg_to_vararg : Warning<
+ "passing object of class type %0 through variadic "
+ "%select{function|block|method|constructor}1"
+ "%select{|; did you mean to call '%3'?}2">,
+ InGroup<ClassVarargs>, DefaultIgnore;
+def err_cannot_pass_to_vararg : Error<
+ "cannot pass %select{expression of type %1|initializer list}0 to variadic "
+ "%select{function|block|method|constructor}2">;
+def err_cannot_pass_to_vararg_format : Error<
+ "cannot pass %select{expression of type %1|initializer list}0 to variadic "
+ "%select{function|block|method|constructor}2; expected type from format "
+ "string was %3">;
+
+def err_typecheck_call_invalid_ordered_compare : Error<
+ "ordered compare requires two args of floating point type"
+ "%diff{ ($ and $)|}0,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_int_float : Error<
+ "used type %0 where integer or floating point type is required">;
+def err_typecheck_cond_expect_scalar : Error<
+ "used type %0 where arithmetic or pointer type is required">;
+def err_typecheck_cond_expect_nonfloat : Error<
+ "used type %0 where floating point type is not allowed">;
+def ext_typecheck_cond_one_void : Extension<
+ "C99 forbids conditional expressions with only one void side">;
+def err_typecheck_cast_to_incomplete : Error<
+ "cast to incomplete type %0">;
+def ext_typecheck_cast_nonscalar : Extension<
+ "C99 forbids casting nonscalar type %0 to the same type">;
+def ext_typecheck_cast_to_union : Extension<
+ "cast to union type is a GNU extension">,
+ InGroup<GNUUnionCast>;
+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 warn_cast_pointer_from_sel : Warning<
+ "cast of type %0 to %1 is deprecated; use sel_getName instead">,
+ InGroup<SelTypeCast>;
+def warn_function_def_in_objc_container : Warning<
+ "function definition inside an Objective-C container is deprecated">,
+ InGroup<FunctionDefInObjCContainer>;
+
+def warn_bad_function_cast : Warning<
+ "cast from function call of type %0 to non-matching type %1">,
+ InGroup<BadFunctionCast>, DefaultIgnore;
+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%diff{ ($ and $)|}0,1">;
+def ext_typecheck_cond_incompatible_operands_nonstandard : ExtWarn<
+ "incompatible operand types%diff{ ($ and $)|}0,1 use non-standard composite "
+ "pointer type %2">;
+def err_cast_selector_expr : Error<
+ "cannot type cast @selector expression">;
+def ext_typecheck_cond_incompatible_pointers : ExtWarn<
+ "pointer type mismatch%diff{ ($ and $)|}0,1">,
+ InGroup<DiagGroup<"pointer-type-mismatch">>;
+def ext_typecheck_cond_pointer_integer_mismatch : ExtWarn<
+ "pointer/integer type mismatch in conditional expression"
+ "%diff{ ($ and $)|}0,1">,
+ InGroup<DiagGroup<"conditional-type-mismatch">>;
+def err_typecheck_choose_expr_requires_constant : Error<
+ "'__builtin_choose_expr' requires a constant expression">;
+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<UnusedGetterReturnValue>;
+def warn_unused_container_subscript_expr : Warning<
+ "container access result unused - container access 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 warn_side_effects_unevaluated_context : Warning<
+ "expression with side effects has no effect in an unevaluated context">,
+ InGroup<UnevaluatedExpression>;
+def warn_side_effects_typeid : Warning<
+ "expression with side effects will be evaluated despite being used as an "
+ "operand to 'typeid'">, InGroup<PotentiallyEvaluatedExpression>;
+def warn_unused_result : Warning<
+ "ignoring return value of function declared with warn_unused_result "
+ "attribute">, InGroup<DiagGroup<"unused-result">>;
+def warn_unused_volatile : Warning<
+ "expression result unused; assign into a variable to force a volatile load">,
+ InGroup<DiagGroup<"unused-volatile-lvalue">>;
+
+def warn_unused_comparison : Warning<
+ "%select{%select{|in}1equality|relational}0 comparison result unused">,
+ InGroup<UnusedComparison>;
+def note_inequality_comparison_to_or_assign : Note<
+ "use '|=' to turn this inequality comparison into an or-assignment">;
+
+def err_incomplete_type_used_in_type_trait_expr : Error<
+ "incomplete type %0 used in type trait expression">;
+
+def err_dimension_expr_not_constant_integer : Error<
+ "dimension expression does not evaluate to a constant unsigned int">;
+
+def err_typecheck_cond_incompatible_operands_null : Error<
+ "non-pointer operand type %0 incompatible with %select{NULL|nullptr}1">;
+def ext_empty_struct_union : Extension<
+ "empty %select{struct|union}0 is a GNU extension">, InGroup<GNUEmptyStruct>;
+def ext_no_named_members_in_struct_union : Extension<
+ "%select{struct|union}0 without named members is a GNU extension">, InGroup<GNUEmptyStruct>;
+def warn_zero_size_struct_union_compat : Warning<"%select{|empty }0"
+ "%select{struct|union}1 has size 0 in C, %select{size 1|non-zero size}2 in C++">,
+ InGroup<CXXCompat>, DefaultIgnore;
+def warn_zero_size_struct_union_in_extern_c : Warning<"%select{|empty }0"
+ "%select{struct|union}1 has size 0 in C, %select{size 1|non-zero size}2 in C++">,
+ InGroup<ExternCCompat>;
+def warn_cast_qual : Warning<"cast from %0 to %1 drops %select{const and "
+ "volatile qualifiers|const qualifier|volatile qualifier}2">,
+ InGroup<CastQual>, DefaultIgnore;
+def warn_cast_qual2 : Warning<"cast from %0 to %1 must have all intermediate "
+ "pointers const qualified to be safe">, InGroup<CastQual>, DefaultIgnore;
+def warn_redefine_extname_not_applied : Warning<
+ "#pragma redefine_extname is applicable to external C declarations only; "
+ "not applied to %select{function|variable}0 %1">,
+ InGroup<Pragmas>;
+} // End of general sema category.
+
+// inline asm.
+let CategoryName = "Inline Assembly Issue" in {
+ 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_immediate_expected : Error<"constraint '%0' expects "
+ "an integer constant expression">;
+ 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 "
+ "%diff{$ matching output with type $|}0,1">;
+ def err_asm_unexpected_constraint_alternatives : Error<
+ "asm constraint has an unexpected number of alternatives: %0 vs %1">;
+ def err_asm_incomplete_type : Error<"asm operand has incomplete type %0">;
+ def err_asm_unknown_register_name : Error<"unknown register name '%0' in asm">;
+ def err_asm_invalid_global_var_reg : Error<"register '%0' unsuitable for "
+ "global register variables on this target">;
+ def err_asm_register_size_mismatch : Error<"size of register '%0' does not "
+ "match variable size">;
+ def err_asm_bad_register_type : Error<"bad type for named register variable">;
+ def err_asm_invalid_input_size : Error<
+ "invalid input size for constraint '%0'">;
+ def err_asm_invalid_output_size : Error<
+ "invalid output size for constraint '%0'">;
+ 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 err_invalid_asm_value_for_constraint
+ : Error <"value '%0' out of range for constraint '%1'">;
+ def err_asm_non_addr_value_in_memory_constraint : Error <
+ "reference to a %select{bit-field|vector element|global register variable}0"
+ " in asm %select{input|output}1 with a memory constraint '%2'">;
+ def err_asm_input_duplicate_match : Error<
+ "more than one input constraint matches the same output '%0'">;
+
+ def warn_asm_label_on_auto_decl : Warning<
+ "ignored asm label '%0' on automatic variable">;
+ def warn_invalid_asm_cast_lvalue : Warning<
+ "invalid use of a cast in an inline asm context requiring an l-value: "
+ "accepted due to -fheinous-gnu-extensions, but clang may remove support "
+ "for this in the future">;
+ def warn_asm_mismatched_size_modifier : Warning<
+ "value size does not match register size specified by the constraint "
+ "and modifier">,
+ InGroup<ASMOperandWidths>;
+
+ def note_asm_missing_constraint_modifier : Note<
+ "use constraint modifier \"%0\"">;
+ def note_asm_input_duplicate_first : Note<
+ "constraint '%0' is already present here">;
+}
+
+let CategoryName = "Semantic Issue" in {
+
+def err_invalid_conversion_between_vectors : Error<
+ "invalid conversion between vector type%diff{ $ and $|}0,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_opencl_function_pointer_variable : Error<
+ "pointers to functions are not allowed">;
+
+def err_opencl_taking_function_address : Error<
+ "taking address of function is not allowed">;
+
+def err_invalid_conversion_between_vector_and_scalar : Error<
+ "invalid conversion between vector type %0 and scalar type %1">;
+
+// 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 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 warn_abstract_vbase_init_ignored : Warning<
+ "initializer for virtual base class %0 of abstract class %1 "
+ "will never be used">,
+ InGroup<DiagGroup<"abstract-vbase-init">>, 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_volatile : Error<
+ "static const volatile 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 GNU extension">,
+ InGroup<GNUStaticFloatInit>;
+def ext_in_class_initializer_float_type_cxx11 : ExtWarn<
+ "in-class initializer for static data member of type %0 requires "
+ "'constexpr' specifier">, InGroup<StaticFloatInit>, DefaultError;
+def note_in_class_initializer_float_type_cxx11 : Note<"add 'constexpr'">;
+def err_in_class_initializer_literal_type : Error<
+ "in-class initializer for static data member of type %0 requires "
+ "'constexpr' specifier">;
+def err_in_class_initializer_non_constant : Error<
+ "in-class initializer for static data member is not a constant expression">;
+def err_in_class_initializer_not_yet_parsed
+ : Error<"cannot use defaulted default constructor of %0 within the class "
+ "outside of member functions because %1 has an initializer">;
+def err_in_class_initializer_not_yet_parsed_outer_class
+ : Error<"cannot use defaulted default constructor of %0 within "
+ "%1 outside of member functions because %2 has an initializer">;
+
+def ext_in_class_initializer_non_constant : Extension<
+ "in-class initializer for static data member is not a constant expression; "
+ "folding it to a constant is a GNU extension">, InGroup<GNUFoldingConstant>;
+
+def err_thread_dynamic_init : Error<
+ "initializer for thread-local variable must be a constant expression">;
+def err_thread_nontrivial_dtor : Error<
+ "type of thread-local variable has non-trivial destruction">;
+def note_use_thread_local : Note<
+ "use 'thread_local' to allow this">;
+
+// C++ anonymous unions and GNU anonymous structs/unions
+def ext_anonymous_union : Extension<
+ "anonymous unions are a C11 extension">, InGroup<C11>;
+def ext_gnu_anonymous_struct : Extension<
+ "anonymous structs are a GNU extension">, InGroup<GNUAnonymousStruct>;
+def ext_c11_anonymous_struct : Extension<
+ "anonymous structs are a C11 extension">, InGroup<C11>;
+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_record_member_redecl : Error<
+ "member of anonymous %select{struct|union}0 redeclares %1">;
+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<MicrosoftAnonTag>;
+def ext_anonymous_record_with_anonymous_type : Extension<
+ "anonymous types declared in an anonymous %select{struct|union}0 "
+ "are an extension">, InGroup<DiagGroup<"nested-anon-types">>;
+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_record : ExtWarn<
+ "anonymous %select{structs|unions}0 are a Microsoft extension">,
+ InGroup<MicrosoftAnonTag>;
+
+// C++ local classes
+def err_reference_to_local_var_in_enclosing_function : Error<
+ "reference to local variable %0 declared in enclosing function %1">;
+def err_reference_to_local_var_in_enclosing_block : Error<
+ "reference to local variable %0 declared in enclosing block literal">;
+def err_reference_to_local_var_in_enclosing_lambda : Error<
+ "reference to local variable %0 declared in enclosing lambda expression">;
+def err_reference_to_local_var_in_enclosing_context : Error<
+ "reference to local variable %0 declared in enclosing context">;
+
+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_circular_inheritance : Error<
+ "circular inheritance between %0 and %1">;
+def err_base_class_has_flexible_array_member : Error<
+ "base class %0 has a flexible array member">;
+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">;
+def warn_inaccessible_base_class : Warning<
+ "direct base %0 is inaccessible due to ambiguity:%1">,
+ InGroup<DiagGroup<"inaccessible-base">>;
+// 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++ 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 ext_operator_new_delete_declared_inline : ExtWarn<
+ "replacement function %0 cannot be declared 'inline'">,
+ InGroup<DiagGroup<"inline-new-delete">>;
+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 warn_operator_new_returns_null : Warning<
+ "%0 should not return a null pointer unless it is declared 'throw()'"
+ "%select{| or 'noexcept'}1">, InGroup<OperatorNewReturnsNull>;
+
+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">;
+def err_literal_operator_id_outside_namespace : Error<
+ "non-namespace scope '%0' cannot have a literal operator member">;
+def err_literal_operator_default_argument : Error<
+ "literal operator cannot have a default argument">;
+// FIXME: This diagnostic sucks
+def err_literal_operator_params : Error<
+ "parameter declaration for literal operator %0 is not valid">;
+def err_literal_operator_extern_c : Error<
+ "literal operator must have C++ linkage">;
+def ext_string_literal_operator_template : ExtWarn<
+ "string literal operator templates are a GNU extension">,
+ InGroup<GNUStringLiteralOperatorTemplate>;
+def warn_user_literal_reserved : Warning<
+ "user-defined literal suffixes not starting with '_' are reserved"
+ "%select{; no literal will invoke this operator|}0">,
+ InGroup<UserDefinedLiterals>;
+
+// 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<
+ "cannot specify any part of a return type in the "
+ "declaration of a conversion function"
+ "%select{"
+ "; put the complete type after 'operator'|"
+ "; use a typedef to declare a conversion to %1|"
+ "; use an alias template to declare a conversion to %1|"
+ "}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++11 explicit conversion operators
+def ext_explicit_conversion_functions : ExtWarn<
+ "explicit conversion functions are a C++11 extension">, InGroup<CXX11>;
+def warn_cxx98_compat_explicit_conversion_functions : Warning<
+ "explicit conversion functions are incompatible with C++98">,
+ InGroup<CXX98Compat>, DefaultIgnore;
+
+// C++11 defaulted functions
+def err_defaulted_special_member_params : Error<
+ "an explicitly-defaulted %select{|copy |move }0constructor cannot "
+ "have default arguments">;
+def err_defaulted_special_member_variadic : Error<
+ "an explicitly-defaulted %select{|copy |move }0constructor cannot "
+ "be variadic">;
+def err_defaulted_special_member_return_type : Error<
+ "explicitly-defaulted %select{copy|move}0 assignment operator must "
+ "return %1">;
+def err_defaulted_special_member_quals : Error<
+ "an explicitly-defaulted %select{copy|move}0 assignment operator may not "
+ "have 'const'%select{, 'constexpr'|}1 or 'volatile' qualifiers">;
+def err_defaulted_special_member_volatile_param : Error<
+ "the parameter for an explicitly-defaulted %select{<<ERROR>>|"
+ "copy constructor|move constructor|copy assignment operator|"
+ "move assignment operator|<<ERROR>>}0 may not be volatile">;
+def err_defaulted_special_member_move_const_param : Error<
+ "the parameter for an explicitly-defaulted move "
+ "%select{constructor|assignment operator}0 may not be const">;
+def err_defaulted_special_member_copy_const_param : Error<
+ "the parameter for this explicitly-defaulted copy "
+ "%select{constructor|assignment operator}0 is const, but a member or base "
+ "requires it to be non-const">;
+def err_defaulted_copy_assign_not_ref : Error<
+ "the parameter for an explicitly-defaulted copy assignment operator must be an "
+ "lvalue reference type">;
+def err_incorrect_defaulted_exception_spec : Error<
+ "exception specification of explicitly defaulted %select{default constructor|"
+ "copy constructor|move constructor|copy assignment operator|move assignment "
+ "operator|destructor}0 does not match the "
+ "calculated one">;
+def err_incorrect_defaulted_constexpr : Error<
+ "defaulted definition of %select{default constructor|copy constructor|"
+ "move constructor|copy assignment operator|move assignment operator}0 "
+ "is not constexpr">;
+def err_out_of_line_default_deletes : Error<
+ "defaulting this %select{default constructor|copy constructor|move "
+ "constructor|copy assignment operator|move assignment operator|destructor}0 "
+ "would delete it after its first declaration">;
+def warn_vbase_moved_multiple_times : Warning<
+ "defaulted move assignment operator of %0 will move assign virtual base "
+ "class %1 multiple times">, InGroup<DiagGroup<"multiple-move-vbase">>;
+def note_vbase_moved_here : Note<
+ "%select{%1 is a virtual base class of base class %2 declared here|"
+ "virtual base class %1 declared here}0">;
+
+def ext_implicit_exception_spec_mismatch : ExtWarn<
+ "function previously declared with an %select{explicit|implicit}0 exception "
+ "specification redeclared with an %select{implicit|explicit}0 exception "
+ "specification">, InGroup<DiagGroup<"implicit-exception-spec-mismatch">>;
+
+def warn_ptr_arith_precedes_bounds : Warning<
+ "the pointer decremented by %0 refers before the beginning of the array">,
+ InGroup<ArrayBoundsPointerArithmetic>, DefaultIgnore;
+def warn_ptr_arith_exceeds_bounds : Warning<
+ "the pointer incremented by %0 refers past the end of the array (that "
+ "contains %1 element%s2)">,
+ InGroup<ArrayBoundsPointerArithmetic>, DefaultIgnore;
+def warn_array_index_precedes_bounds : Warning<
+ "array index %0 is before the beginning of the array">,
+ InGroup<ArrayBounds>;
+def warn_array_index_exceeds_bounds : Warning<
+ "array index %0 is past the end of the array (which contains %1 "
+ "element%s2)">, InGroup<ArrayBounds>;
+def note_array_index_out_of_bounds : Note<
+ "array %0 declared here">;
+
+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<FormatInvalidSpecifier>;
+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_format_conversion_argument_type_mismatch : Warning<
+ "format specifies type %0 but the argument has "
+ "%select{type|underlying type}2 %1">,
+ InGroup<Format>;
+def warn_format_conversion_argument_type_mismatch_pedantic : Extension<
+ "format specifies type %0 but the argument has "
+ "%select{type|underlying type}2 %1">,
+ InGroup<FormatPedantic>;
+def warn_format_argument_needs_cast : Warning<
+ "%select{values of type|enum values with underlying type}2 '%0' should not "
+ "be used as format arguments; add an explicit cast to %1 instead">,
+ 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_static_array_too_small : Warning<
+ "array argument is too small; contains %0 elements, callee requires at least %1">,
+ InGroup<ArrayBounds>;
+def note_callee_static_array : Note<
+ "callee declares array parameter as static here">;
+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_format_string_not_null_terminated : Warning<
+ "format string is not null-terminated">, InGroup<Format>;
+def warn_printf_asterisk_missing_arg : Warning<
+ "'%select{*|.*}0' specified field %select{width|precision}0 is missing a matching 'int' argument">,
+ InGroup<Format>;
+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_format_non_standard_positional_arg: Warning<
+ "positional arguments are not supported by ISO C">, InGroup<FormatNonStandard>, DefaultIgnore;
+def warn_format_non_standard: Warning<
+ "'%0' %select{length modifier|conversion specifier}1 is not supported by ISO C">,
+ InGroup<FormatNonStandard>, DefaultIgnore;
+def warn_format_non_standard_conversion_spec: Warning<
+ "using length modifier '%0' with conversion specifier '%1' is not supported by ISO C">,
+ InGroup<FormatNonStandard>, DefaultIgnore;
+def warn_printf_ignored_flag: Warning<
+ "flag '%0' is ignored when flag '%1' is present">,
+ InGroup<Format>;
+def warn_printf_empty_objc_flag: Warning<
+ "missing object format flag">,
+ InGroup<Format>;
+def warn_printf_ObjCflags_without_ObjCConversion: Warning<
+ "object format flags cannot be used with '%0' conversion specifier">,
+ InGroup<Format>;
+def warn_printf_invalid_objc_flag: Warning<
+ "'%0' is not a valid object format flag">,
+ InGroup<Format>;
+def warn_scanf_scanlist_incomplete : Warning<
+ "no closing ']' for '%%[' in scanf format string">,
+ InGroup<Format>;
+def note_format_string_defined : Note<"format string is defined here">;
+def note_format_fix_specifier : Note<"did you mean to use '%0'?">;
+def note_printf_c_str: Note<"did you mean to call the %0 method?">;
+
+def warn_null_arg : Warning<
+ "null passed to a callee that requires a non-null argument">,
+ InGroup<NonNull>;
+def warn_null_ret : Warning<
+ "null returned from %select{function|method}0 that requires a non-null return value">,
+ InGroup<NonNull>;
+
+// CHECK: returning address/reference of stack memory
+def warn_ret_stack_addr_ref : Warning<
+ "%select{address of|reference to}0 stack memory associated with local "
+ "variable %1 returned">,
+ InGroup<ReturnStackAddress>;
+def warn_ret_local_temp_addr_ref : Warning<
+ "returning %select{address of|reference to}0 local temporary object">,
+ InGroup<ReturnStackAddress>;
+def warn_ret_addr_label : Warning<
+ "returning address of label, which is local">,
+ InGroup<ReturnStackAddress>;
+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">;
+
+// Check for initializing a member variable with the address or a reference to
+// a constructor parameter.
+def warn_bind_ref_member_to_parameter : Warning<
+ "binding reference member %0 to stack allocated parameter %1">,
+ InGroup<DanglingField>;
+def warn_init_ptr_member_to_parameter_addr : Warning<
+ "initializing pointer member %0 with the stack address of parameter %1">,
+ InGroup<DanglingField>;
+def warn_bind_ref_member_to_temporary : Warning<
+ "binding reference %select{|subobject of }1member %0 to a temporary value">,
+ InGroup<DanglingField>;
+def note_ref_or_ptr_member_declared_here : Note<
+ "%select{reference|pointer}0 member declared here">;
+def note_ref_subobject_of_member_declared_here : Note<
+ "member with reference subobject declared 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_comparison_bitwise_always : Warning<
+ "bitwise comparison always evaluates to %select{false|true}0">,
+ InGroup<TautologicalCompare>;
+def warn_tautological_overlap_comparison : Warning<
+ "overlapping comparisons always evaluate to %select{false|true}0">,
+ InGroup<TautologicalOverlapCompare>, DefaultIgnore;
+
+def warn_stringcompare : Warning<
+ "result of comparison against %select{a string literal|@encode}0 is "
+ "unspecified (use strncmp instead)">,
+ InGroup<StringCompare>;
+
+def warn_identity_field_assign : Warning<
+ "assigning %select{field|instance variable}0 to itself">,
+ InGroup<SelfAssignmentField>;
+
+// Type safety attributes
+def err_type_tag_for_datatype_not_ice : Error<
+ "'type_tag_for_datatype' attribute requires the initializer to be "
+ "an %select{integer|integral}0 constant expression">;
+def err_type_tag_for_datatype_too_large : Error<
+ "'type_tag_for_datatype' attribute requires the initializer to be "
+ "an %select{integer|integral}0 constant expression "
+ "that can be represented by a 64 bit integer">;
+def warn_type_tag_for_datatype_wrong_kind : Warning<
+ "this type tag was not designed to be used with this function">,
+ InGroup<TypeSafety>;
+def warn_type_safety_type_mismatch : Warning<
+ "argument type %0 doesn't match specified %1 type tag "
+ "%select{that requires %3|}2">, InGroup<TypeSafety>;
+def warn_type_safety_null_pointer_required : Warning<
+ "specified %0 type tag requires a null pointer">, InGroup<TypeSafety>;
+
+// Generic selections.
+def err_assoc_type_incomplete : Error<
+ "type %0 in generic association incomplete">;
+def err_assoc_type_nonobject : Error<
+ "type %0 in generic association not an object type">;
+def err_assoc_type_variably_modified : Error<
+ "type %0 in generic association is a variably modified type">;
+def err_assoc_compatible_types : Error<
+ "type %0 in generic association compatible with previously specified type %1">;
+def note_compat_assoc : Note<
+ "compatible type %0 specified here">;
+def err_generic_sel_no_match : Error<
+ "controlling expression type %0 not compatible with any generic association type">;
+def err_generic_sel_multi_match : Error<
+ "controlling expression type %0 compatible with %1 generic association types">;
+
+
+// Blocks
+def err_blocks_disable : Error<"blocks support disabled - compile with -fblocks"
+ " or pick a deployment target that supports them">;
+def err_block_returning_array_function : Error<
+ "block cannot return %select{array|function}0 type %1">;
+
+// Builtin annotation
+def err_builtin_annotation_first_arg : Error<
+ "first argument to __builtin_annotation must be an integer">;
+def err_builtin_annotation_second_arg : Error<
+ "second argument to __builtin_annotation must be a non-wide string constant">;
+
+// CFString checking
+def err_cfstring_literal_not_string_constant : Error<
+ "CFString literal is not a string constant">;
+def warn_cfstring_truncated : Warning<
+ "input conversion stopped due to an input byte that does not "
+ "belong to the input codeset UTF-8">,
+ InGroup<DiagGroup<"CFString-literal">>;
+
+// 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 warn_loop_ctrl_binds_to_inner : Warning<
+ "'%0' is bound to current loop, GCC binds it to the enclosing loop">,
+ InGroup<GccCompat>;
+def warn_break_binds_to_switch : Warning<
+ "'break' is bound to loop, GCC binds it to switch">,
+ InGroup<GccCompat>;
+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">, InGroup<SwitchBool>;
+def warn_case_value_overflow : Warning<
+ "overflow converting case value to switch condition type (%0 to %1)">,
+ InGroup<Switch>;
+def err_duplicate_case : Error<"duplicate case value '%0'">;
+def err_duplicate_case_differing_expr : Error<
+ "duplicate case value: '%0' and '%1' both equal '%2'">;
+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_def_missing_case : Warning<"%plural{"
+ "1:enumeration value %1 not explicitly handled in switch|"
+ "2:enumeration values %1 and %2 not explicitly handled in switch|"
+ "3:enumeration values %1, %2, and %3 not explicitly handled in switch|"
+ ":%0 enumeration values not explicitly handled in switch: %1, %2, %3...}0">,
+ InGroup<SwitchEnum>, DefaultIgnore;
+
+def warn_missing_case : Warning<"%plural{"
+ "1:enumeration value %1 not handled in switch|"
+ "2:enumeration values %1 and %2 not handled in switch|"
+ "3:enumeration values %1, %2, and %3 not handled in switch|"
+ ":%0 enumeration values not handled in switch: %1, %2, %3...}0">,
+ InGroup<Switch>;
+
+def warn_unannotated_fallthrough : Warning<
+ "unannotated fall-through between switch labels">,
+ InGroup<ImplicitFallthrough>, DefaultIgnore;
+def warn_unannotated_fallthrough_per_function : Warning<
+ "unannotated fall-through between switch labels in partly-annotated "
+ "function">, InGroup<ImplicitFallthroughPerFunction>, DefaultIgnore;
+def note_insert_fallthrough_fixit : Note<
+ "insert '%0;' to silence this warning">;
+def note_insert_break_fixit : Note<
+ "insert 'break;' to avoid fall-through">;
+def err_fallthrough_attr_wrong_target : Error<
+ "clang::fallthrough attribute is only allowed on empty statements">;
+def note_fallthrough_insert_semi_fixit : Note<"did you forget ';'?">;
+def err_fallthrough_attr_outside_switch : Error<
+ "fallthrough annotation is outside switch statement">;
+def warn_fallthrough_attr_invalid_placement : Warning<
+ "fallthrough annotation does not directly precede switch label">,
+ InGroup<ImplicitFallthrough>;
+def warn_fallthrough_attr_unreachable : Warning<
+ "fallthrough annotation in unreachable code">,
+ InGroup<ImplicitFallthrough>;
+
+def warn_unreachable_default : Warning<
+ "default label in switch which covers all enumeration values">,
+ InGroup<CoveredSwitchDefault>, DefaultIgnore;
+def warn_not_in_enum : Warning<"case value not in enumerated type %0">,
+ InGroup<Switch>;
+def warn_not_in_enum_assignment : Warning<"integer constant not in range "
+ "of enumerated type %0">, InGroup<DiagGroup<"assign-enum">>, DefaultIgnore;
+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 warn_empty_for_body : Warning<
+ "for loop has empty body">, InGroup<EmptyBody>;
+def warn_empty_range_based_for_body : Warning<
+ "range-based for loop has empty body">, InGroup<EmptyBody>;
+def warn_empty_while_body : Warning<
+ "while loop has empty body">, InGroup<EmptyBody>;
+def warn_empty_switch_body : Warning<
+ "switch statement has empty body">, InGroup<EmptyBody>;
+def note_empty_body_on_separate_line : Note<
+ "put the semicolon on a separate line to silence this warning">;
+
+def err_va_start_used_in_non_variadic_function : Error<
+ "'va_start' used in function with fixed args">;
+def err_va_start_used_in_wrong_abi_function : Error<
+ "'va_start' used in %select{System V|Win64}0 ABI function">;
+def err_ms_va_start_used_in_sysv_function : Error<
+ "'__builtin_ms_va_start' used in System V ABI function">;
+def warn_second_parameter_of_va_start_not_last_named_argument : Warning<
+ "second parameter of 'va_start' not last named argument">, InGroup<Varargs>;
+def warn_va_start_of_reference_type_is_undefined : Warning<
+ "'va_start' has undefined behavior with reference types">, InGroup<Varargs>;
+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 err_second_parameter_to_va_arg_incomplete: Error<
+ "second argument to 'va_arg' is of incomplete type %0">;
+def err_second_parameter_to_va_arg_abstract: Error<
+ "second argument to 'va_arg' is of abstract type %0">;
+def warn_second_parameter_to_va_arg_not_pod : Warning<
+ "second argument to 'va_arg' is of non-POD type %0">,
+ InGroup<NonPODVarargs>, DefaultError;
+def warn_second_parameter_to_va_arg_ownership_qualified : Warning<
+ "second argument to 'va_arg' is of ARC ownership-qualified type %0">,
+ InGroup<NonPODVarargs>, DefaultError;
+def warn_second_parameter_to_va_arg_never_compatible : Warning<
+ "second argument to 'va_arg' is of promotable type %0; this va_arg has "
+ "undefined behavior because arguments will be promoted to %1">, InGroup<Varargs>;
+
+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<
+ "%select{void function|void method|constructor|destructor}1 %0 "
+ "should not return a value">,
+ DefaultError, InGroup<ReturnType>;
+def ext_return_has_void_expr : Extension<
+ "void %select{function|method|block}1 %0 should not return void expression">;
+def err_return_init_list : Error<
+ "%select{void function|void method|constructor|destructor}1 %0 "
+ "must not return a value">;
+def err_ctor_dtor_returns_void : Error<
+ "%select{constructor|destructor}1 %0 must not return void expression">;
+def warn_noreturn_function_has_return_expr : Warning<
+ "function %0 declared 'noreturn' should not return">,
+ InGroup<InvalidNoreturn>;
+def warn_falloff_noreturn_function : Warning<
+ "function declared 'noreturn' should not return">,
+ InGroup<InvalidNoreturn>;
+def err_noreturn_block_has_return_expr : Error<
+ "block declared 'noreturn' should not return">;
+def err_noreturn_missing_on_first_decl : Error<
+ "function declared '[[noreturn]]' after its first declaration">;
+def note_noreturn_missing_first_decl : Note<
+ "declaration missing '[[noreturn]]' attribute is here">;
+def err_carries_dependency_missing_on_first_decl : Error<
+ "%select{function|parameter}0 declared '[[carries_dependency]]' "
+ "after its first declaration">;
+def note_carries_dependency_missing_first_decl : Note<
+ "declaration missing '[[carries_dependency]]' attribute is here">;
+def err_carries_dependency_param_not_function_decl : Error<
+ "'[[carries_dependency]]' attribute only allowed on parameter in a function "
+ "declaration or lambda">;
+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_convertvector_non_vector : Error<
+ "first argument to __builtin_convertvector must be a vector">;
+def err_convertvector_non_vector_type : Error<
+ "second argument to __builtin_convertvector must be a vector type">;
+def err_convertvector_incompatible_vector : Error<
+ "first two arguments to __builtin_convertvector must have the same number of elements">;
+
+def err_first_argument_to_cwsc_not_call : Error<
+ "first argument to __builtin_call_with_static_chain must be a non-member call expression">;
+def err_first_argument_to_cwsc_block_call : Error<
+ "first argument to __builtin_call_with_static_chain must not be a block call">;
+def err_first_argument_to_cwsc_builtin_call : Error<
+ "first argument to __builtin_call_with_static_chain must not be a builtin call">;
+def err_first_argument_to_cwsc_pdtor_call : Error<
+ "first argument to __builtin_call_with_static_chain must not be a pseudo-destructor call">;
+def err_second_argument_to_cwsc_not_pointer : Error<
+ "second argument to __builtin_call_with_static_chain must be of pointer type">;
+
+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 warn_neon_vector_initializer_non_portable : Warning<
+ "vector initializers are not compatible with NEON intrinsics in big endian "
+ "mode">, InGroup<DiagGroup<"nonportable-vector-initialization">>;
+def note_neon_vector_initializer_non_portable : Note<
+ "consider using vld1_%0%1() to initialize a vector from memory, or "
+ "vcreate_%0%1() to initialize from an integer constant">;
+def note_neon_vector_initializer_non_portable_q : Note<
+ "consider using vld1q_%0%1() to initialize a vector from memory, or "
+ "vcombine_%0%1(vcreate_%0%1(), vcreate_%0%1()) to initialize from integer "
+ "constants">;
+def err_systemz_invalid_tabort_code : Error<
+ "invalid transaction abort code">;
+def err_64_bit_builtin_32_bit_tgt : Error<
+ "this builtin is only available on 64-bit targets">;
+def err_ppc_builtin_only_on_pwr7 : Error<
+ "this builtin is only valid on POWER7 or later CPUs">;
+def err_x86_builtin_32_bit_tgt : Error<
+ "this builtin is only available on x86-64 targets">;
+
+def err_builtin_longjmp_unsupported : Error<
+ "__builtin_longjmp is not supported for the current target">;
+def err_builtin_setjmp_unsupported : Error<
+ "__builtin_setjmp is not supported for the current target">;
+
+def err_builtin_longjmp_invalid_val : Error<
+ "argument to __builtin_longjmp must be a constant 1">;
+def err_builtin_requires_language : Error<"'%0' is only available in %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_local_variable_decl_in_for : Error<
+ "declaration of non-local variable in 'for' loop">;
+def err_non_variable_decl_in_for : Error<
+ "non-variable declaration 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_selector_element_const_type : Error<
+ "selector element of type %0 cannot be a constant l-value expression">;
+def err_collection_expr_type : Error<
+ "the type %0 is not a pointer to a fast-enumerable 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">;
+
+def warn_duplicate_attribute_exact : Warning<
+ "attribute %0 is already applied">, InGroup<IgnoredAttributes>;
+
+def warn_duplicate_attribute : Warning<
+ "attribute %0 is already applied with different parameters">,
+ InGroup<IgnoredAttributes>;
+
+def warn_sync_fetch_and_nand_semantics_change : Warning<
+ "the semantics of this intrinsic changed with GCC "
+ "version 4.4 - the newer semantics are provided here">,
+ InGroup<DiagGroup<"sync-fetch-and-nand-semantics-changed">>;
+
+// 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">,
+ InGroup<ForwardClassReceiver>;
+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_objc_array_of_interfaces : Error<
+ "array of interface %0 is invalid (probably should be an array of pointers)">;
+def ext_c99_array_usage : Extension<
+ "%select{qualifier in |static |}0array size %select{||'[*] '}0is a C99 "
+ "feature">, InGroup<C99>;
+def err_c99_array_usage_cxx : Error<
+ "%select{qualifier in |static |}0array size %select{||'[*] '}0is a C99 "
+ "feature, not permitted in C++">;
+ def err_type_requires_extension : Error<
+ "use of type %0 requires %1 extension to be enabled">;
+def err_int128_unsupported : Error<
+ "__int128 is not supported on this target">;
+def err_nsconsumed_attribute_mismatch : Error<
+ "overriding method has mismatched ns_consumed attribute on its"
+ " parameter">;
+def err_nsreturns_retained_attribute_mismatch : Error<
+ "overriding method has mismatched ns_returns_%select{not_retained|retained}0"
+ " attributes">;
+
+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">,
+ InGroup<DiagGroup<"shadow-ivar">>;
+def warn_direct_initialize_call : Warning<
+ "explicit call to +initialize results in duplicate call to +initialize">,
+ InGroup<ExplicitInitializeCall>;
+def warn_direct_super_initialize_call : Warning<
+ "explicit call to [super initialize] should only be in implementation "
+ "of +initialize">,
+ InGroup<ExplicitInitializeCall>;
+def error_ivar_use_in_class_method : Error<
+ "instance variable %0 accessed in class method">;
+def error_implicit_ivar_access : Error<
+ "instance variable %0 cannot be accessed because 'self' has been redeclared">;
+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 ext_typecheck_base_super : Warning<
+ "method parameter type "
+ "%diff{$ does not match super class method parameter type $|"
+ "does not match super class method parameter type}0,1">,
+ InGroup<SuperSubClassMismatch>, DefaultIgnore;
+def warn_missing_method_return_type : Warning<
+ "method has no return type specified; defaults to 'id'">,
+ InGroup<MissingMethodReturnType>, DefaultIgnore;
+def warn_direct_ivar_access : Warning<"instance variable %0 is being "
+ "directly accessed">, InGroup<DiagGroup<"direct-ivar-access">>, DefaultIgnore;
+
+// Spell-checking diagnostics
+def err_unknown_typename : Error<
+ "unknown type name %0">;
+def err_unknown_type_or_class_name_suggest : Error<
+ "unknown %select{type|class}1 name %0; did you mean %2?">;
+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 %select{|simply }2%3?">;
+def err_no_member_suggest : Error<"no member named %0 in %1; did you mean %select{|simply }2%3?">;
+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 %select{|simply }2%3?">;
+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_ivar_access_using_property_syntax_suggest : Error<
+ "property %0 not found on object of type %1; did you mean to access instance variable %2?">;
+def warn_property_access_suggest : Warning<
+"property %0 not found on object of type %1; did you mean to access property %2?">,
+InGroup<PropertyAccessDotSyntax>;
+def err_property_found_suggest : Error<
+ "property %0 found on object of type %1; did you mean to access "
+ "it with the \".\" operator?">;
+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 %select{|simply }2%3?">;
+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">;
+
+def err_uncasted_use_of_unknown_any : Error<
+ "%0 has unknown type; cast it to its declared type to use it">;
+def err_uncasted_call_of_unknown_any : Error<
+ "%0 has unknown return type; cast the call to its declared return type">;
+def err_uncasted_send_to_unknown_any_method : Error<
+ "no known method %select{%objcinstance1|%objcclass1}0; cast the "
+ "message send to the method's return type">;
+def err_unsupported_unknown_any_decl : Error<
+ "%0 has unknown type, which is not supported for this kind of declaration">;
+def err_unsupported_unknown_any_expr : Error<
+ "unsupported expression with unknown type">;
+def err_unsupported_unknown_any_call : Error<
+ "call to unsupported expression with unknown type">;
+def err_unknown_any_addrof : Error<
+ "the address of a declaration with unknown type "
+ "can only be cast to a pointer type">;
+def err_unknown_any_var_function_type : Error<
+ "variable %0 with unknown type cannot be given a function type">;
+def err_unknown_any_function : Error<
+ "function %0 with unknown type must be given a function type">;
+
+def err_filter_expression_integral : Error<
+ "filter expression type should be an integral value not %0">;
+
+def err_non_asm_stmt_in_naked_function : Error<
+ "non-ASM statement in naked function is not supported">;
+def err_asm_naked_this_ref : Error<
+ "'this' pointer references not allowed in naked functions">;
+def err_asm_naked_parm_ref : Error<
+ "parameter references not allowed in naked functions">;
+
+def ext_deprecated_attr_is_a_cxx14_extension : ExtWarn<
+ "use of the 'deprecated' attribute is a C++14 extension">, InGroup<CXX14>;
+
+// OpenCL warnings and errors.
+def err_invalid_astype_of_different_size : Error<
+ "invalid reinterpretation: sizes of %0 and %1 must match">;
+def err_static_kernel : Error<
+ "kernel functions cannot be declared static">;
+def err_opencl_ptrptr_kernel_param : Error<
+ "kernel parameter cannot be declared as a pointer to a pointer">;
+def err_opencl_private_ptr_kernel_param : Error<
+ "kernel parameter cannot be declared as a pointer to the __private address space">;
+def err_opencl_non_kernel_variable : Error<
+ "non-kernel function variable cannot be declared in %0 address space">;
+def err_static_function_scope : Error<
+ "variables in function scope cannot be declared static">;
+def err_opencl_bitfields : Error<
+ "bitfields are not supported in OpenCL">;
+def err_opencl_vla : Error<
+ "variable length arrays are not supported in OpenCL">;
+def err_bad_kernel_param_type : Error<
+ "%0 cannot be used as the type of a kernel parameter">;
+def err_record_with_pointers_kernel_param : Error<
+ "%select{struct|union}0 kernel parameters may not contain pointers">;
+def note_within_field_of_type : Note<
+ "within field of type %0 declared here">;
+def note_illegal_field_declared_here : Note<
+ "field of illegal %select{type|pointer type}0 %1 declared here">;
+def err_event_t_global_var : Error<
+ "the event_t type cannot be used to declare a program scope variable">;
+def err_event_t_struct_field : Error<
+ "the event_t type cannot be used to declare a structure or union field">;
+def err_event_t_addr_space_qual : Error<
+ "the event_t type can only be used with __private address space qualifier">;
+def err_expected_kernel_void_return_type : Error<
+ "kernel must have void return type">;
+def err_sampler_argument_required : Error<
+ "sampler_t variable required - got %0">;
+def err_wrong_sampler_addressspace: Error<
+ "sampler type cannot be used with the __local and __global address space qualifiers">;
+def err_opencl_global_invalid_addr_space : Error<
+ "program scope variable must reside in %0 address space">;
+def err_opencl_no_main : Error<"%select{function|kernel}0 cannot be called 'main'">;
+def err_opencl_kernel_attr :
+ Error<"attribute %0 can only be applied to a kernel function">;
+def err_opencl_return_value_with_address_space : Error<
+ "return value cannot be qualified with address space">;
+def err_opencl_constant_no_init : Error<
+ "variable in constant address space must be initialized">;
+def err_atomic_init_constant : Error<
+ "atomic variable can only be assigned to a compile time constant"
+ " in the declaration statement in the program scope">;
+def err_opencl_implicit_vector_conversion : Error<
+ "implicit conversions between vector types (%0 and %1) are not permitted">;
+
+// OpenCL Section 6.8.g
+def err_opencl_unknown_type_specifier : Error<
+ "OpenCL does not support the '%0' %select{type qualifier|storage class specifier}1">;
+
+} // end of sema category
+
+let CategoryName = "OpenMP Issue" in {
+// OpenMP support.
+def err_omp_expected_var_arg : Error<
+ "%0 is not a global variable, static local variable or static data member">;
+def err_omp_expected_var_arg_suggest : Error<
+ "%0 is not a global variable, static local variable or static data member; "
+ "did you mean %1">;
+def err_omp_global_var_arg : Error<
+ "arguments of '#pragma omp %0' must have %select{global storage|static storage duration}1">;
+def err_omp_ref_type_arg : Error<
+ "arguments of '#pragma omp %0' cannot be of reference type %1">;
+def err_omp_var_scope : Error<
+ "'#pragma omp %0' must appear in the scope of the %q1 variable declaration">;
+def err_omp_var_used : Error<
+ "'#pragma omp %0' must precede all references to variable %q1">;
+def err_omp_var_thread_local : Error<
+ "variable %0 cannot be threadprivate because it is %select{thread-local|a global named register variable}1">;
+def err_omp_private_incomplete_type : Error<
+ "a private variable with incomplete type %0">;
+def err_omp_firstprivate_incomplete_type : Error<
+ "a firstprivate variable with incomplete type %0">;
+def err_omp_lastprivate_incomplete_type : Error<
+ "a lastprivate variable with incomplete type %0">;
+def err_omp_reduction_incomplete_type : Error<
+ "a reduction list item with incomplete type %0">;
+def err_omp_unexpected_clause_value : Error<
+ "expected %0 in OpenMP clause '%1'">;
+def err_omp_expected_var_name : Error<
+ "expected variable name">;
+def err_omp_expected_var_name_or_array_item : Error<
+ "expected variable name, array element or array section">;
+def note_omp_task_predetermined_firstprivate_here : Note<
+ "predetermined as a firstprivate in a task construct here">;
+def err_omp_threadprivate_incomplete_type : Error<
+ "threadprivate variable with incomplete type %0">;
+def err_omp_no_dsa_for_variable : Error<
+ "variable %0 must have explicitly specified data sharing attributes">;
+def err_omp_wrong_dsa : Error<
+ "%0 variable cannot be %1">;
+def err_omp_variably_modified_type_not_supported : Error<
+ "arguments of OpenMP clause '%0' in '#pragma omp %2' directive cannot be of variably-modified type %1">;
+def note_omp_explicit_dsa : Note<
+ "defined as %0">;
+def note_omp_predetermined_dsa : Note<
+ "%select{static data member is predetermined as shared|"
+ "variable with static storage duration is predetermined as shared|"
+ "loop iteration variable is predetermined as private|"
+ "loop iteration variable is predetermined as linear|"
+ "loop iteration variable is predetermined as lastprivate|"
+ "constant variable is predetermined as shared|"
+ "global variable is predetermined as shared|"
+ "non-shared variable in a task construct is predetermined as firstprivate|"
+ "variable with automatic storage duration is predetermined as private}0"
+ "%select{|; perhaps you forget to enclose 'omp %2' directive into a parallel or another task region?}1">;
+def note_omp_implicit_dsa : Note<
+ "implicitly determined as %0">;
+def err_omp_loop_var_dsa : Error<
+ "loop iteration variable in the associated loop of 'omp %1' directive may not be %0, predetermined as %2">;
+def err_omp_not_for : Error<
+ "%select{statement after '#pragma omp %1' must be a for loop|"
+ "expected %2 for loops after '#pragma omp %1'%select{|, but found only %4}3}0">;
+def note_omp_collapse_ordered_expr : Note<
+ "as specified in %select{'collapse'|'ordered'|'collapse' and 'ordered'}0 clause%select{||s}0">;
+def err_omp_negative_expression_in_clause : Error<
+ "argument to '%0' clause must be a %select{non-negative|strictly positive}1 integer value">;
+def err_omp_not_integral : Error<
+ "expression must have integral or unscoped enumeration "
+ "type, not %0">;
+def err_omp_incomplete_type : Error<
+ "expression has incomplete class type %0">;
+def err_omp_explicit_conversion : Error<
+ "expression requires explicit conversion from %0 to %1">;
+def note_omp_conversion_here : Note<
+ "conversion to %select{integral|enumeration}0 type %1 declared here">;
+def err_omp_ambiguous_conversion : Error<
+ "ambiguous conversion from type %0 to an integral or unscoped "
+ "enumeration type">;
+def err_omp_required_access : Error<
+ "%0 variable must be %1">;
+def err_omp_const_variable : Error<
+ "const-qualified variable cannot be %0">;
+def err_omp_const_reduction_list_item : Error<
+ "const-qualified list item cannot be reduction">;
+def err_omp_linear_incomplete_type : Error<
+ "a linear variable with incomplete type %0">;
+def err_omp_linear_expected_int_or_ptr : Error<
+ "argument of a linear clause should be of integral or pointer "
+ "type, not %0">;
+def warn_omp_linear_step_zero : Warning<
+ "zero linear step (%0 %select{|and other variables in clause }1should probably be const)">,
+ InGroup<OpenMPClauses>;
+def warn_omp_alignment_not_power_of_two : Warning<
+ "aligned clause will be ignored because the requested alignment is not a power of 2">,
+ InGroup<OpenMPClauses>;
+def err_omp_aligned_expected_array_or_ptr : Error<
+ "argument of aligned clause should be array"
+ "%select{ or pointer|, pointer, reference to array or reference to pointer}1"
+ ", not %0">;
+def err_omp_aligned_twice : Error<
+ "a variable cannot appear in more than one aligned clause">;
+def err_omp_local_var_in_threadprivate_init : Error<
+ "variable with local storage in initial value of threadprivate variable">;
+def err_omp_loop_not_canonical_init : Error<
+ "initialization clause of OpenMP for loop is not in canonical form "
+ "('var = init' or 'T var = init')">;
+def ext_omp_loop_not_canonical_init : ExtWarn<
+ "initialization clause of OpenMP for loop is not in canonical form "
+ "('var = init' or 'T var = init')">, InGroup<OpenMPLoopForm>;
+def err_omp_loop_not_canonical_cond : Error<
+ "condition of OpenMP for loop must be a relational comparison "
+ "('<', '<=', '>', or '>=') of loop variable %0">;
+def err_omp_loop_not_canonical_incr : Error<
+ "increment clause of OpenMP for loop must perform simple addition "
+ "or subtraction on loop variable %0">;
+def err_omp_loop_variable_type : Error<
+ "variable must be of integer or %select{pointer|random access iterator}0 type">;
+def err_omp_loop_incr_not_compatible : Error<
+ "increment expression must cause %0 to %select{decrease|increase}1 "
+ "on each iteration of OpenMP for loop">;
+def note_omp_loop_cond_requres_compatible_incr : Note<
+ "loop step is expected to be %select{negative|positive}0 due to this condition">;
+def err_omp_loop_diff_cxx : Error<
+ "could not calculate number of iterations calling 'operator-' with "
+ "upper and lower loop bounds">;
+def err_omp_loop_cannot_use_stmt : Error<
+ "'%0' statement cannot be used in OpenMP for loop">;
+def err_omp_simd_region_cannot_use_stmt : Error<
+ "'%0' statement cannot be used in OpenMP simd region">;
+def warn_omp_loop_64_bit_var : Warning<
+ "OpenMP loop iteration variable cannot have more than 64 bits size and will be narrowed">,
+ InGroup<OpenMPLoopForm>;
+def err_omp_unknown_reduction_identifier : Error<
+ "incorrect reduction identifier, expected one of '+', '-', '*', '&', '|', '^', '&&', '||', 'min' or 'max'">;
+def err_omp_reduction_type_array : Error<
+ "a reduction list item with array type %0">;
+def err_omp_reduction_ref_type_arg : Error<
+ "argument of OpenMP clause 'reduction' must reference the same object in all threads">;
+def err_omp_clause_not_arithmetic_type_arg : Error<
+ "arguments of OpenMP clause 'reduction' for 'min' or 'max' must be of %select{scalar|arithmetic}0 type">;
+def err_omp_clause_floating_type_arg : Error<
+ "arguments of OpenMP clause 'reduction' with bitwise operators cannot be of floating type">;
+def err_omp_once_referenced : Error<
+ "variable can appear only once in OpenMP '%0' clause">;
+def note_omp_referenced : Note<
+ "previously referenced here">;
+def err_omp_reduction_in_task : Error<
+ "reduction variables may not be accessed in an explicit task">;
+def err_omp_reduction_id_not_compatible : Error<
+ "list item of type %0 is not valid for specified reduction operation: unable to provide default initialization value">;
+def err_omp_prohibited_region : Error<
+ "region cannot be%select{| closely}0 nested inside '%1' region"
+ "%select{|; perhaps you forget to enclose 'omp %3' directive into a parallel region?|"
+ "; perhaps you forget to enclose 'omp %3' directive into a for or a parallel for region with 'ordered' clause?|"
+ "; perhaps you forget to enclose 'omp %3' directive into a target region?|"
+ "; perhaps you forget to enclose 'omp %3' directive into a teams region?}2">;
+def err_omp_prohibited_region_simd : Error<
+ "OpenMP constructs may not be nested inside a simd region">;
+def err_omp_prohibited_region_atomic : Error<
+ "OpenMP constructs may not be nested inside an atomic region">;
+def err_omp_prohibited_region_critical_same_name : Error<
+ "cannot nest 'critical' regions having the same name %0">;
+def note_omp_previous_critical_region : Note<
+ "previous 'critical' region starts here">;
+def err_omp_sections_not_compound_stmt : Error<
+ "the statement for '#pragma omp sections' must be a compound statement">;
+def err_omp_parallel_sections_not_compound_stmt : Error<
+ "the statement for '#pragma omp parallel sections' must be a compound statement">;
+def err_omp_orphaned_section_directive : Error<
+ "%select{orphaned 'omp section' directives are prohibited, it|'omp section' directive}0"
+ " must be closely nested to a sections region%select{|, not a %1 region}0">;
+def err_omp_sections_substmt_not_section : Error<
+ "statement in 'omp sections' directive must be enclosed into a section region">;
+def err_omp_parallel_sections_substmt_not_section : Error<
+ "statement in 'omp parallel sections' directive must be enclosed into a section region">;
+def err_omp_parallel_reduction_in_task_firstprivate : Error<
+ "argument of a reduction clause of a %0 construct must not appear in a firstprivate clause on a task construct">;
+def err_omp_atomic_read_not_expression_statement : Error<
+ "the statement for 'atomic read' must be an expression statement of form 'v = x;',"
+ " where v and x are both lvalue expressions with scalar type">;
+def note_omp_atomic_read_write: Note<
+ "%select{expected an expression statement|expected built-in assignment operator|expected expression of scalar type|expected lvalue expression}0">;
+def err_omp_atomic_write_not_expression_statement : Error<
+ "the statement for 'atomic write' must be an expression statement of form 'x = expr;',"
+ " where x is a lvalue expression with scalar type">;
+def err_omp_atomic_update_not_expression_statement : Error<
+ "the statement for 'atomic update' must be an expression statement of form '++x;', '--x;', 'x++;', 'x--;', 'x binop= expr;', 'x = x binop expr' or 'x = expr binop x',"
+ " where x is an l-value expression with scalar type">;
+def err_omp_atomic_not_expression_statement : Error<
+ "the statement for 'atomic' must be an expression statement of form '++x;', '--x;', 'x++;', 'x--;', 'x binop= expr;', 'x = x binop expr' or 'x = expr binop x',"
+ " where x is an l-value expression with scalar type">;
+def note_omp_atomic_update: Note<
+ "%select{expected an expression statement|expected built-in binary or unary operator|expected unary decrement/increment operation|"
+ "expected expression of scalar type|expected assignment expression|expected built-in binary operator|"
+ "expected one of '+', '*', '-', '/', '&', '^', '%|', '<<', or '>>' built-in operations|expected in right hand side of expression}0">;
+def err_omp_atomic_capture_not_expression_statement : Error<
+ "the statement for 'atomic capture' must be an expression statement of form 'v = ++x;', 'v = --x;', 'v = x++;', 'v = x--;', 'v = x binop= expr;', 'v = x = x binop expr' or 'v = x = expr binop x',"
+ " where x and v are both l-value expressions with scalar type">;
+def err_omp_atomic_capture_not_compound_statement : Error<
+ "the statement for 'atomic capture' must be a compound statement of form '{v = x; x binop= expr;}', '{x binop= expr; v = x;}',"
+ " '{v = x; x = x binop expr;}', '{v = x; x = expr binop x;}', '{x = x binop expr; v = x;}', '{x = expr binop x; v = x;}' or '{v = x; x = expr;}',"
+ " '{v = x; x++;}', '{v = x; ++x;}', '{++x; v = x;}', '{x++; v = x;}', '{v = x; x--;}', '{v = x; --x;}', '{--x; v = x;}', '{x--; v = x;}'"
+ " where x is an l-value expression with scalar type">;
+def note_omp_atomic_capture: Note<
+ "%select{expected assignment expression|expected compound statement|expected exactly two expression statements|expected in right hand side of the first expression}0">;
+def err_omp_atomic_several_clauses : Error<
+ "directive '#pragma omp atomic' cannot contain more than one 'read', 'write', 'update' or 'capture' clause">;
+def note_omp_atomic_previous_clause : Note<
+ "'%0' clause used here">;
+def err_omp_target_contains_not_only_teams : Error<
+ "target construct with nested teams region contains statements outside of the teams construct">;
+def note_omp_nested_teams_construct_here : Note<
+ "nested teams construct here">;
+def note_omp_nested_statement_here : Note<
+ "%select{statement|directive}0 outside teams construct here">;
+def err_omp_single_copyprivate_with_nowait : Error<
+ "the 'copyprivate' clause must not be used with the 'nowait' clause">;
+def note_omp_nowait_clause_here : Note<
+ "'nowait' clause is here">;
+def err_omp_wrong_cancel_region : Error<
+ "one of 'for', 'parallel', 'sections' or 'taskgroup' is expected">;
+def err_omp_parent_cancel_region_nowait : Error<
+ "parent region for 'omp %select{cancellation point/cancel}0' construct cannot be nowait">;
+def err_omp_parent_cancel_region_ordered : Error<
+ "parent region for 'omp %select{cancellation point/cancel}0' construct cannot be ordered">;
+def err_omp_array_section_use : Error<"OpenMP array section is not allowed here">;
+def err_omp_typecheck_section_value : Error<
+ "subscripted value is not an array or pointer">;
+def err_omp_typecheck_section_not_integer : Error<
+ "array section %select{lower bound|length}0 is not an integer">;
+def err_omp_section_function_type : Error<
+ "section of pointer to function type %0">;
+def warn_omp_section_is_char : Warning<"array section %select{lower bound|length}0 is of type 'char'">,
+ InGroup<CharSubscript>, DefaultIgnore;
+def err_omp_section_incomplete_type : Error<
+ "section of pointer to incomplete type %0">;
+def err_omp_section_negative : Error<
+ "section %select{lower bound|length}0 is evaluated to a negative value %1">;
+def err_omp_section_length_undefined : Error<
+ "section length is unspecified and cannot be inferred because subscripted value is %select{not an array|an array of unknown bound}0">;
+def err_omp_wrong_linear_modifier : Error<
+ "expected %select{'val' modifier|one of 'ref', val' or 'uval' modifiers}0">;
+def err_omp_wrong_linear_modifier_non_reference : Error<
+ "variable of non-reference type %0 can be used only with 'val' modifier, but used with '%1'">;
+def err_omp_wrong_simdlen_safelen_values : Error<
+ "the value of 'simdlen' parameter must be less than or equal to the value of the 'safelen' parameter">;
+def err_omp_wrong_if_directive_name_modifier : Error<
+ "directive name modifier '%0' is not allowed for '#pragma omp %1'">;
+def err_omp_no_more_if_clause : Error<
+ "no more 'if' clause is allowed">;
+def err_omp_unnamed_if_clause : Error<
+ "expected %select{|one of}0 %1 directive name modifier%select{|s}0">;
+def note_omp_previous_named_if_clause : Note<
+ "previous clause with directive name modifier specified here">;
+def err_omp_ordered_directive_with_param : Error<
+ "'ordered' directive %select{without any clauses|with 'threads' clause}0 cannot be closely nested inside ordered region with specified parameter">;
+def err_omp_ordered_directive_without_param : Error<
+ "'ordered' directive with 'depend' clause cannot be closely nested inside ordered region without specified parameter">;
+def note_omp_ordered_param : Note<
+ "'ordered' clause with specified parameter">;
+def err_omp_expected_base_var_name : Error<
+ "expected variable name as a base of the array %select{subscript|section}0">;
+def err_omp_map_shared_storage : Error<
+ "variable already marked as mapped in current construct">;
+def err_omp_not_mappable_type : Error<
+ "type %0 is not mappable to target">;
+def note_omp_polymorphic_in_target : Note<
+ "mappable type cannot be polymorphic">;
+def note_omp_static_member_in_target : Note<
+ "mappable type cannot contain static members">;
+def err_omp_threadprivate_in_map : Error<
+ "threadprivate variables are not allowed in map clause">;
+def err_omp_wrong_ordered_loop_count : Error<
+ "the parameter of the 'ordered' clause must be greater than or equal to the parameter of the 'collapse' clause">;
+def note_collapse_loop_count : Note<
+ "parameter of the 'collapse' clause">;
+def err_omp_grainsize_num_tasks_mutually_exclusive : Error<
+ "'%0' and '%1' clause are mutually exclusive and may not appear on the same directive">;
+def note_omp_previous_grainsize_num_tasks : Note<
+ "'%0' clause is specified here">;
+def err_omp_hint_clause_no_name : Error<
+ "the name of the construct must be specified in presence of 'hint' clause">;
+def err_omp_critical_with_hint : Error<
+ "constructs with the same name must have a 'hint' clause with the same value">;
+def note_omp_critical_hint_here : Note<
+ "%select{|previous }0'hint' clause with value '%1'">;
+def note_omp_critical_no_hint : Note<
+ "%select{|previous }0directive with no 'hint' clause specified">;
+def err_omp_firstprivate_distribute_private_teams : Error<
+ "private variable in '#pragma omp teams' cannot be firstprivate in '#pragma omp distribute'">;
+def err_omp_firstprivate_and_lastprivate_in_distribute : Error<
+ "lastprivate variable cannot be firstprivate in '#pragma omp distribute'">;
+def err_omp_firstprivate_distribute_in_teams_reduction : Error<
+ "reduction variable in '#pragma omp teams' cannot be firstprivate in '#pragma omp distribute'">;
+def err_omp_depend_clause_thread_simd : Error<
+ "'depend' clauses cannot be mixed with '%0' clause">;
+def err_omp_depend_sink_wrong_expr : Error<
+ "expected expression form x[+-d], where x is the loop iteration variable and d is a constant non-negative integer">;
+def err_omp_depend_sink_expected_loop_iteration : Error<
+ "expected %0 loop iteration variable">;
+def err_omp_depend_sink_unexpected_expr : Error<
+ "unexpected expression: number of expressions is larger than the number of associated loops">;
+def err_omp_depend_sink_expected_plus_minus : Error<
+ "expected '+' or '-' operation">;
+def err_omp_depend_sink_source_not_allowed : Error<
+ "'depend(%select{source|sink:vec}0)' clause%select{|s}0 cannot be mixed with 'depend(%select{sink:vec|source}0)' clause%select{s|}0">;
+def err_omp_linear_ordered : Error<
+ "'linear' clause cannot be specified along with 'ordered' clause with a parameter">;
+def err_omp_unexpected_schedule_modifier : Error<
+ "modifier '%0' cannot be used along with modifier '%1'">;
+def err_omp_schedule_nonmonotonic_static : Error<
+ "'nonmonotonic' modifier can only be specified with 'dynamic' or 'guided' schedule kind">;
+def err_omp_schedule_nonmonotonic_ordered : Error<
+ "'schedule' clause with 'nonmonotonic' modifier cannot be specified if an 'ordered' clause is specified">;
+def err_omp_ordered_simd : Error<
+ "'ordered' clause with a parameter can not be specified in '#pragma omp %0' directive">;
+} // end of OpenMP category
+
+let CategoryName = "Related Result Type Issue" in {
+// Objective-C related result type compatibility
+def warn_related_result_type_compatibility_class : Warning<
+ "method is expected to return an instance of its class type "
+ "%diff{$, but is declared to return $|"
+ ", but is declared to return different type}0,1">;
+def warn_related_result_type_compatibility_protocol : Warning<
+ "protocol method is expected to return an instance of the implementing "
+ "class, but is declared to return %0">;
+def note_related_result_type_family : Note<
+ "%select{overridden|current}0 method is part of the '%select{|alloc|copy|init|"
+ "mutableCopy|new|autorelease|dealloc|finalize|release|retain|retainCount|"
+ "self}1' method family%select{| and is expected to return an instance of its "
+ "class type}0">;
+def note_related_result_type_overridden : Note<
+ "overridden method returns an instance of its class type">;
+def note_related_result_type_inferred : Note<
+ "%select{class|instance}0 method %1 is assumed to return an instance of "
+ "its receiver type (%2)">;
+def note_related_result_type_explicit : Note<
+ "%select{overridden|current}0 method is explicitly declared 'instancetype'"
+ "%select{| and is expected to return an instance of its class type}0">;
+
+}
+
+let CategoryName = "Modules Issue" in {
+def err_module_private_specialization : Error<
+ "%select{template|partial|member}0 specialization cannot be "
+ "declared __module_private__">;
+def err_module_private_local : Error<
+ "%select{local variable|parameter|typedef}0 %1 cannot be declared "
+ "__module_private__">;
+def err_module_private_local_class : Error<
+ "local %select{struct|interface|union|class|enum}0 cannot be declared "
+ "__module_private__">;
+def err_module_unimported_use : Error<
+ "%select{declaration|definition|default argument}0 of %1 must be imported "
+ "from module '%2' before it is required">;
+def err_module_unimported_use_multiple : Error<
+ "%select{declaration|definition|default argument}0 of %1 must be imported "
+ "from one of the following modules before it is required:%2">;
+def ext_module_import_in_extern_c : ExtWarn<
+ "import of C++ module '%0' appears within extern \"C\" language linkage "
+ "specification">, DefaultError,
+ InGroup<DiagGroup<"module-import-in-extern-c">>;
+def note_module_import_in_extern_c : Note<
+ "extern \"C\" language linkage specification begins here">;
+def err_module_import_not_at_top_level_fatal : Error<
+ "import of module '%0' appears within %1">, DefaultFatal;
+def ext_module_import_not_at_top_level_noop : ExtWarn<
+ "redundant #include of module '%0' appears within %1">, DefaultError,
+ InGroup<DiagGroup<"modules-import-nested-redundant">>;
+def note_module_import_not_at_top_level : Note<"%0 begins here">;
+def err_module_self_import : Error<
+ "import of module '%0' appears within same top-level module '%1'">;
+def err_module_import_in_implementation : Error<
+ "@import of module '%0' in implementation of '%1'; use #import">;
+
+def ext_equivalent_internal_linkage_decl_in_modules : ExtWarn<
+ "ambiguous use of internal linkage declaration %0 defined in multiple modules">,
+ InGroup<DiagGroup<"modules-ambiguous-internal-linkage">>;
+def note_equivalent_internal_linkage_decl : Note<
+ "declared here%select{ in module '%1'|}0">;
+}
+
+let CategoryName = "Coroutines Issue" in {
+def err_return_in_coroutine : Error<
+ "return statement not allowed in coroutine; did you mean 'co_return'?">;
+def note_declared_coroutine_here : Note<
+ "function is a coroutine due to use of "
+ "'%select{co_await|co_yield|co_return}0' here">;
+def err_coroutine_objc_method : Error<
+ "Objective-C methods as coroutines are not yet supported">;
+def err_coroutine_unevaluated_context : Error<
+ "'%0' cannot be used in an unevaluated context">;
+def err_coroutine_outside_function : Error<
+ "'%0' cannot be used outside a function">;
+def err_coroutine_ctor_dtor : Error<
+ "'%1' cannot be used in a %select{constructor|destructor}0">;
+def err_coroutine_constexpr : Error<
+ "'%0' cannot be used in a constexpr function">;
+def err_coroutine_varargs : Error<
+ "'%0' cannot be used in a varargs function">;
+def ext_coroutine_without_co_await_co_yield : ExtWarn<
+ "'co_return' used in a function "
+ "that uses neither 'co_await' nor 'co_yield'">,
+ InGroup<DiagGroup<"coreturn-without-coawait">>;
+def err_implied_std_coroutine_traits_not_found : Error<
+ "you need to include <coroutine> before defining a coroutine">;
+def err_malformed_std_coroutine_traits : Error<
+ "'std::coroutine_traits' must be a class template">;
+def err_implied_std_coroutine_traits_promise_type_not_found : Error<
+ "this function cannot be a coroutine: %q0 has no member named 'promise_type'">;
+def err_implied_std_coroutine_traits_promise_type_not_class : Error<
+ "this function cannot be a coroutine: %0 is not a class">;
+def err_coroutine_traits_missing_specialization : Error<
+ "this function cannot be a coroutine: missing definition of "
+ "specialization %q0">;
+}
+
+let CategoryName = "Documentation Issue" in {
+def warn_not_a_doxygen_trailing_member_comment : Warning<
+ "not a Doxygen trailing comment">, InGroup<Documentation>, DefaultIgnore;
+} // end of documentation issue category
+
+let CategoryName = "Instrumentation Issue" in {
+def warn_profile_data_out_of_date : Warning<
+ "profile data may be out of date: of %0 function%s0, %1 %plural{1:has|:have}1"
+ " no data and %2 %plural{1:has|:have}2 mismatched data that will be ignored">,
+ InGroup<ProfileInstrOutOfDate>;
+def warn_profile_data_unprofiled : Warning<
+ "no profile data available for file \"%0\"">,
+ InGroup<ProfileInstrUnprofiled>;
+
+} // end of instrumentation issue category
+
+let CategoryName = "Nullability Issue" in {
+
+def warn_mismatched_nullability_attr : Warning<
+ "nullability specifier %0 conflicts with existing specifier %1">,
+ InGroup<Nullability>;
+
+def warn_nullability_declspec : Warning<
+ "nullability specifier %0 cannot be applied "
+ "to non-pointer type %1; did you mean to apply the specifier to the "
+ "%select{pointer|block pointer|member pointer|function pointer|"
+ "member function pointer}2?">,
+ InGroup<NullabilityDeclSpec>,
+ DefaultError;
+
+def note_nullability_here : Note<"%0 specified here">;
+
+def err_nullability_nonpointer : Error<
+ "nullability specifier %0 cannot be applied to non-pointer type %1">;
+
+def warn_nullability_lost : Warning<
+ "implicit conversion from nullable pointer %0 to non-nullable pointer "
+ "type %1">,
+ InGroup<NullableToNonNullConversion>, DefaultIgnore;
+
+def err_nullability_cs_multilevel : Error<
+ "nullability keyword %0 cannot be applied to multi-level pointer type %1">;
+def note_nullability_type_specifier : Note<
+ "use nullability type specifier %0 to affect the innermost "
+ "pointer type of %1">;
+
+def warn_null_resettable_setter : Warning<
+ "synthesized setter %0 for null_resettable property %1 does not handle nil">,
+ InGroup<Nullability>;
+
+def warn_nullability_missing : Warning<
+ "%select{pointer|block pointer|member pointer}0 is missing a nullability "
+ "type specifier (_Nonnull, _Nullable, or _Null_unspecified)">,
+ InGroup<NullabilityCompleteness>;
+
+def err_objc_type_arg_explicit_nullability : Error<
+ "type argument %0 cannot explicitly specify nullability">;
+
+def err_objc_type_param_bound_explicit_nullability : Error<
+ "type parameter %0 bound %1 cannot explicitly specify nullability">;
+
+}
+
+let CategoryName = "Generics Issue" in {
+
+def err_objc_type_param_bound_nonobject : Error<
+ "type bound %0 for type parameter %1 is not an Objective-C pointer type">;
+
+def err_objc_type_param_bound_missing_pointer : Error<
+ "missing '*' in type bound %0 for type parameter %1">;
+def err_objc_type_param_bound_qualified : Error<
+ "type bound %1 for type parameter %0 cannot be qualified with '%2'">;
+
+def err_objc_type_param_redecl : Error<
+ "redeclaration of type parameter %0">;
+
+def err_objc_type_param_arity_mismatch : Error<
+ "%select{forward class declaration|class definition|category|extension}0 has "
+ "too %select{few|many}1 type parameters (expected %2, have %3)">;
+
+def err_objc_type_param_bound_conflict : Error<
+ "type bound %0 for type parameter %1 conflicts with "
+ "%select{implicit|previous}2 bound %3%select{for type parameter %5|}4">;
+
+def err_objc_type_param_variance_conflict : Error<
+ "%select{in|co|contra}0variant type parameter %1 conflicts with previous "
+ "%select{in|co|contra}2variant type parameter %3">;
+
+def note_objc_type_param_here : Note<"type parameter %0 declared here">;
+
+def err_objc_type_param_bound_missing : Error<
+ "missing type bound %0 for type parameter %1 in %select{@interface|@class}2">;
+
+def err_objc_parameterized_category_nonclass : Error<
+ "%select{extension|category}0 of non-parameterized class %1 cannot have type "
+ "parameters">;
+
+def err_objc_parameterized_forward_class : Error<
+ "forward declaration of non-parameterized class %0 cannot have type "
+ "parameters">;
+
+def err_objc_parameterized_forward_class_first : Error<
+ "class %0 previously declared with type parameters">;
+
+def err_objc_type_arg_missing_star : Error<
+ "type argument %0 must be a pointer (requires a '*')">;
+def err_objc_type_arg_qualified : Error<
+ "type argument %0 cannot be qualified with '%1'">;
+
+def err_objc_type_arg_missing : Error<
+ "no type or protocol named %0">;
+
+def err_objc_type_args_and_protocols : Error<
+ "angle brackets contain both a %select{type|protocol}0 (%1) and a "
+ "%select{protocol|type}0 (%2)">;
+
+def err_objc_type_args_non_class : Error<
+ "type arguments cannot be applied to non-class type %0">;
+
+def err_objc_type_args_non_parameterized_class : Error<
+ "type arguments cannot be applied to non-parameterized class %0">;
+
+def err_objc_type_args_specialized_class : Error<
+ "type arguments cannot be applied to already-specialized class type %0">;
+
+def err_objc_type_args_wrong_arity : Error<
+ "too %select{many|few}0 type arguments for class %1 (have %2, expected %3)">;
+}
+
+def err_objc_type_arg_not_id_compatible : Error<
+ "type argument %0 is neither an Objective-C object nor a block type">;
+
+def err_objc_type_arg_does_not_match_bound : Error<
+ "type argument %0 does not satisfy the bound (%1) of type parameter %2">;
+
+def warn_objc_redundant_qualified_class_type : Warning<
+ "parameterized class %0 already conforms to the protocols listed; did you "
+ "forget a '*'?">, InGroup<ObjCProtocolQualifiers>;
+
+} // end of sema component.
diff --git a/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticSerializationKinds.td b/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticSerializationKinds.td
new file mode 100644
index 0000000..16c7743
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Basic/DiagnosticSerializationKinds.td
@@ -0,0 +1,124 @@
+//==--- DiagnosticSerializationKinds.td - serialization diagnostics -------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+let Component = "Serialization" in {
+let CategoryName = "AST Deserialization Issue" in {
+
+def err_fe_unable_to_read_pch_file : Error<
+ "unable to read PCH file %0: '%1'">;
+def err_fe_not_a_pch_file : Error<
+ "input is not a PCH file: '%0'">;
+def err_fe_pch_malformed : Error<
+ "malformed or corrupted AST file: '%0'">, DefaultFatal;
+def err_fe_pch_malformed_block : Error<
+ "malformed block record in PCH file: '%0'">, DefaultFatal;
+def err_fe_pch_file_modified : Error<
+ "file '%0' has been modified since the precompiled header '%1' was built">,
+ DefaultFatal;
+def err_fe_pch_file_overridden : Error<
+ "file '%0' from the precompiled header has been overridden">;
+def note_pch_required_by : Note<"'%0' required by '%1'">;
+def note_pch_rebuild_required : Note<"please rebuild precompiled header '%0'">;
+def note_module_cache_path : Note<
+ "after modifying system headers, please delete the module cache at '%0'">;
+
+def err_pch_targetopt_mismatch : Error<
+ "PCH file was compiled for the %0 '%1' but the current translation "
+ "unit is being compiled for target '%2'">;
+def err_pch_targetopt_feature_mismatch : Error<
+ "%select{AST file|current translation unit}0 was compiled with the target "
+ "feature'%1' but the %select{current translation unit is|AST file was}0 "
+ "not">;
+def err_pch_langopt_mismatch : Error<"%0 was %select{disabled|enabled}1 in "
+ "PCH file but is currently %select{disabled|enabled}2">;
+def err_pch_langopt_value_mismatch : Error<
+ "%0 differs in PCH file vs. current file">;
+def err_pch_diagopt_mismatch : Error<"%0 is currently enabled, but was not in "
+ "the PCH file">;
+def err_pch_modulecache_mismatch : Error<"PCH was compiled with module cache "
+ "path '%0', but the path is currently '%1'">;
+
+def err_pch_version_too_old : Error<
+ "PCH file uses an older PCH format that is no longer supported">;
+def err_pch_version_too_new : Error<
+ "PCH file uses a newer PCH format that cannot be read">;
+def err_pch_different_branch : Error<
+ "PCH file built from a different branch (%0) than the compiler (%1)">;
+def err_pch_with_compiler_errors : Error<
+ "PCH file contains compiler errors">;
+
+def err_module_file_conflict : Error<
+ "module '%0' is defined in both '%1' and '%2'">, DefaultFatal;
+def err_module_file_not_found : Error<
+ "%select{PCH|module|AST}0 file '%1' not found%select{|: %3}2">, DefaultFatal;
+def err_module_file_out_of_date : Error<
+ "%select{PCH|module|AST}0 file '%1' is out of date and "
+ "needs to be rebuilt%select{|: %3}2">, DefaultFatal;
+def err_module_file_invalid : Error<
+ "file '%1' is not a valid precompiled %select{PCH|module|AST}0 file">, DefaultFatal;
+def note_module_file_imported_by : Note<
+ "imported by %select{|module '%2' in }1'%0'">;
+def err_module_file_not_module : Error<
+ "AST file '%0' was not built as a module">, DefaultFatal;
+
+def err_imported_module_not_found : Error<
+ "module '%0' in AST file '%1' (imported by AST file '%2') "
+ "is not defined in any loaded module map file; "
+ "maybe you need to load '%3'?">, DefaultFatal;
+def err_imported_module_modmap_changed : Error<
+ "module '%0' imported by AST file '%1' found in a different module map file"
+ " (%2) than when the importing AST file was built (%3)">, DefaultFatal;
+def err_imported_module_relocated : Error<
+ "module '%0' was built in directory '%1' but now resides in "
+ "directory '%2'">, DefaultFatal;
+def err_module_different_modmap : Error<
+ "module '%0' %select{uses|does not use}1 additional module map '%2'"
+ "%select{| not}1 used when the module was built">;
+
+def err_pch_macro_def_undef : Error<
+ "macro '%0' was %select{defined|undef'd}1 in the precompiled header but "
+ "%select{undef'd|defined}1 on the command line">;
+def err_pch_macro_def_conflict : Error<
+ "definition of macro '%0' differs between the precompiled header ('%1') "
+ "and the command line ('%2')">;
+def err_pch_undef : Error<
+ "%select{command line contains|precompiled header was built with}0 "
+ "'-undef' but %select{precompiled header was not built with it|"
+ "it is not present on the command line}0">;
+def err_pch_pp_detailed_record : Error<
+ "%select{command line contains|precompiled header was built with}0 "
+ "'-detailed-preprocessing-record' but %select{precompiled header was not "
+ "built with it|it is not present on the command line}0">;
+
+def err_module_odr_violation_missing_decl : Error<
+ "%q0 from module '%1' is not present in definition of %q2"
+ "%select{ in module '%4'| provided earlier}3">, NoSFINAE;
+def note_module_odr_violation_no_possible_decls : Note<
+ "definition has no member %0">;
+def note_module_odr_violation_possible_decl : Note<
+ "declaration of %0 does not match">;
+def err_module_odr_violation_different_definitions : Error<
+ "%q0 has different definitions in different modules; "
+ "%select{definition in module '%2' is here|defined here}1">;
+def note_module_odr_violation_different_definitions : Note<
+ "definition in module '%0' is here">;
+def err_module_odr_violation_different_instantiations : Error<
+ "instantiation of %q0 is different in different modules">;
+
+def warn_module_uses_date_time : Warning<
+ "%select{precompiled header|module}0 uses __DATE__ or __TIME__">,
+ InGroup<DiagGroup<"pch-date-time">>;
+
+def warn_duplicate_module_file_extension : Warning<
+ "duplicate module file extension block name '%0'">,
+ InGroup<ModuleFileExtension>;
+
+} // let CategoryName
+} // let Component
+
diff --git a/contrib/llvm/tools/clang/include/clang/Basic/ExceptionSpecificationType.h b/contrib/llvm/tools/clang/include/clang/Basic/ExceptionSpecificationType.h
new file mode 100644
index 0000000..132b5ba
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Basic/ExceptionSpecificationType.h
@@ -0,0 +1,60 @@
+//===--- ExceptionSpecificationType.h ---------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+///
+/// \file
+/// \brief Defines the ExceptionSpecificationType enumeration and various
+/// utility functions.
+///
+//===----------------------------------------------------------------------===//
+#ifndef LLVM_CLANG_BASIC_EXCEPTIONSPECIFICATIONTYPE_H
+#define LLVM_CLANG_BASIC_EXCEPTIONSPECIFICATIONTYPE_H
+
+namespace clang {
+
+/// \brief The various types of exception specifications that exist in C++11.
+enum ExceptionSpecificationType {
+ EST_None, ///< no exception specification
+ EST_DynamicNone, ///< throw()
+ EST_Dynamic, ///< throw(T1, T2)
+ EST_MSAny, ///< Microsoft throw(...) extension
+ EST_BasicNoexcept, ///< noexcept
+ EST_ComputedNoexcept, ///< noexcept(expression)
+ EST_Unevaluated, ///< not evaluated yet, for special member function
+ EST_Uninstantiated, ///< not instantiated yet
+ EST_Unparsed ///< not parsed yet
+};
+
+inline bool isDynamicExceptionSpec(ExceptionSpecificationType ESpecType) {
+ return ESpecType >= EST_DynamicNone && ESpecType <= EST_MSAny;
+}
+
+inline bool isNoexceptExceptionSpec(ExceptionSpecificationType ESpecType) {
+ return ESpecType == EST_BasicNoexcept || ESpecType == EST_ComputedNoexcept;
+}
+
+inline bool isUnresolvedExceptionSpec(ExceptionSpecificationType ESpecType) {
+ return ESpecType == EST_Unevaluated || ESpecType == EST_Uninstantiated;
+}
+
+/// \brief Possible results from evaluation of a noexcept expression.
+enum CanThrowResult {
+ CT_Cannot,
+ CT_Dependent,
+ CT_Can
+};
+
+inline CanThrowResult mergeCanThrow(CanThrowResult CT1, CanThrowResult CT2) {
+ // CanThrowResult constants are ordered so that the maximum is the correct
+ // merge result.
+ return CT1 > CT2 ? CT1 : CT2;
+}
+
+} // end namespace clang
+
+#endif // LLVM_CLANG_BASIC_EXCEPTIONSPECIFICATIONTYPE_H
diff --git a/contrib/llvm/tools/clang/include/clang/Basic/ExpressionTraits.h b/contrib/llvm/tools/clang/include/clang/Basic/ExpressionTraits.h
new file mode 100644
index 0000000..0363a1d
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Basic/ExpressionTraits.h
@@ -0,0 +1,26 @@
+//===- ExpressionTraits.h - C++ Expression Traits Support Enums -*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+///
+/// \file
+/// \brief Defines enumerations for expression traits intrinsics.
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_BASIC_EXPRESSIONTRAITS_H
+#define LLVM_CLANG_BASIC_EXPRESSIONTRAITS_H
+
+namespace clang {
+
+ enum ExpressionTrait {
+ ET_IsLValueExpr,
+ ET_IsRValueExpr
+ };
+}
+
+#endif
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..17758ec
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Basic/FileManager.h
@@ -0,0 +1,288 @@
+//===--- 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.
+//
+//===----------------------------------------------------------------------===//
+///
+/// \file
+/// \brief Defines the clang::FileManager interface and associated types.
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_BASIC_FILEMANAGER_H
+#define LLVM_CLANG_BASIC_FILEMANAGER_H
+
+#include "clang/Basic/FileSystemOptions.h"
+#include "clang/Basic/LLVM.h"
+#include "clang/Basic/VirtualFileSystem.h"
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/IntrusiveRefCntPtr.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/StringMap.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/Support/Allocator.h"
+#include <memory>
+#include <map>
+
+namespace llvm {
+class MemoryBuffer;
+}
+
+namespace clang {
+class FileManager;
+class FileSystemStatCache;
+
+/// \brief Cached information about one directory (either on disk or in
+/// the virtual file system).
+class DirectoryEntry {
+ const char *Name; // Name of the directory.
+ friend class FileManager;
+public:
+ DirectoryEntry() : Name(nullptr) {}
+ const char *getName() const { return Name; }
+};
+
+/// \brief Cached information about one file (either on disk
+/// or in the virtual file system).
+///
+/// If the 'File' 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.
+ llvm::sys::fs::UniqueID UniqueID;
+ bool IsNamedPipe;
+ bool InPCH;
+ bool IsValid; // Is this \c FileEntry initialized and valid?
+
+ /// \brief The open file, if it is owned by the \p FileEntry.
+ mutable std::unique_ptr<vfs::File> File;
+ friend class FileManager;
+
+ void operator=(const FileEntry &) = delete;
+
+public:
+ FileEntry()
+ : UniqueID(0, 0), IsNamedPipe(false), InPCH(false), IsValid(false)
+ {}
+
+ // FIXME: this is here to allow putting FileEntry in std::map. Once we have
+ // emplace, we shouldn't need a copy constructor anymore.
+ /// Intentionally does not copy fields that are not set in an uninitialized
+ /// \c FileEntry.
+ FileEntry(const FileEntry &FE) : UniqueID(FE.UniqueID),
+ IsNamedPipe(FE.IsNamedPipe), InPCH(FE.InPCH), IsValid(FE.IsValid) {
+ assert(!isValid() && "Cannot copy an initialized FileEntry");
+ }
+
+ const char *getName() const { return Name; }
+ bool isValid() const { return IsValid; }
+ off_t getSize() const { return Size; }
+ unsigned getUID() const { return UID; }
+ const llvm::sys::fs::UniqueID &getUniqueID() const { return UniqueID; }
+ bool isInPCH() const { return InPCH; }
+ time_t getModificationTime() const { return ModTime; }
+
+ /// \brief Return the directory the file lives in.
+ const DirectoryEntry *getDir() const { return Dir; }
+
+ bool operator<(const FileEntry &RHS) const { return UniqueID < RHS.UniqueID; }
+
+ /// \brief Check whether the file is a named pipe (and thus can't be opened by
+ /// the native FileManager methods).
+ bool isNamedPipe() const { return IsNamedPipe; }
+
+ void closeFile() const {
+ File.reset(); // rely on destructor to close File
+ }
+};
+
+struct FileData;
+
+/// \brief 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 : public RefCountedBase<FileManager> {
+ IntrusiveRefCntPtr<vfs::FileSystem> FS;
+ FileSystemOptions FileSystemOpts;
+
+ /// \brief Cache for existing real directories.
+ std::map<llvm::sys::fs::UniqueID, DirectoryEntry> UniqueRealDirs;
+
+ /// \brief Cache for existing real files.
+ std::map<llvm::sys::fs::UniqueID, FileEntry> 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.
+ SmallVector<std::unique_ptr<DirectoryEntry>, 4> VirtualDirectoryEntries;
+ /// \brief The virtual files that we have allocated.
+ SmallVector<std::unique_ptr<FileEntry>, 4> VirtualFileEntries;
+
+ /// \brief A cache that maps paths to directory 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;
+
+ /// \brief A cache that maps paths to file entries (either real or
+ /// virtual) we have looked up.
+ ///
+ /// \see SeenDirEntries
+ llvm::StringMap<FileEntry*, llvm::BumpPtrAllocator> SeenFileEntries;
+
+ /// \brief The canonical names of directories.
+ llvm::DenseMap<const DirectoryEntry *, llvm::StringRef> CanonicalDirNames;
+
+ /// \brief Storage for canonical names that we have computed.
+ llvm::BumpPtrAllocator CanonicalNameStorage;
+
+ /// \brief Each FileEntry we create is assigned a unique ID #.
+ ///
+ unsigned NextFileUID;
+
+ // Statistics.
+ unsigned NumDirLookups, NumFileLookups;
+ unsigned NumDirCacheMisses, NumFileCacheMisses;
+
+ // Caching.
+ std::unique_ptr<FileSystemStatCache> StatCache;
+
+ bool getStatValue(const char *Path, FileData &Data, bool isFile,
+ std::unique_ptr<vfs::File> *F);
+
+ /// Add all ancestors of the given path (pointing to either a file
+ /// or a directory) as virtual directories.
+ void addAncestorsAsVirtualDirs(StringRef Path);
+
+public:
+ FileManager(const FileSystemOptions &FileSystemOpts,
+ IntrusiveRefCntPtr<vfs::FileSystem> FS = nullptr);
+ ~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(std::unique_ptr<FileSystemStatCache> statCache,
+ bool AtBeginning = false);
+
+ /// \brief Removes the specified FileSystemStatCache object from the manager.
+ void removeStatCache(FileSystemStatCache *statCache);
+
+ /// \brief Removes all FileSystemStatCache objects from the manager.
+ void clearStatCaches();
+
+ /// \brief Lookup, cache, and verify the specified directory (real or
+ /// virtual).
+ ///
+ /// This returns NULL if the directory doesn't exist.
+ ///
+ /// \param CacheFailure If true and the file does not exist, we'll cache
+ /// the failure to find this file.
+ const DirectoryEntry *getDirectory(StringRef DirName,
+ bool CacheFailure = true);
+
+ /// \brief Lookup, cache, and verify the specified file (real or
+ /// virtual).
+ ///
+ /// This returns NULL if the file doesn't exist.
+ ///
+ /// \param OpenFile if true and the file exists, it will be opened.
+ ///
+ /// \param CacheFailure If true and the file does not exist, we'll cache
+ /// the failure to find this file.
+ const FileEntry *getFile(StringRef Filename, bool OpenFile = false,
+ bool CacheFailure = true);
+
+ /// \brief Returns the current file system options
+ FileSystemOptions &getFileSystemOpts() { return FileSystemOpts; }
+ const FileSystemOptions &getFileSystemOpts() const { return FileSystemOpts; }
+
+ IntrusiveRefCntPtr<vfs::FileSystem> getVirtualFileSystem() const {
+ return FS;
+ }
+
+ /// \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(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::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>>
+ getBufferForFile(const FileEntry *Entry, bool isVolatile = false,
+ bool ShouldCloseOpenFile = true);
+ llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>>
+ getBufferForFile(StringRef Filename);
+
+ /// \brief Get the 'stat' information for the given \p Path.
+ ///
+ /// If the path is relative, it will be resolved against the WorkingDir of the
+ /// FileManager's FileSystemOptions.
+ ///
+ /// \returns false on success, true on error.
+ bool getNoncachedStatValue(StringRef Path,
+ vfs::Status &Result);
+
+ /// \brief Remove the real file \p Entry from the cache.
+ void invalidateCache(const FileEntry *Entry);
+
+ /// \brief If path is not absolute and FileSystemOptions set the working
+ /// directory, the path is modified to be relative to the given
+ /// working directory.
+ /// \returns true if \c path changed.
+ bool FixupRelativePath(SmallVectorImpl<char> &path) const;
+
+ /// Makes \c Path absolute taking into account FileSystemOptions and the
+ /// working directory option.
+ /// \returns true if \c Path changed to absolute.
+ bool makeAbsolutePath(SmallVectorImpl<char> &Path) const;
+
+ /// \brief Produce an array mapping from the unique IDs assigned to each
+ /// file to the corresponding FileEntry pointer.
+ void GetUniqueIDMapping(
+ SmallVectorImpl<const FileEntry *> &UIDToFiles) const;
+
+ /// \brief Modifies the size and modification time of a previously created
+ /// FileEntry. Use with caution.
+ static void modifyFileEntry(FileEntry *File, off_t Size,
+ time_t ModificationTime);
+
+ /// \brief Retrieve the canonical name for a given directory.
+ ///
+ /// This is a very expensive operation, despite its results being cached,
+ /// and should only be used when the physical layout of the file system is
+ /// required, which is (almost) never.
+ StringRef getCanonicalName(const DirectoryEntry *Dir);
+
+ 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..38f1346
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Basic/FileSystemOptions.h
@@ -0,0 +1,32 @@
+//===--- 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.
+//
+//===----------------------------------------------------------------------===//
+///
+/// \file
+/// \brief Defines the clang::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..cad9189
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Basic/FileSystemStatCache.h
@@ -0,0 +1,131 @@
+//===--- 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.
+//
+//===----------------------------------------------------------------------===//
+///
+/// \file
+/// \brief Defines the FileSystemStatCache interface.
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_BASIC_FILESYSTEMSTATCACHE_H
+#define LLVM_CLANG_BASIC_FILESYSTEMSTATCACHE_H
+
+#include "clang/Basic/LLVM.h"
+#include "llvm/ADT/StringMap.h"
+#include "llvm/Support/FileSystem.h"
+#include <memory>
+
+namespace clang {
+
+namespace vfs {
+class File;
+class FileSystem;
+}
+
+// FIXME: should probably replace this with vfs::Status
+struct FileData {
+ std::string Name;
+ uint64_t Size;
+ time_t ModTime;
+ llvm::sys::fs::UniqueID UniqueID;
+ bool IsDirectory;
+ bool IsNamedPipe;
+ bool InPCH;
+ bool IsVFSMapped; // FIXME: remove this when files support multiple names
+ FileData()
+ : Size(0), ModTime(0), IsDirectory(false), IsNamedPipe(false),
+ InPCH(false), IsVFSMapped(false) {}
+};
+
+/// \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 {
+ virtual void anchor();
+protected:
+ std::unique_ptr<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.
+ };
+
+ /// \brief Get the 'stat' information for the specified path, using the cache
+ /// to accelerate it if possible.
+ ///
+ /// \returns \c true if the path does not exist or \c false if it exists.
+ ///
+ /// If isFile is true, then this lookup should only return success for files
+ /// (not directories). If it is false this lookup should only return
+ /// success for directories (not files). On a successful file lookup, the
+ /// implementation can optionally fill in \p F with a valid \p File object and
+ /// the client guarantees that it will close it.
+ static bool get(const char *Path, FileData &Data, bool isFile,
+ std::unique_ptr<vfs::File> *F, FileSystemStatCache *Cache,
+ vfs::FileSystem &FS);
+
+ /// \brief Sets the next stat call cache in the chain of stat caches.
+ /// Takes ownership of the given stat cache.
+ void setNextStatCache(std::unique_ptr<FileSystemStatCache> Cache) {
+ NextStatCache = std::move(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.
+ std::unique_ptr<FileSystemStatCache> takeNextStatCache() {
+ return std::move(NextStatCache);
+ }
+
+protected:
+ // FIXME: The pointer here is a non-owning/optional reference to the
+ // unique_ptr. Optional<unique_ptr<vfs::File>&> might be nicer, but
+ // Optional needs some work to support references so this isn't possible yet.
+ virtual LookupResult getStat(const char *Path, FileData &Data, bool isFile,
+ std::unique_ptr<vfs::File> *F,
+ vfs::FileSystem &FS) = 0;
+
+ LookupResult statChained(const char *Path, FileData &Data, bool isFile,
+ std::unique_ptr<vfs::File> *F, vfs::FileSystem &FS) {
+ if (FileSystemStatCache *Next = getNextStatCache())
+ return Next->getStat(Path, Data, isFile, F, FS);
+
+ // If we hit the end of the list of stat caches to try, just compute and
+ // return it without a cache.
+ return get(Path, Data, isFile, F, nullptr, FS) ? 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<FileData, llvm::BumpPtrAllocator> StatCalls;
+
+ typedef llvm::StringMap<FileData, llvm::BumpPtrAllocator>::const_iterator
+ iterator;
+
+ iterator begin() const { return StatCalls.begin(); }
+ iterator end() const { return StatCalls.end(); }
+
+ LookupResult getStat(const char *Path, FileData &Data, bool isFile,
+ std::unique_ptr<vfs::File> *F,
+ vfs::FileSystem &FS) override;
+};
+
+} // 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..d672314
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Basic/IdentifierTable.h
@@ -0,0 +1,876 @@
+//===--- 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.
+//
+//===----------------------------------------------------------------------===//
+///
+/// \file
+/// \brief Defines the clang::IdentifierInfo, clang::IdentifierTable, and
+/// clang::Selector interfaces.
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_BASIC_IDENTIFIERTABLE_H
+#define LLVM_CLANG_BASIC_IDENTIFIERTABLE_H
+
+#include "clang/Basic/LLVM.h"
+#include "clang/Basic/TokenKinds.h"
+#include "llvm/ADT/StringMap.h"
+#include "llvm/ADT/StringRef.h"
+#include <cassert>
+#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
+
+ /// \brief A simple pair of identifier info and location.
+ typedef std::pair<IdentifierInfo*, SourceLocation> IdentifierLocPair;
+
+
+/// 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 {
+ unsigned TokenID : 9; // 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 :13;
+ bool HasMacro : 1; // True if there is a #define for this.
+ bool HadMacro : 1; // True if there was a #define for this.
+ bool IsExtension : 1; // True if identifier is a lang extension.
+ bool IsFutureCompatKeyword : 1; // True if identifier is a keyword in a
+ // newer Standard or proposed Standard.
+ 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 identifier was loaded (at least
+ // partially) from an AST file.
+ bool ChangedAfterLoad : 1; // True if identifier has changed from the
+ // definition loaded from an AST file.
+ bool RevertedTokenID : 1; // True if revertTokenIDToIdentifier was
+ // called.
+ bool OutOfDate : 1; // True if there may be additional
+ // information about this identifier
+ // stored externally.
+ bool IsModulesImport : 1; // True if this is the 'import' contextual
+ // keyword.
+ // 30 bit left in 64-bit word.
+
+ void *FETokenInfo; // Managed by the language front-end.
+ llvm::StringMapEntry<IdentifierInfo*> *Entry;
+
+ IdentifierInfo(const IdentifierInfo&) = delete;
+ void operator=(const IdentifierInfo&) = delete;
+
+ friend class IdentifierTable;
+
+public:
+ IdentifierInfo();
+
+
+ /// \brief 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);
+ }
+
+ /// \brief Return the beginning of the actual null-terminated string for this
+ /// identifier.
+ ///
+ 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;
+ }
+
+ /// \brief 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;
+ }
+
+ /// \brief Return the actual identifier string.
+ StringRef getName() const {
+ return StringRef(getNameStart(), getLength());
+ }
+
+ /// \brief Return true if this identifier is \#defined to some other value.
+ /// \note The current definition may be in a module and not currently visible.
+ bool hasMacroDefinition() const {
+ return HasMacro;
+ }
+ void setHasMacroDefinition(bool Val) {
+ if (HasMacro == Val) return;
+
+ HasMacro = Val;
+ if (Val) {
+ NeedsHandleIdentifier = 1;
+ HadMacro = true;
+ } else {
+ RecomputeNeedsHandleIdentifier();
+ }
+ }
+ /// \brief Returns true if this identifier was \#defined to some value at any
+ /// moment. In this case there should be an entry for the identifier in the
+ /// macro history table in Preprocessor.
+ bool hadMacroDefinition() const {
+ return HadMacro;
+ }
+
+ /// 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;
+ }
+ void revertIdentifierToTokenID(tok::TokenKind TK) {
+ assert(TokenID == tok::identifier && "Should be at tok::identifier");
+ TokenID = TK;
+ RevertedTokenID = false;
+ }
+
+ /// \brief Return the preprocessor keyword ID for this identifier.
+ ///
+ /// For example, "define" will return tok::pp_define.
+ tok::PPKeywordKind getPPKeywordID() const;
+
+ /// \brief 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; }
+
+ /// \brief True if setNotBuiltin() was called.
+ bool hasRevertedBuiltin() const {
+ return ObjCOrBuiltinID == tok::NUM_OBJC_KEYWORDS;
+ }
+
+ /// \brief Revert the identifier to a non-builtin identifier. We do this if
+ /// the name of a known builtin library function is used to declare that
+ /// function, but an unexpected type is specified.
+ void revertBuiltin() {
+ setBuiltinID(0);
+ }
+
+ /// \brief 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();
+ }
+
+ /// is/setIsFutureCompatKeyword - Initialize information about whether or not
+ /// this language token is a keyword in a newer or proposed Standard. This
+ /// controls compatibility warnings, and is only true when not parsing the
+ /// corresponding Standard. Once a compatibility problem has been diagnosed
+ /// with this keyword, the flag will be cleared.
+ bool isFutureCompatKeyword() const { return IsFutureCompatKeyword; }
+ void setIsFutureCompatKeyword(bool Val) {
+ IsFutureCompatKeyword = 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();
+ }
+
+ /// \brief 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; }
+
+ /// \brief Return true if this token is a keyword in the specified language.
+ bool isKeyword(const LangOptions &LangOpts);
+
+ /// 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; }
+
+ /// \brief 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; }
+
+ /// \brief Return true if the identifier in its current state was loaded
+ /// from an AST file.
+ bool isFromAST() const { return IsFromAST; }
+
+ void setIsFromAST() { IsFromAST = true; }
+
+ /// \brief Determine whether this identifier has changed since it was loaded
+ /// from an AST file.
+ bool hasChangedSinceDeserialization() const {
+ return ChangedAfterLoad;
+ }
+
+ /// \brief Note that this identifier has changed since it was loaded from
+ /// an AST file.
+ void setChangedSinceDeserialization() {
+ ChangedAfterLoad = true;
+ }
+
+ /// \brief Determine whether the information for this identifier is out of
+ /// date with respect to the external source.
+ bool isOutOfDate() const { return OutOfDate; }
+
+ /// \brief Set whether the information for this identifier is out of
+ /// date with respect to the external source.
+ void setOutOfDate(bool OOD) {
+ OutOfDate = OOD;
+ if (OOD)
+ NeedsHandleIdentifier = true;
+ else
+ RecomputeNeedsHandleIdentifier();
+ }
+
+ /// \brief Determine whether this is the contextual keyword \c import.
+ bool isModulesImport() const { return IsModulesImport; }
+
+ /// \brief Set whether this identifier is the contextual keyword \c import.
+ void setModulesImport(bool I) {
+ IsModulesImport = I;
+ if (I)
+ NeedsHandleIdentifier = true;
+ else
+ RecomputeNeedsHandleIdentifier();
+ }
+
+ /// \brief Provide less than operator for lexicographical sorting.
+ bool operator<(const IdentifierInfo &RHS) const {
+ return getName() < RHS.getName();
+ }
+
+private:
+ /// The Preprocessor::HandleIdentifier does several special (but rare)
+ /// things to identifiers of various sorts. For example, it changes the
+ /// \c 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() | isFutureCompatKeyword() || isOutOfDate() ||
+ isModulesImport());
+ }
+};
+
+/// \brief An RAII object for [un]poisoning an identifier within a scope.
+///
+/// \p II is allowed to be null, in which case objects of this type have
+/// no effect.
+class PoisonIdentifierRAIIObject {
+ IdentifierInfo *const II;
+ const bool OldValue;
+public:
+ PoisonIdentifierRAIIObject(IdentifierInfo *II, bool NewValue)
+ : II(II), OldValue(II ? II->isPoisoned() : false) {
+ if(II)
+ II->setIsPoisoned(NewValue);
+ }
+
+ ~PoisonIdentifierRAIIObject() {
+ if(II)
+ II->setIsPoisoned(OldValue);
+ }
+};
+
+/// \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 &) = delete;
+ void operator=(const IdentifierIterator &) = delete;
+
+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 StringRef.
+ virtual StringRef Next() = 0;
+};
+
+/// \brief Provides lookups to, and iteration over, IdentiferInfo objects.
+class IdentifierInfoLookup {
+public:
+ virtual ~IdentifierInfoLookup();
+
+ /// \brief Return the IdentifierInfo 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(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();
+};
+
+/// \brief Implements an efficient mapping from strings to IdentifierInfo nodes.
+///
+/// This has no other purpose, but this is an extremely performance-critical
+/// piece of the code, as each occurrence 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:
+ /// \brief Create the identifier table, populating it with info about the
+ /// language keywords for the language specified by \p LangOpts.
+ IdentifierTable(const LangOptions &LangOpts,
+ IdentifierInfoLookup* externalLookup = nullptr);
+
+ /// \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();
+ }
+
+ /// \brief Return the identifier token info for the specified named
+ /// identifier.
+ IdentifierInfo &get(StringRef Name) {
+ auto &Entry = *HashTable.insert(std::make_pair(Name, nullptr)).first;
+
+ IdentifierInfo *&II = Entry.second;
+ if (II) return *II;
+
+ // No entry; if we have an external lookup, look there first.
+ if (ExternalLookup) {
+ II = ExternalLookup->get(Name);
+ if (II)
+ return *II;
+ }
+
+ // Lookups failed, make a new IdentifierInfo.
+ void *Mem = getAllocator().Allocate<IdentifierInfo>();
+ II = new (Mem) IdentifierInfo();
+
+ // Make sure getName() knows how to find the IdentifierInfo
+ // contents.
+ II->Entry = &Entry;
+
+ return *II;
+ }
+
+ IdentifierInfo &get(StringRef Name, tok::TokenKind TokenCode) {
+ IdentifierInfo &II = get(Name);
+ II.TokenID = TokenCode;
+ assert(II.TokenID == (unsigned) TokenCode && "TokenCode too large");
+ return II;
+ }
+
+ /// \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(StringRef Name) {
+ auto &Entry = *HashTable.insert(std::make_pair(Name, nullptr)).first;
+
+ IdentifierInfo *&II = Entry.second;
+ if (II)
+ return *II;
+
+ // Lookups failed, make a new IdentifierInfo.
+ void *Mem = getAllocator().Allocate<IdentifierInfo>();
+ II = new (Mem) IdentifierInfo();
+
+ // Make sure getName() knows how to find the IdentifierInfo
+ // contents.
+ II->Entry = &Entry;
+
+ // If this is the 'import' contextual keyword, mark it as such.
+ if (Name.equals("import"))
+ II->setModulesImport(true);
+
+ return *II;
+ }
+
+ 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(); }
+
+ /// \brief Print some statistics to stderr that indicate how well the
+ /// hashing is doing.
+ void PrintStats() const;
+
+ void AddKeywords(const LangOptions &LangOpts);
+};
+
+/// \brief A family of Objective-C methods.
+///
+/// These families have no inherent meaning in the language, but are
+/// nonetheless central enough in the existing implementations to
+/// merit direct AST support. While, in theory, arbitrary methods can
+/// be considered to form families, we focus here on the methods
+/// involving allocation and retain-count management, as these are the
+/// most "core" and the most likely to be useful to diverse clients
+/// without extra information.
+///
+/// Both selectors and actual method declarations may be classified
+/// into families. Method families may impose additional restrictions
+/// beyond their selector name; for example, a method called '_init'
+/// that returns void is not considered to be in the 'init' family
+/// (but would be if it returned 'id'). It is also possible to
+/// explicitly change or remove a method's family. Therefore the
+/// method's family should be considered the single source of truth.
+enum ObjCMethodFamily {
+ /// \brief No particular method family.
+ OMF_None,
+
+ // Selectors in these families may have arbitrary arity, may be
+ // written with arbitrary leading underscores, and may have
+ // additional CamelCase "words" in their first selector chunk
+ // following the family name.
+ OMF_alloc,
+ OMF_copy,
+ OMF_init,
+ OMF_mutableCopy,
+ OMF_new,
+
+ // These families are singletons consisting only of the nullary
+ // selector with the given name.
+ OMF_autorelease,
+ OMF_dealloc,
+ OMF_finalize,
+ OMF_release,
+ OMF_retain,
+ OMF_retainCount,
+ OMF_self,
+ OMF_initialize,
+
+ // performSelector families
+ OMF_performSelector
+};
+
+/// Enough bits to store any enumerator in ObjCMethodFamily or
+/// InvalidObjCMethodFamily.
+enum { ObjCMethodFamilyBitWidth = 4 };
+
+/// \brief An invalid value of ObjCMethodFamily.
+enum { InvalidObjCMethodFamily = (1 << ObjCMethodFamilyBitWidth) - 1 };
+
+/// \brief A family of Objective-C methods.
+///
+/// These are family of methods whose result type is initially 'id', but
+/// but are candidate for the result type to be changed to 'instancetype'.
+enum ObjCInstanceTypeFamily {
+ OIT_None,
+ OIT_Array,
+ OIT_Dictionary,
+ OIT_Singleton,
+ OIT_Init,
+ OIT_ReturnsSelf
+};
+
+enum ObjCStringFormatFamily {
+ SFF_None,
+ SFF_NSString,
+ SFF_CFString
+};
+
+/// \brief Smart pointer class that 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 Diagnostic;
+
+ enum IdentifierInfoFlag {
+ // Empty selector = 0.
+ ZeroArg = 0x1,
+ OneArg = 0x2,
+ MultiArg = 0x3,
+ 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");
+ InfoPtr |= MultiArg;
+ }
+
+ IdentifierInfo *getAsIdentifierInfo() const {
+ if (getIdentifierInfoFlag() < MultiArg)
+ return reinterpret_cast<IdentifierInfo *>(InfoPtr & ~ArgFlags);
+ return nullptr;
+ }
+ MultiKeywordSelector *getMultiKeywordSelector() const {
+ return reinterpret_cast<MultiKeywordSelector *>(InfoPtr & ~ArgFlags);
+ }
+
+ unsigned getIdentifierInfoFlag() const {
+ return InfoPtr & ArgFlags;
+ }
+
+ static ObjCMethodFamily getMethodFamilyImpl(Selector sel);
+
+ static ObjCStringFormatFamily getStringFormatFamilyImpl(Selector sel);
+
+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.
+ StringRef getNameForSlot(unsigned argIndex) const;
+
+ /// \brief Derive the full selector name (e.g. "foo:bar:") and return
+ /// it as an std::string.
+ std::string getAsString() const;
+
+ /// \brief Prints the full selector name (e.g. "foo:bar:").
+ void print(llvm::raw_ostream &OS) const;
+
+ /// \brief Derive the conventional family of this method.
+ ObjCMethodFamily getMethodFamily() const {
+ return getMethodFamilyImpl(*this);
+ }
+
+ ObjCStringFormatFamily getStringFormatFamily() const {
+ return getStringFormatFamilyImpl(*this);
+ }
+
+ static Selector getEmptyMarker() {
+ return Selector(uintptr_t(-1));
+ }
+ static Selector getTombstoneMarker() {
+ return Selector(uintptr_t(-2));
+ }
+
+ static ObjCInstanceTypeFamily getInstTypeMethodFamily(Selector sel);
+};
+
+/// \brief This table allows us to fully hide how we implement
+/// multi-keyword caching.
+class SelectorTable {
+ void *Impl; // Actually a SelectorTableImpl
+ SelectorTable(const SelectorTable &) = delete;
+ void operator=(const SelectorTable &) = delete;
+public:
+ SelectorTable();
+ ~SelectorTable();
+
+ /// \brief Can create any sort of selector.
+ ///
+ /// \p 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);
+ }
+
+ /// \brief Return the total amount of memory allocated for managing selectors.
+ size_t getTotalMemory() const;
+
+ /// \brief Return the default setter name for the given identifier.
+ ///
+ /// This is "set" + \p Name where the initial character of \p Name
+ /// has been capitalized.
+ static SmallString<64> constructSetterName(StringRef Name);
+
+ /// \brief Return the default setter selector for the given identifier.
+ ///
+ /// This is "set" + \p Name where the initial character of \p Name
+ /// has been capitalized.
+ static Selector constructSetterSelector(IdentifierTable &Idents,
+ SelectorTable &SelTable,
+ const IdentifierInfo *Name);
+};
+
+/// 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 <typename T> class PointerLikeTypeTraits;
+
+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/LLVM.h b/contrib/llvm/tools/clang/include/clang/Basic/LLVM.h
new file mode 100644
index 0000000..0e6ff92
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Basic/LLVM.h
@@ -0,0 +1,83 @@
+//===--- LLVM.h - Import various common LLVM datatypes ----------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+/// \file
+/// \brief Forward-declares and imports various common LLVM datatypes that
+/// clang wants to use unqualified.
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_BASIC_LLVM_H
+#define LLVM_CLANG_BASIC_LLVM_H
+
+// Do not proliferate #includes here, require clients to #include their
+// dependencies.
+// Casting.h has complex templates that cannot be easily forward declared.
+#include "llvm/Support/Casting.h"
+// None.h includes an enumerator that is desired & cannot be forward declared
+// without a definition of NoneType.
+#include "llvm/ADT/None.h"
+
+namespace llvm {
+ // ADT's.
+ class StringRef;
+ class Twine;
+ template<typename T> class ArrayRef;
+ template<typename T> class MutableArrayRef;
+ template<unsigned InternalLen> class SmallString;
+ template<typename T, unsigned N> class SmallVector;
+ template<typename T> class SmallVectorImpl;
+ template<typename T> class Optional;
+
+ template<typename T>
+ struct SaveAndRestore;
+
+ // Reference counting.
+ template <typename T> class IntrusiveRefCntPtr;
+ template <typename T> struct IntrusiveRefCntPtrInfo;
+ template <class Derived> class RefCountedBase;
+ class RefCountedBaseVPTR;
+
+ class raw_ostream;
+ class raw_pwrite_stream;
+ // TODO: DenseMap, ...
+}
+
+
+namespace clang {
+ // Casting operators.
+ using llvm::isa;
+ using llvm::cast;
+ using llvm::dyn_cast;
+ using llvm::dyn_cast_or_null;
+ using llvm::cast_or_null;
+
+ // ADT's.
+ using llvm::None;
+ using llvm::Optional;
+ using llvm::StringRef;
+ using llvm::Twine;
+ using llvm::ArrayRef;
+ using llvm::MutableArrayRef;
+ using llvm::SmallString;
+ using llvm::SmallVector;
+ using llvm::SmallVectorImpl;
+ using llvm::SaveAndRestore;
+
+ // Reference counting.
+ using llvm::IntrusiveRefCntPtr;
+ using llvm::IntrusiveRefCntPtrInfo;
+ using llvm::RefCountedBase;
+ using llvm::RefCountedBaseVPTR;
+
+ using llvm::raw_ostream;
+ using llvm::raw_pwrite_stream;
+} // end namespace clang.
+
+#endif
diff --git a/contrib/llvm/tools/clang/include/clang/Basic/Lambda.h b/contrib/llvm/tools/clang/include/clang/Basic/Lambda.h
new file mode 100644
index 0000000..e676e72
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Basic/Lambda.h
@@ -0,0 +1,43 @@
+//===--- Lambda.h - Types for C++ Lambdas -----------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+///
+/// \file
+/// \brief Defines several types used to describe C++ lambda expressions
+/// that are shared between the parser and AST.
+///
+//===----------------------------------------------------------------------===//
+
+
+#ifndef LLVM_CLANG_BASIC_LAMBDA_H
+#define LLVM_CLANG_BASIC_LAMBDA_H
+
+namespace clang {
+
+/// \brief The default, if any, capture method for a lambda expression.
+enum LambdaCaptureDefault {
+ LCD_None,
+ LCD_ByCopy,
+ LCD_ByRef
+};
+
+/// \brief The different capture forms in a lambda introducer
+///
+/// C++11 allows capture of \c this, or of local variables by copy or
+/// by reference. C++1y also allows "init-capture", where the initializer
+/// is an expression.
+enum LambdaCaptureKind {
+ LCK_This, ///< Capturing the \c this pointer
+ LCK_ByCopy, ///< Capturing by copy (a.k.a., by value)
+ LCK_ByRef, ///< Capturing by reference
+ LCK_VLAType ///< Capturing variable-length array type
+};
+
+} // end namespace clang
+
+#endif // LLVM_CLANG_BASIC_LAMBDA_H
diff --git a/contrib/llvm/tools/clang/include/clang/Basic/LangOptions.def b/contrib/llvm/tools/clang/include/clang/Basic/LangOptions.def
new file mode 100644
index 0000000..cc70d62
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Basic/LangOptions.def
@@ -0,0 +1,246 @@
+//===--- LangOptions.def - Language option 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 language options. Users of this file must
+// define the LANGOPT macro to make use of this information.
+//
+// Optionally, the user may also define:
+//
+// BENIGN_LANGOPT: for options that don't affect the construction of the AST in
+// any way (that is, the value can be different between an implicit module
+// and the user of that module).
+//
+// COMPATIBLE_LANGOPT: for options that affect the construction of the AST in
+// a way that doesn't prevent interoperability (that is, the value can be
+// different between an explicit module and the user of that module).
+//
+// ENUM_LANGOPT: for options that have enumeration, rather than unsigned, type.
+//
+// VALUE_LANGOPT: for options that describe a value rather than a flag.
+//
+// BENIGN_ENUM_LANGOPT, COMPATIBLE_ENUM_LANGOPT: combinations of the above.
+//
+// FIXME: Clients should be able to more easily select whether they want
+// different levels of compatibility versus how to handle different kinds
+// of option.
+//===----------------------------------------------------------------------===//
+
+#ifndef LANGOPT
+# error Define the LANGOPT macro to handle language options
+#endif
+
+#ifndef COMPATIBLE_LANGOPT
+# define COMPATIBLE_LANGOPT(Name, Bits, Default, Description) \
+ LANGOPT(Name, Bits, Default, Description)
+#endif
+
+#ifndef BENIGN_LANGOPT
+# define BENIGN_LANGOPT(Name, Bits, Default, Description) \
+ COMPATIBLE_LANGOPT(Name, Bits, Default, Description)
+#endif
+
+#ifndef ENUM_LANGOPT
+# define ENUM_LANGOPT(Name, Type, Bits, Default, Description) \
+ LANGOPT(Name, Bits, Default, Description)
+#endif
+
+#ifndef COMPATIBLE_ENUM_LANGOPT
+# define COMPATIBLE_ENUM_LANGOPT(Name, Type, Bits, Default, Description) \
+ ENUM_LANGOPT(Name, Type, Bits, Default, Description)
+#endif
+
+#ifndef BENIGN_ENUM_LANGOPT
+# define BENIGN_ENUM_LANGOPT(Name, Type, Bits, Default, Description) \
+ COMPATIBLE_ENUM_LANGOPT(Name, Type, Bits, Default, Description)
+#endif
+
+#ifndef VALUE_LANGOPT
+# define VALUE_LANGOPT(Name, Bits, Default, Description) \
+ LANGOPT(Name, Bits, Default, Description)
+#endif
+
+// FIXME: A lot of the BENIGN_ options should be COMPATIBLE_ instead.
+LANGOPT(C99 , 1, 0, "C99")
+LANGOPT(C11 , 1, 0, "C11")
+LANGOPT(MSVCCompat , 1, 0, "Microsoft Visual C++ full compatibility mode")
+LANGOPT(MicrosoftExt , 1, 0, "Microsoft C++ extensions")
+LANGOPT(AsmBlocks , 1, 0, "Microsoft inline asm blocks")
+LANGOPT(Borland , 1, 0, "Borland extensions")
+LANGOPT(CPlusPlus , 1, 0, "C++")
+LANGOPT(CPlusPlus11 , 1, 0, "C++11")
+LANGOPT(CPlusPlus14 , 1, 0, "C++14")
+LANGOPT(CPlusPlus1z , 1, 0, "C++1z")
+LANGOPT(ObjC1 , 1, 0, "Objective-C 1")
+LANGOPT(ObjC2 , 1, 0, "Objective-C 2")
+BENIGN_LANGOPT(ObjCDefaultSynthProperties , 1, 0,
+ "Objective-C auto-synthesized properties")
+BENIGN_LANGOPT(EncodeExtendedBlockSig , 1, 0,
+ "Encoding extended block type signature")
+BENIGN_LANGOPT(ObjCInferRelatedResultType , 1, 1,
+ "Objective-C related result type inference")
+LANGOPT(AppExt , 1, 0, "Objective-C App Extension")
+LANGOPT(Trigraphs , 1, 0,"trigraphs")
+LANGOPT(LineComment , 1, 0, "'//' comments")
+LANGOPT(Bool , 1, 0, "bool, true, and false keywords")
+LANGOPT(Half , 1, 0, "half keyword")
+LANGOPT(WChar , 1, CPlusPlus, "wchar_t keyword")
+LANGOPT(DeclSpecKeyword , 1, 0, "__declspec keyword")
+BENIGN_LANGOPT(DollarIdents , 1, 1, "'$' in identifiers")
+BENIGN_LANGOPT(AsmPreprocessor, 1, 0, "preprocessor in asm mode")
+BENIGN_LANGOPT(GNUMode , 1, 1, "GNU extensions")
+LANGOPT(GNUKeywords , 1, 1, "GNU keywords")
+BENIGN_LANGOPT(ImplicitInt, 1, !C99 && !CPlusPlus, "C89 implicit 'int'")
+LANGOPT(Digraphs , 1, 0, "digraphs")
+BENIGN_LANGOPT(HexFloats , 1, C99, "C99 hexadecimal float constants")
+LANGOPT(CXXOperatorNames , 1, 0, "C++ operator name keywords")
+LANGOPT(AppleKext , 1, 0, "Apple kext support")
+BENIGN_LANGOPT(PascalStrings, 1, 0, "Pascal string support")
+LANGOPT(WritableStrings , 1, 0, "writable string support")
+LANGOPT(ConstStrings , 1, 0, "const-qualified string support")
+LANGOPT(LaxVectorConversions , 1, 1, "lax vector conversions")
+LANGOPT(AltiVec , 1, 0, "AltiVec-style vector initializers")
+LANGOPT(ZVector , 1, 0, "System z vector extensions")
+LANGOPT(Exceptions , 1, 0, "exception handling")
+LANGOPT(ObjCExceptions , 1, 0, "Objective-C exceptions")
+LANGOPT(CXXExceptions , 1, 0, "C++ exceptions")
+LANGOPT(SjLjExceptions , 1, 0, "setjmp-longjump exception handling")
+LANGOPT(TraditionalCPP , 1, 0, "traditional CPP emulation")
+LANGOPT(RTTI , 1, 1, "run-time type information")
+LANGOPT(RTTIData , 1, 1, "emit run-time type information data")
+LANGOPT(MSBitfields , 1, 0, "Microsoft-compatible structure layout")
+LANGOPT(Freestanding, 1, 0, "freestanding implementation")
+LANGOPT(NoBuiltin , 1, 0, "disable builtin functions")
+LANGOPT(NoMathBuiltin , 1, 0, "disable math builtin functions")
+LANGOPT(GNUAsm , 1, 1, "GNU-style inline assembly")
+LANGOPT(Coroutines , 1, 0, "C++ coroutines")
+
+BENIGN_LANGOPT(ThreadsafeStatics , 1, 1, "thread-safe static initializers")
+LANGOPT(POSIXThreads , 1, 0, "POSIX thread support")
+LANGOPT(Blocks , 1, 0, "blocks extension to C")
+BENIGN_LANGOPT(EmitAllDecls , 1, 0, "support for emitting all declarations")
+LANGOPT(MathErrno , 1, 1, "errno support for math functions")
+BENIGN_LANGOPT(HeinousExtensions , 1, 0, "Extensions that we really don't like and may be ripped out at any time")
+LANGOPT(Modules , 1, 0, "modules extension to C")
+COMPATIBLE_LANGOPT(ModulesDeclUse , 1, 0, "require declaration of module uses")
+LANGOPT(ModulesSearchAll , 1, 1, "search even non-imported modules to find unresolved references")
+COMPATIBLE_LANGOPT(ModulesStrictDeclUse, 1, 0, "require declaration of module uses and all headers to be in modules")
+BENIGN_LANGOPT(ModulesErrorRecovery, 1, 1, "automatically import modules as needed when performing error recovery")
+BENIGN_LANGOPT(ImplicitModules, 1, 1, "build modules that are not specified via -fmodule-file")
+COMPATIBLE_LANGOPT(ModulesLocalVisibility, 1, 0, "local submodule visibility")
+COMPATIBLE_LANGOPT(Optimize , 1, 0, "__OPTIMIZE__ predefined macro")
+COMPATIBLE_LANGOPT(OptimizeSize , 1, 0, "__OPTIMIZE_SIZE__ predefined macro")
+LANGOPT(Static , 1, 0, "__STATIC__ predefined macro (as opposed to __DYNAMIC__)")
+VALUE_LANGOPT(PackStruct , 32, 0,
+ "default struct packing maximum alignment")
+VALUE_LANGOPT(MaxTypeAlign , 32, 0,
+ "default maximum alignment for types")
+VALUE_LANGOPT(PICLevel , 2, 0, "__PIC__ level")
+VALUE_LANGOPT(PIELevel , 2, 0, "__PIE__ level")
+LANGOPT(GNUInline , 1, 0, "GNU inline semantics")
+COMPATIBLE_LANGOPT(NoInlineDefine , 1, 0, "__NO_INLINE__ predefined macro")
+COMPATIBLE_LANGOPT(Deprecated , 1, 0, "__DEPRECATED predefined macro")
+LANGOPT(FastMath , 1, 0, "__FAST_MATH__ predefined macro")
+LANGOPT(FiniteMathOnly , 1, 0, "__FINITE_MATH_ONLY__ predefined macro")
+LANGOPT(UnsafeFPMath , 1, 0, "Unsafe Floating Point Math")
+
+BENIGN_LANGOPT(ObjCGCBitmapPrint , 1, 0, "printing of GC's bitmap layout for __weak/__strong ivars")
+
+BENIGN_LANGOPT(AccessControl , 1, 1, "C++ access control")
+LANGOPT(CharIsSigned , 1, 1, "signed char")
+LANGOPT(ShortWChar , 1, 0, "unsigned short wchar_t")
+ENUM_LANGOPT(MSPointerToMemberRepresentationMethod, PragmaMSPointersToMembersKind, 2, PPTMK_BestCase, "member-pointer representation method")
+
+LANGOPT(ShortEnums , 1, 0, "short enum types")
+
+LANGOPT(OpenCL , 1, 0, "OpenCL")
+LANGOPT(OpenCLVersion , 32, 0, "OpenCL version")
+LANGOPT(NativeHalfType , 1, 0, "Native half type support")
+LANGOPT(HalfArgsAndReturns, 1, 0, "half args and returns")
+LANGOPT(CUDA , 1, 0, "CUDA")
+LANGOPT(OpenMP , 1, 0, "OpenMP support")
+LANGOPT(OpenMPUseTLS , 1, 0, "Use TLS for threadprivates or runtime calls")
+LANGOPT(OpenMPIsDevice , 1, 0, "Generate code only for OpenMP target device")
+
+LANGOPT(CUDAIsDevice , 1, 0, "Compiling for CUDA device")
+LANGOPT(CUDAAllowHostCallsFromHostDevice, 1, 0, "Allow host device functions to call host functions")
+LANGOPT(CUDADisableTargetCallChecks, 1, 0, "Disable checks for call targets (host, device, etc.)")
+LANGOPT(CUDATargetOverloads, 1, 0, "Enable function overloads based on CUDA target attributes")
+
+LANGOPT(AssumeSaneOperatorNew , 1, 1, "implicit __attribute__((malloc)) for C++'s new operators")
+LANGOPT(SizedDeallocation , 1, 0, "enable sized deallocation functions")
+LANGOPT(ConceptsTS , 1, 0, "enable C++ Extensions for Concepts")
+BENIGN_LANGOPT(ElideConstructors , 1, 1, "C++ copy constructor elision")
+BENIGN_LANGOPT(DumpRecordLayouts , 1, 0, "dumping the layout of IRgen'd records")
+BENIGN_LANGOPT(DumpRecordLayoutsSimple , 1, 0, "dumping the layout of IRgen'd records in a simple form")
+BENIGN_LANGOPT(DumpVTableLayouts , 1, 0, "dumping the layouts of emitted vtables")
+LANGOPT(NoConstantCFStrings , 1, 0, "no constant CoreFoundation strings")
+BENIGN_LANGOPT(InlineVisibilityHidden , 1, 0, "hidden default visibility for inline C++ methods")
+BENIGN_LANGOPT(ParseUnknownAnytype, 1, 0, "__unknown_anytype")
+BENIGN_LANGOPT(DebuggerSupport , 1, 0, "debugger support")
+BENIGN_LANGOPT(DebuggerCastResultToId, 1, 0, "for 'po' in the debugger, cast the result to id if it is of unknown type")
+BENIGN_LANGOPT(DebuggerObjCLiteral , 1, 0, "debugger Objective-C literals and subscripting support")
+
+BENIGN_LANGOPT(SpellChecking , 1, 1, "spell-checking")
+LANGOPT(SinglePrecisionConstants , 1, 0, "treating double-precision floating point constants as single precision constants")
+LANGOPT(FastRelaxedMath , 1, 0, "OpenCL fast relaxed math")
+LANGOPT(DefaultFPContract , 1, 0, "FP_CONTRACT")
+LANGOPT(NoBitFieldTypeAlign , 1, 0, "bit-field type alignment")
+LANGOPT(HexagonQdsp6Compat , 1, 0, "hexagon-qdsp6 backward compatibility")
+LANGOPT(ObjCAutoRefCount , 1, 0, "Objective-C automated reference counting")
+LANGOPT(ObjCWeakRuntime , 1, 0, "__weak support in the ARC runtime")
+LANGOPT(ObjCWeak , 1, 0, "Objective-C __weak in ARC and MRC files")
+LANGOPT(ObjCSubscriptingLegacyRuntime , 1, 0, "Subscripting support in legacy ObjectiveC runtime")
+LANGOPT(FakeAddressSpaceMap , 1, 0, "OpenCL fake address space map")
+ENUM_LANGOPT(AddressSpaceMapMangling , AddrSpaceMapMangling, 2, ASMM_Target, "OpenCL address space map mangling mode")
+
+LANGOPT(MRTD , 1, 0, "-mrtd calling convention")
+BENIGN_LANGOPT(DelayedTemplateParsing , 1, 0, "delayed template parsing")
+LANGOPT(BlocksRuntimeOptional , 1, 0, "optional blocks runtime")
+
+ENUM_LANGOPT(GC, GCMode, 2, NonGC, "Objective-C Garbage Collection mode")
+ENUM_LANGOPT(ValueVisibilityMode, Visibility, 3, DefaultVisibility,
+ "value symbol visibility")
+ENUM_LANGOPT(TypeVisibilityMode, Visibility, 3, DefaultVisibility,
+ "type symbol visibility")
+ENUM_LANGOPT(StackProtector, StackProtectorMode, 2, SSPOff,
+ "stack protector mode")
+ENUM_LANGOPT(SignedOverflowBehavior, SignedOverflowBehaviorTy, 2, SOB_Undefined,
+ "signed integer overflow handling")
+
+BENIGN_LANGOPT(ArrowDepth, 32, 256,
+ "maximum number of operator->s to follow")
+BENIGN_LANGOPT(InstantiationDepth, 32, 256,
+ "maximum template instantiation depth")
+BENIGN_LANGOPT(ConstexprCallDepth, 32, 512,
+ "maximum constexpr call depth")
+BENIGN_LANGOPT(ConstexprStepLimit, 32, 1048576,
+ "maximum constexpr evaluation steps")
+BENIGN_LANGOPT(BracketDepth, 32, 256,
+ "maximum bracket nesting depth")
+BENIGN_LANGOPT(NumLargeByValueCopy, 32, 0,
+ "if non-zero, warn about parameter or return Warn if parameter/return value is larger in bytes than this setting. 0 is no check.")
+VALUE_LANGOPT(MSCompatibilityVersion, 32, 0, "Microsoft Visual C/C++ Version")
+VALUE_LANGOPT(VtorDispMode, 2, 1, "How many vtordisps to insert")
+
+LANGOPT(ApplePragmaPack, 1, 0, "Apple gcc-compatible #pragma pack handling")
+
+LANGOPT(RetainCommentsFromSystemHeaders, 1, 0, "retain documentation comments from system headers in the AST")
+
+LANGOPT(SanitizeAddressFieldPadding, 2, 0, "controls how aggressive is ASan "
+ "field padding (0: none, 1:least "
+ "aggressive, 2: more aggressive)")
+
+#undef LANGOPT
+#undef COMPATIBLE_LANGOPT
+#undef BENIGN_LANGOPT
+#undef ENUM_LANGOPT
+#undef COMPATIBLE_ENUM_LANGOPT
+#undef BENIGN_ENUM_LANGOPT
+#undef VALUE_LANGOPT
+
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..736d4e0
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Basic/LangOptions.h
@@ -0,0 +1,190 @@
+//===--- 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.
+//
+//===----------------------------------------------------------------------===//
+///
+/// \file
+/// \brief Defines the clang::LangOptions interface.
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_BASIC_LANGOPTIONS_H
+#define LLVM_CLANG_BASIC_LANGOPTIONS_H
+
+#include "clang/Basic/CommentOptions.h"
+#include "clang/Basic/LLVM.h"
+#include "clang/Basic/ObjCRuntime.h"
+#include "clang/Basic/Sanitizers.h"
+#include "clang/Basic/Visibility.h"
+#include <string>
+#include <vector>
+
+namespace clang {
+
+/// Bitfields of LangOptions, split out from LangOptions in order to ensure that
+/// this large collection of bitfields is a trivial class type.
+class LangOptionsBase {
+public:
+ // Define simple language options (with no accessors).
+#define LANGOPT(Name, Bits, Default, Description) unsigned Name : Bits;
+#define ENUM_LANGOPT(Name, Type, Bits, Default, Description)
+#include "clang/Basic/LangOptions.def"
+
+protected:
+ // Define language options of enumeration type. These are private, and will
+ // have accessors (below).
+#define LANGOPT(Name, Bits, Default, Description)
+#define ENUM_LANGOPT(Name, Type, Bits, Default, Description) \
+ unsigned Name : Bits;
+#include "clang/Basic/LangOptions.def"
+};
+
+/// \brief Keeps track of the various options that can be
+/// enabled, which controls the dialect of C or C++ that is accepted.
+class LangOptions : public LangOptionsBase {
+public:
+ typedef clang::Visibility Visibility;
+
+ enum GCMode { NonGC, GCOnly, HybridGC };
+ enum StackProtectorMode { SSPOff, SSPOn, SSPStrong, SSPReq };
+
+ enum SignedOverflowBehaviorTy {
+ SOB_Undefined, // Default C standard behavior.
+ SOB_Defined, // -fwrapv
+ SOB_Trapping // -ftrapv
+ };
+
+ enum PragmaMSPointersToMembersKind {
+ PPTMK_BestCase,
+ PPTMK_FullGeneralitySingleInheritance,
+ PPTMK_FullGeneralityMultipleInheritance,
+ PPTMK_FullGeneralityVirtualInheritance
+ };
+
+ enum AddrSpaceMapMangling { ASMM_Target, ASMM_On, ASMM_Off };
+
+ enum MSVCMajorVersion {
+ MSVC2010 = 16,
+ MSVC2012 = 17,
+ MSVC2013 = 18,
+ MSVC2015 = 19
+ };
+
+public:
+ /// \brief Set of enabled sanitizers.
+ SanitizerSet Sanitize;
+
+ /// \brief Paths to blacklist files specifying which objects
+ /// (files, functions, variables) should not be instrumented.
+ std::vector<std::string> SanitizerBlacklistFiles;
+
+ clang::ObjCRuntime ObjCRuntime;
+
+ std::string ObjCConstantStringClass;
+
+ /// \brief The name of the handler function to be called when -ftrapv is
+ /// specified.
+ ///
+ /// If none is specified, abort (GCC-compatible behaviour).
+ std::string OverflowHandler;
+
+ /// \brief The name of the current module.
+ std::string CurrentModule;
+
+ /// \brief The name of the module that the translation unit is an
+ /// implementation of. Prevents semantic imports, but does not otherwise
+ /// treat this as the CurrentModule.
+ std::string ImplementationOfModule;
+
+ /// \brief The names of any features to enable in module 'requires' decls
+ /// in addition to the hard-coded list in Module.cpp and the target features.
+ ///
+ /// This list is sorted.
+ std::vector<std::string> ModuleFeatures;
+
+ /// \brief Options for parsing comments.
+ CommentOptions CommentOpts;
+
+ /// \brief A list of all -fno-builtin-* function names (e.g., memset).
+ std::vector<std::string> NoBuiltinFuncs;
+
+ /// \brief Triples of the OpenMP targets that the host code codegen should
+ /// take into account in order to generate accurate offloading descriptors.
+ std::vector<llvm::Triple> OMPTargetTriples;
+
+ /// \brief Name of the IR file that contains the result of the OpenMP target
+ /// host code generation.
+ std::string OMPHostIRFile;
+
+ LangOptions();
+
+ // Define accessors/mutators for language options of enumeration type.
+#define LANGOPT(Name, Bits, Default, Description)
+#define ENUM_LANGOPT(Name, Type, Bits, Default, Description) \
+ Type get##Name() const { return static_cast<Type>(Name); } \
+ void set##Name(Type Value) { Name = static_cast<unsigned>(Value); }
+#include "clang/Basic/LangOptions.def"
+
+ bool isSignedOverflowDefined() const {
+ return getSignedOverflowBehavior() == SOB_Defined;
+ }
+
+ bool isSubscriptPointerArithmetic() const {
+ return ObjCRuntime.isSubscriptPointerArithmetic() &&
+ !ObjCSubscriptingLegacyRuntime;
+ }
+
+ bool isCompatibleWithMSVC(MSVCMajorVersion MajorVersion) const {
+ return MSCompatibilityVersion >= MajorVersion * 10000000U;
+ }
+
+ /// \brief Reset all of the options that are not considered when building a
+ /// module.
+ void resetNonModularOptions();
+
+ /// \brief Is this a libc/libm function that is no longer recognized as a
+ /// builtin because a -fno-builtin-* option has been specified?
+ bool isNoBuiltinFunc(const char *Name) const;
+};
+
+/// \brief Floating point control options
+class FPOptions {
+public:
+ unsigned fp_contract : 1;
+
+ FPOptions() : fp_contract(0) {}
+
+ FPOptions(const LangOptions &LangOpts) :
+ fp_contract(LangOpts.DefaultFPContract) {}
+};
+
+/// \brief 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"
+ }
+};
+
+/// \brief Describes the kind of translation unit being processed.
+enum TranslationUnitKind {
+ /// \brief The translation unit is a complete translation unit.
+ TU_Complete,
+ /// \brief The translation unit is a prefix to a translation unit, and is
+ /// not complete.
+ TU_Prefix,
+ /// \brief The translation unit is a module.
+ TU_Module
+};
+
+} // 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..8b15c8e
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Basic/Linkage.h
@@ -0,0 +1,110 @@
+//===--- 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.
+//
+//===----------------------------------------------------------------------===//
+///
+/// \file
+/// \brief Defines the Linkage enumeration and various utility functions.
+///
+//===----------------------------------------------------------------------===//
+#ifndef LLVM_CLANG_BASIC_LINKAGE_H
+#define LLVM_CLANG_BASIC_LINKAGE_H
+
+#include <assert.h>
+#include <stdint.h>
+#include <utility>
+
+namespace clang {
+
+/// \brief Describes the different kinds of linkage
+/// (C++ [basic.link], C99 6.2.2) that an entity may have.
+enum Linkage : unsigned char {
+ /// \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 language 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 No linkage according to the standard, but is visible from other
+ /// translation units because of types defined in a inline function.
+ VisibleNoLinkage,
+
+ /// \brief External linkage, which indicates that the entity can
+ /// be referred to from other translation units.
+ ExternalLinkage
+};
+
+/// \brief Describes the different kinds of language linkage
+/// (C++ [dcl.link]) that an entity may have.
+enum LanguageLinkage {
+ CLanguageLinkage,
+ CXXLanguageLinkage,
+ NoLanguageLinkage
+};
+
+/// \brief A more specific kind of linkage than enum Linkage.
+///
+/// This is relevant to CodeGen and AST file reading.
+enum GVALinkage {
+ GVA_Internal,
+ GVA_AvailableExternally,
+ GVA_DiscardableODR,
+ GVA_StrongExternal,
+ GVA_StrongODR
+};
+
+inline bool isExternallyVisible(Linkage L) {
+ return L == ExternalLinkage || L == VisibleNoLinkage;
+}
+
+inline Linkage getFormalLinkage(Linkage L) {
+ if (L == UniqueExternalLinkage)
+ return ExternalLinkage;
+ if (L == VisibleNoLinkage)
+ return NoLinkage;
+ return L;
+}
+
+inline bool isExternalFormalLinkage(Linkage L) {
+ return getFormalLinkage(L) == ExternalLinkage;
+}
+
+/// \brief Compute the minimum linkage given two linkages.
+///
+/// The linkage can be interpreted as a pair formed by the formal linkage and
+/// a boolean for external visibility. This is just what getFormalLinkage and
+/// isExternallyVisible return. We want the minimum of both components. The
+/// Linkage enum is defined in an order that makes this simple, we just need
+/// special cases for when VisibleNoLinkage would lose the visible bit and
+/// become NoLinkage.
+inline Linkage minLinkage(Linkage L1, Linkage L2) {
+ if (L2 == VisibleNoLinkage)
+ std::swap(L1, L2);
+ if (L1 == VisibleNoLinkage) {
+ if (L2 == InternalLinkage)
+ return NoLinkage;
+ if (L2 == UniqueExternalLinkage)
+ return NoLinkage;
+ }
+ 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..9a9eaa2
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Basic/MacroBuilder.h
@@ -0,0 +1,48 @@
+//===--- 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.
+//
+//===----------------------------------------------------------------------===//
+///
+/// \file
+/// \brief Defines the clang::MacroBuilder utility class.
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_BASIC_MACROBUILDER_H
+#define LLVM_CLANG_BASIC_MACROBUILDER_H
+
+#include "clang/Basic/LLVM.h"
+#include "llvm/ADT/Twine.h"
+#include "llvm/Support/raw_ostream.h"
+
+namespace clang {
+
+class MacroBuilder {
+ raw_ostream &Out;
+public:
+ MacroBuilder(raw_ostream &Output) : Out(Output) {}
+
+ /// Append a \#define line for macro of the form "\#define Name Value\n".
+ void defineMacro(const Twine &Name, const 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 Twine &Name) {
+ Out << "#undef " << Name << '\n';
+ }
+
+ /// Directly append Str and a newline to the underlying buffer.
+ void append(const Twine &Str) {
+ Out << Str << '\n';
+ }
+};
+
+} // end namespace clang
+
+#endif
diff --git a/contrib/llvm/tools/clang/include/clang/Basic/Module.h b/contrib/llvm/tools/clang/include/clang/Basic/Module.h
new file mode 100644
index 0000000..1702fb1
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Basic/Module.h
@@ -0,0 +1,569 @@
+//===--- Module.h - Describe a module ---------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+///
+/// \file
+/// \brief Defines the clang::Module class, which describes a module in the
+/// source code.
+///
+//===----------------------------------------------------------------------===//
+#ifndef LLVM_CLANG_BASIC_MODULE_H
+#define LLVM_CLANG_BASIC_MODULE_H
+
+#include "clang/Basic/FileManager.h"
+#include "clang/Basic/SourceLocation.h"
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/DenseSet.h"
+#include "llvm/ADT/PointerIntPair.h"
+#include "llvm/ADT/PointerUnion.h"
+#include "llvm/ADT/SetVector.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/StringMap.h"
+#include "llvm/ADT/StringRef.h"
+#include <string>
+#include <utility>
+#include <vector>
+
+namespace llvm {
+ class raw_ostream;
+}
+
+namespace clang {
+
+class LangOptions;
+class TargetInfo;
+class IdentifierInfo;
+
+/// \brief Describes the name of a module.
+typedef SmallVector<std::pair<std::string, SourceLocation>, 2> ModuleId;
+
+/// \brief Describes a module or submodule.
+class Module {
+public:
+ /// \brief The name of this module.
+ std::string Name;
+
+ /// \brief The location of the module definition.
+ SourceLocation DefinitionLoc;
+
+ /// \brief The parent of this module. This will be NULL for the top-level
+ /// module.
+ Module *Parent;
+
+ /// \brief The build directory of this module. This is the directory in
+ /// which the module is notionally built, and relative to which its headers
+ /// are found.
+ const DirectoryEntry *Directory;
+
+ /// \brief The umbrella header or directory.
+ llvm::PointerUnion<const DirectoryEntry *, const FileEntry *> Umbrella;
+
+ /// \brief The module signature.
+ uint64_t Signature;
+
+ /// \brief The name of the umbrella entry, as written in the module map.
+ std::string UmbrellaAsWritten;
+
+private:
+ /// \brief The submodules of this module, indexed by name.
+ std::vector<Module *> SubModules;
+
+ /// \brief A mapping from the submodule name to the index into the
+ /// \c SubModules vector at which that submodule resides.
+ llvm::StringMap<unsigned> SubModuleIndex;
+
+ /// \brief The AST file if this is a top-level module which has a
+ /// corresponding serialized AST file, or null otherwise.
+ const FileEntry *ASTFile;
+
+ /// \brief The top-level headers associated with this module.
+ llvm::SmallSetVector<const FileEntry *, 2> TopHeaders;
+
+ /// \brief top-level header filenames that aren't resolved to FileEntries yet.
+ std::vector<std::string> TopHeaderNames;
+
+ /// \brief Cache of modules visible to lookup in this module.
+ mutable llvm::DenseSet<const Module*> VisibleModulesCache;
+
+ /// The ID used when referencing this module within a VisibleModuleSet.
+ unsigned VisibilityID;
+
+public:
+ enum HeaderKind {
+ HK_Normal,
+ HK_Textual,
+ HK_Private,
+ HK_PrivateTextual,
+ HK_Excluded
+ };
+ static const int NumHeaderKinds = HK_Excluded + 1;
+
+ /// \brief Information about a header directive as found in the module map
+ /// file.
+ struct Header {
+ std::string NameAsWritten;
+ const FileEntry *Entry;
+
+ explicit operator bool() { return Entry; }
+ };
+
+ /// \brief Information about a directory name as found in the module map
+ /// file.
+ struct DirectoryName {
+ std::string NameAsWritten;
+ const DirectoryEntry *Entry;
+
+ explicit operator bool() { return Entry; }
+ };
+
+ /// \brief The headers that are part of this module.
+ SmallVector<Header, 2> Headers[5];
+
+ /// \brief Stored information about a header directive that was found in the
+ /// module map file but has not been resolved to a file.
+ struct UnresolvedHeaderDirective {
+ SourceLocation FileNameLoc;
+ std::string FileName;
+ bool IsUmbrella;
+ };
+
+ /// \brief Headers that are mentioned in the module map file but could not be
+ /// found on the file system.
+ SmallVector<UnresolvedHeaderDirective, 1> MissingHeaders;
+
+ /// \brief An individual requirement: a feature name and a flag indicating
+ /// the required state of that feature.
+ typedef std::pair<std::string, bool> Requirement;
+
+ /// \brief The set of language features required to use this module.
+ ///
+ /// If any of these requirements are not available, the \c IsAvailable bit
+ /// will be false to indicate that this (sub)module is not available.
+ SmallVector<Requirement, 2> Requirements;
+
+ /// \brief Whether this module is missing a feature from \c Requirements.
+ unsigned IsMissingRequirement : 1;
+
+ /// \brief Whether we tried and failed to load a module file for this module.
+ unsigned HasIncompatibleModuleFile : 1;
+
+ /// \brief Whether this module is available in the current translation unit.
+ ///
+ /// If the module is missing headers or does not meet all requirements then
+ /// this bit will be 0.
+ unsigned IsAvailable : 1;
+
+ /// \brief Whether this module was loaded from a module file.
+ unsigned IsFromModuleFile : 1;
+
+ /// \brief Whether this is a framework module.
+ unsigned IsFramework : 1;
+
+ /// \brief Whether this is an explicit submodule.
+ unsigned IsExplicit : 1;
+
+ /// \brief Whether this is a "system" module (which assumes that all
+ /// headers in it are system headers).
+ unsigned IsSystem : 1;
+
+ /// \brief Whether this is an 'extern "C"' module (which implicitly puts all
+ /// headers in it within an 'extern "C"' block, and allows the module to be
+ /// imported within such a block).
+ unsigned IsExternC : 1;
+
+ /// \brief Whether this is an inferred submodule (module * { ... }).
+ unsigned IsInferred : 1;
+
+ /// \brief Whether we should infer submodules for this module based on
+ /// the headers.
+ ///
+ /// Submodules can only be inferred for modules with an umbrella header.
+ unsigned InferSubmodules : 1;
+
+ /// \brief Whether, when inferring submodules, the inferred submodules
+ /// should be explicit.
+ unsigned InferExplicitSubmodules : 1;
+
+ /// \brief Whether, when inferring submodules, the inferr submodules should
+ /// export all modules they import (e.g., the equivalent of "export *").
+ unsigned InferExportWildcard : 1;
+
+ /// \brief Whether the set of configuration macros is exhaustive.
+ ///
+ /// When the set of configuration macros is exhaustive, meaning
+ /// that no identifier not in this list should affect how the module is
+ /// built.
+ unsigned ConfigMacrosExhaustive : 1;
+
+ /// \brief Describes the visibility of the various names within a
+ /// particular module.
+ enum NameVisibilityKind {
+ /// \brief All of the names in this module are hidden.
+ Hidden,
+ /// \brief All of the names in this module are visible.
+ AllVisible
+ };
+
+ /// \brief The visibility of names within this particular module.
+ NameVisibilityKind NameVisibility;
+
+ /// \brief The location of the inferred submodule.
+ SourceLocation InferredSubmoduleLoc;
+
+ /// \brief The set of modules imported by this module, and on which this
+ /// module depends.
+ llvm::SmallSetVector<Module *, 2> Imports;
+
+ /// \brief Describes an exported module.
+ ///
+ /// The pointer is the module being re-exported, while the bit will be true
+ /// to indicate that this is a wildcard export.
+ typedef llvm::PointerIntPair<Module *, 1, bool> ExportDecl;
+
+ /// \brief The set of export declarations.
+ SmallVector<ExportDecl, 2> Exports;
+
+ /// \brief Describes an exported module that has not yet been resolved
+ /// (perhaps because the module it refers to has not yet been loaded).
+ struct UnresolvedExportDecl {
+ /// \brief The location of the 'export' keyword in the module map file.
+ SourceLocation ExportLoc;
+
+ /// \brief The name of the module.
+ ModuleId Id;
+
+ /// \brief Whether this export declaration ends in a wildcard, indicating
+ /// that all of its submodules should be exported (rather than the named
+ /// module itself).
+ bool Wildcard;
+ };
+
+ /// \brief The set of export declarations that have yet to be resolved.
+ SmallVector<UnresolvedExportDecl, 2> UnresolvedExports;
+
+ /// \brief The directly used modules.
+ SmallVector<Module *, 2> DirectUses;
+
+ /// \brief The set of use declarations that have yet to be resolved.
+ SmallVector<ModuleId, 2> UnresolvedDirectUses;
+
+ /// \brief A library or framework to link against when an entity from this
+ /// module is used.
+ struct LinkLibrary {
+ LinkLibrary() : IsFramework(false) { }
+ LinkLibrary(const std::string &Library, bool IsFramework)
+ : Library(Library), IsFramework(IsFramework) { }
+
+ /// \brief The library to link against.
+ ///
+ /// This will typically be a library or framework name, but can also
+ /// be an absolute path to the library or framework.
+ std::string Library;
+
+ /// \brief Whether this is a framework rather than a library.
+ bool IsFramework;
+ };
+
+ /// \brief The set of libraries or frameworks to link against when
+ /// an entity from this module is used.
+ llvm::SmallVector<LinkLibrary, 2> LinkLibraries;
+
+ /// \brief The set of "configuration macros", which are macros that
+ /// (intentionally) change how this module is built.
+ std::vector<std::string> ConfigMacros;
+
+ /// \brief An unresolved conflict with another module.
+ struct UnresolvedConflict {
+ /// \brief The (unresolved) module id.
+ ModuleId Id;
+
+ /// \brief The message provided to the user when there is a conflict.
+ std::string Message;
+ };
+
+ /// \brief The list of conflicts for which the module-id has not yet been
+ /// resolved.
+ std::vector<UnresolvedConflict> UnresolvedConflicts;
+
+ /// \brief A conflict between two modules.
+ struct Conflict {
+ /// \brief The module that this module conflicts with.
+ Module *Other;
+
+ /// \brief The message provided to the user when there is a conflict.
+ std::string Message;
+ };
+
+ /// \brief The list of conflicts.
+ std::vector<Conflict> Conflicts;
+
+ /// \brief Construct a new module or submodule.
+ Module(StringRef Name, SourceLocation DefinitionLoc, Module *Parent,
+ bool IsFramework, bool IsExplicit, unsigned VisibilityID);
+
+ ~Module();
+
+ /// \brief Determine whether this module is available for use within the
+ /// current translation unit.
+ bool isAvailable() const { return IsAvailable; }
+
+ /// \brief Determine whether this module is available for use within the
+ /// current translation unit.
+ ///
+ /// \param LangOpts The language options used for the current
+ /// translation unit.
+ ///
+ /// \param Target The target options used for the current translation unit.
+ ///
+ /// \param Req If this module is unavailable, this parameter
+ /// will be set to one of the requirements that is not met for use of
+ /// this module.
+ bool isAvailable(const LangOptions &LangOpts,
+ const TargetInfo &Target,
+ Requirement &Req,
+ UnresolvedHeaderDirective &MissingHeader) const;
+
+ /// \brief Determine whether this module is a submodule.
+ bool isSubModule() const { return Parent != nullptr; }
+
+ /// \brief Determine whether this module is a submodule of the given other
+ /// module.
+ bool isSubModuleOf(const Module *Other) const;
+
+ /// \brief Determine whether this module is a part of a framework,
+ /// either because it is a framework module or because it is a submodule
+ /// of a framework module.
+ bool isPartOfFramework() const {
+ for (const Module *Mod = this; Mod; Mod = Mod->Parent)
+ if (Mod->IsFramework)
+ return true;
+
+ return false;
+ }
+
+ /// \brief Determine whether this module is a subframework of another
+ /// framework.
+ bool isSubFramework() const {
+ return IsFramework && Parent && Parent->isPartOfFramework();
+ }
+
+ /// \brief Retrieve the full name of this module, including the path from
+ /// its top-level module.
+ std::string getFullModuleName() const;
+
+ /// \brief Whether the full name of this module is equal to joining
+ /// \p nameParts with "."s.
+ ///
+ /// This is more efficient than getFullModuleName().
+ bool fullModuleNameIs(ArrayRef<StringRef> nameParts) const;
+
+ /// \brief Retrieve the top-level module for this (sub)module, which may
+ /// be this module.
+ Module *getTopLevelModule() {
+ return const_cast<Module *>(
+ const_cast<const Module *>(this)->getTopLevelModule());
+ }
+
+ /// \brief Retrieve the top-level module for this (sub)module, which may
+ /// be this module.
+ const Module *getTopLevelModule() const;
+
+ /// \brief Retrieve the name of the top-level module.
+ ///
+ StringRef getTopLevelModuleName() const {
+ return getTopLevelModule()->Name;
+ }
+
+ /// \brief The serialized AST file for this module, if one was created.
+ const FileEntry *getASTFile() const {
+ return getTopLevelModule()->ASTFile;
+ }
+
+ /// \brief Set the serialized AST file for the top-level module of this module.
+ void setASTFile(const FileEntry *File) {
+ assert((File == nullptr || getASTFile() == nullptr ||
+ getASTFile() == File) && "file path changed");
+ getTopLevelModule()->ASTFile = File;
+ }
+
+ /// \brief Retrieve the directory for which this module serves as the
+ /// umbrella.
+ DirectoryName getUmbrellaDir() const;
+
+ /// \brief Retrieve the header that serves as the umbrella header for this
+ /// module.
+ Header getUmbrellaHeader() const {
+ if (auto *E = Umbrella.dyn_cast<const FileEntry *>())
+ return Header{UmbrellaAsWritten, E};
+ return Header{};
+ }
+
+ /// \brief Determine whether this module has an umbrella directory that is
+ /// not based on an umbrella header.
+ bool hasUmbrellaDir() const {
+ return Umbrella && Umbrella.is<const DirectoryEntry *>();
+ }
+
+ /// \brief Add a top-level header associated with this module.
+ void addTopHeader(const FileEntry *File) {
+ assert(File);
+ TopHeaders.insert(File);
+ }
+
+ /// \brief Add a top-level header filename associated with this module.
+ void addTopHeaderFilename(StringRef Filename) {
+ TopHeaderNames.push_back(Filename);
+ }
+
+ /// \brief The top-level headers associated with this module.
+ ArrayRef<const FileEntry *> getTopHeaders(FileManager &FileMgr);
+
+ /// \brief Determine whether this module has declared its intention to
+ /// directly use another module.
+ bool directlyUses(const Module *Requested) const;
+
+ /// \brief Add the given feature requirement to the list of features
+ /// required by this module.
+ ///
+ /// \param Feature The feature that is required by this module (and
+ /// its submodules).
+ ///
+ /// \param RequiredState The required state of this feature: \c true
+ /// if it must be present, \c false if it must be absent.
+ ///
+ /// \param LangOpts The set of language options that will be used to
+ /// evaluate the availability of this feature.
+ ///
+ /// \param Target The target options that will be used to evaluate the
+ /// availability of this feature.
+ void addRequirement(StringRef Feature, bool RequiredState,
+ const LangOptions &LangOpts,
+ const TargetInfo &Target);
+
+ /// \brief Mark this module and all of its submodules as unavailable.
+ void markUnavailable(bool MissingRequirement = false);
+
+ /// \brief Find the submodule with the given name.
+ ///
+ /// \returns The submodule if found, or NULL otherwise.
+ Module *findSubmodule(StringRef Name) const;
+
+ /// \brief Determine whether the specified module would be visible to
+ /// a lookup at the end of this module.
+ ///
+ /// FIXME: This may return incorrect results for (submodules of) the
+ /// module currently being built, if it's queried before we see all
+ /// of its imports.
+ bool isModuleVisible(const Module *M) const {
+ if (VisibleModulesCache.empty())
+ buildVisibleModulesCache();
+ return VisibleModulesCache.count(M);
+ }
+
+ unsigned getVisibilityID() const { return VisibilityID; }
+
+ typedef std::vector<Module *>::iterator submodule_iterator;
+ typedef std::vector<Module *>::const_iterator submodule_const_iterator;
+
+ submodule_iterator submodule_begin() { return SubModules.begin(); }
+ submodule_const_iterator submodule_begin() const {return SubModules.begin();}
+ submodule_iterator submodule_end() { return SubModules.end(); }
+ submodule_const_iterator submodule_end() const { return SubModules.end(); }
+
+ llvm::iterator_range<submodule_iterator> submodules() {
+ return llvm::make_range(submodule_begin(), submodule_end());
+ }
+ llvm::iterator_range<submodule_const_iterator> submodules() const {
+ return llvm::make_range(submodule_begin(), submodule_end());
+ }
+
+ /// \brief Appends this module's list of exported modules to \p Exported.
+ ///
+ /// This provides a subset of immediately imported modules (the ones that are
+ /// directly exported), not the complete set of exported modules.
+ void getExportedModules(SmallVectorImpl<Module *> &Exported) const;
+
+ static StringRef getModuleInputBufferName() {
+ return "<module-includes>";
+ }
+
+ /// \brief Print the module map for this module to the given stream.
+ ///
+ void print(raw_ostream &OS, unsigned Indent = 0) const;
+
+ /// \brief Dump the contents of this module to the given output stream.
+ void dump() const;
+
+private:
+ void buildVisibleModulesCache() const;
+};
+
+/// \brief A set of visible modules.
+class VisibleModuleSet {
+public:
+ VisibleModuleSet() : Generation(0) {}
+ VisibleModuleSet(VisibleModuleSet &&O)
+ : ImportLocs(std::move(O.ImportLocs)), Generation(O.Generation ? 1 : 0) {
+ O.ImportLocs.clear();
+ ++O.Generation;
+ }
+
+ /// Move from another visible modules set. Guaranteed to leave the source
+ /// empty and bump the generation on both.
+ VisibleModuleSet &operator=(VisibleModuleSet &&O) {
+ ImportLocs = std::move(O.ImportLocs);
+ O.ImportLocs.clear();
+ ++O.Generation;
+ ++Generation;
+ return *this;
+ }
+
+ /// \brief Get the current visibility generation. Incremented each time the
+ /// set of visible modules changes in any way.
+ unsigned getGeneration() const { return Generation; }
+
+ /// \brief Determine whether a module is visible.
+ bool isVisible(const Module *M) const {
+ return getImportLoc(M).isValid();
+ }
+
+ /// \brief Get the location at which the import of a module was triggered.
+ SourceLocation getImportLoc(const Module *M) const {
+ return M->getVisibilityID() < ImportLocs.size()
+ ? ImportLocs[M->getVisibilityID()]
+ : SourceLocation();
+ }
+
+ /// \brief A callback to call when a module is made visible (directly or
+ /// indirectly) by a call to \ref setVisible.
+ typedef llvm::function_ref<void(Module *M)> VisibleCallback;
+ /// \brief A callback to call when a module conflict is found. \p Path
+ /// consists of a sequence of modules from the conflicting module to the one
+ /// made visible, where each was exported by the next.
+ typedef llvm::function_ref<void(ArrayRef<Module *> Path,
+ Module *Conflict, StringRef Message)>
+ ConflictCallback;
+ /// \brief Make a specific module visible.
+ void setVisible(Module *M, SourceLocation Loc,
+ VisibleCallback Vis = [](Module *) {},
+ ConflictCallback Cb = [](ArrayRef<Module *>, Module *,
+ StringRef) {});
+
+private:
+ /// Import locations for each visible module. Indexed by the module's
+ /// VisibilityID.
+ std::vector<SourceLocation> ImportLocs;
+ /// Visibility generation, bumped every time the visibility state changes.
+ unsigned Generation;
+};
+
+} // end namespace clang
+
+
+#endif // LLVM_CLANG_BASIC_MODULE_H
diff --git a/contrib/llvm/tools/clang/include/clang/Basic/ObjCRuntime.h b/contrib/llvm/tools/clang/include/clang/Basic/ObjCRuntime.h
new file mode 100644
index 0000000..cf51b14
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Basic/ObjCRuntime.h
@@ -0,0 +1,333 @@
+//===--- ObjCRuntime.h - Objective-C Runtime Configuration ------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+///
+/// \file
+/// \brief Defines types useful for describing an Objective-C runtime.
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_BASIC_OBJCRUNTIME_H
+#define LLVM_CLANG_BASIC_OBJCRUNTIME_H
+
+#include "clang/Basic/VersionTuple.h"
+#include "llvm/ADT/Triple.h"
+#include "llvm/Support/ErrorHandling.h"
+
+namespace clang {
+
+/// \brief The basic abstraction for the target Objective-C runtime.
+class ObjCRuntime {
+public:
+ /// \brief The basic Objective-C runtimes that we know about.
+ enum Kind {
+ /// 'macosx' is the Apple-provided NeXT-derived runtime on Mac OS
+ /// X platforms that use the non-fragile ABI; the version is a
+ /// release of that OS.
+ MacOSX,
+
+ /// 'macosx-fragile' is the Apple-provided NeXT-derived runtime on
+ /// Mac OS X platforms that use the fragile ABI; the version is a
+ /// release of that OS.
+ FragileMacOSX,
+
+ /// 'ios' is the Apple-provided NeXT-derived runtime on iOS or the iOS
+ /// simulator; it is always non-fragile. The version is a release
+ /// version of iOS.
+ iOS,
+
+ /// 'watchos' is a variant of iOS for Apple's watchOS. The version
+ /// is a release version of watchOS.
+ WatchOS,
+
+ /// 'gcc' is the Objective-C runtime shipped with GCC, implementing a
+ /// fragile Objective-C ABI
+ GCC,
+
+ /// 'gnustep' is the modern non-fragile GNUstep runtime.
+ GNUstep,
+
+ /// 'objfw' is the Objective-C runtime included in ObjFW
+ ObjFW
+ };
+
+private:
+ Kind TheKind;
+ VersionTuple Version;
+
+public:
+ /// A bogus initialization of the runtime.
+ ObjCRuntime() : TheKind(MacOSX) {}
+
+ ObjCRuntime(Kind kind, const VersionTuple &version)
+ : TheKind(kind), Version(version) {}
+
+ void set(Kind kind, VersionTuple version) {
+ TheKind = kind;
+ Version = version;
+ }
+
+ Kind getKind() const { return TheKind; }
+ const VersionTuple &getVersion() const { return Version; }
+
+ /// \brief Does this runtime follow the set of implied behaviors for a
+ /// "non-fragile" ABI?
+ bool isNonFragile() const {
+ switch (getKind()) {
+ case FragileMacOSX: return false;
+ case GCC: return false;
+ case MacOSX: return true;
+ case GNUstep: return true;
+ case ObjFW: return true;
+ case iOS: return true;
+ case WatchOS: return true;
+ }
+ llvm_unreachable("bad kind");
+ }
+
+ /// The inverse of isNonFragile(): does this runtime follow the set of
+ /// implied behaviors for a "fragile" ABI?
+ bool isFragile() const { return !isNonFragile(); }
+
+ /// The default dispatch mechanism to use for the specified architecture
+ bool isLegacyDispatchDefaultForArch(llvm::Triple::ArchType Arch) {
+ // The GNUstep runtime uses a newer dispatch method by default from
+ // version 1.6 onwards
+ if (getKind() == GNUstep && getVersion() >= VersionTuple(1, 6)) {
+ if (Arch == llvm::Triple::arm ||
+ Arch == llvm::Triple::x86 ||
+ Arch == llvm::Triple::x86_64)
+ return false;
+ }
+ else if ((getKind() == MacOSX) && isNonFragile() &&
+ (getVersion() >= VersionTuple(10, 0)) &&
+ (getVersion() < VersionTuple(10, 6)))
+ return Arch != llvm::Triple::x86_64;
+ // Except for deployment target of 10.5 or less,
+ // Mac runtimes use legacy dispatch everywhere now.
+ return true;
+ }
+
+ /// \brief Is this runtime basically of the GNU family of runtimes?
+ bool isGNUFamily() const {
+ switch (getKind()) {
+ case FragileMacOSX:
+ case MacOSX:
+ case iOS:
+ case WatchOS:
+ return false;
+ case GCC:
+ case GNUstep:
+ case ObjFW:
+ return true;
+ }
+ llvm_unreachable("bad kind");
+ }
+
+ /// \brief Is this runtime basically of the NeXT family of runtimes?
+ bool isNeXTFamily() const {
+ // For now, this is just the inverse of isGNUFamily(), but that's
+ // not inherently true.
+ return !isGNUFamily();
+ }
+
+ /// \brief Does this runtime allow ARC at all?
+ bool allowsARC() const {
+ switch (getKind()) {
+ case FragileMacOSX:
+ // No stub library for the fragile runtime.
+ return getVersion() >= VersionTuple(10, 7);
+ case MacOSX: return true;
+ case iOS: return true;
+ case WatchOS: return true;
+ case GCC: return false;
+ case GNUstep: return true;
+ case ObjFW: return true;
+ }
+ llvm_unreachable("bad kind");
+ }
+
+ /// \brief Does this runtime natively provide the ARC entrypoints?
+ ///
+ /// ARC cannot be directly supported on a platform that does not provide
+ /// these entrypoints, although it may be supportable via a stub
+ /// library.
+ bool hasNativeARC() const {
+ switch (getKind()) {
+ case FragileMacOSX: return getVersion() >= VersionTuple(10, 7);
+ case MacOSX: return getVersion() >= VersionTuple(10, 7);
+ case iOS: return getVersion() >= VersionTuple(5);
+ case WatchOS: return true;
+
+ case GCC: return false;
+ case GNUstep: return getVersion() >= VersionTuple(1, 6);
+ case ObjFW: return true;
+ }
+ llvm_unreachable("bad kind");
+ }
+
+ /// \brief Does this runtime supports optimized setter entrypoints?
+ bool hasOptimizedSetter() const {
+ switch (getKind()) {
+ case MacOSX:
+ return getVersion() >= VersionTuple(10, 8);
+ case iOS:
+ return (getVersion() >= VersionTuple(6));
+ case WatchOS:
+ return true;
+ case GNUstep:
+ return getVersion() >= VersionTuple(1, 7);
+
+ default:
+ return false;
+ }
+ }
+
+ /// Does this runtime allow the use of __weak?
+ bool allowsWeak() const {
+ return hasNativeWeak();
+ }
+
+ /// \brief Does this runtime natively provide ARC-compliant 'weak'
+ /// entrypoints?
+ bool hasNativeWeak() const {
+ // Right now, this is always equivalent to whether the runtime
+ // natively supports ARC decision.
+ return hasNativeARC();
+ }
+
+ /// \brief Does this runtime directly support the subscripting methods?
+ ///
+ /// This is really a property of the library, not the runtime.
+ bool hasSubscripting() const {
+ switch (getKind()) {
+ case FragileMacOSX: return false;
+ case MacOSX: return getVersion() >= VersionTuple(10, 8);
+ case iOS: return getVersion() >= VersionTuple(6);
+ case WatchOS: return true;
+
+ // This is really a lie, because some implementations and versions
+ // of the runtime do not support ARC. Probably -fgnu-runtime
+ // should imply a "maximal" runtime or something?
+ case GCC: return true;
+ case GNUstep: return true;
+ case ObjFW: return true;
+ }
+ llvm_unreachable("bad kind");
+ }
+
+ /// \brief Does this runtime allow sizeof or alignof on object types?
+ bool allowsSizeofAlignof() const {
+ return isFragile();
+ }
+
+ /// \brief Does this runtime allow pointer arithmetic on objects?
+ ///
+ /// This covers +, -, ++, --, and (if isSubscriptPointerArithmetic()
+ /// yields true) [].
+ bool allowsPointerArithmetic() const {
+ switch (getKind()) {
+ case FragileMacOSX:
+ case GCC:
+ return true;
+ case MacOSX:
+ case iOS:
+ case WatchOS:
+ case GNUstep:
+ case ObjFW:
+ return false;
+ }
+ llvm_unreachable("bad kind");
+ }
+
+ /// \brief Is subscripting pointer arithmetic?
+ bool isSubscriptPointerArithmetic() const {
+ return allowsPointerArithmetic();
+ }
+
+ /// \brief Does this runtime provide an objc_terminate function?
+ ///
+ /// This is used in handlers for exceptions during the unwind process;
+ /// without it, abort() must be used in pure ObjC files.
+ bool hasTerminate() const {
+ switch (getKind()) {
+ case FragileMacOSX: return getVersion() >= VersionTuple(10, 8);
+ case MacOSX: return getVersion() >= VersionTuple(10, 8);
+ case iOS: return getVersion() >= VersionTuple(5);
+ case WatchOS: return true;
+ case GCC: return false;
+ case GNUstep: return false;
+ case ObjFW: return false;
+ }
+ llvm_unreachable("bad kind");
+ }
+
+ /// \brief Does this runtime support weakly importing classes?
+ bool hasWeakClassImport() const {
+ switch (getKind()) {
+ case MacOSX: return true;
+ case iOS: return true;
+ case WatchOS: return true;
+ case FragileMacOSX: return false;
+ case GCC: return true;
+ case GNUstep: return true;
+ case ObjFW: return true;
+ }
+ llvm_unreachable("bad kind");
+ }
+
+ /// \brief Does this runtime use zero-cost exceptions?
+ bool hasUnwindExceptions() const {
+ switch (getKind()) {
+ case MacOSX: return true;
+ case iOS: return true;
+ case WatchOS: return true;
+ case FragileMacOSX: return false;
+ case GCC: return true;
+ case GNUstep: return true;
+ case ObjFW: return true;
+ }
+ llvm_unreachable("bad kind");
+ }
+
+ bool hasAtomicCopyHelper() const {
+ switch (getKind()) {
+ case FragileMacOSX:
+ case MacOSX:
+ case iOS:
+ case WatchOS:
+ return true;
+ case GNUstep:
+ return getVersion() >= VersionTuple(1, 7);
+ default: return false;
+ }
+ }
+
+ /// \brief Try to parse an Objective-C runtime specification from the given
+ /// string.
+ ///
+ /// \return true on error.
+ bool tryParse(StringRef input);
+
+ std::string getAsString() const;
+
+ friend bool operator==(const ObjCRuntime &left, const ObjCRuntime &right) {
+ return left.getKind() == right.getKind() &&
+ left.getVersion() == right.getVersion();
+ }
+
+ friend bool operator!=(const ObjCRuntime &left, const ObjCRuntime &right) {
+ return !(left == right);
+ }
+};
+
+raw_ostream &operator<<(raw_ostream &out, const ObjCRuntime &value);
+
+} // 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..91fd919
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Basic/OpenCLExtensions.def
@@ -0,0 +1,35 @@
+//===--- 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.
+//
+//===----------------------------------------------------------------------===//
+
+// OpenCL 1.1.
+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)
+
+// OpenCL 2.0
+OPENCLEXT(cl_khr_gl_msaa_sharing)
+
+// Clang Extensions.
+OPENCLEXT(cl_clang_storage_class_specifiers)
+
+#undef OPENCLEXT
diff --git a/contrib/llvm/tools/clang/include/clang/Basic/OpenMPKinds.def b/contrib/llvm/tools/clang/include/clang/Basic/OpenMPKinds.def
new file mode 100644
index 0000000..44f77ad
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Basic/OpenMPKinds.def
@@ -0,0 +1,451 @@
+//===--- OpenMPKinds.def - OpenMP directives and clauses list ---*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+/// \file
+/// \brief This file defines the list of supported OpenMP directives and
+/// clauses.
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef OPENMP_DIRECTIVE
+# define OPENMP_DIRECTIVE(Name)
+#endif
+#ifndef OPENMP_DIRECTIVE_EXT
+#define OPENMP_DIRECTIVE_EXT(Name, Str)
+#endif
+#ifndef OPENMP_CLAUSE
+# define OPENMP_CLAUSE(Name, Class)
+#endif
+#ifndef OPENMP_PARALLEL_CLAUSE
+# define OPENMP_PARALLEL_CLAUSE(Name)
+#endif
+#ifndef OPENMP_SIMD_CLAUSE
+# define OPENMP_SIMD_CLAUSE(Name)
+#endif
+#ifndef OPENMP_FOR_CLAUSE
+# define OPENMP_FOR_CLAUSE(Name)
+#endif
+#ifndef OPENMP_FOR_SIMD_CLAUSE
+# define OPENMP_FOR_SIMD_CLAUSE(Name)
+#endif
+#ifndef OPENMP_SECTIONS_CLAUSE
+# define OPENMP_SECTIONS_CLAUSE(Name)
+#endif
+#ifndef OPENMP_SINGLE_CLAUSE
+# define OPENMP_SINGLE_CLAUSE(Name)
+#endif
+#ifndef OPENMP_PARALLEL_FOR_CLAUSE
+# define OPENMP_PARALLEL_FOR_CLAUSE(Name)
+#endif
+#ifndef OPENMP_PARALLEL_FOR_SIMD_CLAUSE
+# define OPENMP_PARALLEL_FOR_SIMD_CLAUSE(Name)
+#endif
+#ifndef OPENMP_PARALLEL_SECTIONS_CLAUSE
+# define OPENMP_PARALLEL_SECTIONS_CLAUSE(Name)
+#endif
+#ifndef OPENMP_TASK_CLAUSE
+# define OPENMP_TASK_CLAUSE(Name)
+#endif
+#ifndef OPENMP_ATOMIC_CLAUSE
+# define OPENMP_ATOMIC_CLAUSE(Name)
+#endif
+#ifndef OPENMP_TARGET_CLAUSE
+# define OPENMP_TARGET_CLAUSE(Name)
+#endif
+#ifndef OPENMP_TARGET_DATA_CLAUSE
+# define OPENMP_TARGET_DATA_CLAUSE(Name)
+#endif
+#ifndef OPENMP_TEAMS_CLAUSE
+# define OPENMP_TEAMS_CLAUSE(Name)
+#endif
+#ifndef OPENMP_CANCEL_CLAUSE
+# define OPENMP_CANCEL_CLAUSE(Name)
+#endif
+#ifndef OPENMP_ORDERED_CLAUSE
+# define OPENMP_ORDERED_CLAUSE(Name)
+#endif
+#ifndef OPENMP_TASKLOOP_CLAUSE
+# define OPENMP_TASKLOOP_CLAUSE(Name)
+#endif
+#ifndef OPENMP_TASKLOOP_SIMD_CLAUSE
+# define OPENMP_TASKLOOP_SIMD_CLAUSE(Name)
+#endif
+#ifndef OPENMP_CRITICAL_CLAUSE
+# define OPENMP_CRITICAL_CLAUSE(Name)
+#endif
+#ifndef OPENMP_DISTRIBUTE_CLAUSE
+#define OPENMP_DISTRIBUTE_CLAUSE(Name)
+#endif
+#ifndef OPENMP_DEFAULT_KIND
+# define OPENMP_DEFAULT_KIND(Name)
+#endif
+#ifndef OPENMP_PROC_BIND_KIND
+# define OPENMP_PROC_BIND_KIND(Name)
+#endif
+#ifndef OPENMP_SCHEDULE_KIND
+#define OPENMP_SCHEDULE_KIND(Name)
+#endif
+#ifndef OPENMP_SCHEDULE_MODIFIER
+#define OPENMP_SCHEDULE_MODIFIER(Name)
+#endif
+#ifndef OPENMP_DEPEND_KIND
+#define OPENMP_DEPEND_KIND(Name)
+#endif
+#ifndef OPENMP_LINEAR_KIND
+#define OPENMP_LINEAR_KIND(Name)
+#endif
+#ifndef OPENMP_MAP_KIND
+#define OPENMP_MAP_KIND(Name)
+#endif
+
+// OpenMP directives.
+OPENMP_DIRECTIVE(threadprivate)
+OPENMP_DIRECTIVE(parallel)
+OPENMP_DIRECTIVE(task)
+OPENMP_DIRECTIVE(simd)
+OPENMP_DIRECTIVE(for)
+OPENMP_DIRECTIVE(sections)
+OPENMP_DIRECTIVE(section)
+OPENMP_DIRECTIVE(single)
+OPENMP_DIRECTIVE(master)
+OPENMP_DIRECTIVE(critical)
+OPENMP_DIRECTIVE(taskyield)
+OPENMP_DIRECTIVE(barrier)
+OPENMP_DIRECTIVE(taskwait)
+OPENMP_DIRECTIVE(taskgroup)
+OPENMP_DIRECTIVE(flush)
+OPENMP_DIRECTIVE(ordered)
+OPENMP_DIRECTIVE(atomic)
+OPENMP_DIRECTIVE(target)
+OPENMP_DIRECTIVE(teams)
+OPENMP_DIRECTIVE(cancel)
+OPENMP_DIRECTIVE_EXT(target_data, "target data")
+OPENMP_DIRECTIVE_EXT(parallel_for, "parallel for")
+OPENMP_DIRECTIVE_EXT(parallel_for_simd, "parallel for simd")
+OPENMP_DIRECTIVE_EXT(parallel_sections, "parallel sections")
+OPENMP_DIRECTIVE_EXT(for_simd, "for simd")
+OPENMP_DIRECTIVE_EXT(cancellation_point, "cancellation point")
+OPENMP_DIRECTIVE(taskloop)
+OPENMP_DIRECTIVE_EXT(taskloop_simd, "taskloop simd")
+OPENMP_DIRECTIVE(distribute)
+
+// OpenMP clauses.
+OPENMP_CLAUSE(if, OMPIfClause)
+OPENMP_CLAUSE(final, OMPFinalClause)
+OPENMP_CLAUSE(num_threads, OMPNumThreadsClause)
+OPENMP_CLAUSE(safelen, OMPSafelenClause)
+OPENMP_CLAUSE(simdlen, OMPSimdlenClause)
+OPENMP_CLAUSE(collapse, OMPCollapseClause)
+OPENMP_CLAUSE(default, OMPDefaultClause)
+OPENMP_CLAUSE(private, OMPPrivateClause)
+OPENMP_CLAUSE(firstprivate, OMPFirstprivateClause)
+OPENMP_CLAUSE(lastprivate, OMPLastprivateClause)
+OPENMP_CLAUSE(shared, OMPSharedClause)
+OPENMP_CLAUSE(reduction, OMPReductionClause)
+OPENMP_CLAUSE(linear, OMPLinearClause)
+OPENMP_CLAUSE(aligned, OMPAlignedClause)
+OPENMP_CLAUSE(copyin, OMPCopyinClause)
+OPENMP_CLAUSE(copyprivate, OMPCopyprivateClause)
+OPENMP_CLAUSE(proc_bind, OMPProcBindClause)
+OPENMP_CLAUSE(schedule, OMPScheduleClause)
+OPENMP_CLAUSE(ordered, OMPOrderedClause)
+OPENMP_CLAUSE(nowait, OMPNowaitClause)
+OPENMP_CLAUSE(untied, OMPUntiedClause)
+OPENMP_CLAUSE(mergeable, OMPMergeableClause)
+OPENMP_CLAUSE(flush, OMPFlushClause)
+OPENMP_CLAUSE(read, OMPReadClause)
+OPENMP_CLAUSE(write, OMPWriteClause)
+OPENMP_CLAUSE(update, OMPUpdateClause)
+OPENMP_CLAUSE(capture, OMPCaptureClause)
+OPENMP_CLAUSE(seq_cst, OMPSeqCstClause)
+OPENMP_CLAUSE(depend, OMPDependClause)
+OPENMP_CLAUSE(device, OMPDeviceClause)
+OPENMP_CLAUSE(threads, OMPThreadsClause)
+OPENMP_CLAUSE(simd, OMPSIMDClause)
+OPENMP_CLAUSE(map, OMPMapClause)
+OPENMP_CLAUSE(num_teams, OMPNumTeamsClause)
+OPENMP_CLAUSE(thread_limit, OMPThreadLimitClause)
+OPENMP_CLAUSE(priority, OMPPriorityClause)
+OPENMP_CLAUSE(grainsize, OMPGrainsizeClause)
+OPENMP_CLAUSE(nogroup, OMPNogroupClause)
+OPENMP_CLAUSE(num_tasks, OMPNumTasksClause)
+OPENMP_CLAUSE(hint, OMPHintClause)
+
+// Clauses allowed for OpenMP directive 'parallel'.
+OPENMP_PARALLEL_CLAUSE(if)
+OPENMP_PARALLEL_CLAUSE(num_threads)
+OPENMP_PARALLEL_CLAUSE(default)
+OPENMP_PARALLEL_CLAUSE(proc_bind)
+OPENMP_PARALLEL_CLAUSE(private)
+OPENMP_PARALLEL_CLAUSE(firstprivate)
+OPENMP_PARALLEL_CLAUSE(shared)
+OPENMP_PARALLEL_CLAUSE(reduction)
+OPENMP_PARALLEL_CLAUSE(copyin)
+
+// Clauses allowed for directive 'omp simd'.
+OPENMP_SIMD_CLAUSE(private)
+OPENMP_SIMD_CLAUSE(lastprivate)
+OPENMP_SIMD_CLAUSE(linear)
+OPENMP_SIMD_CLAUSE(aligned)
+OPENMP_SIMD_CLAUSE(safelen)
+OPENMP_SIMD_CLAUSE(simdlen)
+OPENMP_SIMD_CLAUSE(collapse)
+OPENMP_SIMD_CLAUSE(reduction)
+
+// Clauses allowed for directive 'omp for'.
+OPENMP_FOR_CLAUSE(private)
+OPENMP_FOR_CLAUSE(lastprivate)
+OPENMP_FOR_CLAUSE(firstprivate)
+OPENMP_FOR_CLAUSE(reduction)
+OPENMP_FOR_CLAUSE(collapse)
+OPENMP_FOR_CLAUSE(schedule)
+OPENMP_FOR_CLAUSE(ordered)
+OPENMP_FOR_CLAUSE(nowait)
+OPENMP_FOR_CLAUSE(linear)
+
+// Clauses allowed for directive 'omp for simd'.
+OPENMP_FOR_SIMD_CLAUSE(private)
+OPENMP_FOR_SIMD_CLAUSE(firstprivate)
+OPENMP_FOR_SIMD_CLAUSE(lastprivate)
+OPENMP_FOR_SIMD_CLAUSE(reduction)
+OPENMP_FOR_SIMD_CLAUSE(schedule)
+OPENMP_FOR_SIMD_CLAUSE(collapse)
+OPENMP_FOR_SIMD_CLAUSE(nowait)
+OPENMP_FOR_SIMD_CLAUSE(safelen)
+OPENMP_FOR_SIMD_CLAUSE(simdlen)
+OPENMP_FOR_SIMD_CLAUSE(linear)
+OPENMP_FOR_SIMD_CLAUSE(aligned)
+OPENMP_FOR_SIMD_CLAUSE(ordered)
+
+// Clauses allowed for OpenMP directive 'omp sections'.
+OPENMP_SECTIONS_CLAUSE(private)
+OPENMP_SECTIONS_CLAUSE(lastprivate)
+OPENMP_SECTIONS_CLAUSE(firstprivate)
+OPENMP_SECTIONS_CLAUSE(reduction)
+OPENMP_SECTIONS_CLAUSE(nowait)
+
+// Clauses allowed for directive 'omp single'.
+OPENMP_SINGLE_CLAUSE(private)
+OPENMP_SINGLE_CLAUSE(firstprivate)
+OPENMP_SINGLE_CLAUSE(copyprivate)
+OPENMP_SINGLE_CLAUSE(nowait)
+
+// Clauses allowed for OpenMP directive 'cancel'.
+OPENMP_CANCEL_CLAUSE(if)
+
+// Static attributes for 'default' clause.
+OPENMP_DEFAULT_KIND(none)
+OPENMP_DEFAULT_KIND(shared)
+
+// Static attributes for 'proc_bind' clause.
+OPENMP_PROC_BIND_KIND(master)
+OPENMP_PROC_BIND_KIND(close)
+OPENMP_PROC_BIND_KIND(spread)
+
+// Static attributes for 'schedule' clause.
+OPENMP_SCHEDULE_KIND(static)
+OPENMP_SCHEDULE_KIND(dynamic)
+OPENMP_SCHEDULE_KIND(guided)
+OPENMP_SCHEDULE_KIND(auto)
+OPENMP_SCHEDULE_KIND(runtime)
+
+// Modifiers for 'schedule' clause.
+OPENMP_SCHEDULE_MODIFIER(monotonic)
+OPENMP_SCHEDULE_MODIFIER(nonmonotonic)
+OPENMP_SCHEDULE_MODIFIER(simd)
+
+// Static attributes for 'depend' clause.
+OPENMP_DEPEND_KIND(in)
+OPENMP_DEPEND_KIND(out)
+OPENMP_DEPEND_KIND(inout)
+OPENMP_DEPEND_KIND(source)
+OPENMP_DEPEND_KIND(sink)
+
+// Modifiers for 'linear' clause.
+OPENMP_LINEAR_KIND(val)
+OPENMP_LINEAR_KIND(ref)
+OPENMP_LINEAR_KIND(uval)
+
+// Clauses allowed for OpenMP directive 'parallel for'.
+OPENMP_PARALLEL_FOR_CLAUSE(if)
+OPENMP_PARALLEL_FOR_CLAUSE(num_threads)
+OPENMP_PARALLEL_FOR_CLAUSE(default)
+OPENMP_PARALLEL_FOR_CLAUSE(proc_bind)
+OPENMP_PARALLEL_FOR_CLAUSE(private)
+OPENMP_PARALLEL_FOR_CLAUSE(firstprivate)
+OPENMP_PARALLEL_FOR_CLAUSE(shared)
+OPENMP_PARALLEL_FOR_CLAUSE(reduction)
+OPENMP_PARALLEL_FOR_CLAUSE(copyin)
+OPENMP_PARALLEL_FOR_CLAUSE(lastprivate)
+OPENMP_PARALLEL_FOR_CLAUSE(collapse)
+OPENMP_PARALLEL_FOR_CLAUSE(schedule)
+OPENMP_PARALLEL_FOR_CLAUSE(ordered)
+OPENMP_PARALLEL_FOR_CLAUSE(linear)
+
+// Clauses allowed for OpenMP directive 'parallel for simd'.
+OPENMP_PARALLEL_FOR_SIMD_CLAUSE(if)
+OPENMP_PARALLEL_FOR_SIMD_CLAUSE(num_threads)
+OPENMP_PARALLEL_FOR_SIMD_CLAUSE(default)
+OPENMP_PARALLEL_FOR_SIMD_CLAUSE(proc_bind)
+OPENMP_PARALLEL_FOR_SIMD_CLAUSE(private)
+OPENMP_PARALLEL_FOR_SIMD_CLAUSE(firstprivate)
+OPENMP_PARALLEL_FOR_SIMD_CLAUSE(shared)
+OPENMP_PARALLEL_FOR_SIMD_CLAUSE(reduction)
+OPENMP_PARALLEL_FOR_SIMD_CLAUSE(copyin)
+OPENMP_PARALLEL_FOR_SIMD_CLAUSE(lastprivate)
+OPENMP_PARALLEL_FOR_SIMD_CLAUSE(collapse)
+OPENMP_PARALLEL_FOR_SIMD_CLAUSE(schedule)
+OPENMP_PARALLEL_FOR_SIMD_CLAUSE(safelen)
+OPENMP_PARALLEL_FOR_SIMD_CLAUSE(simdlen)
+OPENMP_PARALLEL_FOR_SIMD_CLAUSE(linear)
+OPENMP_PARALLEL_FOR_SIMD_CLAUSE(aligned)
+OPENMP_PARALLEL_FOR_SIMD_CLAUSE(ordered)
+
+// Clauses allowed for OpenMP directive 'parallel sections'.
+OPENMP_PARALLEL_SECTIONS_CLAUSE(if)
+OPENMP_PARALLEL_SECTIONS_CLAUSE(num_threads)
+OPENMP_PARALLEL_SECTIONS_CLAUSE(default)
+OPENMP_PARALLEL_SECTIONS_CLAUSE(proc_bind)
+OPENMP_PARALLEL_SECTIONS_CLAUSE(private)
+OPENMP_PARALLEL_SECTIONS_CLAUSE(firstprivate)
+OPENMP_PARALLEL_SECTIONS_CLAUSE(shared)
+OPENMP_PARALLEL_SECTIONS_CLAUSE(reduction)
+OPENMP_PARALLEL_SECTIONS_CLAUSE(copyin)
+OPENMP_PARALLEL_SECTIONS_CLAUSE(lastprivate)
+
+// Clauses allowed for OpenMP directive 'task'.
+OPENMP_TASK_CLAUSE(if)
+OPENMP_TASK_CLAUSE(final)
+OPENMP_TASK_CLAUSE(default)
+OPENMP_TASK_CLAUSE(private)
+OPENMP_TASK_CLAUSE(firstprivate)
+OPENMP_TASK_CLAUSE(shared)
+OPENMP_TASK_CLAUSE(untied)
+OPENMP_TASK_CLAUSE(mergeable)
+OPENMP_TASK_CLAUSE(depend)
+OPENMP_TASK_CLAUSE(priority)
+
+// Clauses allowed for OpenMP directive 'atomic'.
+OPENMP_ATOMIC_CLAUSE(read)
+OPENMP_ATOMIC_CLAUSE(write)
+OPENMP_ATOMIC_CLAUSE(update)
+OPENMP_ATOMIC_CLAUSE(capture)
+OPENMP_ATOMIC_CLAUSE(seq_cst)
+
+// Clauses allowed for OpenMP directive 'target'.
+// TODO More clauses for 'target' directive.
+OPENMP_TARGET_CLAUSE(if)
+OPENMP_TARGET_CLAUSE(device)
+OPENMP_TARGET_CLAUSE(map)
+
+// Clauses allowed for OpenMP directive 'target data'.
+// TODO More clauses for 'target data' directive.
+OPENMP_TARGET_DATA_CLAUSE(if)
+OPENMP_TARGET_DATA_CLAUSE(device)
+OPENMP_TARGET_DATA_CLAUSE(map)
+
+// Clauses allowed for OpenMP directive 'teams'.
+// TODO More clauses for 'teams' directive.
+OPENMP_TEAMS_CLAUSE(default)
+OPENMP_TEAMS_CLAUSE(private)
+OPENMP_TEAMS_CLAUSE(firstprivate)
+OPENMP_TEAMS_CLAUSE(shared)
+OPENMP_TEAMS_CLAUSE(reduction)
+OPENMP_TEAMS_CLAUSE(num_teams)
+OPENMP_TEAMS_CLAUSE(thread_limit)
+
+// Clauses allowed for OpenMP directive 'ordered'.
+// TODO More clauses for 'ordered' directive.
+OPENMP_ORDERED_CLAUSE(threads)
+OPENMP_ORDERED_CLAUSE(simd)
+OPENMP_ORDERED_CLAUSE(depend)
+
+// Map types and map type modifier for 'map' clause.
+OPENMP_MAP_KIND(alloc)
+OPENMP_MAP_KIND(to)
+OPENMP_MAP_KIND(from)
+OPENMP_MAP_KIND(tofrom)
+OPENMP_MAP_KIND(delete)
+OPENMP_MAP_KIND(release)
+OPENMP_MAP_KIND(always)
+
+// Clauses allowed for OpenMP directive 'taskloop'.
+OPENMP_TASKLOOP_CLAUSE(if)
+OPENMP_TASKLOOP_CLAUSE(shared)
+OPENMP_TASKLOOP_CLAUSE(private)
+OPENMP_TASKLOOP_CLAUSE(firstprivate)
+OPENMP_TASKLOOP_CLAUSE(lastprivate)
+OPENMP_TASKLOOP_CLAUSE(default)
+OPENMP_TASKLOOP_CLAUSE(collapse)
+OPENMP_TASKLOOP_CLAUSE(final)
+OPENMP_TASKLOOP_CLAUSE(untied)
+OPENMP_TASKLOOP_CLAUSE(mergeable)
+OPENMP_TASKLOOP_CLAUSE(priority)
+OPENMP_TASKLOOP_CLAUSE(grainsize)
+OPENMP_TASKLOOP_CLAUSE(nogroup)
+OPENMP_TASKLOOP_CLAUSE(num_tasks)
+
+// Clauses allowed for OpenMP directive 'taskloop simd'.
+OPENMP_TASKLOOP_SIMD_CLAUSE(if)
+OPENMP_TASKLOOP_SIMD_CLAUSE(shared)
+OPENMP_TASKLOOP_SIMD_CLAUSE(private)
+OPENMP_TASKLOOP_SIMD_CLAUSE(firstprivate)
+OPENMP_TASKLOOP_SIMD_CLAUSE(lastprivate)
+OPENMP_TASKLOOP_SIMD_CLAUSE(default)
+OPENMP_TASKLOOP_SIMD_CLAUSE(collapse)
+OPENMP_TASKLOOP_SIMD_CLAUSE(final)
+OPENMP_TASKLOOP_SIMD_CLAUSE(untied)
+OPENMP_TASKLOOP_SIMD_CLAUSE(mergeable)
+OPENMP_TASKLOOP_SIMD_CLAUSE(priority)
+OPENMP_TASKLOOP_SIMD_CLAUSE(linear)
+OPENMP_TASKLOOP_SIMD_CLAUSE(aligned)
+OPENMP_TASKLOOP_SIMD_CLAUSE(safelen)
+OPENMP_TASKLOOP_SIMD_CLAUSE(simdlen)
+OPENMP_TASKLOOP_SIMD_CLAUSE(grainsize)
+OPENMP_TASKLOOP_SIMD_CLAUSE(nogroup)
+OPENMP_TASKLOOP_SIMD_CLAUSE(num_tasks)
+
+// Clauses allowed for OpenMP directive 'critical'.
+OPENMP_CRITICAL_CLAUSE(hint)
+
+// Clauses allowed for OpenMP directive 'distribute'
+OPENMP_DISTRIBUTE_CLAUSE(private)
+OPENMP_DISTRIBUTE_CLAUSE(firstprivate)
+OPENMP_DISTRIBUTE_CLAUSE(lastprivate)
+OPENMP_DISTRIBUTE_CLAUSE(collapse)
+
+#undef OPENMP_TASKLOOP_SIMD_CLAUSE
+#undef OPENMP_TASKLOOP_CLAUSE
+#undef OPENMP_LINEAR_KIND
+#undef OPENMP_DEPEND_KIND
+#undef OPENMP_SCHEDULE_MODIFIER
+#undef OPENMP_SCHEDULE_KIND
+#undef OPENMP_PROC_BIND_KIND
+#undef OPENMP_DEFAULT_KIND
+#undef OPENMP_DIRECTIVE
+#undef OPENMP_DIRECTIVE_EXT
+#undef OPENMP_CLAUSE
+#undef OPENMP_CRITICAL_CLAUSE
+#undef OPENMP_ORDERED_CLAUSE
+#undef OPENMP_CANCEL_CLAUSE
+#undef OPENMP_SINGLE_CLAUSE
+#undef OPENMP_SECTIONS_CLAUSE
+#undef OPENMP_PARALLEL_CLAUSE
+#undef OPENMP_PARALLEL_FOR_CLAUSE
+#undef OPENMP_PARALLEL_FOR_SIMD_CLAUSE
+#undef OPENMP_PARALLEL_SECTIONS_CLAUSE
+#undef OPENMP_TASK_CLAUSE
+#undef OPENMP_ATOMIC_CLAUSE
+#undef OPENMP_TARGET_CLAUSE
+#undef OPENMP_TARGET_DATA_CLAUSE
+#undef OPENMP_TEAMS_CLAUSE
+#undef OPENMP_SIMD_CLAUSE
+#undef OPENMP_FOR_CLAUSE
+#undef OPENMP_FOR_SIMD_CLAUSE
+#undef OPENMP_MAP_KIND
+#undef OPENMP_DISTRIBUTE_CLAUSE
diff --git a/contrib/llvm/tools/clang/include/clang/Basic/OpenMPKinds.h b/contrib/llvm/tools/clang/include/clang/Basic/OpenMPKinds.h
new file mode 100644
index 0000000..d4d3db8
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Basic/OpenMPKinds.h
@@ -0,0 +1,175 @@
+//===--- OpenMPKinds.h - OpenMP enums ---------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+///
+/// \file
+/// \brief Defines some OpenMP-specific enums and functions.
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_BASIC_OPENMPKINDS_H
+#define LLVM_CLANG_BASIC_OPENMPKINDS_H
+
+#include "llvm/ADT/StringRef.h"
+
+namespace clang {
+
+/// \brief OpenMP directives.
+enum OpenMPDirectiveKind {
+#define OPENMP_DIRECTIVE(Name) \
+ OMPD_##Name,
+#define OPENMP_DIRECTIVE_EXT(Name, Str) \
+ OMPD_##Name,
+#include "clang/Basic/OpenMPKinds.def"
+ OMPD_unknown
+};
+
+/// \brief OpenMP clauses.
+enum OpenMPClauseKind {
+#define OPENMP_CLAUSE(Name, Class) \
+ OMPC_##Name,
+#include "clang/Basic/OpenMPKinds.def"
+ OMPC_threadprivate,
+ OMPC_unknown
+};
+
+/// \brief OpenMP attributes for 'default' clause.
+enum OpenMPDefaultClauseKind {
+#define OPENMP_DEFAULT_KIND(Name) \
+ OMPC_DEFAULT_##Name,
+#include "clang/Basic/OpenMPKinds.def"
+ OMPC_DEFAULT_unknown
+};
+
+/// \brief OpenMP attributes for 'proc_bind' clause.
+enum OpenMPProcBindClauseKind {
+#define OPENMP_PROC_BIND_KIND(Name) \
+ OMPC_PROC_BIND_##Name,
+#include "clang/Basic/OpenMPKinds.def"
+ OMPC_PROC_BIND_unknown
+};
+
+/// \brief OpenMP attributes for 'schedule' clause.
+enum OpenMPScheduleClauseKind {
+#define OPENMP_SCHEDULE_KIND(Name) \
+ OMPC_SCHEDULE_##Name,
+#include "clang/Basic/OpenMPKinds.def"
+ OMPC_SCHEDULE_unknown
+};
+
+/// \brief OpenMP modifiers for 'schedule' clause.
+enum OpenMPScheduleClauseModifier {
+ OMPC_SCHEDULE_MODIFIER_unknown = OMPC_SCHEDULE_unknown,
+#define OPENMP_SCHEDULE_MODIFIER(Name) \
+ OMPC_SCHEDULE_MODIFIER_##Name,
+#include "clang/Basic/OpenMPKinds.def"
+ OMPC_SCHEDULE_MODIFIER_last
+};
+
+/// \brief OpenMP attributes for 'depend' clause.
+enum OpenMPDependClauseKind {
+#define OPENMP_DEPEND_KIND(Name) \
+ OMPC_DEPEND_##Name,
+#include "clang/Basic/OpenMPKinds.def"
+ OMPC_DEPEND_unknown
+};
+
+/// \brief OpenMP attributes for 'linear' clause.
+enum OpenMPLinearClauseKind {
+#define OPENMP_LINEAR_KIND(Name) \
+ OMPC_LINEAR_##Name,
+#include "clang/Basic/OpenMPKinds.def"
+ OMPC_LINEAR_unknown
+};
+
+/// \brief OpenMP mapping kind for 'map' clause.
+enum OpenMPMapClauseKind {
+#define OPENMP_MAP_KIND(Name) \
+ OMPC_MAP_##Name,
+#include "clang/Basic/OpenMPKinds.def"
+ OMPC_MAP_unknown
+};
+
+OpenMPDirectiveKind getOpenMPDirectiveKind(llvm::StringRef Str);
+const char *getOpenMPDirectiveName(OpenMPDirectiveKind Kind);
+
+OpenMPClauseKind getOpenMPClauseKind(llvm::StringRef Str);
+const char *getOpenMPClauseName(OpenMPClauseKind Kind);
+
+unsigned getOpenMPSimpleClauseType(OpenMPClauseKind Kind, llvm::StringRef Str);
+const char *getOpenMPSimpleClauseTypeName(OpenMPClauseKind Kind, unsigned Type);
+
+bool isAllowedClauseForDirective(OpenMPDirectiveKind DKind,
+ OpenMPClauseKind CKind);
+
+/// \brief Checks if the specified directive is a directive with an associated
+/// loop construct.
+/// \param DKind Specified directive.
+/// \return true - the directive is a loop-associated directive like 'omp simd'
+/// or 'omp for' directive, otherwise - false.
+bool isOpenMPLoopDirective(OpenMPDirectiveKind DKind);
+
+/// \brief Checks if the specified directive is a worksharing directive.
+/// \param DKind Specified directive.
+/// \return true - the directive is a worksharing directive like 'omp for',
+/// otherwise - false.
+bool isOpenMPWorksharingDirective(OpenMPDirectiveKind DKind);
+
+/// \brief Checks if the specified directive is a taskloop directive.
+/// \param DKind Specified directive.
+/// \return true - the directive is a worksharing directive like 'omp taskloop',
+/// otherwise - false.
+bool isOpenMPTaskLoopDirective(OpenMPDirectiveKind DKind);
+
+/// \brief Checks if the specified directive is a parallel-kind directive.
+/// \param DKind Specified directive.
+/// \return true - the directive is a parallel-like directive like 'omp
+/// parallel', otherwise - false.
+bool isOpenMPParallelDirective(OpenMPDirectiveKind DKind);
+
+/// \brief Checks if the specified directive is a target-kind directive.
+/// \param DKind Specified directive.
+/// \return true - the directive is a target-like directive like 'omp target',
+/// otherwise - false.
+bool isOpenMPTargetDirective(OpenMPDirectiveKind DKind);
+
+/// \brief Checks if the specified directive is a teams-kind directive.
+/// \param DKind Specified directive.
+/// \return true - the directive is a teams-like directive like 'omp teams',
+/// otherwise - false.
+bool isOpenMPTeamsDirective(OpenMPDirectiveKind DKind);
+
+/// \brief Checks if the specified directive is a simd directive.
+/// \param DKind Specified directive.
+/// \return true - the directive is a simd directive like 'omp simd',
+/// otherwise - false.
+bool isOpenMPSimdDirective(OpenMPDirectiveKind DKind);
+
+/// \brief Checks if the specified directive is a distribute directive.
+/// \param DKind Specified directive.
+/// \return true - the directive is a distribute-directive like 'omp
+/// distribute',
+/// otherwise - false.
+bool isOpenMPDistributeDirective(OpenMPDirectiveKind DKind);
+
+/// \brief Checks if the specified clause is one of private clauses like
+/// 'private', 'firstprivate', 'reduction' etc..
+/// \param Kind Clause kind.
+/// \return true - the clause is a private clause, otherwise - false.
+bool isOpenMPPrivate(OpenMPClauseKind Kind);
+
+/// \brief Checks if the specified clause is one of threadprivate clauses like
+/// 'threadprivate', 'copyin' or 'copyprivate'.
+/// \param Kind Clause kind.
+/// \return true - the clause is a threadprivate clause, otherwise - false.
+bool isOpenMPThreadPrivate(OpenMPClauseKind Kind);
+
+}
+
+#endif
+
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..34ad764
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Basic/OperatorKinds.def
@@ -0,0 +1,107 @@
+//===--- 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)
+OVERLOADED_OPERATOR(Coawait , "co_await", kw_co_await , true , false, 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..7120bae
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Basic/OperatorKinds.h
@@ -0,0 +1,36 @@
+//===--- 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.
+//
+//===----------------------------------------------------------------------===//
+///
+/// \file
+/// \brief Defines an enumeration for C++ overloaded operators.
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_BASIC_OPERATORKINDS_H
+#define LLVM_CLANG_BASIC_OPERATORKINDS_H
+
+namespace clang {
+
+/// \brief Enumeration specifying the different kinds of C++ overloaded
+/// operators.
+enum OverloadedOperatorKind : int {
+ 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/OperatorPrecedence.h b/contrib/llvm/tools/clang/include/clang/Basic/OperatorPrecedence.h
new file mode 100644
index 0000000..640749f
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Basic/OperatorPrecedence.h
@@ -0,0 +1,52 @@
+//===--- OperatorPrecedence.h - Operator precedence levels ------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+///
+/// \file
+/// \brief Defines and computes precedence levels for binary/ternary operators.
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_BASIC_OPERATORPRECEDENCE_H
+#define LLVM_CLANG_BASIC_OPERATORPRECEDENCE_H
+
+#include "clang/Basic/TokenKinds.h"
+
+namespace clang {
+
+/// 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 // .*, ->*
+ };
+}
+
+/// \brief Return the precedence of the specified binary operator token.
+prec::Level getBinOpPrecedence(tok::TokenKind Kind, bool GreaterThanIsOperator,
+ bool CPlusPlus11);
+
+} // end namespace clang
+
+#endif // LLVM_CLANG_OPERATOR_PRECEDENCE_H
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..53ce95c
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Basic/PartialDiagnostic.h
@@ -0,0 +1,410 @@
+//===--- 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.
+//
+//===----------------------------------------------------------------------===//
+///
+/// \file
+/// \brief Implements a partial diagnostic that can be emitted anwyhere
+/// in a DiagnosticBuilder stream.
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_BASIC_PARTIALDIAGNOSTIC_H
+#define LLVM_CLANG_BASIC_PARTIALDIAGNOSTIC_H
+
+#include "clang/Basic/Diagnostic.h"
+#include "clang/Basic/SourceLocation.h"
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/Support/Compiler.h"
+#include "llvm/Support/DataTypes.h"
+#include <cassert>
+
+namespace clang {
+
+class PartialDiagnostic {
+public:
+ enum {
+ // The MaxArguments and MaxFixItHints member enum values from
+ // DiagnosticsEngine are private but DiagnosticsEngine declares
+ // PartialDiagnostic a friend. These enum values are redeclared
+ // here so that the nested Storage class below can access them.
+ MaxArguments = DiagnosticsEngine::MaxArguments
+ };
+
+ struct Storage {
+ Storage() : NumDiagArgs(0) { }
+
+ enum {
+ /// \brief 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 = PartialDiagnostic::MaxArguments
+ };
+
+ /// \brief The number of entries in Arguments.
+ unsigned char NumDiagArgs;
+
+ /// \brief Specifies for each argument whether it is in DiagArgumentsStr
+ /// or in DiagArguments.
+ unsigned char DiagArgumentsKind[MaxArguments];
+
+ /// \brief 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 interpretation 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];
+
+ /// \brief The list of ranges added to this diagnostic.
+ SmallVector<CharSourceRange, 8> DiagRanges;
+
+ /// \brief If valid, provides a hint with some code to insert, remove, or
+ /// modify at a particular position.
+ SmallVector<FixItHint, 6> FixItHints;
+ };
+
+ /// \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 = 16;
+ 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->DiagRanges.clear();
+ Result->FixItHints.clear();
+ 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.
+
+ /// \brief The diagnostic ID.
+ mutable unsigned DiagID;
+
+ /// \brief 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;
+
+ // The hot path for PartialDiagnostic is when we just used it to wrap an ID
+ // (typically so we have the flexibility of passing a more complex
+ // diagnostic into the callee, but that does not commonly occur).
+ //
+ // Split this out into a slow function for silly compilers (*cough*) which
+ // can't do decent partial inlining.
+ freeStorageSlow();
+ }
+
+ void freeStorageSlow() {
+ if (Allocator)
+ Allocator->Deallocate(DiagStorage);
+ else if (Allocator != reinterpret_cast<StorageAllocator *>(~uintptr_t(0)))
+ delete DiagStorage;
+ DiagStorage = nullptr;
+ }
+
+ void AddSourceRange(const CharSourceRange &R) const {
+ if (!DiagStorage)
+ DiagStorage = getStorage();
+
+ DiagStorage->DiagRanges.push_back(R);
+ }
+
+ void AddFixItHint(const FixItHint &Hint) const {
+ if (Hint.isNull())
+ return;
+
+ if (!DiagStorage)
+ DiagStorage = getStorage();
+
+ DiagStorage->FixItHints.push_back(Hint);
+ }
+
+public:
+ struct NullDiagnostic {};
+ /// \brief Create a null partial diagnostic, which cannot carry a payload,
+ /// and only exists to be swapped with a real partial diagnostic.
+ PartialDiagnostic(NullDiagnostic)
+ : DiagID(0), DiagStorage(nullptr), Allocator(nullptr) { }
+
+ PartialDiagnostic(unsigned DiagID, StorageAllocator &Allocator)
+ : DiagID(DiagID), DiagStorage(nullptr), Allocator(&Allocator) { }
+
+ PartialDiagnostic(const PartialDiagnostic &Other)
+ : DiagID(Other.DiagID), DiagStorage(nullptr), Allocator(Other.Allocator)
+ {
+ if (Other.DiagStorage) {
+ DiagStorage = getStorage();
+ *DiagStorage = *Other.DiagStorage;
+ }
+ }
+
+ PartialDiagnostic(PartialDiagnostic &&Other)
+ : DiagID(Other.DiagID), DiagStorage(Other.DiagStorage),
+ Allocator(Other.Allocator) {
+ Other.DiagStorage = nullptr;
+ }
+
+ 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 Diagnostic &Other, StorageAllocator &Allocator)
+ : DiagID(Other.getID()), DiagStorage(nullptr), Allocator(&Allocator)
+ {
+ // Copy arguments.
+ for (unsigned I = 0, N = Other.getNumArgs(); I != N; ++I) {
+ if (Other.getArgKind(I) == DiagnosticsEngine::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 &operator=(PartialDiagnostic &&Other) {
+ freeStorage();
+
+ DiagID = Other.DiagID;
+ DiagStorage = Other.DiagStorage;
+ Allocator = Other.Allocator;
+
+ Other.DiagStorage = nullptr;
+ return *this;
+ }
+
+ ~PartialDiagnostic() {
+ freeStorage();
+ }
+
+ void swap(PartialDiagnostic &PD) {
+ std::swap(DiagID, PD.DiagID);
+ std::swap(DiagStorage, PD.DiagStorage);
+ std::swap(Allocator, PD.Allocator);
+ }
+
+ unsigned getDiagID() const { return DiagID; }
+
+ void AddTaggedVal(intptr_t V, DiagnosticsEngine::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(StringRef V) const {
+ if (!DiagStorage)
+ DiagStorage = getStorage();
+
+ assert(DiagStorage->NumDiagArgs < Storage::MaxArguments &&
+ "Too many arguments to diagnostic!");
+ DiagStorage->DiagArgumentsKind[DiagStorage->NumDiagArgs]
+ = DiagnosticsEngine::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 ((DiagnosticsEngine::ArgumentKind)DiagStorage->DiagArgumentsKind[i]
+ == DiagnosticsEngine::ak_std_string)
+ DB.AddString(DiagStorage->DiagArgumentsStr[i]);
+ else
+ DB.AddTaggedVal(DiagStorage->DiagArgumentsVal[i],
+ (DiagnosticsEngine::ArgumentKind)DiagStorage->DiagArgumentsKind[i]);
+ }
+
+ // Add all ranges.
+ for (const CharSourceRange &Range : DiagStorage->DiagRanges)
+ DB.AddSourceRange(Range);
+
+ // Add all fix-its.
+ for (const FixItHint &Fix : DiagStorage->FixItHints)
+ DB.AddFixItHint(Fix);
+ }
+
+ void EmitToString(DiagnosticsEngine &Diags,
+ SmallVectorImpl<char> &Buf) const {
+ // FIXME: It should be possible to render a diagnostic to a string without
+ // messing with the state of the diagnostics engine.
+ DiagnosticBuilder DB(Diags.Report(getDiagID()));
+ Emit(DB);
+ DB.FlushCounts();
+ Diagnostic(&Diags).FormatDiagnostic(Buf);
+ DB.Clear();
+ Diags.Clear();
+ }
+
+ /// \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 != nullptr; }
+
+ friend const PartialDiagnostic &operator<<(const PartialDiagnostic &PD,
+ unsigned I) {
+ PD.AddTaggedVal(I, DiagnosticsEngine::ak_uint);
+ return PD;
+ }
+
+ friend const PartialDiagnostic &operator<<(const PartialDiagnostic &PD,
+ int I) {
+ PD.AddTaggedVal(I, DiagnosticsEngine::ak_sint);
+ return PD;
+ }
+
+ friend inline const PartialDiagnostic &operator<<(const PartialDiagnostic &PD,
+ const char *S) {
+ PD.AddTaggedVal(reinterpret_cast<intptr_t>(S),
+ DiagnosticsEngine::ak_c_string);
+ return PD;
+ }
+
+ friend inline const PartialDiagnostic &operator<<(const PartialDiagnostic &PD,
+ StringRef S) {
+
+ PD.AddString(S);
+ return PD;
+ }
+
+ friend inline const PartialDiagnostic &operator<<(const PartialDiagnostic &PD,
+ const IdentifierInfo *II) {
+ PD.AddTaggedVal(reinterpret_cast<intptr_t>(II),
+ DiagnosticsEngine::ak_identifierinfo);
+ return PD;
+ }
+
+ // 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>
+ friend inline
+ typename std::enable_if<std::is_same<T, DeclContext>::value,
+ const PartialDiagnostic &>::type
+ operator<<(const PartialDiagnostic &PD, T *DC) {
+ PD.AddTaggedVal(reinterpret_cast<intptr_t>(DC),
+ DiagnosticsEngine::ak_declcontext);
+ return PD;
+ }
+
+ friend inline const PartialDiagnostic &operator<<(const PartialDiagnostic &PD,
+ 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/PlistSupport.h b/contrib/llvm/tools/clang/include/clang/Basic/PlistSupport.h
new file mode 100644
index 0000000..84dd291
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Basic/PlistSupport.h
@@ -0,0 +1,119 @@
+//===---------- PlistSupport.h - Plist Output 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_BASIC_PLISTSUPPORT_H
+#define LLVM_CLANG_BASIC_PLISTSUPPORT_H
+
+#include "clang/Basic/FileManager.h"
+#include "clang/Basic/SourceManager.h"
+#include "llvm/Support/raw_ostream.h"
+
+namespace clang {
+namespace markup {
+typedef llvm::DenseMap<FileID, unsigned> FIDMap;
+
+inline void AddFID(FIDMap &FIDs, SmallVectorImpl<FileID> &V,
+ const SourceManager &SM, SourceLocation L) {
+ FileID FID = SM.getFileID(SM.getExpansionLoc(L));
+ FIDMap::iterator I = FIDs.find(FID);
+ if (I != FIDs.end())
+ return;
+ FIDs[FID] = V.size();
+ V.push_back(FID);
+}
+
+inline unsigned GetFID(const FIDMap &FIDs, const SourceManager &SM,
+ SourceLocation L) {
+ FileID FID = SM.getFileID(SM.getExpansionLoc(L));
+ FIDMap::const_iterator I = FIDs.find(FID);
+ assert(I != FIDs.end());
+ return I->second;
+}
+
+inline raw_ostream &Indent(raw_ostream &o, const unsigned indent) {
+ for (unsigned i = 0; i < indent; ++i)
+ o << ' ';
+ return o;
+}
+
+inline raw_ostream &EmitPlistHeader(raw_ostream &o) {
+ static const char *PlistHeader =
+ "<?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";
+ return o << PlistHeader;
+}
+
+inline raw_ostream &EmitInteger(raw_ostream &o, int64_t value) {
+ o << "<integer>";
+ o << value;
+ o << "</integer>";
+ return o;
+}
+
+inline raw_ostream &EmitString(raw_ostream &o, StringRef s) {
+ o << "<string>";
+ for (StringRef::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;
+}
+
+inline void EmitLocation(raw_ostream &o, const SourceManager &SM,
+ SourceLocation L, const FIDMap &FM, unsigned indent) {
+ if (L.isInvalid()) return;
+
+ FullSourceLoc Loc(SM.getExpansionLoc(L), const_cast<SourceManager &>(SM));
+
+ Indent(o, indent) << "<dict>\n";
+ Indent(o, indent) << " <key>line</key>";
+ EmitInteger(o, Loc.getExpansionLineNumber()) << '\n';
+ Indent(o, indent) << " <key>col</key>";
+ EmitInteger(o, Loc.getExpansionColumnNumber()) << '\n';
+ Indent(o, indent) << " <key>file</key>";
+ EmitInteger(o, GetFID(FM, SM, Loc)) << '\n';
+ Indent(o, indent) << "</dict>\n";
+}
+
+inline void EmitRange(raw_ostream &o, const SourceManager &SM,
+ CharSourceRange R, const FIDMap &FM, unsigned indent) {
+ if (R.isInvalid()) return;
+
+ assert(R.isCharRange() && "cannot handle a token range");
+ Indent(o, indent) << "<array>\n";
+ EmitLocation(o, SM, R.getBegin(), FM, indent + 1);
+ EmitLocation(o, SM, R.getEnd(), FM, indent + 1);
+ Indent(o, indent) << "</array>\n";
+}
+}
+}
+
+#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..6badae5
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Basic/PrettyStackTrace.h
@@ -0,0 +1,38 @@
+//===- 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.
+//
+//===----------------------------------------------------------------------===//
+///
+/// \file
+/// \brief Defines the PrettyStackTraceEntry class, which is used to make
+/// crashes give more contextual information about what the program was doing
+/// when it crashed.
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_BASIC_PRETTYSTACKTRACE_H
+#define LLVM_CLANG_BASIC_PRETTYSTACKTRACE_H
+
+#include "clang/Basic/SourceLocation.h"
+#include "llvm/Support/PrettyStackTrace.h"
+
+namespace clang {
+
+ /// 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) {}
+ void print(raw_ostream &OS) const override;
+ };
+}
+
+#endif
diff --git a/contrib/llvm/tools/clang/include/clang/Basic/SanitizerBlacklist.h b/contrib/llvm/tools/clang/include/clang/Basic/SanitizerBlacklist.h
new file mode 100644
index 0000000..e651e18
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Basic/SanitizerBlacklist.h
@@ -0,0 +1,46 @@
+//===--- SanitizerBlacklist.h - Blacklist for sanitizers --------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// User-provided blacklist used to disable/alter instrumentation done in
+// sanitizers.
+//
+//===----------------------------------------------------------------------===//
+#ifndef LLVM_CLANG_BASIC_SANITIZERBLACKLIST_H
+#define LLVM_CLANG_BASIC_SANITIZERBLACKLIST_H
+
+#include "clang/Basic/LLVM.h"
+#include "clang/Basic/SourceLocation.h"
+#include "clang/Basic/SourceManager.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/Support/SpecialCaseList.h"
+#include <memory>
+
+namespace clang {
+
+class SanitizerBlacklist {
+ std::unique_ptr<llvm::SpecialCaseList> SCL;
+ SourceManager &SM;
+
+public:
+ SanitizerBlacklist(const std::vector<std::string> &BlacklistPaths,
+ SourceManager &SM);
+ bool isBlacklistedGlobal(StringRef GlobalName,
+ StringRef Category = StringRef()) const;
+ bool isBlacklistedType(StringRef MangledTypeName,
+ StringRef Category = StringRef()) const;
+ bool isBlacklistedFunction(StringRef FunctionName) const;
+ bool isBlacklistedFile(StringRef FileName,
+ StringRef Category = StringRef()) const;
+ bool isBlacklistedLocation(SourceLocation Loc,
+ StringRef Category = StringRef()) const;
+};
+
+} // end namespace clang
+
+#endif
diff --git a/contrib/llvm/tools/clang/include/clang/Basic/Sanitizers.def b/contrib/llvm/tools/clang/include/clang/Basic/Sanitizers.def
new file mode 100644
index 0000000..4b68593
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Basic/Sanitizers.def
@@ -0,0 +1,122 @@
+//===--- Sanitizers.def - Runtime sanitizer 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 options for specifying which runtime sanitizers to
+// enable. Users of this file must define the SANITIZER macro to make use of
+// this information. Users of this file can also define the SANITIZER_GROUP
+// macro to get information on options which refer to sets of sanitizers.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef SANITIZER
+#error "Define SANITIZER prior to including this file!"
+#endif
+
+// SANITIZER(NAME, ID)
+
+// The first value is the name of the sanitizer as a string. The sanitizer can
+// be enabled by specifying -fsanitize=NAME.
+
+// The second value is an identifier which can be used to refer to the
+// sanitizer.
+
+
+// SANITIZER_GROUP(NAME, ID, ALIAS)
+
+// The first two values have the same semantics as the corresponding SANITIZER
+// values. The third value is an expression ORing together the IDs of individual
+// sanitizers in this group.
+
+#ifndef SANITIZER_GROUP
+#define SANITIZER_GROUP(NAME, ID, ALIAS)
+#endif
+
+
+// AddressSanitizer
+SANITIZER("address", Address)
+
+// Kernel AddressSanitizer (KASan)
+SANITIZER("kernel-address", KernelAddress)
+
+// MemorySanitizer
+SANITIZER("memory", Memory)
+
+// ThreadSanitizer
+SANITIZER("thread", Thread)
+
+// LeakSanitizer
+SANITIZER("leak", Leak)
+
+// UndefinedBehaviorSanitizer
+SANITIZER("alignment", Alignment)
+SANITIZER("array-bounds", ArrayBounds)
+SANITIZER("bool", Bool)
+SANITIZER("enum", Enum)
+SANITIZER("float-cast-overflow", FloatCastOverflow)
+SANITIZER("float-divide-by-zero", FloatDivideByZero)
+SANITIZER("function", Function)
+SANITIZER("integer-divide-by-zero", IntegerDivideByZero)
+SANITIZER("nonnull-attribute", NonnullAttribute)
+SANITIZER("null", Null)
+SANITIZER("object-size", ObjectSize)
+SANITIZER("return", Return)
+SANITIZER("returns-nonnull-attribute", ReturnsNonnullAttribute)
+SANITIZER("shift-base", ShiftBase)
+SANITIZER("shift-exponent", ShiftExponent)
+SANITIZER_GROUP("shift", Shift, ShiftBase | ShiftExponent)
+SANITIZER("signed-integer-overflow", SignedIntegerOverflow)
+SANITIZER("unreachable", Unreachable)
+SANITIZER("vla-bound", VLABound)
+SANITIZER("vptr", Vptr)
+
+// IntegerSanitizer
+SANITIZER("unsigned-integer-overflow", UnsignedIntegerOverflow)
+
+// DataFlowSanitizer
+SANITIZER("dataflow", DataFlow)
+
+// Control Flow Integrity
+SANITIZER("cfi-cast-strict", CFICastStrict)
+SANITIZER("cfi-derived-cast", CFIDerivedCast)
+SANITIZER("cfi-icall", CFIICall)
+SANITIZER("cfi-unrelated-cast", CFIUnrelatedCast)
+SANITIZER("cfi-nvcall", CFINVCall)
+SANITIZER("cfi-vcall", CFIVCall)
+SANITIZER_GROUP("cfi", CFI,
+ CFIDerivedCast | CFIICall | CFIUnrelatedCast | CFINVCall |
+ CFIVCall)
+
+// Safe Stack
+SANITIZER("safe-stack", SafeStack)
+
+// -fsanitize=undefined includes all the sanitizers which have low overhead, no
+// ABI or address space layout implications, and only catch undefined behavior.
+SANITIZER_GROUP("undefined", Undefined,
+ Alignment | Bool | ArrayBounds | Enum | FloatCastOverflow |
+ FloatDivideByZero | IntegerDivideByZero | NonnullAttribute |
+ Null | ObjectSize | Return | ReturnsNonnullAttribute |
+ Shift | SignedIntegerOverflow | Unreachable | VLABound |
+ Function | Vptr)
+
+// -fsanitize=undefined-trap is an alias for -fsanitize=undefined.
+SANITIZER_GROUP("undefined-trap", UndefinedTrap, Undefined)
+
+SANITIZER_GROUP("integer", Integer,
+ SignedIntegerOverflow | UnsignedIntegerOverflow | Shift |
+ IntegerDivideByZero)
+
+SANITIZER("local-bounds", LocalBounds)
+SANITIZER_GROUP("bounds", Bounds, ArrayBounds | LocalBounds)
+
+// Magic group, containing all sanitizers. For example, "-fno-sanitize=all"
+// can be used to disable all the sanitizers.
+SANITIZER_GROUP("all", All, ~0ULL)
+
+#undef SANITIZER
+#undef SANITIZER_GROUP
diff --git a/contrib/llvm/tools/clang/include/clang/Basic/Sanitizers.h b/contrib/llvm/tools/clang/include/clang/Basic/Sanitizers.h
new file mode 100644
index 0000000..98e70de
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Basic/Sanitizers.h
@@ -0,0 +1,86 @@
+//===--- Sanitizers.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.
+//
+//===----------------------------------------------------------------------===//
+///
+/// \file
+/// \brief Defines the clang::SanitizerKind enum.
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_BASIC_SANITIZERS_H
+#define LLVM_CLANG_BASIC_SANITIZERS_H
+
+#include "clang/Basic/LLVM.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/Support/MathExtras.h"
+
+namespace clang {
+
+typedef uint64_t SanitizerMask;
+
+namespace SanitizerKind {
+
+// Assign ordinals to possible values of -fsanitize= flag, which we will use as
+// bit positions.
+enum SanitizerOrdinal : uint64_t {
+#define SANITIZER(NAME, ID) SO_##ID,
+#define SANITIZER_GROUP(NAME, ID, ALIAS) SO_##ID##Group,
+#include "clang/Basic/Sanitizers.def"
+ SO_Count
+};
+
+// Define the set of sanitizer kinds, as well as the set of sanitizers each
+// sanitizer group expands into.
+#define SANITIZER(NAME, ID) \
+ const SanitizerMask ID = 1ULL << SO_##ID;
+#define SANITIZER_GROUP(NAME, ID, ALIAS) \
+ const SanitizerMask ID = ALIAS; \
+ const SanitizerMask ID##Group = 1ULL << SO_##ID##Group;
+#include "clang/Basic/Sanitizers.def"
+
+}
+
+struct SanitizerSet {
+ SanitizerSet() : Mask(0) {}
+
+ /// \brief Check if a certain (single) sanitizer is enabled.
+ bool has(SanitizerMask K) const {
+ assert(llvm::isPowerOf2_64(K));
+ return Mask & K;
+ }
+
+ /// \brief Check if one or more sanitizers are enabled.
+ bool hasOneOf(SanitizerMask K) const { return Mask & K; }
+
+ /// \brief Enable or disable a certain (single) sanitizer.
+ void set(SanitizerMask K, bool Value) {
+ assert(llvm::isPowerOf2_64(K));
+ Mask = Value ? (Mask | K) : (Mask & ~K);
+ }
+
+ /// \brief Disable all sanitizers.
+ void clear() { Mask = 0; }
+
+ /// \brief Returns true if at least one sanitizer is enabled.
+ bool empty() const { return Mask == 0; }
+
+ /// \brief Bitmask of enabled sanitizers.
+ SanitizerMask Mask;
+};
+
+/// Parse a single value from a -fsanitize= or -fno-sanitize= value list.
+/// Returns a non-zero SanitizerMask, or \c 0 if \p Value is not known.
+SanitizerMask parseSanitizerValue(StringRef Value, bool AllowGroups);
+
+/// For each sanitizer group bit set in \p Kinds, set the bits for sanitizers
+/// this group enables.
+SanitizerMask expandSanitizerGroups(SanitizerMask Kinds);
+
+} // end namespace clang
+
+#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..0aeba5e
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Basic/SourceLocation.h
@@ -0,0 +1,438 @@
+//===--- 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.
+//
+//===----------------------------------------------------------------------===//
+///
+/// \file
+/// \brief Defines the clang::SourceLocation class and associated facilities.
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_BASIC_SOURCELOCATION_H
+#define LLVM_CLANG_BASIC_SOURCELOCATION_H
+
+#include "clang/Basic/LLVM.h"
+#include "llvm/Support/Compiler.h"
+#include "llvm/Support/PointerLikeTypeTraits.h"
+#include <cassert>
+#include <functional>
+#include <string>
+#include <utility>
+
+namespace llvm {
+ class MemoryBuffer;
+ template <typename T> struct DenseMapInfo;
+ template <typename T> struct isPodLike;
+}
+
+namespace clang {
+
+class SourceManager;
+
+/// \brief An opaque identifier used by SourceManager which refers to a
+/// source file (MemoryBuffer) along with its \#include path and \#line data.
+///
+class FileID {
+ /// \brief A mostly-opaque identifier, where 0 is "invalid", >0 is
+ /// this module, and <-1 is something loaded from another module.
+ int ID;
+public:
+ FileID() : ID(0) {}
+
+ bool isValid() const { return 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(-1); }
+ unsigned getHashValue() const { return static_cast<unsigned>(ID); }
+
+private:
+ friend class SourceManager;
+ friend class ASTWriter;
+ friend class ASTReader;
+
+ static FileID get(int V) {
+ FileID F;
+ F.ID = V;
+ return F;
+ }
+ int getOpaqueValue() const { return ID; }
+};
+
+
+/// \brief Encodes a location in the source. The SourceManager can decode this
+/// to get at the full include stack, line and column information.
+///
+/// Technically, a source location is simply an offset into the manager's view
+/// of the input source, which is all input buffers (including macro
+/// expansions) concatenated in an effectively arbitrary order. The manager
+/// actually maintains two blocks of input buffers. One, starting at offset
+/// 0 and growing upwards, contains all buffers from this module. The other,
+/// starting at the highest possible offset and growing downwards, contains
+/// buffers of loaded modules.
+///
+/// In addition, one bit of SourceLocation is used for quick access to the
+/// information whether the location is in a file or a macro expansion.
+///
+/// It is important that this type remains small. It is currently 32 bits wide.
+class SourceLocation {
+ unsigned ID;
+ friend class SourceManager;
+ friend class ASTReader;
+ friend class ASTWriter;
+ enum : unsigned {
+ MacroIDBit = 1U << 31
+ };
+public:
+
+ SourceLocation() : ID(0) {}
+
+ bool isFileID() const { return (ID & MacroIDBit) == 0; }
+ bool isMacroID() const { return (ID & MacroIDBit) != 0; }
+
+ /// \brief 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:
+ /// \brief Return the offset into the manager's global input view.
+ 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:
+
+ /// \brief Return a source location with the specified offset from this
+ /// SourceLocation.
+ SourceLocation getLocWithOffset(int Offset) const {
+ assert(((getOffset()+Offset) & MacroIDBit) == 0 && "offset overflow");
+ SourceLocation L;
+ L.ID = ID+Offset;
+ return L;
+ }
+
+ /// \brief 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; }
+
+ /// \brief Turn a raw encoding of a SourceLocation object into
+ /// a real SourceLocation.
+ ///
+ /// \see getRawEncoding.
+ static SourceLocation getFromRawEncoding(unsigned Encoding) {
+ SourceLocation X;
+ X.ID = Encoding;
+ return X;
+ }
+
+ /// \brief 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();
+ }
+
+ /// \brief Turn a pointer encoding of a SourceLocation object back
+ /// into a real SourceLocation.
+ static SourceLocation getFromPtrEncoding(const void *Encoding) {
+ return getFromRawEncoding((unsigned)(uintptr_t)Encoding);
+ }
+
+ void print(raw_ostream &OS, const SourceManager &SM) const;
+ std::string printToString(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();
+}
+
+/// \brief A trivial 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;
+ }
+};
+
+/// \brief 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 of 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) {
+ return CharSourceRange(R, true);
+ }
+
+ static CharSourceRange getCharRange(SourceRange R) {
+ return CharSourceRange(R, false);
+ }
+
+ static CharSourceRange getTokenRange(SourceLocation B, SourceLocation E) {
+ return getTokenRange(SourceRange(B, E));
+ }
+ static CharSourceRange getCharRange(SourceLocation B, SourceLocation E) {
+ return getCharRange(SourceRange(B, E));
+ }
+
+ /// \brief 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; }
+ bool isCharRange() const { return !IsTokenRange; }
+
+ SourceLocation getBegin() const { return Range.getBegin(); }
+ SourceLocation getEnd() const { return Range.getEnd(); }
+ 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(); }
+};
+
+/// \brief A SourceLocation and its associated SourceManager.
+///
+/// This is useful for argument passing to functions that expect both objects.
+class FullSourceLoc : public SourceLocation {
+ const SourceManager *SrcMgr;
+public:
+ /// \brief Creates a FullSourceLoc where isValid() returns \c false.
+ explicit FullSourceLoc() : SrcMgr(nullptr) {}
+
+ explicit FullSourceLoc(SourceLocation Loc, const SourceManager &SM)
+ : SourceLocation(Loc), SrcMgr(&SM) {}
+
+ /// \pre This FullSourceLoc has an associated SourceManager.
+ const SourceManager &getManager() const {
+ assert(SrcMgr && "SourceManager is NULL.");
+ return *SrcMgr;
+ }
+
+ FileID getFileID() const;
+
+ FullSourceLoc getExpansionLoc() const;
+ FullSourceLoc getSpellingLoc() const;
+
+ unsigned getExpansionLineNumber(bool *Invalid = nullptr) const;
+ unsigned getExpansionColumnNumber(bool *Invalid = nullptr) const;
+
+ unsigned getSpellingLineNumber(bool *Invalid = nullptr) const;
+ unsigned getSpellingColumnNumber(bool *Invalid = nullptr) const;
+
+ const char *getCharacterData(bool *Invalid = nullptr) const;
+
+
+ /// \brief Return a StringRef to the source buffer data for the
+ /// specified FileID.
+ StringRef getBufferData(bool *Invalid = nullptr) const;
+
+ /// \brief 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);
+ }
+
+ /// \brief Comparison function class, useful for sorting FullSourceLocs.
+ struct BeforeThanCompare : public std::binary_function<FullSourceLoc,
+ FullSourceLoc, bool> {
+ bool operator()(const FullSourceLoc& lhs, const FullSourceLoc& rhs) const {
+ return lhs.isBeforeInTranslationUnitThan(rhs);
+ }
+ };
+
+ /// \brief Prints information about this FullSourceLoc to stderr.
+ ///
+ /// This is useful for debugging.
+ void dump() const;
+
+ 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);
+ }
+
+};
+
+/// \brief 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 expansion 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(nullptr) {}
+ PresumedLoc(const char *FN, unsigned Ln, unsigned Co, SourceLocation IL)
+ : Filename(FN), Line(Ln), Col(Co), IncludeLoc(IL) {
+ }
+
+ /// \brief 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 == nullptr; }
+ bool isValid() const { return Filename != nullptr; }
+
+ /// \brief Return the presumed filename of this location.
+ ///
+ /// This can be affected by \#line etc.
+ const char *getFilename() const { return Filename; }
+
+ /// \brief Return the presumed line number of this location.
+ ///
+ /// This can be affected by \#line etc.
+ unsigned getLine() const { return Line; }
+
+ /// \brief Return the presumed column number of this location.
+ ///
+ /// This cannot be affected by \#line, but is packaged here for convenience.
+ unsigned getColumn() const { return Col; }
+
+ /// \brief 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..99392a0
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Basic/SourceManager.h
@@ -0,0 +1,1711 @@
+//===--- 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.
+//
+//===----------------------------------------------------------------------===//
+///
+/// \file
+/// \brief Defines the SourceManager interface.
+///
+/// There are three different types of locations in a %file: a spelling
+/// location, an expansion location, and a presumed location.
+///
+/// Given an example of:
+/// \code
+/// #define min(x, y) x < y ? x : y
+/// \endcode
+///
+/// and then later on a use of min:
+/// \code
+/// #line 17
+/// return min(a, b);
+/// \endcode
+///
+/// The expansion location is the line in the source code where the macro
+/// was expanded (the return statement), the spelling location is the
+/// location in the source where the macro was originally defined,
+/// and the presumed location is where the line directive states that
+/// the line is 17, or any other line.
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_BASIC_SOURCEMANAGER_H
+#define LLVM_CLANG_BASIC_SOURCEMANAGER_H
+
+#include "clang/Basic/FileManager.h"
+#include "clang/Basic/LLVM.h"
+#include "clang/Basic/SourceLocation.h"
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/BitVector.h"
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/DenseSet.h"
+#include "llvm/ADT/IntrusiveRefCntPtr.h"
+#include "llvm/ADT/PointerIntPair.h"
+#include "llvm/ADT/PointerUnion.h"
+#include "llvm/Support/AlignOf.h"
+#include "llvm/Support/Allocator.h"
+#include "llvm/Support/DataTypes.h"
+#include "llvm/Support/MemoryBuffer.h"
+#include <cassert>
+#include <map>
+#include <memory>
+#include <vector>
+
+namespace clang {
+
+class DiagnosticsEngine;
+class SourceManager;
+class FileManager;
+class FileEntry;
+class LineTableInfo;
+class LangOptions;
+class ASTWriter;
+class ASTReader;
+
+/// \brief Public enums and private classes that are part of the
+/// SourceManager implementation.
+///
+namespace SrcMgr {
+ /// \brief Indicates 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 FileInfos when a \#pragma
+ /// system_header is seen or in various other cases.
+ ///
+ enum CharacteristicKind {
+ C_User, C_System, C_ExternCSystem
+ };
+
+ /// \brief One instance of this struct is kept for every file loaded or used.
+ ///
+ /// This object owns the MemoryBuffer object.
+ class LLVM_ALIGNAS(8) ContentCache {
+ enum CCFlags {
+ /// \brief Whether the buffer is invalid.
+ InvalidFlag = 0x01,
+ /// \brief Whether the buffer should not be freed on destruction.
+ DoNotFreeFlag = 0x02
+ };
+
+ /// \brief The actual buffer containing the characters from the input
+ /// file.
+ ///
+ /// This is owned by the ContentCache object. The bits indicate
+ /// whether the buffer is invalid.
+ mutable llvm::PointerIntPair<llvm::MemoryBuffer *, 2> Buffer;
+
+ public:
+ /// \brief Reference to the file entry representing this ContentCache.
+ ///
+ /// 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 *OrigEntry;
+
+ /// \brief References the file which the contents were actually loaded from.
+ ///
+ /// Can be different from 'Entry' if we overridden the contents of one file
+ /// with the contents of another file.
+ const FileEntry *ContentsEntry;
+
+ /// \brief 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;
+
+ /// \brief The number of lines in this ContentCache.
+ ///
+ /// This is only valid if SourceLineCache is non-null.
+ unsigned NumLines;
+
+ /// \brief Indicates whether the buffer itself was provided to override
+ /// the actual file contents.
+ ///
+ /// When true, the original entry may be a virtual file that does not
+ /// exist.
+ unsigned BufferOverridden : 1;
+
+ /// \brief True if this content cache was initially created for a source
+ /// file considered as a system one.
+ unsigned IsSystemFile : 1;
+
+ /// \brief True if this file may be transient, that is, if it might not
+ /// exist at some later point in time when this content entry is used,
+ /// after serialization and deserialization.
+ unsigned IsTransient : 1;
+
+ ContentCache(const FileEntry *Ent = nullptr) : ContentCache(Ent, Ent) {}
+
+ ContentCache(const FileEntry *Ent, const FileEntry *contentEnt)
+ : Buffer(nullptr, false), OrigEntry(Ent), ContentsEntry(contentEnt),
+ SourceLineCache(nullptr), NumLines(0), BufferOverridden(false),
+ IsSystemFile(false), IsTransient(false) {}
+
+ ~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 transferred, so this is a logical error.
+ ContentCache(const ContentCache &RHS)
+ : Buffer(nullptr, false), SourceLineCache(nullptr),
+ BufferOverridden(false), IsSystemFile(false), IsTransient(false) {
+ OrigEntry = RHS.OrigEntry;
+ ContentsEntry = RHS.ContentsEntry;
+
+ assert(RHS.Buffer.getPointer() == nullptr &&
+ RHS.SourceLineCache == nullptr &&
+ "Passed ContentCache object cannot own a buffer.");
+
+ NumLines = RHS.NumLines;
+ }
+
+ /// \brief Returns the memory buffer for the associated content.
+ ///
+ /// \param Diag Object through which diagnostics will be emitted if 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.
+ llvm::MemoryBuffer *getBuffer(DiagnosticsEngine &Diag,
+ const SourceManager &SM,
+ SourceLocation Loc = SourceLocation(),
+ bool *Invalid = nullptr) const;
+
+ /// \brief 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;
+
+ /// \brief Returns the number of bytes actually mapped for this
+ /// ContentCache.
+ ///
+ /// This can be 0 if the MemBuffer was not actually expanded.
+ unsigned getSizeBytesMapped() const;
+
+ /// Returns the kind of memory used to back the memory buffer for
+ /// this content cache. This is used for performance analysis.
+ llvm::MemoryBuffer::BufferKind getMemoryBufferKind() const;
+
+ void setBuffer(std::unique_ptr<llvm::MemoryBuffer> B) {
+ assert(!Buffer.getPointer() && "MemoryBuffer already set.");
+ Buffer.setPointer(B.release());
+ Buffer.setInt(0);
+ }
+
+ /// \brief Get the underlying buffer, returning NULL if the buffer is not
+ /// yet available.
+ llvm::MemoryBuffer *getRawBuffer() const { return Buffer.getPointer(); }
+
+ /// \brief Replace the existing buffer (which will be deleted)
+ /// with the given buffer.
+ void replaceBuffer(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;
+ }
+
+ private:
+ // Disable assignments.
+ ContentCache &operator=(const ContentCache& RHS) = delete;
+ };
+
+ // Assert that the \c ContentCache objects will always be 8-byte aligned so
+ // that we can pack 3 bits of integer into pointers to such objects.
+ static_assert(llvm::AlignOf<ContentCache>::Alignment >= 8,
+ "ContentCache must be 8-byte aligned.");
+
+ /// \brief 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
+ /// expanded from. The main include file has an invalid IncludeLoc.
+ ///
+ /// FileInfos contain a "ContentCache *", with the contents of the file.
+ ///
+ class FileInfo {
+ /// \brief 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
+
+ /// \brief Number of FileIDs (files and macros) that were created during
+ /// preprocessing of this \#include, including this SLocEntry.
+ ///
+ /// Zero means the preprocessor didn't provide such info for this SLocEntry.
+ unsigned NumCreatedFIDs;
+
+ /// \brief Contains the ContentCache* and the bits indicating the
+ /// characteristic of the file and whether it has \#line info, all
+ /// bitmangled together.
+ uintptr_t Data;
+
+ friend class clang::SourceManager;
+ friend class clang::ASTWriter;
+ friend class clang::ASTReader;
+ public:
+ /// \brief Return a FileInfo object.
+ static FileInfo get(SourceLocation IL, const ContentCache *Con,
+ CharacteristicKind FileCharacter) {
+ FileInfo X;
+ X.IncludeLoc = IL.getRawEncoding();
+ X.NumCreatedFIDs = 0;
+ 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 & ~uintptr_t(7));
+ }
+
+ /// \brief Return whether this is a system header or not.
+ CharacteristicKind getFileCharacteristic() const {
+ return (CharacteristicKind)(Data & 3);
+ }
+
+ /// \brief Return true if this FileID has \#line directives in it.
+ bool hasLineDirectives() const { return (Data & 4) != 0; }
+
+ /// \brief Set the flag that indicates that this FileID has
+ /// line table entries associated with it.
+ void setHasLineDirectives() {
+ Data |= 4;
+ }
+ };
+
+ /// \brief Each ExpansionInfo encodes the expansion location - where
+ /// the token was ultimately expanded, and the SpellingLoc - where the actual
+ /// character data for the token came from.
+ class ExpansionInfo {
+ // Really these are all SourceLocations.
+
+ /// \brief Where the spelling for the token can be found.
+ unsigned SpellingLoc;
+
+ /// In a macro expansion, ExpansionLocStart and ExpansionLocEnd
+ /// indicate the start and end of the expansion. In object-like macros,
+ /// they will be the same. In a function-like macro expansion, the start
+ /// will be the identifier and the end will be the ')'. Finally, in
+ /// macro-argument instantiations, the end will be 'SourceLocation()', an
+ /// invalid location.
+ unsigned ExpansionLocStart, ExpansionLocEnd;
+
+ public:
+ SourceLocation getSpellingLoc() const {
+ return SourceLocation::getFromRawEncoding(SpellingLoc);
+ }
+ SourceLocation getExpansionLocStart() const {
+ return SourceLocation::getFromRawEncoding(ExpansionLocStart);
+ }
+ SourceLocation getExpansionLocEnd() const {
+ SourceLocation EndLoc =
+ SourceLocation::getFromRawEncoding(ExpansionLocEnd);
+ return EndLoc.isInvalid() ? getExpansionLocStart() : EndLoc;
+ }
+
+ std::pair<SourceLocation,SourceLocation> getExpansionLocRange() const {
+ return std::make_pair(getExpansionLocStart(), getExpansionLocEnd());
+ }
+
+ bool isMacroArgExpansion() const {
+ // Note that this needs to return false for default constructed objects.
+ return getExpansionLocStart().isValid() &&
+ SourceLocation::getFromRawEncoding(ExpansionLocEnd).isInvalid();
+ }
+
+ bool isMacroBodyExpansion() const {
+ return getExpansionLocStart().isValid() &&
+ SourceLocation::getFromRawEncoding(ExpansionLocEnd).isValid();
+ }
+
+ bool isFunctionMacroExpansion() const {
+ return getExpansionLocStart().isValid() &&
+ getExpansionLocStart() != getExpansionLocEnd();
+ }
+
+ /// \brief Return a ExpansionInfo for an expansion.
+ ///
+ /// Start and End specify the expansion range (where the macro is
+ /// expanded), and SpellingLoc specifies the spelling location (where
+ /// the characters from the token come from). All three can refer to
+ /// normal File SLocs or expansion locations.
+ static ExpansionInfo create(SourceLocation SpellingLoc,
+ SourceLocation Start, SourceLocation End) {
+ ExpansionInfo X;
+ X.SpellingLoc = SpellingLoc.getRawEncoding();
+ X.ExpansionLocStart = Start.getRawEncoding();
+ X.ExpansionLocEnd = End.getRawEncoding();
+ return X;
+ }
+
+ /// \brief Return a special ExpansionInfo for the expansion of
+ /// a macro argument into a function-like macro's body.
+ ///
+ /// ExpansionLoc specifies the expansion location (where the macro is
+ /// expanded). This doesn't need to be a range because a macro is always
+ /// expanded at a macro parameter reference, and macro parameters are
+ /// always exactly one token. SpellingLoc specifies the spelling location
+ /// (where the characters from the token come from). ExpansionLoc and
+ /// SpellingLoc can both refer to normal File SLocs or expansion locations.
+ ///
+ /// Given the code:
+ /// \code
+ /// #define F(x) f(x)
+ /// F(42);
+ /// \endcode
+ ///
+ /// When expanding '\c F(42)', the '\c x' would call this with an
+ /// SpellingLoc pointing at '\c 42' and an ExpansionLoc pointing at its
+ /// location in the definition of '\c F'.
+ static ExpansionInfo createForMacroArg(SourceLocation SpellingLoc,
+ SourceLocation ExpansionLoc) {
+ // We store an intentionally invalid source location for the end of the
+ // expansion range to mark that this is a macro argument ion rather than
+ // a normal one.
+ return create(SpellingLoc, ExpansionLoc, SourceLocation());
+ }
+ };
+
+ /// \brief This is a discriminated union of FileInfo and ExpansionInfo.
+ ///
+ /// SourceManager keeps an array of these objects, and they are uniquely
+ /// identified by the FileID datatype.
+ class SLocEntry {
+ unsigned Offset : 31;
+ unsigned IsExpansion : 1;
+ union {
+ FileInfo File;
+ ExpansionInfo Expansion;
+ };
+ public:
+ unsigned getOffset() const { return Offset; }
+
+ bool isExpansion() const { return IsExpansion; }
+ bool isFile() const { return !isExpansion(); }
+
+ const FileInfo &getFile() const {
+ assert(isFile() && "Not a file SLocEntry!");
+ return File;
+ }
+
+ const ExpansionInfo &getExpansion() const {
+ assert(isExpansion() && "Not a macro expansion SLocEntry!");
+ return Expansion;
+ }
+
+ static SLocEntry get(unsigned Offset, const FileInfo &FI) {
+ assert(!(Offset & (1 << 31)) && "Offset is too large");
+ SLocEntry E;
+ E.Offset = Offset;
+ E.IsExpansion = false;
+ E.File = FI;
+ return E;
+ }
+
+ static SLocEntry get(unsigned Offset, const ExpansionInfo &Expansion) {
+ assert(!(Offset & (1 << 31)) && "Offset is too large");
+ SLocEntry E;
+ E.Offset = Offset;
+ E.IsExpansion = true;
+ E.Expansion = Expansion;
+ 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, which will always be
+ /// less than -1.
+ ///
+ /// \returns true if an error occurred that prevented the source-location
+ /// entry from being loaded.
+ virtual bool ReadSLocEntry(int ID) = 0;
+
+ /// \brief Retrieve the module import location and name for the given ID, if
+ /// in fact it was loaded from a module (rather than, say, a precompiled
+ /// header).
+ virtual std::pair<SourceLocation, StringRef> getModuleImportLoc(int ID) = 0;
+};
+
+
+/// \brief Holds the cache used by isBeforeInTranslationUnit.
+///
+/// The cache structure is complex enough to be worth breaking out of
+/// SourceManager.
+class InBeforeInTUCacheEntry {
+ /// \brief The FileID's of the cached query.
+ ///
+ /// If these match up with a subsequent query, the result can be reused.
+ FileID LQueryFID, RQueryFID;
+
+ /// \brief True if LQueryFID was created before RQueryFID.
+ ///
+ /// This is used to compare macro expansion locations.
+ bool IsLQFIDBeforeRQFID;
+
+ /// \brief The file found in common between the two \#include traces, i.e.,
+ /// the nearest common ancestor of the \#include tree.
+ FileID CommonFID;
+
+ /// \brief 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 vice versa) then these can be a
+ /// random token in the parent.
+ unsigned LCommonOffset, RCommonOffset;
+public:
+ /// \brief 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;
+ }
+
+ /// \brief If the cache is valid, compute the result given the
+ /// specified offsets in the LHS/RHS FileID'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;
+
+ // It is common for multiple macro expansions to be "included" from the same
+ // location (expansion location), in which case use the order of the FileIDs
+ // to determine which came first. This will also take care the case where
+ // one of the locations points at the inclusion/expansion point of the other
+ // in which case its FileID will come before the other.
+ if (LOffset == ROffset)
+ return IsLQFIDBeforeRQFID;
+
+ return LOffset < ROffset;
+ }
+
+ /// \brief Set up a new query.
+ void setQueryFIDs(FileID LHS, FileID RHS, bool isLFIDBeforeRFID) {
+ assert(LHS != RHS);
+ LQueryFID = LHS;
+ RQueryFID = RHS;
+ IsLQFIDBeforeRQFID = isLFIDBeforeRFID;
+ }
+
+ void clear() {
+ LQueryFID = RQueryFID = FileID();
+ IsLQFIDBeforeRQFID = false;
+ }
+
+ void setCommonLoc(FileID commonFID, unsigned lCommonOffset,
+ unsigned rCommonOffset) {
+ CommonFID = commonFID;
+ LCommonOffset = lCommonOffset;
+ RCommonOffset = rCommonOffset;
+ }
+
+};
+
+/// \brief The stack used when building modules on demand, which is used
+/// to provide a link between the source managers of the different compiler
+/// instances.
+typedef ArrayRef<std::pair<std::string, FullSourceLoc> > ModuleBuildStack;
+
+/// \brief This class 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 expansion locations. Spelling
+/// locations represent where the bytes corresponding to a token came from and
+/// expansion 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 expansion location specifies
+/// where it was expanded.
+class SourceManager : public RefCountedBase<SourceManager> {
+ /// \brief DiagnosticsEngine object.
+ DiagnosticsEngine &Diag;
+
+ FileManager &FileMgr;
+
+ mutable llvm::BumpPtrAllocator ContentCacheAlloc;
+
+ /// \brief Memoized information about all of the files tracked by this
+ /// SourceManager.
+ ///
+ /// This map 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;
+
+ /// \brief True if the ContentCache for files that are overridden by other
+ /// files, should report the original file name. Defaults to true.
+ bool OverridenFilesKeepOriginalName;
+
+ /// \brief True if non-system source files should be treated as volatile
+ /// (likely to change while trying to use them). Defaults to false.
+ bool UserFilesAreVolatile;
+
+ /// \brief True if all files read during this compilation should be treated
+ /// as transient (may not be present in later compilations using a module
+ /// file created from this compilation). Defaults to false.
+ bool FilesAreTransient;
+
+ struct OverriddenFilesInfoTy {
+ /// \brief Files that have been overridden with the contents from another
+ /// file.
+ llvm::DenseMap<const FileEntry *, const FileEntry *> OverriddenFiles;
+ /// \brief Files that were overridden with a memory buffer.
+ llvm::DenseSet<const FileEntry *> OverriddenFilesWithBuffer;
+ };
+
+ /// \brief Lazily create the object keeping overridden files info, since
+ /// it is uncommonly used.
+ std::unique_ptr<OverriddenFilesInfoTy> OverriddenFilesInfo;
+
+ OverriddenFilesInfoTy &getOverriddenFilesInfo() {
+ if (!OverriddenFilesInfo)
+ OverriddenFilesInfo.reset(new OverriddenFilesInfoTy);
+ return *OverriddenFilesInfo;
+ }
+
+ /// \brief 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;
+
+ /// \brief The table of SLocEntries that are local to this module.
+ ///
+ /// Positive FileIDs are indexes into this table. Entry 0 indicates an invalid
+ /// expansion.
+ SmallVector<SrcMgr::SLocEntry, 0> LocalSLocEntryTable;
+
+ /// \brief The table of SLocEntries that are loaded from other modules.
+ ///
+ /// Negative FileIDs are indexes into this table. To get from ID to an index,
+ /// use (-ID - 2).
+ mutable SmallVector<SrcMgr::SLocEntry, 0> LoadedSLocEntryTable;
+
+ /// \brief The starting offset of the next local SLocEntry.
+ ///
+ /// This is LocalSLocEntryTable.back().Offset + the size of that entry.
+ unsigned NextLocalOffset;
+
+ /// \brief The starting offset of the latest batch of loaded SLocEntries.
+ ///
+ /// This is LoadedSLocEntryTable.back().Offset, except that that entry might
+ /// not have been loaded, so that value would be unknown.
+ unsigned CurrentLoadedOffset;
+
+ /// \brief The highest possible offset is 2^31-1, so CurrentLoadedOffset
+ /// starts at 2^31.
+ static const unsigned MaxLoadedOffset = 1U << 31U;
+
+ /// \brief A bitmap that indicates whether the entries of LoadedSLocEntryTable
+ /// have already been loaded from the external source.
+ ///
+ /// Same indexing as LoadedSLocEntryTable.
+ llvm::BitVector SLocEntryLoaded;
+
+ /// \brief An external source for source location entries.
+ ExternalSLocEntrySource *ExternalSLocEntries;
+
+ /// \brief 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;
+
+ /// \brief Holds information for \#line directives.
+ ///
+ /// This is referenced by indices from SLocEntryTable.
+ LineTableInfo *LineTable;
+
+ /// \brief 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;
+
+ /// \brief The file ID for the main source file of the translation unit.
+ FileID MainFileID;
+
+ /// \brief The file ID for the precompiled preamble there is one.
+ FileID PreambleFileID;
+
+ // Statistics for -print-stats.
+ mutable unsigned NumLinearScans, NumBinaryProbes;
+
+ /// \brief Associates a FileID with its "included/expanded in" decomposed
+ /// location.
+ ///
+ /// Used to cache results from and speed-up \c getDecomposedIncludedLoc
+ /// function.
+ mutable llvm::DenseMap<FileID, std::pair<FileID, unsigned> > IncludedLocMap;
+
+ /// The key value into the IsBeforeInTUCache table.
+ typedef std::pair<FileID, FileID> IsBeforeInTUCacheKey;
+
+ /// The IsBeforeInTranslationUnitCache is a mapping from FileID pairs
+ /// to cache results.
+ typedef llvm::DenseMap<IsBeforeInTUCacheKey, InBeforeInTUCacheEntry>
+ InBeforeInTUCache;
+
+ /// Cache results for the isBeforeInTranslationUnit method.
+ mutable InBeforeInTUCache IBTUCache;
+ mutable InBeforeInTUCacheEntry IBTUCacheOverflow;
+
+ /// Return the cache entry for comparing the given file IDs
+ /// for isBeforeInTranslationUnit.
+ InBeforeInTUCacheEntry &getInBeforeInTUCache(FileID LFID, FileID RFID) const;
+
+ // Cache for the "fake" buffer used for error-recovery purposes.
+ mutable std::unique_ptr<llvm::MemoryBuffer> FakeBufferForRecovery;
+
+ mutable std::unique_ptr<SrcMgr::ContentCache> FakeContentCacheForRecovery;
+
+ /// \brief Lazily computed map of macro argument chunks to their expanded
+ /// source location.
+ typedef std::map<unsigned, SourceLocation> MacroArgsMap;
+
+ mutable llvm::DenseMap<FileID, MacroArgsMap *> MacroArgsCacheMap;
+
+ /// \brief The stack of modules being built, which is used to detect
+ /// cycles in the module dependency graph as modules are being built, as
+ /// well as to describe why we're rebuilding a particular module.
+ ///
+ /// There is no way to set this value from the command line. If we ever need
+ /// to do so (e.g., if on-demand module construction moves out-of-process),
+ /// we can add a cc1-level option to do so.
+ SmallVector<std::pair<std::string, FullSourceLoc>, 2> StoredModuleBuildStack;
+
+ // SourceManager doesn't support copy construction.
+ explicit SourceManager(const SourceManager&) = delete;
+ void operator=(const SourceManager&) = delete;
+public:
+ SourceManager(DiagnosticsEngine &Diag, FileManager &FileMgr,
+ bool UserFilesAreVolatile = false);
+ ~SourceManager();
+
+ void clearIDTables();
+
+ DiagnosticsEngine &getDiagnostics() const { return Diag; }
+
+ FileManager &getFileManager() const { return FileMgr; }
+
+ /// \brief Set true if the SourceManager should report the original file name
+ /// for contents of files that were overridden by other files. Defaults to
+ /// true.
+ void setOverridenFilesKeepOriginalName(bool value) {
+ OverridenFilesKeepOriginalName = value;
+ }
+
+ /// \brief True if non-system source files should be treated as volatile
+ /// (likely to change while trying to use them).
+ bool userFilesAreVolatile() const { return UserFilesAreVolatile; }
+
+ /// \brief Retrieve the module build stack.
+ ModuleBuildStack getModuleBuildStack() const {
+ return StoredModuleBuildStack;
+ }
+
+ /// \brief Set the module build stack.
+ void setModuleBuildStack(ModuleBuildStack stack) {
+ StoredModuleBuildStack.clear();
+ StoredModuleBuildStack.append(stack.begin(), stack.end());
+ }
+
+ /// \brief Push an entry to the module build stack.
+ void pushModuleBuildStack(StringRef moduleName, FullSourceLoc importLoc) {
+ StoredModuleBuildStack.push_back(std::make_pair(moduleName.str(),importLoc));
+ }
+
+ //===--------------------------------------------------------------------===//
+ // MainFileID creation and querying methods.
+ //===--------------------------------------------------------------------===//
+
+ /// \brief Returns the FileID of the main source file.
+ FileID getMainFileID() const { return MainFileID; }
+
+ /// \brief Set the file ID for the main source file.
+ void setMainFileID(FileID FID) {
+ MainFileID = FID;
+ }
+
+ /// \brief Set the file ID for the precompiled preamble.
+ void setPreambleFileID(FileID Preamble) {
+ assert(PreambleFileID.isInvalid() && "PreambleFileID already set!");
+ PreambleFileID = Preamble;
+ }
+
+ /// \brief Get the file ID for the precompiled preamble if there is one.
+ FileID getPreambleFileID() const { return PreambleFileID; }
+
+ //===--------------------------------------------------------------------===//
+ // Methods to create new FileID's and macro expansions.
+ //===--------------------------------------------------------------------===//
+
+ /// \brief Create a new FileID that represents the specified file
+ /// being \#included from the specified IncludePosition.
+ ///
+ /// This translates NULL into standard input.
+ FileID createFileID(const FileEntry *SourceFile, SourceLocation IncludePos,
+ SrcMgr::CharacteristicKind FileCharacter,
+ int LoadedID = 0, unsigned LoadedOffset = 0) {
+ const SrcMgr::ContentCache *
+ IR = getOrCreateContentCache(SourceFile,
+ /*isSystemFile=*/FileCharacter != SrcMgr::C_User);
+ assert(IR && "getOrCreateContentCache() cannot return NULL");
+ return createFileID(IR, IncludePos, FileCharacter, LoadedID, LoadedOffset);
+ }
+
+ /// \brief 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 createFileID(std::unique_ptr<llvm::MemoryBuffer> Buffer,
+ SrcMgr::CharacteristicKind FileCharacter = SrcMgr::C_User,
+ int LoadedID = 0, unsigned LoadedOffset = 0,
+ SourceLocation IncludeLoc = SourceLocation()) {
+ return createFileID(createMemBufferContentCache(std::move(Buffer)),
+ IncludeLoc, FileCharacter, LoadedID, LoadedOffset);
+ }
+
+ /// \brief Return a new SourceLocation that encodes the
+ /// fact that a token from SpellingLoc should actually be referenced from
+ /// ExpansionLoc, and that it represents the expansion of a macro argument
+ /// into the function-like macro body.
+ SourceLocation createMacroArgExpansionLoc(SourceLocation Loc,
+ SourceLocation ExpansionLoc,
+ unsigned TokLength);
+
+ /// \brief Return a new SourceLocation that encodes the fact
+ /// that a token from SpellingLoc should actually be referenced from
+ /// ExpansionLoc.
+ SourceLocation createExpansionLoc(SourceLocation Loc,
+ SourceLocation ExpansionLocStart,
+ SourceLocation ExpansionLocEnd,
+ unsigned TokLength,
+ int LoadedID = 0,
+ unsigned LoadedOffset = 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.
+ llvm::MemoryBuffer *getMemoryBufferForFile(const FileEntry *File,
+ bool *Invalid = nullptr);
+
+ /// \brief Override the contents of the given source file by providing an
+ /// already-allocated buffer.
+ ///
+ /// \param SourceFile the source file whose contents will be overridden.
+ ///
+ /// \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,
+ llvm::MemoryBuffer *Buffer, bool DoNotFree);
+ void overrideFileContents(const FileEntry *SourceFile,
+ std::unique_ptr<llvm::MemoryBuffer> Buffer) {
+ overrideFileContents(SourceFile, Buffer.release(), /*DoNotFree*/ false);
+ }
+
+ /// \brief Override the given source file with another one.
+ ///
+ /// \param SourceFile the source file which will be overridden.
+ ///
+ /// \param NewFile the file whose contents will be used as the
+ /// data instead of the contents of the given source file.
+ void overrideFileContents(const FileEntry *SourceFile,
+ const FileEntry *NewFile);
+
+ /// \brief Returns true if the file contents have been overridden.
+ bool isFileOverridden(const FileEntry *File) {
+ if (OverriddenFilesInfo) {
+ if (OverriddenFilesInfo->OverriddenFilesWithBuffer.count(File))
+ return true;
+ if (OverriddenFilesInfo->OverriddenFiles.find(File) !=
+ OverriddenFilesInfo->OverriddenFiles.end())
+ return true;
+ }
+ return false;
+ }
+
+ /// \brief Disable overridding the contents of a file, previously enabled
+ /// with #overrideFileContents.
+ ///
+ /// This should be called before parsing has begun.
+ void disableFileContentsOverride(const FileEntry *File);
+
+ /// \brief Specify that a file is transient.
+ void setFileIsTransient(const FileEntry *SourceFile);
+
+ /// \brief Specify that all files that are read during this compilation are
+ /// transient.
+ void setAllFilesAreTransient(bool Transient) {
+ FilesAreTransient = Transient;
+ }
+
+ //===--------------------------------------------------------------------===//
+ // FileID manipulation methods.
+ //===--------------------------------------------------------------------===//
+
+ /// \brief 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.
+ llvm::MemoryBuffer *getBuffer(FileID FID, SourceLocation Loc,
+ bool *Invalid = nullptr) const {
+ bool MyInvalid = false;
+ const SrcMgr::SLocEntry &Entry = getSLocEntry(FID, &MyInvalid);
+ if (MyInvalid || !Entry.isFile()) {
+ if (Invalid)
+ *Invalid = true;
+
+ return getFakeBufferForRecovery();
+ }
+
+ return Entry.getFile().getContentCache()->getBuffer(Diag, *this, Loc,
+ Invalid);
+ }
+
+ llvm::MemoryBuffer *getBuffer(FileID FID, bool *Invalid = nullptr) const {
+ bool MyInvalid = false;
+ const SrcMgr::SLocEntry &Entry = getSLocEntry(FID, &MyInvalid);
+ if (MyInvalid || !Entry.isFile()) {
+ if (Invalid)
+ *Invalid = true;
+
+ return getFakeBufferForRecovery();
+ }
+
+ return Entry.getFile().getContentCache()->getBuffer(Diag, *this,
+ SourceLocation(),
+ Invalid);
+ }
+
+ /// \brief Returns the FileEntry record for the provided FileID.
+ const FileEntry *getFileEntryForID(FileID FID) const {
+ bool MyInvalid = false;
+ const SrcMgr::SLocEntry &Entry = getSLocEntry(FID, &MyInvalid);
+ if (MyInvalid || !Entry.isFile())
+ return nullptr;
+
+ const SrcMgr::ContentCache *Content = Entry.getFile().getContentCache();
+ if (!Content)
+ return nullptr;
+ return Content->OrigEntry;
+ }
+
+ /// \brief Returns the FileEntry record for the provided SLocEntry.
+ const FileEntry *getFileEntryForSLocEntry(const SrcMgr::SLocEntry &sloc) const
+ {
+ const SrcMgr::ContentCache *Content = sloc.getFile().getContentCache();
+ if (!Content)
+ return nullptr;
+ return Content->OrigEntry;
+ }
+
+ /// \brief 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.
+ StringRef getBufferData(FileID FID, bool *Invalid = nullptr) const;
+
+ /// \brief Get the number of FileIDs (files and macros) that were created
+ /// during preprocessing of \p FID, including it.
+ unsigned getNumCreatedFIDsForFileID(FileID FID) const {
+ bool Invalid = false;
+ const SrcMgr::SLocEntry &Entry = getSLocEntry(FID, &Invalid);
+ if (Invalid || !Entry.isFile())
+ return 0;
+
+ return Entry.getFile().NumCreatedFIDs;
+ }
+
+ /// \brief Set the number of FileIDs (files and macros) that were created
+ /// during preprocessing of \p FID, including it.
+ void setNumCreatedFIDsForFileID(FileID FID, unsigned NumFIDs) const {
+ bool Invalid = false;
+ const SrcMgr::SLocEntry &Entry = getSLocEntry(FID, &Invalid);
+ if (Invalid || !Entry.isFile())
+ return;
+
+ assert(Entry.getFile().NumCreatedFIDs == 0 && "Already set!");
+ const_cast<SrcMgr::FileInfo &>(Entry.getFile()).NumCreatedFIDs = NumFIDs;
+ }
+
+ //===--------------------------------------------------------------------===//
+ // SourceLocation manipulation methods.
+ //===--------------------------------------------------------------------===//
+
+ /// \brief 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);
+ }
+
+ /// \brief Return the filename of the file containing a SourceLocation.
+ StringRef getFilename(SourceLocation SpellingLoc) const {
+ if (const FileEntry *F = getFileEntryForID(getFileID(SpellingLoc)))
+ return F->getName();
+ return StringRef();
+ }
+
+ /// \brief Return the source location corresponding to the first byte of
+ /// the specified file.
+ SourceLocation getLocForStartOfFile(FileID FID) const {
+ bool Invalid = false;
+ const SrcMgr::SLocEntry &Entry = getSLocEntry(FID, &Invalid);
+ if (Invalid || !Entry.isFile())
+ return SourceLocation();
+
+ unsigned FileOffset = Entry.getOffset();
+ return SourceLocation::getFileLoc(FileOffset);
+ }
+
+ /// \brief Return the source location corresponding to the last byte of the
+ /// specified file.
+ SourceLocation getLocForEndOfFile(FileID FID) const {
+ bool Invalid = false;
+ const SrcMgr::SLocEntry &Entry = getSLocEntry(FID, &Invalid);
+ if (Invalid || !Entry.isFile())
+ return SourceLocation();
+
+ unsigned FileOffset = Entry.getOffset();
+ return SourceLocation::getFileLoc(FileOffset + getFileIDSize(FID));
+ }
+
+ /// \brief Returns the include location if \p FID is a \#include'd file
+ /// otherwise it returns an invalid location.
+ SourceLocation getIncludeLoc(FileID FID) const {
+ bool Invalid = false;
+ const SrcMgr::SLocEntry &Entry = getSLocEntry(FID, &Invalid);
+ if (Invalid || !Entry.isFile())
+ return SourceLocation();
+
+ return Entry.getFile().getIncludeLoc();
+ }
+
+ // \brief Returns the import location if the given source location is
+ // located within a module, or an invalid location if the source location
+ // is within the current translation unit.
+ std::pair<SourceLocation, StringRef>
+ getModuleImportLoc(SourceLocation Loc) const {
+ FileID FID = getFileID(Loc);
+
+ // Positive file IDs are in the current translation unit, and -1 is a
+ // placeholder.
+ if (FID.ID >= -1)
+ return std::make_pair(SourceLocation(), "");
+
+ return ExternalSLocEntries->getModuleImportLoc(FID.ID);
+ }
+
+ /// \brief Given a SourceLocation object \p Loc, return the expansion
+ /// location referenced by the ID.
+ SourceLocation getExpansionLoc(SourceLocation Loc) const {
+ // Handle the non-mapped case inline, defer to out of line code to handle
+ // expansions.
+ if (Loc.isFileID()) return Loc;
+ return getExpansionLocSlowCase(Loc);
+ }
+
+ /// \brief Given \p Loc, if it is a macro location return the expansion
+ /// location or the spelling location, depending on if it comes from a
+ /// macro argument or not.
+ SourceLocation getFileLoc(SourceLocation Loc) const {
+ if (Loc.isFileID()) return Loc;
+ return getFileLocSlowCase(Loc);
+ }
+
+ /// \brief Return the start/end of the expansion information for an
+ /// expansion location.
+ ///
+ /// \pre \p Loc is required to be an expansion location.
+ std::pair<SourceLocation,SourceLocation>
+ getImmediateExpansionRange(SourceLocation Loc) const;
+
+ /// \brief Given a SourceLocation object, return the range of
+ /// tokens covered by the expansion in the ultimate file.
+ std::pair<SourceLocation,SourceLocation>
+ getExpansionRange(SourceLocation Loc) const;
+
+ /// \brief Given a SourceRange object, return the range of
+ /// tokens covered by the expansion in the ultimate file.
+ SourceRange getExpansionRange(SourceRange Range) const {
+ return SourceRange(getExpansionRange(Range.getBegin()).first,
+ getExpansionRange(Range.getEnd()).second);
+ }
+
+ /// \brief 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
+ // expansions.
+ if (Loc.isFileID()) return Loc;
+ return getSpellingLocSlowCase(Loc);
+ }
+
+ /// \brief 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;
+
+ /// \brief 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);
+ bool Invalid = false;
+ const SrcMgr::SLocEntry &E = getSLocEntry(FID, &Invalid);
+ if (Invalid)
+ return std::make_pair(FileID(), 0);
+ return std::make_pair(FID, Loc.getOffset()-E.getOffset());
+ }
+
+ /// \brief Decompose the specified location into a raw FileID + Offset pair.
+ ///
+ /// If the location is an expansion record, walk through it until we find
+ /// the final location expanded.
+ std::pair<FileID, unsigned>
+ getDecomposedExpansionLoc(SourceLocation Loc) const {
+ FileID FID = getFileID(Loc);
+ bool Invalid = false;
+ const SrcMgr::SLocEntry *E = &getSLocEntry(FID, &Invalid);
+ if (Invalid)
+ return std::make_pair(FileID(), 0);
+
+ unsigned Offset = Loc.getOffset()-E->getOffset();
+ if (Loc.isFileID())
+ return std::make_pair(FID, Offset);
+
+ return getDecomposedExpansionLocSlowCase(E);
+ }
+
+ /// \brief Decompose the specified location into a raw FileID + Offset pair.
+ ///
+ /// If the location is an expansion record, walk through it until we find
+ /// its spelling record.
+ std::pair<FileID, unsigned>
+ getDecomposedSpellingLoc(SourceLocation Loc) const {
+ FileID FID = getFileID(Loc);
+ bool Invalid = false;
+ const SrcMgr::SLocEntry *E = &getSLocEntry(FID, &Invalid);
+ if (Invalid)
+ return std::make_pair(FileID(), 0);
+
+ unsigned Offset = Loc.getOffset()-E->getOffset();
+ if (Loc.isFileID())
+ return std::make_pair(FID, Offset);
+ return getDecomposedSpellingLocSlowCase(E, Offset);
+ }
+
+ /// \brief Returns the "included/expanded in" decomposed location of the given
+ /// FileID.
+ std::pair<FileID, unsigned> getDecomposedIncludedLoc(FileID FID) const;
+
+ /// \brief 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;
+ }
+
+ /// \brief Tests whether the given source location represents a macro
+ /// argument's expansion into the function-like macro definition.
+ ///
+ /// \param StartLoc If non-null and function returns true, it is set to the
+ /// start location of the macro argument expansion.
+ ///
+ /// Such source locations only appear inside of the expansion
+ /// locations representing where a particular function-like macro was
+ /// expanded.
+ bool isMacroArgExpansion(SourceLocation Loc,
+ SourceLocation *StartLoc = nullptr) const;
+
+ /// \brief Tests whether the given source location represents the expansion of
+ /// a macro body.
+ ///
+ /// This is equivalent to testing whether the location is part of a macro
+ /// expansion but not the expansion of an argument to a function-like macro.
+ bool isMacroBodyExpansion(SourceLocation Loc) const;
+
+ /// \brief Returns true if the given MacroID location points at the beginning
+ /// of the immediate macro expansion.
+ ///
+ /// \param MacroBegin If non-null and function returns true, it is set to the
+ /// begin location of the immediate macro expansion.
+ bool isAtStartOfImmediateMacroExpansion(SourceLocation Loc,
+ SourceLocation *MacroBegin = nullptr) const;
+
+ /// \brief Returns true if the given MacroID location points at the character
+ /// end of the immediate macro expansion.
+ ///
+ /// \param MacroEnd If non-null and function returns true, it is set to the
+ /// character end location of the immediate macro expansion.
+ bool
+ isAtEndOfImmediateMacroExpansion(SourceLocation Loc,
+ SourceLocation *MacroEnd = nullptr) const;
+
+ /// \brief Returns true if \p Loc is inside the [\p Start, +\p Length)
+ /// chunk of the source location address space.
+ ///
+ /// If it's true and \p RelativeOffset is non-null, it will be set to the
+ /// relative offset of \p Loc inside the chunk.
+ bool isInSLocAddrSpace(SourceLocation Loc,
+ SourceLocation Start, unsigned Length,
+ unsigned *RelativeOffset = nullptr) const {
+ assert(((Start.getOffset() < NextLocalOffset &&
+ Start.getOffset()+Length <= NextLocalOffset) ||
+ (Start.getOffset() >= CurrentLoadedOffset &&
+ Start.getOffset()+Length < MaxLoadedOffset)) &&
+ "Chunk is not valid SLoc address space");
+ unsigned LocOffs = Loc.getOffset();
+ unsigned BeginOffs = Start.getOffset();
+ unsigned EndOffs = BeginOffs + Length;
+ if (LocOffs >= BeginOffs && LocOffs < EndOffs) {
+ if (RelativeOffset)
+ *RelativeOffset = LocOffs - BeginOffs;
+ return true;
+ }
+
+ return false;
+ }
+
+ /// \brief Return true if both \p LHS and \p RHS are in the local source
+ /// location address space or the loaded one.
+ ///
+ /// If it's true and \p RelativeOffset is non-null, it will be set to the
+ /// offset of \p RHS relative to \p LHS.
+ bool isInSameSLocAddrSpace(SourceLocation LHS, SourceLocation RHS,
+ int *RelativeOffset) const {
+ unsigned LHSOffs = LHS.getOffset(), RHSOffs = RHS.getOffset();
+ bool LHSLoaded = LHSOffs >= CurrentLoadedOffset;
+ bool RHSLoaded = RHSOffs >= CurrentLoadedOffset;
+
+ if (LHSLoaded == RHSLoaded) {
+ if (RelativeOffset)
+ *RelativeOffset = RHSOffs - LHSOffs;
+ return true;
+ }
+
+ return false;
+ }
+
+ //===--------------------------------------------------------------------===//
+ // Queries about the code at a SourceLocation.
+ //===--------------------------------------------------------------------===//
+
+ /// \brief 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 = nullptr) const;
+
+ /// \brief 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 expansion location
+ /// before calling this method.
+ unsigned getColumnNumber(FileID FID, unsigned FilePos,
+ bool *Invalid = nullptr) const;
+ unsigned getSpellingColumnNumber(SourceLocation Loc,
+ bool *Invalid = nullptr) const;
+ unsigned getExpansionColumnNumber(SourceLocation Loc,
+ bool *Invalid = nullptr) const;
+ unsigned getPresumedColumnNumber(SourceLocation Loc,
+ bool *Invalid = nullptr) const;
+
+ /// \brief 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 = nullptr) const;
+ unsigned getSpellingLineNumber(SourceLocation Loc, bool *Invalid = nullptr) const;
+ unsigned getExpansionLineNumber(SourceLocation Loc, bool *Invalid = nullptr) const;
+ unsigned getPresumedLineNumber(SourceLocation Loc, bool *Invalid = nullptr) const;
+
+ /// \brief 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 = nullptr) const;
+
+ /// \brief 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:
+ /// \code
+ /// # 4 "foo.h" 3
+ /// \endcode
+ /// 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;
+
+ /// \brief 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 expansion point of
+ /// an expansion location, not at the spelling location.
+ ///
+ /// \returns The presumed location of the specified SourceLocation. If the
+ /// presumed location cannot be calculated (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,
+ bool UseLineDirectives = true) const;
+
+ /// \brief Returns whether the PresumedLoc for a given SourceLocation is
+ /// in the main file.
+ ///
+ /// This computes the "presumed" location for a SourceLocation, then checks
+ /// whether it came from a file other than the main file. This is different
+ /// from isWrittenInMainFile() because it takes line marker directives into
+ /// account.
+ bool isInMainFile(SourceLocation Loc) const;
+
+ /// \brief Returns true if the spelling locations for both SourceLocations
+ /// are part of the same file buffer.
+ ///
+ /// This check ignores line marker directives.
+ bool isWrittenInSameFile(SourceLocation Loc1, SourceLocation Loc2) const {
+ return getFileID(Loc1) == getFileID(Loc2);
+ }
+
+ /// \brief Returns true if the spelling location for the given location
+ /// is in the main file buffer.
+ ///
+ /// This check ignores line marker directives.
+ bool isWrittenInMainFile(SourceLocation Loc) const {
+ return getFileID(Loc) == getMainFileID();
+ }
+
+ /// \brief Returns if a SourceLocation is in a system header.
+ bool isInSystemHeader(SourceLocation Loc) const {
+ return getFileCharacteristic(Loc) != SrcMgr::C_User;
+ }
+
+ /// \brief Returns if a SourceLocation is in an "extern C" system header.
+ bool isInExternCSystemHeader(SourceLocation Loc) const {
+ return getFileCharacteristic(Loc) == SrcMgr::C_ExternCSystem;
+ }
+
+ /// \brief Returns whether \p Loc is expanded from a macro in a system header.
+ bool isInSystemMacro(SourceLocation loc) {
+ return loc.isMacroID() && isInSystemHeader(getSpellingLoc(loc));
+ }
+
+ /// \brief The size of the SLocEntry that \p FID represents.
+ unsigned getFileIDSize(FileID FID) const;
+
+ /// \brief Given a specific FileID, returns true if \p Loc is inside that
+ /// FileID chunk and sets relative offset (offset of \p Loc from beginning
+ /// of FileID) to \p relativeOffset.
+ bool isInFileID(SourceLocation Loc, FileID FID,
+ unsigned *RelativeOffset = nullptr) const {
+ unsigned Offs = Loc.getOffset();
+ if (isOffsetInFileID(FID, Offs)) {
+ if (RelativeOffset)
+ *RelativeOffset = Offs - getSLocEntry(FID).getOffset();
+ return true;
+ }
+
+ return false;
+ }
+
+ //===--------------------------------------------------------------------===//
+ // Line Table Manipulation Routines
+ //===--------------------------------------------------------------------===//
+
+ /// \brief Return the uniqued ID for the specified filename.
+ ///
+ unsigned getLineTableFilenameID(StringRef Str);
+
+ /// \brief 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 != nullptr; }
+
+ /// \brief Retrieve the stored line table.
+ LineTableInfo &getLineTable();
+
+ //===--------------------------------------------------------------------===//
+ // Queries for performance analysis.
+ //===--------------------------------------------------------------------===//
+
+ /// \brief Return the total amount of physical memory allocated by the
+ /// ContentCache allocator.
+ size_t getContentCacheSize() const {
+ return ContentCacheAlloc.getTotalMemory();
+ }
+
+ struct MemoryBufferSizes {
+ const size_t malloc_bytes;
+ const size_t mmap_bytes;
+
+ MemoryBufferSizes(size_t malloc_bytes, size_t mmap_bytes)
+ : malloc_bytes(malloc_bytes), mmap_bytes(mmap_bytes) {}
+ };
+
+ /// \brief Return the amount of memory used by memory buffers, breaking down
+ /// by heap-backed versus mmap'ed memory.
+ MemoryBufferSizes getMemoryBufferSizes() const;
+
+ /// \brief Return the amount of memory used for various side tables and
+ /// data structures in the SourceManager.
+ size_t getDataStructureSizes() const;
+
+ //===--------------------------------------------------------------------===//
+ // 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 translateFileLineCol(const FileEntry *SourceFile,
+ unsigned Line, unsigned Col) const;
+
+ /// \brief Get the FileID for the given file.
+ ///
+ /// If the source file is included multiple times, the FileID will be the
+ /// first inclusion.
+ FileID translateFile(const FileEntry *SourceFile) const;
+
+ /// \brief Get the source location in \p FID for the given line:col.
+ /// Returns null location if \p FID is not a file SLocEntry.
+ SourceLocation translateLineCol(FileID FID,
+ unsigned Line, unsigned Col) const;
+
+ /// \brief If \p Loc points inside a function macro argument, the returned
+ /// location will be the macro location in which the argument was expanded.
+ /// If a macro argument is used multiple times, the expanded location will
+ /// be at the first expansion of the argument.
+ /// e.g.
+ /// MY_MACRO(foo);
+ /// ^
+ /// Passing a file location pointing at 'foo', will yield a macro location
+ /// where 'foo' was expanded into.
+ SourceLocation getMacroArgExpandedLocation(SourceLocation Loc) const;
+
+ /// \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;
+
+ /// \brief Determines the order of 2 source locations in the "source location
+ /// address space".
+ bool isBeforeInSLocAddrSpace(SourceLocation LHS, SourceLocation RHS) const {
+ return isBeforeInSLocAddrSpace(LHS, RHS.getOffset());
+ }
+
+ /// \brief Determines the order of a source location and a source location
+ /// offset in the "source location address space".
+ ///
+ /// Note that we always consider source locations loaded from
+ bool isBeforeInSLocAddrSpace(SourceLocation LHS, unsigned RHS) const {
+ unsigned LHSOffset = LHS.getOffset();
+ bool LHSLoaded = LHSOffset >= CurrentLoadedOffset;
+ bool RHSLoaded = RHS >= CurrentLoadedOffset;
+ if (LHSLoaded == RHSLoaded)
+ return LHSOffset < RHS;
+
+ return LHSLoaded;
+ }
+
+ // 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();
+ }
+
+ /// \brief Print statistics to stderr.
+ ///
+ void PrintStats() const;
+
+ void dump() const;
+
+ /// \brief Get the number of local SLocEntries we have.
+ unsigned local_sloc_entry_size() const { return LocalSLocEntryTable.size(); }
+
+ /// \brief Get a local SLocEntry. This is exposed for indexing.
+ const SrcMgr::SLocEntry &getLocalSLocEntry(unsigned Index,
+ bool *Invalid = nullptr) const {
+ assert(Index < LocalSLocEntryTable.size() && "Invalid index");
+ return LocalSLocEntryTable[Index];
+ }
+
+ /// \brief Get the number of loaded SLocEntries we have.
+ unsigned loaded_sloc_entry_size() const { return LoadedSLocEntryTable.size();}
+
+ /// \brief Get a loaded SLocEntry. This is exposed for indexing.
+ const SrcMgr::SLocEntry &getLoadedSLocEntry(unsigned Index,
+ bool *Invalid = nullptr) const {
+ assert(Index < LoadedSLocEntryTable.size() && "Invalid index");
+ if (SLocEntryLoaded[Index])
+ return LoadedSLocEntryTable[Index];
+ return loadSLocEntry(Index, Invalid);
+ }
+
+ const SrcMgr::SLocEntry &getSLocEntry(FileID FID,
+ bool *Invalid = nullptr) const {
+ if (FID.ID == 0 || FID.ID == -1) {
+ if (Invalid) *Invalid = true;
+ return LocalSLocEntryTable[0];
+ }
+ return getSLocEntryByID(FID.ID, Invalid);
+ }
+
+ unsigned getNextLocalOffset() const { return NextLocalOffset; }
+
+ void setExternalSLocEntrySource(ExternalSLocEntrySource *Source) {
+ assert(LoadedSLocEntryTable.empty() &&
+ "Invalidating existing loaded entries");
+ ExternalSLocEntries = Source;
+ }
+
+ /// \brief Allocate a number of loaded SLocEntries, which will be actually
+ /// loaded on demand from the external source.
+ ///
+ /// NumSLocEntries will be allocated, which occupy a total of TotalSize space
+ /// in the global source view. The lowest ID and the base offset of the
+ /// entries will be returned.
+ std::pair<int, unsigned>
+ AllocateLoadedSLocEntries(unsigned NumSLocEntries, unsigned TotalSize);
+
+ /// \brief Returns true if \p Loc came from a PCH/Module.
+ bool isLoadedSourceLocation(SourceLocation Loc) const {
+ return Loc.getOffset() >= CurrentLoadedOffset;
+ }
+
+ /// \brief Returns true if \p Loc did not come from a PCH/Module.
+ bool isLocalSourceLocation(SourceLocation Loc) const {
+ return Loc.getOffset() < NextLocalOffset;
+ }
+
+ /// \brief Returns true if \p FID came from a PCH/Module.
+ bool isLoadedFileID(FileID FID) const {
+ assert(FID.ID != -1 && "Using FileID sentinel value");
+ return FID.ID < 0;
+ }
+
+ /// \brief Returns true if \p FID did not come from a PCH/Module.
+ bool isLocalFileID(FileID FID) const {
+ return !isLoadedFileID(FID);
+ }
+
+ /// Gets the location of the immediate macro caller, one level up the stack
+ /// toward the initial macro typed into the source.
+ SourceLocation getImmediateMacroCallerLoc(SourceLocation Loc) const {
+ if (!Loc.isMacroID()) return Loc;
+
+ // When we have the location of (part of) an expanded parameter, its
+ // spelling location points to the argument as expanded in the macro call,
+ // and therefore is used to locate the macro caller.
+ if (isMacroArgExpansion(Loc))
+ return getImmediateSpellingLoc(Loc);
+
+ // Otherwise, the caller of the macro is located where this macro is
+ // expanded (while the spelling is part of the macro definition).
+ return getImmediateExpansionRange(Loc).first;
+ }
+
+private:
+ llvm::MemoryBuffer *getFakeBufferForRecovery() const;
+ const SrcMgr::ContentCache *getFakeContentCacheForRecovery() const;
+
+ const SrcMgr::SLocEntry &loadSLocEntry(unsigned Index, bool *Invalid) const;
+
+ /// \brief Get the entry with the given unwrapped FileID.
+ const SrcMgr::SLocEntry &getSLocEntryByID(int ID,
+ bool *Invalid = nullptr) const {
+ assert(ID != -1 && "Using FileID sentinel value");
+ if (ID < 0)
+ return getLoadedSLocEntryByID(ID, Invalid);
+ return getLocalSLocEntry(static_cast<unsigned>(ID), Invalid);
+ }
+
+ const SrcMgr::SLocEntry &
+ getLoadedSLocEntryByID(int ID, bool *Invalid = nullptr) const {
+ return getLoadedSLocEntry(static_cast<unsigned>(-ID - 2), Invalid);
+ }
+
+ /// Implements the common elements of storing an expansion info struct into
+ /// the SLocEntry table and producing a source location that refers to it.
+ SourceLocation createExpansionLocImpl(const SrcMgr::ExpansionInfo &Expansion,
+ unsigned TokLength,
+ int LoadedID = 0,
+ unsigned LoadedOffset = 0);
+
+ /// \brief 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 very last entry then it does.
+ if (FID.ID == -2)
+ return true;
+
+ // If it is the last local entry, then it does if the location is local.
+ if (FID.ID+1 == static_cast<int>(LocalSLocEntryTable.size()))
+ return SLocOffset < NextLocalOffset;
+
+ // Otherwise, the entry after it has to not include it. This works for both
+ // local and loaded entries.
+ return SLocOffset < getSLocEntryByID(FID.ID+1).getOffset();
+ }
+
+ /// \brief Returns the previous in-order FileID or an invalid FileID if there
+ /// is no previous one.
+ FileID getPreviousFileID(FileID FID) const;
+
+ /// \brief Returns the next in-order FileID or an invalid FileID if there is
+ /// no next one.
+ FileID getNextFileID(FileID FID) const;
+
+ /// \brief 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,
+ int LoadedID, unsigned LoadedOffset);
+
+ const SrcMgr::ContentCache *
+ getOrCreateContentCache(const FileEntry *SourceFile,
+ bool isSystemFile = false);
+
+ /// \brief Create a new ContentCache for the specified memory buffer.
+ const SrcMgr::ContentCache *
+ createMemBufferContentCache(std::unique_ptr<llvm::MemoryBuffer> Buf);
+
+ FileID getFileIDSlow(unsigned SLocOffset) const;
+ FileID getFileIDLocal(unsigned SLocOffset) const;
+ FileID getFileIDLoaded(unsigned SLocOffset) const;
+
+ SourceLocation getExpansionLocSlowCase(SourceLocation Loc) const;
+ SourceLocation getSpellingLocSlowCase(SourceLocation Loc) const;
+ SourceLocation getFileLocSlowCase(SourceLocation Loc) const;
+
+ std::pair<FileID, unsigned>
+ getDecomposedExpansionLocSlowCase(const SrcMgr::SLocEntry *E) const;
+ std::pair<FileID, unsigned>
+ getDecomposedSpellingLocSlowCase(const SrcMgr::SLocEntry *E,
+ unsigned Offset) const;
+ void computeMacroArgsCache(MacroArgsMap *&MacroArgsCache, FileID FID) const;
+ void associateFileChunkWithMacroArgExp(MacroArgsMap &MacroArgsCache,
+ FileID FID,
+ SourceLocation SpellLoc,
+ SourceLocation ExpansionLoc,
+ unsigned ExpansionLength) const;
+ friend class ASTReader;
+ friend class ASTWriter;
+};
+
+/// \brief Comparison function object.
+template<typename T>
+class BeforeThanCompare;
+
+/// \brief Compare two source locations.
+template<>
+class BeforeThanCompare<SourceLocation> {
+ SourceManager &SM;
+
+public:
+ explicit BeforeThanCompare(SourceManager &SM) : SM(SM) { }
+
+ bool operator()(SourceLocation LHS, SourceLocation RHS) const {
+ return SM.isBeforeInTranslationUnit(LHS, RHS);
+ }
+};
+
+/// \brief Compare two non-overlapping source ranges.
+template<>
+class BeforeThanCompare<SourceRange> {
+ SourceManager &SM;
+
+public:
+ explicit BeforeThanCompare(SourceManager &SM) : SM(SM) { }
+
+ bool operator()(SourceRange LHS, SourceRange RHS) const {
+ return SM.isBeforeInTranslationUnit(LHS.getBegin(), RHS.getBegin());
+ }
+};
+
+} // 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..27dea9f
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Basic/SourceManagerInternals.h
@@ -0,0 +1,128 @@
+//===--- 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.
+//
+//===----------------------------------------------------------------------===//
+///
+/// \file
+/// \brief Defines implementation details of the clang::SourceManager class.
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_BASIC_SOURCEMANAGERINTERNALS_H
+#define LLVM_CLANG_BASIC_SOURCEMANAGERINTERNALS_H
+
+#include "clang/Basic/SourceLocation.h"
+#include "clang/Basic/SourceManager.h"
+#include "llvm/ADT/StringMap.h"
+#include <map>
+
+namespace clang {
+
+//===----------------------------------------------------------------------===//
+// Line Table Implementation
+//===----------------------------------------------------------------------===//
+
+struct LineEntry {
+ /// \brief The offset in this file that the line entry occurs at.
+ unsigned FileOffset;
+
+ /// \brief The presumed line number of this line entry: \#line 4.
+ unsigned LineNo;
+
+ /// \brief The ID of the filename identified by this line entry:
+ /// \#line 4 "foo.c". This is -1 if not specified.
+ int FilenameID;
+
+ /// \brief Set the 0 if no flags, 1 if a system header,
+ SrcMgr::CharacteristicKind FileKind;
+
+ /// \brief 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;
+}
+
+/// \brief Used to hold and unique data used to represent \#line information.
+class LineTableInfo {
+ /// \brief Map 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;
+
+ /// \brief Map from FileIDs to a list of line entries (sorted by the offset
+ /// at which they occur in the file).
+ std::map<FileID, std::vector<LineEntry> > LineEntries;
+public:
+ void clear() {
+ FilenameIDs.clear();
+ FilenamesByID.clear();
+ LineEntries.clear();
+ }
+
+ unsigned getLineTableFilenameID(StringRef Str);
+ const char *getFilename(unsigned ID) const {
+ assert(ID < FilenamesByID.size() && "Invalid FilenameID");
+ return FilenamesByID[ID]->getKeyData();
+ }
+ unsigned getNumFilenames() const { return FilenamesByID.size(); }
+
+ void AddLineNote(FileID FID, unsigned Offset,
+ unsigned LineNo, int FilenameID);
+ void AddLineNote(FileID FID, unsigned Offset,
+ unsigned LineNo, int FilenameID,
+ unsigned EntryExit, SrcMgr::CharacteristicKind FileKind);
+
+
+ /// \brief Find the line entry nearest to FID that is before it.
+ ///
+ /// If there is no line entry before \p Offset in \p FID, returns null.
+ const LineEntry *FindNearestLineEntry(FileID FID, unsigned Offset);
+
+ // Low-level access
+ typedef std::map<FileID, 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(FileID 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..1d59d64
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Basic/Specifiers.h
@@ -0,0 +1,283 @@
+//===--- 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.
+//
+//===----------------------------------------------------------------------===//
+///
+/// \file
+/// \brief Defines various enumerations that describe declaration and
+/// type specifiers.
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_BASIC_SPECIFIERS_H
+#define LLVM_CLANG_BASIC_SPECIFIERS_H
+
+#include "llvm/ADT/StringRef.h"
+#include "llvm/Support/DataTypes.h"
+#include "llvm/Support/ErrorHandling.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++11 char16_t
+ TST_char32, // C++11 char32_t
+ TST_int,
+ TST_int128,
+ TST_half, // OpenCL half, ARM NEON __fp16
+ 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_interface, // C++ (Microsoft-specific) __interface type
+ TST_typename, // Typedef, C++ class-name or enum name, etc.
+ TST_typeofType,
+ TST_typeofExpr,
+ TST_decltype, // C++11 decltype
+ TST_underlyingType, // __underlying_type for C++11
+ TST_auto, // C++11 auto
+ TST_decltype_auto, // C++1y decltype(auto)
+ TST_auto_type, // __auto_type extension
+ TST_unknown_anytype, // __unknown_anytype extension
+ TST_atomic, // C11 _Atomic
+ TST_error // erroneous type
+ };
+
+ /// \brief 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;
+ };
+
+ /// \brief 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
+ };
+
+ /// \brief The categorization of expression values, currently following the
+ /// C++11 scheme.
+ enum ExprValueKind {
+ /// \brief An r-value expression (a pr-value in the C++11 taxonomy)
+ /// produces a temporary value.
+ VK_RValue,
+
+ /// \brief An l-value expression is a reference to an object with
+ /// independent storage.
+ VK_LValue,
+
+ /// \brief An x-value expression is a reference to an object with
+ /// independent storage but which can be "moved", i.e.
+ /// efficiently cannibalized for its resources.
+ VK_XValue
+ };
+
+ /// \brief 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,
+
+ /// An Objective-C array/dictionary subscripting which reads an
+ /// object or writes at the subscripted array/dictionary element via
+ /// Objective-C method calls.
+ OK_ObjCSubscript
+ };
+
+ /// \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++11 [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 Determine whether this template specialization kind refers
+ /// to an instantiation of an entity (as opposed to a non-template or
+ /// an explicit specialization).
+ inline bool isTemplateInstantiation(TemplateSpecializationKind Kind) {
+ return Kind != TSK_Undeclared && Kind != TSK_ExplicitSpecialization;
+ }
+
+ /// \brief True if this template specialization kind is an explicit
+ /// specialization, explicit instantiation declaration, or explicit
+ /// instantiation definition.
+ inline bool isTemplateExplicitInstantiationOrSpecialization(
+ TemplateSpecializationKind Kind) {
+ switch (Kind) {
+ case TSK_ExplicitSpecialization:
+ case TSK_ExplicitInstantiationDeclaration:
+ case TSK_ExplicitInstantiationDefinition:
+ return true;
+
+ case TSK_Undeclared:
+ case TSK_ImplicitInstantiation:
+ return false;
+ }
+ llvm_unreachable("bad template specialization kind");
+ }
+
+ /// \brief Thread storage-class-specifier.
+ enum ThreadStorageClassSpecifier {
+ TSCS_unspecified,
+ /// GNU __thread.
+ TSCS___thread,
+ /// C++11 thread_local. Implies 'static' at block scope, but not at
+ /// class scope.
+ TSCS_thread_local,
+ /// C11 _Thread_local. Must be combined with either 'static' or 'extern'
+ /// if used at block scope.
+ TSCS__Thread_local
+ };
+
+ /// \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
+ };
+
+ /// \brief Checks whether the given storage class is legal for functions.
+ inline bool isLegalForFunction(StorageClass SC) {
+ return SC <= SC_PrivateExtern;
+ }
+
+ /// \brief Checks whether the given storage class is legal for variables.
+ inline bool isLegalForVariable(StorageClass SC) {
+ return true;
+ }
+
+ /// \brief In-class initialization styles for non-static data members.
+ enum InClassInitStyle {
+ ICIS_NoInit, ///< No in-class initializer.
+ ICIS_CopyInit, ///< Copy initialization.
+ ICIS_ListInit ///< Direct list-initialization.
+ };
+
+ /// \brief CallingConv - Specifies the calling convention that a function uses.
+ enum CallingConv {
+ CC_C, // __attribute__((cdecl))
+ CC_X86StdCall, // __attribute__((stdcall))
+ CC_X86FastCall, // __attribute__((fastcall))
+ CC_X86ThisCall, // __attribute__((thiscall))
+ CC_X86VectorCall, // __attribute__((vectorcall))
+ CC_X86Pascal, // __attribute__((pascal))
+ CC_X86_64Win64, // __attribute__((ms_abi))
+ CC_X86_64SysV, // __attribute__((sysv_abi))
+ CC_AAPCS, // __attribute__((pcs("aapcs")))
+ CC_AAPCS_VFP, // __attribute__((pcs("aapcs-vfp")))
+ CC_IntelOclBicc, // __attribute__((intel_ocl_bicc))
+ CC_SpirFunction, // default for OpenCL functions on SPIR target
+ CC_SpirKernel // inferred for OpenCL kernels on SPIR target
+ };
+
+ /// \brief Checks whether the given calling convention supports variadic
+ /// calls. Unprototyped calls also use the variadic call rules.
+ inline bool supportsVariadicCall(CallingConv CC) {
+ switch (CC) {
+ case CC_X86StdCall:
+ case CC_X86FastCall:
+ case CC_X86ThisCall:
+ case CC_X86Pascal:
+ case CC_X86VectorCall:
+ case CC_SpirFunction:
+ case CC_SpirKernel:
+ return false;
+ default:
+ return true;
+ }
+ }
+
+ /// \brief The storage duration for an object (per C++ [basic.stc]).
+ enum StorageDuration {
+ SD_FullExpression, ///< Full-expression storage duration (for temporaries).
+ SD_Automatic, ///< Automatic storage duration (most local variables).
+ SD_Thread, ///< Thread storage duration.
+ SD_Static, ///< Static storage duration.
+ SD_Dynamic ///< Dynamic storage duration.
+ };
+
+ /// Describes the nullability of a particular type.
+ enum class NullabilityKind : uint8_t {
+ /// Values of this type can never be null.
+ NonNull = 0,
+ /// Values of this type can be null.
+ Nullable,
+ /// Whether values of this type can be null is (explicitly)
+ /// unspecified. This captures a (fairly rare) case where we
+ /// can't conclude anything about the nullability of the type even
+ /// though it has been considered.
+ Unspecified
+ };
+
+ /// Retrieve the spelling of the given nullability kind.
+ llvm::StringRef getNullabilitySpelling(NullabilityKind kind,
+ bool isContextSensitive = false);
+} // 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..36519ea
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Basic/StmtNodes.td
@@ -0,0 +1,224 @@
+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 AttributedStmt : 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>;
+def CapturedStmt : Stmt;
+
+// Asm statements
+def AsmStmt : Stmt<1>;
+def GCCAsmStmt : DStmt<AsmStmt>;
+def MSAsmStmt : DStmt<AsmStmt>;
+
+// Obj-C statements
+def ObjCAtTryStmt : Stmt;
+def ObjCAtCatchStmt : Stmt;
+def ObjCAtFinallyStmt : Stmt;
+def ObjCAtThrowStmt : Stmt;
+def ObjCAtSynchronizedStmt : Stmt;
+def ObjCForCollectionStmt : Stmt;
+def ObjCAutoreleasePoolStmt : Stmt;
+
+// C++ statments
+def CXXCatchStmt : Stmt;
+def CXXTryStmt : Stmt;
+def CXXForRangeStmt : Stmt;
+
+// C++ Coroutines TS statements
+def CoroutineBodyStmt : Stmt;
+def CoreturnStmt : 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 UnaryExprOrTypeTraitExpr : DStmt<Expr>;
+def ArraySubscriptExpr : DStmt<Expr>;
+def OMPArraySectionExpr : 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 DesignatedInitUpdateExpr : DStmt<Expr>;
+def ImplicitValueInitExpr : DStmt<Expr>;
+def NoInitExpr : DStmt<Expr>;
+def ParenListExpr : DStmt<Expr>;
+def VAArgExpr : DStmt<Expr>;
+def GenericSelectionExpr : DStmt<Expr>;
+def PseudoObjectExpr : DStmt<Expr>;
+
+// Atomic expressions
+def AtomicExpr : 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 UserDefinedLiteral : DStmt<CallExpr>;
+def CXXBoolLiteralExpr : DStmt<Expr>;
+def CXXNullPtrLiteralExpr : DStmt<Expr>;
+def CXXThisExpr : DStmt<Expr>;
+def CXXThrowExpr : DStmt<Expr>;
+def CXXDefaultArgExpr : DStmt<Expr>;
+def CXXDefaultInitExpr : DStmt<Expr>;
+def CXXScalarValueInitExpr : DStmt<Expr>;
+def CXXStdInitializerListExpr : DStmt<Expr>;
+def CXXNewExpr : DStmt<Expr>;
+def CXXDeleteExpr : DStmt<Expr>;
+def CXXPseudoDestructorExpr : DStmt<Expr>;
+def TypeTraitExpr : DStmt<Expr>;
+def ArrayTypeTraitExpr : DStmt<Expr>;
+def ExpressionTraitExpr : 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 SubstNonTypeTemplateParmExpr : DStmt<Expr>;
+def SubstNonTypeTemplateParmPackExpr : DStmt<Expr>;
+def FunctionParmPackExpr : DStmt<Expr>;
+def MaterializeTemporaryExpr : DStmt<Expr>;
+def LambdaExpr : DStmt<Expr>;
+def CXXFoldExpr : DStmt<Expr>;
+
+// C++ Coroutines TS expressions
+def CoroutineSuspendExpr : DStmt<Expr, 1>;
+def CoawaitExpr : DStmt<CoroutineSuspendExpr>;
+def CoyieldExpr : DStmt<CoroutineSuspendExpr>;
+
+// Obj-C Expressions.
+def ObjCStringLiteral : DStmt<Expr>;
+def ObjCBoxedExpr : DStmt<Expr>;
+def ObjCArrayLiteral : DStmt<Expr>;
+def ObjCDictionaryLiteral : 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>;
+def ObjCIndirectCopyRestoreExpr : DStmt<Expr>;
+def ObjCBoolLiteralExpr : DStmt<Expr>;
+def ObjCSubscriptRefExpr : DStmt<Expr>;
+
+// Obj-C ARC Expressions.
+def ObjCBridgedCastExpr : DStmt<ExplicitCastExpr>;
+
+// CUDA Expressions.
+def CUDAKernelCallExpr : DStmt<CallExpr>;
+
+// Clang Extensions.
+def ShuffleVectorExpr : DStmt<Expr>;
+def ConvertVectorExpr : DStmt<Expr>;
+def BlockExpr : DStmt<Expr>;
+def OpaqueValueExpr : DStmt<Expr>;
+def TypoExpr : DStmt<Expr>;
+
+// Microsoft Extensions.
+def MSPropertyRefExpr : DStmt<Expr>;
+def MSPropertySubscriptExpr : DStmt<Expr>;
+def CXXUuidofExpr : DStmt<Expr>;
+def SEHTryStmt : Stmt;
+def SEHExceptStmt : Stmt;
+def SEHFinallyStmt : Stmt;
+def SEHLeaveStmt : Stmt;
+def MSDependentExistsStmt : Stmt;
+
+// OpenCL Extensions.
+def AsTypeExpr : DStmt<Expr>;
+
+// OpenMP Directives.
+def OMPExecutableDirective : Stmt<1>;
+def OMPLoopDirective : DStmt<OMPExecutableDirective, 1>;
+def OMPParallelDirective : DStmt<OMPExecutableDirective>;
+def OMPSimdDirective : DStmt<OMPLoopDirective>;
+def OMPForDirective : DStmt<OMPLoopDirective>;
+def OMPForSimdDirective : DStmt<OMPLoopDirective>;
+def OMPSectionsDirective : DStmt<OMPExecutableDirective>;
+def OMPSectionDirective : DStmt<OMPExecutableDirective>;
+def OMPSingleDirective : DStmt<OMPExecutableDirective>;
+def OMPMasterDirective : DStmt<OMPExecutableDirective>;
+def OMPCriticalDirective : DStmt<OMPExecutableDirective>;
+def OMPParallelForDirective : DStmt<OMPLoopDirective>;
+def OMPParallelForSimdDirective : DStmt<OMPLoopDirective>;
+def OMPParallelSectionsDirective : DStmt<OMPExecutableDirective>;
+def OMPTaskDirective : DStmt<OMPExecutableDirective>;
+def OMPTaskyieldDirective : DStmt<OMPExecutableDirective>;
+def OMPBarrierDirective : DStmt<OMPExecutableDirective>;
+def OMPTaskwaitDirective : DStmt<OMPExecutableDirective>;
+def OMPTaskgroupDirective : DStmt<OMPExecutableDirective>;
+def OMPFlushDirective : DStmt<OMPExecutableDirective>;
+def OMPOrderedDirective : DStmt<OMPExecutableDirective>;
+def OMPAtomicDirective : DStmt<OMPExecutableDirective>;
+def OMPTargetDirective : DStmt<OMPExecutableDirective>;
+def OMPTargetDataDirective : DStmt<OMPExecutableDirective>;
+def OMPTeamsDirective : DStmt<OMPExecutableDirective>;
+def OMPCancellationPointDirective : DStmt<OMPExecutableDirective>;
+def OMPCancelDirective : DStmt<OMPExecutableDirective>;
+def OMPTaskLoopDirective : DStmt<OMPLoopDirective>;
+def OMPTaskLoopSimdDirective : DStmt<OMPLoopDirective>;
+def OMPDistributeDirective : DStmt<OMPLoopDirective>;
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..623c0b6
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Basic/TargetBuiltins.h
@@ -0,0 +1,201 @@
+//===--- TargetBuiltins.h - Target specific builtin IDs ---------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+///
+/// \file
+/// \brief Enumerates target-specific builtins in their own namespaces within
+/// namespace ::clang.
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_BASIC_TARGETBUILTINS_H
+#define LLVM_CLANG_BASIC_TARGETBUILTINS_H
+
+#include <stdint.h>
+#include "clang/Basic/Builtins.h"
+#undef PPC
+
+namespace clang {
+
+ namespace NEON {
+ enum {
+ LastTIBuiltin = clang::Builtin::FirstTSBuiltin - 1,
+#define BUILTIN(ID, TYPE, ATTRS) BI##ID,
+#include "clang/Basic/BuiltinsNEON.def"
+ FirstTSBuiltin
+ };
+ }
+
+ /// \brief ARM builtins
+ namespace ARM {
+ enum {
+ LastTIBuiltin = clang::Builtin::FirstTSBuiltin-1,
+ LastNEONBuiltin = NEON::FirstTSBuiltin - 1,
+#define BUILTIN(ID, TYPE, ATTRS) BI##ID,
+#include "clang/Basic/BuiltinsARM.def"
+ LastTSBuiltin
+ };
+ }
+
+ /// \brief AArch64 builtins
+ namespace AArch64 {
+ enum {
+ LastTIBuiltin = clang::Builtin::FirstTSBuiltin - 1,
+ LastNEONBuiltin = NEON::FirstTSBuiltin - 1,
+ #define BUILTIN(ID, TYPE, ATTRS) BI##ID,
+ #include "clang/Basic/BuiltinsAArch64.def"
+ LastTSBuiltin
+ };
+ }
+
+ /// \brief PPC builtins
+ namespace PPC {
+ enum {
+ LastTIBuiltin = clang::Builtin::FirstTSBuiltin-1,
+#define BUILTIN(ID, TYPE, ATTRS) BI##ID,
+#include "clang/Basic/BuiltinsPPC.def"
+ LastTSBuiltin
+ };
+ }
+
+ /// \brief NVPTX builtins
+ namespace NVPTX {
+ enum {
+ LastTIBuiltin = clang::Builtin::FirstTSBuiltin-1,
+#define BUILTIN(ID, TYPE, ATTRS) BI##ID,
+#include "clang/Basic/BuiltinsNVPTX.def"
+ LastTSBuiltin
+ };
+ }
+
+ /// \brief AMDGPU builtins
+ namespace AMDGPU {
+ enum {
+ LastTIBuiltin = clang::Builtin::FirstTSBuiltin - 1,
+ #define BUILTIN(ID, TYPE, ATTRS) BI##ID,
+ #include "clang/Basic/BuiltinsAMDGPU.def"
+ LastTSBuiltin
+ };
+ }
+
+ /// \brief X86 builtins
+ namespace X86 {
+ enum {
+ LastTIBuiltin = clang::Builtin::FirstTSBuiltin-1,
+#define BUILTIN(ID, TYPE, ATTRS) BI##ID,
+#include "clang/Basic/BuiltinsX86.def"
+ LastTSBuiltin
+ };
+ }
+
+ /// \brief Flags to identify the types for overloaded Neon builtins.
+ ///
+ /// These must be kept in sync with the flags in utils/TableGen/NeonEmitter.h.
+ class NeonTypeFlags {
+ enum {
+ EltTypeMask = 0xf,
+ UnsignedFlag = 0x10,
+ QuadFlag = 0x20
+ };
+ uint32_t Flags;
+
+ public:
+ enum EltType {
+ Int8,
+ Int16,
+ Int32,
+ Int64,
+ Poly8,
+ Poly16,
+ Poly64,
+ Poly128,
+ Float16,
+ Float32,
+ Float64
+ };
+
+ NeonTypeFlags(unsigned F) : Flags(F) {}
+ NeonTypeFlags(EltType ET, bool IsUnsigned, bool IsQuad) : Flags(ET) {
+ if (IsUnsigned)
+ Flags |= UnsignedFlag;
+ if (IsQuad)
+ Flags |= QuadFlag;
+ }
+
+ EltType getEltType() const { return (EltType)(Flags & EltTypeMask); }
+ bool isPoly() const {
+ EltType ET = getEltType();
+ return ET == Poly8 || ET == Poly16;
+ }
+ bool isUnsigned() const { return (Flags & UnsignedFlag) != 0; }
+ bool isQuad() const { return (Flags & QuadFlag) != 0; }
+ };
+
+ /// \brief Hexagon builtins
+ namespace Hexagon {
+ enum {
+ LastTIBuiltin = clang::Builtin::FirstTSBuiltin-1,
+#define BUILTIN(ID, TYPE, ATTRS) BI##ID,
+#include "clang/Basic/BuiltinsHexagon.def"
+ LastTSBuiltin
+ };
+ }
+
+ /// \brief MIPS builtins
+ namespace Mips {
+ enum {
+ LastTIBuiltin = clang::Builtin::FirstTSBuiltin-1,
+#define BUILTIN(ID, TYPE, ATTRS) BI##ID,
+#include "clang/Basic/BuiltinsMips.def"
+ LastTSBuiltin
+ };
+ }
+
+ /// \brief XCore builtins
+ namespace XCore {
+ enum {
+ LastTIBuiltin = clang::Builtin::FirstTSBuiltin-1,
+#define BUILTIN(ID, TYPE, ATTRS) BI##ID,
+#include "clang/Basic/BuiltinsXCore.def"
+ LastTSBuiltin
+ };
+ }
+
+ /// \brief Le64 builtins
+ namespace Le64 {
+ enum {
+ LastTIBuiltin = clang::Builtin::FirstTSBuiltin - 1,
+ #define BUILTIN(ID, TYPE, ATTRS) BI##ID,
+ #include "clang/Basic/BuiltinsLe64.def"
+ LastTSBuiltin
+ };
+ }
+
+ /// \brief SystemZ builtins
+ namespace SystemZ {
+ enum {
+ LastTIBuiltin = clang::Builtin::FirstTSBuiltin-1,
+#define BUILTIN(ID, TYPE, ATTRS) BI##ID,
+#include "clang/Basic/BuiltinsSystemZ.def"
+ LastTSBuiltin
+ };
+ }
+
+ /// \brief WebAssembly builtins
+ namespace WebAssembly {
+ enum {
+ LastTIBuiltin = clang::Builtin::FirstTSBuiltin-1,
+#define BUILTIN(ID, TYPE, ATTRS) BI##ID,
+#include "clang/Basic/BuiltinsWebAssembly.def"
+ LastTSBuiltin
+ };
+ }
+
+} // end namespace clang.
+
+#endif
diff --git a/contrib/llvm/tools/clang/include/clang/Basic/TargetCXXABI.h b/contrib/llvm/tools/clang/include/clang/Basic/TargetCXXABI.h
new file mode 100644
index 0000000..67247ea
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Basic/TargetCXXABI.h
@@ -0,0 +1,354 @@
+//===--- TargetCXXABI.h - C++ ABI Target Configuration ----------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+///
+/// \file
+/// \brief Defines the TargetCXXABI class, which abstracts details of the
+/// C++ ABI that we're targeting.
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_BASIC_TARGETCXXABI_H
+#define LLVM_CLANG_BASIC_TARGETCXXABI_H
+
+#include "llvm/ADT/Triple.h"
+#include "llvm/Support/ErrorHandling.h"
+
+namespace clang {
+
+/// \brief The basic abstraction for the target C++ ABI.
+class TargetCXXABI {
+public:
+ /// \brief The basic C++ ABI kind.
+ enum Kind {
+ /// The generic Itanium ABI is the standard ABI of most open-source
+ /// and Unix-like platforms. It is the primary ABI targeted by
+ /// many compilers, including Clang and GCC.
+ ///
+ /// It is documented here:
+ /// http://www.codesourcery.com/public/cxx-abi/
+ GenericItanium,
+
+ /// The generic ARM ABI is a modified version of the Itanium ABI
+ /// proposed by ARM for use on ARM-based platforms.
+ ///
+ /// These changes include:
+ /// - the representation of member function pointers is adjusted
+ /// to not conflict with the 'thumb' bit of ARM function pointers;
+ /// - constructors and destructors return 'this';
+ /// - guard variables are smaller;
+ /// - inline functions are never key functions;
+ /// - array cookies have a slightly different layout;
+ /// - additional convenience functions are specified;
+ /// - and more!
+ ///
+ /// It is documented here:
+ /// http://infocenter.arm.com
+ /// /help/topic/com.arm.doc.ihi0041c/IHI0041C_cppabi.pdf
+ GenericARM,
+
+ /// The iOS ABI is a partial implementation of the ARM ABI.
+ /// Several of the features of the ARM ABI were not fully implemented
+ /// in the compilers that iOS was launched with.
+ ///
+ /// Essentially, the iOS ABI includes the ARM changes to:
+ /// - member function pointers,
+ /// - guard variables,
+ /// - array cookies, and
+ /// - constructor/destructor signatures.
+ iOS,
+
+ /// The iOS 64-bit ABI is follows ARM's published 64-bit ABI more
+ /// closely, but we don't guarantee to follow it perfectly.
+ ///
+ /// It is documented here:
+ /// http://infocenter.arm.com
+ /// /help/topic/com.arm.doc.ihi0059a/IHI0059A_cppabi64.pdf
+ iOS64,
+
+ /// WatchOS is a modernisation of the iOS ABI, which roughly means it's
+ /// the iOS64 ABI ported to 32-bits. The primary difference from iOS64 is
+ /// that RTTI objects must still be unique at the moment.
+ WatchOS,
+
+ /// The generic AArch64 ABI is also a modified version of the Itanium ABI,
+ /// but it has fewer divergences than the 32-bit ARM ABI.
+ ///
+ /// The relevant changes from the generic ABI in this case are:
+ /// - representation of member function pointers adjusted as in ARM.
+ /// - guard variables are smaller.
+ GenericAArch64,
+
+ /// The generic Mips ABI is a modified version of the Itanium ABI.
+ ///
+ /// At the moment, only change from the generic ABI in this case is:
+ /// - representation of member function pointers adjusted as in ARM.
+ GenericMIPS,
+
+ /// The WebAssembly ABI is a modified version of the Itanium ABI.
+ ///
+ /// The changes from the Itanium ABI are:
+ /// - representation of member function pointers is adjusted, as in ARM;
+ /// - member functions are not specially aligned;
+ /// - constructors and destructors return 'this', as in ARM;
+ /// - guard variables are 32-bit on wasm32, as in ARM;
+ /// - unused bits of guard variables are reserved, as in ARM;
+ /// - inline functions are never key functions, as in ARM;
+ /// - C++11 POD rules are used for tail padding, as in iOS64.
+ ///
+ /// TODO: At present the WebAssembly ABI is not considered stable, so none
+ /// of these details is necessarily final yet.
+ WebAssembly,
+
+ /// The Microsoft ABI is the ABI used by Microsoft Visual Studio (and
+ /// compatible compilers).
+ ///
+ /// FIXME: should this be split into Win32 and Win64 variants?
+ ///
+ /// Only scattered and incomplete official documentation exists.
+ Microsoft
+ };
+
+private:
+ // Right now, this class is passed around as a cheap value type.
+ // If you add more members, especially non-POD members, please
+ // audit the users to pass it by reference instead.
+ Kind TheKind;
+
+public:
+ /// A bogus initialization of the platform ABI.
+ TargetCXXABI() : TheKind(GenericItanium) {}
+
+ TargetCXXABI(Kind kind) : TheKind(kind) {}
+
+ void set(Kind kind) {
+ TheKind = kind;
+ }
+
+ Kind getKind() const { return TheKind; }
+
+ /// \brief Does this ABI generally fall into the Itanium family of ABIs?
+ bool isItaniumFamily() const {
+ switch (getKind()) {
+ case GenericAArch64:
+ case GenericItanium:
+ case GenericARM:
+ case iOS:
+ case iOS64:
+ case WatchOS:
+ case GenericMIPS:
+ case WebAssembly:
+ return true;
+
+ case Microsoft:
+ return false;
+ }
+ llvm_unreachable("bad ABI kind");
+ }
+
+ /// \brief Is this ABI an MSVC-compatible ABI?
+ bool isMicrosoft() const {
+ switch (getKind()) {
+ case GenericAArch64:
+ case GenericItanium:
+ case GenericARM:
+ case iOS:
+ case iOS64:
+ case WatchOS:
+ case GenericMIPS:
+ case WebAssembly:
+ return false;
+
+ case Microsoft:
+ return true;
+ }
+ llvm_unreachable("bad ABI kind");
+ }
+
+ /// \brief Are member functions differently aligned?
+ ///
+ /// Many Itanium-style C++ ABIs require member functions to be aligned, so
+ /// that a pointer to such a function is guaranteed to have a zero in the
+ /// least significant bit, so that pointers to member functions can use that
+ /// bit to distinguish between virtual and non-virtual functions. However,
+ /// some Itanium-style C++ ABIs differentiate between virtual and non-virtual
+ /// functions via other means, and consequently don't require that member
+ /// functions be aligned.
+ bool areMemberFunctionsAligned() const {
+ switch (getKind()) {
+ case WebAssembly:
+ // WebAssembly doesn't require any special alignment for member functions.
+ return false;
+ case GenericARM:
+ case GenericAArch64:
+ case GenericMIPS:
+ // TODO: ARM-style pointers to member functions put the discriminator in
+ // the this adjustment, so they don't require functions to have any
+ // special alignment and could therefore also return false.
+ case GenericItanium:
+ case iOS:
+ case iOS64:
+ case WatchOS:
+ case Microsoft:
+ return true;
+ }
+ llvm_unreachable("bad ABI kind");
+ }
+
+ /// \brief Is the default C++ member function calling convention
+ /// the same as the default calling convention?
+ bool isMemberFunctionCCDefault() const {
+ // Right now, this is always false for Microsoft.
+ return !isMicrosoft();
+ }
+
+ /// Are arguments to a call destroyed left to right in the callee?
+ /// This is a fundamental language change, since it implies that objects
+ /// passed by value do *not* live to the end of the full expression.
+ /// Temporaries passed to a function taking a const reference live to the end
+ /// of the full expression as usual. Both the caller and the callee must
+ /// have access to the destructor, while only the caller needs the
+ /// destructor if this is false.
+ bool areArgsDestroyedLeftToRightInCallee() const {
+ return isMicrosoft();
+ }
+
+ /// \brief Does this ABI have different entrypoints for complete-object
+ /// and base-subobject constructors?
+ bool hasConstructorVariants() const {
+ return isItaniumFamily();
+ }
+
+ /// \brief Does this ABI allow virtual bases to be primary base classes?
+ bool hasPrimaryVBases() const {
+ return isItaniumFamily();
+ }
+
+ /// \brief Does this ABI use key functions? If so, class data such as the
+ /// vtable is emitted with strong linkage by the TU containing the key
+ /// function.
+ bool hasKeyFunctions() const {
+ return isItaniumFamily();
+ }
+
+ /// \brief Can an out-of-line inline function serve as a key function?
+ ///
+ /// This flag is only useful in ABIs where type data (for example,
+ /// v-tables and type_info objects) are emitted only after processing
+ /// the definition of a special "key" virtual function. (This is safe
+ /// because the ODR requires that every virtual function be defined
+ /// somewhere in a program.) This usually permits such data to be
+ /// emitted in only a single object file, as opposed to redundantly
+ /// in every object file that requires it.
+ ///
+ /// One simple and common definition of "key function" is the first
+ /// virtual function in the class definition which is not defined there.
+ /// This rule works very well when that function has a non-inline
+ /// definition in some non-header file. Unfortunately, when that
+ /// function is defined inline, this rule requires the type data
+ /// to be emitted weakly, as if there were no key function.
+ ///
+ /// The ARM ABI observes that the ODR provides an additional guarantee:
+ /// a virtual function is always ODR-used, so if it is defined inline,
+ /// that definition must appear in every translation unit that defines
+ /// the class. Therefore, there is no reason to allow such functions
+ /// to serve as key functions.
+ ///
+ /// Because this changes the rules for emitting type data,
+ /// it can cause type data to be emitted with both weak and strong
+ /// linkage, which is not allowed on all platforms. Therefore,
+ /// exploiting this observation requires an ABI break and cannot be
+ /// done on a generic Itanium platform.
+ bool canKeyFunctionBeInline() const {
+ switch (getKind()) {
+ case GenericARM:
+ case iOS64:
+ case WebAssembly:
+ case WatchOS:
+ return false;
+
+ case GenericAArch64:
+ case GenericItanium:
+ case iOS: // old iOS compilers did not follow this rule
+ case Microsoft:
+ case GenericMIPS:
+ return true;
+ }
+ llvm_unreachable("bad ABI kind");
+ }
+
+ /// When is record layout allowed to allocate objects in the tail
+ /// padding of a base class?
+ ///
+ /// This decision cannot be changed without breaking platform ABI
+ /// compatibility, and yet it is tied to language guarantees which
+ /// the committee has so far seen fit to strengthen no less than
+ /// three separate times:
+ /// - originally, there were no restrictions at all;
+ /// - C++98 declared that objects could not be allocated in the
+ /// tail padding of a POD type;
+ /// - C++03 extended the definition of POD to include classes
+ /// containing member pointers; and
+ /// - C++11 greatly broadened the definition of POD to include
+ /// all trivial standard-layout classes.
+ /// Each of these changes technically took several existing
+ /// platforms and made them permanently non-conformant.
+ enum TailPaddingUseRules {
+ /// The tail-padding of a base class is always theoretically
+ /// available, even if it's POD. This is not strictly conforming
+ /// in any language mode.
+ AlwaysUseTailPadding,
+
+ /// Only allocate objects in the tail padding of a base class if
+ /// the base class is not POD according to the rules of C++ TR1.
+ /// This is non-strictly conforming in C++11 mode.
+ UseTailPaddingUnlessPOD03,
+
+ /// Only allocate objects in the tail padding of a base class if
+ /// the base class is not POD according to the rules of C++11.
+ UseTailPaddingUnlessPOD11
+ };
+ TailPaddingUseRules getTailPaddingUseRules() const {
+ switch (getKind()) {
+ // To preserve binary compatibility, the generic Itanium ABI has
+ // permanently locked the definition of POD to the rules of C++ TR1,
+ // and that trickles down to derived ABIs.
+ case GenericItanium:
+ case GenericAArch64:
+ case GenericARM:
+ case iOS:
+ case GenericMIPS:
+ return UseTailPaddingUnlessPOD03;
+
+ // iOS on ARM64 and WebAssembly use the C++11 POD rules. They do not honor
+ // the Itanium exception about classes with over-large bitfields.
+ case iOS64:
+ case WebAssembly:
+ case WatchOS:
+ return UseTailPaddingUnlessPOD11;
+
+ // MSVC always allocates fields in the tail-padding of a base class
+ // subobject, even if they're POD.
+ case Microsoft:
+ return AlwaysUseTailPadding;
+ }
+ llvm_unreachable("bad ABI kind");
+ }
+
+ friend bool operator==(const TargetCXXABI &left, const TargetCXXABI &right) {
+ return left.getKind() == right.getKind();
+ }
+
+ friend bool operator!=(const TargetCXXABI &left, const TargetCXXABI &right) {
+ return !(left == right);
+ }
+};
+
+} // 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..f1d8338
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Basic/TargetInfo.h
@@ -0,0 +1,953 @@
+//===--- 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.
+//
+//===----------------------------------------------------------------------===//
+///
+/// \file
+/// \brief Defines the clang::TargetInfo interface.
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_BASIC_TARGETINFO_H
+#define LLVM_CLANG_BASIC_TARGETINFO_H
+
+#include "clang/Basic/AddressSpaces.h"
+#include "clang/Basic/LLVM.h"
+#include "clang/Basic/Specifiers.h"
+#include "clang/Basic/TargetCXXABI.h"
+#include "clang/Basic/TargetOptions.h"
+#include "clang/Basic/VersionTuple.h"
+#include "llvm/ADT/IntrusiveRefCntPtr.h"
+#include "llvm/ADT/APInt.h"
+#include "llvm/ADT/SmallSet.h"
+#include "llvm/ADT/StringMap.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/ADT/StringSwitch.h"
+#include "llvm/ADT/Triple.h"
+#include "llvm/Support/DataTypes.h"
+#include <cassert>
+#include <string>
+#include <vector>
+
+namespace llvm {
+struct fltSemantics;
+}
+
+namespace clang {
+class DiagnosticsEngine;
+class LangOptions;
+class MacroBuilder;
+class SourceLocation;
+class SourceManager;
+
+namespace Builtin { struct Info; }
+
+/// \brief Exposes information about the current target.
+///
+class TargetInfo : public RefCountedBase<TargetInfo> {
+ std::shared_ptr<TargetOptions> TargetOpts;
+ llvm::Triple Triple;
+protected:
+ // Target values set by the ctor of the actual target implementation. Default
+ // values are specified by the TargetInfo constructor.
+ bool BigEndian;
+ bool TLSSupported;
+ bool NoAsmVariants; // True if {|} are normal characters.
+ unsigned char PointerWidth, PointerAlign;
+ unsigned char BoolWidth, BoolAlign;
+ unsigned char IntWidth, IntAlign;
+ unsigned char HalfWidth, HalfAlign;
+ unsigned char FloatWidth, FloatAlign;
+ unsigned char DoubleWidth, DoubleAlign;
+ unsigned char LongDoubleWidth, LongDoubleAlign;
+ unsigned char LargeArrayMinWidth, LargeArrayAlign;
+ unsigned char LongWidth, LongAlign;
+ unsigned char LongLongWidth, LongLongAlign;
+ unsigned char SuitableAlign;
+ unsigned char DefaultAlignForAttributeAligned;
+ unsigned char MinGlobalAlign;
+ unsigned char MaxAtomicPromoteWidth, MaxAtomicInlineWidth;
+ unsigned short MaxVectorAlign;
+ unsigned short MaxTLSAlign;
+ unsigned short SimdDefaultAlign;
+ const char *DataLayoutString;
+ const char *UserLabelPrefix;
+ const char *MCountName;
+ const llvm::fltSemantics *HalfFormat, *FloatFormat, *DoubleFormat,
+ *LongDoubleFormat;
+ unsigned char RegParmMax, SSERegParmMax;
+ TargetCXXABI TheCXXABI;
+ const LangAS::Map *AddrSpaceMap;
+
+ mutable StringRef PlatformName;
+ mutable VersionTuple PlatformMinVersion;
+
+ unsigned HasAlignMac68kSupport : 1;
+ unsigned RealTypeUsesObjCFPRet : 3;
+ unsigned ComplexLongDoubleUsesFP2Ret : 1;
+
+ unsigned HasBuiltinMSVaList : 1;
+
+ // TargetInfo Constructor. Default initializes all fields.
+ TargetInfo(const llvm::Triple &T);
+
+public:
+ /// \brief 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(DiagnosticsEngine &Diags,
+ const std::shared_ptr<TargetOptions> &Opts);
+
+ virtual ~TargetInfo();
+
+ /// \brief Retrieve the target options.
+ TargetOptions &getTargetOpts() const {
+ assert(TargetOpts && "Missing target options");
+ return *TargetOpts;
+ }
+
+ ///===---- Target Data Type Query Methods -------------------------------===//
+ enum IntType {
+ NoInt = 0,
+ SignedChar,
+ UnsignedChar,
+ SignedShort,
+ UnsignedShort,
+ SignedInt,
+ UnsignedInt,
+ SignedLong,
+ UnsignedLong,
+ SignedLongLong,
+ UnsignedLongLong
+ };
+
+ enum RealType {
+ NoFloat = 255,
+ Float = 0,
+ Double,
+ LongDouble
+ };
+
+ /// \brief The different kinds of __builtin_va_list types defined by
+ /// the target implementation.
+ enum BuiltinVaListKind {
+ /// typedef char* __builtin_va_list;
+ CharPtrBuiltinVaList = 0,
+
+ /// typedef void* __builtin_va_list;
+ VoidPtrBuiltinVaList,
+
+ /// __builtin_va_list as defind by the AArch64 ABI
+ /// http://infocenter.arm.com/help/topic/com.arm.doc.ihi0055a/IHI0055A_aapcs64.pdf
+ AArch64ABIBuiltinVaList,
+
+ /// __builtin_va_list as defined by the PNaCl ABI:
+ /// http://www.chromium.org/nativeclient/pnacl/bitcode-abi#TOC-Machine-Types
+ PNaClABIBuiltinVaList,
+
+ /// __builtin_va_list as defined by the Power ABI:
+ /// https://www.power.org
+ /// /resources/downloads/Power-Arch-32-bit-ABI-supp-1.0-Embedded.pdf
+ PowerABIBuiltinVaList,
+
+ /// __builtin_va_list as defined by the x86-64 ABI:
+ /// http://www.x86-64.org/documentation/abi.pdf
+ X86_64ABIBuiltinVaList,
+
+ /// __builtin_va_list as defined by ARM AAPCS ABI
+ /// http://infocenter.arm.com
+ // /help/topic/com.arm.doc.ihi0042d/IHI0042D_aapcs.pdf
+ AAPCSABIBuiltinVaList,
+
+ // typedef struct __va_list_tag
+ // {
+ // long __gpr;
+ // long __fpr;
+ // void *__overflow_arg_area;
+ // void *__reg_save_area;
+ // } va_list[1];
+ SystemZBuiltinVaList
+ };
+
+protected:
+ IntType SizeType, IntMaxType, PtrDiffType, IntPtrType, WCharType,
+ WIntType, Char16Type, Char32Type, Int64Type, SigAtomicType,
+ ProcessIDType;
+
+ /// \brief Whether Objective-C's built-in boolean type should be signed char.
+ ///
+ /// Otherwise, when this flag is not set, the normal built-in boolean type is
+ /// used.
+ unsigned UseSignedCharForObjCBool : 1;
+
+ /// 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;
+
+ /// \brief Whether zero length bitfields (e.g., int : 0;) force alignment of
+ /// the next bitfield.
+ ///
+ /// If the alignment of the zero length bitfield is greater than the member
+ /// that follows it, `bar', `bar' will be aligned as the type of the
+ /// zero-length bitfield.
+ unsigned UseZeroLengthBitfieldAlignment : 1;
+
+ /// If non-zero, specifies a fixed alignment value for bitfields that follow
+ /// zero length bitfield, regardless of the zero length bitfield type.
+ unsigned ZeroLengthBitfieldBoundary;
+
+ /// \brief Specify if mangling based on address space map should be used or
+ /// not for language specific address spaces
+ bool UseAddrSpaceMapMangling;
+
+public:
+ IntType getSizeType() const { return SizeType; }
+ IntType getIntMaxType() const { return IntMaxType; }
+ IntType getUIntMaxType() const {
+ return getCorrespondingUnsignedType(IntMaxType);
+ }
+ IntType getPtrDiffType(unsigned AddrSpace) const {
+ return AddrSpace == 0 ? PtrDiffType : getPtrDiffTypeV(AddrSpace);
+ }
+ IntType getIntPtrType() const { return IntPtrType; }
+ IntType getUIntPtrType() const {
+ return getCorrespondingUnsignedType(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 getUInt64Type() const {
+ return getCorrespondingUnsignedType(Int64Type);
+ }
+ IntType getSigAtomicType() const { return SigAtomicType; }
+ IntType getProcessIDType() const { return ProcessIDType; }
+
+ static IntType getCorrespondingUnsignedType(IntType T) {
+ switch (T) {
+ case SignedChar:
+ return UnsignedChar;
+ case SignedShort:
+ return UnsignedShort;
+ case SignedInt:
+ return UnsignedInt;
+ case SignedLong:
+ return UnsignedLong;
+ case SignedLongLong:
+ return UnsignedLongLong;
+ default:
+ llvm_unreachable("Unexpected signed integer type");
+ }
+ }
+
+ /// \brief Return the width (in bits) of the specified integer type enum.
+ ///
+ /// For example, SignedInt -> getIntWidth().
+ unsigned getTypeWidth(IntType T) const;
+
+ /// \brief Return integer type with specified width.
+ virtual IntType getIntTypeByWidth(unsigned BitWidth, bool IsSigned) const;
+
+ /// \brief Return the smallest integer type with at least the specified width.
+ virtual IntType getLeastIntTypeByWidth(unsigned BitWidth,
+ bool IsSigned) const;
+
+ /// \brief Return floating point type with specified width.
+ RealType getRealTypeByWidth(unsigned BitWidth) const;
+
+ /// \brief Return the alignment (in bits) of the specified integer type enum.
+ ///
+ /// For example, SignedInt -> getIntAlign().
+ unsigned getTypeAlign(IntType T) const;
+
+ /// \brief Returns true if the type is signed; false otherwise.
+ static bool isTypeSigned(IntType T);
+
+ /// \brief 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);
+ }
+
+ /// \brief Return the size of '_Bool' and C++ 'bool' for this target, in bits.
+ unsigned getBoolWidth() const { return BoolWidth; }
+
+ /// \brief Return the alignment of '_Bool' and C++ 'bool' for this target.
+ unsigned getBoolAlign() const { return BoolAlign; }
+
+ unsigned getCharWidth() const { return 8; } // FIXME
+ unsigned getCharAlign() const { return 8; } // FIXME
+
+ /// \brief Return the size of 'signed short' and 'unsigned short' for this
+ /// target, in bits.
+ unsigned getShortWidth() const { return 16; } // FIXME
+
+ /// \brief Return the alignment of 'signed short' and 'unsigned short' for
+ /// this target.
+ 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; }
+
+ /// \brief Determine whether the __int128 type is supported on this target.
+ virtual bool hasInt128Type() const {
+ return getPointerWidth(0) >= 64;
+ } // FIXME
+
+ /// \brief Return the alignment that is suitable for storing any
+ /// object with a fundamental alignment requirement.
+ unsigned getSuitableAlign() const { return SuitableAlign; }
+
+ /// \brief Return the default alignment for __attribute__((aligned)) on
+ /// this target, to be used if no alignment value is specified.
+ unsigned getDefaultAlignForAttributeAligned() const {
+ return DefaultAlignForAttributeAligned;
+ }
+
+ /// getMinGlobalAlign - Return the minimum alignment of a global variable,
+ /// unless its alignment is explicitly reduced via attributes.
+ unsigned getMinGlobalAlign() const { return MinGlobalAlign; }
+
+ /// 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); }
+
+ /// getHalfWidth/Align/Format - Return the size/align/format of 'half'.
+ unsigned getHalfWidth() const { return HalfWidth; }
+ unsigned getHalfAlign() const { return HalfAlign; }
+ const llvm::fltSemantics &getHalfFormat() const { return *HalfFormat; }
+
+ /// 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;
+ }
+
+ /// \brief Return true if the 'long double' type should be mangled like
+ /// __float128.
+ virtual bool useFloat128ManglingForLongDouble() const { return false; }
+
+ /// \brief Return the value for the C99 FLT_EVAL_METHOD macro.
+ virtual unsigned getFloatEvalMethod() const { return 0; }
+
+ // getLargeArrayMinWidth/Align - Return the minimum array size that is
+ // 'large' and its alignment.
+ unsigned getLargeArrayMinWidth() const { return LargeArrayMinWidth; }
+ unsigned getLargeArrayAlign() const { return LargeArrayAlign; }
+
+ /// \brief Return the maximum width lock-free atomic operation which will
+ /// ever be supported for the given target
+ unsigned getMaxAtomicPromoteWidth() const { return MaxAtomicPromoteWidth; }
+ /// \brief Return the maximum width lock-free atomic operation which can be
+ /// inlined given the supported features of the given target.
+ unsigned getMaxAtomicInlineWidth() const { return MaxAtomicInlineWidth; }
+ /// \brief Returns true if the given target supports lock-free atomic
+ /// operations at the specified width and alignment.
+ virtual bool hasBuiltinAtomic(uint64_t AtomicSizeInBits,
+ uint64_t AlignmentInBits) const {
+ return AtomicSizeInBits <= AlignmentInBits &&
+ AtomicSizeInBits <= getMaxAtomicInlineWidth() &&
+ (AtomicSizeInBits <= getCharWidth() ||
+ llvm::isPowerOf2_64(AtomicSizeInBits / getCharWidth()));
+ }
+
+ /// \brief Return the maximum vector alignment supported for the given target.
+ unsigned getMaxVectorAlign() const { return MaxVectorAlign; }
+ /// \brief Return default simd alignment for the given target. Generally, this
+ /// value is type-specific, but this alignment can be used for most of the
+ /// types for the given target.
+ unsigned getSimdDefaultAlign() const { return SimdDefaultAlign; }
+
+ /// \brief Return the size of intmax_t and uintmax_t for this target, in bits.
+ unsigned getIntMaxTWidth() const {
+ return getTypeWidth(IntMaxType);
+ }
+
+ // Return the size of unwind_word for this target.
+ unsigned getUnwindWordWidth() const { return getPointerWidth(0); }
+
+ /// \brief Return the "preferred" register width on this target.
+ unsigned getRegisterWidth() const {
+ // Currently we assume the register width on the target matches the pointer
+ // width, we can introduce a new variable for this if/when some target wants
+ // it.
+ return PointerWidth;
+ }
+
+ /// \brief 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;
+ }
+
+ /// \brief Returns the name of the mcount instrumentation function.
+ const char *getMCountName() const {
+ return MCountName;
+ }
+
+ /// \brief Check if the Objective-C built-in boolean type should be signed
+ /// char.
+ ///
+ /// Otherwise, if this returns false, the normal built-in boolean type
+ /// should also be used for Objective-C.
+ bool useSignedCharForObjCBool() const {
+ return UseSignedCharForObjCBool;
+ }
+ void noSignedCharForObjCBool() {
+ UseSignedCharForObjCBool = false;
+ }
+
+ /// \brief Check whether the alignment of bit-field types is respected
+ /// when laying out structures.
+ bool useBitFieldTypeAlignment() const {
+ return UseBitFieldTypeAlignment;
+ }
+
+ /// \brief Check whether zero length bitfields should force alignment of
+ /// the next member.
+ bool useZeroLengthBitfieldAlignment() const {
+ return UseZeroLengthBitfieldAlignment;
+ }
+
+ /// \brief Get the fixed alignment value in bits for a member that follows
+ /// a zero length bitfield.
+ unsigned getZeroLengthBitfieldBoundary() const {
+ return ZeroLengthBitfieldBoundary;
+ }
+
+ /// \brief Check whether this target support '\#pragma options align=mac68k'.
+ bool hasAlignMac68kSupport() const {
+ return HasAlignMac68kSupport;
+ }
+
+ /// \brief Return the user string for the specified integer type enum.
+ ///
+ /// For example, SignedShort -> "short".
+ static const char *getTypeName(IntType T);
+
+ /// \brief Return the constant suffix for the specified integer type enum.
+ ///
+ /// For example, SignedLong -> "L".
+ const char *getTypeConstantSuffix(IntType T) const;
+
+ /// \brief Return the printf format modifier for the specified
+ /// integer type enum.
+ ///
+ /// For example, SignedLong -> "l".
+ static const char *getTypeFormatModifier(IntType T);
+
+ /// \brief Check whether the given real type should use the "fpret" flavor of
+ /// Objective-C message passing on this target.
+ bool useObjCFPRetForRealType(RealType T) const {
+ return RealTypeUsesObjCFPRet & (1 << T);
+ }
+
+ /// \brief Check whether _Complex long double should use the "fp2ret" flavor
+ /// of Objective-C message passing on this target.
+ bool useObjCFP2RetForComplexLongDouble() const {
+ return ComplexLongDoubleUsesFP2Ret;
+ }
+
+ /// \brief Specify if mangling based on address space map should be used or
+ /// not for language specific address spaces
+ bool useAddressSpaceMapMangling() const {
+ return UseAddrSpaceMapMangling;
+ }
+
+ ///===---- Other target property query methods --------------------------===//
+
+ /// \brief Appends the target-specific \#define values for this
+ /// target set to the specified buffer.
+ virtual void getTargetDefines(const LangOptions &Opts,
+ MacroBuilder &Builder) const = 0;
+
+
+ /// 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 ArrayRef<Builtin::Info> getTargetBuiltins() const = 0;
+
+ /// The __builtin_clz* and __builtin_ctz* built-in
+ /// functions are specified to have undefined results for zero inputs, but
+ /// on targets that support these operations in a way that provides
+ /// well-defined results for zero without loss of performance, it is a good
+ /// idea to avoid optimizing based on that undef behavior.
+ virtual bool isCLZForZeroUndef() const { return true; }
+
+ /// \brief Returns the kind of __builtin_va_list type that should be used
+ /// with this target.
+ virtual BuiltinVaListKind getBuiltinVaListKind() const = 0;
+
+ /// Returns whether or not type \c __builtin_ms_va_list type is
+ /// available on this target.
+ bool hasBuiltinMSVaList() const { return HasBuiltinMSVaList; }
+
+ /// \brief Returns whether the passed in string is a valid clobber in an
+ /// inline asm statement.
+ ///
+ /// This is used by Sema.
+ bool isValidClobber(StringRef Name) const;
+
+ /// \brief 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(StringRef Name) const;
+
+ /// \brief Returns the "normalized" GCC register name.
+ ///
+ /// For example, on x86 it will return "ax" when "eax" is passed in.
+ StringRef getNormalizedGCCRegisterName(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.
+ CI_ImmediateConstant = 0x10, // This operand must be an immediate constant
+ CI_EarlyClobber = 0x20, // "&" output constraint (early clobber).
+ };
+ unsigned Flags;
+ int TiedOperand;
+ struct {
+ int Min;
+ int Max;
+ } ImmRange;
+ llvm::SmallSet<int, 4> ImmSet;
+
+ std::string ConstraintStr; // constraint: "=rm"
+ std::string Name; // Operand name: [foo] with no []'s.
+ public:
+ ConstraintInfo(StringRef ConstraintStr, StringRef Name)
+ : Flags(0), TiedOperand(-1), ConstraintStr(ConstraintStr.str()),
+ Name(Name.str()) {
+ ImmRange.Min = ImmRange.Max = 0;
+ }
+
+ const std::string &getConstraintStr() const { return ConstraintStr; }
+ const std::string &getName() const { return Name; }
+ bool isReadWrite() const { return (Flags & CI_ReadWrite) != 0; }
+ bool earlyClobber() { return (Flags & CI_EarlyClobber) != 0; }
+ bool allowsRegister() const { return (Flags & CI_AllowsRegister) != 0; }
+ bool allowsMemory() const { return (Flags & CI_AllowsMemory) != 0; }
+
+ /// \brief Return true if this output operand has a matching
+ /// (tied) input operand.
+ bool hasMatchingInput() const { return (Flags & CI_HasMatchingInput) != 0; }
+
+ /// \brief 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;
+ }
+
+ bool requiresImmediateConstant() const {
+ return (Flags & CI_ImmediateConstant) != 0;
+ }
+ bool isValidAsmImmediate(const llvm::APInt &Value) const {
+ return (Value.sge(ImmRange.Min) && Value.sle(ImmRange.Max)) ||
+ ImmSet.count(Value.getZExtValue()) != 0;
+ }
+
+ void setIsReadWrite() { Flags |= CI_ReadWrite; }
+ void setEarlyClobber() { Flags |= CI_EarlyClobber; }
+ void setAllowsMemory() { Flags |= CI_AllowsMemory; }
+ void setAllowsRegister() { Flags |= CI_AllowsRegister; }
+ void setHasMatchingInput() { Flags |= CI_HasMatchingInput; }
+ void setRequiresImmediate(int Min, int Max) {
+ Flags |= CI_ImmediateConstant;
+ ImmRange.Min = Min;
+ ImmRange.Max = Max;
+ }
+ void setRequiresImmediate(llvm::ArrayRef<int> Exacts) {
+ Flags |= CI_ImmediateConstant;
+ for (int Exact : Exacts)
+ ImmSet.insert(Exact);
+ }
+ void setRequiresImmediate(int Exact) {
+ Flags |= CI_ImmediateConstant;
+ ImmSet.insert(Exact);
+ }
+ void setRequiresImmediate() {
+ Flags |= CI_ImmediateConstant;
+ ImmRange.Min = INT_MIN;
+ ImmRange.Max = INT_MAX;
+ }
+
+ /// \brief 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.
+ }
+ };
+
+ /// \brief Validate register name used for global register variables.
+ ///
+ /// This function returns true if the register passed in RegName can be used
+ /// for global register variables on this target. In addition, it returns
+ /// true in HasSizeMismatch if the size of the register doesn't match the
+ /// variable size passed in RegSize.
+ virtual bool validateGlobalRegisterVariable(StringRef RegName,
+ unsigned RegSize,
+ bool &HasSizeMismatch) const {
+ HasSizeMismatch = false;
+ return true;
+ }
+
+ // 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(MutableArrayRef<ConstraintInfo> OutputConstraints,
+ ConstraintInfo &info) const;
+
+ virtual bool validateOutputSize(StringRef /*Constraint*/,
+ unsigned /*Size*/) const {
+ return true;
+ }
+
+ virtual bool validateInputSize(StringRef /*Constraint*/,
+ unsigned /*Size*/) const {
+ return true;
+ }
+ virtual bool
+ validateConstraintModifier(StringRef /*Constraint*/,
+ char /*Modifier*/,
+ unsigned /*Size*/,
+ std::string &/*SuggestedModifier*/) const {
+ return true;
+ }
+ virtual bool
+ validateAsmConstraint(const char *&Name,
+ TargetInfo::ConstraintInfo &info) const = 0;
+
+ bool resolveSymbolicName(const char *&Name,
+ ArrayRef<ConstraintInfo> OutputConstraints,
+ unsigned &Index) const;
+
+ // Constraint parm will be left pointing at the last character of
+ // the constraint. In practice, it won't be changed unless the
+ // constraint is longer than one character.
+ 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);
+ }
+
+ /// \brief Returns a string of target-specific clobbers, in LLVM format.
+ virtual const char *getClobbers() const = 0;
+
+ /// \brief Returns true if NaN encoding is IEEE 754-2008.
+ /// Only MIPS allows a different encoding.
+ virtual bool isNan2008() const {
+ return true;
+ }
+
+ /// \brief Returns the target triple of the primary target.
+ const llvm::Triple &getTriple() const {
+ return Triple;
+ }
+
+ const char *getDataLayoutString() const {
+ assert(DataLayoutString && "Uninitialized DataLayoutString!");
+ return DataLayoutString;
+ }
+
+ struct GCCRegAlias {
+ const char * const Aliases[5];
+ const char * const Register;
+ };
+
+ struct AddlRegName {
+ const char * const Names[5];
+ const unsigned RegNum;
+ };
+
+ /// \brief Does this target support "protected" visibility?
+ ///
+ /// Any target which dynamic libraries will naturally support
+ /// something like "default" (meaning that the symbol is visible
+ /// outside this shared object) and "hidden" (meaning that it isn't)
+ /// visibilities, but "protected" is really an ELF-specific concept
+ /// with weird semantics designed around the convenience of dynamic
+ /// linker implementations. Which is not to suggest that there's
+ /// consistent target-independent semantics for "default" visibility
+ /// either; the entire thing is pretty badly mangled.
+ virtual bool hasProtectedVisibility() const { return true; }
+
+ /// \brief 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(StringRef SR) const {
+ return "";
+ }
+
+ /// \brief Set forced language options.
+ ///
+ /// Apply changes to the target information with respect to certain
+ /// language options which change the target configuration.
+ virtual void adjust(const LangOptions &Opts);
+
+ /// \brief Initialize the map with the default set of target features for the
+ /// CPU this should include all legal feature strings on the target.
+ ///
+ /// \return False on error (invalid features).
+ virtual bool initFeatureMap(llvm::StringMap<bool> &Features,
+ DiagnosticsEngine &Diags, StringRef CPU,
+ const std::vector<std::string> &FeatureVec) const;
+
+ /// \brief Get the ABI currently in use.
+ virtual StringRef getABI() const { return StringRef(); }
+
+ /// \brief Get the C++ ABI currently in use.
+ TargetCXXABI getCXXABI() const {
+ return TheCXXABI;
+ }
+
+ /// \brief Target the specified CPU.
+ ///
+ /// \return False on error (invalid CPU name).
+ virtual bool setCPU(const std::string &Name) {
+ return false;
+ }
+
+ /// \brief Use the specified ABI.
+ ///
+ /// \return False on error (invalid ABI name).
+ virtual bool setABI(const std::string &Name) {
+ return false;
+ }
+
+ /// \brief Use the specified unit for FP math.
+ ///
+ /// \return False on error (invalid unit name).
+ virtual bool setFPMath(StringRef Name) {
+ return false;
+ }
+
+ /// \brief Enable or disable a specific target feature;
+ /// the feature name must be valid.
+ virtual void setFeatureEnabled(llvm::StringMap<bool> &Features,
+ StringRef Name,
+ bool Enabled) const {
+ Features[Name] = Enabled;
+ }
+
+ /// \brief 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.
+ /// FIXME: This part should be fixed so that we can change handleTargetFeatures
+ /// to merely a TargetInfo initialization routine.
+ ///
+ /// \return False on error.
+ virtual bool handleTargetFeatures(std::vector<std::string> &Features,
+ DiagnosticsEngine &Diags) {
+ return true;
+ }
+
+ /// \brief Determine whether the given target has the given feature.
+ virtual bool hasFeature(StringRef Feature) const {
+ return false;
+ }
+
+ // \brief Validate the contents of the __builtin_cpu_supports(const char*)
+ // argument.
+ virtual bool validateCpuSupports(StringRef Name) const { return false; }
+
+ // \brief Returns maximal number of args passed in registers.
+ unsigned getRegParmMax() const {
+ assert(RegParmMax < 7 && "RegParmMax value is larger than AST can handle");
+ return RegParmMax;
+ }
+
+ /// \brief Whether the target supports thread-local storage.
+ bool isTLSSupported() const {
+ return TLSSupported;
+ }
+
+ /// \brief Return the maximum alignment (in bits) of a TLS variable
+ ///
+ /// Gets the maximum alignment (in bits) of a TLS variable on this target.
+ /// Returns zero if there is no such constraint.
+ unsigned short getMaxTLSAlign() const {
+ return MaxTLSAlign;
+ }
+
+ /// \brief Whether the target supports SEH __try.
+ bool isSEHTrySupported() const {
+ return getTriple().isOSWindows() &&
+ (getTriple().getArch() == llvm::Triple::x86 ||
+ getTriple().getArch() == llvm::Triple::x86_64);
+ }
+
+ /// \brief 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;
+ }
+
+ /// \brief Return the register number that __builtin_eh_return_regno would
+ /// return with the specified argument.
+ virtual int getEHDataRegisterNumber(unsigned RegNo) const {
+ return -1;
+ }
+
+ /// \brief Return the section to use for C++ static initialization functions.
+ virtual const char *getStaticInitSectionSpecifier() const {
+ return nullptr;
+ }
+
+ const LangAS::Map &getAddressSpaceMap() const {
+ return *AddrSpaceMap;
+ }
+
+ /// \brief Retrieve the name of the platform as it is used in the
+ /// availability attribute.
+ StringRef getPlatformName() const { return PlatformName; }
+
+ /// \brief Retrieve the minimum desired version of the platform, to
+ /// which the program should be compiled.
+ VersionTuple getPlatformMinVersion() const { return PlatformMinVersion; }
+
+ bool isBigEndian() const { return BigEndian; }
+
+ enum CallingConvMethodType {
+ CCMT_Unknown,
+ CCMT_Member,
+ CCMT_NonMember
+ };
+
+ /// \brief Gets the default calling convention for the given target and
+ /// declaration context.
+ virtual CallingConv getDefaultCallingConv(CallingConvMethodType MT) const {
+ // Not all targets will specify an explicit calling convention that we can
+ // express. This will always do the right thing, even though it's not
+ // an explicit calling convention.
+ return CC_C;
+ }
+
+ enum CallingConvCheckResult {
+ CCCR_OK,
+ CCCR_Warning,
+ CCCR_Ignore,
+ };
+
+ /// \brief Determines whether a given calling convention is valid for the
+ /// target. A calling convention can either be accepted, produce a warning
+ /// and be substituted with the default calling convention, or (someday)
+ /// produce an error (such as using thiscall on a non-instance function).
+ virtual CallingConvCheckResult checkCallingConvention(CallingConv CC) const {
+ switch (CC) {
+ default:
+ return CCCR_Warning;
+ case CC_C:
+ return CCCR_OK;
+ }
+ }
+
+ /// Controls if __builtin_longjmp / __builtin_setjmp can be lowered to
+ /// llvm.eh.sjlj.longjmp / llvm.eh.sjlj.setjmp.
+ virtual bool hasSjLjLowering() const {
+ return false;
+ }
+
+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 ArrayRef<const char *> getGCCRegNames() const = 0;
+ virtual ArrayRef<GCCRegAlias> getGCCRegAliases() const = 0;
+ virtual ArrayRef<AddlRegName> getGCCAddlRegNames() const {
+ return None;
+ }
+};
+
+} // 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..ca0cca7
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Basic/TargetOptions.h
@@ -0,0 +1,54 @@
+//===--- TargetOptions.h ----------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+///
+/// \file
+/// \brief Defines the clang::TargetOptions class.
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_BASIC_TARGETOPTIONS_H
+#define LLVM_CLANG_BASIC_TARGETOPTIONS_H
+
+#include <string>
+#include <vector>
+
+namespace clang {
+
+/// \brief 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 unit to use for floating point math.
+ std::string FPMath;
+
+ /// If given, the name of the target ABI to use.
+ std::string ABI;
+
+ /// If given, the version string of the linker in use.
+ std::string LinkerVersion;
+
+ /// \brief The list of target specific features to enable or disable, as written on the command line.
+ std::vector<std::string> FeaturesAsWritten;
+
+ /// 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;
+
+ std::vector<std::string> Reciprocals;
+};
+
+} // 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..aed287b
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Basic/TemplateKinds.h
@@ -0,0 +1,44 @@
+//===--- 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.
+//
+//===----------------------------------------------------------------------===//
+///
+/// \file
+/// \brief Defines the clang::TemplateNameKind enum.
+///
+//===----------------------------------------------------------------------===//
+#ifndef LLVM_CLANG_BASIC_TEMPLATEKINDS_H
+#define LLVM_CLANG_BASIC_TEMPLATEKINDS_H
+
+namespace clang {
+
+/// \brief Specifies the kind of template name that an identifier refers to.
+/// Be careful when changing this: this enumeration is used in diagnostics.
+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 variable template whose specialization produces a
+ /// variable.
+ TNK_Var_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..9252d99
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Basic/TokenKinds.def
@@ -0,0 +1,781 @@
+//===--- 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,
+// CXX11_KEYWORD, CONCEPTS_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 CXX11_KEYWORD
+#define CXX11_KEYWORD(X,Y) KEYWORD(X,KEYCXX11|(Y))
+#endif
+#ifndef CONCEPTS_KEYWORD
+#define CONCEPTS_KEYWORD(X) KEYWORD(X,KEYCONCEPTS)
+#endif
+#ifndef TYPE_TRAIT
+#define TYPE_TRAIT(N,I,K) KEYWORD(I,K)
+#endif
+#ifndef TYPE_TRAIT_1
+#define TYPE_TRAIT_1(I,E,K) TYPE_TRAIT(1,I,K)
+#endif
+#ifndef TYPE_TRAIT_2
+#define TYPE_TRAIT_2(I,E,K) TYPE_TRAIT(2,I,K)
+#endif
+#ifndef TYPE_TRAIT_N
+#define TYPE_TRAIT_N(I,E,K) TYPE_TRAIT(0,I,K)
+#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 TESTING_KEYWORD
+#define TESTING_KEYWORD(X, L) KEYWORD(X, L)
+#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)
+
+// Clang extensions
+PPKEYWORD(__public_macro)
+PPKEYWORD(__private_macro)
+
+//===----------------------------------------------------------------------===//
+// Language keywords.
+//===----------------------------------------------------------------------===//
+
+// These define members of the tok::* namespace.
+
+TOK(unknown) // Not a token.
+TOK(eof) // End of file.
+TOK(eod) // End of preprocessing directive (end of line inside a
+ // directive).
+TOK(code_completion) // Code completion 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'
+TOK(wide_char_constant) // L'b'
+
+// C++1z Character Constants
+TOK(utf8_char_constant) // u8'a'
+
+// C++11 Character Constants
+TOK(utf16_char_constant) // u'a'
+TOK(utf32_char_constant) // U'a'
+
+// C99 6.4.5: String Literals.
+TOK(string_literal) // "foo"
+TOK(wide_string_literal) // L"foo"
+TOK(angle_string_literal)// <foo>
+
+// C++11 String Literals.
+TOK(utf8_string_literal) // u8"foo"
+TOK(utf16_string_literal)// u"foo"
+TOK(utf32_string_literal)// U"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
+// KEYC11 - This is a keyword introduced to C in C11
+// 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.
+// KEYCXX11 - This is a C++ keyword introduced to C++ in C++11
+// KEYCONCEPTS - This is a keyword if the C++ extensions for concepts
+// are enabled.
+// KEYGNU - This is a keyword if GNU extensions are enabled
+// KEYMS - This is a keyword if Microsoft extensions are enabled
+// KEYNOMS18 - This is a keyword that must never be enabled under
+// MSVC <= v18.
+// KEYOPENCL - This is a keyword in OpenCL
+// KEYNOOPENCL - This is a keyword that is not supported in OpenCL
+// KEYALTIVEC - This is a keyword in AltiVec
+// KEYZVECTOR - This is a keyword for the System z vector extensions,
+// which are heavily based on AltiVec
+// KEYBORLAND - This is a keyword if Borland extensions are enabled
+// KEYCOROUTINES - This is a keyword if support for the C++ coroutines
+// TS is enabled
+// BOOLSUPPORT - This is a keyword if 'bool' is a built-in type
+// HALFSUPPORT - This is a keyword if 'half' is a built-in type
+// WCHARSUPPORT - This is a keyword if 'wchar_t' is a built-in type
+//
+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(_Alignas , KEYALL)
+KEYWORD(_Alignof , KEYALL)
+KEYWORD(_Atomic , KEYALL|KEYNOOPENCL)
+KEYWORD(_Bool , KEYNOCXX)
+KEYWORD(_Complex , KEYALL)
+KEYWORD(_Generic , KEYALL)
+KEYWORD(_Imaginary , KEYALL)
+KEYWORD(_Noreturn , KEYALL)
+KEYWORD(_Static_assert , KEYALL)
+KEYWORD(_Thread_local , KEYALL)
+KEYWORD(__func__ , KEYALL)
+KEYWORD(__objc_yes , KEYALL)
+KEYWORD(__objc_no , KEYALL)
+
+
+// C++ 2.11p1: Keywords.
+KEYWORD(asm , KEYCXX|KEYGNU)
+KEYWORD(bool , BOOLSUPPORT)
+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)
+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)
+KEYWORD(try , KEYCXX)
+KEYWORD(typename , KEYCXX)
+KEYWORD(typeid , KEYCXX)
+KEYWORD(using , KEYCXX)
+KEYWORD(virtual , KEYCXX)
+KEYWORD(wchar_t , WCHARSUPPORT)
+
+// 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++11 keywords
+CXX11_KEYWORD(alignas , 0)
+CXX11_KEYWORD(alignof , 0)
+CXX11_KEYWORD(char16_t , KEYNOMS18)
+CXX11_KEYWORD(char32_t , KEYNOMS18)
+CXX11_KEYWORD(constexpr , 0)
+CXX11_KEYWORD(decltype , 0)
+CXX11_KEYWORD(noexcept , 0)
+CXX11_KEYWORD(nullptr , 0)
+CXX11_KEYWORD(static_assert , 0)
+CXX11_KEYWORD(thread_local , 0)
+
+// C++ concepts TS keywords
+CONCEPTS_KEYWORD(concept)
+CONCEPTS_KEYWORD(requires)
+
+// C++ coroutines TS keywords
+KEYWORD(co_await , KEYCOROUTINES)
+KEYWORD(co_return , KEYCOROUTINES)
+KEYWORD(co_yield , KEYCOROUTINES)
+
+// 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)
+// __builtin_types_compatible_p is a GNU C extension that we handle like a C++
+// type trait.
+TYPE_TRAIT_2(__builtin_types_compatible_p, TypeCompatible, KEYNOCXX)
+KEYWORD(__builtin_va_arg , KEYALL)
+KEYWORD(__extension__ , KEYALL)
+KEYWORD(__imag , KEYALL)
+KEYWORD(__int128 , KEYALL)
+KEYWORD(__label__ , KEYALL)
+KEYWORD(__real , KEYALL)
+KEYWORD(__thread , KEYALL)
+KEYWORD(__FUNCTION__ , KEYALL)
+KEYWORD(__PRETTY_FUNCTION__ , KEYALL)
+KEYWORD(__auto_type , KEYALL)
+
+// GNU Extensions (outside impl-reserved namespace)
+KEYWORD(typeof , KEYGNU)
+
+// MS Extensions
+KEYWORD(__FUNCDNAME__ , KEYMS)
+KEYWORD(__FUNCSIG__ , KEYMS)
+KEYWORD(L__FUNCTION__ , KEYMS)
+TYPE_TRAIT_1(__is_interface_class, IsInterfaceClass, KEYMS)
+TYPE_TRAIT_1(__is_sealed, IsSealed, KEYMS)
+
+// MSVC12.0 / VS2013 Type Traits
+TYPE_TRAIT_1(__is_destructible, IsDestructible, KEYMS)
+TYPE_TRAIT_1(__is_nothrow_destructible, IsNothrowDestructible, KEYMS)
+TYPE_TRAIT_2(__is_nothrow_assignable, IsNothrowAssignable, KEYCXX)
+TYPE_TRAIT_N(__is_constructible, IsConstructible, KEYCXX)
+TYPE_TRAIT_N(__is_nothrow_constructible, IsNothrowConstructible, KEYCXX)
+
+// GNU and MS Type Traits
+TYPE_TRAIT_1(__has_nothrow_assign, HasNothrowAssign, KEYCXX)
+TYPE_TRAIT_1(__has_nothrow_move_assign, HasNothrowMoveAssign, KEYCXX)
+TYPE_TRAIT_1(__has_nothrow_copy, HasNothrowCopy, KEYCXX)
+TYPE_TRAIT_1(__has_nothrow_constructor, HasNothrowConstructor, KEYCXX)
+TYPE_TRAIT_1(__has_trivial_assign, HasTrivialAssign, KEYCXX)
+TYPE_TRAIT_1(__has_trivial_move_assign, HasTrivialMoveAssign, KEYCXX)
+TYPE_TRAIT_1(__has_trivial_copy, HasTrivialCopy, KEYCXX)
+TYPE_TRAIT_1(__has_trivial_constructor, HasTrivialDefaultConstructor, KEYCXX)
+TYPE_TRAIT_1(__has_trivial_move_constructor, HasTrivialMoveConstructor, KEYCXX)
+TYPE_TRAIT_1(__has_trivial_destructor, HasTrivialDestructor, KEYCXX)
+TYPE_TRAIT_1(__has_virtual_destructor, HasVirtualDestructor, KEYCXX)
+TYPE_TRAIT_1(__is_abstract, IsAbstract, KEYCXX)
+TYPE_TRAIT_2(__is_base_of, IsBaseOf, KEYCXX)
+TYPE_TRAIT_1(__is_class, IsClass, KEYCXX)
+TYPE_TRAIT_2(__is_convertible_to, IsConvertibleTo, KEYCXX)
+TYPE_TRAIT_1(__is_empty, IsEmpty, KEYCXX)
+TYPE_TRAIT_1(__is_enum, IsEnum, KEYCXX)
+TYPE_TRAIT_1(__is_final, IsFinal, KEYCXX)
+// Tentative name - there's no implementation of std::is_literal_type yet.
+TYPE_TRAIT_1(__is_literal, IsLiteral, KEYCXX)
+// Name for GCC 4.6 compatibility - people have already written libraries using
+// this name unfortunately.
+ALIAS("__is_literal_type", __is_literal, KEYCXX)
+TYPE_TRAIT_1(__is_pod, IsPOD, KEYCXX)
+TYPE_TRAIT_1(__is_polymorphic, IsPolymorphic, KEYCXX)
+TYPE_TRAIT_1(__is_trivial, IsTrivial, KEYCXX)
+TYPE_TRAIT_1(__is_union, IsUnion, KEYCXX)
+
+// Clang-only C++ Type Traits
+TYPE_TRAIT_N(__is_trivially_constructible, IsTriviallyConstructible, KEYCXX)
+TYPE_TRAIT_1(__is_trivially_copyable, IsTriviallyCopyable, KEYCXX)
+TYPE_TRAIT_2(__is_trivially_assignable, IsTriviallyAssignable, KEYCXX)
+KEYWORD(__underlying_type , KEYCXX)
+
+// Embarcadero Expression Traits
+KEYWORD(__is_lvalue_expr , KEYCXX)
+KEYWORD(__is_rvalue_expr , KEYCXX)
+
+// Embarcadero Unary Type Traits
+TYPE_TRAIT_1(__is_arithmetic, IsArithmetic, KEYCXX)
+TYPE_TRAIT_1(__is_floating_point, IsFloatingPoint, KEYCXX)
+TYPE_TRAIT_1(__is_integral, IsIntegral, KEYCXX)
+TYPE_TRAIT_1(__is_complete_type, IsCompleteType, KEYCXX)
+TYPE_TRAIT_1(__is_void, IsVoid, KEYCXX)
+TYPE_TRAIT_1(__is_array, IsArray, KEYCXX)
+TYPE_TRAIT_1(__is_function, IsFunction, KEYCXX)
+TYPE_TRAIT_1(__is_reference, IsReference, KEYCXX)
+TYPE_TRAIT_1(__is_lvalue_reference, IsLvalueReference, KEYCXX)
+TYPE_TRAIT_1(__is_rvalue_reference, IsRvalueReference, KEYCXX)
+TYPE_TRAIT_1(__is_fundamental, IsFundamental, KEYCXX)
+TYPE_TRAIT_1(__is_object, IsObject, KEYCXX)
+TYPE_TRAIT_1(__is_scalar, IsScalar, KEYCXX)
+TYPE_TRAIT_1(__is_compound, IsCompound, KEYCXX)
+TYPE_TRAIT_1(__is_pointer, IsPointer, KEYCXX)
+TYPE_TRAIT_1(__is_member_object_pointer, IsMemberObjectPointer, KEYCXX)
+TYPE_TRAIT_1(__is_member_function_pointer, IsMemberFunctionPointer, KEYCXX)
+TYPE_TRAIT_1(__is_member_pointer, IsMemberPointer, KEYCXX)
+TYPE_TRAIT_1(__is_const, IsConst, KEYCXX)
+TYPE_TRAIT_1(__is_volatile, IsVolatile, KEYCXX)
+TYPE_TRAIT_1(__is_standard_layout, IsStandardLayout, KEYCXX)
+TYPE_TRAIT_1(__is_signed, IsSigned, KEYCXX)
+TYPE_TRAIT_1(__is_unsigned, IsUnsigned, KEYCXX)
+
+// Embarcadero Binary Type Traits
+TYPE_TRAIT_2(__is_same, IsSame, KEYCXX)
+TYPE_TRAIT_2(__is_convertible, IsConvertible, KEYCXX)
+KEYWORD(__array_rank , KEYCXX)
+KEYWORD(__array_extent , KEYCXX)
+
+// Apple Extension.
+KEYWORD(__private_extern__ , KEYALL)
+KEYWORD(__module_private__ , KEYALL)
+
+// Extension that will be enabled for Microsoft, Borland and PS4, but can be
+// disabled via '-fno-declspec'.
+KEYWORD(__declspec , 0)
+
+// Microsoft Extension.
+KEYWORD(__cdecl , KEYALL)
+KEYWORD(__stdcall , KEYALL)
+KEYWORD(__fastcall , KEYALL)
+KEYWORD(__thiscall , KEYALL)
+KEYWORD(__vectorcall , KEYALL)
+KEYWORD(__forceinline , KEYMS)
+KEYWORD(__unaligned , KEYMS)
+KEYWORD(__super , KEYMS)
+
+// OpenCL address space qualifiers
+KEYWORD(__global , KEYOPENCL)
+KEYWORD(__local , KEYOPENCL)
+KEYWORD(__constant , KEYOPENCL)
+KEYWORD(__private , KEYOPENCL)
+KEYWORD(__generic , KEYOPENCL)
+ALIAS("global", __global , KEYOPENCL)
+ALIAS("local", __local , KEYOPENCL)
+ALIAS("constant", __constant , KEYOPENCL)
+ALIAS("private", __private , KEYOPENCL)
+ALIAS("generic", __generic , KEYOPENCL)
+// OpenCL function qualifiers
+KEYWORD(__kernel , KEYOPENCL)
+ALIAS("kernel", __kernel , KEYOPENCL)
+// OpenCL access qualifiers
+KEYWORD(__read_only , KEYOPENCL)
+KEYWORD(__write_only , KEYOPENCL)
+KEYWORD(__read_write , KEYOPENCL)
+ALIAS("read_only", __read_only , KEYOPENCL)
+ALIAS("write_only", __write_only , KEYOPENCL)
+ALIAS("read_write", __read_write , KEYOPENCL)
+// OpenCL builtins
+KEYWORD(__builtin_astype , KEYOPENCL)
+KEYWORD(vec_step , KEYOPENCL|KEYALTIVEC|KEYZVECTOR)
+
+// OpenMP Type Traits
+KEYWORD(__builtin_omp_required_simd_align, KEYALL)
+
+// Borland Extensions.
+KEYWORD(__pascal , KEYALL)
+
+// Altivec Extension.
+KEYWORD(__vector , KEYALTIVEC|KEYZVECTOR)
+KEYWORD(__pixel , KEYALTIVEC)
+KEYWORD(__bool , KEYALTIVEC|KEYZVECTOR)
+
+// ARM NEON extensions.
+ALIAS("__fp16", half , KEYALL)
+
+// OpenCL Extension.
+KEYWORD(half , HALFSUPPORT)
+
+// Objective-C ARC keywords.
+KEYWORD(__bridge , KEYARC)
+KEYWORD(__bridge_transfer , KEYARC)
+KEYWORD(__bridge_retained , KEYARC)
+KEYWORD(__bridge_retain , KEYARC)
+
+// Objective-C keywords.
+KEYWORD(__covariant , KEYOBJC2)
+KEYWORD(__contravariant , KEYOBJC2)
+KEYWORD(__kindof , KEYOBJC2)
+
+// Alternate spelling for various tokens. There are GCC extensions in all
+// languages, but should not be disabled in strict conformance mode.
+ALIAS("__alignof__" , __alignof , KEYALL)
+ALIAS("__asm" , asm , KEYALL)
+ALIAS("__asm__" , asm , KEYALL)
+ALIAS("__attribute__", __attribute, KEYALL)
+ALIAS("__complex" , _Complex , KEYALL)
+ALIAS("__complex__" , _Complex , KEYALL)
+ALIAS("__const" , const , KEYALL)
+ALIAS("__const__" , const , KEYALL)
+ALIAS("__decltype" , decltype , KEYCXX)
+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)
+
+// Type nullability.
+KEYWORD(_Nonnull , KEYALL)
+KEYWORD(_Nullable , KEYALL)
+KEYWORD(_Null_unspecified , KEYALL)
+
+// Microsoft extensions which should be disabled in strict conformance mode
+KEYWORD(__ptr64 , KEYMS)
+KEYWORD(__ptr32 , KEYMS)
+KEYWORD(__sptr , KEYMS)
+KEYWORD(__uptr , KEYMS)
+KEYWORD(__w64 , KEYMS)
+KEYWORD(__uuidof , KEYMS | KEYBORLAND)
+KEYWORD(__try , KEYMS | KEYBORLAND)
+KEYWORD(__finally , KEYMS | KEYBORLAND)
+KEYWORD(__leave , KEYMS | KEYBORLAND)
+KEYWORD(__int64 , KEYMS)
+KEYWORD(__if_exists , KEYMS)
+KEYWORD(__if_not_exists , KEYMS)
+KEYWORD(__single_inheritance , KEYMS)
+KEYWORD(__multiple_inheritance , KEYMS)
+KEYWORD(__virtual_inheritance , KEYMS)
+KEYWORD(__interface , KEYMS)
+ALIAS("__int8" , char , KEYMS)
+ALIAS("_int8" , char , KEYMS)
+ALIAS("__int16" , short , KEYMS)
+ALIAS("_int16" , short , KEYMS)
+ALIAS("__int32" , int , KEYMS)
+ALIAS("_int32" , int , KEYMS)
+ALIAS("_int64" , __int64 , KEYMS)
+ALIAS("__wchar_t" , wchar_t , KEYMS)
+ALIAS("_asm" , asm , KEYMS)
+ALIAS("_alignof" , __alignof , KEYMS)
+ALIAS("__builtin_alignof", __alignof , KEYMS)
+ALIAS("_cdecl" , __cdecl , KEYMS | KEYBORLAND)
+ALIAS("_fastcall" , __fastcall , KEYMS | KEYBORLAND)
+ALIAS("_stdcall" , __stdcall , KEYMS | KEYBORLAND)
+ALIAS("_thiscall" , __thiscall , KEYMS)
+ALIAS("_vectorcall" , __vectorcall, KEYMS)
+ALIAS("_uuidof" , __uuidof , KEYMS | KEYBORLAND)
+ALIAS("_inline" , inline , KEYMS)
+ALIAS("_declspec" , __declspec , KEYMS)
+
+// Borland Extensions which should be disabled in strict conformance mode.
+ALIAS("_pascal" , __pascal , KEYBORLAND)
+
+// Clang Extensions.
+KEYWORD(__builtin_convertvector , KEYALL)
+ALIAS("__char16_t" , char16_t , KEYCXX)
+ALIAS("__char32_t" , char32_t , KEYCXX)
+
+// Clang-specific keywords enabled only in testing.
+TESTING_KEYWORD(__unknown_anytype , KEYALL)
+
+
+//===----------------------------------------------------------------------===//
+// Objective-C @-preceded 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)
+OBJC1_AT_KEYWORD(autoreleasepool)
+
+OBJC2_AT_KEYWORD(property)
+OBJC2_AT_KEYWORD(package)
+OBJC2_AT_KEYWORD(required)
+OBJC2_AT_KEYWORD(optional)
+OBJC2_AT_KEYWORD(synthesize)
+OBJC2_AT_KEYWORD(dynamic)
+OBJC2_AT_KEYWORD(import)
+
+// 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(primary_expr) // annotation for a primary expression
+ANNOTATION(decltype) // annotation for a decltype expression,
+ // e.g., "decltype(foo.bar())"
+
+// 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)
+
+// Annotation for #pragma GCC visibility...
+// The lexer produces these so that they only take effect when the parser
+// handles them.
+ANNOTATION(pragma_vis)
+
+// Annotation for #pragma pack...
+// The lexer produces these so that they only take effect when the parser
+// handles them.
+ANNOTATION(pragma_pack)
+
+// Annotation for #pragma clang __debug parser_crash...
+// The lexer produces these so that they only take effect when the parser
+// handles them.
+ANNOTATION(pragma_parser_crash)
+
+// Annotation for #pragma clang __debug captured...
+// The lexer produces these so that they only take effect when the parser
+// handles them.
+ANNOTATION(pragma_captured)
+
+// Annotation for #pragma ms_struct...
+// The lexer produces these so that they only take effect when the parser
+// handles them.
+ANNOTATION(pragma_msstruct)
+
+// Annotation for #pragma align...
+// The lexer produces these so that they only take effect when the parser
+// handles them.
+ANNOTATION(pragma_align)
+
+// Annotation for #pragma weak id
+// The lexer produces these so that they only take effect when the parser
+// handles them.
+ANNOTATION(pragma_weak)
+
+// Annotation for #pragma weak id = id
+// The lexer produces these so that they only take effect when the parser
+// handles them.
+ANNOTATION(pragma_weakalias)
+
+// Annotation for #pragma redefine_extname...
+// The lexer produces these so that they only take effect when the parser
+// handles them.
+ANNOTATION(pragma_redefine_extname)
+
+// Annotation for #pragma STDC FP_CONTRACT...
+// The lexer produces these so that they only take effect when the parser
+// handles them.
+ANNOTATION(pragma_fp_contract)
+
+// Annotation for #pragma pointers_to_members...
+// The lexer produces these so that they only take effect when the parser
+// handles them.
+ANNOTATION(pragma_ms_pointers_to_members)
+
+// Annotation for #pragma vtordisp...
+// The lexer produces these so that they only take effect when the parser
+// handles them.
+ANNOTATION(pragma_ms_vtordisp)
+
+// Annotation for all microsoft #pragmas...
+// The lexer produces these so that they only take effect when the parser
+// handles them.
+ANNOTATION(pragma_ms_pragma)
+
+// Annotation for #pragma OPENCL EXTENSION...
+// The lexer produces these so that they only take effect when the parser
+// handles them.
+ANNOTATION(pragma_opencl_extension)
+
+// Annotations for OpenMP pragma directives - #pragma omp ...
+// The lexer produces these so that they only take effect when the parser
+// handles #pragma omp ... directives.
+ANNOTATION(pragma_openmp)
+ANNOTATION(pragma_openmp_end)
+
+// Annotations for loop pragma directives #pragma clang loop ...
+// The lexer produces these so that they only take effect when the parser
+// handles #pragma loop ... directives.
+ANNOTATION(pragma_loop_hint)
+
+// Annotations for module import translated from #include etc.
+ANNOTATION(module_include)
+ANNOTATION(module_begin)
+ANNOTATION(module_end)
+
+#undef ANNOTATION
+#undef TESTING_KEYWORD
+#undef OBJC2_AT_KEYWORD
+#undef OBJC1_AT_KEYWORD
+#undef CXX_KEYWORD_OPERATOR
+#undef PPKEYWORD
+#undef ALIAS
+#undef TYPE_TRAIT_N
+#undef TYPE_TRAIT_2
+#undef TYPE_TRAIT_1
+#undef TYPE_TRAIT
+#undef CONCEPTS_KEYWORD
+#undef CXX11_KEYWORD
+#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..f4ecb3e
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Basic/TokenKinds.h
@@ -0,0 +1,106 @@
+//===--- 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.
+//
+//===----------------------------------------------------------------------===//
+///
+/// \file
+/// \brief Defines the clang::TokenKind enum and support functions.
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_BASIC_TOKENKINDS_H
+#define LLVM_CLANG_BASIC_TOKENKINDS_H
+
+#include "llvm/Support/Compiler.h"
+
+namespace clang {
+
+namespace tok {
+
+/// \brief Provides a simple uniform namespace for tokens from all C languages.
+enum TokenKind : unsigned short {
+#define TOK(X) X,
+#include "clang/Basic/TokenKinds.def"
+ NUM_TOKENS
+};
+
+/// \brief 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
+};
+
+/// \brief 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
+};
+
+/// \brief 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(TokenKind Kind) LLVM_READNONE;
+
+/// \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 *getPunctuatorSpelling(TokenKind Kind) LLVM_READNONE;
+
+/// \brief Determines the spelling of simple keyword and contextual keyword
+/// tokens like 'int' and 'dynamic_cast'. Returns NULL for other token kinds.
+const char *getKeywordSpelling(TokenKind Kind) LLVM_READNONE;
+
+/// \brief Return true if this is a raw identifier or an identifier kind.
+inline bool isAnyIdentifier(TokenKind K) {
+ return (K == tok::identifier) || (K == tok::raw_identifier);
+}
+
+/// \brief Return true if this is a C or C++ string-literal (or
+/// C++11 user-defined-string-literal) token.
+inline bool isStringLiteral(TokenKind K) {
+ return K == tok::string_literal || K == tok::wide_string_literal ||
+ K == tok::utf8_string_literal || K == tok::utf16_string_literal ||
+ K == tok::utf32_string_literal;
+}
+
+/// \brief Return true if this is a "literal" kind, like a numeric
+/// constant, string, etc.
+inline bool isLiteral(TokenKind K) {
+ return K == tok::numeric_constant || K == tok::char_constant ||
+ K == tok::wide_char_constant || K == tok::utf8_char_constant ||
+ K == tok::utf16_char_constant || K == tok::utf32_char_constant ||
+ isStringLiteral(K) || K == tok::angle_string_literal;
+}
+
+/// \brief Return true if this is any of tok::annot_* kinds.
+inline bool isAnnotation(TokenKind K) {
+#define ANNOTATION(NAME) \
+ if (K == tok::annot_##NAME) \
+ return true;
+#include "clang/Basic/TokenKinds.def"
+ return false;
+}
+
+} // 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..765246b
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Basic/TypeTraits.h
@@ -0,0 +1,100 @@
+//===--- 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.
+//
+//===----------------------------------------------------------------------===//
+///
+/// \file
+/// \brief Defines enumerations for the type traits support.
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_BASIC_TYPETRAITS_H
+#define LLVM_CLANG_BASIC_TYPETRAITS_H
+
+namespace clang {
+
+ /// \brief Names for traits that operate specifically on types.
+ enum TypeTrait {
+ UTT_HasNothrowAssign,
+ UTT_HasNothrowMoveAssign,
+ UTT_HasNothrowCopy,
+ UTT_HasNothrowConstructor,
+ UTT_HasTrivialAssign,
+ UTT_HasTrivialMoveAssign,
+ UTT_HasTrivialCopy,
+ UTT_HasTrivialDefaultConstructor,
+ UTT_HasTrivialMoveConstructor,
+ UTT_HasTrivialDestructor,
+ UTT_HasVirtualDestructor,
+ UTT_IsAbstract,
+ UTT_IsArithmetic,
+ UTT_IsArray,
+ UTT_IsClass,
+ UTT_IsCompleteType,
+ UTT_IsCompound,
+ UTT_IsConst,
+ UTT_IsDestructible,
+ UTT_IsEmpty,
+ UTT_IsEnum,
+ UTT_IsFinal,
+ UTT_IsFloatingPoint,
+ UTT_IsFunction,
+ UTT_IsFundamental,
+ UTT_IsIntegral,
+ UTT_IsInterfaceClass,
+ UTT_IsLiteral,
+ UTT_IsLvalueReference,
+ UTT_IsMemberFunctionPointer,
+ UTT_IsMemberObjectPointer,
+ UTT_IsMemberPointer,
+ UTT_IsNothrowDestructible,
+ UTT_IsObject,
+ UTT_IsPOD,
+ UTT_IsPointer,
+ UTT_IsPolymorphic,
+ UTT_IsReference,
+ UTT_IsRvalueReference,
+ UTT_IsScalar,
+ UTT_IsSealed,
+ UTT_IsSigned,
+ UTT_IsStandardLayout,
+ UTT_IsTrivial,
+ UTT_IsTriviallyCopyable,
+ UTT_IsUnion,
+ UTT_IsUnsigned,
+ UTT_IsVoid,
+ UTT_IsVolatile,
+ UTT_Last = UTT_IsVolatile,
+ BTT_IsBaseOf,
+ BTT_IsConvertible,
+ BTT_IsConvertibleTo,
+ BTT_IsSame,
+ BTT_TypeCompatible,
+ BTT_IsNothrowAssignable,
+ BTT_IsTriviallyAssignable,
+ BTT_Last = BTT_IsTriviallyAssignable,
+ TT_IsConstructible,
+ TT_IsNothrowConstructible,
+ TT_IsTriviallyConstructible
+ };
+
+ /// \brief Names for the array type traits.
+ enum ArrayTypeTrait {
+ ATT_ArrayRank,
+ ATT_ArrayExtent
+ };
+
+ /// \brief Names for the "expression or type" traits.
+ enum UnaryExprOrTypeTrait {
+ UETT_SizeOf,
+ UETT_AlignOf,
+ UETT_VecStep,
+ UETT_OpenMPRequiredSimdAlign,
+ };
+}
+
+#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..02da432
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Basic/Version.h
@@ -0,0 +1,82 @@
+//===- 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.
+//
+//===----------------------------------------------------------------------===//
+///
+/// \file
+/// \brief Defines version macros and version-related utility functions
+/// for Clang.
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_BASIC_VERSION_H
+#define LLVM_CLANG_BASIC_VERSION_H
+
+#include "clang/Basic/Version.inc"
+#include "llvm/ADT/StringRef.h"
+
+/// \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 path from which LLVM was built.
+ ///
+ /// This supports LLVM residing in a separate repository from clang.
+ std::string getLLVMRepositoryPath();
+
+ /// \brief Retrieves the repository revision number (or identifer) from which
+ /// this Clang was built.
+ std::string getClangRevision();
+
+ /// \brief Retrieves the repository revision number (or identifer) from which
+ /// LLVM was built.
+ ///
+ /// If Clang and LLVM are in the same repository, this returns the same
+ /// string as getClangRevision.
+ std::string getLLVMRevision();
+
+ /// \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();
+
+ /// \brief Like getClangFullVersion(), but with a custom tool name.
+ std::string getClangToolFullVersion(llvm::StringRef ToolName);
+
+ /// \brief Retrieves a string representing the complete clang version suitable
+ /// for use in the CPP __VERSION__ macro, which includes the clang version
+ /// number, the repository version, and the vendor tag.
+ std::string getClangFullCPPVersion();
+}
+
+#endif // LLVM_CLANG_BASIC_VERSION_H
diff --git a/contrib/llvm/tools/clang/include/clang/Basic/VersionTuple.h b/contrib/llvm/tools/clang/include/clang/Basic/VersionTuple.h
new file mode 100644
index 0000000..784f3f3
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Basic/VersionTuple.h
@@ -0,0 +1,163 @@
+//===- VersionTuple.h - Version Number Handling -----------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+///
+/// \file
+/// \brief Defines the clang::VersionTuple class, which represents a version in
+/// the form major[.minor[.subminor]].
+///
+//===----------------------------------------------------------------------===//
+#ifndef LLVM_CLANG_BASIC_VERSIONTUPLE_H
+#define LLVM_CLANG_BASIC_VERSIONTUPLE_H
+
+#include "clang/Basic/LLVM.h"
+#include "llvm/ADT/Optional.h"
+#include <string>
+#include <tuple>
+
+namespace clang {
+
+/// \brief Represents a version number in the form major[.minor[.subminor[.build]]].
+class VersionTuple {
+ unsigned Major : 31;
+ unsigned Minor : 31;
+ unsigned Subminor : 31;
+ unsigned Build : 31;
+ unsigned HasMinor : 1;
+ unsigned HasSubminor : 1;
+ unsigned HasBuild : 1;
+ unsigned UsesUnderscores : 1;
+
+public:
+ VersionTuple()
+ : Major(0), Minor(0), Subminor(0), Build(0), HasMinor(false),
+ HasSubminor(false), HasBuild(false), UsesUnderscores(false) {}
+
+ explicit VersionTuple(unsigned Major)
+ : Major(Major), Minor(0), Subminor(0), Build(0), HasMinor(false),
+ HasSubminor(false), HasBuild(false), UsesUnderscores(false) {}
+
+ explicit VersionTuple(unsigned Major, unsigned Minor,
+ bool UsesUnderscores = false)
+ : Major(Major), Minor(Minor), Subminor(0), Build(0), HasMinor(true),
+ HasSubminor(false), HasBuild(false), UsesUnderscores(UsesUnderscores) {}
+
+ explicit VersionTuple(unsigned Major, unsigned Minor, unsigned Subminor,
+ bool UsesUnderscores = false)
+ : Major(Major), Minor(Minor), Subminor(Subminor), Build(0),
+ HasMinor(true), HasSubminor(true), HasBuild(false),
+ UsesUnderscores(UsesUnderscores) {}
+
+ explicit VersionTuple(unsigned Major, unsigned Minor, unsigned Subminor,
+ unsigned Build, bool UsesUnderscores = false)
+ : Major(Major), Minor(Minor), Subminor(Subminor), Build(Build),
+ HasMinor(true), HasSubminor(true), HasBuild(true),
+ UsesUnderscores(UsesUnderscores) {}
+
+ /// \brief Determine whether this version information is empty
+ /// (e.g., all version components are zero).
+ bool empty() const {
+ return Major == 0 && Minor == 0 && Subminor == 0 && Build == 0;
+ }
+
+ /// \brief Retrieve the major version number.
+ unsigned getMajor() const { return Major; }
+
+ /// \brief Retrieve the minor version number, if provided.
+ Optional<unsigned> getMinor() const {
+ if (!HasMinor)
+ return None;
+ return Minor;
+ }
+
+ /// \brief Retrieve the subminor version number, if provided.
+ Optional<unsigned> getSubminor() const {
+ if (!HasSubminor)
+ return None;
+ return Subminor;
+ }
+
+ /// \brief Retrieve the build version number, if provided.
+ Optional<unsigned> getBuild() const {
+ if (!HasBuild)
+ return None;
+ return Build;
+ }
+
+ bool usesUnderscores() const {
+ return UsesUnderscores;
+ }
+
+ void UseDotAsSeparator() {
+ UsesUnderscores = false;
+ }
+
+ /// \brief Determine if two version numbers are equivalent. If not
+ /// provided, minor and subminor version numbers are considered to be zero.
+ friend bool operator==(const VersionTuple& X, const VersionTuple &Y) {
+ return X.Major == Y.Major && X.Minor == Y.Minor &&
+ X.Subminor == Y.Subminor && X.Build == Y.Build;
+ }
+
+ /// \brief Determine if two version numbers are not equivalent.
+ ///
+ /// If not provided, minor and subminor version numbers are considered to be
+ /// zero.
+ friend bool operator!=(const VersionTuple &X, const VersionTuple &Y) {
+ return !(X == Y);
+ }
+
+ /// \brief Determine whether one version number precedes another.
+ ///
+ /// If not provided, minor and subminor version numbers are considered to be
+ /// zero.
+ friend bool operator<(const VersionTuple &X, const VersionTuple &Y) {
+ return std::tie(X.Major, X.Minor, X.Subminor, X.Build) <
+ std::tie(Y.Major, Y.Minor, Y.Subminor, Y.Build);
+ }
+
+ /// \brief Determine whether one version number follows another.
+ ///
+ /// If not provided, minor and subminor version numbers are considered to be
+ /// zero.
+ friend bool operator>(const VersionTuple &X, const VersionTuple &Y) {
+ return Y < X;
+ }
+
+ /// \brief Determine whether one version number precedes or is
+ /// equivalent to another.
+ ///
+ /// If not provided, minor and subminor version numbers are considered to be
+ /// zero.
+ friend bool operator<=(const VersionTuple &X, const VersionTuple &Y) {
+ return !(Y < X);
+ }
+
+ /// \brief Determine whether one version number follows or is
+ /// equivalent to another.
+ ///
+ /// If not provided, minor and subminor version numbers are considered to be
+ /// zero.
+ friend bool operator>=(const VersionTuple &X, const VersionTuple &Y) {
+ return !(X < Y);
+ }
+
+ /// \brief Retrieve a string representation of the version number.
+ std::string getAsString() const;
+
+ /// \brief Try to parse the given string as a version number.
+ /// \returns \c true if the string does not match the regular expression
+ /// [0-9]+(\.[0-9]+){0,3}
+ bool tryParse(StringRef string);
+};
+
+/// \brief Print a version number.
+raw_ostream& operator<<(raw_ostream &Out, const VersionTuple &V);
+
+} // end namespace clang
+#endif // LLVM_CLANG_BASIC_VERSIONTUPLE_H
diff --git a/contrib/llvm/tools/clang/include/clang/Basic/VirtualFileSystem.h b/contrib/llvm/tools/clang/include/clang/Basic/VirtualFileSystem.h
new file mode 100644
index 0000000..1df4947
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Basic/VirtualFileSystem.h
@@ -0,0 +1,341 @@
+//===- VirtualFileSystem.h - Virtual File System Layer ----------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+/// \file
+/// \brief Defines the virtual file system interface vfs::FileSystem.
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_BASIC_VIRTUALFILESYSTEM_H
+#define LLVM_CLANG_BASIC_VIRTUALFILESYSTEM_H
+
+#include "clang/Basic/LLVM.h"
+#include "llvm/ADT/IntrusiveRefCntPtr.h"
+#include "llvm/ADT/Optional.h"
+#include "llvm/Support/ErrorOr.h"
+#include "llvm/Support/FileSystem.h"
+#include "llvm/Support/SourceMgr.h"
+#include "llvm/Support/raw_ostream.h"
+
+namespace llvm {
+class MemoryBuffer;
+}
+
+namespace clang {
+namespace vfs {
+
+/// \brief The result of a \p status operation.
+class Status {
+ std::string Name;
+ llvm::sys::fs::UniqueID UID;
+ llvm::sys::TimeValue MTime;
+ uint32_t User;
+ uint32_t Group;
+ uint64_t Size;
+ llvm::sys::fs::file_type Type;
+ llvm::sys::fs::perms Perms;
+
+public:
+ bool IsVFSMapped; // FIXME: remove when files support multiple names
+
+public:
+ Status() : Type(llvm::sys::fs::file_type::status_error) {}
+ Status(const llvm::sys::fs::file_status &Status);
+ Status(StringRef Name, llvm::sys::fs::UniqueID UID,
+ llvm::sys::TimeValue MTime, uint32_t User, uint32_t Group,
+ uint64_t Size, llvm::sys::fs::file_type Type,
+ llvm::sys::fs::perms Perms);
+
+ /// Get a copy of a Status with a different name.
+ static Status copyWithNewName(const Status &In, StringRef NewName);
+ static Status copyWithNewName(const llvm::sys::fs::file_status &In,
+ StringRef NewName);
+
+ /// \brief Returns the name that should be used for this file or directory.
+ StringRef getName() const { return Name; }
+
+ /// @name Status interface from llvm::sys::fs
+ /// @{
+ llvm::sys::fs::file_type getType() const { return Type; }
+ llvm::sys::fs::perms getPermissions() const { return Perms; }
+ llvm::sys::TimeValue getLastModificationTime() const { return MTime; }
+ llvm::sys::fs::UniqueID getUniqueID() const { return UID; }
+ uint32_t getUser() const { return User; }
+ uint32_t getGroup() const { return Group; }
+ uint64_t getSize() const { return Size; }
+ /// @}
+ /// @name Status queries
+ /// These are static queries in llvm::sys::fs.
+ /// @{
+ bool equivalent(const Status &Other) const;
+ bool isDirectory() const;
+ bool isRegularFile() const;
+ bool isOther() const;
+ bool isSymlink() const;
+ bool isStatusKnown() const;
+ bool exists() const;
+ /// @}
+};
+
+/// \brief Represents an open file.
+class File {
+public:
+ /// \brief Destroy the file after closing it (if open).
+ /// Sub-classes should generally call close() inside their destructors. We
+ /// cannot do that from the base class, since close is virtual.
+ virtual ~File();
+ /// \brief Get the status of the file.
+ virtual llvm::ErrorOr<Status> status() = 0;
+ /// \brief Get the contents of the file as a \p MemoryBuffer.
+ virtual llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>>
+ getBuffer(const Twine &Name, int64_t FileSize = -1,
+ bool RequiresNullTerminator = true, bool IsVolatile = false) = 0;
+ /// \brief Closes the file.
+ virtual std::error_code close() = 0;
+};
+
+namespace detail {
+/// \brief An interface for virtual file systems to provide an iterator over the
+/// (non-recursive) contents of a directory.
+struct DirIterImpl {
+ virtual ~DirIterImpl();
+ /// \brief Sets \c CurrentEntry to the next entry in the directory on success,
+ /// or returns a system-defined \c error_code.
+ virtual std::error_code increment() = 0;
+ Status CurrentEntry;
+};
+} // end namespace detail
+
+/// \brief An input iterator over the entries in a virtual path, similar to
+/// llvm::sys::fs::directory_iterator.
+class directory_iterator {
+ std::shared_ptr<detail::DirIterImpl> Impl; // Input iterator semantics on copy
+
+public:
+ directory_iterator(std::shared_ptr<detail::DirIterImpl> I) : Impl(I) {
+ assert(Impl.get() != nullptr && "requires non-null implementation");
+ if (!Impl->CurrentEntry.isStatusKnown())
+ Impl.reset(); // Normalize the end iterator to Impl == nullptr.
+ }
+
+ /// \brief Construct an 'end' iterator.
+ directory_iterator() { }
+
+ /// \brief Equivalent to operator++, with an error code.
+ directory_iterator &increment(std::error_code &EC) {
+ assert(Impl && "attempting to increment past end");
+ EC = Impl->increment();
+ if (EC || !Impl->CurrentEntry.isStatusKnown())
+ Impl.reset(); // Normalize the end iterator to Impl == nullptr.
+ return *this;
+ }
+
+ const Status &operator*() const { return Impl->CurrentEntry; }
+ const Status *operator->() const { return &Impl->CurrentEntry; }
+
+ bool operator==(const directory_iterator &RHS) const {
+ if (Impl && RHS.Impl)
+ return Impl->CurrentEntry.equivalent(RHS.Impl->CurrentEntry);
+ return !Impl && !RHS.Impl;
+ }
+ bool operator!=(const directory_iterator &RHS) const {
+ return !(*this == RHS);
+ }
+};
+
+class FileSystem;
+
+/// \brief An input iterator over the recursive contents of a virtual path,
+/// similar to llvm::sys::fs::recursive_directory_iterator.
+class recursive_directory_iterator {
+ typedef std::stack<directory_iterator, std::vector<directory_iterator>>
+ IterState;
+
+ FileSystem *FS;
+ std::shared_ptr<IterState> State; // Input iterator semantics on copy.
+
+public:
+ recursive_directory_iterator(FileSystem &FS, const Twine &Path,
+ std::error_code &EC);
+ /// \brief Construct an 'end' iterator.
+ recursive_directory_iterator() { }
+
+ /// \brief Equivalent to operator++, with an error code.
+ recursive_directory_iterator &increment(std::error_code &EC);
+
+ const Status &operator*() const { return *State->top(); }
+ const Status *operator->() const { return &*State->top(); }
+
+ bool operator==(const recursive_directory_iterator &Other) const {
+ return State == Other.State; // identity
+ }
+ bool operator!=(const recursive_directory_iterator &RHS) const {
+ return !(*this == RHS);
+ }
+};
+
+/// \brief The virtual file system interface.
+class FileSystem : public llvm::ThreadSafeRefCountedBase<FileSystem> {
+public:
+ virtual ~FileSystem();
+
+ /// \brief Get the status of the entry at \p Path, if one exists.
+ virtual llvm::ErrorOr<Status> status(const Twine &Path) = 0;
+ /// \brief Get a \p File object for the file at \p Path, if one exists.
+ virtual llvm::ErrorOr<std::unique_ptr<File>>
+ openFileForRead(const Twine &Path) = 0;
+
+ /// This is a convenience method that opens a file, gets its content and then
+ /// closes the file.
+ llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>>
+ getBufferForFile(const Twine &Name, int64_t FileSize = -1,
+ bool RequiresNullTerminator = true, bool IsVolatile = false);
+
+ /// \brief Get a directory_iterator for \p Dir.
+ /// \note The 'end' iterator is directory_iterator().
+ virtual directory_iterator dir_begin(const Twine &Dir,
+ std::error_code &EC) = 0;
+
+ /// Set the working directory. This will affect all following operations on
+ /// this file system and may propagate down for nested file systems.
+ virtual std::error_code setCurrentWorkingDirectory(const Twine &Path) = 0;
+ /// Get the working directory of this file system.
+ virtual llvm::ErrorOr<std::string> getCurrentWorkingDirectory() const = 0;
+
+ /// Check whether a file exists. Provided for convenience.
+ bool exists(const Twine &Path);
+
+ /// Make \a Path an absolute path.
+ ///
+ /// Makes \a Path absolute using the current directory if it is not already.
+ /// An empty \a Path will result in the current directory.
+ ///
+ /// /absolute/path => /absolute/path
+ /// relative/../path => <current-directory>/relative/../path
+ ///
+ /// \param Path A path that is modified to be an absolute path.
+ /// \returns success if \a path has been made absolute, otherwise a
+ /// platform-specific error_code.
+ std::error_code makeAbsolute(SmallVectorImpl<char> &Path) const;
+};
+
+/// \brief Gets an \p vfs::FileSystem for the 'real' file system, as seen by
+/// the operating system.
+IntrusiveRefCntPtr<FileSystem> getRealFileSystem();
+
+/// \brief A file system that allows overlaying one \p AbstractFileSystem on top
+/// of another.
+///
+/// Consists of a stack of >=1 \p FileSystem objects, which are treated as being
+/// one merged file system. When there is a directory that exists in more than
+/// one file system, the \p OverlayFileSystem contains a directory containing
+/// the union of their contents. The attributes (permissions, etc.) of the
+/// top-most (most recently added) directory are used. When there is a file
+/// that exists in more than one file system, the file in the top-most file
+/// system overrides the other(s).
+class OverlayFileSystem : public FileSystem {
+ typedef SmallVector<IntrusiveRefCntPtr<FileSystem>, 1> FileSystemList;
+ /// \brief The stack of file systems, implemented as a list in order of
+ /// their addition.
+ FileSystemList FSList;
+
+public:
+ OverlayFileSystem(IntrusiveRefCntPtr<FileSystem> Base);
+ /// \brief Pushes a file system on top of the stack.
+ void pushOverlay(IntrusiveRefCntPtr<FileSystem> FS);
+
+ llvm::ErrorOr<Status> status(const Twine &Path) override;
+ llvm::ErrorOr<std::unique_ptr<File>>
+ openFileForRead(const Twine &Path) override;
+ directory_iterator dir_begin(const Twine &Dir, std::error_code &EC) override;
+ llvm::ErrorOr<std::string> getCurrentWorkingDirectory() const override;
+ std::error_code setCurrentWorkingDirectory(const Twine &Path) override;
+
+ typedef FileSystemList::reverse_iterator iterator;
+
+ /// \brief Get an iterator pointing to the most recently added file system.
+ iterator overlays_begin() { return FSList.rbegin(); }
+
+ /// \brief Get an iterator pointing one-past the least recently added file
+ /// system.
+ iterator overlays_end() { return FSList.rend(); }
+};
+
+namespace detail {
+class InMemoryDirectory;
+} // end namespace detail
+
+/// An in-memory file system.
+class InMemoryFileSystem : public FileSystem {
+ std::unique_ptr<detail::InMemoryDirectory> Root;
+ std::string WorkingDirectory;
+ bool UseNormalizedPaths = true;
+
+public:
+ explicit InMemoryFileSystem(bool UseNormalizedPaths = true);
+ ~InMemoryFileSystem() override;
+ /// Add a buffer to the VFS with a path. The VFS owns the buffer.
+ /// \return true if the file was successfully added, false if the file already
+ /// exists in the file system with different contents.
+ bool addFile(const Twine &Path, time_t ModificationTime,
+ std::unique_ptr<llvm::MemoryBuffer> Buffer);
+ /// Add a buffer to the VFS with a path. The VFS does not own the buffer.
+ /// \return true if the file was successfully added, false if the file already
+ /// exists in the file system with different contents.
+ bool addFileNoOwn(const Twine &Path, time_t ModificationTime,
+ llvm::MemoryBuffer *Buffer);
+ std::string toString() const;
+ /// Return true if this file system normalizes . and .. in paths.
+ bool useNormalizedPaths() const { return UseNormalizedPaths; }
+
+ llvm::ErrorOr<Status> status(const Twine &Path) override;
+ llvm::ErrorOr<std::unique_ptr<File>>
+ openFileForRead(const Twine &Path) override;
+ directory_iterator dir_begin(const Twine &Dir, std::error_code &EC) override;
+ llvm::ErrorOr<std::string> getCurrentWorkingDirectory() const override {
+ return WorkingDirectory;
+ }
+ std::error_code setCurrentWorkingDirectory(const Twine &Path) override {
+ WorkingDirectory = Path.str();
+ return std::error_code();
+ }
+};
+
+/// \brief Get a globally unique ID for a virtual file or directory.
+llvm::sys::fs::UniqueID getNextVirtualUniqueID();
+
+/// \brief Gets a \p FileSystem for a virtual file system described in YAML
+/// format.
+IntrusiveRefCntPtr<FileSystem>
+getVFSFromYAML(std::unique_ptr<llvm::MemoryBuffer> Buffer,
+ llvm::SourceMgr::DiagHandlerTy DiagHandler,
+ void *DiagContext = nullptr,
+ IntrusiveRefCntPtr<FileSystem> ExternalFS = getRealFileSystem());
+
+struct YAMLVFSEntry {
+ template <typename T1, typename T2> YAMLVFSEntry(T1 &&VPath, T2 &&RPath)
+ : VPath(std::forward<T1>(VPath)), RPath(std::forward<T2>(RPath)) {}
+ std::string VPath;
+ std::string RPath;
+};
+
+class YAMLVFSWriter {
+ std::vector<YAMLVFSEntry> Mappings;
+ Optional<bool> IsCaseSensitive;
+
+public:
+ YAMLVFSWriter() {}
+ void addFileMapping(StringRef VirtualPath, StringRef RealPath);
+ void setCaseSensitivity(bool CaseSensitive) {
+ IsCaseSensitive = CaseSensitive;
+ }
+ void write(llvm::raw_ostream &OS);
+};
+
+} // end namespace vfs
+} // end namespace clang
+#endif
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..6ac52ed
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Basic/Visibility.h
@@ -0,0 +1,141 @@
+//===--- 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.
+//
+//===----------------------------------------------------------------------===//
+///
+/// \file
+/// \brief Defines the clang::Visibility enumeration and various utility
+/// functions.
+///
+//===----------------------------------------------------------------------===//
+#ifndef LLVM_CLANG_BASIC_VISIBILITY_H
+#define LLVM_CLANG_BASIC_VISIBILITY_H
+
+#include "clang/Basic/Linkage.h"
+
+namespace clang {
+
+/// \brief 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;
+}
+
+class LinkageInfo {
+ uint8_t linkage_ : 3;
+ uint8_t visibility_ : 2;
+ uint8_t explicit_ : 1;
+
+ void setVisibility(Visibility V, bool E) { visibility_ = V; explicit_ = E; }
+public:
+ LinkageInfo() : linkage_(ExternalLinkage), visibility_(DefaultVisibility),
+ explicit_(false) {}
+ LinkageInfo(Linkage L, Visibility V, bool E)
+ : linkage_(L), visibility_(V), explicit_(E) {
+ assert(getLinkage() == L && getVisibility() == V &&
+ isVisibilityExplicit() == E && "Enum truncated!");
+ }
+
+ 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 getLinkage() const { return (Linkage)linkage_; }
+ Visibility getVisibility() const { return (Visibility)visibility_; }
+ bool isVisibilityExplicit() const { return explicit_; }
+
+ void setLinkage(Linkage L) { linkage_ = L; }
+
+ void mergeLinkage(Linkage L) {
+ setLinkage(minLinkage(getLinkage(), L));
+ }
+ void mergeLinkage(LinkageInfo other) {
+ mergeLinkage(other.getLinkage());
+ }
+
+ void mergeExternalVisibility(Linkage L) {
+ Linkage ThisL = getLinkage();
+ if (!isExternallyVisible(L)) {
+ if (ThisL == VisibleNoLinkage)
+ ThisL = NoLinkage;
+ else if (ThisL == ExternalLinkage)
+ ThisL = UniqueExternalLinkage;
+ }
+ setLinkage(ThisL);
+ }
+ void mergeExternalVisibility(LinkageInfo Other) {
+ mergeExternalVisibility(Other.getLinkage());
+ }
+
+ /// Merge in the visibility 'newVis'.
+ void mergeVisibility(Visibility newVis, bool newExplicit) {
+ Visibility oldVis = getVisibility();
+
+ // Never increase visibility.
+ if (oldVis < newVis)
+ return;
+
+ // If the new visibility is the same as the old and the new
+ // visibility isn't explicit, we have nothing to add.
+ if (oldVis == newVis && !newExplicit)
+ return;
+
+ // Otherwise, we're either decreasing visibility or making our
+ // existing visibility explicit.
+ setVisibility(newVis, newExplicit);
+ }
+ void mergeVisibility(LinkageInfo other) {
+ mergeVisibility(other.getVisibility(), other.isVisibilityExplicit());
+ }
+
+ /// Merge both linkage and visibility.
+ void merge(LinkageInfo other) {
+ mergeLinkage(other);
+ mergeVisibility(other);
+ }
+
+ /// Merge linkage and conditionally merge visibility.
+ void mergeMaybeWithVisibility(LinkageInfo other, bool withVis) {
+ mergeLinkage(other);
+ if (withVis) mergeVisibility(other);
+ }
+};
+}
+
+#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..6d95c1e
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Basic/arm_neon.td
@@ -0,0 +1,1657 @@
+//===--- 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.
+//
+//===----------------------------------------------------------------------===//
+//
+// Each intrinsic is a subclass of the Inst class. An intrinsic can either
+// generate a __builtin_* call or it can expand to a set of generic operations.
+//
+// The operations are subclasses of Operation providing a list of DAGs, the
+// last of which is the return value. The available DAG nodes are documented
+// below.
+//
+//===----------------------------------------------------------------------===//
+
+// The base Operation class. All operations must subclass this.
+class Operation<list<dag> ops=[]> {
+ list<dag> Ops = ops;
+ bit Unavailable = 0;
+}
+// An operation that only contains a single DAG.
+class Op<dag op> : Operation<[op]>;
+// A shorter version of Operation - takes a list of DAGs. The last of these will
+// be the return value.
+class LOp<list<dag> ops> : Operation<ops>;
+
+// These defs and classes are used internally to implement the SetTheory
+// expansion and should be ignored.
+foreach Index = 0-63 in
+ def sv##Index;
+class MaskExpand;
+
+//===----------------------------------------------------------------------===//
+// Available operations
+//===----------------------------------------------------------------------===//
+
+// DAG arguments can either be operations (documented below) or variables.
+// Variables are prefixed with '$'. There are variables for each input argument,
+// with the name $pN, where N starts at zero. So the zero'th argument will be
+// $p0, the first $p1 etc.
+
+// op - Binary or unary operator, depending on the number of arguments. The
+// operator itself is just treated as a raw string and is not checked.
+// example: (op "+", $p0, $p1) -> "__p0 + __p1".
+// (op "-", $p0) -> "-__p0"
+def op;
+// call - Invoke another intrinsic. The input types are type checked and
+// disambiguated. If there is no intrinsic defined that takes
+// the given types (or if there is a type ambiguity) an error is
+// generated at tblgen time. The name of the intrinsic is the raw
+// name as given to the Inst class (not mangled).
+// example: (call "vget_high", $p0) -> "vgetq_high_s16(__p0)"
+// (assuming $p0 has type int16x8_t).
+def call;
+// cast - Perform a cast to a different type. This gets emitted as a static
+// C-style cast. For a pure reinterpret cast (T x = *(T*)&y), use
+// "bitcast".
+//
+// The syntax is (cast MOD* VAL). The last argument is the value to
+// cast, preceded by a sequence of type modifiers. The target type
+// starts off as the type of VAL, and is modified by MOD in sequence.
+// The available modifiers are:
+// - $X - Take the type of parameter/variable X. For example:
+// (cast $p0, $p1) would cast $p1 to the type of $p0.
+// - "R" - The type of the return type.
+// - A typedef string - A NEON or stdint.h type that is then parsed.
+// for example: (cast "uint32x4_t", $p0).
+// - "U" - Make the type unsigned.
+// - "S" - Make the type signed.
+// - "H" - Halve the number of lanes in the type.
+// - "D" - Double the number of lanes in the type.
+// - "8" - Convert type to an equivalent vector of 8-bit signed
+// integers.
+// example: (cast "R", "U", $p0) -> "(uint32x4_t)__p0" (assuming the return
+// value is of type "int32x4_t".
+// (cast $p0, "D", "8", $p1) -> "(int8x16_t)__p1" (assuming __p0
+// has type float64x1_t or any other vector type of 64 bits).
+// (cast "int32_t", $p2) -> "(int32_t)__p2"
+def cast;
+// bitcast - Same as "cast", except a reinterpret-cast is produced:
+// (bitcast "T", $p0) -> "*(T*)&__p0".
+// The VAL argument is saved to a temporary so it can be used
+// as an l-value.
+def bitcast;
+// dup - Take a scalar argument and create a vector by duplicating it into
+// all lanes. The type of the vector is the base type of the intrinsic.
+// example: (dup $p1) -> "(uint32x2_t) {__p1, __p1}" (assuming the base type
+// is uint32x2_t).
+def dup;
+// splat - Take a vector and a lane index, and return a vector of the same type
+// containing repeated instances of the source vector at the lane index.
+// example: (splat $p0, $p1) ->
+// "__builtin_shufflevector(__p0, __p0, __p1, __p1, __p1, __p1)"
+// (assuming __p0 has four elements).
+def splat;
+// save_temp - Create a temporary (local) variable. The variable takes a name
+// based on the zero'th parameter and can be referenced using
+// using that name in subsequent DAGs in the same
+// operation. The scope of a temp is the operation. If a variable
+// with the given name already exists, an error will be given at
+// tblgen time.
+// example: [(save_temp $var, (call "foo", $p0)),
+// (op "+", $var, $p1)] ->
+// "int32x2_t __var = foo(__p0); return __var + __p1;"
+def save_temp;
+// name_replace - Return the name of the current intrinsic with the first
+// argument replaced by the second argument. Raises an error if
+// the first argument does not exist in the intrinsic name.
+// example: (call (name_replace "_high_", "_"), $p0) (to call the non-high
+// version of this intrinsic).
+def name_replace;
+// literal - Create a literal piece of code. The code is treated as a raw
+// string, and must be given a type. The type is a stdint.h or
+// NEON intrinsic type as given to (cast).
+// example: (literal "int32_t", "0")
+def literal;
+// shuffle - Create a vector shuffle. The syntax is (shuffle ARG0, ARG1, MASK).
+// The MASK argument is a set of elements. The elements are generated
+// from the two special defs "mask0" and "mask1". "mask0" expands to
+// the lane indices in sequence for ARG0, and "mask1" expands to
+// the lane indices in sequence for ARG1. They can be used as-is, e.g.
+//
+// (shuffle $p0, $p1, mask0) -> $p0
+// (shuffle $p0, $p1, mask1) -> $p1
+//
+// or, more usefully, they can be manipulated using the SetTheory
+// operators plus some extra operators defined in the NEON emitter.
+// The operators are described below.
+// example: (shuffle $p0, $p1, (add (highhalf mask0), (highhalf mask1))) ->
+// A concatenation of the high halves of the input vectors.
+def shuffle;
+
+// add, interleave, decimate: These set operators are vanilla SetTheory
+// operators and take their normal definition.
+def add;
+def interleave;
+def decimate;
+// rotl - Rotate set left by a number of elements.
+// example: (rotl mask0, 3) -> [3, 4, 5, 6, 0, 1, 2]
+def rotl;
+// rotl - Rotate set right by a number of elements.
+// example: (rotr mask0, 3) -> [4, 5, 6, 0, 1, 2, 3]
+def rotr;
+// highhalf - Take only the high half of the input.
+// example: (highhalf mask0) -> [4, 5, 6, 7] (assuming mask0 had 8 elements)
+def highhalf;
+// highhalf - Take only the low half of the input.
+// example: (lowhalf mask0) -> [0, 1, 2, 3] (assuming mask0 had 8 elements)
+def lowhalf;
+// rev - Perform a variable-width reversal of the elements. The zero'th argument
+// is a width in bits to reverse. The lanes this maps to is determined
+// based on the element width of the underlying type.
+// example: (rev 32, mask0) -> [3, 2, 1, 0, 7, 6, 5, 4] (if 8-bit elements)
+// example: (rev 32, mask0) -> [1, 0, 3, 2] (if 16-bit elements)
+def rev;
+// mask0 - The initial sequence of lanes for shuffle ARG0
+def mask0 : MaskExpand;
+// mask0 - The initial sequence of lanes for shuffle ARG1
+def mask1 : MaskExpand;
+
+def OP_NONE : Operation;
+def OP_UNAVAILABLE : Operation {
+ let Unavailable = 1;
+}
+
+//===----------------------------------------------------------------------===//
+// Instruction definitions
+//===----------------------------------------------------------------------===//
+
+// Every intrinsic subclasses "Inst". An intrinsic has a name, a prototype and
+// a sequence of typespecs.
+//
+// The name is the base name of the intrinsic, for example "vget_lane". This is
+// then mangled by the tblgen backend to add type information ("vget_lane_s16").
+//
+// A typespec is a sequence of uppercase characters (modifiers) followed by one
+// lowercase character. A typespec encodes a particular "base type" of the
+// intrinsic.
+//
+// An example typespec is "Qs" - quad-size short - uint16x8_t. The available
+// typespec codes are given below.
+//
+// The string given to an Inst class is a sequence of typespecs. The intrinsic
+// is instantiated for every typespec in the sequence. For example "sdQsQd".
+//
+// The prototype is a string that defines the return type of the intrinsic
+// and the type of each argument. The return type and every argument gets a
+// "modifier" that can change in some way the "base type" of the intrinsic.
+//
+// The modifier 'd' means "default" and does not modify the base type in any
+// way. The available modifiers are given below.
+//
+// Typespecs
+// ---------
+// c: char
+// s: short
+// i: int
+// l: long
+// k: 128-bit long
+// f: float
+// h: half-float
+// d: double
+//
+// Typespec modifiers
+// ------------------
+// S: scalar, only used for function mangling.
+// U: unsigned
+// Q: 128b
+// H: 128b without mangling 'q'
+// P: polynomial
+//
+// Prototype modifiers
+// -------------------
+// 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)
+// F: double (int args)
+// d: default
+// g: default, ignore 'Q' size modifier.
+// j: default, force 'Q' size modifier.
+// w: double width elements, same num elts
+// n: double width elements, half num elts
+// h: half width elements, double num elts
+// q: half width elements, quad num elts
+// e: half width elements, double num elts, unsigned
+// m: half width elements, same num elts
+// i: constant int
+// l: constant uint64
+// s: scalar of element type
+// z: scalar of half width element type, signed
+// r: scalar of double width element type, signed
+// a: scalar of element type (splat to vector type)
+// b: scalar of unsigned integer/long type (int/float args)
+// $: scalar of signed integer/long type (int/float args)
+// y: scalar of float
+// o: scalar of double
+// k: default elt width, double num elts
+// 2,3,4: array of default vectors
+// B,C,D: array of default elts, force 'Q' size modifier.
+// p: pointer type
+// c: const pointer type
+
+// Every intrinsic subclasses Inst.
+class Inst <string n, string p, string t, Operation o> {
+ string Name = n;
+ string Prototype = p;
+ string Types = t;
+ string ArchGuard = "";
+
+ Operation Operation = o;
+ bit CartesianProductOfTypes = 0;
+ bit BigEndianSafe = 0;
+ bit isShift = 0;
+ bit isScalarShift = 0;
+ bit isScalarNarrowShift = 0;
+ bit isVCVT_N = 0;
+ // For immediate checks: the immediate will be assumed to specify the lane of
+ // a Q register. Only used for intrinsics which end up calling polymorphic
+ // builtins.
+ bit isLaneQ = 0;
+
+ // Certain intrinsics have different names than their representative
+ // instructions. This field allows us to handle this correctly when we
+ // are generating tests.
+ string InstName = "";
+
+ // Certain intrinsics even though they are not a WOpInst or LOpInst,
+ // generate a WOpInst/LOpInst instruction (see below for definition
+ // of a WOpInst/LOpInst). For testing purposes we need to know
+ // this. Ex: vset_lane which outputs vmov instructions.
+ bit isHiddenWInst = 0;
+ bit isHiddenLInst = 0;
+}
+
+// The following instruction classes are implemented via builtins.
+// These declarations are 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> {}
+
+// The following instruction classes are implemented via operators
+// instead of builtins. As such these declarations are only used for
+// the purpose of generating tests.
+//
+// SOpInst: Instruction with signed/unsigned suffix (e.g., "s8",
+// "u8", "p8").
+// IOpInst: Instruction with generic integer suffix (e.g., "i8").
+// WOpInst: Instruction with bit size only suffix (e.g., "8").
+// LOpInst: Logical instruction with no bit size suffix.
+// NoTestOpInst: Intrinsic that has no corresponding instruction.
+class SOpInst<string n, string p, string t, Operation o> : Inst<n, p, t, o> {}
+class IOpInst<string n, string p, string t, Operation o> : Inst<n, p, t, o> {}
+class WOpInst<string n, string p, string t, Operation o> : Inst<n, p, t, o> {}
+class LOpInst<string n, string p, string t, Operation o> : Inst<n, p, t, o> {}
+class NoTestOpInst<string n, string p, string t, Operation o> : Inst<n, p, t, o> {}
+
+//===----------------------------------------------------------------------===//
+// Operations
+//===----------------------------------------------------------------------===//
+
+def OP_ADD : Op<(op "+", $p0, $p1)>;
+def OP_ADDL : Op<(op "+", (call "vmovl", $p0), (call "vmovl", $p1))>;
+def OP_ADDLHi : Op<(op "+", (call "vmovl_high", $p0),
+ (call "vmovl_high", $p1))>;
+def OP_ADDW : Op<(op "+", $p0, (call "vmovl", $p1))>;
+def OP_ADDWHi : Op<(op "+", $p0, (call "vmovl_high", $p1))>;
+def OP_SUB : Op<(op "-", $p0, $p1)>;
+def OP_SUBL : Op<(op "-", (call "vmovl", $p0), (call "vmovl", $p1))>;
+def OP_SUBLHi : Op<(op "-", (call "vmovl_high", $p0),
+ (call "vmovl_high", $p1))>;
+def OP_SUBW : Op<(op "-", $p0, (call "vmovl", $p1))>;
+def OP_SUBWHi : Op<(op "-", $p0, (call "vmovl_high", $p1))>;
+def OP_MUL : Op<(op "*", $p0, $p1)>;
+def OP_MLA : Op<(op "+", $p0, (op "*", $p1, $p2))>;
+def OP_MLAL : Op<(op "+", $p0, (call "vmull", $p1, $p2))>;
+def OP_MULLHi : Op<(call "vmull", (call "vget_high", $p0),
+ (call "vget_high", $p1))>;
+def OP_MULLHi_P64 : Op<(call "vmull",
+ (cast "poly64_t", (call "vget_high", $p0)),
+ (cast "poly64_t", (call "vget_high", $p1)))>;
+def OP_MULLHi_N : Op<(call "vmull_n", (call "vget_high", $p0), $p1)>;
+def OP_MLALHi : Op<(call "vmlal", $p0, (call "vget_high", $p1),
+ (call "vget_high", $p2))>;
+def OP_MLALHi_N : Op<(call "vmlal_n", $p0, (call "vget_high", $p1), $p2)>;
+def OP_MLS : Op<(op "-", $p0, (op "*", $p1, $p2))>;
+def OP_MLSL : Op<(op "-", $p0, (call "vmull", $p1, $p2))>;
+def OP_MLSLHi : Op<(call "vmlsl", $p0, (call "vget_high", $p1),
+ (call "vget_high", $p2))>;
+def OP_MLSLHi_N : Op<(call "vmlsl_n", $p0, (call "vget_high", $p1), $p2)>;
+def OP_MUL_N : Op<(op "*", $p0, (dup $p1))>;
+def OP_MLA_N : Op<(op "+", $p0, (op "*", $p1, (dup $p2)))>;
+def OP_MLS_N : Op<(op "-", $p0, (op "*", $p1, (dup $p2)))>;
+def OP_FMLA_N : Op<(call "vfma", $p0, $p1, (dup $p2))>;
+def OP_FMLS_N : Op<(call "vfms", $p0, $p1, (dup $p2))>;
+def OP_MLAL_N : Op<(op "+", $p0, (call "vmull", $p1, (dup $p2)))>;
+def OP_MLSL_N : Op<(op "-", $p0, (call "vmull", $p1, (dup $p2)))>;
+def OP_MUL_LN : Op<(op "*", $p0, (splat $p1, $p2))>;
+def OP_MULX_LN : Op<(call "vmulx", $p0, (splat $p1, $p2))>;
+def OP_MULL_LN : Op<(call "vmull", $p0, (splat $p1, $p2))>;
+def OP_MULLHi_LN: Op<(call "vmull", (call "vget_high", $p0), (splat $p1, $p2))>;
+def OP_MLA_LN : Op<(op "+", $p0, (op "*", $p1, (splat $p2, $p3)))>;
+def OP_MLS_LN : Op<(op "-", $p0, (op "*", $p1, (splat $p2, $p3)))>;
+def OP_MLAL_LN : Op<(op "+", $p0, (call "vmull", $p1, (splat $p2, $p3)))>;
+def OP_MLALHi_LN: Op<(op "+", $p0, (call "vmull", (call "vget_high", $p1),
+ (splat $p2, $p3)))>;
+def OP_MLSL_LN : Op<(op "-", $p0, (call "vmull", $p1, (splat $p2, $p3)))>;
+def OP_MLSLHi_LN : Op<(op "-", $p0, (call "vmull", (call "vget_high", $p1),
+ (splat $p2, $p3)))>;
+def OP_QDMULL_LN : Op<(call "vqdmull", $p0, (splat $p1, $p2))>;
+def OP_QDMULLHi_LN : Op<(call "vqdmull", (call "vget_high", $p0),
+ (splat $p1, $p2))>;
+def OP_QDMLAL_LN : Op<(call "vqdmlal", $p0, $p1, (splat $p2, $p3))>;
+def OP_QDMLALHi_LN : Op<(call "vqdmlal", $p0, (call "vget_high", $p1),
+ (splat $p2, $p3))>;
+def OP_QDMLSL_LN : Op<(call "vqdmlsl", $p0, $p1, (splat $p2, $p3))>;
+def OP_QDMLSLHi_LN : Op<(call "vqdmlsl", $p0, (call "vget_high", $p1),
+ (splat $p2, $p3))>;
+def OP_QDMULH_LN : Op<(call "vqdmulh", $p0, (splat $p1, $p2))>;
+def OP_QRDMULH_LN : Op<(call "vqrdmulh", $p0, (splat $p1, $p2))>;
+def OP_QRDMLAH : Op<(call "vqadd", $p0, (call "vqrdmulh", $p1, $p2))>;
+def OP_QRDMLSH : Op<(call "vqsub", $p0, (call "vqrdmulh", $p1, $p2))>;
+def OP_QRDMLAH_LN : Op<(call "vqadd", $p0, (call "vqrdmulh", $p1, (splat $p2, $p3)))>;
+def OP_QRDMLSH_LN : Op<(call "vqsub", $p0, (call "vqrdmulh", $p1, (splat $p2, $p3)))>;
+def OP_FMS_LN : Op<(call "vfma_lane", $p0, $p1, (op "-", $p2), $p3)>;
+def OP_FMS_LNQ : Op<(call "vfma_laneq", $p0, $p1, (op "-", $p2), $p3)>;
+def OP_TRN1 : Op<(shuffle $p0, $p1, (interleave (decimate mask0, 2),
+ (decimate mask1, 2)))>;
+def OP_ZIP1 : Op<(shuffle $p0, $p1, (lowhalf (interleave mask0, mask1)))>;
+def OP_UZP1 : Op<(shuffle $p0, $p1, (add (decimate mask0, 2),
+ (decimate mask1, 2)))>;
+def OP_TRN2 : Op<(shuffle $p0, $p1, (interleave
+ (decimate (rotl mask0, 1), 2),
+ (decimate (rotl mask1, 1), 2)))>;
+def OP_ZIP2 : Op<(shuffle $p0, $p1, (highhalf (interleave mask0, mask1)))>;
+def OP_UZP2 : Op<(shuffle $p0, $p1, (add (decimate (rotl mask0, 1), 2),
+ (decimate (rotl mask1, 1), 2)))>;
+def OP_EQ : Op<(cast "R", (op "==", $p0, $p1))>;
+def OP_GE : Op<(cast "R", (op ">=", $p0, $p1))>;
+def OP_LE : Op<(cast "R", (op "<=", $p0, $p1))>;
+def OP_GT : Op<(cast "R", (op ">", $p0, $p1))>;
+def OP_LT : Op<(cast "R", (op "<", $p0, $p1))>;
+def OP_NEG : Op<(op "-", $p0)>;
+def OP_NOT : Op<(op "~", $p0)>;
+def OP_AND : Op<(op "&", $p0, $p1)>;
+def OP_OR : Op<(op "|", $p0, $p1)>;
+def OP_XOR : Op<(op "^", $p0, $p1)>;
+def OP_ANDN : Op<(op "&", $p0, (op "~", $p1))>;
+def OP_ORN : Op<(op "|", $p0, (op "~", $p1))>;
+def OP_CAST : Op<(cast "R", $p0)>;
+def OP_HI : Op<(shuffle $p0, $p0, (highhalf mask0))>;
+def OP_LO : Op<(shuffle $p0, $p0, (lowhalf mask0))>;
+def OP_CONC : Op<(shuffle $p0, $p1, (add mask0, mask1))>;
+def OP_DUP : Op<(dup $p0)>;
+def OP_DUP_LN : Op<(splat $p0, $p1)>;
+def OP_SEL : Op<(cast "R", (op "|",
+ (op "&", $p0, (cast $p0, $p1)),
+ (op "&", (op "~", $p0), (cast $p0, $p2))))>;
+def OP_REV16 : Op<(shuffle $p0, $p0, (rev 16, mask0))>;
+def OP_REV32 : Op<(shuffle $p0, $p0, (rev 32, mask0))>;
+def OP_REV64 : Op<(shuffle $p0, $p0, (rev 64, mask0))>;
+def OP_XTN : Op<(call "vcombine", $p0, (call "vmovn", $p1))>;
+def OP_SQXTUN : Op<(call "vcombine", (cast $p0, "U", $p0),
+ (call "vqmovun", $p1))>;
+def OP_QXTN : Op<(call "vcombine", $p0, (call "vqmovn", $p1))>;
+def OP_VCVT_NA_HI_F16 : Op<(call "vcombine", $p0, (call "vcvt_f16_f32", $p1))>;
+def OP_VCVT_NA_HI_F32 : Op<(call "vcombine", $p0, (call "vcvt_f32_f64", $p1))>;
+def OP_VCVT_EX_HI_F32 : Op<(call "vcvt_f32_f16", (call "vget_high", $p0))>;
+def OP_VCVT_EX_HI_F64 : Op<(call "vcvt_f64_f32", (call "vget_high", $p0))>;
+def OP_VCVTX_HI : Op<(call "vcombine", $p0, (call "vcvtx_f32", $p1))>;
+def OP_REINT : Op<(cast "R", $p0)>;
+def OP_ADDHNHi : Op<(call "vcombine", $p0, (call "vaddhn", $p1, $p2))>;
+def OP_RADDHNHi : Op<(call "vcombine", $p0, (call "vraddhn", $p1, $p2))>;
+def OP_SUBHNHi : Op<(call "vcombine", $p0, (call "vsubhn", $p1, $p2))>;
+def OP_RSUBHNHi : Op<(call "vcombine", $p0, (call "vrsubhn", $p1, $p2))>;
+def OP_ABDL : Op<(cast "R", (call "vmovl", (cast $p0, "U",
+ (call "vabd", $p0, $p1))))>;
+def OP_ABDLHi : Op<(call "vabdl", (call "vget_high", $p0),
+ (call "vget_high", $p1))>;
+def OP_ABA : Op<(op "+", $p0, (call "vabd", $p1, $p2))>;
+def OP_ABAL : Op<(op "+", $p0, (call "vabdl", $p1, $p2))>;
+def OP_ABALHi : Op<(call "vabal", $p0, (call "vget_high", $p1),
+ (call "vget_high", $p2))>;
+def OP_QDMULLHi : Op<(call "vqdmull", (call "vget_high", $p0),
+ (call "vget_high", $p1))>;
+def OP_QDMULLHi_N : Op<(call "vqdmull_n", (call "vget_high", $p0), $p1)>;
+def OP_QDMLALHi : Op<(call "vqdmlal", $p0, (call "vget_high", $p1),
+ (call "vget_high", $p2))>;
+def OP_QDMLALHi_N : Op<(call "vqdmlal_n", $p0, (call "vget_high", $p1), $p2)>;
+def OP_QDMLSLHi : Op<(call "vqdmlsl", $p0, (call "vget_high", $p1),
+ (call "vget_high", $p2))>;
+def OP_QDMLSLHi_N : Op<(call "vqdmlsl_n", $p0, (call "vget_high", $p1), $p2)>;
+def OP_DIV : Op<(op "/", $p0, $p1)>;
+def OP_LONG_HI : Op<(cast "R", (call (name_replace "_high_", "_"),
+ (call "vget_high", $p0), $p1))>;
+def OP_NARROW_HI : Op<(cast "R", (call "vcombine",
+ (cast "R", "H", $p0),
+ (cast "R", "H",
+ (call (name_replace "_high_", "_"),
+ $p1, $p2))))>;
+def OP_MOVL_HI : LOp<[(save_temp $a1, (call "vget_high", $p0)),
+ (cast "R",
+ (call "vshll_n", $a1, (literal "int32_t", "0")))]>;
+def OP_COPY_LN : Op<(call "vset_lane", (call "vget_lane", $p2, $p3), $p0, $p1)>;
+def OP_SCALAR_MUL_LN : Op<(op "*", $p0, (call "vget_lane", $p1, $p2))>;
+def OP_SCALAR_MULX_LN : Op<(call "vmulx", $p0, (call "vget_lane", $p1, $p2))>;
+def OP_SCALAR_VMULX_LN : LOp<[(save_temp $x, (call "vget_lane", $p0,
+ (literal "int32_t", "0"))),
+ (save_temp $y, (call "vget_lane", $p1, $p2)),
+ (save_temp $z, (call "vmulx", $x, $y)),
+ (call "vset_lane", $z, $p0, $p2)]>;
+def OP_SCALAR_VMULX_LNQ : LOp<[(save_temp $x, (call "vget_lane", $p0,
+ (literal "int32_t", "0"))),
+ (save_temp $y, (call "vget_lane", $p1, $p2)),
+ (save_temp $z, (call "vmulx", $x, $y)),
+ (call "vset_lane", $z, $p0, (literal "int32_t",
+ "0"))]>;
+class ScalarMulOp<string opname> :
+ Op<(call opname, $p0, (call "vget_lane", $p1, $p2))>;
+
+def OP_SCALAR_QDMULL_LN : ScalarMulOp<"vqdmull">;
+def OP_SCALAR_QDMULH_LN : ScalarMulOp<"vqdmulh">;
+def OP_SCALAR_QRDMULH_LN : ScalarMulOp<"vqrdmulh">;
+
+def OP_SCALAR_QRDMLAH_LN : Op<(call "vqadd", $p0, (call "vqrdmulh", $p1,
+ (call "vget_lane", $p2, $p3)))>;
+def OP_SCALAR_QRDMLSH_LN : Op<(call "vqsub", $p0, (call "vqrdmulh", $p1,
+ (call "vget_lane", $p2, $p3)))>;
+
+def OP_SCALAR_HALF_GET_LN : Op<(bitcast "float16_t",
+ (call "vget_lane",
+ (bitcast "int16x4_t", $p0), $p1))>;
+def OP_SCALAR_HALF_GET_LNQ : Op<(bitcast "float16_t",
+ (call "vget_lane",
+ (bitcast "int16x8_t", $p0), $p1))>;
+def OP_SCALAR_HALF_SET_LN : Op<(bitcast "float16x4_t",
+ (call "vset_lane",
+ (bitcast "int16_t", $p0),
+ (bitcast "int16x4_t", $p1), $p2))>;
+def OP_SCALAR_HALF_SET_LNQ : Op<(bitcast "float16x8_t",
+ (call "vset_lane",
+ (bitcast "int16_t", $p0),
+ (bitcast "int16x8_t", $p1), $p2))>;
+
+//===----------------------------------------------------------------------===//
+// Instructions
+//===----------------------------------------------------------------------===//
+
+////////////////////////////////////////////////////////////////////////////////
+// E.3.1 Addition
+def VADD : IOpInst<"vadd", "ddd",
+ "csilfUcUsUiUlQcQsQiQlQfQUcQUsQUiQUl", OP_ADD>;
+def VADDL : SOpInst<"vaddl", "wdd", "csiUcUsUi", OP_ADDL>;
+def VADDW : SOpInst<"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 : IOpInst<"vmul", "ddd", "csifUcUsUiQcQsQiQfQUcQUsQUi", OP_MUL>;
+def VMULP : SInst<"vmul", "ddd", "PcQPc">;
+def VMLA : IOpInst<"vmla", "dddd", "csifUcUsUiQcQsQiQfQUcQUsQUi", OP_MLA>;
+def VMLAL : SOpInst<"vmlal", "wwdd", "csiUcUsUi", OP_MLAL>;
+def VMLS : IOpInst<"vmls", "dddd", "csifUcUsUiQcQsQiQfQUcQUsQUi", OP_MLS>;
+def VMLSL : SOpInst<"vmlsl", "wwdd", "csiUcUsUi", OP_MLSL>;
+def VQDMULH : SInst<"vqdmulh", "ddd", "siQsQi">;
+def VQRDMULH : SInst<"vqrdmulh", "ddd", "siQsQi">;
+
+let ArchGuard = "defined(__ARM_FEATURE_QRDMX)" in {
+def VQRDMLAH : SOpInst<"vqrdmlah", "dddd", "siQsQi", OP_QRDMLAH>;
+def VQRDMLSH : SOpInst<"vqrdmlsh", "dddd", "siQsQi", OP_QRDMLSH>;
+}
+
+def VQDMLAL : SInst<"vqdmlal", "wwdd", "si">;
+def VQDMLSL : SInst<"vqdmlsl", "wwdd", "si">;
+def VMULL : SInst<"vmull", "wdd", "csiUcUsUiPc">;
+def VQDMULL : SInst<"vqdmull", "wdd", "si">;
+
+////////////////////////////////////////////////////////////////////////////////
+// E.3.3 Subtraction
+def VSUB : IOpInst<"vsub", "ddd",
+ "csilfUcUsUiUlQcQsQiQlQfQUcQUsQUiQUl", OP_SUB>;
+def VSUBL : SOpInst<"vsubl", "wdd", "csiUcUsUi", OP_SUBL>;
+def VSUBW : SOpInst<"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 : IOpInst<"vceq", "udd", "csifUcUsUiPcQcQsQiQfQUcQUsQUiQPc", OP_EQ>;
+def VCGE : SOpInst<"vcge", "udd", "csifUcUsUiQcQsQiQfQUcQUsQUi", OP_GE>;
+let InstName = "vcge" in
+def VCLE : SOpInst<"vcle", "udd", "csifUcUsUiQcQsQiQfQUcQUsQUi", OP_LE>;
+def VCGT : SOpInst<"vcgt", "udd", "csifUcUsUiQcQsQiQfQUcQUsQUi", OP_GT>;
+let InstName = "vcgt" in
+def VCLT : SOpInst<"vclt", "udd", "csifUcUsUiQcQsQiQfQUcQUsQUi", OP_LT>;
+let InstName = "vacge" in {
+def VCAGE : IInst<"vcage", "udd", "fQf">;
+def VCALE : IInst<"vcale", "udd", "fQf">;
+}
+let InstName = "vacgt" in {
+def VCAGT : IInst<"vcagt", "udd", "fQf">;
+def VCALT : IInst<"vcalt", "udd", "fQf">;
+}
+def VTST : WInst<"vtst", "udd", "csiUcUsUiPcPsQcQsQiQUcQUsQUiQPcQPs">;
+
+////////////////////////////////////////////////////////////////////////////////
+// E.3.5 Absolute Difference
+def VABD : SInst<"vabd", "ddd", "csiUcUsUifQcQsQiQUcQUsQUiQf">;
+def VABDL : SOpInst<"vabdl", "wdd", "csiUcUsUi", OP_ABDL>;
+def VABA : SOpInst<"vaba", "dddd", "csiUcUsUiQcQsQiQUcQUsQUi", OP_ABA>;
+def VABAL : SOpInst<"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 Pairwise 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
+let InstName = "vmov" in
+def VGET_LANE : IInst<"vget_lane", "sdi",
+ "UcUsUicsiPcPsfQUcQUsQUiQcQsQiQPcQPsQflUlQlQUl">;
+
+////////////////////////////////////////////////////////////////////////////////
+// E.3.17 Set lanes within a vector
+let InstName = "vmov" in
+def VSET_LANE : IInst<"vset_lane", "dsdi",
+ "UcUsUicsiPcPsfQUcQUsQUiQcQsQiQPcQPsQflUlQlQUl">;
+
+////////////////////////////////////////////////////////////////////////////////
+// E.3.18 Initialize a vector from bit pattern
+def VCREATE : NoTestOpInst<"vcreate", "dl", "csihfUcUsUiUlPcPsl", OP_CAST> {
+ let BigEndianSafe = 1;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// E.3.19 Set all lanes to same value
+let InstName = "vmov" in {
+def VDUP_N : WOpInst<"vdup_n", "ds",
+ "UcUsUicsiPcPshfQUcQUsQUiQcQsQiQPcQPsQhQflUlQlQUl",
+ OP_DUP>;
+def VMOV_N : WOpInst<"vmov_n", "ds",
+ "UcUsUicsiPcPshfQUcQUsQUiQcQsQiQPcQPsQhQflUlQlQUl",
+ OP_DUP>;
+}
+let InstName = "" in
+def VDUP_LANE: WOpInst<"vdup_lane", "dgi",
+ "UcUsUicsiPcPsfQUcQUsQUiQcQsQiQPcQPsQflUlQlQUl",
+ OP_DUP_LN>;
+
+////////////////////////////////////////////////////////////////////////////////
+// E.3.20 Combining vectors
+def VCOMBINE : NoTestOpInst<"vcombine", "kdd", "csilhfUcUsUiUlPcPs", OP_CONC>;
+
+////////////////////////////////////////////////////////////////////////////////
+// E.3.21 Splitting vectors
+let InstName = "vmov" in {
+def VGET_HIGH : NoTestOpInst<"vget_high", "dk", "csilhfUcUsUiUlPcPs", OP_HI>;
+def VGET_LOW : NoTestOpInst<"vget_low", "dk", "csilhfUcUsUiUlPcPs", OP_LO>;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// E.3.22 Converting vectors
+
+def VCVT_F16_F32 : SInst<"vcvt_f16_f32", "md", "Hf">;
+def VCVT_F32_F16 : SInst<"vcvt_f32_f16", "wd", "h">;
+
+def VCVT_S32 : SInst<"vcvt_s32", "xd", "fQf">;
+def VCVT_U32 : SInst<"vcvt_u32", "ud", "fQf">;
+def VCVT_F32 : SInst<"vcvt_f32", "fd", "iUiQiQUi">;
+let isVCVT_N = 1 in {
+def VCVT_N_S32 : SInst<"vcvt_n_s32", "xdi", "fQf">;
+def VCVT_N_U32 : SInst<"vcvt_n_u32", "udi", "fQf">;
+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
+let InstName = "vtbl" in {
+def VTBL1 : WInst<"vtbl1", "ddt", "UccPc">;
+def VTBL2 : WInst<"vtbl2", "d2t", "UccPc">;
+def VTBL3 : WInst<"vtbl3", "d3t", "UccPc">;
+def VTBL4 : WInst<"vtbl4", "d4t", "UccPc">;
+}
+let InstName = "vtbx" in {
+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 : IOpInst<"vmla_lane", "dddgi",
+ "siUsUifQsQiQUsQUiQf", OP_MLA_LN>;
+def VMLAL_LANE : SOpInst<"vmlal_lane", "wwddi", "siUsUi", OP_MLAL_LN>;
+def VQDMLAL_LANE : SOpInst<"vqdmlal_lane", "wwddi", "si", OP_QDMLAL_LN>;
+def VMLS_LANE : IOpInst<"vmls_lane", "dddgi",
+ "siUsUifQsQiQUsQUiQf", OP_MLS_LN>;
+def VMLSL_LANE : SOpInst<"vmlsl_lane", "wwddi", "siUsUi", OP_MLSL_LN>;
+def VQDMLSL_LANE : SOpInst<"vqdmlsl_lane", "wwddi", "si", OP_QDMLSL_LN>;
+def VMUL_N : IOpInst<"vmul_n", "dds", "sifUsUiQsQiQfQUsQUi", OP_MUL_N>;
+def VMUL_LANE : IOpInst<"vmul_lane", "ddgi",
+ "sifUsUiQsQiQfQUsQUi", OP_MUL_LN>;
+def VMULL_N : SInst<"vmull_n", "wda", "siUsUi">;
+def VMULL_LANE : SOpInst<"vmull_lane", "wddi", "siUsUi", OP_MULL_LN>;
+def VQDMULL_N : SInst<"vqdmull_n", "wda", "si">;
+def VQDMULL_LANE : SOpInst<"vqdmull_lane", "wddi", "si", OP_QDMULL_LN>;
+def VQDMULH_N : SInst<"vqdmulh_n", "dda", "siQsQi">;
+def VQDMULH_LANE : SOpInst<"vqdmulh_lane", "ddgi", "siQsQi", OP_QDMULH_LN>;
+def VQRDMULH_N : SInst<"vqrdmulh_n", "dda", "siQsQi">;
+def VQRDMULH_LANE : SOpInst<"vqrdmulh_lane", "ddgi", "siQsQi", OP_QRDMULH_LN>;
+
+let ArchGuard = "defined(__ARM_FEATURE_QRDMX)" in {
+def VQRDMLAH_LANE : SOpInst<"vqrdmlah_lane", "dddgi", "siQsQi", OP_QRDMLAH_LN>;
+def VQRDMLSH_LANE : SOpInst<"vqrdmlsh_lane", "dddgi", "siQsQi", OP_QRDMLSH_LN>;
+}
+
+def VMLA_N : IOpInst<"vmla_n", "ddda", "siUsUifQsQiQUsQUiQf", OP_MLA_N>;
+def VMLAL_N : SOpInst<"vmlal_n", "wwda", "siUsUi", OP_MLAL_N>;
+def VQDMLAL_N : SInst<"vqdmlal_n", "wwda", "si">;
+def VMLS_N : IOpInst<"vmls_n", "ddds", "siUsUifQsQiQUsQUiQf", OP_MLS_N>;
+def VMLSL_N : SOpInst<"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
+def VREV64 : WOpInst<"vrev64", "dd", "csiUcUsUiPcPsfQcQsQiQUcQUsQUiQPcQPsQf",
+ OP_REV64>;
+def VREV32 : WOpInst<"vrev32", "dd", "csUcUsPcPsQcQsQUcQUsQPcQPs", OP_REV32>;
+def VREV16 : WOpInst<"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 : SOpInst<"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 : LOpInst<"vmvn", "dd", "csiUcUsUiPcQcQsQiQUcQUsQUiQPc", OP_NOT>;
+def VAND : LOpInst<"vand", "ddd", "csilUcUsUiUlQcQsQiQlQUcQUsQUiQUl", OP_AND>;
+def VORR : LOpInst<"vorr", "ddd", "csilUcUsUiUlQcQsQiQlQUcQUsQUiQUl", OP_OR>;
+def VEOR : LOpInst<"veor", "ddd", "csilUcUsUiUlQcQsQiQlQUcQUsQUiQUl", OP_XOR>;
+def VBIC : LOpInst<"vbic", "ddd", "csilUcUsUiUlQcQsQiQlQUcQUsQUiQUl", OP_ANDN>;
+def VORN : LOpInst<"vorn", "ddd", "csilUcUsUiUlQcQsQiQlQUcQUsQUiQUl", OP_ORN>;
+let isHiddenLInst = 1 in
+def VBSL : SInst<"vbsl", "dudd",
+ "csilUcUsUiUlfPcPsQcQsQiQlQUcQUsQUiQUlQfQPcQPs">;
+
+////////////////////////////////////////////////////////////////////////////////
+// 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
+ : NoTestOpInst<"vreinterpret", "dd",
+ "csilUcUsUiUlhfPcPsQcQsQiQlQUcQUsQUiQUlQhQfQPcQPs", OP_REINT> {
+ let CartesianProductOfTypes = 1;
+ let ArchGuard = "!defined(__aarch64__)";
+ let BigEndianSafe = 1;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// Vector fused multiply-add operations
+
+def VFMA : SInst<"vfma", "dddd", "fQf">;
+
+////////////////////////////////////////////////////////////////////////////////
+// fp16 vector operations
+def SCALAR_HALF_GET_LANE : IOpInst<"vget_lane", "sdi", "h", OP_SCALAR_HALF_GET_LN>;
+def SCALAR_HALF_SET_LANE : IOpInst<"vset_lane", "dsdi", "h", OP_SCALAR_HALF_SET_LN>;
+def SCALAR_HALF_GET_LANEQ : IOpInst<"vget_lane", "sdi", "Qh", OP_SCALAR_HALF_GET_LNQ>;
+def SCALAR_HALF_SET_LANEQ : IOpInst<"vset_lane", "dsdi", "Qh", OP_SCALAR_HALF_SET_LNQ>;
+
+////////////////////////////////////////////////////////////////////////////////
+// AArch64 Intrinsics
+
+let ArchGuard = "defined(__aarch64__)" in {
+
+////////////////////////////////////////////////////////////////////////////////
+// Load/Store
+def LD1 : WInst<"vld1", "dc", "dQdPlQPl">;
+def LD2 : WInst<"vld2", "2c", "QUlQldQdPlQPl">;
+def LD3 : WInst<"vld3", "3c", "QUlQldQdPlQPl">;
+def LD4 : WInst<"vld4", "4c", "QUlQldQdPlQPl">;
+def ST1 : WInst<"vst1", "vpd", "dQdPlQPl">;
+def ST2 : WInst<"vst2", "vp2", "QUlQldQdPlQPl">;
+def ST3 : WInst<"vst3", "vp3", "QUlQldQdPlQPl">;
+def ST4 : WInst<"vst4", "vp4", "QUlQldQdPlQPl">;
+
+def LD1_X2 : WInst<"vld1_x2", "2c",
+ "QUcQUsQUiQcQsQiQhQfQPcQPsUcUsUiUlcsilhfPcPsQUlQldQdPlQPl">;
+def LD3_x3 : WInst<"vld1_x3", "3c",
+ "QUcQUsQUiQcQsQiQhQfQPcQPsUcUsUiUlcsilhfPcPsQUlQldQdPlQPl">;
+def LD4_x4 : WInst<"vld1_x4", "4c",
+ "QUcQUsQUiQcQsQiQhQfQPcQPsUcUsUiUlcsilhfPcPsQUlQldQdPlQPl">;
+
+def ST1_X2 : WInst<"vst1_x2", "vp2",
+ "QUcQUsQUiQcQsQiQhQfQPcQPsUcUsUiUlcsilhfPcPsQUlQldQdPlQPl">;
+def ST1_X3 : WInst<"vst1_x3", "vp3",
+ "QUcQUsQUiQcQsQiQhQfQPcQPsUcUsUiUlcsilhfPcPsQUlQldQdPlQPl">;
+def ST1_X4 : WInst<"vst1_x4", "vp4",
+ "QUcQUsQUiQcQsQiQhQfQPcQPsUcUsUiUlcsilhfPcPsQUlQldQdPlQPl">;
+
+def LD1_LANE : WInst<"vld1_lane", "dcdi", "dQdPlQPl">;
+def LD2_LANE : WInst<"vld2_lane", "2c2i", "lUlQcQUcQPcQlQUldQdPlQPl">;
+def LD3_LANE : WInst<"vld3_lane", "3c3i", "lUlQcQUcQPcQlQUldQdPlQPl">;
+def LD4_LANE : WInst<"vld4_lane", "4c4i", "lUlQcQUcQPcQlQUldQdPlQPl">;
+def ST1_LANE : WInst<"vst1_lane", "vpdi", "dQdPlQPl">;
+def ST2_LANE : WInst<"vst2_lane", "vp2i", "lUlQcQUcQPcQlQUldQdPlQPl">;
+def ST3_LANE : WInst<"vst3_lane", "vp3i", "lUlQcQUcQPcQlQUldQdPlQPl">;
+def ST4_LANE : WInst<"vst4_lane", "vp4i", "lUlQcQUcQPcQlQUldQdPlQPl">;
+
+def LD1_DUP : WInst<"vld1_dup", "dc", "dQdPlQPl">;
+def LD2_DUP : WInst<"vld2_dup", "2c",
+ "QUcQUsQUiQUlQcQsQiQlQhQfQdQPcQPsQPldPl">;
+def LD3_DUP : WInst<"vld3_dup", "3c",
+ "QUcQUsQUiQUlQcQsQiQlQhQfQdQPcQPsQPldPl">;
+def LD4_DUP : WInst<"vld4_dup", "4c",
+ "QUcQUsQUiQUlQcQsQiQlQhQfQdQPcQPsQPldPl">;
+
+def VLDRQ : WInst<"vldrq", "sc", "Pk">;
+def VSTRQ : WInst<"vstrq", "vps", "Pk">;
+
+////////////////////////////////////////////////////////////////////////////////
+// Addition
+def ADD : IOpInst<"vadd", "ddd", "dQd", OP_ADD>;
+
+////////////////////////////////////////////////////////////////////////////////
+// Subtraction
+def SUB : IOpInst<"vsub", "ddd", "dQd", OP_SUB>;
+
+////////////////////////////////////////////////////////////////////////////////
+// Multiplication
+def MUL : IOpInst<"vmul", "ddd", "dQd", OP_MUL>;
+def MLA : IOpInst<"vmla", "dddd", "dQd", OP_MLA>;
+def MLS : IOpInst<"vmls", "dddd", "dQd", OP_MLS>;
+
+////////////////////////////////////////////////////////////////////////////////
+// Multiplication Extended
+def MULX : SInst<"vmulx", "ddd", "fdQfQd">;
+
+////////////////////////////////////////////////////////////////////////////////
+// Division
+def FDIV : IOpInst<"vdiv", "ddd", "fdQfQd", OP_DIV>;
+
+////////////////////////////////////////////////////////////////////////////////
+// Vector fused multiply-add operations
+def FMLA : SInst<"vfma", "dddd", "dQd">;
+def FMLS : SInst<"vfms", "dddd", "fdQfQd">;
+
+////////////////////////////////////////////////////////////////////////////////
+// MUL, MLA, MLS, FMA, FMS definitions with scalar argument
+def VMUL_N_A64 : IOpInst<"vmul_n", "dds", "Qd", OP_MUL_N>;
+
+def FMLA_N : SOpInst<"vfma_n", "ddds", "fQfQd", OP_FMLA_N>;
+def FMLS_N : SOpInst<"vfms_n", "ddds", "fQfQd", OP_FMLS_N>;
+
+def MLA_N : SOpInst<"vmla_n", "ddds", "Qd", OP_MLA_N>;
+def MLS_N : SOpInst<"vmls_n", "ddds", "Qd", OP_MLS_N>;
+
+////////////////////////////////////////////////////////////////////////////////
+// Logical operations
+def BSL : SInst<"vbsl", "dudd", "dPlQdQPl">;
+
+////////////////////////////////////////////////////////////////////////////////
+// Absolute Difference
+def ABD : SInst<"vabd", "ddd", "dQd">;
+
+////////////////////////////////////////////////////////////////////////////////
+// saturating absolute/negate
+def ABS : SInst<"vabs", "dd", "dQdlQl">;
+def QABS : SInst<"vqabs", "dd", "lQl">;
+def NEG : SOpInst<"vneg", "dd", "dlQdQl", OP_NEG>;
+def QNEG : SInst<"vqneg", "dd", "lQl">;
+
+////////////////////////////////////////////////////////////////////////////////
+// Signed Saturating Accumulated of Unsigned Value
+def SUQADD : SInst<"vuqadd", "ddd", "csilQcQsQiQl">;
+
+////////////////////////////////////////////////////////////////////////////////
+// Unsigned Saturating Accumulated of Signed Value
+def USQADD : SInst<"vsqadd", "ddd", "UcUsUiUlQUcQUsQUiQUl">;
+
+////////////////////////////////////////////////////////////////////////////////
+// Reciprocal/Sqrt
+def FRECPS : IInst<"vrecps", "ddd", "dQd">;
+def FRSQRTS : IInst<"vrsqrts", "ddd", "dQd">;
+def FRECPE : SInst<"vrecpe", "dd", "dQd">;
+def FRSQRTE : SInst<"vrsqrte", "dd", "dQd">;
+def FSQRT : SInst<"vsqrt", "dd", "fdQfQd">;
+
+////////////////////////////////////////////////////////////////////////////////
+// bitwise reverse
+def RBIT : IInst<"vrbit", "dd", "cUcPcQcQUcQPc">;
+
+////////////////////////////////////////////////////////////////////////////////
+// Integer extract and narrow to high
+def XTN2 : SOpInst<"vmovn_high", "qhk", "silUsUiUl", OP_XTN>;
+
+////////////////////////////////////////////////////////////////////////////////
+// Signed integer saturating extract and unsigned narrow to high
+def SQXTUN2 : SOpInst<"vqmovun_high", "qhk", "sil", OP_SQXTUN>;
+
+////////////////////////////////////////////////////////////////////////////////
+// Integer saturating extract and narrow to high
+def QXTN2 : SOpInst<"vqmovn_high", "qhk", "silUsUiUl", OP_QXTN>;
+
+////////////////////////////////////////////////////////////////////////////////
+// Converting vectors
+
+def VCVT_F32_F64 : SInst<"vcvt_f32_f64", "md", "Qd">;
+def VCVT_F64_F32 : SInst<"vcvt_f64_f32", "wd", "f">;
+
+def VCVT_S64 : SInst<"vcvt_s64", "xd", "dQd">;
+def VCVT_U64 : SInst<"vcvt_u64", "ud", "dQd">;
+def VCVT_F64 : SInst<"vcvt_f64", "Fd", "lUlQlQUl">;
+
+def VCVT_HIGH_F16_F32 : SOpInst<"vcvt_high_f16", "hmj", "Hf", OP_VCVT_NA_HI_F16>;
+def VCVT_HIGH_F32_F16 : SOpInst<"vcvt_high_f32", "wk", "h", OP_VCVT_EX_HI_F32>;
+def VCVT_HIGH_F32_F64 : SOpInst<"vcvt_high_f32", "qfj", "d", OP_VCVT_NA_HI_F32>;
+def VCVT_HIGH_F64_F32 : SOpInst<"vcvt_high_f64", "wj", "f", OP_VCVT_EX_HI_F64>;
+
+def VCVTX_F32_F64 : SInst<"vcvtx_f32", "fj", "d">;
+def VCVTX_HIGH_F32_F64 : SOpInst<"vcvtx_high_f32", "qfj", "d", OP_VCVTX_HI>;
+
+////////////////////////////////////////////////////////////////////////////////
+// Comparison
+def FCAGE : IInst<"vcage", "udd", "dQd">;
+def FCAGT : IInst<"vcagt", "udd", "dQd">;
+def FCALE : IInst<"vcale", "udd", "dQd">;
+def FCALT : IInst<"vcalt", "udd", "dQd">;
+def CMTST : WInst<"vtst", "udd", "lUlPlQlQUlQPl">;
+def CFMEQ : SOpInst<"vceq", "udd", "lUldQdQlQUlPlQPl", OP_EQ>;
+def CFMGE : SOpInst<"vcge", "udd", "lUldQdQlQUl", OP_GE>;
+def CFMLE : SOpInst<"vcle", "udd", "lUldQdQlQUl", OP_LE>;
+def CFMGT : SOpInst<"vcgt", "udd", "lUldQdQlQUl", OP_GT>;
+def CFMLT : SOpInst<"vclt", "udd", "lUldQdQlQUl", OP_LT>;
+
+def CMEQ : SInst<"vceqz", "ud",
+ "csilfUcUsUiUlPcPsPlQcQsQiQlQfQUcQUsQUiQUlQPcQPsdQdQPl">;
+def CMGE : SInst<"vcgez", "ud", "csilfdQcQsQiQlQfQd">;
+def CMLE : SInst<"vclez", "ud", "csilfdQcQsQiQlQfQd">;
+def CMGT : SInst<"vcgtz", "ud", "csilfdQcQsQiQlQfQd">;
+def CMLT : SInst<"vcltz", "ud", "csilfdQcQsQiQlQfQd">;
+
+////////////////////////////////////////////////////////////////////////////////
+// Max/Min Integer
+def MAX : SInst<"vmax", "ddd", "dQd">;
+def MIN : SInst<"vmin", "ddd", "dQd">;
+
+////////////////////////////////////////////////////////////////////////////////
+// Pairwise Max/Min
+def MAXP : SInst<"vpmax", "ddd", "QcQsQiQUcQUsQUiQfQd">;
+def MINP : SInst<"vpmin", "ddd", "QcQsQiQUcQUsQUiQfQd">;
+
+////////////////////////////////////////////////////////////////////////////////
+// Pairwise MaxNum/MinNum Floating Point
+def FMAXNMP : SInst<"vpmaxnm", "ddd", "fQfQd">;
+def FMINNMP : SInst<"vpminnm", "ddd", "fQfQd">;
+
+////////////////////////////////////////////////////////////////////////////////
+// Pairwise Addition
+def ADDP : IInst<"vpadd", "ddd", "QcQsQiQlQUcQUsQUiQUlQfQd">;
+
+////////////////////////////////////////////////////////////////////////////////
+// Shifts by constant
+let isShift = 1 in {
+// Left shift long high
+def SHLL_HIGH_N : SOpInst<"vshll_high_n", "ndi", "HcHsHiHUcHUsHUi",
+ OP_LONG_HI>;
+
+////////////////////////////////////////////////////////////////////////////////
+def SRI_N : WInst<"vsri_n", "dddi", "PlQPl">;
+def SLI_N : WInst<"vsli_n", "dddi", "PlQPl">;
+
+// Right shift narrow high
+def SHRN_HIGH_N : IOpInst<"vshrn_high_n", "hmdi",
+ "HsHiHlHUsHUiHUl", OP_NARROW_HI>;
+def QSHRUN_HIGH_N : SOpInst<"vqshrun_high_n", "hmdi",
+ "HsHiHl", OP_NARROW_HI>;
+def RSHRN_HIGH_N : IOpInst<"vrshrn_high_n", "hmdi",
+ "HsHiHlHUsHUiHUl", OP_NARROW_HI>;
+def QRSHRUN_HIGH_N : SOpInst<"vqrshrun_high_n", "hmdi",
+ "HsHiHl", OP_NARROW_HI>;
+def QSHRN_HIGH_N : SOpInst<"vqshrn_high_n", "hmdi",
+ "HsHiHlHUsHUiHUl", OP_NARROW_HI>;
+def QRSHRN_HIGH_N : SOpInst<"vqrshrn_high_n", "hmdi",
+ "HsHiHlHUsHUiHUl", OP_NARROW_HI>;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// Converting vectors
+def VMOVL_HIGH : SOpInst<"vmovl_high", "nd", "HcHsHiHUcHUsHUi", OP_MOVL_HI>;
+
+let isVCVT_N = 1 in {
+def CVTF_N_F64 : SInst<"vcvt_n_f64", "Fdi", "lUlQlQUl">;
+def FCVTZS_N_S64 : SInst<"vcvt_n_s64", "xdi", "dQd">;
+def FCVTZS_N_U64 : SInst<"vcvt_n_u64", "udi", "dQd">;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// 3VDiff class using high 64-bit in operands
+def VADDL_HIGH : SOpInst<"vaddl_high", "wkk", "csiUcUsUi", OP_ADDLHi>;
+def VADDW_HIGH : SOpInst<"vaddw_high", "wwk", "csiUcUsUi", OP_ADDWHi>;
+def VSUBL_HIGH : SOpInst<"vsubl_high", "wkk", "csiUcUsUi", OP_SUBLHi>;
+def VSUBW_HIGH : SOpInst<"vsubw_high", "wwk", "csiUcUsUi", OP_SUBWHi>;
+
+def VABDL_HIGH : SOpInst<"vabdl_high", "wkk", "csiUcUsUi", OP_ABDLHi>;
+def VABAL_HIGH : SOpInst<"vabal_high", "wwkk", "csiUcUsUi", OP_ABALHi>;
+
+def VMULL_HIGH : SOpInst<"vmull_high", "wkk", "csiUcUsUiPc", OP_MULLHi>;
+def VMULL_HIGH_N : SOpInst<"vmull_high_n", "wks", "siUsUi", OP_MULLHi_N>;
+def VMLAL_HIGH : SOpInst<"vmlal_high", "wwkk", "csiUcUsUi", OP_MLALHi>;
+def VMLAL_HIGH_N : SOpInst<"vmlal_high_n", "wwks", "siUsUi", OP_MLALHi_N>;
+def VMLSL_HIGH : SOpInst<"vmlsl_high", "wwkk", "csiUcUsUi", OP_MLSLHi>;
+def VMLSL_HIGH_N : SOpInst<"vmlsl_high_n", "wwks", "siUsUi", OP_MLSLHi_N>;
+
+def VADDHN_HIGH : SOpInst<"vaddhn_high", "qhkk", "silUsUiUl", OP_ADDHNHi>;
+def VRADDHN_HIGH : SOpInst<"vraddhn_high", "qhkk", "silUsUiUl", OP_RADDHNHi>;
+def VSUBHN_HIGH : SOpInst<"vsubhn_high", "qhkk", "silUsUiUl", OP_SUBHNHi>;
+def VRSUBHN_HIGH : SOpInst<"vrsubhn_high", "qhkk", "silUsUiUl", OP_RSUBHNHi>;
+
+def VQDMULL_HIGH : SOpInst<"vqdmull_high", "wkk", "si", OP_QDMULLHi>;
+def VQDMULL_HIGH_N : SOpInst<"vqdmull_high_n", "wks", "si", OP_QDMULLHi_N>;
+def VQDMLAL_HIGH : SOpInst<"vqdmlal_high", "wwkk", "si", OP_QDMLALHi>;
+def VQDMLAL_HIGH_N : SOpInst<"vqdmlal_high_n", "wwks", "si", OP_QDMLALHi_N>;
+def VQDMLSL_HIGH : SOpInst<"vqdmlsl_high", "wwkk", "si", OP_QDMLSLHi>;
+def VQDMLSL_HIGH_N : SOpInst<"vqdmlsl_high_n", "wwks", "si", OP_QDMLSLHi_N>;
+def VMULL_P64 : SInst<"vmull", "rss", "Pl">;
+def VMULL_HIGH_P64 : SOpInst<"vmull_high", "rdd", "HPl", OP_MULLHi_P64>;
+
+
+////////////////////////////////////////////////////////////////////////////////
+// Extract or insert element from vector
+def GET_LANE : IInst<"vget_lane", "sdi", "dQdPlQPl">;
+def SET_LANE : IInst<"vset_lane", "dsdi", "dQdPlQPl">;
+def COPY_LANE : IOpInst<"vcopy_lane", "ddidi",
+ "csilUcUsUiUlPcPsPlfd", OP_COPY_LN>;
+def COPYQ_LANE : IOpInst<"vcopy_lane", "ddigi",
+ "QcQsQiQlQUcQUsQUiQUlQPcQPsQfQdQPl", OP_COPY_LN>;
+def COPY_LANEQ : IOpInst<"vcopy_laneq", "ddiki",
+ "csilPcPsPlUcUsUiUlfd", OP_COPY_LN>;
+def COPYQ_LANEQ : IOpInst<"vcopy_laneq", "ddidi",
+ "QcQsQiQlQUcQUsQUiQUlQPcQPsQfQdQPl", OP_COPY_LN>;
+
+////////////////////////////////////////////////////////////////////////////////
+// Set all lanes to same value
+def VDUP_LANE1: WOpInst<"vdup_lane", "dgi", "hdQhQdPlQPl", OP_DUP_LN>;
+def VDUP_LANE2: WOpInst<"vdup_laneq", "dji",
+ "csilUcUsUiUlPcPshfdQcQsQiQlQPcQPsQUcQUsQUiQUlQhQfQdPlQPl",
+ OP_DUP_LN>;
+def DUP_N : WOpInst<"vdup_n", "ds", "dQdPlQPl", OP_DUP>;
+def MOV_N : WOpInst<"vmov_n", "ds", "dQdPlQPl", OP_DUP>;
+
+////////////////////////////////////////////////////////////////////////////////
+def COMBINE : NoTestOpInst<"vcombine", "kdd", "dPl", OP_CONC>;
+
+////////////////////////////////////////////////////////////////////////////////
+//Initialize a vector from bit pattern
+def CREATE : NoTestOpInst<"vcreate", "dl", "dPl", OP_CAST> {
+ let BigEndianSafe = 1;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+
+def VMLA_LANEQ : IOpInst<"vmla_laneq", "dddji",
+ "siUsUifQsQiQUsQUiQf", OP_MLA_LN>;
+def VMLS_LANEQ : IOpInst<"vmls_laneq", "dddji",
+ "siUsUifQsQiQUsQUiQf", OP_MLS_LN>;
+
+def VFMA_LANE : IInst<"vfma_lane", "dddgi", "fdQfQd">;
+def VFMA_LANEQ : IInst<"vfma_laneq", "dddji", "fdQfQd"> {
+ let isLaneQ = 1;
+}
+def VFMS_LANE : IOpInst<"vfms_lane", "dddgi", "fdQfQd", OP_FMS_LN>;
+def VFMS_LANEQ : IOpInst<"vfms_laneq", "dddji", "fdQfQd", OP_FMS_LNQ>;
+
+def VMLAL_LANEQ : SOpInst<"vmlal_laneq", "wwdki", "siUsUi", OP_MLAL_LN>;
+def VMLAL_HIGH_LANE : SOpInst<"vmlal_high_lane", "wwkdi", "siUsUi",
+ OP_MLALHi_LN>;
+def VMLAL_HIGH_LANEQ : SOpInst<"vmlal_high_laneq", "wwkki", "siUsUi",
+ OP_MLALHi_LN>;
+def VMLSL_LANEQ : SOpInst<"vmlsl_laneq", "wwdki", "siUsUi", OP_MLSL_LN>;
+def VMLSL_HIGH_LANE : SOpInst<"vmlsl_high_lane", "wwkdi", "siUsUi",
+ OP_MLSLHi_LN>;
+def VMLSL_HIGH_LANEQ : SOpInst<"vmlsl_high_laneq", "wwkki", "siUsUi",
+ OP_MLSLHi_LN>;
+
+def VQDMLAL_LANEQ : SOpInst<"vqdmlal_laneq", "wwdki", "si", OP_QDMLAL_LN>;
+def VQDMLAL_HIGH_LANE : SOpInst<"vqdmlal_high_lane", "wwkdi", "si",
+ OP_QDMLALHi_LN>;
+def VQDMLAL_HIGH_LANEQ : SOpInst<"vqdmlal_high_laneq", "wwkki", "si",
+ OP_QDMLALHi_LN>;
+def VQDMLSL_LANEQ : SOpInst<"vqdmlsl_laneq", "wwdki", "si", OP_QDMLSL_LN>;
+def VQDMLSL_HIGH_LANE : SOpInst<"vqdmlsl_high_lane", "wwkdi", "si",
+ OP_QDMLSLHi_LN>;
+def VQDMLSL_HIGH_LANEQ : SOpInst<"vqdmlsl_high_laneq", "wwkki", "si",
+ OP_QDMLSLHi_LN>;
+
+// Newly add double parameter for vmul_lane in aarch64
+// Note: d type is handled by SCALAR_VMUL_LANE
+def VMUL_LANE_A64 : IOpInst<"vmul_lane", "ddgi", "Qd", OP_MUL_LN>;
+
+// Note: d type is handled by SCALAR_VMUL_LANEQ
+def VMUL_LANEQ : IOpInst<"vmul_laneq", "ddji",
+ "sifUsUiQsQiQUsQUiQfQd", OP_MUL_LN>;
+def VMULL_LANEQ : SOpInst<"vmull_laneq", "wdki", "siUsUi", OP_MULL_LN>;
+def VMULL_HIGH_LANE : SOpInst<"vmull_high_lane", "wkdi", "siUsUi",
+ OP_MULLHi_LN>;
+def VMULL_HIGH_LANEQ : SOpInst<"vmull_high_laneq", "wkki", "siUsUi",
+ OP_MULLHi_LN>;
+
+def VQDMULL_LANEQ : SOpInst<"vqdmull_laneq", "wdki", "si", OP_QDMULL_LN>;
+def VQDMULL_HIGH_LANE : SOpInst<"vqdmull_high_lane", "wkdi", "si",
+ OP_QDMULLHi_LN>;
+def VQDMULL_HIGH_LANEQ : SOpInst<"vqdmull_high_laneq", "wkki", "si",
+ OP_QDMULLHi_LN>;
+
+def VQDMULH_LANEQ : SOpInst<"vqdmulh_laneq", "ddji", "siQsQi", OP_QDMULH_LN>;
+def VQRDMULH_LANEQ : SOpInst<"vqrdmulh_laneq", "ddji", "siQsQi", OP_QRDMULH_LN>;
+
+let ArchGuard = "defined(__ARM_FEATURE_QRDMX) && defined(__aarch64__)" in {
+def VQRDMLAH_LANEQ : SOpInst<"vqrdmlah_laneq", "dddji", "siQsQi", OP_QRDMLAH_LN>;
+def VQRDMLSH_LANEQ : SOpInst<"vqrdmlsh_laneq", "dddji", "siQsQi", OP_QRDMLSH_LN>;
+}
+
+// Note: d type implemented by SCALAR_VMULX_LANE
+def VMULX_LANE : IOpInst<"vmulx_lane", "ddgi", "fQfQd", OP_MULX_LN>;
+// Note: d type is implemented by SCALAR_VMULX_LANEQ
+def VMULX_LANEQ : IOpInst<"vmulx_laneq", "ddji", "fQfQd", OP_MULX_LN>;
+
+////////////////////////////////////////////////////////////////////////////////
+// Across vectors class
+def VADDLV : SInst<"vaddlv", "rd", "csiUcUsUiQcQsQiQUcQUsQUi">;
+def VMAXV : SInst<"vmaxv", "sd", "csifUcUsUiQcQsQiQUcQUsQUiQfQd">;
+def VMINV : SInst<"vminv", "sd", "csifUcUsUiQcQsQiQUcQUsQUiQfQd">;
+def VADDV : SInst<"vaddv", "sd", "csifUcUsUiQcQsQiQUcQUsQUiQfQdQlQUl">;
+def FMAXNMV : SInst<"vmaxnmv", "sd", "fQfQd">;
+def FMINNMV : SInst<"vminnmv", "sd", "fQfQd">;
+
+////////////////////////////////////////////////////////////////////////////////
+// Newly added Vector Extract for f64
+def VEXT_A64 : WInst<"vext", "dddi", "dQdPlQPl">;
+
+////////////////////////////////////////////////////////////////////////////////
+// Crypto
+let ArchGuard = "__ARM_FEATURE_CRYPTO" in {
+def AESE : SInst<"vaese", "ddd", "QUc">;
+def AESD : SInst<"vaesd", "ddd", "QUc">;
+def AESMC : SInst<"vaesmc", "dd", "QUc">;
+def AESIMC : SInst<"vaesimc", "dd", "QUc">;
+
+def SHA1H : SInst<"vsha1h", "ss", "Ui">;
+def SHA1SU1 : SInst<"vsha1su1", "ddd", "QUi">;
+def SHA256SU0 : SInst<"vsha256su0", "ddd", "QUi">;
+
+def SHA1C : SInst<"vsha1c", "ddsd", "QUi">;
+def SHA1P : SInst<"vsha1p", "ddsd", "QUi">;
+def SHA1M : SInst<"vsha1m", "ddsd", "QUi">;
+def SHA1SU0 : SInst<"vsha1su0", "dddd", "QUi">;
+def SHA256H : SInst<"vsha256h", "dddd", "QUi">;
+def SHA256H2 : SInst<"vsha256h2", "dddd", "QUi">;
+def SHA256SU1 : SInst<"vsha256su1", "dddd", "QUi">;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// Float -> Int conversions with explicit rounding mode
+
+let ArchGuard = "__ARM_ARCH >= 8" in {
+def FCVTNS_S32 : SInst<"vcvtn_s32", "xd", "fQf">;
+def FCVTNU_S32 : SInst<"vcvtn_u32", "ud", "fQf">;
+def FCVTPS_S32 : SInst<"vcvtp_s32", "xd", "fQf">;
+def FCVTPU_S32 : SInst<"vcvtp_u32", "ud", "fQf">;
+def FCVTMS_S32 : SInst<"vcvtm_s32", "xd", "fQf">;
+def FCVTMU_S32 : SInst<"vcvtm_u32", "ud", "fQf">;
+def FCVTAS_S32 : SInst<"vcvta_s32", "xd", "fQf">;
+def FCVTAU_S32 : SInst<"vcvta_u32", "ud", "fQf">;
+}
+
+let ArchGuard = "__ARM_ARCH >= 8 && defined(__aarch64__)" in {
+def FCVTNS_S64 : SInst<"vcvtn_s64", "xd", "dQd">;
+def FCVTNU_S64 : SInst<"vcvtn_u64", "ud", "dQd">;
+def FCVTPS_S64 : SInst<"vcvtp_s64", "xd", "dQd">;
+def FCVTPU_S64 : SInst<"vcvtp_u64", "ud", "dQd">;
+def FCVTMS_S64 : SInst<"vcvtm_s64", "xd", "dQd">;
+def FCVTMU_S64 : SInst<"vcvtm_u64", "ud", "dQd">;
+def FCVTAS_S64 : SInst<"vcvta_s64", "xd", "dQd">;
+def FCVTAU_S64 : SInst<"vcvta_u64", "ud", "dQd">;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// Round to Integral
+
+let ArchGuard = "__ARM_ARCH >= 8 && defined(__ARM_FEATURE_DIRECTED_ROUNDING)" in {
+def FRINTN_S32 : SInst<"vrndn", "dd", "fQf">;
+def FRINTA_S32 : SInst<"vrnda", "dd", "fQf">;
+def FRINTP_S32 : SInst<"vrndp", "dd", "fQf">;
+def FRINTM_S32 : SInst<"vrndm", "dd", "fQf">;
+def FRINTX_S32 : SInst<"vrndx", "dd", "fQf">;
+def FRINTZ_S32 : SInst<"vrnd", "dd", "fQf">;
+}
+
+let ArchGuard = "__ARM_ARCH >= 8 && defined(__aarch64__) && defined(__ARM_FEATURE_DIRECTED_ROUNDING)" in {
+def FRINTN_S64 : SInst<"vrndn", "dd", "dQd">;
+def FRINTA_S64 : SInst<"vrnda", "dd", "dQd">;
+def FRINTP_S64 : SInst<"vrndp", "dd", "dQd">;
+def FRINTM_S64 : SInst<"vrndm", "dd", "dQd">;
+def FRINTX_S64 : SInst<"vrndx", "dd", "dQd">;
+def FRINTZ_S64 : SInst<"vrnd", "dd", "dQd">;
+def FRINTI_S64 : SInst<"vrndi", "dd", "fdQfQd">;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// MaxNum/MinNum Floating Point
+
+let ArchGuard = "__ARM_ARCH >= 8 && defined(__ARM_FEATURE_NUMERIC_MAXMIN)" in {
+def FMAXNM_S32 : SInst<"vmaxnm", "ddd", "fQf">;
+def FMINNM_S32 : SInst<"vminnm", "ddd", "fQf">;
+}
+
+let ArchGuard = "__ARM_ARCH >= 8 && defined(__aarch64__) && defined(__ARM_FEATURE_NUMERIC_MAXMIN)" in {
+def FMAXNM_S64 : SInst<"vmaxnm", "ddd", "dQd">;
+def FMINNM_S64 : SInst<"vminnm", "ddd", "dQd">;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// Permutation
+def VTRN1 : SOpInst<"vtrn1", "ddd",
+ "csiUcUsUifPcPsQcQsQiQlQUcQUsQUiQUlQfQdQPcQPsQPl", OP_TRN1>;
+def VZIP1 : SOpInst<"vzip1", "ddd",
+ "csiUcUsUifPcPsQcQsQiQlQUcQUsQUiQUlQfQdQPcQPsQPl", OP_ZIP1>;
+def VUZP1 : SOpInst<"vuzp1", "ddd",
+ "csiUcUsUifPcPsQcQsQiQlQUcQUsQUiQUlQfQdQPcQPsQPl", OP_UZP1>;
+def VTRN2 : SOpInst<"vtrn2", "ddd",
+ "csiUcUsUifPcPsQcQsQiQlQUcQUsQUiQUlQfQdQPcQPsQPl", OP_TRN2>;
+def VZIP2 : SOpInst<"vzip2", "ddd",
+ "csiUcUsUifPcPsQcQsQiQlQUcQUsQUiQUlQfQdQPcQPsQPl", OP_ZIP2>;
+def VUZP2 : SOpInst<"vuzp2", "ddd",
+ "csiUcUsUifPcPsQcQsQiQlQUcQUsQUiQUlQfQdQPcQPsQPl", OP_UZP2>;
+
+////////////////////////////////////////////////////////////////////////////////
+// Table lookup
+let InstName = "vtbl" in {
+def VQTBL1_A64 : WInst<"vqtbl1", "djt", "UccPcQUcQcQPc">;
+def VQTBL2_A64 : WInst<"vqtbl2", "dBt", "UccPcQUcQcQPc">;
+def VQTBL3_A64 : WInst<"vqtbl3", "dCt", "UccPcQUcQcQPc">;
+def VQTBL4_A64 : WInst<"vqtbl4", "dDt", "UccPcQUcQcQPc">;
+}
+let InstName = "vtbx" in {
+def VQTBX1_A64 : WInst<"vqtbx1", "ddjt", "UccPcQUcQcQPc">;
+def VQTBX2_A64 : WInst<"vqtbx2", "ddBt", "UccPcQUcQcQPc">;
+def VQTBX3_A64 : WInst<"vqtbx3", "ddCt", "UccPcQUcQcQPc">;
+def VQTBX4_A64 : WInst<"vqtbx4", "ddDt", "UccPcQUcQcQPc">;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// Vector reinterpret cast operations
+
+// NeonEmitter implicitly takes the cartesian product of the type string with
+// itself during generation so, unlike all other intrinsics, this one should
+// include *all* types, not just additional ones.
+def VVREINTERPRET
+ : NoTestOpInst<"vreinterpret", "dd",
+ "csilUcUsUiUlhfdPcPsPlQcQsQiQlQUcQUsQUiQUlQhQfQdQPcQPsQPlQPk", OP_REINT> {
+ let CartesianProductOfTypes = 1;
+ let BigEndianSafe = 1;
+ let ArchGuard = "__ARM_ARCH >= 8 && defined(__aarch64__)";
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// Scalar Intrinsics
+// Scalar Arithmetic
+
+// Scalar Addition
+def SCALAR_ADD : SInst<"vadd", "sss", "SlSUl">;
+// Scalar Saturating Add
+def SCALAR_QADD : SInst<"vqadd", "sss", "ScSsSiSlSUcSUsSUiSUl">;
+
+// Scalar Subtraction
+def SCALAR_SUB : SInst<"vsub", "sss", "SlSUl">;
+// Scalar Saturating Sub
+def SCALAR_QSUB : SInst<"vqsub", "sss", "ScSsSiSlSUcSUsSUiSUl">;
+
+let InstName = "vmov" in {
+def VGET_HIGH_A64 : NoTestOpInst<"vget_high", "dk", "dPl", OP_HI>;
+def VGET_LOW_A64 : NoTestOpInst<"vget_low", "dk", "dPl", OP_LO>;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// Scalar Shift
+// Scalar Shift Left
+def SCALAR_SHL: SInst<"vshl", "sss", "SlSUl">;
+// Scalar Saturating Shift Left
+def SCALAR_QSHL: SInst<"vqshl", "sss", "ScSsSiSlSUcSUsSUiSUl">;
+// Scalar Saturating Rounding Shift Left
+def SCALAR_QRSHL: SInst<"vqrshl", "sss", "ScSsSiSlSUcSUsSUiSUl">;
+// Scalar Shift Rouding Left
+def SCALAR_RSHL: SInst<"vrshl", "sss", "SlSUl">;
+
+////////////////////////////////////////////////////////////////////////////////
+// Scalar Shift (Immediate)
+let isScalarShift = 1 in {
+// Signed/Unsigned Shift Right (Immediate)
+def SCALAR_SSHR_N: SInst<"vshr_n", "ssi", "SlSUl">;
+// Signed/Unsigned Rounding Shift Right (Immediate)
+def SCALAR_SRSHR_N: SInst<"vrshr_n", "ssi", "SlSUl">;
+
+// Signed/Unsigned Shift Right and Accumulate (Immediate)
+def SCALAR_SSRA_N: SInst<"vsra_n", "sssi", "SlSUl">;
+// Signed/Unsigned Rounding Shift Right and Accumulate (Immediate)
+def SCALAR_SRSRA_N: SInst<"vrsra_n", "sssi", "SlSUl">;
+
+// Shift Left (Immediate)
+def SCALAR_SHL_N: SInst<"vshl_n", "ssi", "SlSUl">;
+// Signed/Unsigned Saturating Shift Left (Immediate)
+def SCALAR_SQSHL_N: SInst<"vqshl_n", "ssi", "ScSsSiSlSUcSUsSUiSUl">;
+// Signed Saturating Shift Left Unsigned (Immediate)
+def SCALAR_SQSHLU_N: SInst<"vqshlu_n", "ssi", "ScSsSiSl">;
+
+// Shift Right And Insert (Immediate)
+def SCALAR_SRI_N: SInst<"vsri_n", "sssi", "SlSUl">;
+// Shift Left And Insert (Immediate)
+def SCALAR_SLI_N: SInst<"vsli_n", "sssi", "SlSUl">;
+
+let isScalarNarrowShift = 1 in {
+ // Signed/Unsigned Saturating Shift Right Narrow (Immediate)
+ def SCALAR_SQSHRN_N: SInst<"vqshrn_n", "zsi", "SsSiSlSUsSUiSUl">;
+ // Signed/Unsigned Saturating Rounded Shift Right Narrow (Immediate)
+ def SCALAR_SQRSHRN_N: SInst<"vqrshrn_n", "zsi", "SsSiSlSUsSUiSUl">;
+ // Signed Saturating Shift Right Unsigned Narrow (Immediate)
+ def SCALAR_SQSHRUN_N: SInst<"vqshrun_n", "zsi", "SsSiSl">;
+ // Signed Saturating Rounded Shift Right Unsigned Narrow (Immediate)
+ def SCALAR_SQRSHRUN_N: SInst<"vqrshrun_n", "zsi", "SsSiSl">;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// Scalar Signed/Unsigned Fixed-point Convert To Floating-Point (Immediate)
+def SCALAR_SCVTF_N_F32: SInst<"vcvt_n_f32", "ysi", "SiSUi">;
+def SCALAR_SCVTF_N_F64: SInst<"vcvt_n_f64", "osi", "SlSUl">;
+
+////////////////////////////////////////////////////////////////////////////////
+// Scalar Floating-point Convert To Signed/Unsigned Fixed-point (Immediate)
+def SCALAR_FCVTZS_N_S32 : SInst<"vcvt_n_s32", "$si", "Sf">;
+def SCALAR_FCVTZU_N_U32 : SInst<"vcvt_n_u32", "bsi", "Sf">;
+def SCALAR_FCVTZS_N_S64 : SInst<"vcvt_n_s64", "$si", "Sd">;
+def SCALAR_FCVTZU_N_U64 : SInst<"vcvt_n_u64", "bsi", "Sd">;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// Scalar Reduce Pairwise Addition (Scalar and Floating Point)
+def SCALAR_ADDP : SInst<"vpadd", "sd", "SfSHlSHdSHUl">;
+
+////////////////////////////////////////////////////////////////////////////////
+// Scalar Reduce Floating Point Pairwise Max/Min
+def SCALAR_FMAXP : SInst<"vpmax", "sd", "SfSQd">;
+
+def SCALAR_FMINP : SInst<"vpmin", "sd", "SfSQd">;
+
+////////////////////////////////////////////////////////////////////////////////
+// Scalar Reduce Floating Point Pairwise maxNum/minNum
+def SCALAR_FMAXNMP : SInst<"vpmaxnm", "sd", "SfSQd">;
+def SCALAR_FMINNMP : SInst<"vpminnm", "sd", "SfSQd">;
+
+////////////////////////////////////////////////////////////////////////////////
+// Scalar Integer Saturating Doubling Multiply Half High
+def SCALAR_SQDMULH : SInst<"vqdmulh", "sss", "SsSi">;
+
+////////////////////////////////////////////////////////////////////////////////
+// Scalar Integer Saturating Rounding Doubling Multiply Half High
+def SCALAR_SQRDMULH : SInst<"vqrdmulh", "sss", "SsSi">;
+
+let ArchGuard = "defined(__ARM_FEATURE_QRDMX) && defined(__aarch64__)" in {
+////////////////////////////////////////////////////////////////////////////////
+// Signed Saturating Rounding Doubling Multiply Accumulate Returning High Half
+def SCALAR_SQRDMLAH : SOpInst<"vqrdmlah", "ssss", "SsSi", OP_QRDMLAH>;
+
+////////////////////////////////////////////////////////////////////////////////
+// Signed Saturating Rounding Doubling Multiply Subtract Returning High Half
+def SCALAR_SQRDMLSH : SOpInst<"vqrdmlsh", "ssss", "SsSi", OP_QRDMLSH>;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// Scalar Floating-point Multiply Extended
+def SCALAR_FMULX : IInst<"vmulx", "sss", "SfSd">;
+
+////////////////////////////////////////////////////////////////////////////////
+// Scalar Floating-point Reciprocal Step
+def SCALAR_FRECPS : IInst<"vrecps", "sss", "SfSd">;
+
+////////////////////////////////////////////////////////////////////////////////
+// Scalar Floating-point Reciprocal Square Root Step
+def SCALAR_FRSQRTS : IInst<"vrsqrts", "sss", "SfSd">;
+
+////////////////////////////////////////////////////////////////////////////////
+// Scalar Signed Integer Convert To Floating-point
+def SCALAR_SCVTFS : SInst<"vcvt_f32", "ys", "Si">;
+def SCALAR_SCVTFD : SInst<"vcvt_f64", "os", "Sl">;
+
+////////////////////////////////////////////////////////////////////////////////
+// Scalar Unsigned Integer Convert To Floating-point
+def SCALAR_UCVTFS : SInst<"vcvt_f32", "ys", "SUi">;
+def SCALAR_UCVTFD : SInst<"vcvt_f64", "os", "SUl">;
+
+////////////////////////////////////////////////////////////////////////////////
+// Scalar Floating-point Converts
+def SCALAR_FCVTXN : IInst<"vcvtx_f32", "ys", "Sd">;
+def SCALAR_FCVTNSS : SInst<"vcvtn_s32", "$s", "Sf">;
+def SCALAR_FCVTNUS : SInst<"vcvtn_u32", "bs", "Sf">;
+def SCALAR_FCVTNSD : SInst<"vcvtn_s64", "$s", "Sd">;
+def SCALAR_FCVTNUD : SInst<"vcvtn_u64", "bs", "Sd">;
+def SCALAR_FCVTMSS : SInst<"vcvtm_s32", "$s", "Sf">;
+def SCALAR_FCVTMUS : SInst<"vcvtm_u32", "bs", "Sf">;
+def SCALAR_FCVTMSD : SInst<"vcvtm_s64", "$s", "Sd">;
+def SCALAR_FCVTMUD : SInst<"vcvtm_u64", "bs", "Sd">;
+def SCALAR_FCVTASS : SInst<"vcvta_s32", "$s", "Sf">;
+def SCALAR_FCVTAUS : SInst<"vcvta_u32", "bs", "Sf">;
+def SCALAR_FCVTASD : SInst<"vcvta_s64", "$s", "Sd">;
+def SCALAR_FCVTAUD : SInst<"vcvta_u64", "bs", "Sd">;
+def SCALAR_FCVTPSS : SInst<"vcvtp_s32", "$s", "Sf">;
+def SCALAR_FCVTPUS : SInst<"vcvtp_u32", "bs", "Sf">;
+def SCALAR_FCVTPSD : SInst<"vcvtp_s64", "$s", "Sd">;
+def SCALAR_FCVTPUD : SInst<"vcvtp_u64", "bs", "Sd">;
+def SCALAR_FCVTZSS : SInst<"vcvt_s32", "$s", "Sf">;
+def SCALAR_FCVTZUS : SInst<"vcvt_u32", "bs", "Sf">;
+def SCALAR_FCVTZSD : SInst<"vcvt_s64", "$s", "Sd">;
+def SCALAR_FCVTZUD : SInst<"vcvt_u64", "bs", "Sd">;
+
+////////////////////////////////////////////////////////////////////////////////
+// Scalar Floating-point Reciprocal Estimate
+def SCALAR_FRECPE : IInst<"vrecpe", "ss", "SfSd">;
+
+////////////////////////////////////////////////////////////////////////////////
+// Scalar Floating-point Reciprocal Exponent
+def SCALAR_FRECPX : IInst<"vrecpx", "ss", "SfSd">;
+
+////////////////////////////////////////////////////////////////////////////////
+// Scalar Floating-point Reciprocal Square Root Estimate
+def SCALAR_FRSQRTE : IInst<"vrsqrte", "ss", "SfSd">;
+
+////////////////////////////////////////////////////////////////////////////////
+// Scalar Integer Comparison
+def SCALAR_CMEQ : SInst<"vceq", "sss", "SlSUl">;
+def SCALAR_CMEQZ : SInst<"vceqz", "ss", "SlSUl">;
+def SCALAR_CMGE : SInst<"vcge", "sss", "Sl">;
+def SCALAR_CMGEZ : SInst<"vcgez", "ss", "Sl">;
+def SCALAR_CMHS : SInst<"vcge", "sss", "SUl">;
+def SCALAR_CMLE : SInst<"vcle", "sss", "SlSUl">;
+def SCALAR_CMLEZ : SInst<"vclez", "ss", "Sl">;
+def SCALAR_CMLT : SInst<"vclt", "sss", "SlSUl">;
+def SCALAR_CMLTZ : SInst<"vcltz", "ss", "Sl">;
+def SCALAR_CMGT : SInst<"vcgt", "sss", "Sl">;
+def SCALAR_CMGTZ : SInst<"vcgtz", "ss", "Sl">;
+def SCALAR_CMHI : SInst<"vcgt", "sss", "SUl">;
+def SCALAR_CMTST : SInst<"vtst", "sss", "SlSUl">;
+
+////////////////////////////////////////////////////////////////////////////////
+// Scalar Floating-point Comparison
+def SCALAR_FCMEQ : IInst<"vceq", "bss", "SfSd">;
+def SCALAR_FCMEQZ : IInst<"vceqz", "bs", "SfSd">;
+def SCALAR_FCMGE : IInst<"vcge", "bss", "SfSd">;
+def SCALAR_FCMGEZ : IInst<"vcgez", "bs", "SfSd">;
+def SCALAR_FCMGT : IInst<"vcgt", "bss", "SfSd">;
+def SCALAR_FCMGTZ : IInst<"vcgtz", "bs", "SfSd">;
+def SCALAR_FCMLE : IInst<"vcle", "bss", "SfSd">;
+def SCALAR_FCMLEZ : IInst<"vclez", "bs", "SfSd">;
+def SCALAR_FCMLT : IInst<"vclt", "bss", "SfSd">;
+def SCALAR_FCMLTZ : IInst<"vcltz", "bs", "SfSd">;
+
+////////////////////////////////////////////////////////////////////////////////
+// Scalar Floating-point Absolute Compare Mask Greater Than Or Equal
+def SCALAR_FACGE : IInst<"vcage", "bss", "SfSd">;
+def SCALAR_FACLE : IInst<"vcale", "bss", "SfSd">;
+
+////////////////////////////////////////////////////////////////////////////////
+// Scalar Floating-point Absolute Compare Mask Greater Than
+def SCALAR_FACGT : IInst<"vcagt", "bss", "SfSd">;
+def SCALAR_FACLT : IInst<"vcalt", "bss", "SfSd">;
+
+////////////////////////////////////////////////////////////////////////////////
+// Scalar Absolute Value
+def SCALAR_ABS : SInst<"vabs", "ss", "Sl">;
+
+////////////////////////////////////////////////////////////////////////////////
+// Scalar Absolute Difference
+def SCALAR_ABD : IInst<"vabd", "sss", "SfSd">;
+
+////////////////////////////////////////////////////////////////////////////////
+// Scalar Signed Saturating Absolute Value
+def SCALAR_SQABS : SInst<"vqabs", "ss", "ScSsSiSl">;
+
+////////////////////////////////////////////////////////////////////////////////
+// Scalar Negate
+def SCALAR_NEG : SInst<"vneg", "ss", "Sl">;
+
+////////////////////////////////////////////////////////////////////////////////
+// Scalar Signed Saturating Negate
+def SCALAR_SQNEG : SInst<"vqneg", "ss", "ScSsSiSl">;
+
+////////////////////////////////////////////////////////////////////////////////
+// Scalar Signed Saturating Accumulated of Unsigned Value
+def SCALAR_SUQADD : SInst<"vuqadd", "sss", "ScSsSiSl">;
+
+////////////////////////////////////////////////////////////////////////////////
+// Scalar Unsigned Saturating Accumulated of Signed Value
+def SCALAR_USQADD : SInst<"vsqadd", "sss", "SUcSUsSUiSUl">;
+
+////////////////////////////////////////////////////////////////////////////////
+// Signed Saturating Doubling Multiply-Add Long
+def SCALAR_SQDMLAL : SInst<"vqdmlal", "rrss", "SsSi">;
+
+////////////////////////////////////////////////////////////////////////////////
+// Signed Saturating Doubling Multiply-Subtract Long
+def SCALAR_SQDMLSL : SInst<"vqdmlsl", "rrss", "SsSi">;
+
+////////////////////////////////////////////////////////////////////////////////
+// Signed Saturating Doubling Multiply Long
+def SCALAR_SQDMULL : SInst<"vqdmull", "rss", "SsSi">;
+
+////////////////////////////////////////////////////////////////////////////////
+// Scalar Signed Saturating Extract Unsigned Narrow
+def SCALAR_SQXTUN : SInst<"vqmovun", "zs", "SsSiSl">;
+
+////////////////////////////////////////////////////////////////////////////////
+// Scalar Signed Saturating Extract Narrow
+def SCALAR_SQXTN : SInst<"vqmovn", "zs", "SsSiSl">;
+
+////////////////////////////////////////////////////////////////////////////////
+// Scalar Unsigned Saturating Extract Narrow
+def SCALAR_UQXTN : SInst<"vqmovn", "zs", "SUsSUiSUl">;
+
+// Scalar Floating Point multiply (scalar, by element)
+def SCALAR_FMUL_LANE : IOpInst<"vmul_lane", "ssdi", "SfSd", OP_SCALAR_MUL_LN>;
+def SCALAR_FMUL_LANEQ : IOpInst<"vmul_laneq", "ssji", "SfSd", OP_SCALAR_MUL_LN>;
+
+// Scalar Floating Point multiply extended (scalar, by element)
+def SCALAR_FMULX_LANE : IOpInst<"vmulx_lane", "ssdi", "SfSd", OP_SCALAR_MULX_LN>;
+def SCALAR_FMULX_LANEQ : IOpInst<"vmulx_laneq", "ssji", "SfSd", OP_SCALAR_MULX_LN>;
+
+def SCALAR_VMUL_N : IInst<"vmul_n", "dds", "d">;
+
+// VMUL_LANE_A64 d type implemented using scalar mul lane
+def SCALAR_VMUL_LANE : IInst<"vmul_lane", "ddgi", "d">;
+
+// VMUL_LANEQ d type implemented using scalar mul lane
+def SCALAR_VMUL_LANEQ : IInst<"vmul_laneq", "ddji", "d"> {
+ let isLaneQ = 1;
+}
+
+// VMULX_LANE d type implemented using scalar vmulx_lane
+def SCALAR_VMULX_LANE : IOpInst<"vmulx_lane", "ddgi", "d", OP_SCALAR_VMULX_LN>;
+
+// VMULX_LANEQ d type implemented using scalar vmulx_laneq
+def SCALAR_VMULX_LANEQ : IOpInst<"vmulx_laneq", "ddji", "d", OP_SCALAR_VMULX_LNQ>;
+
+// Scalar Floating Point fused multiply-add (scalar, by element)
+def SCALAR_FMLA_LANE : IInst<"vfma_lane", "sssdi", "SfSd">;
+def SCALAR_FMLA_LANEQ : IInst<"vfma_laneq", "sssji", "SfSd">;
+
+// Scalar Floating Point fused multiply-subtract (scalar, by element)
+def SCALAR_FMLS_LANE : IOpInst<"vfms_lane", "sssdi", "SfSd", OP_FMS_LN>;
+def SCALAR_FMLS_LANEQ : IOpInst<"vfms_laneq", "sssji", "SfSd", OP_FMS_LNQ>;
+
+// Signed Saturating Doubling Multiply Long (scalar by element)
+def SCALAR_SQDMULL_LANE : SOpInst<"vqdmull_lane", "rsdi", "SsSi", OP_SCALAR_QDMULL_LN>;
+def SCALAR_SQDMULL_LANEQ : SOpInst<"vqdmull_laneq", "rsji", "SsSi", OP_SCALAR_QDMULL_LN>;
+
+// Signed Saturating Doubling Multiply-Add Long (scalar by element)
+def SCALAR_SQDMLAL_LANE : SInst<"vqdmlal_lane", "rrsdi", "SsSi">;
+def SCALAR_SQDMLAL_LANEQ : SInst<"vqdmlal_laneq", "rrsji", "SsSi">;
+
+// Signed Saturating Doubling Multiply-Subtract Long (scalar by element)
+def SCALAR_SQDMLS_LANE : SInst<"vqdmlsl_lane", "rrsdi", "SsSi">;
+def SCALAR_SQDMLS_LANEQ : SInst<"vqdmlsl_laneq", "rrsji", "SsSi">;
+
+// Scalar Integer Saturating Doubling Multiply Half High (scalar by element)
+def SCALAR_SQDMULH_LANE : SOpInst<"vqdmulh_lane", "ssdi", "SsSi", OP_SCALAR_QDMULH_LN>;
+def SCALAR_SQDMULH_LANEQ : SOpInst<"vqdmulh_laneq", "ssji", "SsSi", OP_SCALAR_QDMULH_LN>;
+
+// Scalar Integer Saturating Rounding Doubling Multiply Half High
+def SCALAR_SQRDMULH_LANE : SOpInst<"vqrdmulh_lane", "ssdi", "SsSi", OP_SCALAR_QRDMULH_LN>;
+def SCALAR_SQRDMULH_LANEQ : SOpInst<"vqrdmulh_laneq", "ssji", "SsSi", OP_SCALAR_QRDMULH_LN>;
+
+let ArchGuard = "defined(__ARM_FEATURE_QRDMX) && defined(__aarch64__)" in {
+// Signed Saturating Rounding Doubling Multiply Accumulate Returning High Half
+def SCALAR_SQRDMLAH_LANE : SOpInst<"vqrdmlah_lane", "sssdi", "SsSi", OP_SCALAR_QRDMLAH_LN>;
+def SCALAR_SQRDMLAH_LANEQ : SOpInst<"vqrdmlah_laneq", "sssji", "SsSi", OP_SCALAR_QRDMLAH_LN>;
+
+// Signed Saturating Rounding Doubling Multiply Subtract Returning High Half
+def SCALAR_SQRDMLSH_LANE : SOpInst<"vqrdmlsh_lane", "sssdi", "SsSi", OP_SCALAR_QRDMLSH_LN>;
+def SCALAR_SQRDMLSH_LANEQ : SOpInst<"vqrdmlsh_laneq", "sssji", "SsSi", OP_SCALAR_QRDMLSH_LN>;
+}
+
+def SCALAR_VDUP_LANE : IInst<"vdup_lane", "sdi", "ScSsSiSlSfSdSUcSUsSUiSUlSPcSPs">;
+def SCALAR_VDUP_LANEQ : IInst<"vdup_laneq", "sji", "ScSsSiSlSfSdSUcSUsSUiSUlSPcSPs">;
+}
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..ba5dc39
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/CodeGen/BackendUtil.h
@@ -0,0 +1,44 @@
+//===--- 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_BACKENDUTIL_H
+#define LLVM_CLANG_CODEGEN_BACKENDUTIL_H
+
+#include "clang/Basic/LLVM.h"
+#include "llvm/IR/FunctionInfo.h"
+#include <memory>
+
+namespace llvm {
+ class Module;
+}
+
+namespace clang {
+ class DiagnosticsEngine;
+ class CodeGenOptions;
+ class TargetOptions;
+ class LangOptions;
+
+ 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(DiagnosticsEngine &Diags, const CodeGenOptions &CGOpts,
+ const TargetOptions &TOpts, const LangOptions &LOpts,
+ StringRef TDesc, llvm::Module *M, BackendAction Action,
+ raw_pwrite_stream *OS,
+ std::unique_ptr<llvm::FunctionInfoIndex> Index = nullptr);
+}
+
+#endif
diff --git a/contrib/llvm/tools/clang/include/clang/CodeGen/CGFunctionInfo.h b/contrib/llvm/tools/clang/include/clang/CodeGen/CGFunctionInfo.h
new file mode 100644
index 0000000..bb6ceb4
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/CodeGen/CGFunctionInfo.h
@@ -0,0 +1,538 @@
+//==-- CGFunctionInfo.h - Representation of function argument/return types -==//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// Defines CGFunctionInfo and associated types used in representing the
+// LLVM source types and ABI-coerced types for function arguments and
+// return values.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_CODEGEN_CGFUNCTIONINFO_H
+#define LLVM_CLANG_CODEGEN_CGFUNCTIONINFO_H
+
+#include "clang/AST/CanonicalType.h"
+#include "clang/AST/CharUnits.h"
+#include "clang/AST/Type.h"
+#include "llvm/ADT/FoldingSet.h"
+#include <cassert>
+
+namespace llvm {
+ class Type;
+ class StructType;
+}
+
+namespace clang {
+class Decl;
+
+namespace CodeGen {
+
+/// 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 : uint8_t {
+ /// 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. A dummy argument is emitted before the real argument
+ /// if the specified type stored in "PaddingType" is not zero.
+ 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,
+
+ /// InAlloca - Pass the argument directly using the LLVM inalloca attribute.
+ /// This is similar to indirect with byval, except it only applies to
+ /// arguments stored in memory and forbids any implicit copies. When
+ /// applied to a return type, it means the value is returned indirectly via
+ /// an implicit sret parameter stored in the argument struct.
+ InAlloca,
+ KindFirst = Direct,
+ KindLast = InAlloca
+ };
+
+private:
+ llvm::Type *TypeData; // isDirect() || isExtend()
+ llvm::Type *PaddingType;
+ union {
+ unsigned DirectOffset; // isDirect() || isExtend()
+ unsigned IndirectAlign; // isIndirect()
+ unsigned AllocaFieldIndex; // isInAlloca()
+ };
+ Kind TheKind;
+ bool PaddingInReg : 1;
+ bool InAllocaSRet : 1; // isInAlloca()
+ bool IndirectByVal : 1; // isIndirect()
+ bool IndirectRealign : 1; // isIndirect()
+ bool SRetAfterThis : 1; // isIndirect()
+ bool InReg : 1; // isDirect() || isExtend() || isIndirect()
+ bool CanBeFlattened: 1; // isDirect()
+
+ ABIArgInfo(Kind K)
+ : PaddingType(nullptr), TheKind(K), PaddingInReg(false), InReg(false) {}
+
+public:
+ ABIArgInfo()
+ : TypeData(nullptr), PaddingType(nullptr), DirectOffset(0),
+ TheKind(Direct), PaddingInReg(false), InReg(false) {}
+
+ static ABIArgInfo getDirect(llvm::Type *T = nullptr, unsigned Offset = 0,
+ llvm::Type *Padding = nullptr,
+ bool CanBeFlattened = true) {
+ auto AI = ABIArgInfo(Direct);
+ AI.setCoerceToType(T);
+ AI.setDirectOffset(Offset);
+ AI.setPaddingType(Padding);
+ AI.setCanBeFlattened(CanBeFlattened);
+ return AI;
+ }
+ static ABIArgInfo getDirectInReg(llvm::Type *T = nullptr) {
+ auto AI = getDirect(T);
+ AI.setInReg(true);
+ return AI;
+ }
+ static ABIArgInfo getExtend(llvm::Type *T = nullptr) {
+ auto AI = ABIArgInfo(Extend);
+ AI.setCoerceToType(T);
+ AI.setDirectOffset(0);
+ return AI;
+ }
+ static ABIArgInfo getExtendInReg(llvm::Type *T = nullptr) {
+ auto AI = getExtend(T);
+ AI.setInReg(true);
+ return AI;
+ }
+ static ABIArgInfo getIgnore() {
+ return ABIArgInfo(Ignore);
+ }
+ static ABIArgInfo getIndirect(CharUnits Alignment, bool ByVal = true,
+ bool Realign = false,
+ llvm::Type *Padding = nullptr) {
+ auto AI = ABIArgInfo(Indirect);
+ AI.setIndirectAlign(Alignment);
+ AI.setIndirectByVal(ByVal);
+ AI.setIndirectRealign(Realign);
+ AI.setSRetAfterThis(false);
+ AI.setPaddingType(Padding);
+ return AI;
+ }
+ static ABIArgInfo getIndirectInReg(CharUnits Alignment, bool ByVal = true,
+ bool Realign = false) {
+ auto AI = getIndirect(Alignment, ByVal, Realign);
+ AI.setInReg(true);
+ return AI;
+ }
+ static ABIArgInfo getInAlloca(unsigned FieldIndex) {
+ auto AI = ABIArgInfo(InAlloca);
+ AI.setInAllocaFieldIndex(FieldIndex);
+ return AI;
+ }
+ static ABIArgInfo getExpand() {
+ return ABIArgInfo(Expand);
+ }
+ static ABIArgInfo getExpandWithPadding(bool PaddingInReg,
+ llvm::Type *Padding) {
+ auto AI = getExpand();
+ AI.setPaddingInReg(PaddingInReg);
+ AI.setPaddingType(Padding);
+ return AI;
+ }
+
+ Kind getKind() const { return TheKind; }
+ bool isDirect() const { return TheKind == Direct; }
+ bool isInAlloca() const { return TheKind == InAlloca; }
+ 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 isDirect() || isExtend(); }
+
+ // Direct/Extend accessors
+ unsigned getDirectOffset() const {
+ assert((isDirect() || isExtend()) && "Not a direct or extend kind");
+ return DirectOffset;
+ }
+ void setDirectOffset(unsigned Offset) {
+ assert((isDirect() || isExtend()) && "Not a direct or extend kind");
+ DirectOffset = Offset;
+ }
+
+ llvm::Type *getPaddingType() const { return PaddingType; }
+
+ void setPaddingType(llvm::Type *T) { PaddingType = T; }
+
+ bool getPaddingInReg() const {
+ return PaddingInReg;
+ }
+ void setPaddingInReg(bool PIR) {
+ PaddingInReg = PIR;
+ }
+
+ llvm::Type *getCoerceToType() const {
+ assert(canHaveCoerceToType() && "Invalid kind!");
+ return TypeData;
+ }
+
+ void setCoerceToType(llvm::Type *T) {
+ assert(canHaveCoerceToType() && "Invalid kind!");
+ TypeData = T;
+ }
+
+ bool getInReg() const {
+ assert((isDirect() || isExtend() || isIndirect()) && "Invalid kind!");
+ return InReg;
+ }
+
+ void setInReg(bool IR) {
+ assert((isDirect() || isExtend() || isIndirect()) && "Invalid kind!");
+ InReg = IR;
+ }
+
+ // Indirect accessors
+ CharUnits getIndirectAlign() const {
+ assert(isIndirect() && "Invalid kind!");
+ return CharUnits::fromQuantity(IndirectAlign);
+ }
+ void setIndirectAlign(CharUnits IA) {
+ assert(isIndirect() && "Invalid kind!");
+ IndirectAlign = IA.getQuantity();
+ }
+
+ bool getIndirectByVal() const {
+ assert(isIndirect() && "Invalid kind!");
+ return IndirectByVal;
+ }
+ void setIndirectByVal(bool IBV) {
+ assert(isIndirect() && "Invalid kind!");
+ IndirectByVal = IBV;
+ }
+
+ bool getIndirectRealign() const {
+ assert(isIndirect() && "Invalid kind!");
+ return IndirectRealign;
+ }
+ void setIndirectRealign(bool IR) {
+ assert(isIndirect() && "Invalid kind!");
+ IndirectRealign = IR;
+ }
+
+ bool isSRetAfterThis() const {
+ assert(isIndirect() && "Invalid kind!");
+ return SRetAfterThis;
+ }
+ void setSRetAfterThis(bool AfterThis) {
+ assert(isIndirect() && "Invalid kind!");
+ SRetAfterThis = AfterThis;
+ }
+
+ unsigned getInAllocaFieldIndex() const {
+ assert(isInAlloca() && "Invalid kind!");
+ return AllocaFieldIndex;
+ }
+ void setInAllocaFieldIndex(unsigned FieldIndex) {
+ assert(isInAlloca() && "Invalid kind!");
+ AllocaFieldIndex = FieldIndex;
+ }
+
+ /// \brief Return true if this field of an inalloca struct should be returned
+ /// to implement a struct return calling convention.
+ bool getInAllocaSRet() const {
+ assert(isInAlloca() && "Invalid kind!");
+ return InAllocaSRet;
+ }
+
+ void setInAllocaSRet(bool SRet) {
+ assert(isInAlloca() && "Invalid kind!");
+ InAllocaSRet = SRet;
+ }
+
+ bool getCanBeFlattened() const {
+ assert(isDirect() && "Invalid kind!");
+ return CanBeFlattened;
+ }
+
+ void setCanBeFlattened(bool Flatten) {
+ assert(isDirect() && "Invalid kind!");
+ CanBeFlattened = Flatten;
+ }
+
+ void dump() const;
+};
+
+/// A class for recording the number of arguments that a function
+/// signature requires.
+class RequiredArgs {
+ /// The number of required arguments, or ~0 if the signature does
+ /// not permit optional arguments.
+ unsigned NumRequired;
+public:
+ enum All_t { All };
+
+ RequiredArgs(All_t _) : NumRequired(~0U) {}
+ explicit RequiredArgs(unsigned n) : NumRequired(n) {
+ assert(n != ~0U);
+ }
+
+ /// Compute the arguments required by the given formal prototype,
+ /// given that there may be some additional, non-formal arguments
+ /// in play.
+ static RequiredArgs forPrototypePlus(const FunctionProtoType *prototype,
+ unsigned additional) {
+ if (!prototype->isVariadic()) return All;
+ return RequiredArgs(prototype->getNumParams() + additional);
+ }
+
+ static RequiredArgs forPrototype(const FunctionProtoType *prototype) {
+ return forPrototypePlus(prototype, 0);
+ }
+
+ static RequiredArgs forPrototype(CanQual<FunctionProtoType> prototype) {
+ return forPrototype(prototype.getTypePtr());
+ }
+
+ static RequiredArgs forPrototypePlus(CanQual<FunctionProtoType> prototype,
+ unsigned additional) {
+ return forPrototypePlus(prototype.getTypePtr(), additional);
+ }
+
+ bool allowsOptionalArgs() const { return NumRequired != ~0U; }
+ unsigned getNumRequiredArgs() const {
+ assert(allowsOptionalArgs());
+ return NumRequired;
+ }
+
+ unsigned getOpaqueData() const { return NumRequired; }
+ static RequiredArgs getFromOpaqueData(unsigned value) {
+ if (value == ~0U) return All;
+ return RequiredArgs(value);
+ }
+};
+
+/// 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 : 8;
+
+ /// The LLVM::CallingConv to actually use for this function, which may
+ /// depend on the ABI.
+ unsigned EffectiveCallingConvention : 8;
+
+ /// The clang::CallingConv that this was originally created with.
+ unsigned ASTCallingConvention : 8;
+
+ /// Whether this is an instance method.
+ unsigned InstanceMethod : 1;
+
+ /// Whether this is a chain call.
+ unsigned ChainCall : 1;
+
+ /// Whether this function is noreturn.
+ unsigned NoReturn : 1;
+
+ /// Whether this function is returns-retained.
+ unsigned ReturnsRetained : 1;
+
+ /// How many arguments to pass inreg.
+ unsigned HasRegParm : 1;
+ unsigned RegParm : 3;
+
+ RequiredArgs Required;
+
+ /// The struct representing all arguments passed in memory. Only used when
+ /// passing non-trivial types with inalloca. Not part of the profile.
+ llvm::StructType *ArgStruct;
+ unsigned ArgStructAlign;
+
+ unsigned NumArgs;
+ ArgInfo *getArgsBuffer() {
+ return reinterpret_cast<ArgInfo*>(this+1);
+ }
+ const ArgInfo *getArgsBuffer() const {
+ return reinterpret_cast<const ArgInfo*>(this + 1);
+ }
+
+ CGFunctionInfo() : Required(RequiredArgs::All) {}
+
+public:
+ static CGFunctionInfo *create(unsigned llvmCC,
+ bool instanceMethod,
+ bool chainCall,
+ const FunctionType::ExtInfo &extInfo,
+ CanQualType resultType,
+ ArrayRef<CanQualType> argTypes,
+ RequiredArgs required);
+
+ typedef const ArgInfo *const_arg_iterator;
+ typedef ArgInfo *arg_iterator;
+
+ typedef llvm::iterator_range<arg_iterator> arg_range;
+ typedef llvm::iterator_range<const_arg_iterator> arg_const_range;
+
+ arg_range arguments() { return arg_range(arg_begin(), arg_end()); }
+ arg_const_range arguments() const {
+ return arg_const_range(arg_begin(), arg_end());
+ }
+
+ const_arg_iterator arg_begin() const { return getArgsBuffer() + 1; }
+ const_arg_iterator arg_end() const { return getArgsBuffer() + 1 + NumArgs; }
+ arg_iterator arg_begin() { return getArgsBuffer() + 1; }
+ arg_iterator arg_end() { return getArgsBuffer() + 1 + NumArgs; }
+
+ unsigned arg_size() const { return NumArgs; }
+
+ bool isVariadic() const { return Required.allowsOptionalArgs(); }
+ RequiredArgs getRequiredArgs() const { return Required; }
+ unsigned getNumRequiredArgs() const {
+ return isVariadic() ? getRequiredArgs().getNumRequiredArgs() : arg_size();
+ }
+
+ bool isInstanceMethod() const { return InstanceMethod; }
+
+ bool isChainCall() const { return ChainCall; }
+
+ bool isNoReturn() const { return NoReturn; }
+
+ /// In ARC, whether this function retains its return value. This
+ /// is not always reliable for call sites.
+ bool isReturnsRetained() const { return ReturnsRetained; }
+
+ /// getASTCallingConvention() - Return the AST-specified calling
+ /// convention.
+ CallingConv getASTCallingConvention() const {
+ return CallingConv(ASTCallingConvention);
+ }
+
+ /// getCallingConvention - Return the user specified calling
+ /// convention, which has been translated into an LLVM CC.
+ 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;
+ }
+
+ bool getHasRegParm() const { return HasRegParm; }
+ unsigned getRegParm() const { return RegParm; }
+
+ FunctionType::ExtInfo getExtInfo() const {
+ return FunctionType::ExtInfo(isNoReturn(),
+ getHasRegParm(), getRegParm(),
+ getASTCallingConvention(),
+ isReturnsRetained());
+ }
+
+ CanQualType getReturnType() const { return getArgsBuffer()[0].type; }
+
+ ABIArgInfo &getReturnInfo() { return getArgsBuffer()[0].info; }
+ const ABIArgInfo &getReturnInfo() const { return getArgsBuffer()[0].info; }
+
+ /// \brief Return true if this function uses inalloca arguments.
+ bool usesInAlloca() const { return ArgStruct; }
+
+ /// \brief Get the struct type used to represent all the arguments in memory.
+ llvm::StructType *getArgStruct() const { return ArgStruct; }
+ CharUnits getArgStructAlignment() const {
+ return CharUnits::fromQuantity(ArgStructAlign);
+ }
+ void setArgStruct(llvm::StructType *Ty, CharUnits Align) {
+ ArgStruct = Ty;
+ ArgStructAlign = Align.getQuantity();
+ }
+
+ void Profile(llvm::FoldingSetNodeID &ID) {
+ ID.AddInteger(getASTCallingConvention());
+ ID.AddBoolean(InstanceMethod);
+ ID.AddBoolean(ChainCall);
+ ID.AddBoolean(NoReturn);
+ ID.AddBoolean(ReturnsRetained);
+ ID.AddBoolean(HasRegParm);
+ ID.AddInteger(RegParm);
+ ID.AddInteger(Required.getOpaqueData());
+ getReturnType().Profile(ID);
+ for (const auto &I : arguments())
+ I.type.Profile(ID);
+ }
+ static void Profile(llvm::FoldingSetNodeID &ID,
+ bool InstanceMethod,
+ bool ChainCall,
+ const FunctionType::ExtInfo &info,
+ RequiredArgs required,
+ CanQualType resultType,
+ ArrayRef<CanQualType> argTypes) {
+ ID.AddInteger(info.getCC());
+ ID.AddBoolean(InstanceMethod);
+ ID.AddBoolean(ChainCall);
+ ID.AddBoolean(info.getNoReturn());
+ ID.AddBoolean(info.getProducesResult());
+ ID.AddBoolean(info.getHasRegParm());
+ ID.AddInteger(info.getRegParm());
+ ID.AddInteger(required.getOpaqueData());
+ resultType.Profile(ID);
+ for (ArrayRef<CanQualType>::iterator
+ i = argTypes.begin(), e = argTypes.end(); i != e; ++i) {
+ i->Profile(ID);
+ }
+ }
+};
+
+/// CGCalleeInfo - Class to encapsulate the information about a callee to be
+/// used during the generation of call/invoke instructions.
+class CGCalleeInfo {
+ /// \brief The function proto type of the callee.
+ const FunctionProtoType *CalleeProtoTy;
+ /// \brief The function declaration of the callee.
+ const Decl *CalleeDecl;
+
+public:
+ explicit CGCalleeInfo() : CalleeProtoTy(nullptr), CalleeDecl(nullptr) {}
+ CGCalleeInfo(const FunctionProtoType *calleeProtoTy, const Decl *calleeDecl)
+ : CalleeProtoTy(calleeProtoTy), CalleeDecl(calleeDecl) {}
+ CGCalleeInfo(const FunctionProtoType *calleeProtoTy)
+ : CalleeProtoTy(calleeProtoTy), CalleeDecl(nullptr) {}
+ CGCalleeInfo(const Decl *calleeDecl)
+ : CalleeProtoTy(nullptr), CalleeDecl(calleeDecl) {}
+
+ const FunctionProtoType *getCalleeFunctionProtoType() {
+ return CalleeProtoTy;
+ }
+ const Decl *getCalleeDecl() { return CalleeDecl; }
+};
+
+} // end namespace CodeGen
+} // end namespace clang
+
+#endif
diff --git a/contrib/llvm/tools/clang/include/clang/CodeGen/CodeGenABITypes.h b/contrib/llvm/tools/clang/include/clang/CodeGen/CodeGenABITypes.h
new file mode 100644
index 0000000..9d9504a
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/CodeGen/CodeGenABITypes.h
@@ -0,0 +1,91 @@
+//==---- CodeGenABITypes.h - Convert Clang types to LLVM types for ABI -----==//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// CodeGenABITypes is a simple interface for getting LLVM types for
+// the parameters and the return value of a function given the Clang
+// types.
+//
+// The class is implemented as a public wrapper around the private
+// CodeGenTypes class in lib/CodeGen.
+//
+// It allows other clients, like LLDB, to determine the LLVM types that are
+// actually used in function calls, which makes it possible to then determine
+// the acutal ABI locations (e.g. registers, stack locations, etc.) that
+// these parameters are stored in.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_CODEGEN_CODEGENABITYPES_H
+#define LLVM_CLANG_CODEGEN_CODEGENABITYPES_H
+
+#include "clang/AST/CanonicalType.h"
+#include "clang/AST/Type.h"
+#include "clang/CodeGen/CGFunctionInfo.h"
+
+namespace llvm {
+ class DataLayout;
+ class Module;
+}
+
+namespace clang {
+class ASTContext;
+class CXXRecordDecl;
+class CXXMethodDecl;
+class CodeGenOptions;
+class CoverageSourceInfo;
+class DiagnosticsEngine;
+class HeaderSearchOptions;
+class ObjCMethodDecl;
+class PreprocessorOptions;
+
+namespace CodeGen {
+class CGFunctionInfo;
+class CodeGenModule;
+
+class CodeGenABITypes
+{
+public:
+ CodeGenABITypes(ASTContext &C, llvm::Module &M,
+ CoverageSourceInfo *CoverageInfo = nullptr);
+ ~CodeGenABITypes();
+
+ /// These methods all forward to methods in the private implementation class
+ /// CodeGenTypes.
+
+ const CGFunctionInfo &arrangeObjCMessageSendSignature(
+ const ObjCMethodDecl *MD,
+ QualType receiverType);
+ const CGFunctionInfo &arrangeFreeFunctionType(CanQual<FunctionProtoType> Ty,
+ const FunctionDecl *FD);
+ const CGFunctionInfo &arrangeFreeFunctionType(
+ CanQual<FunctionNoProtoType> Ty);
+ const CGFunctionInfo &arrangeCXXMethodType(const CXXRecordDecl *RD,
+ const FunctionProtoType *FTP,
+ const CXXMethodDecl *MD);
+ const CGFunctionInfo &arrangeFreeFunctionCall(CanQualType returnType,
+ ArrayRef<CanQualType> argTypes,
+ FunctionType::ExtInfo info,
+ RequiredArgs args);
+
+private:
+ /// Default CodeGenOptions object used to initialize the
+ /// CodeGenModule and otherwise not used. More specifically, it is
+ /// not used in ABI type generation, so none of the options matter.
+ std::unique_ptr<CodeGenOptions> CGO;
+ std::unique_ptr<HeaderSearchOptions> HSO;
+ std::unique_ptr<PreprocessorOptions> PPO;
+
+ /// The CodeGenModule we use get to the CodeGenTypes object.
+ std::unique_ptr<CodeGen::CodeGenModule> CGM;
+};
+
+} // end namespace CodeGen
+} // end namespace clang
+
+#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..cc38e24
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/CodeGen/CodeGenAction.h
@@ -0,0 +1,107 @@
+//===--- 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_CODEGENACTION_H
+#define LLVM_CLANG_CODEGEN_CODEGENACTION_H
+
+#include "clang/Frontend/FrontendAction.h"
+#include <memory>
+
+namespace llvm {
+ class LLVMContext;
+ class Module;
+}
+
+namespace clang {
+class BackendConsumer;
+
+class CodeGenAction : public ASTFrontendAction {
+private:
+ unsigned Act;
+ std::unique_ptr<llvm::Module> TheModule;
+ // Vector of {Linker::Flags, Module*} pairs to specify bitcode
+ // modules to link in using corresponding linker flags.
+ SmallVector<std::pair<unsigned, llvm::Module *>, 4> LinkModules;
+ llvm::LLVMContext *VMContext;
+ bool OwnsVMContext;
+
+protected:
+ /// Create a new code generation action. If the optional \p _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 = nullptr);
+
+ bool hasIRSupport() const override;
+
+ std::unique_ptr<ASTConsumer> CreateASTConsumer(CompilerInstance &CI,
+ StringRef InFile) override;
+
+ void ExecuteAction() override;
+
+ void EndSourceFileAction() override;
+
+public:
+ ~CodeGenAction() override;
+
+ /// setLinkModule - Set the link module to be used by this action. If a link
+ /// module is not provided, and CodeGenOptions::LinkBitcodeFile is non-empty,
+ /// the action will load it from the specified file.
+ void addLinkModule(llvm::Module *Mod, unsigned LinkFlags) {
+ LinkModules.push_back(std::make_pair(LinkFlags, Mod));
+ }
+
+ /// Take the generated LLVM module, for use after the action has been run.
+ /// The result may be null on failure.
+ std::unique_ptr<llvm::Module> takeModule();
+
+ /// Take the LLVM context used by this action.
+ llvm::LLVMContext *takeLLVMContext();
+
+ BackendConsumer *BEConsumer;
+};
+
+class EmitAssemblyAction : public CodeGenAction {
+ virtual void anchor();
+public:
+ EmitAssemblyAction(llvm::LLVMContext *_VMContext = nullptr);
+};
+
+class EmitBCAction : public CodeGenAction {
+ virtual void anchor();
+public:
+ EmitBCAction(llvm::LLVMContext *_VMContext = nullptr);
+};
+
+class EmitLLVMAction : public CodeGenAction {
+ virtual void anchor();
+public:
+ EmitLLVMAction(llvm::LLVMContext *_VMContext = nullptr);
+};
+
+class EmitLLVMOnlyAction : public CodeGenAction {
+ virtual void anchor();
+public:
+ EmitLLVMOnlyAction(llvm::LLVMContext *_VMContext = nullptr);
+};
+
+class EmitCodeGenOnlyAction : public CodeGenAction {
+ virtual void anchor();
+public:
+ EmitCodeGenOnlyAction(llvm::LLVMContext *_VMContext = nullptr);
+};
+
+class EmitObjAction : public CodeGenAction {
+ virtual void anchor();
+public:
+ EmitObjAction(llvm::LLVMContext *_VMContext = nullptr);
+};
+
+}
+
+#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..52497d9
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/CodeGen/ModuleBuilder.h
@@ -0,0 +1,54 @@
+//===--- 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 DiagnosticsEngine;
+ class CoverageSourceInfo;
+ class LangOptions;
+ class HeaderSearchOptions;
+ class PreprocessorOptions;
+ class CodeGenOptions;
+ class Decl;
+
+ class CodeGenerator : public ASTConsumer {
+ virtual void anchor();
+ public:
+ virtual llvm::Module* GetModule() = 0;
+ virtual llvm::Module* ReleaseModule() = 0;
+ virtual const Decl *GetDeclForMangledName(llvm::StringRef MangledName) = 0;
+ };
+
+ /// CreateLLVMCodeGen - Create a CodeGenerator instance.
+ /// It is the responsibility of the caller to call delete on
+ /// the allocated CodeGenerator instance.
+ CodeGenerator *CreateLLVMCodeGen(DiagnosticsEngine &Diags,
+ const std::string &ModuleName,
+ const HeaderSearchOptions &HeaderSearchOpts,
+ const PreprocessorOptions &PreprocessorOpts,
+ const CodeGenOptions &CGO,
+ llvm::LLVMContext& C,
+ CoverageSourceInfo *CoverageInfo = nullptr);
+}
+
+#endif
diff --git a/contrib/llvm/tools/clang/include/clang/CodeGen/ObjectFilePCHContainerOperations.h b/contrib/llvm/tools/clang/include/clang/CodeGen/ObjectFilePCHContainerOperations.h
new file mode 100644
index 0000000..15132ac
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/CodeGen/ObjectFilePCHContainerOperations.h
@@ -0,0 +1,43 @@
+//===-- CodeGen/ObjectFilePCHContainerOperations.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_CODEGEN_OBJECT_FILE_PCH_CONTAINER_OPERATIONS_H
+#define LLVM_CLANG_CODEGEN_OBJECT_FILE_PCH_CONTAINER_OPERATIONS_H
+
+#include "clang/Frontend/PCHContainerOperations.h"
+
+namespace clang {
+
+/// A PCHContainerWriter implementation that uses LLVM to
+/// wraps Clang modules inside a COFF, ELF, or Mach-O container.
+class ObjectFilePCHContainerWriter : public PCHContainerWriter {
+ StringRef getFormat() const override { return "obj"; }
+
+ /// Return an ASTConsumer that can be chained with a
+ /// PCHGenerator that produces a wrapper file format
+ /// that also contains full debug info for the module.
+ std::unique_ptr<ASTConsumer> CreatePCHContainerGenerator(
+ CompilerInstance &CI, const std::string &MainFileName,
+ const std::string &OutputFileName, llvm::raw_pwrite_stream *OS,
+ std::shared_ptr<PCHBuffer> Buffer) const override;
+};
+
+/// A PCHContainerReader implementation that uses LLVM to
+/// wraps Clang modules inside a COFF, ELF, or Mach-O container.
+class ObjectFilePCHContainerReader : public PCHContainerReader {
+ StringRef getFormat() const override { return "obj"; }
+
+ /// Initialize an llvm::BitstreamReader with the serialized
+ /// AST inside the PCH container Buffer.
+ void ExtractPCH(llvm::MemoryBufferRef Buffer,
+ llvm::BitstreamReader &StreamFile) const override;
+};
+}
+
+#endif
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..fc31d4b
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Driver/Action.h
@@ -0,0 +1,317 @@
+//===--- 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 LLVM_CLANG_DRIVER_ACTION_H
+#define LLVM_CLANG_DRIVER_ACTION_H
+
+#include "clang/Driver/Types.h"
+#include "clang/Driver/Util.h"
+#include "llvm/ADT/SmallVector.h"
+
+namespace llvm {
+namespace opt {
+ class Arg;
+}
+}
+
+namespace clang {
+namespace driver {
+
+/// 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,
+ CudaDeviceClass,
+ CudaHostClass,
+ PreprocessJobClass,
+ PrecompileJobClass,
+ AnalyzeJobClass,
+ MigrateJobClass,
+ CompileJobClass,
+ BackendJobClass,
+ AssembleJobClass,
+ LinkJobClass,
+ LipoJobClass,
+ DsymutilJobClass,
+ VerifyDebugInfoJobClass,
+ VerifyPCHJobClass,
+
+ JobClassFirst=PreprocessJobClass,
+ JobClassLast=VerifyPCHJobClass
+ };
+
+ 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, std::unique_ptr<Action> Input, types::ID Type)
+ : Kind(Kind), Type(Type), Inputs(1, Input.release()), OwnsInputs(true) {
+ }
+ Action(ActionClass Kind, std::unique_ptr<Action> Input)
+ : Kind(Kind), Type(Input->getType()), Inputs(1, Input.release()),
+ 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(); }
+};
+
+class InputAction : public Action {
+ virtual void anchor();
+ const llvm::opt::Arg &Input;
+
+public:
+ InputAction(const llvm::opt::Arg &Input, types::ID Type);
+
+ const llvm::opt::Arg &getInputArg() const { return Input; }
+
+ static bool classof(const Action *A) {
+ return A->getKind() == InputClass;
+ }
+};
+
+class BindArchAction : public Action {
+ virtual void anchor();
+ /// The architecture to bind, or 0 if the default architecture
+ /// should be bound.
+ const char *ArchName;
+
+public:
+ BindArchAction(std::unique_ptr<Action> Input, const char *ArchName);
+
+ const char *getArchName() const { return ArchName; }
+
+ static bool classof(const Action *A) {
+ return A->getKind() == BindArchClass;
+ }
+};
+
+class CudaDeviceAction : public Action {
+ virtual void anchor();
+ /// GPU architecture to bind -- e.g 'sm_35'.
+ const char *GpuArchName;
+ /// True when action results are not consumed by the host action (e.g when
+ /// -fsyntax-only or --cuda-device-only options are used).
+ bool AtTopLevel;
+
+public:
+ CudaDeviceAction(std::unique_ptr<Action> Input, const char *ArchName,
+ bool AtTopLevel);
+
+ const char *getGpuArchName() const { return GpuArchName; }
+ bool isAtTopLevel() const { return AtTopLevel; }
+
+ static bool classof(const Action *A) {
+ return A->getKind() == CudaDeviceClass;
+ }
+};
+
+class CudaHostAction : public Action {
+ virtual void anchor();
+ ActionList DeviceActions;
+
+public:
+ CudaHostAction(std::unique_ptr<Action> Input,
+ const ActionList &DeviceActions);
+ ~CudaHostAction() override;
+
+ const ActionList &getDeviceActions() const { return DeviceActions; }
+
+ static bool classof(const Action *A) { return A->getKind() == CudaHostClass; }
+};
+
+class JobAction : public Action {
+ virtual void anchor();
+protected:
+ JobAction(ActionClass Kind, std::unique_ptr<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);
+ }
+};
+
+class PreprocessJobAction : public JobAction {
+ void anchor() override;
+public:
+ PreprocessJobAction(std::unique_ptr<Action> Input, types::ID OutputType);
+
+ static bool classof(const Action *A) {
+ return A->getKind() == PreprocessJobClass;
+ }
+};
+
+class PrecompileJobAction : public JobAction {
+ void anchor() override;
+public:
+ PrecompileJobAction(std::unique_ptr<Action> Input, types::ID OutputType);
+
+ static bool classof(const Action *A) {
+ return A->getKind() == PrecompileJobClass;
+ }
+};
+
+class AnalyzeJobAction : public JobAction {
+ void anchor() override;
+public:
+ AnalyzeJobAction(std::unique_ptr<Action> Input, types::ID OutputType);
+
+ static bool classof(const Action *A) {
+ return A->getKind() == AnalyzeJobClass;
+ }
+};
+
+class MigrateJobAction : public JobAction {
+ void anchor() override;
+public:
+ MigrateJobAction(std::unique_ptr<Action> Input, types::ID OutputType);
+
+ static bool classof(const Action *A) {
+ return A->getKind() == MigrateJobClass;
+ }
+};
+
+class CompileJobAction : public JobAction {
+ void anchor() override;
+public:
+ CompileJobAction(std::unique_ptr<Action> Input, types::ID OutputType);
+
+ static bool classof(const Action *A) {
+ return A->getKind() == CompileJobClass;
+ }
+};
+
+class BackendJobAction : public JobAction {
+ void anchor() override;
+public:
+ BackendJobAction(std::unique_ptr<Action> Input, types::ID OutputType);
+
+ static bool classof(const Action *A) {
+ return A->getKind() == BackendJobClass;
+ }
+};
+
+class AssembleJobAction : public JobAction {
+ void anchor() override;
+public:
+ AssembleJobAction(std::unique_ptr<Action> Input, types::ID OutputType);
+
+ static bool classof(const Action *A) {
+ return A->getKind() == AssembleJobClass;
+ }
+};
+
+class LinkJobAction : public JobAction {
+ void anchor() override;
+public:
+ LinkJobAction(ActionList &Inputs, types::ID Type);
+
+ static bool classof(const Action *A) {
+ return A->getKind() == LinkJobClass;
+ }
+};
+
+class LipoJobAction : public JobAction {
+ void anchor() override;
+public:
+ LipoJobAction(ActionList &Inputs, types::ID Type);
+
+ static bool classof(const Action *A) {
+ return A->getKind() == LipoJobClass;
+ }
+};
+
+class DsymutilJobAction : public JobAction {
+ void anchor() override;
+public:
+ DsymutilJobAction(ActionList &Inputs, types::ID Type);
+
+ static bool classof(const Action *A) {
+ return A->getKind() == DsymutilJobClass;
+ }
+};
+
+class VerifyJobAction : public JobAction {
+ void anchor() override;
+public:
+ VerifyJobAction(ActionClass Kind, std::unique_ptr<Action> Input,
+ types::ID Type);
+ static bool classof(const Action *A) {
+ return A->getKind() == VerifyDebugInfoJobClass ||
+ A->getKind() == VerifyPCHJobClass;
+ }
+};
+
+class VerifyDebugInfoJobAction : public VerifyJobAction {
+ void anchor() override;
+public:
+ VerifyDebugInfoJobAction(std::unique_ptr<Action> Input, types::ID Type);
+ static bool classof(const Action *A) {
+ return A->getKind() == VerifyDebugInfoJobClass;
+ }
+};
+
+class VerifyPCHJobAction : public VerifyJobAction {
+ void anchor() override;
+public:
+ VerifyPCHJobAction(std::unique_ptr<Action> Input, types::ID Type);
+ static bool classof(const Action *A) {
+ return A->getKind() == VerifyPCHJobClass;
+ }
+};
+
+} // end namespace driver
+} // end namespace clang
+
+#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..051f903
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Driver/CC1Options.td
@@ -0,0 +1,718 @@
+//===--- 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 and clang -cc1as.
+//
+//===----------------------------------------------------------------------===//
+
+let Flags = [CC1Option, NoDriverOption] in {
+
+//===----------------------------------------------------------------------===//
+// Target Options
+//===----------------------------------------------------------------------===//
+
+let Flags = [CC1Option, CC1AsOption, NoDriverOption] in {
+
+def target_cpu : Separate<["-"], "target-cpu">,
+ HelpText<"Target a specific cpu type">;
+def target_feature : Separate<["-"], "target-feature">,
+ HelpText<"Target specific attributes">;
+def triple : Separate<["-"], "triple">,
+ HelpText<"Specify target triple (e.g. i686-apple-darwin9)">;
+def target_abi : Separate<["-"], "target-abi">,
+ HelpText<"Target a particular ABI type">;
+
+}
+
+def target_linker_version : Separate<["-"], "target-linker-version">,
+ HelpText<"Target linker version">;
+def triple_EQ : Joined<["-"], "triple=">, Alias<triple>;
+def mfpmath : Separate<["-"], "mfpmath">,
+ HelpText<"Which unit to use for fp math">;
+
+//===----------------------------------------------------------------------===//
+// 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 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_purge : Separate<["-"], "analyzer-purge">,
+ HelpText<"Source Code Analysis - Dead Symbol Removal Frequency">;
+def analyzer_purge_EQ : Joined<["-"], "analyzer-purge=">, Alias<analyzer_purge>;
+
+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 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 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_max_stack_depth : Separate<["-"], "analyzer-inline-max-stack-depth">,
+ HelpText<"Bound on stack depth while inlining (4 by default)">;
+def analyzer_inline_max_stack_depth_EQ : Joined<["-"], "analyzer-inline-max-stack-depth=">,
+ Alias<analyzer_inline_max_stack_depth>;
+
+def analyzer_inlining_mode : Separate<["-"], "analyzer-inlining-mode">,
+ HelpText<"Specify the function selection heuristic used during inlining">;
+def analyzer_inlining_mode_EQ : Joined<["-"], "analyzer-inlining-mode=">, Alias<analyzer_inlining_mode>;
+
+def analyzer_disable_retry_exhausted : Flag<["-"], "analyzer-disable-retry-exhausted">,
+ HelpText<"Do not re-analyze paths leading to exhausted nodes with a different strategy (may decrease code coverage)">;
+
+def analyzer_max_loop : Separate<["-"], "analyzer-max-loop">,
+ HelpText<"The maximum number of times the analyzer will go through a loop">;
+def analyzer_stats : Flag<["-"], "analyzer-stats">,
+ HelpText<"Print internal analyzer statistics.">;
+
+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>;
+
+def analyzer_disable_all_checks : Flag<["-"], "analyzer-disable-all-checks">,
+ HelpText<"Disable all static analyzer checks">;
+
+def analyzer_checker_help : Flag<["-"], "analyzer-checker-help">,
+ HelpText<"Display the list of analyzer checkers that are available">;
+
+def analyzer_config : Separate<["-"], "analyzer-config">,
+ HelpText<"Choose analyzer options to enable">;
+
+//===----------------------------------------------------------------------===//
+// Migrator Options
+//===----------------------------------------------------------------------===//
+def migrator_no_nsalloc_error : Flag<["-"], "no-ns-alloc-error">,
+ HelpText<"Do not error on use of NSAllocateCollectable/NSReallocateCollectable">;
+
+def migrator_no_finalize_removal : Flag<["-"], "no-finalize-removal">,
+ HelpText<"Do not remove finalize method in gc mode">;
+
+//===----------------------------------------------------------------------===//
+// CodeGen Options
+//===----------------------------------------------------------------------===//
+
+let Flags = [CC1Option, CC1AsOption, NoDriverOption] in {
+
+def debug_info_kind_EQ : Joined<["-"], "debug-info-kind=">;
+def dwarf_version_EQ : Joined<["-"], "dwarf-version=">;
+def debugger_tuning_EQ : Joined<["-"], "debugger-tuning=">;
+def fdebug_compilation_dir : Separate<["-"], "fdebug-compilation-dir">,
+ HelpText<"The compilation directory to embed in the debug info.">;
+def dwarf_debug_flags : Separate<["-"], "dwarf-debug-flags">,
+ HelpText<"The string to embed in the Dwarf debug flags record.">;
+def mno_exec_stack : Flag<["-"], "mnoexecstack">,
+ HelpText<"Mark the file as not needing an executable stack">;
+def massembler_fatal_warnings : Flag<["-"], "massembler-fatal-warnings">,
+ HelpText<"Make assembler warnings fatal">;
+def compress_debug_sections : Flag<["-"], "compress-debug-sections">,
+ HelpText<"Compress DWARF debug sections using zlib">;
+def msave_temp_labels : Flag<["-"], "msave-temp-labels">,
+ HelpText<"Save temporary labels in the symbol table. "
+ "Note this may change .s semantics and shouldn't generally be used "
+ "on compiler-generated code.">;
+def mrelocation_model : Separate<["-"], "mrelocation-model">,
+ HelpText<"The relocation model to use">;
+}
+
+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_llvm_passes : Flag<["-"], "disable-llvm-passes">,
+ HelpText<"Use together with -emit-llvm to get pristine LLVM IR from the "
+ "frontend by not running any LLVM passes at all">;
+def disable_red_zone : Flag<["-"], "disable-red-zone">,
+ HelpText<"Do not emit code that uses the red zone.">;
+def dwarf_column_info : Flag<["-"], "dwarf-column-info">,
+ HelpText<"Turn on column location information.">;
+def split_dwarf : Flag<["-"], "split-dwarf">,
+ HelpText<"Split out the dwarf .dwo sections">;
+def gnu_pubnames : Flag<["-"], "gnu-pubnames">,
+ HelpText<"Emit newer GNU style pubnames">;
+def arange_sections : Flag<["-"], "arange_sections">,
+ HelpText<"Emit DWARF .debug_arange sections">;
+def dwarf_ext_refs : Flag<["-"], "dwarf-ext-refs">,
+ HelpText<"Generate debug info with external references to clang modules"
+ " or precompiled headers">;
+def fforbid_guard_variables : Flag<["-"], "fforbid-guard-variables">,
+ HelpText<"Emit an error if a C++ static local initializer would need a guard variable">;
+def no_implicit_float : Flag<["-"], "no-implicit-float">,
+ HelpText<"Don't generate implicit floating point instructions">;
+def fdump_vtable_layouts : Flag<["-"], "fdump-vtable-layouts">,
+ HelpText<"Dump the layouts of all vtables that will be emitted in a translation unit">;
+def fmerge_functions : Flag<["-"], "fmerge-functions">,
+ HelpText<"Permit merging of identical functions when optimizing.">;
+def femit_coverage_notes : Flag<["-"], "femit-coverage-notes">,
+ HelpText<"Emit a gcov coverage notes file when compiling.">;
+def femit_coverage_data: Flag<["-"], "femit-coverage-data">,
+ HelpText<"Instrument the program to emit gcov coverage data when run.">;
+def coverage_file : Separate<["-"], "coverage-file">,
+ HelpText<"Emit coverage data to this filename. The extension will be replaced.">;
+def coverage_file_EQ : Joined<["-"], "coverage-file=">, Alias<coverage_file>;
+def coverage_cfg_checksum : Flag<["-"], "coverage-cfg-checksum">,
+ HelpText<"Emit CFG checksum for functions in .gcno files.">;
+def coverage_no_function_names_in_data : Flag<["-"], "coverage-no-function-names-in-data">,
+ HelpText<"Emit function names in .gcda files.">;
+def coverage_exit_block_before_body : Flag<["-"], "coverage-exit-block-before-body">,
+ HelpText<"Emit the exit block before the body blocks in .gcno files.">;
+def coverage_version_EQ : Joined<["-"], "coverage-version=">,
+ HelpText<"Four-byte version string for gcov files.">;
+def test_coverage : Flag<["-"], "test-coverage">,
+ HelpText<"Do not generate coverage files or remove coverage changes from IR">;
+def dump_coverage_mapping : Flag<["-"], "dump-coverage-mapping">,
+ HelpText<"Dump the coverage mapping records, for testing">;
+def fuse_register_sized_bitfield_access: Flag<["-"], "fuse-register-sized-bitfield-access">,
+ HelpText<"Use register sized accesses to bit-fields, when possible.">;
+def relaxed_aliasing : Flag<["-"], "relaxed-aliasing">,
+ HelpText<"Turn off Type Based Alias Analysis">;
+def no_struct_path_tbaa : Flag<["-"], "no-struct-path-tbaa">,
+ HelpText<"Turn off struct-path aware 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 mdisable_tail_calls : Flag<["-"], "mdisable-tail-calls">,
+ HelpText<"Disable tail call optimization, keeping the call stack accurate">;
+def menable_no_infinities : Flag<["-"], "menable-no-infs">,
+ HelpText<"Allow optimization to assume there are no infinities.">;
+def menable_no_nans : Flag<["-"], "menable-no-nans">,
+ HelpText<"Allow optimization to assume there are no NaNs.">;
+def menable_unsafe_fp_math : Flag<["-"], "menable-unsafe-fp-math">,
+ HelpText<"Allow unsafe floating-point math optimizations which may decrease "
+ "precision">;
+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 split_stacks : Flag<["-"], "split-stacks">,
+ HelpText<"Try to use a split stack if possible.">;
+def mno_zero_initialized_in_bss : Flag<["-"], "mno-zero-initialized-in-bss">,
+ HelpText<"Do not put zero initialized data in the BSS">;
+def backend_option : Separate<["-"], "backend-option">,
+ HelpText<"Additional arguments to forward to LLVM backend (during code gen)">;
+def mregparm : Separate<["-"], "mregparm">,
+ HelpText<"Limit the number of registers available for integer arguments">;
+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 mlink_bitcode_file : Separate<["-"], "mlink-bitcode-file">,
+ HelpText<"Link the given bitcode file before performing optimizations.">;
+def mlink_cuda_bitcode : Separate<["-"], "mlink-cuda-bitcode">,
+ HelpText<"Link and internalize needed symbols from the given bitcode file "
+ "before performing optimizations.">;
+def vectorize_loops : Flag<["-"], "vectorize-loops">,
+ HelpText<"Run the Loop vectorization passes">;
+def vectorize_slp : Flag<["-"], "vectorize-slp">,
+ HelpText<"Run the SLP vectorization passes">;
+def vectorize_slp_aggressive : Flag<["-"], "vectorize-slp-aggressive">,
+ HelpText<"Run the BB vectorization passes">;
+def dependent_lib : Joined<["--"], "dependent-lib=">,
+ HelpText<"Add dependent library">;
+def fsanitize_coverage_type : Joined<["-"], "fsanitize-coverage-type=">,
+ HelpText<"Sanitizer coverage type">;
+def fsanitize_coverage_indirect_calls
+ : Flag<["-"], "fsanitize-coverage-indirect-calls">,
+ HelpText<"Enable sanitizer coverage for indirect calls">;
+def fsanitize_coverage_trace_bb
+ : Flag<["-"], "fsanitize-coverage-trace-bb">,
+ HelpText<"Enable basic block tracing in sanitizer coverage">;
+def fsanitize_coverage_trace_cmp
+ : Flag<["-"], "fsanitize-coverage-trace-cmp">,
+ HelpText<"Enable cmp instruction tracing in sanitizer coverage">;
+def fsanitize_coverage_8bit_counters
+ : Flag<["-"], "fsanitize-coverage-8bit-counters">,
+ HelpText<"Enable frequency counters in sanitizer coverage">;
+
+//===----------------------------------------------------------------------===//
+// Dependency Output Options
+//===----------------------------------------------------------------------===//
+
+def sys_header_deps : Flag<["-"], "sys-header-deps">,
+ HelpText<"Include system headers in dependency output">;
+def module_file_deps : Flag<["-"], "module-file-deps">,
+ HelpText<"Include module files in dependency output">;
+def header_include_file : Separate<["-"], "header-include-file">,
+ HelpText<"Filename (or -) to write header include output to">;
+def show_includes : Flag<["--"], "show-includes">,
+ HelpText<"Print cl.exe style /showIncludes to stdout">;
+
+//===----------------------------------------------------------------------===//
+// Diagnostic Options
+//===----------------------------------------------------------------------===//
+
+def diagnostic_log_file : Separate<["-"], "diagnostic-log-file">,
+ HelpText<"Filename (or -) to log diagnostics to">;
+def diagnostic_serialized_file : Separate<["-"], "serialize-diagnostic-file">,
+ MetaVarName<"<filename>">,
+ HelpText<"File for serializing diagnostics in a binary format">;
+
+def fdiagnostics_format : Separate<["-"], "fdiagnostics-format">,
+ HelpText<"Change diagnostic formatting to match IDE and command line tools">;
+def fdiagnostics_show_category : Separate<["-"], "fdiagnostics-show-category">,
+ HelpText<"Print diagnostic category">;
+def fno_diagnostics_use_presumed_location : Flag<["-"], "fno-diagnostics-use-presumed-location">,
+ HelpText<"Ignore #line directives when displaying diagnostic locations">;
+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 expansion 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 fconstexpr_backtrace_limit : Separate<["-"], "fconstexpr-backtrace-limit">, MetaVarName<"<N>">,
+ HelpText<"Set the maximum number of entries to print in a constexpr evaluation backtrace (0 = no limit).">;
+def fspell_checking_limit : Separate<["-"], "fspell-checking-limit">, MetaVarName<"<N>">,
+ HelpText<"Set the maximum number of times to perform spell checking on unrecognized identifiers (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 verify : Flag<["-"], "verify">,
+ HelpText<"Verify diagnostic output using comment directives">;
+def verify_ignore_unexpected : Flag<["-"], "verify-ignore-unexpected">,
+ HelpText<"Ignore unexpected diagnostic messages">;
+def verify_ignore_unexpected_EQ : CommaJoined<["-"], "verify-ignore-unexpected=">,
+ HelpText<"Ignore unexpected diagnostic messages">;
+def Wno_rewrite_macros : Flag<["-"], "Wno-rewrite-macros">,
+ HelpText<"Silence ObjC rewriting 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 cc1as : Flag<["-"], "cc1as">;
+
+def ast_merge : Separate<["-"], "ast-merge">,
+ MetaVarName<"<ast file>">,
+ HelpText<"Merge the given AST file into the translation unit being compiled.">;
+def aux_triple : Separate<["-"], "aux-triple">,
+ HelpText<"Auxiliary target triple.">;
+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 code_completion_brief_comments : Flag<["-"], "code-completion-brief-comments">,
+ HelpText<"Include brief documentation comments in code-completion results.">;
+def disable_free : Flag<["-"], "disable-free">,
+ HelpText<"Disable freeing of memory on exit">;
+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 ast_dump_filter : Separate<["-"], "ast-dump-filter">,
+ MetaVarName<"<dump_filter>">,
+ HelpText<"Use with -ast-dump or -ast-print to dump/print only AST declaration"
+ " nodes having a certain substring in a qualified name. Use"
+ " -ast-list to list all filterable declaration node names.">;
+def fno_modules_global_index : Flag<["-"], "fno-modules-global-index">,
+ HelpText<"Do not automatically generate or update the global module index">;
+def fno_modules_error_recovery : Flag<["-"], "fno-modules-error-recovery">,
+ HelpText<"Do not automatically import modules for error recovery">;
+def fmodule_implementation_of : Separate<["-"], "fmodule-implementation-of">,
+ MetaVarName<"<name>">,
+ HelpText<"Specify the name of the module whose implementation file this is">;
+def fmodule_map_file_home_is_cwd : Flag<["-"], "fmodule-map-file-home-is-cwd">,
+ HelpText<"Use the current working directory as the home directory of "
+ "module maps specified by -fmodule-map-file=<FILE>">;
+def fmodule_feature : Separate<["-"], "fmodule-feature">,
+ MetaVarName<"<feature>">,
+ HelpText<"Enable <feature> in module map requires declarations">;
+def fmodules_embed_file_EQ : Joined<["-"], "fmodules-embed-file=">,
+ MetaVarName<"<file>">,
+ HelpText<"Embed the contents of the specified file into the module file "
+ "being compiled.">;
+def fmodules_embed_all_files : Joined<["-"], "fmodules-embed-all-files">,
+ HelpText<"Embed the contents of all files read by this compilation into "
+ "the produced module file.">;
+def fmodules_local_submodule_visibility :
+ Flag<["-"], "fmodules-local-submodule-visibility">,
+ HelpText<"Enforce name visibility rules across submodules of the same "
+ "top-level module.">;
+def fmodule_format_EQ : Joined<["-"], "fmodule-format=">,
+ HelpText<"Select the container format for clang modules and PCH. "
+ "Supported options are 'raw' and 'obj'.">;
+def ftest_module_file_extension_EQ :
+ Joined<["-"], "ftest-module-file-extension=">,
+ HelpText<"introduce a module file extension for testing purposes. "
+ "The argument is parsed as blockname:major:minor:hashed:user info">;
+def fconcepts_ts : Flag<["-"], "fconcepts-ts">,
+ HelpText<"Enable C++ Extensions for Concepts.">;
+
+let Group = Action_Group in {
+
+def Eonly : Flag<["-"], "Eonly">,
+ HelpText<"Just run preprocessor, no output (for timings)">;
+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 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_list : Flag<["-"], "ast-list">,
+ HelpText<"Build ASTs and print the list of declaration node qualified names">;
+def ast_dump : Flag<["-"], "ast-dump">,
+ HelpText<"Build ASTs and then debug dump them">;
+def ast_dump_lookups : Flag<["-"], "ast-dump-lookups">,
+ HelpText<"Build ASTs and then debug dump their name lookup tables">;
+def ast_view : Flag<["-"], "ast-view">,
+ HelpText<"Build ASTs and view them with GraphViz">;
+def print_decl_contexts : Flag<["-"], "print-decl-contexts">,
+ HelpText<"Print DeclContexts and their Decls">;
+def emit_module : Flag<["-"], "emit-module">,
+ HelpText<"Generate pre-compiled module file from a module map">;
+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 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_macros : Flag<["-"], "rewrite-macros">,
+ HelpText<"Expand macros without full preprocessing">;
+def migrate : Flag<["-"], "migrate">,
+ HelpText<"Migrate source code">;
+}
+
+def emit_llvm_uselists : Flag<["-"], "emit-llvm-uselists">,
+ HelpText<"Preserve order of LLVM use-lists when serializing">;
+def no_emit_llvm_uselists : Flag<["-"], "no-emit-llvm-uselists">,
+ HelpText<"Don't preserve order of LLVM use-lists when serializing">;
+
+def mt_migrate_directory : Separate<["-"], "mt-migrate-directory">,
+ HelpText<"Directory for temporary files produced during ARC or ObjC migration">;
+def arcmt_check : Flag<["-"], "arcmt-check">,
+ HelpText<"Check for ARC migration issues that need manual handling">;
+def arcmt_modify : Flag<["-"], "arcmt-modify">,
+ HelpText<"Apply modifications to files to conform to ARC">;
+def arcmt_migrate : Flag<["-"], "arcmt-migrate">,
+ HelpText<"Apply modifications and produces temporary files that conform to ARC">;
+
+def print_stats : Flag<["-"], "print-stats">,
+ HelpText<"Print performance metrics and statistics">;
+def fdump_record_layouts : Flag<["-"], "fdump-record-layouts">,
+ HelpText<"Dump record layout information">;
+def fdump_record_layouts_simple : Flag<["-"], "fdump-record-layouts-simple">,
+ HelpText<"Dump record layout information in a simple form used for testing">;
+def fix_what_you_can : Flag<["-"], "fix-what-you-can">,
+ HelpText<"Apply fix-it advice even in the presence of unfixable errors">;
+def fix_only_warnings : Flag<["-"], "fix-only-warnings">,
+ HelpText<"Apply fix-it advice only for warnings, not errors">;
+def fixit_recompile : Flag<["-"], "fixit-recompile">,
+ HelpText<"Apply fix-it changes and recompile">;
+def fixit_to_temp : Flag<["-"], "fixit-to-temporary">,
+ HelpText<"Apply fix-it changes to temporary files">;
+
+def foverride_record_layout_EQ : Joined<["-"], "foverride-record-layout=">,
+ HelpText<"Override record layouts with those in the given file">;
+
+//===----------------------------------------------------------------------===//
+// Language Options
+//===----------------------------------------------------------------------===//
+
+let Flags = [CC1Option, CC1AsOption, NoDriverOption] in {
+
+def version : Flag<["-"], "version">,
+ HelpText<"Print the compiler version">;
+def main_file_name : Separate<["-"], "main-file-name">,
+ HelpText<"Main file name to use for debug info">;
+
+}
+
+def fblocks_runtime_optional : Flag<["-"], "fblocks-runtime-optional">,
+ HelpText<"Weakly link in the blocks runtime">;
+def fsjlj_exceptions : Flag<["-"], "fsjlj-exceptions">,
+ HelpText<"Use SjLj style exceptions">;
+def fnew_ms_eh: Flag<["-"], "fnew-ms-eh">,
+ HelpText<"Use the new IR representation for MS exceptions">;
+def split_dwarf_file : Separate<["-"], "split-dwarf-file">,
+ HelpText<"File name to use for split dwarf debug info output">;
+def fno_wchar : Flag<["-"], "fno-wchar">,
+ HelpText<"Disable C++ builtin type wchar_t">;
+def fconstant_string_class : Separate<["-"], "fconstant-string-class">,
+ MetaVarName<"<class name>">,
+ HelpText<"Specify the class to use for constant Objective-C string objects.">;
+def fobjc_arc_cxxlib_EQ : Joined<["-"], "fobjc-arc-cxxlib=">,
+ HelpText<"Objective-C++ Automatic Reference Counting standard library kind">;
+def fobjc_runtime_has_weak : Flag<["-"], "fobjc-runtime-has-weak">,
+ HelpText<"The target Objective-C runtime supports ARC weak operations">;
+def fobjc_dispatch_method_EQ : Joined<["-"], "fobjc-dispatch-method=">,
+ HelpText<"Objective-C dispatch method to use">;
+def disable_objc_default_synthesize_properties : Flag<["-"], "disable-objc-default-synthesize-properties">,
+ HelpText<"disable the default synthesis of Objective-C properties">;
+def fencode_extended_block_signature : Flag<["-"], "fencode-extended-block-signature">,
+ HelpText<"enable extended encoding of block type signature">;
+def pic_level : Separate<["-"], "pic-level">,
+ HelpText<"Value for __PIC__">;
+def pie_level : Separate<["-"], "pie-level">,
+ HelpText<"Value for __PIE__">;
+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 error_on_deserialized_pch_decl_EQ : Joined<["-"], "error-on-deserialized-decl=">,
+ Alias<error_on_deserialized_pch_decl>;
+def static_define : Flag<["-"], "static-define">,
+ HelpText<"Should __STATIC__ be defined">;
+def stack_protector : Separate<["-"], "stack-protector">,
+ HelpText<"Enable stack protectors">;
+def stack_protector_buffer_size : Separate<["-"], "stack-protector-buffer-size">,
+ HelpText<"Lower bound for a buffer to be considered for stack protection">;
+def fvisibility : Separate<["-"], "fvisibility">,
+ HelpText<"Default type and symbol visibility">;
+def ftype_visibility : Separate<["-"], "ftype-visibility">,
+ HelpText<"Default type visibility">;
+def ftemplate_depth : Separate<["-"], "ftemplate-depth">,
+ HelpText<"Maximum depth of recursive template instantiation">;
+def foperator_arrow_depth : Separate<["-"], "foperator-arrow-depth">,
+ HelpText<"Maximum number of 'operator->'s to call for a member access">;
+def fconstexpr_depth : Separate<["-"], "fconstexpr-depth">,
+ HelpText<"Maximum depth of recursive constexpr function calls">;
+def fconstexpr_steps : Separate<["-"], "fconstexpr-steps">,
+ HelpText<"Maximum number of steps in constexpr function evaluation">;
+def fbracket_depth : Separate<["-"], "fbracket-depth">,
+ HelpText<"Maximum nesting level for parentheses, brackets, and braces">;
+def fconst_strings : Flag<["-"], "fconst-strings">,
+ HelpText<"Use a const qualified type for string literals in C and ObjC">;
+def fno_const_strings : Flag<["-"], "fno-const-strings">,
+ HelpText<"Don't use a const qualified type for string literals in C and ObjC">;
+def fno_bitfield_type_align : Flag<["-"], "fno-bitfield-type-align">,
+ HelpText<"Ignore bit-field types when aligning structures">;
+def ffake_address_space_map : Flag<["-"], "ffake-address-space-map">,
+ HelpText<"Use a fake address space map; OpenCL testing purposes only">;
+def faddress_space_map_mangling_EQ : Joined<["-"], "faddress-space-map-mangling=">, MetaVarName<"<yes|no|target>">,
+ HelpText<"Set the mode for address space map based mangling; OpenCL testing purposes only">;
+def funknown_anytype : Flag<["-"], "funknown-anytype">,
+ HelpText<"Enable parser support for the __unknown_anytype type; for testing purposes only">;
+def fdebugger_support : Flag<["-"], "fdebugger-support">,
+ HelpText<"Enable special debugger support behavior">;
+def fdebugger_cast_result_to_id : Flag<["-"], "fdebugger-cast-result-to-id">,
+ HelpText<"Enable casting unknown expression results to id">;
+def fdebugger_objc_literal : Flag<["-"], "fdebugger-objc-literal">,
+ HelpText<"Enable special debugger support for Objective-C subscripting and literals">;
+def fdeprecated_macro : Flag<["-"], "fdeprecated-macro">,
+ HelpText<"Defines the __DEPRECATED macro">;
+def fno_deprecated_macro : Flag<["-"], "fno-deprecated-macro">,
+ HelpText<"Undefines the __DEPRECATED macro">;
+def fobjc_subscripting_legacy_runtime : Flag<["-"], "fobjc-subscripting-legacy-runtime">,
+ HelpText<"Allow Objective-C array and dictionary subscripting in legacy runtime">;
+def vtordisp_mode_EQ : Joined<["-"], "vtordisp-mode=">,
+ HelpText<"Control vtordisp placement on win32 targets">;
+def fno_rtti_data : Flag<["-"], "fno-rtti-data">,
+ HelpText<"Control emission of RTTI data">;
+def fnative_half_type: Flag<["-"], "fnative-half-type">,
+ HelpText<"Use the native half type for __fp16 instead of promoting to float">;
+def fallow_half_arguments_and_returns : Flag<["-"], "fallow-half-arguments-and-returns">,
+ HelpText<"Allow function arguments and returns of type half">;
+
+// C++ TSes.
+def fcoroutines : Flag<["-"], "fcoroutines">,
+ HelpText<"Enable support for the C++ Coroutines TS">;
+
+//===----------------------------------------------------------------------===//
+// Header Search Options
+//===----------------------------------------------------------------------===//
+
+def nostdsysteminc : Flag<["-"], "nostdsysteminc">,
+ HelpText<"Disable standard system #include directories">;
+def fdisable_module_hash : Flag<["-"], "fdisable-module-hash">,
+ HelpText<"Disable the module hash">;
+def c_isystem : JoinedOrSeparate<["-"], "c-isystem">, MetaVarName<"<directory>">,
+ HelpText<"Add directory to the C SYSTEM include search path">;
+def objc_isystem : JoinedOrSeparate<["-"], "objc-isystem">,
+ MetaVarName<"<directory>">,
+ HelpText<"Add directory to the ObjC SYSTEM include search path">;
+def objcxx_isystem : JoinedOrSeparate<["-"], "objcxx-isystem">,
+ MetaVarName<"<directory>">,
+ HelpText<"Add directory to the ObjC++ SYSTEM include search path">;
+def internal_isystem : JoinedOrSeparate<["-"], "internal-isystem">,
+ MetaVarName<"<directory>">,
+ HelpText<"Add directory to the internal system include search path; these "
+ "are assumed to not be user-provided and are used to model system "
+ "and standard headers' paths.">;
+def internal_externc_isystem : JoinedOrSeparate<["-"], "internal-externc-isystem">,
+ MetaVarName<"<directory>">,
+ HelpText<"Add directory to the internal system include search path with "
+ "implicit extern \"C\" semantics; these are assumed to not be "
+ "user-provided and are used to model system and standard headers' "
+ "paths.">;
+
+//===----------------------------------------------------------------------===//
+// Preprocessor Options
+//===----------------------------------------------------------------------===//
+
+def include_pth : Separate<["-"], "include-pth">, MetaVarName<"<file>">,
+ HelpText<"Include file before parsing">;
+def chain_include : Separate<["-"], "chain-include">, MetaVarName<"<file>">,
+ HelpText<"Include and chain a header file after turning it into PCH">;
+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 detailed_preprocessing_record : Flag<["-"], "detailed-preprocessing-record">,
+ HelpText<"include a detailed record of preprocessing actions">;
+
+//===----------------------------------------------------------------------===//
+// 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_strict_aliasing : Flag<["-"], "cl-strict-aliasing">,
+ HelpText<"OpenCL only. This option does nothing and is for compatibility with OpenCL 1.0">;
+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_kernel_arg_info : Flag<["-"], "cl-kernel-arg-info">,
+ HelpText<"OpenCL only. Generate kernel argument metadata.">;
+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">;
+def cl_denorms_are_zero : Flag<["-"], "cl-denorms-are-zero">,
+ HelpText<"OpenCL only. Allow denormals to be flushed to zero">;
+
+//===----------------------------------------------------------------------===//
+// CUDA Options
+//===----------------------------------------------------------------------===//
+
+def fcuda_is_device : Flag<["-"], "fcuda-is-device">,
+ HelpText<"Generate code for CUDA device">;
+def fcuda_allow_host_calls_from_host_device : Flag<["-"],
+ "fcuda-allow-host-calls-from-host-device">,
+ HelpText<"Allow host device functions to call host functions">;
+def fcuda_disable_target_call_checks : Flag<["-"],
+ "fcuda-disable-target-call-checks">,
+ HelpText<"Disable all cross-target (host, device, etc.) call checks in CUDA">;
+def fcuda_include_gpubinary : Separate<["-"], "fcuda-include-gpubinary">,
+ HelpText<"Incorporate CUDA device-side binary into host object file.">;
+def fcuda_target_overloads : Flag<["-"], "fcuda-target-overloads">,
+ HelpText<"Enable function overloads based on CUDA target attributes.">;
+
+//===----------------------------------------------------------------------===//
+// OpenMP Options
+//===----------------------------------------------------------------------===//
+
+def fopenmp_is_device : Flag<["-"], "fopenmp-is-device">,
+ HelpText<"Generate code only for an OpenMP target device.">;
+def omp_host_ir_file_path : Separate<["-"], "omp-host-ir-file-path">,
+ HelpText<"Path to the IR file produced by the frontend for the host.">;
+
+} // let Flags = [CC1Option]
+
+
+//===----------------------------------------------------------------------===//
+// cc1as-only Options
+//===----------------------------------------------------------------------===//
+
+let Flags = [CC1AsOption, NoDriverOption] in {
+
+// Language Options
+def n : Flag<["-"], "n">,
+ HelpText<"Don't automatically start assembly file with a text section">;
+
+// Frontend Options
+def filetype : Separate<["-"], "filetype">,
+ HelpText<"Specify the output file type ('asm', 'null', or 'obj')">;
+
+// 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 dwarf_debug_producer : Separate<["-"], "dwarf-debug-producer">,
+ HelpText<"The string to embed in the Dwarf debug AT_producer record.">;
+
+} // let Flags = [CC1AsOption]
diff --git a/contrib/llvm/tools/clang/include/clang/Driver/CLCompatOptions.td b/contrib/llvm/tools/clang/include/clang/Driver/CLCompatOptions.td
new file mode 100644
index 0000000..16a5b72
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Driver/CLCompatOptions.td
@@ -0,0 +1,342 @@
+//===--- CLCompatOptions.td - Options for clang-cl ------------------------===//
+//
+// 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-cl.
+//
+//===----------------------------------------------------------------------===//
+
+def cl_Group : OptionGroup<"<clang-cl options>">,
+ HelpText<"CL.EXE COMPATIBILITY OPTIONS">;
+
+def cl_compile_Group : OptionGroup<"<clang-cl compile-only options>">,
+ Group<cl_Group>;
+
+def cl_ignored_Group : OptionGroup<"<clang-cl ignored options>">,
+ Group<cl_Group>;
+
+class CLFlag<string name> : Option<["/", "-"], name, KIND_FLAG>,
+ Group<cl_Group>, Flags<[CLOption, DriverOption]>;
+
+class CLCompileFlag<string name> : Option<["/", "-"], name, KIND_FLAG>,
+ Group<cl_compile_Group>, Flags<[CLOption, DriverOption]>;
+
+class CLIgnoredFlag<string name> : Option<["/", "-"], name, KIND_FLAG>,
+ Group<cl_ignored_Group>, Flags<[CLOption, DriverOption, HelpHidden]>;
+
+class CLJoined<string name> : Option<["/", "-"], name, KIND_JOINED>,
+ Group<cl_Group>, Flags<[CLOption, DriverOption]>;
+
+class CLCompileJoined<string name> : Option<["/", "-"], name, KIND_JOINED>,
+ Group<cl_compile_Group>, Flags<[CLOption, DriverOption]>;
+
+class CLIgnoredJoined<string name> : Option<["/", "-"], name, KIND_JOINED>,
+ Group<cl_ignored_Group>, Flags<[CLOption, DriverOption, HelpHidden]>;
+
+class CLJoinedOrSeparate<string name> : Option<["/", "-"], name,
+ KIND_JOINED_OR_SEPARATE>, Group<cl_Group>, Flags<[CLOption, DriverOption]>;
+
+class CLCompileJoinedOrSeparate<string name> : Option<["/", "-"], name,
+ KIND_JOINED_OR_SEPARATE>, Group<cl_compile_Group>,
+ Flags<[CLOption, DriverOption]>;
+
+class CLRemainingArgs<string name> : Option<["/", "-"], name,
+ KIND_REMAINING_ARGS>, Group<cl_Group>, Flags<[CLOption, DriverOption]>;
+
+// Aliases:
+// (We don't put any of these in cl_compile_Group as the options they alias are
+// already in the right group.)
+
+def _SLASH_Brepro : CLFlag<"Brepro">,
+ HelpText<"Emit an object file which can be reproduced over time">,
+ Alias<mincremental_linker_compatible>;
+def _SLASH_Brepro_ : CLFlag<"Brepro-">,
+ HelpText<"Emit an object file which cannot be reproduced over time">,
+ Alias<mno_incremental_linker_compatible>;
+def _SLASH_C : CLFlag<"C">,
+ HelpText<"Don't discard comments when preprocessing">, Alias<C>;
+def _SLASH_c : CLFlag<"c">, HelpText<"Compile only">, Alias<c>;
+def _SLASH_D : CLJoinedOrSeparate<"D">, HelpText<"Define macro">,
+ MetaVarName<"<macro[=value]>">, Alias<D>;
+def _SLASH_E : CLFlag<"E">, HelpText<"Preprocess to stdout">, Alias<E>;
+def _SLASH_fp_except : CLFlag<"fp:except">, HelpText<"">, Alias<ftrapping_math>;
+def _SLASH_fp_except_ : CLFlag<"fp:except-">,
+ HelpText<"">, Alias<fno_trapping_math>;
+def _SLASH_fp_fast : CLFlag<"fp:fast">, HelpText<"">, Alias<ffast_math>;
+def _SLASH_fp_precise : CLFlag<"fp:precise">,
+ HelpText<"">, Alias<fno_fast_math>;
+def _SLASH_fp_strict : CLFlag<"fp:strict">, HelpText<"">, Alias<fno_fast_math>;
+def _SLASH_GA : CLFlag<"GA">, Alias<ftlsmodel_EQ>, AliasArgs<["local-exec"]>,
+ HelpText<"Assume thread-local variables are defined in the executable">;
+def _SLASH_GR : CLFlag<"GR">, HelpText<"Enable emission of RTTI data">;
+def _SLASH_GR_ : CLFlag<"GR-">, HelpText<"Disable emission of RTTI data">;
+def _SLASH_GF_ : CLFlag<"GF-">, HelpText<"Disable string pooling">,
+ Alias<fwritable_strings>;
+def _SLASH_Gs : CLJoined<"Gs">, HelpText<"Set stack probe size">,
+ Alias<mstack_probe_size>;
+def _SLASH_Gy : CLFlag<"Gy">, HelpText<"Put each function in its own section">,
+ Alias<ffunction_sections>;
+def _SLASH_Gy_ : CLFlag<"Gy-">,
+ HelpText<"Don't put each function in its own section">,
+ Alias<fno_function_sections>;
+def _SLASH_Gw : CLFlag<"Gw">, HelpText<"Put each data item in its own section">,
+ Alias<fdata_sections>;
+def _SLASH_Gw_ : CLFlag<"Gw-">,
+ HelpText<"Don't put each data item in its own section">,
+ Alias<fno_data_sections>;
+def _SLASH_help : CLFlag<"help">, Alias<help>,
+ HelpText<"Display available options">;
+def _SLASH_HELP : CLFlag<"HELP">, Alias<help>;
+def _SLASH_I : CLJoinedOrSeparate<"I">,
+ HelpText<"Add directory to include search path">, MetaVarName<"<dir>">,
+ Alias<I>;
+def _SLASH_J : CLFlag<"J">, HelpText<"Make char type unsigned">,
+ Alias<funsigned_char>;
+def _SLASH_O0 : CLFlag<"O0">, Alias<O0>;
+def _SLASH_O : CLJoined<"O">, HelpText<"Optimization level">;
+def _SLASH_Ob0 : CLFlag<"Ob0">, HelpText<"Disable inlining">,
+ Alias<fno_inline>;
+def _SLASH_Od : CLFlag<"Od">, HelpText<"Disable optimization">, Alias<O0>;
+def _SLASH_Oi : CLFlag<"Oi">, HelpText<"Enable use of builtin functions">,
+ Alias<fbuiltin>;
+def _SLASH_Oi_ : CLFlag<"Oi-">, HelpText<"Disable use of builtin functions">,
+ Alias<fno_builtin>;
+def _SLASH_Os : CLFlag<"Os">, HelpText<"Optimize for size">, Alias<O>,
+ AliasArgs<["s"]>;
+def _SLASH_Ot : CLFlag<"Ot">, HelpText<"Optimize for speed">, Alias<O>,
+ AliasArgs<["2"]>;
+def _SLASH_QUESTION : CLFlag<"?">, Alias<help>,
+ HelpText<"Display available options">;
+def _SLASH_Qvec : CLFlag<"Qvec">,
+ HelpText<"Enable the loop vectorization passes">, Alias<fvectorize>;
+def _SLASH_Qvec_ : CLFlag<"Qvec-">,
+ HelpText<"Disable the loop vectorization passes">, Alias<fno_vectorize>;
+def _SLASH_showIncludes : CLFlag<"showIncludes">,
+ HelpText<"Print info about included files to stderr">,
+ Alias<show_includes>;
+def _SLASH_U : CLJoinedOrSeparate<"U">, HelpText<"Undefine macro">,
+ MetaVarName<"<macro>">, Alias<U>;
+def _SLASH_W0 : CLFlag<"W0">, HelpText<"Disable all warnings">, Alias<w>;
+def _SLASH_W1 : CLFlag<"W1">, HelpText<"Enable -Wall">, Alias<Wall>;
+def _SLASH_W2 : CLFlag<"W2">, HelpText<"Enable -Wall">, Alias<Wall>;
+def _SLASH_W3 : CLFlag<"W3">, HelpText<"Enable -Wall">, Alias<Wall>;
+def _SLASH_W4 : CLFlag<"W4">, HelpText<"Enable -Wall and -Wextra">, Alias<WCL4>;
+def _SLASH_Wall : CLFlag<"Wall">, HelpText<"Enable -Wall and -Wextra">, Alias<WCL4>;
+def _SLASH_WX : CLFlag<"WX">, HelpText<"Treat warnings as errors">,
+ Alias<W_Joined>, AliasArgs<["error"]>;
+def _SLASH_WX_ : CLFlag<"WX-">, HelpText<"Do not treat warnings as errors">,
+ Alias<W_Joined>, AliasArgs<["no-error"]>;
+def _SLASH_w_flag : CLFlag<"w">, HelpText<"Disable all warnings">, Alias<w>;
+def _SLASH_wd4005 : CLFlag<"wd4005">, Alias<W_Joined>,
+ AliasArgs<["no-macro-redefined"]>;
+def _SLASH_wd4100 : CLFlag<"wd4100">, Alias<W_Joined>,
+ AliasArgs<["no-unused-parameter"]>;
+def _SLASH_wd4910 : CLFlag<"wd4910">, Alias<W_Joined>,
+ AliasArgs<["no-dllexport-explicit-instantiation-decl"]>;
+def _SLASH_wd4996 : CLFlag<"wd4996">, Alias<W_Joined>,
+ AliasArgs<["no-deprecated-declarations"]>;
+def _SLASH_vd : CLJoined<"vd">, HelpText<"Control vtordisp placement">,
+ Alias<vtordisp_mode_EQ>;
+def _SLASH_Zc_sizedDealloc : CLFlag<"Zc:sizedDealloc">,
+ HelpText<"Enable C++14 sized global deallocation functions">,
+ Alias<fsized_deallocation>;
+def _SLASH_Zc_sizedDealloc_ : CLFlag<"Zc:sizedDealloc-">,
+ HelpText<"Disable C++14 sized global deallocation functions">,
+ Alias<fno_sized_deallocation>;
+def _SLASH_Zc_strictStrings : CLFlag<"Zc:strictStrings">,
+ HelpText<"Treat string literals as const">, Alias<W_Joined>,
+ AliasArgs<["error=c++11-compat-deprecated-writable-strings"]>;
+def _SLASH_Zc_threadSafeInit : CLFlag<"Zc:threadSafeInit">,
+ HelpText<"Enable thread-safe initialization of static variables">,
+ Alias<fthreadsafe_statics>;
+def _SLASH_Zc_threadSafeInit_ : CLFlag<"Zc:threadSafeInit-">,
+ HelpText<"Disable thread-safe initialization of static variables">,
+ Alias<fno_threadsafe_statics>;
+def _SLASH_Zc_trigraphs : CLFlag<"Zc:trigraphs">,
+ HelpText<"Enable trigraphs">, Alias<ftrigraphs>;
+def _SLASH_Zc_trigraphs_off : CLFlag<"Zc:trigraphs-">,
+ HelpText<"Disable trigraphs (default)">, Alias<fno_trigraphs>;
+def _SLASH_Z7 : CLFlag<"Z7">,
+ HelpText<"Enable CodeView debug information in object files">;
+def _SLASH_Zi : CLFlag<"Zi">, Alias<_SLASH_Z7>,
+ HelpText<"Alias for /Z7. Does not produce PDBs.">;
+def _SLASH_Zp : CLJoined<"Zp">,
+ HelpText<"Specify the default maximum struct packing alignment">,
+ Alias<fpack_struct_EQ>;
+def _SLASH_Zp_flag : CLFlag<"Zp">,
+ HelpText<"Set the default maximum struct packing alignment to 1">,
+ Alias<fpack_struct_EQ>, AliasArgs<["1"]>;
+def _SLASH_Zs : CLFlag<"Zs">, HelpText<"Syntax-check only">,
+ Alias<fsyntax_only>;
+
+
+// Non-aliases:
+
+def _SLASH_arch : CLCompileJoined<"arch:">,
+ HelpText<"Set architecture for code generation">;
+
+def _SLASH_M_Group : OptionGroup<"</M group>">, Group<cl_compile_Group>;
+def _SLASH_volatile_Group : OptionGroup<"</volatile group>">,
+ Group<cl_compile_Group>;
+
+def _SLASH_EH : CLJoined<"EH">, HelpText<"Exception handling model">;
+def _SLASH_EP : CLFlag<"EP">,
+ HelpText<"Disable linemarker output and preprocess to stdout">;
+def _SLASH_FA : CLFlag<"FA">,
+ HelpText<"Output assembly code file during compilation">;
+def _SLASH_Fa : CLJoined<"Fa">,
+ HelpText<"Output assembly code to this file during compilation (with /FA)">,
+ MetaVarName<"<file or directory>">;
+def _SLASH_fallback : CLCompileFlag<"fallback">,
+ HelpText<"Fall back to cl.exe if clang-cl fails to compile">;
+def _SLASH_FI : CLJoinedOrSeparate<"FI">,
+ HelpText<"Include file before parsing">, Alias<include_>;
+def _SLASH_Fe : CLJoined<"Fe">,
+ HelpText<"Set output executable file or directory (ends in / or \\)">,
+ MetaVarName<"<file or directory>">;
+def _SLASH_Fi : CLCompileJoined<"Fi">,
+ HelpText<"Set preprocess output file name (with /P)">,
+ MetaVarName<"<file>">;
+def _SLASH_Fo : CLCompileJoined<"Fo">,
+ HelpText<"Set output object file, or directory (ends in / or \\) (with /c)">,
+ MetaVarName<"<file or directory>">;
+def _SLASH_LD : CLFlag<"LD">, HelpText<"Create DLL">;
+def _SLASH_LDd : CLFlag<"LDd">, HelpText<"Create debug DLL">;
+def _SLASH_link : CLRemainingArgs<"link">,
+ HelpText<"Forward options to the linker">, MetaVarName<"<options>">;
+def _SLASH_MD : Option<["/", "-"], "MD", KIND_FLAG>, Group<_SLASH_M_Group>,
+ Flags<[CLOption, DriverOption]>, HelpText<"Use DLL run-time">;
+def _SLASH_MDd : Option<["/", "-"], "MDd", KIND_FLAG>, Group<_SLASH_M_Group>,
+ Flags<[CLOption, DriverOption]>, HelpText<"Use DLL debug run-time">;
+def _SLASH_MT : Option<["/", "-"], "MT", KIND_FLAG>, Group<_SLASH_M_Group>,
+ Flags<[CLOption, DriverOption]>, HelpText<"Use static run-time">;
+def _SLASH_MTd : Option<["/", "-"], "MTd", KIND_FLAG>, Group<_SLASH_M_Group>,
+ Flags<[CLOption, DriverOption]>, HelpText<"Use static debug run-time">;
+def _SLASH_o : CLJoinedOrSeparate<"o">,
+ HelpText<"Set output file or directory (ends in / or \\)">,
+ MetaVarName<"<file or directory>">;
+def _SLASH_P : CLFlag<"P">, HelpText<"Preprocess to file">;
+def _SLASH_Tc : CLCompileJoinedOrSeparate<"Tc">,
+ HelpText<"Specify a C source file">, MetaVarName<"<filename>">;
+def _SLASH_TC : CLCompileFlag<"TC">, HelpText<"Treat all source files as C">;
+def _SLASH_Tp : CLCompileJoinedOrSeparate<"Tp">,
+ HelpText<"Specify a C++ source file">, MetaVarName<"<filename>">;
+def _SLASH_TP : CLCompileFlag<"TP">, HelpText<"Treat all source files as C++">;
+def _SLASH_volatile_iso : Option<["/", "-"], "volatile:iso", KIND_FLAG>,
+ Group<_SLASH_volatile_Group>, Flags<[CLOption, DriverOption]>,
+ HelpText<"Volatile loads and stores have standard semantics">;
+def _SLASH_vmb : CLFlag<"vmb">,
+ HelpText<"Use a best-case representation method for member pointers">;
+def _SLASH_vmg : CLFlag<"vmg">,
+ HelpText<"Use a most-general representation for member pointers">;
+def _SLASH_vms : CLFlag<"vms">,
+ HelpText<"Set the default most-general representation to single inheritance">;
+def _SLASH_vmm : CLFlag<"vmm">,
+ HelpText<"Set the default most-general representation to "
+ "multiple inheritance">;
+def _SLASH_vmv : CLFlag<"vmv">,
+ HelpText<"Set the default most-general representation to "
+ "virtual inheritance">;
+def _SLASH_volatile_ms : Option<["/", "-"], "volatile:ms", KIND_FLAG>,
+ Group<_SLASH_volatile_Group>, Flags<[CLOption, DriverOption]>,
+ HelpText<"Volatile loads and stores have acquire and release semantics">;
+def _SLASH_Zl : CLFlag<"Zl">,
+ HelpText<"Don't mention any default libraries in the object file">;
+
+// Ignored:
+
+def _SLASH_analyze_ : CLIgnoredFlag<"analyze-">;
+def _SLASH_bigobj : CLIgnoredFlag<"bigobj">;
+def _SLASH_cgthreads : CLIgnoredJoined<"cgthreads">;
+def _SLASH_d2Zi_PLUS : CLIgnoredFlag<"d2Zi+">;
+def _SLASH_errorReport : CLIgnoredJoined<"errorReport">;
+def _SLASH_Fd : CLIgnoredJoined<"Fd">;
+def _SLASH_FS : CLIgnoredFlag<"FS">, HelpText<"Force synchronous PDB writes">;
+def _SLASH_Gd : CLIgnoredFlag<"Gd">;
+def _SLASH_GF : CLIgnoredFlag<"GF">;
+def _SLASH_GS_ : CLIgnoredFlag<"GS-">;
+def _SLASH_kernel_ : CLIgnoredFlag<"kernel-">;
+def _SLASH_nologo : CLIgnoredFlag<"nologo">;
+def _SLASH_Ob1 : CLIgnoredFlag<"Ob1">;
+def _SLASH_Ob2 : CLIgnoredFlag<"Ob2">;
+def _SLASH_Og : CLIgnoredFlag<"Og">;
+def _SLASH_openmp_ : CLIgnoredFlag<"openmp-">;
+def _SLASH_RTC : CLIgnoredJoined<"RTC">;
+def _SLASH_sdl : CLIgnoredFlag<"sdl">;
+def _SLASH_sdl_ : CLIgnoredFlag<"sdl-">;
+def _SLASH_w : CLIgnoredJoined<"w">;
+def _SLASH_Zc_auto : CLIgnoredFlag<"Zc:auto">;
+def _SLASH_Zc_forScope : CLIgnoredFlag<"Zc:forScope">;
+def _SLASH_Zc_inline : CLIgnoredFlag<"Zc:inline">;
+def _SLASH_Zc_rvalueCast : CLIgnoredFlag<"Zc:rvalueCast">;
+def _SLASH_Zc_wchar_t : CLIgnoredFlag<"Zc:wchar_t">;
+def _SLASH_Zm : CLIgnoredJoined<"Zm">;
+def _SLASH_Zo : CLIgnoredFlag<"Zo">;
+def _SLASH_Zo_ : CLIgnoredFlag<"Zo-">;
+
+
+// Unsupported:
+
+def _SLASH_AI : CLJoined<"AI">;
+def _SLASH_clr : CLJoined<"clr">;
+def _SLASH_doc : CLJoined<"doc">;
+def _SLASH_FA_joined : CLJoined<"FA">;
+def _SLASH_favor : CLJoined<"favor">;
+def _SLASH_FC : CLFlag<"FC">;
+def _SLASH_F : CLFlag<"F">;
+def _SLASH_Fm : CLJoined<"Fm">;
+def _SLASH_Fp : CLJoined<"Fp">;
+def _SLASH_Fr : CLJoined<"Fr">;
+def _SLASH_FR : CLJoined<"FR">;
+def _SLASH_FU : CLJoinedOrSeparate<"FU">;
+def _SLASH_Fx : CLFlag<"Fx">;
+def _SLASH_G1 : CLFlag<"G1">;
+def _SLASH_G2 : CLFlag<"G2">;
+def _SLASH_Ge : CLFlag<"Ge">;
+def _SLASH_Gh : CLFlag<"Gh">;
+def _SLASH_GH : CLFlag<"GH">;
+def _SLASH_GL : CLFlag<"GL">;
+def _SLASH_GL_ : CLFlag<"GL-">;
+def _SLASH_Gm : CLFlag<"Gm">;
+def _SLASH_Gm_ : CLFlag<"Gm-">;
+def _SLASH_Gr : CLFlag<"Gr">;
+def _SLASH_GS : CLFlag<"GS">;
+def _SLASH_GT : CLFlag<"GT">;
+def _SLASH_Guard : CLJoined<"guard:">;
+def _SLASH_GX : CLFlag<"GX">;
+def _SLASH_Gv : CLFlag<"Gv">;
+def _SLASH_Gz : CLFlag<"Gz">;
+def _SLASH_GZ : CLFlag<"GZ">;
+def _SLASH_H : CLFlag<"H">;
+def _SLASH_homeparams : CLFlag<"homeparams">;
+def _SLASH_hotpatch : CLFlag<"hotpatch">;
+def _SLASH_kernel : CLFlag<"kernel">;
+def _SLASH_LN : CLFlag<"LN">;
+def _SLASH_MP : CLJoined<"MP">;
+def _SLASH_openmp : CLFlag<"openmp">;
+def _SLASH_Qfast_transcendentals : CLFlag<"Qfast_transcendentals">;
+def _SLASH_QIfist : CLFlag<"QIfist">;
+def _SLASH_Qimprecise_fwaits : CLFlag<"Qimprecise_fwaits">;
+def _SLASH_Qpar : CLFlag<"Qpar">;
+def _SLASH_Qvec_report : CLJoined<"Qvec-report">;
+def _SLASH_u : CLFlag<"u">;
+def _SLASH_V : CLFlag<"V">;
+def _SLASH_WL : CLFlag<"WL">;
+def _SLASH_Wp64 : CLFlag<"Wp64">;
+def _SLASH_X : CLFlag<"X">;
+def _SLASH_Yc : CLJoined<"Yc">;
+def _SLASH_Y_ : CLFlag<"Y-">;
+def _SLASH_Yd : CLFlag<"Yd">;
+def _SLASH_Yl : CLJoined<"Yl">;
+def _SLASH_Yu : CLJoined<"Yu">;
+def _SLASH_Za : CLFlag<"Za">;
+def _SLASH_Zc : CLJoined<"Zc:">;
+def _SLASH_Ze : CLFlag<"Ze">;
+def _SLASH_Zg : CLFlag<"Zg">;
+def _SLASH_ZI : CLFlag<"ZI">;
+def _SLASH_ZW : CLJoined<"ZW">;
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..12ff068
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Driver/Compilation.h
@@ -0,0 +1,202 @@
+//===--- 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 LLVM_CLANG_DRIVER_COMPILATION_H
+#define LLVM_CLANG_DRIVER_COMPILATION_H
+
+#include "clang/Driver/Action.h"
+#include "clang/Driver/Job.h"
+#include "clang/Driver/Util.h"
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/Support/Path.h"
+
+namespace llvm {
+namespace opt {
+ class DerivedArgList;
+ class InputArgList;
+}
+}
+
+namespace clang {
+namespace driver {
+ class Driver;
+ 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;
+
+ const ToolChain *CudaHostToolChain;
+ const ToolChain *CudaDeviceToolChain;
+
+ /// The original (untranslated) input argument list.
+ llvm::opt::InputArgList *Args;
+
+ /// The driver translated arguments. Note that toolchains may perform their
+ /// own argument translation.
+ llvm::opt::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 *>,
+ llvm::opt::DerivedArgList *> TCArgs;
+
+ /// Temporary files which should be removed on exit.
+ llvm::opt::ArgStringList TempFiles;
+
+ /// Result files which should be removed on failure.
+ ArgStringMap ResultFiles;
+
+ /// Result files which are generated correctly on failure, and which should
+ /// only be removed if we crash.
+ ArgStringMap FailureResultFiles;
+
+ /// Redirection for stdout, stderr, etc.
+ const StringRef **Redirects;
+
+ /// Whether we're compiling for diagnostic purposes.
+ bool ForDiagnostics;
+
+public:
+ Compilation(const Driver &D, const ToolChain &DefaultToolChain,
+ llvm::opt::InputArgList *Args,
+ llvm::opt::DerivedArgList *TranslatedArgs);
+ ~Compilation();
+
+ const Driver &getDriver() const { return TheDriver; }
+
+ const ToolChain &getDefaultToolChain() const { return DefaultToolChain; }
+ const ToolChain *getCudaHostToolChain() const { return CudaHostToolChain; }
+ const ToolChain *getCudaDeviceToolChain() const {
+ return CudaDeviceToolChain;
+ }
+
+ void setCudaHostToolChain(const ToolChain *HostToolChain) {
+ CudaHostToolChain = HostToolChain;
+ }
+ void setCudaDeviceToolChain(const ToolChain *DeviceToolChain) {
+ CudaDeviceToolChain = DeviceToolChain;
+ }
+
+ const llvm::opt::InputArgList &getInputArgs() const { return *Args; }
+
+ const llvm::opt::DerivedArgList &getArgs() const { return *TranslatedArgs; }
+
+ llvm::opt::DerivedArgList &getArgs() { return *TranslatedArgs; }
+
+ ActionList &getActions() { return Actions; }
+ const ActionList &getActions() const { return Actions; }
+
+ JobList &getJobs() { return Jobs; }
+ const JobList &getJobs() const { return Jobs; }
+
+ void addCommand(std::unique_ptr<Command> C) { Jobs.addJob(std::move(C)); }
+
+ const llvm::opt::ArgStringList &getTempFiles() const { return TempFiles; }
+
+ const ArgStringMap &getResultFiles() const { return ResultFiles; }
+
+ const ArgStringMap &getFailureResultFiles() const {
+ return FailureResultFiles;
+ }
+
+ /// Returns the sysroot path.
+ StringRef getSysRoot() const;
+
+ /// getArgsForToolChain - Return the derived argument list for the
+ /// tool chain \p TC (or the default tool chain, if TC is not specified).
+ ///
+ /// \param BoundArch - The bound architecture name, or 0.
+ const llvm::opt::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, const JobAction *JA) {
+ ResultFiles[JA] = Name;
+ return Name;
+ }
+
+ /// addFailureResultFile - Add a file to remove if we crash, and returns its
+ /// argument.
+ const char *addFailureResultFile(const char *Name, const JobAction *JA) {
+ FailureResultFiles[JA] = Name;
+ return Name;
+ }
+
+ /// CleanupFile - Delete a given file.
+ ///
+ /// \param IssueErrors - Report failures as errors.
+ /// \return Whether the file was removed successfully.
+ bool CleanupFile(const char *File, bool IssueErrors = false) const;
+
+ /// CleanupFileList - Remove the files in the given list.
+ ///
+ /// \param IssueErrors - Report failures as errors.
+ /// \return Whether all files were removed successfully.
+ bool CleanupFileList(const llvm::opt::ArgStringList &Files,
+ bool IssueErrors = false) const;
+
+ /// CleanupFileMap - Remove the files in the given map.
+ ///
+ /// \param JA - If specified, only delete the files associated with this
+ /// JobAction. Otherwise, delete all files in the map.
+ /// \param IssueErrors - Report failures as errors.
+ /// \return Whether all files were removed successfully.
+ bool CleanupFileMap(const ArgStringMap &Files,
+ const JobAction *JA,
+ bool IssueErrors = false) 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 FailingCommands - For non-zero results, this will be a vector of
+ /// failing commands and their associated result code.
+ void ExecuteJobs(
+ const JobList &Jobs,
+ SmallVectorImpl<std::pair<int, const Command *>> &FailingCommands) const;
+
+ /// initCompilationForDiagnostics - Remove stale state and suppress output
+ /// so compilation can be reexecuted to generate additional diagnostic
+ /// information (e.g., preprocessed source(s)).
+ void initCompilationForDiagnostics();
+
+ /// Return true if we're compiling for diagnostics.
+ bool isForDiagnostics() const { return ForDiagnostics; }
+};
+
+} // 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..c9940ba
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Driver/Driver.h
@@ -0,0 +1,468 @@
+//===--- 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 LLVM_CLANG_DRIVER_DRIVER_H
+#define LLVM_CLANG_DRIVER_DRIVER_H
+
+#include "clang/Basic/Diagnostic.h"
+#include "clang/Basic/LLVM.h"
+#include "clang/Driver/Phases.h"
+#include "clang/Driver/Types.h"
+#include "clang/Driver/Util.h"
+#include "llvm/ADT/StringMap.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/ADT/Triple.h"
+#include "llvm/Support/Path.h" // FIXME: Kill when CompilationInfo
+#include <memory>
+ // lands.
+#include <list>
+#include <set>
+#include <string>
+
+namespace llvm {
+namespace opt {
+ class Arg;
+ class ArgList;
+ class DerivedArgList;
+ class InputArgList;
+ class OptTable;
+}
+}
+
+namespace clang {
+
+namespace vfs {
+class FileSystem;
+}
+
+namespace driver {
+
+ class Action;
+ class Command;
+ class Compilation;
+ class InputInfo;
+ class JobList;
+ class JobAction;
+ class SanitizerArgs;
+ class ToolChain;
+
+/// Describes the kind of LTO mode selected via -f(no-)?lto(=.*)? options.
+enum LTOKind {
+ LTOK_None,
+ LTOK_Full,
+ LTOK_Thin,
+ LTOK_Unknown
+};
+
+/// Driver - Encapsulate logic for constructing compilation processes
+/// from a set of gcc-driver-like command line arguments.
+class Driver {
+ llvm::opt::OptTable *Opts;
+
+ DiagnosticsEngine &Diags;
+
+ IntrusiveRefCntPtr<vfs::FileSystem> VFS;
+
+ enum DriverMode {
+ GCCMode,
+ GXXMode,
+ CPPMode,
+ CLMode
+ } Mode;
+
+ enum SaveTempsMode {
+ SaveTempsNone,
+ SaveTempsCwd,
+ SaveTempsObj
+ } SaveTemps;
+
+ /// LTO mode selected via -f(no-)?lto(=.*)? options.
+ LTOKind LTOMode;
+
+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 emulate 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 SmallVector<std::string, 4> prefix_list;
+ prefix_list PrefixDirs;
+
+ /// sysroot, if present
+ std::string SysRoot;
+
+ /// Dynamic loader prefix, if present
+ std::string DyldPrefix;
+
+ /// If the standard library is used
+ bool UseStdLib;
+
+ /// Default target triple.
+ std::string DefaultTargetTriple;
+
+ /// Driver title to use with help.
+ std::string DriverTitle;
+
+ /// Information about the host which can be overridden 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;
+
+ /// The file to log CC_LOG_DIAGNOSTICS output to, if enabled.
+ const char *CCLogDiagnosticsFilename;
+
+ /// A list of inputs and their types for the given arguments.
+ typedef SmallVector<std::pair<types::ID, const llvm::opt::Arg *>, 16>
+ InputList;
+
+ /// Whether the driver should follow g++ like behavior.
+ bool CCCIsCXX() const { return Mode == GXXMode; }
+
+ /// Whether the driver is just the preprocessor.
+ bool CCCIsCPP() const { return Mode == CPPMode; }
+
+ /// Whether the driver should follow cl.exe like behavior.
+ bool IsCLMode() const { return Mode == CLMode; }
+
+ /// 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;
+
+ /// Set CC_LOG_DIAGNOSTICS mode, which causes the frontend to log diagnostics
+ /// to CCLogDiagnosticsFilename or to stderr, in a stable machine readable
+ /// format.
+ unsigned CCLogDiagnostics : 1;
+
+ /// Whether the driver is generating diagnostics for debugging purposes.
+ unsigned CCGenDiagnostics : 1;
+
+private:
+ /// Name to use when invoking gcc/g++.
+ std::string CCCGenericGCCName;
+
+ /// Whether to check that input files exist when constructing compilation
+ /// jobs.
+ unsigned CheckInputsExist : 1;
+
+public:
+ /// Use lazy precompiled headers for PCH support.
+ unsigned CCCUsePCH : 1;
+
+private:
+ /// Certain options suppress the 'no input files' warning.
+ bool SuppressMissingInputWarning : 1;
+
+ std::list<std::string> TempFiles;
+ std::list<std::string> ResultFiles;
+
+ /// \brief Cache of all the ToolChains in use by the driver.
+ ///
+ /// This maps from the string representation of a triple to a ToolChain
+ /// created targeting that triple. The driver owns all the ToolChain objects
+ /// stored in it, and will clean them up when torn down.
+ mutable llvm::StringMap<ToolChain *> ToolChains;
+
+private:
+ /// TranslateInputArgs - Create a new derived argument list from the input
+ /// arguments, after applying the standard argument translations.
+ llvm::opt::DerivedArgList *
+ TranslateInputArgs(const llvm::opt::InputArgList &Args) const;
+
+ // getFinalPhase - Determine which compilation mode we are in and record
+ // which option we used to determine the final phase.
+ phases::ID getFinalPhase(const llvm::opt::DerivedArgList &DAL,
+ llvm::opt::Arg **FinalPhaseArg = nullptr) const;
+
+ // Before executing jobs, sets up response files for commands that need them.
+ void setUpResponseFiles(Compilation &C, Command &Cmd);
+
+ void generatePrefixedToolNames(const char *Tool, const ToolChain &TC,
+ SmallVectorImpl<std::string> &Names) const;
+
+public:
+ Driver(StringRef ClangExecutable, StringRef DefaultTargetTriple,
+ DiagnosticsEngine &Diags,
+ IntrusiveRefCntPtr<vfs::FileSystem> VFS = nullptr);
+ ~Driver();
+
+ /// @name Accessors
+ /// @{
+
+ /// Name to use when invoking gcc/g++.
+ const std::string &getCCCGenericGCCName() const { return CCCGenericGCCName; }
+
+ const llvm::opt::OptTable &getOpts() const { return *Opts; }
+
+ const DiagnosticsEngine &getDiags() const { return Diags; }
+
+ vfs::FileSystem &getVFS() const { return *VFS; }
+
+ 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(StringRef Value) {
+ InstalledDir = Value;
+ }
+
+ bool isSaveTempsEnabled() const { return SaveTemps != SaveTempsNone; }
+ bool isSaveTempsObj() const { return SaveTemps == SaveTempsObj; }
+
+ /// @}
+ /// @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(ArrayRef<const char *> Args);
+
+ /// @name Driver Steps
+ /// @{
+
+ /// ParseDriverMode - Look for and handle the driver mode option in Args.
+ void ParseDriverMode(ArrayRef<const char *> Args);
+
+ /// ParseArgStrings - Parse the given list of strings into an
+ /// ArgList.
+ llvm::opt::InputArgList ParseArgStrings(ArrayRef<const char *> Args);
+
+ /// BuildInputs - Construct the list of inputs and their types from
+ /// the given arguments.
+ ///
+ /// \param TC - The default host tool chain.
+ /// \param Args - The input arguments.
+ /// \param Inputs - The list to store the resulting compilation
+ /// inputs onto.
+ void BuildInputs(const ToolChain &TC, llvm::opt::DerivedArgList &Args,
+ InputList &Inputs) const;
+
+ /// BuildActions - Construct the list of actions to perform for the
+ /// given arguments, which are only done for a single architecture.
+ ///
+ /// \param C - The compilation that is being built.
+ /// \param TC - The default host tool chain.
+ /// \param Args - The input arguments.
+ /// \param Actions - The list to store the resulting actions onto.
+ void BuildActions(Compilation &C, const ToolChain &TC,
+ llvm::opt::DerivedArgList &Args, const InputList &Inputs,
+ ActionList &Actions) const;
+
+ /// BuildUniversalActions - Construct the list of actions to perform
+ /// for the given arguments, which may require a universal build.
+ ///
+ /// \param C - The compilation that is being built.
+ /// \param TC - The default host tool chain.
+ void BuildUniversalActions(Compilation &C, const ToolChain &TC,
+ const InputList &BAInputs) const;
+
+ /// BuildJobs - Bind actions to concrete tools and translate
+ /// arguments to form the list of jobs to run.
+ ///
+ /// \param 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, setting
+ /// up response files, removing temporary files, etc.
+ int ExecuteCompilation(Compilation &C,
+ SmallVectorImpl< std::pair<int, const Command *> > &FailingCommands);
+
+ /// generateCompilationDiagnostics - Generate diagnostics information
+ /// including preprocessed source file(s).
+ ///
+ void generateCompilationDiagnostics(Compilation &C,
+ const Command &FailingCommand);
+
+ /// @}
+ /// @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;
+
+ /// PrintVersion - Print the driver version.
+ void PrintVersion(const Compilation &C, raw_ostream &OS) const;
+
+ /// GetFilePath - Lookup \p Name in the list of file search paths.
+ ///
+ /// \param 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 \p Name in the list of program search paths.
+ ///
+ /// \param TC - The provided tool chain for additional information on
+ /// directories to search.
+ //
+ // FIXME: This should be in CompilationInfo.
+ std::string GetProgramPath(const char *Name, const ToolChain &TC) 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
+ /// \p Phase on the \p Input, taking in to account arguments
+ /// like -fsyntax-only or --analyze.
+ std::unique_ptr<Action>
+ ConstructPhaseAction(const ToolChain &TC, const llvm::opt::ArgList &Args,
+ phases::ID Phase, std::unique_ptr<Action> Input) const;
+
+ /// BuildJobsForAction - Construct the jobs to perform for the
+ /// action \p A.
+ void BuildJobsForAction(Compilation &C,
+ const Action *A,
+ const ToolChain *TC,
+ const char *BoundArch,
+ bool AtTopLevel,
+ bool MultipleArchs,
+ const char *LinkingOutput,
+ InputInfo &Result) const;
+
+ /// Returns the default name for linked images (e.g., "a.out").
+ const char *getDefaultImageName() const;
+
+ /// GetNamedOutputPath - Return the name to use for the output of
+ /// the action \p 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 BoundArch - The bound architecture.
+ /// \param AtTopLevel - Whether this is a "top-level" action.
+ /// \param MultipleArchs - Whether multiple -arch options were supplied.
+ const char *GetNamedOutputPath(Compilation &C,
+ const JobAction &JA,
+ const char *BaseInput,
+ const char *BoundArch,
+ bool AtTopLevel,
+ bool MultipleArchs) const;
+
+ /// GetTemporaryPath - Return the pathname of a temporary file to use
+ /// as part of compilation; the file will have the given prefix and suffix.
+ ///
+ /// GCC goes to extra lengths here to be a bit more robust.
+ std::string GetTemporaryPath(StringRef Prefix, const char *Suffix) const;
+
+ /// ShouldUseClangCompiler - Should the clang compiler be used to
+ /// handle this action.
+ bool ShouldUseClangCompiler(const JobAction &JA) const;
+
+ /// Returns true if we are performing any kind of LTO.
+ bool isUsingLTO() const { return LTOMode != LTOK_None; }
+
+ /// Get the specific kind of LTO being performed.
+ LTOKind getLTOMode() const { return LTOMode; }
+
+private:
+ /// Parse the \p Args list for LTO options and record the type of LTO
+ /// compilation based on which -f(no-)?lto(=.*)? option occurs last.
+ void setLTOMode(const llvm::opt::ArgList &Args);
+
+ /// \brief Retrieves a ToolChain for a particular \p Target triple.
+ ///
+ /// Will cache ToolChains for the life of the driver object, and create them
+ /// on-demand.
+ const ToolChain &getToolChain(const llvm::opt::ArgList &Args,
+ const llvm::Triple &Target) const;
+
+ /// @}
+
+ /// \brief Get bitmasks for which option flags to include and exclude based on
+ /// the driver mode.
+ std::pair<unsigned, unsigned> getIncludeExcludeOptionFlagMasks() const;
+
+public:
+ /// 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);
+};
+
+/// \return True if the last defined optimization level is -Ofast.
+/// And False otherwise.
+bool isOptimizationLevelFast(const llvm::opt::ArgList &Args);
+
+} // 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..680338a
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Driver/DriverDiagnostic.h
@@ -0,0 +1,28 @@
+//===--- 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_DRIVER_DRIVERDIAGNOSTIC_H
+#define LLVM_CLANG_DRIVER_DRIVERDIAGNOSTIC_H
+
+#include "clang/Basic/Diagnostic.h"
+
+namespace clang {
+ namespace diag {
+ enum {
+#define DIAG(ENUM,FLAGS,DEFAULT_MAPPING,DESC,GROUP,\
+ SFINAE,NOWERROR,SHOWINSYSHEADER,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/Job.h b/contrib/llvm/tools/clang/include/clang/Driver/Job.h
new file mode 100644
index 0000000..263356f
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Driver/Job.h
@@ -0,0 +1,174 @@
+//===--- 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 LLVM_CLANG_DRIVER_JOB_H
+#define LLVM_CLANG_DRIVER_JOB_H
+
+#include "clang/Basic/LLVM.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/iterator.h"
+#include "llvm/Option/Option.h"
+#include <memory>
+
+namespace llvm {
+ class raw_ostream;
+}
+
+namespace clang {
+namespace driver {
+class Action;
+class Command;
+class Tool;
+class InputInfo;
+
+// Re-export this as clang::driver::ArgStringList.
+using llvm::opt::ArgStringList;
+
+struct CrashReportInfo {
+ StringRef Filename;
+ StringRef VFSPath;
+
+ CrashReportInfo(StringRef Filename, StringRef VFSPath)
+ : Filename(Filename), VFSPath(VFSPath) {}
+};
+
+/// Command - An executable path/name and argument vector to
+/// execute.
+class Command {
+ /// 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).
+ llvm::opt::ArgStringList Arguments;
+
+ /// The list of program arguments which are inputs.
+ llvm::opt::ArgStringList InputFilenames;
+
+ /// Response file name, if this command is set to use one, or nullptr
+ /// otherwise
+ const char *ResponseFile;
+
+ /// The input file list in case we need to emit a file list instead of a
+ /// proper response file
+ llvm::opt::ArgStringList InputFileList;
+
+ /// String storage if we need to create a new argument to specify a response
+ /// file
+ std::string ResponseFileFlag;
+
+ /// When a response file is needed, we try to put most arguments in an
+ /// exclusive file, while others remains as regular command line arguments.
+ /// This functions fills a vector with the regular command line arguments,
+ /// argv, excluding the ones passed in a response file.
+ void buildArgvForResponseFile(llvm::SmallVectorImpl<const char *> &Out) const;
+
+ /// Encodes an array of C strings into a single string separated by whitespace.
+ /// This function will also put in quotes arguments that have whitespaces and
+ /// will escape the regular backslashes (used in Windows paths) and quotes.
+ /// The results are the contents of a response file, written into a raw_ostream.
+ void writeResponseFile(raw_ostream &OS) const;
+
+public:
+ Command(const Action &Source, const Tool &Creator, const char *Executable,
+ const llvm::opt::ArgStringList &Arguments,
+ ArrayRef<InputInfo> Inputs);
+ // FIXME: This really shouldn't be copyable, but is currently copied in some
+ // error handling in Driver::generateCompilationDiagnostics.
+ Command(const Command &) = default;
+ virtual ~Command() {}
+
+ virtual void Print(llvm::raw_ostream &OS, const char *Terminator, bool Quote,
+ CrashReportInfo *CrashInfo = nullptr) const;
+
+ virtual int Execute(const StringRef **Redirects, std::string *ErrMsg,
+ bool *ExecutionFailed) const;
+
+ /// 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; }
+
+ /// Set to pass arguments via a response file when launching the command
+ void setResponseFile(const char *FileName);
+
+ /// Set an input file list, necessary if we need to use a response file but
+ /// the tool being called only supports input files lists.
+ void setInputFileList(llvm::opt::ArgStringList List) {
+ InputFileList = std::move(List);
+ }
+
+ const char *getExecutable() const { return Executable; }
+
+ const llvm::opt::ArgStringList &getArguments() const { return Arguments; }
+
+ /// Print a command argument, and optionally quote it.
+ static void printArg(llvm::raw_ostream &OS, const char *Arg, bool Quote);
+};
+
+/// Like Command, but with a fallback which is executed in case
+/// the primary command crashes.
+class FallbackCommand : public Command {
+public:
+ FallbackCommand(const Action &Source_, const Tool &Creator_,
+ const char *Executable_, const ArgStringList &Arguments_,
+ ArrayRef<InputInfo> Inputs,
+ std::unique_ptr<Command> Fallback_);
+
+ void Print(llvm::raw_ostream &OS, const char *Terminator, bool Quote,
+ CrashReportInfo *CrashInfo = nullptr) const override;
+
+ int Execute(const StringRef **Redirects, std::string *ErrMsg,
+ bool *ExecutionFailed) const override;
+
+private:
+ std::unique_ptr<Command> Fallback;
+};
+
+/// JobList - A sequence of jobs to perform.
+class JobList {
+public:
+ typedef SmallVector<std::unique_ptr<Command>, 4> list_type;
+ typedef list_type::size_type size_type;
+ typedef llvm::pointee_iterator<list_type::iterator> iterator;
+ typedef llvm::pointee_iterator<list_type::const_iterator> const_iterator;
+
+private:
+ list_type Jobs;
+
+public:
+ void Print(llvm::raw_ostream &OS, const char *Terminator,
+ bool Quote, CrashReportInfo *CrashInfo = nullptr) const;
+
+ /// Add a job to the list (taking ownership).
+ void addJob(std::unique_ptr<Command> J) { Jobs.push_back(std::move(J)); }
+
+ /// Clear the job list.
+ void clear();
+
+ 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(); }
+};
+
+} // end namespace driver
+} // end namespace clang
+
+#endif
diff --git a/contrib/llvm/tools/clang/include/clang/Driver/Multilib.h b/contrib/llvm/tools/clang/include/clang/Driver/Multilib.h
new file mode 100644
index 0000000..20bb80d
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Driver/Multilib.h
@@ -0,0 +1,175 @@
+//===--- Multilib.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_DRIVER_MULTILIB_H
+#define LLVM_CLANG_DRIVER_MULTILIB_H
+
+#include "clang/Basic/LLVM.h"
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/Triple.h"
+#include "llvm/Option/Option.h"
+#include <functional>
+#include <string>
+#include <vector>
+
+namespace clang {
+namespace driver {
+
+/// This corresponds to a single GCC Multilib, or a segment of one controlled
+/// by a command line flag
+class Multilib {
+public:
+ typedef std::vector<std::string> flags_list;
+
+private:
+ std::string GCCSuffix;
+ std::string OSSuffix;
+ std::string IncludeSuffix;
+ flags_list Flags;
+
+public:
+ Multilib(StringRef GCCSuffix = "", StringRef OSSuffix = "",
+ StringRef IncludeSuffix = "");
+
+ /// \brief Get the detected GCC installation path suffix for the multi-arch
+ /// target variant. Always starts with a '/', unless empty
+ const std::string &gccSuffix() const {
+ assert(GCCSuffix.empty() ||
+ (StringRef(GCCSuffix).front() == '/' && GCCSuffix.size() > 1));
+ return GCCSuffix;
+ }
+ /// Set the GCC installation path suffix.
+ Multilib &gccSuffix(StringRef S);
+
+ /// \brief Get the detected os path suffix for the multi-arch
+ /// target variant. Always starts with a '/', unless empty
+ const std::string &osSuffix() const {
+ assert(OSSuffix.empty() ||
+ (StringRef(OSSuffix).front() == '/' && OSSuffix.size() > 1));
+ return OSSuffix;
+ }
+ /// Set the os path suffix.
+ Multilib &osSuffix(StringRef S);
+
+ /// \brief Get the include directory suffix. Always starts with a '/', unless
+ /// empty
+ const std::string &includeSuffix() const {
+ assert(IncludeSuffix.empty() ||
+ (StringRef(IncludeSuffix).front() == '/' && IncludeSuffix.size() > 1));
+ return IncludeSuffix;
+ }
+ /// Set the include directory suffix
+ Multilib &includeSuffix(StringRef S);
+
+ /// \brief Get the flags that indicate or contraindicate this multilib's use
+ /// All elements begin with either '+' or '-'
+ const flags_list &flags() const { return Flags; }
+ flags_list &flags() { return Flags; }
+ /// Add a flag to the flags list
+ Multilib &flag(StringRef F) {
+ assert(F.front() == '+' || F.front() == '-');
+ Flags.push_back(F);
+ return *this;
+ }
+
+ /// \brief print summary of the Multilib
+ void print(raw_ostream &OS) const;
+
+ /// Check whether any of the 'against' flags contradict the 'for' flags.
+ bool isValid() const;
+
+ /// Check whether the default is selected
+ bool isDefault() const
+ { return GCCSuffix.empty() && OSSuffix.empty() && IncludeSuffix.empty(); }
+
+ bool operator==(const Multilib &Other) const;
+};
+
+raw_ostream &operator<<(raw_ostream &OS, const Multilib &M);
+
+class MultilibSet {
+public:
+ typedef std::vector<Multilib> multilib_list;
+ typedef multilib_list::iterator iterator;
+ typedef multilib_list::const_iterator const_iterator;
+
+ typedef std::function<std::vector<std::string>(
+ StringRef InstallDir, StringRef Triple, const Multilib &M)>
+ IncludeDirsFunc;
+
+ typedef llvm::function_ref<bool(const Multilib &)> FilterCallback;
+
+private:
+ multilib_list Multilibs;
+ IncludeDirsFunc IncludeCallback;
+
+public:
+ MultilibSet() {}
+
+ /// Add an optional Multilib segment
+ MultilibSet &Maybe(const Multilib &M);
+
+ /// Add a set of mutually incompatible Multilib segments
+ MultilibSet &Either(const Multilib &M1, const Multilib &M2);
+ MultilibSet &Either(const Multilib &M1, const Multilib &M2,
+ const Multilib &M3);
+ MultilibSet &Either(const Multilib &M1, const Multilib &M2,
+ const Multilib &M3, const Multilib &M4);
+ MultilibSet &Either(const Multilib &M1, const Multilib &M2,
+ const Multilib &M3, const Multilib &M4,
+ const Multilib &M5);
+ MultilibSet &Either(ArrayRef<Multilib> Ms);
+
+ /// Filter out some subset of the Multilibs using a user defined callback
+ MultilibSet &FilterOut(FilterCallback F);
+ /// Filter out those Multilibs whose gccSuffix matches the given expression
+ MultilibSet &FilterOut(const char *Regex);
+
+ /// Add a completed Multilib to the set
+ void push_back(const Multilib &M);
+
+ /// Union this set of multilibs with another
+ void combineWith(const MultilibSet &MS);
+
+ /// Remove all of thie multilibs from the set
+ void clear() { Multilibs.clear(); }
+
+ iterator begin() { return Multilibs.begin(); }
+ const_iterator begin() const { return Multilibs.begin(); }
+
+ iterator end() { return Multilibs.end(); }
+ const_iterator end() const { return Multilibs.end(); }
+
+ /// Pick the best multilib in the set, \returns false if none are compatible
+ bool select(const Multilib::flags_list &Flags, Multilib &M) const;
+
+ unsigned size() const { return Multilibs.size(); }
+
+ void print(raw_ostream &OS) const;
+
+ MultilibSet &setIncludeDirsCallback(IncludeDirsFunc F) {
+ IncludeCallback = std::move(F);
+ return *this;
+ }
+ const IncludeDirsFunc &includeDirsCallback() const { return IncludeCallback; }
+
+private:
+ /// Apply the filter to Multilibs and return the subset that remains
+ static multilib_list filterCopy(FilterCallback F, const multilib_list &Ms);
+
+ /// Apply the filter to the multilib_list, removing those that don't match
+ static void filterInPlace(FilterCallback F, multilib_list &Ms);
+};
+
+raw_ostream &operator<<(raw_ostream &OS, const MultilibSet &MS);
+}
+}
+
+#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..2716fa9
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Driver/Options.h
@@ -0,0 +1,51 @@
+//===--- 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 LLVM_CLANG_DRIVER_OPTIONS_H
+#define LLVM_CLANG_DRIVER_OPTIONS_H
+
+namespace llvm {
+namespace opt {
+class OptTable;
+}
+}
+
+namespace clang {
+namespace driver {
+
+namespace options {
+/// Flags specifically for clang options. Must not overlap with
+/// llvm::opt::DriverFlag.
+enum ClangFlags {
+ DriverOption = (1 << 4),
+ LinkerInput = (1 << 5),
+ NoArgumentUnused = (1 << 6),
+ Unsupported = (1 << 7),
+ CoreOption = (1 << 8),
+ CLOption = (1 << 9),
+ CC1Option = (1 << 10),
+ CC1AsOption = (1 << 11),
+ NoDriverOption = (1 << 12)
+};
+
+enum ID {
+ OPT_INVALID = 0, // This is not an option ID.
+#define OPTION(PREFIX, NAME, ID, KIND, GROUP, ALIAS, ALIASARGS, FLAGS, PARAM, \
+ HELPTEXT, METAVAR) OPT_##ID,
+#include "clang/Driver/Options.inc"
+ LastOption
+#undef OPTION
+ };
+}
+
+llvm::opt::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..e219a9b
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Driver/Options.td
@@ -0,0 +1,2133 @@
+//===--- Options.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 "llvm/Option/OptParser.td"
+
+/////////
+// Flags
+
+// DriverOption - The option is a "driver" option, and should not be forwarded
+// to other tools.
+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;
+
+// Unsupported - The option is unsupported, and the driver will reject command
+// lines that use it.
+def Unsupported : OptionFlag;
+
+// CoreOption - This is considered a "core" Clang option, available in both
+// clang and clang-cl modes.
+def CoreOption : OptionFlag;
+
+// CLOption - This is a cl.exe compatibility option. Options with this flag
+// are made available when the driver is running in CL compatibility mode.
+def CLOption : OptionFlag;
+
+// CC1Option - This option should be accepted by clang -cc1.
+def CC1Option : OptionFlag;
+
+// CC1AsOption - This option should be accepted by clang -cc1as.
+def CC1AsOption : OptionFlag;
+
+// NoDriverOption - This option should not be accepted by the driver.
+def NoDriverOption : OptionFlag;
+
+/////////
+// Groups
+
+// Meta-group for options which are only used for compilation,
+// and not linking etc.
+def CompileOnly_Group : OptionGroup<"<CompileOnly group>">;
+
+def Action_Group : OptionGroup<"<action 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 R_Group : OptionGroup<"<R group>">, Group<CompileOnly_Group>;
+def R_value_Group : OptionGroup<"<R (with value) group>">, Group<R_Group>;
+def W_Group : OptionGroup<"<W group>">, Group<CompileOnly_Group>;
+def W_value_Group : OptionGroup<"<W (with value) group>">, Group<W_Group>;
+def d_Group : OptionGroup<"<d group>">;
+def f_Group : OptionGroup<"<f group>">, Group<CompileOnly_Group>;
+def f_clang_Group : OptionGroup<"<f (clang-only) group>">, Group<CompileOnly_Group>;
+def g_Group : OptionGroup<"<g group>">;
+def gN_Group : OptionGroup<"<gN group>">, Group<g_Group>;
+def ggdbN_Group : OptionGroup<"<ggdbN group>">, Group<gN_Group>;
+def gTune_Group : OptionGroup<"<gTune group>">, Group<g_Group>;
+def g_flags_Group : OptionGroup<"<g flags 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>;
+
+// Feature groups - these take command line options that correspond directly to
+// target specific features and can be translated directly from command line
+// options.
+def m_x86_Features_Group : OptionGroup<"<x86 features group>">,
+ Group<m_Group>,
+ Flags<[CoreOption]>;
+def m_hexagon_Features_Group : OptionGroup<"<hexagon features group>">,
+ Group<m_Group>;
+def m_arm_Features_Group : OptionGroup<"<arm features group>">,
+ Group<m_Group>;
+def m_aarch64_Features_Group : OptionGroup<"<aarch64 features group>">,
+ Group<m_Group>;
+def m_ppc_Features_Group : OptionGroup<"<ppc features group>">,
+ Group<m_Group>;
+def m_wasm_Features_Group : OptionGroup<"<wasm features group>">,
+ Group<m_Group>;
+
+def m_libc_Group : OptionGroup<"<m libc 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>;
+
+// Group that ignores all gcc optimizations that won't be implemented
+def clang_ignored_gcc_optimization_f_Group : OptionGroup<
+ "<clang_ignored_gcc_optimization_f_Group>">, Group<f_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:
+// _ => __
+// - => _
+// / => _SLASH
+// # => _HASH
+// ? => _QUESTION
+// , => _COMMA
+// = => _EQ
+// C++ => CXX
+// . => _
+
+// Developer Driver Options
+
+def internal_Group : OptionGroup<"<clang internal options>">;
+def internal_driver_Group : OptionGroup<"<clang driver internal options>">,
+ Group<internal_Group>, HelpText<"DRIVER OPTIONS">;
+def internal_debug_Group :
+ OptionGroup<"<clang debug/development internal options>">,
+ Group<internal_Group>, HelpText<"DEBUG/DEVELOPMENT OPTIONS">;
+
+class InternalDriverOpt : Group<internal_driver_Group>,
+ Flags<[DriverOption, HelpHidden]>;
+def driver_mode : Joined<["--"], "driver-mode=">, Group<internal_driver_Group>,
+ Flags<[CoreOption, DriverOption, HelpHidden]>,
+ HelpText<"Set the driver mode to either 'gcc', 'g++', 'cpp', or 'cl'">;
+def ccc_gcc_name : Separate<["-"], "ccc-gcc-name">, InternalDriverOpt,
+ HelpText<"Name for native GCC compiler">,
+ MetaVarName<"<gcc-path>">;
+def ccc_pch_is_pch : Flag<["-"], "ccc-pch-is-pch">, InternalDriverOpt,
+ HelpText<"Use lazy PCH for precompiled headers">;
+def ccc_pch_is_pth : Flag<["-"], "ccc-pch-is-pth">, InternalDriverOpt,
+ HelpText<"Use pretokenized headers for precompiled headers">;
+
+class InternalDebugOpt : Group<internal_debug_Group>,
+ Flags<[DriverOption, HelpHidden, CoreOption]>;
+def ccc_install_dir : Separate<["-"], "ccc-install-dir">, InternalDebugOpt,
+ HelpText<"Simulate installation in the given directory">;
+def ccc_print_phases : Flag<["-"], "ccc-print-phases">, InternalDebugOpt,
+ HelpText<"Dump list of actions to perform">;
+def ccc_print_bindings : Flag<["-"], "ccc-print-bindings">, InternalDebugOpt,
+ HelpText<"Show bindings of tools to actions">;
+
+def ccc_arcmt_check : Flag<["-"], "ccc-arcmt-check">, InternalDriverOpt,
+ HelpText<"Check for ARC migration issues that need manual handling">;
+def ccc_arcmt_modify : Flag<["-"], "ccc-arcmt-modify">, InternalDriverOpt,
+ HelpText<"Apply modifications to files to conform to ARC">;
+def ccc_arcmt_migrate : Separate<["-"], "ccc-arcmt-migrate">, InternalDriverOpt,
+ HelpText<"Apply modifications and produces temporary files that conform to ARC">;
+def arcmt_migrate_report_output : Separate<["-"], "arcmt-migrate-report-output">,
+ HelpText<"Output path for the plist report">, Flags<[CC1Option]>;
+def arcmt_migrate_emit_arc_errors : Flag<["-"], "arcmt-migrate-emit-errors">,
+ HelpText<"Emit ARC errors even if the migrator can fix them">,
+ Flags<[CC1Option]>;
+
+def _migrate : Flag<["--"], "migrate">, Flags<[DriverOption]>,
+ HelpText<"Run the migrator">;
+def ccc_objcmt_migrate : Separate<["-"], "ccc-objcmt-migrate">,
+ InternalDriverOpt,
+ HelpText<"Apply modifications and produces temporary files to migrate to "
+ "modern ObjC syntax">;
+def objcmt_migrate_literals : Flag<["-"], "objcmt-migrate-literals">, Flags<[CC1Option]>,
+ HelpText<"Enable migration to modern ObjC literals">;
+def objcmt_migrate_subscripting : Flag<["-"], "objcmt-migrate-subscripting">, Flags<[CC1Option]>,
+ HelpText<"Enable migration to modern ObjC subscripting">;
+def objcmt_migrate_property : Flag<["-"], "objcmt-migrate-property">, Flags<[CC1Option]>,
+ HelpText<"Enable migration to modern ObjC property">;
+def objcmt_migrate_all : Flag<["-"], "objcmt-migrate-all">, Flags<[CC1Option]>,
+ HelpText<"Enable migration to modern ObjC">;
+def objcmt_migrate_readonly_property : Flag<["-"], "objcmt-migrate-readonly-property">, Flags<[CC1Option]>,
+ HelpText<"Enable migration to modern ObjC readonly property">;
+def objcmt_migrate_readwrite_property : Flag<["-"], "objcmt-migrate-readwrite-property">, Flags<[CC1Option]>,
+ HelpText<"Enable migration to modern ObjC readwrite property">;
+def objcmt_migrate_property_dot_syntax : Flag<["-"], "objcmt-migrate-property-dot-syntax">, Flags<[CC1Option]>,
+ HelpText<"Enable migration of setter/getter messages to property-dot syntax">;
+def objcmt_migrate_annotation : Flag<["-"], "objcmt-migrate-annotation">, Flags<[CC1Option]>,
+ HelpText<"Enable migration to property and method annotations">;
+def objcmt_migrate_instancetype : Flag<["-"], "objcmt-migrate-instancetype">, Flags<[CC1Option]>,
+ HelpText<"Enable migration to infer instancetype for method result type">;
+def objcmt_migrate_nsmacros : Flag<["-"], "objcmt-migrate-ns-macros">, Flags<[CC1Option]>,
+ HelpText<"Enable migration to NS_ENUM/NS_OPTIONS macros">;
+def objcmt_migrate_protocol_conformance : Flag<["-"], "objcmt-migrate-protocol-conformance">, Flags<[CC1Option]>,
+ HelpText<"Enable migration to add protocol conformance on classes">;
+def objcmt_atomic_property : Flag<["-"], "objcmt-atomic-property">, Flags<[CC1Option]>,
+ HelpText<"Make migration to 'atomic' properties">;
+def objcmt_returns_innerpointer_property : Flag<["-"], "objcmt-returns-innerpointer-property">, Flags<[CC1Option]>,
+ HelpText<"Enable migration to annotate property with NS_RETURNS_INNER_POINTER">;
+def objcmt_ns_nonatomic_iosonly: Flag<["-"], "objcmt-ns-nonatomic-iosonly">, Flags<[CC1Option]>,
+ HelpText<"Enable migration to use NS_NONATOMIC_IOSONLY macro for setting property's 'atomic' attribute">;
+def objcmt_migrate_designated_init : Flag<["-"], "objcmt-migrate-designated-init">, Flags<[CC1Option]>,
+ HelpText<"Enable migration to infer NS_DESIGNATED_INITIALIZER for initializer methods">;
+def objcmt_whitelist_dir_path: Joined<["-"], "objcmt-whitelist-dir-path=">, Flags<[CC1Option]>,
+ HelpText<"Only modify files with a filename contained in the provided directory path">;
+// The misspelt "white-list" [sic] alias is due for removal.
+def : Joined<["-"], "objcmt-white-list-dir-path=">, Flags<[CC1Option]>,
+ Alias<objcmt_whitelist_dir_path>;
+
+// Make sure all other -ccc- options are rejected.
+def ccc_ : Joined<["-"], "ccc-">, Group<internal_Group>, Flags<[Unsupported]>;
+
+// Standard Options
+
+def _HASH_HASH_HASH : Flag<["-"], "###">, Flags<[DriverOption, CoreOption]>,
+ HelpText<"Print (but do not run) the commands to run for this compilation">;
+def _DASH_DASH : Option<["--"], "", KIND_REMAINING_ARGS>,
+ Flags<[DriverOption, CoreOption]>;
+def A : JoinedOrSeparate<["-"], "A">, Flags<[RenderJoined]>;
+def B : JoinedOrSeparate<["-"], "B">;
+def CC : Flag<["-"], "CC">, Flags<[CC1Option]>;
+def C : Flag<["-"], "C">, Flags<[CC1Option]>;
+def D : JoinedOrSeparate<["-"], "D">, Group<CompileOnly_Group>, Flags<[CC1Option]>;
+def E : Flag<["-"], "E">, Flags<[DriverOption,CC1Option]>, Group<Action_Group>,
+ HelpText<"Only run the preprocessor">;
+def F : JoinedOrSeparate<["-"], "F">, Flags<[RenderJoined,CC1Option]>,
+ HelpText<"Add directory to framework include search path">;
+def G : JoinedOrSeparate<["-"], "G">, Flags<[DriverOption]>;
+def G_EQ : Joined<["-"], "G=">, Flags<[DriverOption]>;
+def H : Flag<["-"], "H">, Flags<[CC1Option]>,
+ HelpText<"Show header includes and nesting depth">;
+def I_ : Flag<["-"], "I-">, Group<I_Group>;
+def I : JoinedOrSeparate<["-"], "I">, Group<I_Group>, Flags<[CC1Option,CC1AsOption]>,
+ HelpText<"Add directory to include search path">;
+def L : JoinedOrSeparate<["-"], "L">, Flags<[RenderJoined]>;
+def MD : Flag<["-"], "MD">, Group<M_Group>,
+ HelpText<"Write a depfile containing user and system headers">;
+def MMD : Flag<["-"], "MMD">, Group<M_Group>,
+ HelpText<"Write a depfile containing user headers">;
+def M : Flag<["-"], "M">, Group<M_Group>,
+ HelpText<"Like -MD, but also implies -E and writes to stdout by default">;
+def MM : Flag<["-"], "MM">, Group<M_Group>,
+ HelpText<"Like -MMD, but also implies -E and writes to stdout by default">;
+def MF : JoinedOrSeparate<["-"], "MF">, Group<M_Group>,
+ HelpText<"Write depfile output from -MMD, -MD, -MM, or -M to <file>">,
+ MetaVarName<"<file>">;
+def MG : Flag<["-"], "MG">, Group<M_Group>, Flags<[CC1Option]>,
+ HelpText<"Add missing headers to depfile">;
+def MP : Flag<["-"], "MP">, Group<M_Group>, Flags<[CC1Option]>,
+ HelpText<"Create phony target for each dependency (other than main file)">;
+def MQ : JoinedOrSeparate<["-"], "MQ">, Group<M_Group>, Flags<[CC1Option]>,
+ HelpText<"Specify name of main file output to quote in depfile">;
+def MT : JoinedOrSeparate<["-"], "MT">, Group<M_Group>, Flags<[CC1Option]>,
+ HelpText<"Specify name of main file output in depfile">;
+def MV : Flag<["-"], "MV">, Group<M_Group>, Flags<[CC1Option]>,
+ HelpText<"Use NMake/Jom format for the depfile">;
+def Mach : Flag<["-"], "Mach">;
+def O0 : Flag<["-"], "O0">, Group<O_Group>, Flags<[CC1Option]>;
+def O4 : Flag<["-"], "O4">, Group<O_Group>, Flags<[CC1Option]>;
+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>, Flags<[CC1Option]>;
+def O_flag : Flag<["-"], "O">, Flags<[CC1Option]>, Alias<O>, AliasArgs<["2"]>;
+def Ofast : Joined<["-"], "Ofast">, Group<O_Group>, Flags<[CC1Option]>;
+def P : Flag<["-"], "P">, Flags<[CC1Option]>,
+ HelpText<"Disable linemarker output in -E mode">;
+def Qn : Flag<["-"], "Qn">;
+def Qunused_arguments : Flag<["-"], "Qunused-arguments">, Flags<[DriverOption, CoreOption]>,
+ HelpText<"Don't emit warning for unused driver arguments">;
+def Q : Flag<["-"], "Q">;
+def Rpass_EQ : Joined<["-"], "Rpass=">, Group<R_value_Group>, Flags<[CC1Option]>,
+ HelpText<"Report transformations performed by optimization passes whose "
+ "name matches the given POSIX regular expression">;
+def Rpass_missed_EQ : Joined<["-"], "Rpass-missed=">, Group<R_value_Group>,
+ Flags<[CC1Option]>,
+ HelpText<"Report missed transformations by optimization passes whose "
+ "name matches the given POSIX regular expression">;
+def Rpass_analysis_EQ : Joined<["-"], "Rpass-analysis=">, Group<R_value_Group>,
+ Flags<[CC1Option]>,
+ HelpText<"Report transformation analysis from optimization passes whose "
+ "name matches the given POSIX regular expression">;
+def R_Joined : Joined<["-"], "R">, Group<R_Group>, Flags<[CC1Option, CoreOption]>,
+ MetaVarName<"<remark>">, HelpText<"Enable the specified remark">;
+def S : Flag<["-"], "S">, Flags<[DriverOption,CC1Option]>, Group<Action_Group>,
+ 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>, Flags<[CC1Option]>;
+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>, Flags<[CC1Option]>;
+def WCL4 : Flag<["-"], "WCL4">, Group<W_Group>, Flags<[CC1Option]>;
+def Wdeprecated : Flag<["-"], "Wdeprecated">, Group<W_Group>, Flags<[CC1Option]>;
+def Wno_deprecated : Flag<["-"], "Wno-deprecated">, Group<W_Group>, Flags<[CC1Option]>;
+def Wextra : Flag<["-"], "Wextra">, Group<W_Group>, Flags<[CC1Option]>;
+def Wl_COMMA : CommaJoined<["-"], "Wl,">, Flags<[LinkerInput, RenderAsInput]>,
+ HelpText<"Pass the comma separated arguments in <arg> to the linker">,
+ MetaVarName<"<arg>">;
+// FIXME: This is broken; these should not be Joined arguments.
+def Wno_nonportable_cfstrings : Joined<["-"], "Wno-nonportable-cfstrings">, Group<W_Group>,
+ Flags<[CC1Option]>;
+def Wnonportable_cfstrings : Joined<["-"], "Wnonportable-cfstrings">, Group<W_Group>,
+ Flags<[CC1Option]>;
+def Wp_COMMA : CommaJoined<["-"], "Wp,">,
+ HelpText<"Pass the comma separated arguments in <arg> to the preprocessor">,
+ MetaVarName<"<arg>">;
+def Wwrite_strings : Flag<["-"], "Wwrite-strings">, Group<W_Group>, Flags<[CC1Option]>;
+def Wno_write_strings : Flag<["-"], "Wno-write-strings">, Group<W_Group>, Flags<[CC1Option]>;
+def W_Joined : Joined<["-"], "W">, Group<W_Group>, Flags<[CC1Option, CoreOption]>,
+ MetaVarName<"<warning>">, HelpText<"Enable the specified warning">;
+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<[DriverOption, CoreOption]>;
+def z : Separate<["-"], "z">, Flags<[LinkerInput, RenderAsInput]>,
+ HelpText<"Pass -z <arg> to the linker">, MetaVarName<"<arg>">;
+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">;
+def arch__errors__fatal : Flag<["-"], "arch_errors_fatal">;
+def arch : Separate<["-"], "arch">, Flags<[DriverOption]>;
+def arch__only : Separate<["-"], "arch_only">;
+def a : Joined<["-"], "a">;
+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">, Group<clang_ignored_f_Group>;
+def current__version : JoinedOrSeparate<["-"], "current_version">;
+def cxx_isystem : JoinedOrSeparate<["-"], "cxx-isystem">, Group<clang_i_Group>,
+ HelpText<"Add directory to the C++ SYSTEM include search path">, Flags<[CC1Option]>,
+ MetaVarName<"<directory>">;
+def c : Flag<["-"], "c">, Flags<[DriverOption]>,
+ HelpText<"Only run preprocess, compile, and assemble steps">;
+def cuda_device_only : Flag<["--"], "cuda-device-only">,
+ HelpText<"Do device-side CUDA compilation only">;
+def cuda_gpu_arch_EQ : Joined<["--"], "cuda-gpu-arch=">,
+ Flags<[DriverOption, HelpHidden]>, HelpText<"CUDA GPU architecture">;
+def cuda_host_only : Flag<["--"], "cuda-host-only">,
+ HelpText<"Do host-side CUDA compilation only">;
+def cuda_path_EQ : Joined<["--"], "cuda-path=">, Group<i_Group>,
+ HelpText<"CUDA installation path">;
+def dA : Flag<["-"], "dA">, Group<d_Group>;
+def dD : Flag<["-"], "dD">, Group<d_Group>, Flags<[CC1Option]>,
+ HelpText<"Print macro definitions in -E mode in addition to normal output">;
+def dM : Flag<["-"], "dM">, Group<d_Group>, Flags<[CC1Option]>,
+ HelpText<"Print macro definitions in -E mode instead of normal output">;
+def dead__strip : Flag<["-"], "dead_strip">;
+def dependency_file : Separate<["-"], "dependency-file">, Flags<[CC1Option]>,
+ HelpText<"Filename (or -) to write dependency output to">;
+def dependency_dot : Separate<["-"], "dependency-dot">, Flags<[CC1Option]>,
+ HelpText<"Filename to write DOT-formatted header dependencies to">;
+def module_dependency_dir : Separate<["-"], "module-dependency-dir">,
+ Flags<[CC1Option]>, HelpText<"Directory to dump module dependencies to">;
+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">, Flags<[CC1Option]>, Group<Action_Group>,
+ 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 fno_PIC : Flag<["-"], "fno-PIC">, 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>, Flags<[CC1Option]>,
+ HelpText<"Use Apple's kernel extensions ABI">;
+def fapple_pragma_pack : Flag<["-"], "fapple-pragma-pack">, Group<f_Group>, Flags<[CC1Option]>,
+ HelpText<"Enable Apple gcc-compatible #pragma pack handling">;
+def shared_libasan : Flag<["-"], "shared-libasan">;
+def fasm : Flag<["-"], "fasm">, Group<f_Group>;
+
+def fasm_blocks : Flag<["-"], "fasm-blocks">, Group<f_Group>, Flags<[CC1Option]>;
+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 fautolink : Flag <["-"], "fautolink">, Group<f_Group>;
+def fno_autolink : Flag <["-"], "fno-autolink">, Group<f_Group>,
+ Flags<[DriverOption, CC1Option]>,
+ HelpText<"Disable generation of linker directives for automatic library linking">;
+
+def fgnu_inline_asm : Flag<["-"], "fgnu-inline-asm">, Group<f_Group>, Flags<[DriverOption]>;
+def fno_gnu_inline_asm : Flag<["-"], "fno-gnu-inline-asm">, Group<f_Group>,
+ Flags<[DriverOption, CC1Option]>,
+ HelpText<"Disable GNU style inline asm">;
+
+def fprofile_sample_use_EQ : Joined<["-"], "fprofile-sample-use=">,
+ Group<f_Group>, Flags<[DriverOption, CC1Option]>,
+ HelpText<"Enable sample-based profile guided optimizations">;
+def fauto_profile_EQ : Joined<["-"], "fauto-profile=">,
+ Alias<fprofile_sample_use_EQ>;
+def fprofile_instr_generate : Flag<["-"], "fprofile-instr-generate">,
+ Group<f_Group>, Flags<[CC1Option]>,
+ HelpText<"Generate instrumented code to collect execution counts into default.profraw file (overriden by '=' form of option or LLVM_PROFILE_FILE env var)">;
+def fprofile_instr_generate_EQ : Joined<["-"], "fprofile-instr-generate=">,
+ Group<f_Group>, Flags<[CC1Option]>, MetaVarName<"<file>">,
+ HelpText<"Generate instrumented code to collect execution counts into <file> (overridden by LLVM_PROFILE_FILE env var)">;
+def fprofile_instr_use : Flag<["-"], "fprofile-instr-use">, Group<f_Group>,
+ Flags<[DriverOption]>;
+def fprofile_instr_use_EQ : Joined<["-"], "fprofile-instr-use=">,
+ Group<f_Group>, Flags<[CC1Option]>,
+ HelpText<"Use instrumentation data for profile-guided optimization">;
+def fcoverage_mapping : Flag<["-"], "fcoverage-mapping">,
+ Group<f_Group>, Flags<[CC1Option]>,
+ HelpText<"Generate coverage mapping to enable code coverage analysis">;
+def fno_coverage_mapping : Flag<["-"], "fno-coverage-mapping">,
+ Group<f_Group>, Flags<[DriverOption]>,
+ HelpText<"Disable code coverage analysis">;
+def fprofile_generate : Flag<["-"], "fprofile-generate">,
+ Alias<fprofile_instr_generate>;
+def fprofile_generate_EQ : Joined<["-"], "fprofile-generate=">,
+ Group<f_Group>, Flags<[DriverOption]>, MetaVarName<"<directory>">,
+ HelpText<"Generate instrumented code to collect execution counts into <directory>/default.profraw (overridden by LLVM_PROFILE_FILE env var)">;
+def fprofile_use : Flag<["-"], "fprofile-use">, Group<f_Group>,
+ Alias<fprofile_instr_use>;
+def fprofile_use_EQ : Joined<["-"], "fprofile-use=">,
+ Group<f_Group>, Flags<[DriverOption]>, MetaVarName<"<pathname>">,
+ HelpText<"Use instrumentation data for profile-guided optimization. If pathname is a directory, it reads from <pathname>/default.profdata. Otherwise, it reads from file <pathname>.">;
+def fno_profile_instr_generate : Flag<["-"], "fno-profile-instr-generate">,
+ Group<f_Group>, Flags<[DriverOption]>,
+ HelpText<"Disable generation of profile instrumentation.">;
+def fno_profile_generate : Flag<["-"], "fno-profile-generate">,
+ Alias<fno_profile_instr_generate>;
+def fno_profile_instr_use : Flag<["-"], "fno-profile-instr-use">,
+ Group<f_Group>, Flags<[DriverOption]>,
+ HelpText<"Disable using instrumentation data for profile-guided optimization">;
+def fno_profile_use : Flag<["-"], "fno-profile-use">,
+ Alias<fno_profile_instr_use>;
+
+def fblocks : Flag<["-"], "fblocks">, Group<f_Group>, Flags<[CC1Option]>,
+ HelpText<"Enable the 'blocks' language feature">;
+def fbootclasspath_EQ : Joined<["-"], "fbootclasspath=">, Group<f_Group>;
+def fborland_extensions : Flag<["-"], "fborland-extensions">, Group<f_Group>, Flags<[CC1Option]>,
+ HelpText<"Accept non-standard constructs supported by the Borland compiler">;
+def fbuiltin : Flag<["-"], "fbuiltin">, Group<f_Group>;
+def fcaret_diagnostics : Flag<["-"], "fcaret-diagnostics">, Group<f_Group>;
+def fclasspath_EQ : Joined<["-"], "fclasspath=">, Group<f_Group>;
+def fcolor_diagnostics : Flag<["-"], "fcolor-diagnostics">, Group<f_Group>,
+ Flags<[CoreOption, CC1Option]>, HelpText<"Use colors in diagnostics">;
+def fdiagnostics_color : Flag<["-"], "fdiagnostics-color">, Group<f_Group>,
+ Flags<[CoreOption, DriverOption]>;
+def fdiagnostics_color_EQ : Joined<["-"], "fdiagnostics-color=">, Group<f_Group>;
+def fansi_escape_codes : Flag<["-"], "fansi-escape-codes">, Group<f_Group>,
+ Flags<[CoreOption, CC1Option]>, HelpText<"Use ANSI escape codes for diagnostics">;
+def fcomment_block_commands : CommaJoined<["-"], "fcomment-block-commands=">, Group<f_clang_Group>, Flags<[CC1Option]>,
+ HelpText<"Treat each comma separated argument in <arg> as a documentation comment block command">,
+ MetaVarName<"<arg>">;
+def fparse_all_comments : Flag<["-"], "fparse-all-comments">, Group<f_clang_Group>, Flags<[CC1Option]>;
+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 fconstexpr_depth_EQ : Joined<["-"], "fconstexpr-depth=">, Group<f_Group>;
+def fconstexpr_steps_EQ : Joined<["-"], "fconstexpr-steps=">, Group<f_Group>;
+def fconstexpr_backtrace_limit_EQ : Joined<["-"], "fconstexpr-backtrace-limit=">,
+ Group<f_Group>;
+def fno_crash_diagnostics : Flag<["-"], "fno-crash-diagnostics">, Group<f_clang_Group>, Flags<[NoArgumentUnused]>;
+def fcreate_profile : Flag<["-"], "fcreate-profile">, Group<f_Group>;
+def fcxx_exceptions: Flag<["-"], "fcxx-exceptions">, Group<f_Group>,
+ HelpText<"Enable C++ exceptions">, Flags<[CC1Option]>;
+def fcxx_modules : Flag <["-"], "fcxx-modules">, Group<f_Group>,
+ Flags<[DriverOption]>;
+def fdebug_pass_arguments : Flag<["-"], "fdebug-pass-arguments">, Group<f_Group>;
+def fdebug_pass_structure : Flag<["-"], "fdebug-pass-structure">, Group<f_Group>;
+def fdepfile_entry : Joined<["-"], "fdepfile-entry=">,
+ Group<f_clang_Group>, Flags<[CC1Option]>;
+def fdiagnostics_fixit_info : Flag<["-"], "fdiagnostics-fixit-info">, Group<f_clang_Group>;
+def fdiagnostics_parseable_fixits : Flag<["-"], "fdiagnostics-parseable-fixits">, Group<f_clang_Group>,
+ Flags<[CoreOption, CC1Option]>, HelpText<"Print fix-its in machine parseable form">;
+def fdiagnostics_print_source_range_info : Flag<["-"], "fdiagnostics-print-source-range-info">,
+ Group<f_clang_Group>, Flags<[CC1Option]>,
+ HelpText<"Print source range spans in numeric form">;
+def fdiagnostics_show_option : Flag<["-"], "fdiagnostics-show-option">, Group<f_Group>,
+ Flags<[CC1Option]>, HelpText<"Print option name with mappable diagnostics">;
+def fdiagnostics_show_note_include_stack : Flag<["-"], "fdiagnostics-show-note-include-stack">,
+ Group<f_Group>, Flags<[CC1Option]>, HelpText<"Display include stacks for diagnostic notes">;
+def fdiagnostics_format_EQ : Joined<["-"], "fdiagnostics-format=">, Group<f_clang_Group>;
+def fdiagnostics_show_category_EQ : Joined<["-"], "fdiagnostics-show-category=">, Group<f_clang_Group>;
+def fdiagnostics_show_template_tree : Flag<["-"], "fdiagnostics-show-template-tree">,
+ Group<f_Group>, Flags<[CC1Option]>,
+ HelpText<"Print a template comparison tree for differing templates">;
+def fdeclspec : Flag<["-"], "fdeclspec">, Group<f_clang_Group>,
+ HelpText<"Allow __declspec as a keyword">, Flags<[CC1Option]>;
+def fdollars_in_identifiers : Flag<["-"], "fdollars-in-identifiers">, Group<f_Group>,
+ HelpText<"Allow '$' in identifiers">, Flags<[CC1Option]>;
+def fdwarf2_cfi_asm : Flag<["-"], "fdwarf2-cfi-asm">, Group<clang_ignored_f_Group>;
+def fno_dwarf2_cfi_asm : Flag<["-"], "fno-dwarf2-cfi-asm">, Group<clang_ignored_f_Group>;
+def fdwarf_directory_asm : Flag<["-"], "fdwarf-directory-asm">, Group<f_Group>;
+def fno_dwarf_directory_asm : Flag<["-"], "fno-dwarf-directory-asm">, Group<f_Group>, Flags<[CC1Option]>;
+def felide_constructors : Flag<["-"], "felide-constructors">, Group<f_Group>;
+def fno_elide_type : Flag<["-"], "fno-elide-type">, Group<f_Group>,
+ Flags<[CC1Option]>,
+ HelpText<"Do not elide types when printing diagnostics">;
+def feliminate_unused_debug_symbols : Flag<["-"], "feliminate-unused-debug-symbols">, Group<f_Group>;
+def femit_all_decls : Flag<["-"], "femit-all-decls">, Group<f_Group>, Flags<[CC1Option]>,
+ HelpText<"Emit all declarations, even if unused">;
+def femulated_tls : Flag<["-"], "femulated-tls">, Group<f_Group>, Flags<[CC1Option]>,
+ HelpText<"Use emutls functions to access thread_local variables">;
+def fno_emulated_tls : Flag<["-"], "fno-emulated-tls">, Group<f_Group>;
+def fencoding_EQ : Joined<["-"], "fencoding=">, Group<f_Group>;
+def ferror_limit_EQ : Joined<["-"], "ferror-limit=">, Group<f_Group>, Flags<[CoreOption]>;
+def fexceptions : Flag<["-"], "fexceptions">, Group<f_Group>, Flags<[CC1Option]>,
+ HelpText<"Enable support for exception handling">;
+def fexcess_precision_EQ : Joined<["-"], "fexcess-precision=">,
+ Group<clang_ignored_gcc_optimization_f_Group>;
+def : Flag<["-"], "fexpensive-optimizations">, Group<clang_ignored_gcc_optimization_f_Group>;
+def : Flag<["-"], "fno-expensive-optimizations">, Group<clang_ignored_gcc_optimization_f_Group>;
+def fextdirs_EQ : Joined<["-"], "fextdirs=">, Group<f_Group>;
+def : Flag<["-"], "fdefer-pop">, Group<clang_ignored_gcc_optimization_f_Group>;
+def : Flag<["-"], "fno-defer-pop">, Group<clang_ignored_gcc_optimization_f_Group>;
+def : Flag<["-"], "fextended-identifiers">, Group<clang_ignored_f_Group>;
+def : Flag<["-"], "fno-extended-identifiers">, Group<f_Group>, Flags<[Unsupported]>;
+def fhosted : Flag<["-"], "fhosted">, Group<f_Group>;
+def ffast_math : Flag<["-"], "ffast-math">, Group<f_Group>, Flags<[CC1Option]>,
+ HelpText<"Enable the *frontend*'s 'fast-math' mode. This has no effect on "
+ "optimizations, but provides a preprocessor macro __FAST_MATH__ the "
+ "same as GCC's -ffast-math flag">;
+def fno_fast_math : Flag<["-"], "fno-fast-math">, Group<f_Group>;
+def fmath_errno : Flag<["-"], "fmath-errno">, Group<f_Group>, Flags<[CC1Option]>,
+ HelpText<"Require math functions to indicate errors by setting errno">;
+def fno_math_errno : Flag<["-"], "fno-math-errno">, Group<f_Group>;
+def fbracket_depth_EQ : Joined<["-"], "fbracket-depth=">, Group<f_Group>;
+def fsignaling_math : Flag<["-"], "fsignaling-math">, Group<f_Group>;
+def fno_signaling_math : Flag<["-"], "fno-signaling-math">, Group<f_Group>;
+def fsanitize_EQ : CommaJoined<["-"], "fsanitize=">, Group<f_clang_Group>,
+ Flags<[CC1Option, CoreOption]>, MetaVarName<"<check>">,
+ HelpText<"Turn on runtime checks for various forms of undefined "
+ "or suspicious behavior. See user manual for available checks">;
+def fno_sanitize_EQ : CommaJoined<["-"], "fno-sanitize=">, Group<f_clang_Group>,
+ Flags<[CoreOption]>;
+def fsanitize_blacklist : Joined<["-"], "fsanitize-blacklist=">,
+ Group<f_clang_Group>, Flags<[CC1Option, CoreOption]>,
+ HelpText<"Path to blacklist file for sanitizers">;
+def fno_sanitize_blacklist : Flag<["-"], "fno-sanitize-blacklist">,
+ Group<f_clang_Group>,
+ HelpText<"Don't use blacklist file for sanitizers">;
+def fsanitize_coverage
+ : CommaJoined<["-"], "fsanitize-coverage=">,
+ Group<f_clang_Group>, Flags<[CoreOption]>,
+ HelpText<"Specify the type of coverage instrumentation for Sanitizers">;
+def fno_sanitize_coverage
+ : CommaJoined<["-"], "fno-sanitize-coverage=">,
+ Group<f_clang_Group>, Flags<[CoreOption]>,
+ HelpText<"Disable specified features of coverage instrumentation for "
+ "Sanitizers">;
+def fsanitize_memory_track_origins_EQ : Joined<["-"], "fsanitize-memory-track-origins=">,
+ Group<f_clang_Group>, Flags<[CC1Option]>,
+ HelpText<"Enable origins tracking in MemorySanitizer">;
+def fsanitize_memory_track_origins : Flag<["-"], "fsanitize-memory-track-origins">,
+ Group<f_clang_Group>, Flags<[CC1Option]>,
+ HelpText<"Enable origins tracking in MemorySanitizer">;
+def fno_sanitize_memory_track_origins : Flag<["-"], "fno-sanitize-memory-track-origins">,
+ Group<f_clang_Group>, Flags<[CC1Option]>,
+ HelpText<"Disable origins tracking in MemorySanitizer">;
+def fsanitize_memory_use_after_dtor : Flag<["-"], "fsanitize-memory-use-after-dtor">,
+ Group<f_clang_Group>, Flags<[CC1Option]>,
+ HelpText<"Enable use-after-destroy detection in MemorySanitizer">;
+def fsanitize_address_field_padding : Joined<["-"], "fsanitize-address-field-padding=">,
+ Group<f_clang_Group>, Flags<[CC1Option]>,
+ HelpText<"Level of field padding for AddressSanitizer">;
+def fsanitize_recover : Flag<["-"], "fsanitize-recover">, Group<f_clang_Group>,
+ Flags<[CoreOption]>;
+def fno_sanitize_recover : Flag<["-"], "fno-sanitize-recover">,
+ Group<f_clang_Group>, Flags<[CoreOption]>;
+def fsanitize_recover_EQ : CommaJoined<["-"], "fsanitize-recover=">,
+ Group<f_clang_Group>,
+ Flags<[CC1Option, CoreOption]>,
+ HelpText<"Enable recovery for specified sanitizers">;
+def fno_sanitize_recover_EQ
+ : CommaJoined<["-"], "fno-sanitize-recover=">,
+ Group<f_clang_Group>, Flags<[CoreOption]>,
+ HelpText<"Disable recovery for specified sanitizers">;
+def fsanitize_trap_EQ : CommaJoined<["-"], "fsanitize-trap=">, Group<f_clang_Group>,
+ Flags<[CC1Option, CoreOption]>,
+ HelpText<"Enable trapping for specified sanitizers">;
+def fno_sanitize_trap_EQ : CommaJoined<["-"], "fno-sanitize-trap=">, Group<f_clang_Group>,
+ Flags<[CoreOption]>,
+ HelpText<"Disable trapping for specified sanitizers">;
+def fsanitize_undefined_trap_on_error : Flag<["-"], "fsanitize-undefined-trap-on-error">,
+ Group<f_clang_Group>;
+def fno_sanitize_undefined_trap_on_error : Flag<["-"], "fno-sanitize-undefined-trap-on-error">,
+ Group<f_clang_Group>;
+def fsanitize_link_cxx_runtime : Flag<["-"], "fsanitize-link-c++-runtime">,
+ Group<f_clang_Group>;
+def fsanitize_cfi_cross_dso : Flag<["-"], "fsanitize-cfi-cross-dso">,
+ Group<f_clang_Group>, Flags<[CC1Option]>,
+ HelpText<"Enable control flow integrity (CFI) checks for cross-DSO calls.">;
+def fno_sanitize_cfi_cross_dso : Flag<["-"], "fno-sanitize-cfi-cross-dso">,
+ Group<f_clang_Group>, Flags<[CC1Option]>,
+ HelpText<"Disable control flow integrity (CFI) checks for cross-DSO calls.">;
+def funsafe_math_optimizations : Flag<["-"], "funsafe-math-optimizations">,
+ Group<f_Group>;
+def fno_unsafe_math_optimizations : Flag<["-"], "fno-unsafe-math-optimizations">,
+ Group<f_Group>;
+def fassociative_math : Flag<["-"], "fassociative-math">, Group<f_Group>;
+def fno_associative_math : Flag<["-"], "fno-associative-math">, Group<f_Group>;
+def freciprocal_math :
+ Flag<["-"], "freciprocal-math">, Group<f_Group>, Flags<[CC1Option]>,
+ HelpText<"Allow division operations to be reassociated">;
+def fno_reciprocal_math : Flag<["-"], "fno-reciprocal-math">, Group<f_Group>;
+def ffinite_math_only : Flag<["-"], "ffinite-math-only">, Group<f_Group>, Flags<[CC1Option]>;
+def fno_finite_math_only : Flag<["-"], "fno-finite-math-only">, Group<f_Group>;
+def fsigned_zeros : Flag<["-"], "fsigned-zeros">, Group<f_Group>;
+def fno_signed_zeros :
+ Flag<["-"], "fno-signed-zeros">, Group<f_Group>, Flags<[CC1Option]>,
+ HelpText<"Allow optimizations that ignore the sign of floating point zeros">;
+def fhonor_nans : Flag<["-"], "fhonor-nans">, Group<f_Group>;
+def fno_honor_nans : Flag<["-"], "fno-honor-nans">, Group<f_Group>;
+def fhonor_infinities : Flag<["-"], "fhonor-infinities">, Group<f_Group>;
+def fno_honor_infinities : Flag<["-"], "fno-honor-infinities">, Group<f_Group>;
+// This option was originally misspelt "infinites" [sic].
+def : Flag<["-"], "fhonor-infinites">, Alias<fhonor_infinities>;
+def : Flag<["-"], "fno-honor-infinites">, Alias<fno_honor_infinities>;
+def ftrapping_math : Flag<["-"], "ftrapping-math">, Group<f_Group>;
+def fno_trapping_math : Flag<["-"], "fno-trapping-math">, Group<f_Group>;
+def ffp_contract : Joined<["-"], "ffp-contract=">, Group<f_Group>,
+ Flags<[CC1Option]>, HelpText<"Form fused FP ops (e.g. FMAs): fast (everywhere)"
+ " | on (according to FP_CONTRACT pragma, default) | off (never fuse)">;
+
+def ffor_scope : Flag<["-"], "ffor-scope">, Group<f_Group>;
+def fno_for_scope : Flag<["-"], "fno-for-scope">, Group<f_Group>;
+
+def frewrite_includes : Flag<["-"], "frewrite-includes">, Group<f_Group>,
+ Flags<[CC1Option]>;
+def fno_rewrite_includes : Flag<["-"], "fno-rewrite-includes">, Group<f_Group>;
+
+def frewrite_map_file : Separate<["-"], "frewrite-map-file">,
+ Group<f_Group>,
+ Flags<[ DriverOption, CC1Option ]>;
+def frewrite_map_file_EQ : Joined<["-"], "frewrite-map-file=">,
+ Group<f_Group>,
+ Flags<[DriverOption]>;
+
+def fuse_line_directives : Flag<["-"], "fuse-line-directives">, Group<f_Group>,
+ Flags<[CC1Option]>;
+def fno_use_line_directives : Flag<["-"], "fno-use-line-directives">, Group<f_Group>;
+
+def ffreestanding : Flag<["-"], "ffreestanding">, Group<f_Group>, Flags<[CC1Option]>,
+ HelpText<"Assert that the compilation takes place in a freestanding environment">;
+def fgnu_keywords : Flag<["-"], "fgnu-keywords">, Group<f_Group>, Flags<[CC1Option]>,
+ HelpText<"Allow GNU-extension keywords regardless of language standard">;
+def fgnu89_inline : Flag<["-"], "fgnu89-inline">, Group<f_Group>, Flags<[CC1Option]>,
+ HelpText<"Use the gnu89 inline semantics">;
+def fno_gnu89_inline : Flag<["-"], "fno-gnu89-inline">, Group<f_Group>;
+def fgnu_runtime : Flag<["-"], "fgnu-runtime">, Group<f_Group>,
+ HelpText<"Generate output compatible with the standard GNU Objective-C runtime">;
+def fheinous_gnu_extensions : Flag<["-"], "fheinous-gnu-extensions">, Flags<[CC1Option]>;
+def filelist : Separate<["-"], "filelist">, Flags<[LinkerInput]>;
+def : Flag<["-"], "findirect-virtual-calls">, Alias<fapple_kext>;
+def finline_functions : Flag<["-"], "finline-functions">, Group<clang_ignored_gcc_optimization_f_Group>;
+def finline : Flag<["-"], "finline">, Group<clang_ignored_f_Group>;
+def finput_charset_EQ : Joined<["-"], "finput-charset=">, Group<f_Group>;
+def fexec_charset_EQ : Joined<["-"], "fexec-charset=">, Group<f_Group>;
+def finstrument_functions : Flag<["-"], "finstrument-functions">, Group<f_Group>, Flags<[CC1Option]>,
+ HelpText<"Generate calls to instrument function entry and exit">;
+def flat__namespace : Flag<["-"], "flat_namespace">;
+def flax_vector_conversions : Flag<["-"], "flax-vector-conversions">, Group<f_Group>;
+def flimited_precision_EQ : Joined<["-"], "flimited-precision=">, Group<f_Group>;
+def flto_EQ : Joined<["-"], "flto=">, Flags<[CC1Option]>, Group<f_Group>,
+ HelpText<"Set LTO mode to either 'full' or 'thin'">;
+def flto : Flag<["-"], "flto">, Flags<[CC1Option]>, Group<f_Group>,
+ HelpText<"Enable LTO in 'full' mode">;
+def fno_lto : Flag<["-"], "fno-lto">, Group<f_Group>,
+ HelpText<"Disable LTO mode (default)">;
+def fthinlto_index_EQ : Joined<["-"], "fthinlto-index=">,
+ Flags<[CC1Option]>, Group<f_Group>,
+ HelpText<"Perform ThinLTO importing using provided function summary index">;
+def fmacro_backtrace_limit_EQ : Joined<["-"], "fmacro-backtrace-limit=">,
+ Group<f_Group>, Flags<[DriverOption, CoreOption]>;
+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>, Flags<[CC1Option, CoreOption]>,
+ HelpText<"Accept some non-standard constructs supported by the Microsoft compiler">;
+def fms_compatibility : Flag<["-"], "fms-compatibility">, Group<f_Group>, Flags<[CC1Option, CoreOption]>,
+ HelpText<"Enable full Microsoft Visual C++ compatibility">;
+def fms_volatile : Joined<["-"], "fms-volatile">, Group<f_Group>, Flags<[CC1Option]>;
+def fmsc_version : Joined<["-"], "fmsc-version=">, Group<f_Group>, Flags<[DriverOption, CoreOption]>,
+ HelpText<"Microsoft compiler version number to report in _MSC_VER (0 = don't define it (default))">;
+def fms_compatibility_version
+ : Joined<["-"], "fms-compatibility-version=">,
+ Group<f_Group>,
+ Flags<[ CC1Option, CoreOption ]>,
+ HelpText<"Dot-separated value representing the Microsoft compiler "
+ "version number to report in _MSC_VER (0 = don't define it "
+ "(default))">;
+def fdelayed_template_parsing : Flag<["-"], "fdelayed-template-parsing">, Group<f_Group>,
+ HelpText<"Parse templated function definitions at the end of the "
+ "translation unit">, Flags<[CC1Option]>;
+def fms_memptr_rep_EQ : Joined<["-"], "fms-memptr-rep=">, Group<f_Group>, Flags<[CC1Option]>;
+def fmodules_cache_path : Joined<["-"], "fmodules-cache-path=">, Group<i_Group>,
+ Flags<[DriverOption, CC1Option]>, MetaVarName<"<directory>">,
+ HelpText<"Specify the module cache path">;
+def fmodules_user_build_path : Separate<["-"], "fmodules-user-build-path">, Group<i_Group>,
+ Flags<[DriverOption, CC1Option]>, MetaVarName<"<directory>">,
+ HelpText<"Specify the module user build path">;
+def fmodules_prune_interval : Joined<["-"], "fmodules-prune-interval=">, Group<i_Group>,
+ Flags<[CC1Option]>, MetaVarName<"<seconds>">,
+ HelpText<"Specify the interval (in seconds) between attempts to prune the module cache">;
+def fmodules_prune_after : Joined<["-"], "fmodules-prune-after=">, Group<i_Group>,
+ Flags<[CC1Option]>, MetaVarName<"<seconds>">,
+ HelpText<"Specify the interval (in seconds) after which a module file will be considered unused">;
+def fmodules_search_all : Flag <["-"], "fmodules-search-all">, Group<f_Group>,
+ Flags<[DriverOption, CC1Option]>,
+ HelpText<"Search even non-imported modules to resolve references">;
+def fbuild_session_timestamp : Joined<["-"], "fbuild-session-timestamp=">,
+ Group<i_Group>, Flags<[CC1Option]>, MetaVarName<"<time since Epoch in seconds>">,
+ HelpText<"Time when the current build session started">;
+def fbuild_session_file : Joined<["-"], "fbuild-session-file=">,
+ Group<i_Group>, MetaVarName<"<file>">,
+ HelpText<"Use the last modification time of <file> as the build session timestamp">;
+def fmodules_validate_once_per_build_session : Flag<["-"], "fmodules-validate-once-per-build-session">,
+ Group<i_Group>, Flags<[CC1Option]>,
+ HelpText<"Don't verify input files for the modules if the module has been "
+ "successfully validated or loaded during this build session">;
+def fmodules_validate_system_headers : Flag<["-"], "fmodules-validate-system-headers">,
+ Group<i_Group>, Flags<[CC1Option]>,
+ HelpText<"Validate the system headers that a module depends on when loading the module">;
+def fmodules : Flag <["-"], "fmodules">, Group<f_Group>,
+ Flags<[DriverOption, CC1Option]>,
+ HelpText<"Enable the 'modules' language feature">;
+def fimplicit_module_maps : Flag <["-"], "fimplicit-module-maps">, Group<f_Group>,
+ Flags<[DriverOption, CC1Option]>,
+ HelpText<"Implicitly search the file system for module map files.">;
+def fmodule_maps : Flag <["-"], "fmodule-maps">, Alias<fimplicit_module_maps>;
+def fmodule_name : JoinedOrSeparate<["-"], "fmodule-name=">, Group<f_Group>,
+ Flags<[DriverOption,CC1Option]>, MetaVarName<"<name>">,
+ HelpText<"Specify the name of the module to build">;
+def fmodule_map_file : Joined<["-"], "fmodule-map-file=">,
+ Group<f_Group>, Flags<[DriverOption,CC1Option]>, MetaVarName<"<file>">,
+ HelpText<"Load this module map file">;
+def fmodule_file : Joined<["-"], "fmodule-file=">,
+ Group<f_Group>, Flags<[DriverOption,CC1Option]>,
+ HelpText<"Load this precompiled module file">, MetaVarName<"<file>">;
+def fmodules_ignore_macro : Joined<["-"], "fmodules-ignore-macro=">, Group<f_Group>, Flags<[CC1Option]>,
+ HelpText<"Ignore the definition of the given macro when building and loading modules">;
+def fmodules_decluse : Flag <["-"], "fmodules-decluse">, Group<f_Group>,
+ Flags<[DriverOption,CC1Option]>,
+ HelpText<"Require declaration of modules used within a module">;
+def fmodules_strict_decluse : Flag <["-"], "fmodules-strict-decluse">, Group<f_Group>,
+ Flags<[DriverOption,CC1Option]>,
+ HelpText<"Like -fmodules-decluse but requires all headers to be in modules">;
+def fno_modules_search_all : Flag <["-"], "fno-modules-search-all">, Group<f_Group>,
+ Flags<[DriverOption, CC1Option]>;
+def fno_implicit_modules :
+ Flag <["-"], "fno-implicit-modules">,
+ Group<f_Group>, Flags<[DriverOption, CC1Option]>;
+def fretain_comments_from_system_headers : Flag<["-"], "fretain-comments-from-system-headers">, Group<f_Group>, Flags<[CC1Option]>;
+
+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>, Flags<[CC1Option]>,
+ HelpText<"Disable C++ access control">;
+def fno_apple_pragma_pack : Flag<["-"], "fno-apple-pragma-pack">, 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>,
+ HelpText<"Don't assume that C++'s global operator new can't alias any pointer">,
+ Flags<[CC1Option]>;
+def fno_blocks : Flag<["-"], "fno-blocks">, Group<f_Group>;
+def fno_borland_extensions : Flag<["-"], "fno-borland-extensions">, Group<f_Group>;
+def fno_builtin : Flag<["-"], "fno-builtin">, Group<f_Group>, Flags<[CC1Option]>,
+ HelpText<"Disable implicit builtin knowledge of functions">;
+def fno_builtin_ : Joined<["-"], "fno-builtin-">, Group<f_Group>, Flags<[CC1Option]>,
+ HelpText<"Disable implicit builtin knowledge of a specific function">;
+def fno_math_builtin : Flag<["-"], "fno-math-builtin">, Group<f_Group>, Flags<[CC1Option]>,
+ HelpText<"Disable implicit builtin knowledge of math functions">;
+def fno_caret_diagnostics : Flag<["-"], "fno-caret-diagnostics">, Group<f_Group>,
+ Flags<[CC1Option]>;
+def fno_color_diagnostics : Flag<["-"], "fno-color-diagnostics">, Group<f_Group>,
+ Flags<[CoreOption, CC1Option]>;
+def fno_diagnostics_color : Flag<["-"], "fno-diagnostics-color">, Group<f_Group>,
+ Flags<[CoreOption, DriverOption]>;
+def fno_common : Flag<["-"], "fno-common">, Group<f_Group>, Flags<[CC1Option]>,
+ HelpText<"Compile common globals like normal definitions">;
+def fno_constant_cfstrings : Flag<["-"], "fno-constant-cfstrings">, Group<f_Group>,
+ Flags<[CC1Option]>,
+ HelpText<"Disable creation of CodeFoundation-type constant strings">;
+def fno_cxx_exceptions: Flag<["-"], "fno-cxx-exceptions">, Group<f_Group>;
+def fno_cxx_modules : Flag <["-"], "fno-cxx-modules">, Group<f_Group>,
+ Flags<[DriverOption]>;
+def fno_diagnostics_fixit_info : Flag<["-"], "fno-diagnostics-fixit-info">, Group<f_Group>,
+ Flags<[CC1Option]>, HelpText<"Do not include fixit information in diagnostics">;
+def fno_diagnostics_show_option : Flag<["-"], "fno-diagnostics-show-option">, Group<f_Group>;
+def fno_diagnostics_show_note_include_stack : Flag<["-"], "fno-diagnostics-show-note-include-stack">,
+ Flags<[CC1Option]>, Group<f_Group>;
+def fno_declspec : Flag<["-"], "fno-declspec">, Group<f_clang_Group>,
+ HelpText<"Disallow __declspec as a keyword">, Flags<[CC1Option]>;
+def fno_dollars_in_identifiers : Flag<["-"], "fno-dollars-in-identifiers">, Group<f_Group>,
+ HelpText<"Disallow '$' in identifiers">, Flags<[CC1Option]>;
+def fno_elide_constructors : Flag<["-"], "fno-elide-constructors">, Group<f_Group>,
+ HelpText<"Disable C++ copy constructor elision">, Flags<[CC1Option]>;
+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_gnu_keywords : Flag<["-"], "fno-gnu-keywords">, Group<f_Group>, Flags<[CC1Option]>;
+def fno_inline_functions : Flag<["-"], "fno-inline-functions">, Group<f_clang_Group>, Flags<[CC1Option]>;
+def fno_inline : Flag<["-"], "fno-inline">, Group<f_clang_Group>, Flags<[CC1Option]>;
+def fveclib : Joined<["-"], "fveclib=">, Group<f_Group>, Flags<[CC1Option]>,
+ HelpText<"Use the given vector functions library">;
+def fno_lax_vector_conversions : Flag<["-"], "fno-lax-vector-conversions">, Group<f_Group>,
+ HelpText<"Disallow implicit conversions between vectors with a different number of elements or different element types">, Flags<[CC1Option]>;
+def fno_merge_all_constants : Flag<["-"], "fno-merge-all-constants">, Group<f_Group>,
+ Flags<[CC1Option]>, HelpText<"Disallow merging of constants">;
+def fno_modules : Flag <["-"], "fno-modules">, Group<f_Group>,
+ Flags<[DriverOption]>;
+def fno_implicit_module_maps : Flag <["-"], "fno-implicit-module-maps">, Group<f_Group>,
+ Flags<[DriverOption]>;
+def fno_module_maps : Flag <["-"], "fno-module-maps">, Alias<fno_implicit_module_maps>;
+def fno_modules_decluse : Flag <["-"], "fno-modules-decluse">, Group<f_Group>,
+ Flags<[DriverOption]>;
+def fno_modules_strict_decluse : Flag <["-"], "fno-strict-modules-decluse">, Group<f_Group>,
+ Flags<[DriverOption]>;
+def fimplicit_modules : Flag <["-"], "fimplicit-modules">, Group<f_Group>,
+ Flags<[DriverOption]>;
+def fmodule_file_deps : Flag <["-"], "fmodule-file-deps">, Group<f_Group>,
+ Flags<[DriverOption]>;
+def fno_module_file_deps : Flag <["-"], "fno-module-file-deps">, Group<f_Group>,
+ Flags<[DriverOption]>;
+def fno_ms_extensions : Flag<["-"], "fno-ms-extensions">, Group<f_Group>,
+ Flags<[CoreOption]>;
+def fno_ms_compatibility : Flag<["-"], "fno-ms-compatibility">, Group<f_Group>,
+ Flags<[CoreOption]>;
+def fno_delayed_template_parsing : Flag<["-"], "fno-delayed-template-parsing">, 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_objc_weak : Flag<["-"], "fno-objc-weak">, Group<f_Group>, Flags<[CC1Option]>;
+def fno_omit_frame_pointer : Flag<["-"], "fno-omit-frame-pointer">, Group<f_Group>;
+def fno_operator_names : Flag<["-"], "fno-operator-names">, Group<f_Group>,
+ HelpText<"Do not treat C++ operator name keywords as synonyms for operators">,
+ Flags<[CC1Option]>;
+def fno_pascal_strings : Flag<["-"], "fno-pascal-strings">, Group<f_Group>;
+def fno_rtti : Flag<["-"], "fno-rtti">, Group<f_Group>, Flags<[CC1Option]>,
+ HelpText<"Disable generation of rtti information">;
+def fno_short_enums : Flag<["-"], "fno-short-enums">, Group<f_Group>;
+def fno_show_column : Flag<["-"], "fno-show-column">, Group<f_Group>, Flags<[CC1Option]>,
+ HelpText<"Do not include column number on diagnostics">;
+def fno_show_source_location : Flag<["-"], "fno-show-source-location">, Group<f_Group>,
+ Flags<[CC1Option]>, HelpText<"Do not include source location information with diagnostics">;
+def fno_spell_checking : Flag<["-"], "fno-spell-checking">, Group<f_Group>,
+ Flags<[CC1Option]>, HelpText<"Disable spell-checking">;
+def fno_stack_protector : Flag<["-"], "fno-stack-protector">, Group<f_Group>,
+ HelpText<"Disable the use of stack protectors">;
+def fno_strict_aliasing : Flag<["-"], "fno-strict-aliasing">, Group<f_Group>,
+ Flags<[DriverOption, CoreOption]>;
+def fstruct_path_tbaa : Flag<["-"], "fstruct-path-tbaa">, Group<f_Group>;
+def fno_struct_path_tbaa : Flag<["-"], "fno-struct-path-tbaa">, Group<f_Group>;
+def fno_strict_enums : Flag<["-"], "fno-strict-enums">, Group<f_Group>;
+def fno_strict_vtable_pointers: Flag<["-"], "fno-strict-vtable-pointers">,
+ Group<f_Group>;
+def fno_strict_overflow : Flag<["-"], "fno-strict-overflow">, Group<f_Group>;
+def fno_threadsafe_statics : Flag<["-"], "fno-threadsafe-statics">, Group<f_Group>,
+ Flags<[CC1Option]>, HelpText<"Do not emit code to make initialization of local statics thread safe">;
+def fno_use_cxa_atexit : Flag<["-"], "fno-use-cxa-atexit">, Group<f_Group>, Flags<[CC1Option]>,
+ HelpText<"Don't use __cxa_atexit for calling destructors">;
+def fno_use_init_array : Flag<["-"], "fno-use-init-array">, Group<f_Group>, Flags<[CC1Option]>,
+ HelpText<"Don't use .init_array instead of .ctors">;
+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_wrapv : Flag<["-"], "fno-wrapv">, Group<f_Group>;
+def fno_zero_initialized_in_bss : Flag<["-"], "fno-zero-initialized-in-bss">, Group<f_Group>;
+def fobjc_arc : Flag<["-"], "fobjc-arc">, Group<f_Group>, Flags<[CC1Option]>,
+ HelpText<"Synthesize retain and release calls for Objective-C pointers">;
+def fno_objc_arc : Flag<["-"], "fno-objc-arc">, Group<f_Group>;
+def fobjc_arc_exceptions : Flag<["-"], "fobjc-arc-exceptions">, Group<f_Group>, Flags<[CC1Option]>,
+ HelpText<"Use EH-safe code when synthesizing retains and releases in -fobjc-arc">;
+def fno_objc_arc_exceptions : Flag<["-"], "fno-objc-arc-exceptions">, 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_exceptions: Flag<["-"], "fobjc-exceptions">, Group<f_Group>,
+ HelpText<"Enable Objective-C exceptions">, Flags<[CC1Option]>;
+def fapplication_extension : Flag<["-"], "fapplication-extension">,
+ Group<f_Group>, Flags<[CC1Option]>,
+ HelpText<"Restrict code to those available for App Extensions">;
+def fno_application_extension : Flag<["-"], "fno-application-extension">,
+ Group<f_Group>;
+def fsized_deallocation : Flag<["-"], "fsized-deallocation">, Flags<[CC1Option]>,
+ HelpText<"Enable C++14 sized global deallocation functions">, Group<f_Group>;
+def fno_sized_deallocation: Flag<["-"], "fno-sized-deallocation">, Group<f_Group>;
+
+def fobjc_gc_only : Flag<["-"], "fobjc-gc-only">, Group<f_Group>, Flags<[CC1Option]>,
+ HelpText<"Use GC exclusively for Objective-C related memory management">;
+def fobjc_gc : Flag<["-"], "fobjc-gc">, Group<f_Group>, Flags<[CC1Option]>,
+ HelpText<"Enable Objective-C garbage collection">;
+def fobjc_legacy_dispatch : Flag<["-"], "fobjc-legacy-dispatch">, Group<f_Group>;
+def fobjc_new_property : Flag<["-"], "fobjc-new-property">, Group<clang_ignored_f_Group>;
+def fobjc_infer_related_result_type : Flag<["-"], "fobjc-infer-related-result-type">,
+ Group<f_Group>;
+def fno_objc_infer_related_result_type : Flag<["-"],
+ "fno-objc-infer-related-result-type">, Group<f_Group>,
+ HelpText<
+ "do not infer Objective-C related result type based on method family">,
+ Flags<[CC1Option]>;
+def fobjc_link_runtime: Flag<["-"], "fobjc-link-runtime">, Group<f_Group>;
+def fobjc_weak : Flag<["-"], "fobjc-weak">, Group<f_Group>, Flags<[CC1Option]>,
+ HelpText<"Enable ARC-style weak references in Objective-C">;
+
+// Objective-C ABI options.
+def fobjc_runtime_EQ : Joined<["-"], "fobjc-runtime=">, Group<f_Group>, Flags<[CC1Option]>,
+ HelpText<"Specify the target Objective-C runtime kind and version">;
+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 fomit_frame_pointer : Flag<["-"], "fomit-frame-pointer">, Group<f_Group>;
+def fopenmp : Flag<["-"], "fopenmp">, Group<f_Group>, Flags<[CC1Option, NoArgumentUnused]>;
+def fno_openmp : Flag<["-"], "fno-openmp">, Group<f_Group>, Flags<[NoArgumentUnused]>;
+def fopenmp_EQ : Joined<["-"], "fopenmp=">, Group<f_Group>;
+def fopenmp_use_tls : Flag<["-"], "fopenmp-use-tls">, Group<f_Group>, Flags<[NoArgumentUnused]>;
+def fnoopenmp_use_tls : Flag<["-"], "fnoopenmp-use-tls">, Group<f_Group>, Flags<[CC1Option, NoArgumentUnused]>;
+def fno_optimize_sibling_calls : Flag<["-"], "fno-optimize-sibling-calls">, Group<f_Group>;
+def foptimize_sibling_calls : Flag<["-"], "foptimize-sibling-calls">, Group<f_Group>;
+def force__cpusubtype__ALL : Flag<["-"], "force_cpusubtype_ALL">;
+def force__flat__namespace : Flag<["-"], "force_flat_namespace">;
+def force__load : Separate<["-"], "force_load">;
+def force_addr : Joined<["-"], "fforce-addr">, Group<clang_ignored_f_Group>;
+def foutput_class_dir_EQ : Joined<["-"], "foutput-class-dir=">, Group<f_Group>;
+def fpack_struct : Flag<["-"], "fpack-struct">, Group<f_Group>;
+def fno_pack_struct : Flag<["-"], "fno-pack-struct">, Group<f_Group>;
+def fpack_struct_EQ : Joined<["-"], "fpack-struct=">, Group<f_Group>, Flags<[CC1Option]>,
+ HelpText<"Specify the default maximum struct packing alignment">;
+def fmax_type_align_EQ : Joined<["-"], "fmax-type-align=">, Group<f_Group>, Flags<[CC1Option]>,
+ HelpText<"Specify the maximum alignment to enforce on pointers lacking an explicit alignment">;
+def fno_max_type_align : Flag<["-"], "fno-max-type-align">, Group<f_Group>;
+def fpascal_strings : Flag<["-"], "fpascal-strings">, Group<f_Group>, Flags<[CC1Option]>,
+ HelpText<"Recognize and construct Pascal-style string literals">;
+def fpcc_struct_return : Flag<["-"], "fpcc-struct-return">, Group<f_Group>, Flags<[CC1Option]>,
+ HelpText<"Override the default ABI to return all structs on the stack">;
+def fpch_preprocess : Flag<["-"], "fpch-preprocess">, Group<f_Group>;
+def fpic : Flag<["-"], "fpic">, Group<f_Group>;
+def fno_pic : Flag<["-"], "fno-pic">, Group<f_Group>;
+def fpie : Flag<["-"], "fpie">, Group<f_Group>;
+def fno_pie : Flag<["-"], "fno-pie">, Group<f_Group>;
+def fplugin_EQ : Joined<["-"], "fplugin=">, Group<f_Group>, Flags<[DriverOption]>, MetaVarName<"<dsopath>">,
+ HelpText<"Load the named plugin (dynamic shared object)">;
+def fprofile_arcs : Flag<["-"], "fprofile-arcs">, Group<f_Group>;
+def fno_profile_arcs : Flag<["-"], "fno-profile-arcs">, Group<f_Group>;
+def framework : Separate<["-"], "framework">, Flags<[LinkerInput]>;
+def frandom_seed_EQ : Joined<["-"], "frandom-seed=">, Group<clang_ignored_f_Group>;
+def freg_struct_return : Flag<["-"], "freg-struct-return">, Group<f_Group>, Flags<[CC1Option]>,
+ HelpText<"Override the default ABI to return small structs in registers">;
+def frtti : Flag<["-"], "frtti">, Group<f_Group>;
+def : Flag<["-"], "fsched-interblock">, Group<clang_ignored_f_Group>;
+def fshort_enums : Flag<["-"], "fshort-enums">, Group<f_Group>, Flags<[CC1Option]>,
+ HelpText<"Allocate to an enum type only as many bytes as it needs for the declared range of possible values">;
+def fshort_wchar : Flag<["-"], "fshort-wchar">, Group<f_Group>, Flags<[CC1Option]>,
+ HelpText<"Force wchar_t to be a short unsigned int">;
+def fno_short_wchar : Flag<["-"], "fno-short-wchar">, Group<f_Group>, Flags<[CC1Option]>,
+ HelpText<"Force wchar_t to be an unsigned int">;
+def fshow_overloads_EQ : Joined<["-"], "fshow-overloads=">, Group<f_Group>, Flags<[CC1Option]>,
+ HelpText<"Which overload candidates to show when overload resolution fails: "
+ "best|all; defaults to all">;
+def fshow_column : Flag<["-"], "fshow-column">, Group<f_Group>, Flags<[CC1Option]>;
+def fshow_source_location : Flag<["-"], "fshow-source-location">, Group<f_Group>;
+def fspell_checking : Flag<["-"], "fspell-checking">, Group<f_Group>;
+def fspell_checking_limit_EQ : Joined<["-"], "fspell-checking-limit=">, Group<f_Group>;
+def fsigned_bitfields : Flag<["-"], "fsigned-bitfields">, Group<f_Group>;
+def fsigned_char : Flag<["-"], "fsigned-char">, Group<f_Group>;
+def fno_signed_char : Flag<["-"], "fno-signed-char">, Group<f_Group>,
+ Flags<[CC1Option]>, HelpText<"Char is unsigned">;
+def fsplit_stack : Flag<["-"], "fsplit-stack">, Group<f_Group>;
+def fstack_protector_all : Flag<["-"], "fstack-protector-all">, Group<f_Group>,
+ HelpText<"Force the usage of stack protectors for all functions">;
+def fstack_protector_strong : Flag<["-"], "fstack-protector-strong">, Group<f_Group>,
+ HelpText<"Use a strong heuristic to apply stack protectors to functions">;
+def fstack_protector : Flag<["-"], "fstack-protector">, Group<f_Group>,
+ HelpText<"Enable stack protectors for functions potentially vulnerable to stack smashing">;
+def fstandalone_debug : Flag<["-"], "fstandalone-debug">, Group<f_Group>,
+ HelpText<"Emit full debug info for all types used by the program">;
+def fno_standalone_debug : Flag<["-"], "fno-standalone-debug">, Group<f_Group>,
+ HelpText<"Limit debug information produced to reduce size of debug binary">;
+def flimit_debug_info : Flag<["-"], "flimit-debug-info">, Alias<fno_standalone_debug>;
+def fno_limit_debug_info : Flag<["-"], "fno-limit-debug-info">, Alias<fstandalone_debug>;
+def fstrict_aliasing : Flag<["-"], "fstrict-aliasing">, Group<f_Group>,
+ Flags<[DriverOption, CoreOption]>;
+def fstrict_enums : Flag<["-"], "fstrict-enums">, Group<f_Group>, Flags<[CC1Option]>,
+ HelpText<"Enable optimizations based on the strict definition of an enum's "
+ "value range">;
+def fstrict_vtable_pointers: Flag<["-"], "fstrict-vtable-pointers">,
+ Group<f_Group>, Flags<[CC1Option]>,
+ HelpText<"Enable optimizations based on the strict rules for overwriting "
+ "polymorphic C++ objects">;
+def fstrict_overflow : Flag<["-"], "fstrict-overflow">, Group<f_Group>;
+def fsyntax_only : Flag<["-"], "fsyntax-only">,
+ Flags<[DriverOption,CoreOption,CC1Option]>, Group<Action_Group>;
+def ftabstop_EQ : Joined<["-"], "ftabstop=">, Group<f_Group>;
+def ftemplate_depth_EQ : Joined<["-"], "ftemplate-depth=">, 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 foperator_arrow_depth_EQ : Joined<["-"], "foperator-arrow-depth=">,
+ Group<f_Group>;
+def ftest_coverage : Flag<["-"], "ftest-coverage">, Group<f_Group>;
+def fvectorize : Flag<["-"], "fvectorize">, Group<f_Group>,
+ HelpText<"Enable the loop vectorization passes">;
+def fno_vectorize : Flag<["-"], "fno-vectorize">, Group<f_Group>;
+def : Flag<["-"], "ftree-vectorize">, Alias<fvectorize>;
+def : Flag<["-"], "fno-tree-vectorize">, Alias<fno_vectorize>;
+def fslp_vectorize : Flag<["-"], "fslp-vectorize">, Group<f_Group>,
+ HelpText<"Enable the superword-level parallelism vectorization passes">;
+def fno_slp_vectorize : Flag<["-"], "fno-slp-vectorize">, Group<f_Group>;
+def fslp_vectorize_aggressive : Flag<["-"], "fslp-vectorize-aggressive">, Group<f_Group>,
+ HelpText<"Enable the BB vectorization passes">;
+def fno_slp_vectorize_aggressive : Flag<["-"], "fno-slp-vectorize-aggressive">, Group<f_Group>;
+def : Flag<["-"], "ftree-slp-vectorize">, Alias<fslp_vectorize>;
+def : Flag<["-"], "fno-tree-slp-vectorize">, Alias<fno_slp_vectorize>;
+def Wlarge_by_value_copy_def : Flag<["-"], "Wlarge-by-value-copy">,
+ HelpText<"Warn if a function definition returns or accepts an object larger "
+ "in bytes than a given value">, Flags<[HelpHidden]>;
+def Wlarge_by_value_copy_EQ : Joined<["-"], "Wlarge-by-value-copy=">, Flags<[CC1Option]>;
+
+// These "special" warning flags are effectively processed as f_Group flags by the driver:
+// Just silence warnings about -Wlarger-than for now.
+def Wlarger_than_EQ : Joined<["-"], "Wlarger-than=">, Group<clang_ignored_f_Group>;
+def Wlarger_than_ : Joined<["-"], "Wlarger-than-">, Alias<Wlarger_than_EQ>;
+def Wframe_larger_than_EQ : Joined<["-"], "Wframe-larger-than=">, Group<f_Group>, Flags<[DriverOption]>;
+
+def : Flag<["-"], "fterminated-vtables">, Alias<fapple_kext>;
+def fthreadsafe_statics : Flag<["-"], "fthreadsafe-statics">, Group<f_Group>;
+def ftime_report : Flag<["-"], "ftime-report">, Group<f_Group>, Flags<[CC1Option]>;
+def ftlsmodel_EQ : Joined<["-"], "ftls-model=">, Group<f_Group>, Flags<[CC1Option]>;
+def ftrapv : Flag<["-"], "ftrapv">, Group<f_Group>, Flags<[CC1Option]>,
+ HelpText<"Trap on integer overflow">;
+def ftrapv_handler_EQ : Joined<["-"], "ftrapv-handler=">, Group<f_Group>,
+ MetaVarName<"<function name>">,
+ HelpText<"Specify the function to be called on overflow">;
+def ftrapv_handler : Separate<["-"], "ftrapv-handler">, Group<f_Group>, Flags<[CC1Option]>;
+def ftrap_function_EQ : Joined<["-"], "ftrap-function=">, Group<f_Group>, Flags<[CC1Option]>,
+ HelpText<"Issue call to specified function rather than a trap instruction">;
+def funit_at_a_time : Flag<["-"], "funit-at-a-time">, Group<f_Group>;
+def funroll_loops : Flag<["-"], "funroll-loops">, Group<f_Group>,
+ HelpText<"Turn on loop unroller">, Flags<[CC1Option]>;
+def fno_unroll_loops : Flag<["-"], "fno-unroll-loops">, Group<f_Group>,
+ HelpText<"Turn off loop unroller">, Flags<[CC1Option]>;
+def freroll_loops : Flag<["-"], "freroll-loops">, Group<f_Group>,
+ HelpText<"Turn on loop reroller">, Flags<[CC1Option]>;
+def fno_reroll_loops : Flag<["-"], "fno-reroll-loops">, Group<f_Group>,
+ HelpText<"Turn off loop reroller">;
+def ftrigraphs : Flag<["-"], "ftrigraphs">, Group<f_Group>,
+ HelpText<"Process trigraph sequences">, Flags<[CC1Option]>;
+def fno_trigraphs : Flag<["-"], "fno-trigraphs">, Group<f_Group>,
+ HelpText<"Do not process trigraph sequences">, Flags<[CC1Option]>;
+def funsigned_bitfields : Flag<["-"], "funsigned-bitfields">, Group<f_Group>;
+def funsigned_char : Flag<["-"], "funsigned-char">, Group<f_Group>;
+def fno_unsigned_char : Flag<["-"], "fno-unsigned-char">;
+def funwind_tables : Flag<["-"], "funwind-tables">, Group<f_Group>;
+def fuse_cxa_atexit : Flag<["-"], "fuse-cxa-atexit">, Group<f_Group>;
+def fuse_init_array : Flag<["-"], "fuse-init-array">, Group<f_Group>, Flags<[CC1Option]>,
+ HelpText<"Use .init_array instead of .ctors">;
+def fno_var_tracking : Flag<["-"], "fno-var-tracking">, Group<clang_ignored_f_Group>;
+def fverbose_asm : Flag<["-"], "fverbose-asm">, Group<f_Group>;
+def fvisibility_EQ : Joined<["-"], "fvisibility=">, Group<f_Group>,
+ HelpText<"Set the default symbol visibility for all global declarations">;
+def fvisibility_inlines_hidden : Flag<["-"], "fvisibility-inlines-hidden">, Group<f_Group>,
+ HelpText<"Give inline C++ member functions default visibility by default">,
+ Flags<[CC1Option]>;
+def fvisibility_ms_compat : Flag<["-"], "fvisibility-ms-compat">, Group<f_Group>,
+ HelpText<"Give global types 'default' visibility and global functions and "
+ "variables 'hidden' visibility by default">;
+def fwrapv : Flag<["-"], "fwrapv">, Group<f_Group>, Flags<[CC1Option]>,
+ HelpText<"Treat signed integer overflow as two's complement">;
+def fwritable_strings : Flag<["-"], "fwritable-strings">, Group<f_Group>, Flags<[CC1Option]>,
+ HelpText<"Store string literals as writable data">;
+def fzero_initialized_in_bss : Flag<["-"], "fzero-initialized-in-bss">, Group<f_Group>;
+def ffunction_sections : Flag<["-"], "ffunction-sections">, Group<f_Group>,
+ Flags<[CC1Option]>,
+ HelpText<"Place each function in its own section (ELF Only)">;
+def fno_function_sections : Flag<["-"], "fno-function-sections">,
+ Group<f_Group>, Flags<[CC1Option]>;
+def fdata_sections : Flag <["-"], "fdata-sections">, Group<f_Group>,
+ Flags<[CC1Option]>, HelpText<"Place each data in its own section (ELF Only)">;
+def fno_data_sections : Flag <["-"], "fno-data-sections">, Group<f_Group>,
+ Flags<[CC1Option]>;
+
+def funique_section_names : Flag <["-"], "funique-section-names">,
+ Group<f_Group>, Flags<[CC1Option]>,
+ HelpText<"Use unique names for text and data sections (ELF Only)">;
+def fno_unique_section_names : Flag <["-"], "fno-unique-section-names">,
+ Group<f_Group>, Flags<[CC1Option]>;
+
+
+def fdebug_types_section: Flag <["-"], "fdebug-types-section">, Group<f_Group>,
+ Flags<[CC1Option]>, HelpText<"Place debug types in their own section (ELF Only)">;
+def fno_debug_types_section: Flag<["-"], "fno-debug-types-section">, Group<f_Group>,
+ Flags<[CC1Option]>;
+def fdebug_prefix_map_EQ
+ : Joined<["-"], "fdebug-prefix-map=">, Group<f_Group>, Flags<[CC1Option]>,
+ HelpText<"remap file source paths in debug info">;
+def g_Flag : Flag<["-"], "g">, Group<g_Group>,
+ HelpText<"Generate source-level debug information">;
+def gline_tables_only : Flag<["-"], "gline-tables-only">, Group<gN_Group>,
+ HelpText<"Emit debug line number tables only">;
+def gmlt : Flag<["-"], "gmlt">, Alias<gline_tables_only>;
+def g0 : Flag<["-"], "g0">, Group<gN_Group>;
+def g1 : Flag<["-"], "g1">, Group<gN_Group>, Alias<gline_tables_only>;
+def g2 : Flag<["-"], "g2">, Group<gN_Group>;
+def g3 : Flag<["-"], "g3">, Group<gN_Group>;
+def ggdb : Flag<["-"], "ggdb">, Group<gTune_Group>;
+def ggdb0 : Flag<["-"], "ggdb0">, Group<ggdbN_Group>;
+def ggdb1 : Flag<["-"], "ggdb1">, Group<ggdbN_Group>;
+def ggdb2 : Flag<["-"], "ggdb2">, Group<ggdbN_Group>;
+def ggdb3 : Flag<["-"], "ggdb3">, Group<ggdbN_Group>;
+def glldb : Flag<["-"], "glldb">, Group<gTune_Group>;
+def gsce : Flag<["-"], "gsce">, Group<gTune_Group>;
+def gdwarf_2 : Flag<["-"], "gdwarf-2">, Group<g_Group>,
+ HelpText<"Generate source-level debug information with dwarf version 2">;
+def gdwarf_3 : Flag<["-"], "gdwarf-3">, Group<g_Group>,
+ HelpText<"Generate source-level debug information with dwarf version 3">;
+def gdwarf_4 : Flag<["-"], "gdwarf-4">, Group<g_Group>,
+ HelpText<"Generate source-level debug information with dwarf version 4">;
+def gdwarf_5 : Flag<["-"], "gdwarf-5">, Group<g_Group>,
+ HelpText<"Generate source-level debug information with dwarf version 5">;
+def gcodeview : Flag<["-"], "gcodeview">,
+ HelpText<"Generate CodeView debug information">,
+ Flags<[CC1Option, CC1AsOption, CoreOption]>;
+// Equivalent to our default dwarf version. Forces usual dwarf emission when
+// CodeView is enabled.
+def gdwarf : Flag<["-"], "gdwarf">, Alias<gdwarf_4>, Flags<[CoreOption]>;
+
+def gfull : Flag<["-"], "gfull">, Group<g_Group>;
+def gused : Flag<["-"], "gused">, Group<g_Group>;
+def gstabs : Joined<["-"], "gstabs">, Group<g_Group>, Flags<[Unsupported]>;
+def gcoff : Joined<["-"], "gcoff">, Group<g_Group>, Flags<[Unsupported]>;
+def gxcoff : Joined<["-"], "gxcoff">, Group<g_Group>, Flags<[Unsupported]>;
+def gvms : Joined<["-"], "gvms">, Group<g_Group>, Flags<[Unsupported]>;
+def gtoggle : Flag<["-"], "gtoggle">, Group<g_flags_Group>, Flags<[Unsupported]>;
+def grecord_gcc_switches : Flag<["-"], "grecord-gcc-switches">, Group<g_flags_Group>;
+def gno_record_gcc_switches : Flag<["-"], "gno-record-gcc-switches">,
+ Group<g_flags_Group>;
+def gstrict_dwarf : Flag<["-"], "gstrict-dwarf">, Group<g_flags_Group>;
+def gno_strict_dwarf : Flag<["-"], "gno-strict-dwarf">, Group<g_flags_Group>;
+def gcolumn_info : Flag<["-"], "gcolumn-info">, Group<g_flags_Group>;
+def gno_column_info : Flag<["-"], "gno-column-info">, Group<g_flags_Group>;
+def gsplit_dwarf : Flag<["-"], "gsplit-dwarf">, Group<g_flags_Group>;
+def ggnu_pubnames : Flag<["-"], "ggnu-pubnames">, Group<g_flags_Group>;
+def gdwarf_aranges : Flag<["-"], "gdwarf-aranges">, Group<g_flags_Group>;
+def gmodules : Flag <["-"], "gmodules">, Group<f_Group>,
+ HelpText<"Generate debug info with external references to clang modules"
+ " or precompiled headers">;
+def headerpad__max__install__names : Joined<["-"], "headerpad_max_install_names">;
+def help : Flag<["-", "--"], "help">, Flags<[CC1Option,CC1AsOption]>,
+ HelpText<"Display available options">;
+def index_header_map : Flag<["-"], "index-header-map">, Flags<[CC1Option]>,
+ HelpText<"Make the next included directory (-I or -F) an indexer header map">;
+def idirafter : JoinedOrSeparate<["-"], "idirafter">, Group<clang_i_Group>, Flags<[CC1Option]>,
+ HelpText<"Add directory to AFTER include search path">;
+def iframework : JoinedOrSeparate<["-"], "iframework">, Group<clang_i_Group>, Flags<[CC1Option]>,
+ HelpText<"Add directory to SYSTEM framework search path">;
+def imacros : JoinedOrSeparate<["-", "--"], "imacros">, Group<clang_i_Group>, Flags<[CC1Option]>,
+ HelpText<"Include macros from file before parsing">, MetaVarName<"<file>">;
+def image__base : Separate<["-"], "image_base">;
+def include_ : JoinedOrSeparate<["-", "--"], "include">, Group<clang_i_Group>, EnumName<"include">,
+ MetaVarName<"<file>">, HelpText<"Include file before parsing">, Flags<[CC1Option]>;
+def include_pch : Separate<["-"], "include-pch">, Group<clang_i_Group>, Flags<[CC1Option]>,
+ HelpText<"Include precompiled header file">, MetaVarName<"<file>">;
+def relocatable_pch : Flag<["-", "--"], "relocatable-pch">, Flags<[CC1Option]>,
+ HelpText<"Whether to build a relocatable precompiled header">;
+def verify_pch : Flag<["-"], "verify-pch">, Group<Action_Group>, Flags<[CC1Option]>,
+ HelpText<"Load and verify that a pre-compiled header file is not stale">;
+def init : Separate<["-"], "init">;
+def install__name : Separate<["-"], "install_name">;
+def iprefix : JoinedOrSeparate<["-"], "iprefix">, Group<clang_i_Group>, Flags<[CC1Option]>,
+ HelpText<"Set the -iwithprefix/-iwithprefixbefore prefix">, MetaVarName<"<dir>">;
+def iquote : JoinedOrSeparate<["-"], "iquote">, Group<clang_i_Group>, Flags<[CC1Option]>,
+ HelpText<"Add directory to QUOTE include search path">, MetaVarName<"<directory>">;
+def isysroot : JoinedOrSeparate<["-"], "isysroot">, Group<clang_i_Group>, Flags<[CC1Option]>,
+ HelpText<"Set the system root directory (usually /)">, MetaVarName<"<dir>">;
+def isystem : JoinedOrSeparate<["-"], "isystem">, Group<clang_i_Group>, Flags<[CC1Option]>,
+ HelpText<"Add directory to SYSTEM include search path">, MetaVarName<"<directory>">;
+def iwithprefixbefore : JoinedOrSeparate<["-"], "iwithprefixbefore">, Group<clang_i_Group>,
+ HelpText<"Set directory to include search path with prefix">, MetaVarName<"<dir>">,
+ Flags<[CC1Option]>;
+def iwithprefix : JoinedOrSeparate<["-"], "iwithprefix">, Group<clang_i_Group>, Flags<[CC1Option]>,
+ HelpText<"Set directory to SYSTEM include search path with prefix">, MetaVarName<"<dir>">;
+def iwithsysroot : JoinedOrSeparate<["-"], "iwithsysroot">, Group<clang_i_Group>,
+ HelpText<"Add directory to SYSTEM include search path, "
+ "absolute paths are relative to -isysroot">, MetaVarName<"<directory>">,
+ Flags<[CC1Option]>;
+def ivfsoverlay : JoinedOrSeparate<["-"], "ivfsoverlay">, Group<clang_i_Group>, Flags<[CC1Option]>,
+ HelpText<"Overlay the virtual filesystem described by file over the real file system">;
+def i : Joined<["-"], "i">, Group<i_Group>;
+def keep__private__externs : Flag<["-"], "keep_private_externs">;
+def l : JoinedOrSeparate<["-"], "l">, Flags<[LinkerInput, RenderJoined]>;
+def lazy__framework : Separate<["-"], "lazy_framework">, Flags<[LinkerInput]>;
+def lazy__library : Separate<["-"], "lazy_library">, Flags<[LinkerInput]>;
+def mlittle_endian : Flag<["-"], "mlittle-endian">, Flags<[DriverOption]>;
+def EL : Flag<["-"], "EL">, Alias<mlittle_endian>;
+def mbig_endian : Flag<["-"], "mbig-endian">, Flags<[DriverOption]>;
+def EB : Flag<["-"], "EB">, Alias<mbig_endian>;
+def m16 : Flag<["-"], "m16">, Group<m_Group>, Flags<[DriverOption, CoreOption]>;
+def m32 : Flag<["-"], "m32">, Group<m_Group>, Flags<[DriverOption, CoreOption]>;
+def mqdsp6_compat : Flag<["-"], "mqdsp6-compat">, Group<m_Group>, Flags<[DriverOption,CC1Option]>,
+ HelpText<"Enable hexagon-qdsp6 backward compatibility">;
+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, CoreOption]>;
+def mx32 : Flag<["-"], "mx32">, Group<m_Group>, Flags<[DriverOption, CoreOption]>;
+def mabi_EQ : Joined<["-"], "mabi=">, Group<m_Group>;
+def malign_functions_EQ : Joined<["-"], "malign-functions=">, Group<clang_ignored_m_Group>;
+def malign_loops_EQ : Joined<["-"], "malign-loops=">, Group<clang_ignored_m_Group>;
+def malign_jumps_EQ : Joined<["-"], "malign-jumps=">, Group<clang_ignored_m_Group>;
+def mfancy_math_387 : Flag<["-"], "mfancy-math-387">, Group<clang_ignored_m_Group>;
+def mtvos_version_min_EQ : Joined<["-"], "mtvos-version-min=">, Group<m_Group>;
+def mappletvos_version_min_EQ : Joined<["-"], "mappletvos-version-min=">, Alias<mtvos_version_min_EQ>;
+def mtvos_simulator_version_min_EQ : Joined<["-"], "mtvos-simulator-version-min=">, Alias<mtvos_version_min_EQ>;
+def mappletvsimulator_version_min_EQ : Joined<["-"], "mappletvsimulator-version-min=">, Alias<mtvos_version_min_EQ>;
+def mwatchos_version_min_EQ : Joined<["-"], "mwatchos-version-min=">, Group<m_Group>;
+def mwatchos_simulator_version_min_EQ : Joined<["-"], "mwatchos-simulator-version-min=">, Alias<mwatchos_version_min_EQ>;
+def mwatchsimulator_version_min_EQ : Joined<["-"], "mwatchsimulator-version-min=">, Alias<mwatchos_version_min_EQ>;
+def march_EQ : Joined<["-"], "march=">, Group<m_Group>;
+def masm_EQ : Joined<["-"], "masm=">, Group<m_Group>, Flags<[DriverOption]>;
+def mcmodel_EQ : Joined<["-"], "mcmodel=">, Group<m_Group>;
+def mconstant_cfstrings : Flag<["-"], "mconstant-cfstrings">, Group<clang_ignored_m_Group>;
+def mconsole : Joined<["-"], "mconsole">, Group<m_Group>, Flags<[DriverOption]>;
+def mwindows : Joined<["-"], "mwindows">, Group<m_Group>, Flags<[DriverOption]>;
+def mdll : Joined<["-"], "mdll">, Group<m_Group>, Flags<[DriverOption]>;
+def municode : Joined<["-"], "municode">, Group<m_Group>, Flags<[DriverOption]>;
+def mthreads : Joined<["-"], "mthreads">, Group<m_Group>, Flags<[DriverOption]>;
+def mcpu_EQ : Joined<["-"], "mcpu=">, Group<m_Group>;
+def mdynamic_no_pic : Joined<["-"], "mdynamic-no-pic">, Group<m_Group>;
+def mfix_and_continue : Flag<["-"], "mfix-and-continue">, Group<clang_ignored_m_Group>;
+def mieee_fp : Flag<["-"], "mieee-fp">, Group<clang_ignored_m_Group>;
+def minline_all_stringops : Flag<["-"], "minline-all-stringops">, Group<clang_ignored_m_Group>;
+def mno_inline_all_stringops : Flag<["-"], "mno-inline-all-stringops">, Group<clang_ignored_m_Group>;
+def mfloat_abi_EQ : Joined<["-"], "mfloat-abi=">, Group<m_Group>;
+def mfpmath_EQ : Joined<["-"], "mfpmath=">, Group<m_Group>;
+def mfpu_EQ : Joined<["-"], "mfpu=">, Group<m_Group>;
+def mhwdiv_EQ : Joined<["-"], "mhwdiv=">, Group<m_Group>;
+def mglobal_merge : Flag<["-"], "mglobal-merge">, Group<m_Group>, Flags<[CC1Option]>,
+ HelpText<"Enable merging of globals">;
+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>, HelpText<"Set iOS deployment target">;
+def mios_simulator_version_min_EQ : Joined<["-"], "mios-simulator-version-min=">, Alias<miphoneos_version_min_EQ>;
+def miphonesimulator_version_min_EQ : Joined<["-"], "miphonesimulator-version-min=">, Alias<miphoneos_version_min_EQ>;
+def mkernel : Flag<["-"], "mkernel">, Group<m_Group>;
+def mlinker_version_EQ : Joined<["-"], "mlinker-version=">,
+ Flags<[DriverOption]>;
+def mllvm : Separate<["-"], "mllvm">, Flags<[CC1Option,CC1AsOption,CoreOption]>,
+ HelpText<"Additional arguments to forward to LLVM's option processing">;
+def mmacosx_version_min_EQ : Joined<["-"], "mmacosx-version-min=">,
+ Group<m_Group>, HelpText<"Set Mac OS X deployment target">;
+def mms_bitfields : Flag<["-"], "mms-bitfields">, Group<m_Group>, Flags<[CC1Option]>,
+ HelpText<"Set the default structure layout to be compatible with the Microsoft compiler standard">;
+def mno_ms_bitfields : Flag<["-"], "mno-ms-bitfields">, Group<m_Group>,
+ HelpText<"Do not set the default structure layout to be compatible with the Microsoft compiler standard">;
+def mstackrealign : Flag<["-"], "mstackrealign">, Group<m_Group>, Flags<[CC1Option]>,
+ HelpText<"Force realign the stack at entry to every function">;
+def mstack_alignment : Joined<["-"], "mstack-alignment=">, Group<m_Group>, Flags<[CC1Option]>,
+ HelpText<"Set the stack alignment">;
+def mstack_probe_size : Joined<["-"], "mstack-probe-size=">, Group<m_Group>, Flags<[CC1Option]>,
+ HelpText<"Set the stack probe size">;
+def mthread_model : Separate<["-"], "mthread-model">, Group<m_Group>, Flags<[CC1Option]>,
+ HelpText<"The thread model to use, e.g. posix, single (posix by default)">;
+def meabi : Separate<["-"], "meabi">, Group<m_Group>, Flags<[CC1Option]>,
+ HelpText<"Set EABI type, e.g. 4, 5 or gnu (default depends on triple)">;
+
+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_global_merge : Flag<["-"], "mno-global-merge">, Group<m_Group>, Flags<[CC1Option]>,
+ HelpText<"Disable merging of globals">;
+def mno_mmx : Flag<["-"], "mno-mmx">, Group<m_x86_Features_Group>;
+def mno_pascal_strings : Flag<["-"], "mno-pascal-strings">,
+ Alias<fno_pascal_strings>;
+def mno_red_zone : Flag<["-"], "mno-red-zone">, Group<m_Group>;
+def mno_relax_all : Flag<["-"], "mno-relax-all">, Group<m_Group>;
+def mno_rtd: Flag<["-"], "mno-rtd">, Group<m_Group>;
+def mno_soft_float : Flag<["-"], "mno-soft-float">, Group<m_Group>;
+def mno_stackrealign : Flag<["-"], "mno-stackrealign">, 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_1 : Flag<["-"], "mno-sse4.1">, Group<m_x86_Features_Group>;
+def mno_sse4_2 : Flag<["-"], "mno-sse4.2">, Group<m_x86_Features_Group>;
+// -mno-sse4 turns off sse4.1 which has the effect of turning off everything
+// later than 4.1. -msse4 turns on 4.2 which has the effect of turning on
+// everything earlier than 4.2.
+def mno_sse4 : Flag<["-"], "mno-sse4">, Alias<mno_sse4_1>;
+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_avx2 : Flag<["-"], "mno-avx2">, Group<m_x86_Features_Group>;
+def mno_avx512f : Flag<["-"], "mno-avx512f">, Group<m_x86_Features_Group>;
+def mno_avx512cd : Flag<["-"], "mno-avx512cd">, Group<m_x86_Features_Group>;
+def mno_avx512er : Flag<["-"], "mno-avx512er">, Group<m_x86_Features_Group>;
+def mno_avx512pf : Flag<["-"], "mno-avx512pf">, Group<m_x86_Features_Group>;
+def mno_avx512dq : Flag<["-"], "mno-avx512dq">, Group<m_x86_Features_Group>;
+def mno_avx512bw : Flag<["-"], "mno-avx512bw">, Group<m_x86_Features_Group>;
+def mno_avx512vl : Flag<["-"], "mno-avx512vl">, Group<m_x86_Features_Group>;
+def mno_pclmul : Flag<["-"], "mno-pclmul">, Group<m_x86_Features_Group>;
+def mno_lzcnt : Flag<["-"], "mno-lzcnt">, Group<m_x86_Features_Group>;
+def mno_rdrnd : Flag<["-"], "mno-rdrnd">, Group<m_x86_Features_Group>;
+def mno_fsgsbase : Flag<["-"], "mno-fsgsbase">, Group<m_x86_Features_Group>;
+def mno_bmi : Flag<["-"], "mno-bmi">, Group<m_x86_Features_Group>;
+def mno_bmi2 : Flag<["-"], "mno-bmi2">, Group<m_x86_Features_Group>;
+def mno_popcnt : Flag<["-"], "mno-popcnt">, Group<m_x86_Features_Group>;
+def mno_tbm : Flag<["-"], "mno-tbm">, Group<m_x86_Features_Group>;
+def mno_fma4 : Flag<["-"], "mno-fma4">, Group<m_x86_Features_Group>;
+def mno_fma : Flag<["-"], "mno-fma">, Group<m_x86_Features_Group>;
+def mno_xop : Flag<["-"], "mno-xop">, Group<m_x86_Features_Group>;
+def mno_f16c : Flag<["-"], "mno-f16c">, Group<m_x86_Features_Group>;
+def mno_rtm : Flag<["-"], "mno-rtm">, Group<m_x86_Features_Group>;
+def mno_prfchw : Flag<["-"], "mno-prfchw">, Group<m_x86_Features_Group>;
+def mno_rdseed : Flag<["-"], "mno-rdseed">, Group<m_x86_Features_Group>;
+def mno_adx : Flag<["-"], "mno-adx">, Group<m_x86_Features_Group>;
+def mno_sha : Flag<["-"], "mno-sha">, Group<m_x86_Features_Group>;
+def mno_fxsr : Flag<["-"], "mno-fxsr">, Group<m_x86_Features_Group>;
+def mno_xsave : Flag<["-"], "mno-xsave">, Group<m_x86_Features_Group>;
+def mno_xsaveopt : Flag<["-"], "mno-xsaveopt">, Group<m_x86_Features_Group>;
+def mno_xsavec : Flag<["-"], "mno-xsavec">, Group<m_x86_Features_Group>;
+def mno_xsaves : Flag<["-"], "mno-xsaves">, Group<m_x86_Features_Group>;
+def mno_pku : Flag<["-"], "mno-pku">, Group<m_x86_Features_Group>;
+
+def munaligned_access : Flag<["-"], "munaligned-access">, Group<m_arm_Features_Group>,
+ HelpText<"Allow memory accesses to be unaligned (AArch32/AArch64 only)">;
+def mno_unaligned_access : Flag<["-"], "mno-unaligned-access">, Group<m_arm_Features_Group>,
+ HelpText<"Force all memory accesses to be aligned (AArch32/AArch64 only)">;
+def mstrict_align : Flag<["-"], "mstrict-align">, Alias<mno_unaligned_access>, Flags<[CC1Option,HelpHidden]>,
+ HelpText<"Force all memory accesses to be aligned (same as mno-unaligned-access)">;
+def mno_thumb : Flag<["-"], "mno-thumb">, Group<m_arm_Features_Group>;
+def mrestrict_it: Flag<["-"], "mrestrict-it">, Group<m_arm_Features_Group>,
+ HelpText<"Disallow generation of deprecated IT blocks for ARMv8. It is on by default for ARMv8 Thumb mode.">;
+def mno_restrict_it: Flag<["-"], "mno-restrict-it">, Group<m_arm_Features_Group>,
+ HelpText<"Allow generation of deprecated IT blocks for ARMv8. It is off by default for ARMv8 Thumb mode">;
+def marm : Flag<["-"], "marm">, Alias<mno_thumb>;
+def ffixed_r9 : Flag<["-"], "ffixed-r9">, Group<m_arm_Features_Group>,
+ HelpText<"Reserve the r9 register (ARM only)">;
+def mno_movt : Flag<["-"], "mno-movt">, Group<m_arm_Features_Group>,
+ HelpText<"Disallow use of movt/movw pairs (ARM only)">;
+def mcrc : Flag<["-"], "mcrc">, Group<m_arm_Features_Group>,
+ HelpText<"Allow use of CRC instructions (ARM only)">;
+def mnocrc : Flag<["-"], "mnocrc">, Group<m_arm_Features_Group>,
+ HelpText<"Disallow use of CRC instructions (ARM only)">;
+def mlong_calls : Flag<["-"], "mlong-calls">, Group<m_arm_Features_Group>,
+ HelpText<"Generate an indirect jump to enable jumps further than 64M">;
+def mno_long_calls : Flag<["-"], "mno-long-calls">, Group<m_arm_Features_Group>,
+ HelpText<"Restore the default behaviour of not generating long calls">;
+
+def mgeneral_regs_only : Flag<["-"], "mgeneral-regs-only">, Group<m_aarch64_Features_Group>,
+ HelpText<"Generate code which only uses the general purpose registers (AArch64 only)">;
+
+def mfix_cortex_a53_835769 : Flag<["-"], "mfix-cortex-a53-835769">,
+ Group<m_aarch64_Features_Group>,
+ HelpText<"Workaround Cortex-A53 erratum 835769 (AArch64 only)">;
+def mno_fix_cortex_a53_835769 : Flag<["-"], "mno-fix-cortex-a53-835769">,
+ Group<m_aarch64_Features_Group>,
+ HelpText<"Don't workaround Cortex-A53 erratum 835769 (AArch64 only)">;
+def ffixed_x18 : Flag<["-"], "ffixed-x18">, Group<m_aarch64_Features_Group>,
+ HelpText<"Reserve the x18 register (AArch64 only)">;
+
+def msimd128 : Flag<["-"], "msimd128">, Group<m_wasm_Features_Group>;
+def mno_simd128 : Flag<["-"], "mno-simd128">, Group<m_wasm_Features_Group>;
+
+def mvsx : Flag<["-"], "mvsx">, Group<m_ppc_Features_Group>;
+def mno_vsx : Flag<["-"], "mno-vsx">, Group<m_ppc_Features_Group>;
+def mpower8_vector : Flag<["-"], "mpower8-vector">,
+ Group<m_ppc_Features_Group>;
+def mno_power8_vector : Flag<["-"], "mno-power8-vector">,
+ Group<m_ppc_Features_Group>;
+def mpower8_crypto : Flag<["-"], "mcrypto">,
+ Group<m_ppc_Features_Group>;
+def mnopower8_crypto : Flag<["-"], "mno-crypto">,
+ Group<m_ppc_Features_Group>;
+def mdirect_move : Flag<["-"], "mdirect-move">,
+ Group<m_ppc_Features_Group>;
+def mnodirect_move : Flag<["-"], "mno-direct-move">,
+ Group<m_ppc_Features_Group>;
+def mhtm : Flag<["-"], "mhtm">, Group<m_ppc_Features_Group>;
+def mno_htm : Flag<["-"], "mno-htm">, Group<m_ppc_Features_Group>;
+def mfprnd : Flag<["-"], "mfprnd">, Group<m_ppc_Features_Group>;
+def mno_fprnd : Flag<["-"], "mno-fprnd">, Group<m_ppc_Features_Group>;
+def mcmpb : Flag<["-"], "mcmpb">, Group<m_ppc_Features_Group>;
+def mno_cmpb : Flag<["-"], "mno-cmpb">, Group<m_ppc_Features_Group>;
+def misel : Flag<["-"], "misel">, Group<m_ppc_Features_Group>;
+def mno_isel : Flag<["-"], "mno-isel">, Group<m_ppc_Features_Group>;
+def mmfocrf : Flag<["-"], "mmfocrf">, Group<m_ppc_Features_Group>;
+def mmfcrf : Flag<["-"], "mmfcrf">, Alias<mmfocrf>;
+def mno_mfocrf : Flag<["-"], "mno-mfocrf">, Group<m_ppc_Features_Group>;
+def mno_mfcrf : Flag<["-"], "mno-mfcrf">, Alias<mno_mfocrf>;
+def mpopcntd : Flag<["-"], "mpopcntd">, Group<m_ppc_Features_Group>;
+def mno_popcntd : Flag<["-"], "mno-popcntd">, Group<m_ppc_Features_Group>;
+def mqpx : Flag<["-"], "mqpx">, Group<m_ppc_Features_Group>;
+def mno_qpx : Flag<["-"], "mno-qpx">, Group<m_ppc_Features_Group>;
+def mcrbits : Flag<["-"], "mcrbits">, Group<m_ppc_Features_Group>;
+def mno_crbits : Flag<["-"], "mno-crbits">, Group<m_ppc_Features_Group>;
+def minvariant_function_descriptors :
+ Flag<["-"], "minvariant-function-descriptors">, Group<m_ppc_Features_Group>;
+def mno_invariant_function_descriptors :
+ Flag<["-"], "mno-invariant-function-descriptors">,
+ Group<m_ppc_Features_Group>;
+
+def faltivec : Flag<["-"], "faltivec">, Group<f_Group>, Flags<[CC1Option]>,
+ HelpText<"Enable AltiVec vector initializer syntax">;
+def fno_altivec : Flag<["-"], "fno-altivec">, Group<f_Group>, Flags<[CC1Option]>;
+def maltivec : Flag<["-"], "maltivec">, Alias<faltivec>;
+def mno_altivec : Flag<["-"], "mno-altivec">, Alias<fno_altivec>;
+
+def mvx : Flag<["-"], "mvx">, Group<m_Group>;
+def mno_vx : Flag<["-"], "mno-vx">, Group<m_Group>;
+
+def fzvector : Flag<["-"], "fzvector">, Group<f_Group>, Flags<[CC1Option]>,
+ HelpText<"Enable System z vector language extension">;
+def fno_zvector : Flag<["-"], "fno-zvector">, Group<f_Group>,
+ Flags<[CC1Option]>;
+def mzvector : Flag<["-"], "mzvector">, Alias<fzvector>;
+def mno_zvector : Flag<["-"], "mno-zvector">, Alias<fno_zvector>;
+
+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<m_Group>;
+def momit_leaf_frame_pointer : Flag<["-"], "momit-leaf-frame-pointer">, Group<m_Group>,
+ HelpText<"Omit frame pointer setup for leaf functions">, Flags<[CC1Option]>;
+def moslib_EQ : Joined<["-"], "moslib=">, Group<m_Group>;
+def mpascal_strings : Flag<["-"], "mpascal-strings">, Alias<fpascal_strings>;
+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>, Flags<[CC1Option,CC1AsOption]>,
+ HelpText<"(integrated-as) Relax all machine instructions">;
+def mincremental_linker_compatible : Flag<["-"], "mincremental-linker-compatible">, Group<m_Group>,
+ Flags<[CC1Option,CC1AsOption]>,
+ HelpText<"(integrated-as) Emit an object file which can be used with an incremental linker">;
+def mno_incremental_linker_compatible : Flag<["-"], "mno-incremental-linker-compatible">, Group<m_Group>,
+ HelpText<"(integrated-as) Emit an object file which cannot be used with an incremental linker">;
+def mrtd : Flag<["-"], "mrtd">, Group<m_Group>, Flags<[CC1Option]>,
+ HelpText<"Make StdCall calling convention the default">;
+def msmall_data_threshold_EQ : Joined <["-"], "msmall-data-threshold=">, Group<m_Group>;
+def msoft_float : Flag<["-"], "msoft-float">, Group<m_Group>, Flags<[CC1Option]>,
+ HelpText<"Use software floating point">;
+def mno_implicit_float : Flag<["-"], "mno-implicit-float">, Group<m_Group>,
+ HelpText<"Don't generate implicit floating point instructions">;
+def mimplicit_float : Flag<["-"], "mimplicit-float">, Group<m_Group>;
+def mrecip : Flag<["-"], "mrecip">, Group<m_Group>;
+def mrecip_EQ : CommaJoined<["-"], "mrecip=">, Group<m_Group>, Flags<[CC1Option]>;
+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_1 : Flag<["-"], "msse4.1">, Group<m_x86_Features_Group>;
+def msse4_2 : Flag<["-"], "msse4.2">, Group<m_x86_Features_Group>;
+def msse4 : Flag<["-"], "msse4">, Alias<msse4_2>;
+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 mavx2 : Flag<["-"], "mavx2">, Group<m_x86_Features_Group>;
+def mavx512f : Flag<["-"], "mavx512f">, Group<m_x86_Features_Group>;
+def mavx512cd : Flag<["-"], "mavx512cd">, Group<m_x86_Features_Group>;
+def mavx512er : Flag<["-"], "mavx512er">, Group<m_x86_Features_Group>;
+def mavx512pf : Flag<["-"], "mavx512pf">, Group<m_x86_Features_Group>;
+def mavx512dq : Flag<["-"], "mavx512dq">, Group<m_x86_Features_Group>;
+def mavx512bw : Flag<["-"], "mavx512bw">, Group<m_x86_Features_Group>;
+def mavx512vl : Flag<["-"], "mavx512vl">, Group<m_x86_Features_Group>;
+def mpclmul : Flag<["-"], "mpclmul">, Group<m_x86_Features_Group>;
+def mlzcnt : Flag<["-"], "mlzcnt">, Group<m_x86_Features_Group>;
+def mrdrnd : Flag<["-"], "mrdrnd">, Group<m_x86_Features_Group>;
+def mfsgsbase : Flag<["-"], "mfsgsbase">, Group<m_x86_Features_Group>;
+def mbmi : Flag<["-"], "mbmi">, Group<m_x86_Features_Group>;
+def mbmi2 : Flag<["-"], "mbmi2">, Group<m_x86_Features_Group>;
+def mpopcnt : Flag<["-"], "mpopcnt">, Group<m_x86_Features_Group>;
+def mtbm : Flag<["-"], "mtbm">, Group<m_x86_Features_Group>;
+def mfma4 : Flag<["-"], "mfma4">, Group<m_x86_Features_Group>;
+def mfma : Flag<["-"], "mfma">, Group<m_x86_Features_Group>;
+def mxop : Flag<["-"], "mxop">, Group<m_x86_Features_Group>;
+def mf16c : Flag<["-"], "mf16c">, Group<m_x86_Features_Group>;
+def mrtm : Flag<["-"], "mrtm">, Group<m_x86_Features_Group>;
+def mprfchw : Flag<["-"], "mprfchw">, Group<m_x86_Features_Group>;
+def mrdseed : Flag<["-"], "mrdseed">, Group<m_x86_Features_Group>;
+def mpku : Flag<["-"], "mpku">, Group<m_x86_Features_Group>;
+def madx : Flag<["-"], "madx">, Group<m_x86_Features_Group>;
+def msha : Flag<["-"], "msha">, Group<m_x86_Features_Group>;
+def mcx16 : Flag<["-"], "mcx16">, Group<m_x86_Features_Group>;
+def mfxsr : Flag<["-"], "mfxsr">, Group<m_x86_Features_Group>;
+def mxsave : Flag<["-"], "mxsave">, Group<m_x86_Features_Group>;
+def mxsaveopt : Flag<["-"], "mxsaveopt">, Group<m_x86_Features_Group>;
+def mxsavec : Flag<["-"], "mxsavec">, Group<m_x86_Features_Group>;
+def mxsaves : Flag<["-"], "mxsaves">, Group<m_x86_Features_Group>;
+def mips16 : Flag<["-"], "mips16">, Group<m_Group>;
+def mno_mips16 : Flag<["-"], "mno-mips16">, Group<m_Group>;
+def mmicromips : Flag<["-"], "mmicromips">, Group<m_Group>;
+def mno_micromips : Flag<["-"], "mno-micromips">, Group<m_Group>;
+def mxgot : Flag<["-"], "mxgot">, Group<m_Group>;
+def mno_xgot : Flag<["-"], "mno-xgot">, Group<m_Group>;
+def mldc1_sdc1 : Flag<["-"], "mldc1-sdc1">, Group<m_Group>;
+def mno_ldc1_sdc1 : Flag<["-"], "mno-ldc1-sdc1">, Group<m_Group>;
+def mcheck_zero_division : Flag<["-"], "mcheck-zero-division">, Group<m_Group>;
+def mno_check_zero_division : Flag<["-"], "mno-check-zero-division">,
+ Group<m_Group>;
+def mdsp : Flag<["-"], "mdsp">, Group<m_Group>;
+def mno_dsp : Flag<["-"], "mno-dsp">, Group<m_Group>;
+def mdspr2 : Flag<["-"], "mdspr2">, Group<m_Group>;
+def mno_dspr2 : Flag<["-"], "mno-dspr2">, Group<m_Group>;
+def msingle_float : Flag<["-"], "msingle-float">, Group<m_Group>;
+def mdouble_float : Flag<["-"], "mdouble-float">, Group<m_Group>;
+def mmsa : Flag<["-"], "mmsa">, Group<m_Group>,
+ HelpText<"Enable MSA ASE (MIPS only)">;
+def mno_msa : Flag<["-"], "mno-msa">, Group<m_Group>,
+ HelpText<"Disable MSA ASE (MIPS only)">;
+def mfp64 : Flag<["-"], "mfp64">, Group<m_Group>,
+ HelpText<"Use 64-bit floating point registers (MIPS only)">;
+def mfp32 : Flag<["-"], "mfp32">, Group<m_Group>,
+ HelpText<"Use 32-bit floating point registers (MIPS only)">;
+def mnan_EQ : Joined<["-"], "mnan=">, Group<m_Group>;
+def mabicalls : Flag<["-"], "mabicalls">, Group<m_Group>,
+ HelpText<"Enable SVR4-style position-independent code (Mips only)">;
+def mno_abicalls : Flag<["-"], "mno-abicalls">, Group<m_Group>,
+ HelpText<"Disable SVR4-style position-independent code (Mips only)">;
+def mips1 : Flag<["-"], "mips1">,
+ Alias<march_EQ>, AliasArgs<["mips1"]>,
+ HelpText<"Equivalent to -march=mips1">, Flags<[HelpHidden]>;
+def mips2 : Flag<["-"], "mips2">,
+ Alias<march_EQ>, AliasArgs<["mips2"]>,
+ HelpText<"Equivalent to -march=mips2">, Flags<[HelpHidden]>;
+def mips3 : Flag<["-"], "mips3">,
+ Alias<march_EQ>, AliasArgs<["mips3"]>,
+ HelpText<"Equivalent to -march=mips3">, Flags<[HelpHidden]>;
+def mips4 : Flag<["-"], "mips4">,
+ Alias<march_EQ>, AliasArgs<["mips4"]>,
+ HelpText<"Equivalent to -march=mips4">, Flags<[HelpHidden]>;
+def mips5 : Flag<["-"], "mips5">,
+ Alias<march_EQ>, AliasArgs<["mips5"]>,
+ HelpText<"Equivalent to -march=mips5">, Flags<[HelpHidden]>;
+def mips32 : Flag<["-"], "mips32">,
+ Alias<march_EQ>, AliasArgs<["mips32"]>,
+ HelpText<"Equivalent to -march=mips32">, Flags<[HelpHidden]>;
+def mips32r2 : Flag<["-"], "mips32r2">,
+ Alias<march_EQ>, AliasArgs<["mips32r2"]>,
+ HelpText<"Equivalent to -march=mips32r2">, Flags<[HelpHidden]>;
+def mips32r3 : Flag<["-"], "mips32r3">,
+ Alias<march_EQ>, AliasArgs<["mips32r3"]>,
+ HelpText<"Equivalent to -march=mips32r3">, Flags<[HelpHidden]>;
+def mips32r5 : Flag<["-"], "mips32r5">,
+ Alias<march_EQ>, AliasArgs<["mips32r5"]>,
+ HelpText<"Equivalent to -march=mips32r5">, Flags<[HelpHidden]>;
+def mips32r6 : Flag<["-"], "mips32r6">,
+ Alias<march_EQ>, AliasArgs<["mips32r6"]>,
+ HelpText<"Equivalent to -march=mips32r6">, Flags<[HelpHidden]>;
+def mips64 : Flag<["-"], "mips64">,
+ Alias<march_EQ>, AliasArgs<["mips64"]>,
+ HelpText<"Equivalent to -march=mips64">, Flags<[HelpHidden]>;
+def mips64r2 : Flag<["-"], "mips64r2">,
+ Alias<march_EQ>, AliasArgs<["mips64r2"]>,
+ HelpText<"Equivalent to -march=mips64r2">, Flags<[HelpHidden]>;
+def mips64r3 : Flag<["-"], "mips64r3">,
+ Alias<march_EQ>, AliasArgs<["mips64r3"]>,
+ HelpText<"Equivalent to -march=mips64r3">, Flags<[HelpHidden]>;
+def mips64r5 : Flag<["-"], "mips64r5">,
+ Alias<march_EQ>, AliasArgs<["mips64r5"]>,
+ HelpText<"Equivalent to -march=mips64r5">, Flags<[HelpHidden]>;
+def mips64r6 : Flag<["-"], "mips64r6">,
+ Alias<march_EQ>, AliasArgs<["mips64r6"]>,
+ HelpText<"Equivalent to -march=mips64r6">, Flags<[HelpHidden]>;
+def mfpxx : Flag<["-"], "mfpxx">, Group<m_Group>,
+ HelpText<"Avoid FPU mode dependent operations when used with the O32 ABI">,
+ Flags<[HelpHidden]>;
+def modd_spreg : Flag<["-"], "modd-spreg">, Group<m_Group>,
+ HelpText<"Enable odd single-precision floating point registers">,
+ Flags<[HelpHidden]>;
+def mno_odd_spreg : Flag<["-"], "mno-odd-spreg">, Group<m_Group>,
+ HelpText<"Disable odd single-precision floating point registers">,
+ Flags<[HelpHidden]>;
+def mglibc : Flag<["-"], "mglibc">, Group<m_libc_Group>, Flags<[HelpHidden]>;
+def muclibc : Flag<["-"], "muclibc">, Group<m_libc_Group>, Flags<[HelpHidden]>;
+def module_file_info : Flag<["-"], "module-file-info">, Flags<[DriverOption,CC1Option]>, Group<Action_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 no_canonical_prefixes : Flag<["-"], "no-canonical-prefixes">, Flags<[HelpHidden]>,
+ HelpText<"Use relative instead of canonical paths">;
+def no_cpp_precomp : Flag<["-"], "no-cpp-precomp">, Group<clang_ignored_f_Group>;
+def no_integrated_cpp : Flag<["-", "--"], "no-integrated-cpp">, Flags<[DriverOption]>;
+def no_pedantic : Flag<["-", "--"], "no-pedantic">, Group<pedantic_Group>;
+def no__dead__strip__inits__and__terms : Flag<["-"], "no_dead_strip_inits_and_terms">;
+def nobuiltininc : Flag<["-"], "nobuiltininc">, Flags<[CC1Option]>,
+ HelpText<"Disable builtin #include directories">;
+def nocudainc : Flag<["-"], "nocudainc">;
+def nocudalib : Flag<["-"], "nocudalib">;
+def nodefaultlibs : Flag<["-"], "nodefaultlibs">;
+def nofixprebinding : Flag<["-"], "nofixprebinding">;
+def nolibc : Flag<["-"], "nolibc">;
+def nomultidefs : Flag<["-"], "nomultidefs">;
+def nopie : Flag<["-"], "nopie">;
+def noprebind : Flag<["-"], "noprebind">;
+def noseglinkedit : Flag<["-"], "noseglinkedit">;
+def nostartfiles : Flag<["-"], "nostartfiles">;
+def nostdinc : Flag<["-"], "nostdinc">;
+def nostdlibinc : Flag<["-"], "nostdlibinc">;
+def nostdincxx : Flag<["-"], "nostdinc++">, Flags<[CC1Option]>,
+ HelpText<"Disable standard #include directories for the C++ standard library">;
+def nostdlib : Flag<["-"], "nostdlib">;
+def object : Flag<["-"], "object">;
+def o : JoinedOrSeparate<["-"], "o">, Flags<[DriverOption, RenderAsInput, CC1Option, CC1AsOption]>,
+ HelpText<"Write output to <file>">, MetaVarName<"<file>">;
+def omptargets_EQ : CommaJoined<["-"], "omptargets=">, Flags<[DriverOption, CC1Option]>,
+ HelpText<"Specify comma-separated list of triples OpenMP offloading targets to be supported">;
+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>, Flags<[CC1Option]>;
+def pedantic : Flag<["-", "--"], "pedantic">, Group<pedantic_Group>, Flags<[CC1Option]>;
+def pg : Flag<["-"], "pg">, HelpText<"Enable mcount instrumentation">, Flags<[CC1Option]>;
+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">, Flags<[CC1Option]>,
+ HelpText<"Enable Objective-C Ivar layout bitmap print trace">;
+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">,
+ Flags<[Unsupported]>;
+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">, Flags<[CC1Option]>,
+ HelpText<"Support POSIX threads in generated code">;
+def no_pthread : Flag<["-"], "no-pthread">, Flags<[CC1Option]>;
+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,CC1Option]>,
+ HelpText<"Rewrite Objective-C source to C++">, Group<Action_Group>;
+def rewrite_legacy_objc : Flag<["-"], "rewrite-legacy-objc">, Flags<[DriverOption]>,
+ HelpText<"Rewrite Legacy Objective-C source to C++">;
+def rdynamic : Flag<["-"], "rdynamic">;
+def resource_dir : Separate<["-"], "resource-dir">,
+ Flags<[DriverOption, CC1Option, HelpHidden]>,
+ HelpText<"The directory which holds the compiler resource files">;
+def resource_dir_EQ : Joined<["-"], "resource-dir=">, Flags<[DriverOption]>,
+ Alias<resource_dir>;
+def rpath : Separate<["-"], "rpath">, Flags<[LinkerInput]>;
+def rtlib_EQ : Joined<["-", "--"], "rtlib=">;
+def r : Flag<["-"], "r">, Flags<[LinkerInput,NoArgumentUnused]>;
+def save_temps_EQ : Joined<["-", "--"], "save-temps=">, Flags<[DriverOption]>,
+ HelpText<"Save intermediate compilation results.">;
+def save_temps : Flag<["-", "--"], "save-temps">, Flags<[DriverOption]>,
+ Alias<save_temps_EQ>, AliasArgs<["cwd"]>,
+ HelpText<"Save intermediate compilation results">;
+def via_file_asm : Flag<["-", "--"], "via-file-asm">, InternalDebugOpt,
+ HelpText<"Write assembly to file for input to assemble jobs">;
+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_libstdcxx : Flag<["-"], "static-libstdc++">;
+def static : Flag<["-", "--"], "static">, Flags<[NoArgumentUnused]>;
+def std_default_EQ : Joined<["-"], "std-default=">;
+def std_EQ : Joined<["-", "--"], "std=">, Flags<[CC1Option]>,
+ Group<CompileOnly_Group>, HelpText<"Language standard to compile for">;
+def stdlib_EQ : Joined<["-", "--"], "stdlib=">, Flags<[CC1Option]>,
+ HelpText<"C++ standard library to use">;
+def sub__library : JoinedOrSeparate<["-"], "sub_library">;
+def sub__umbrella : JoinedOrSeparate<["-"], "sub_umbrella">;
+def system_header_prefix : Joined<["--"], "system-header-prefix=">,
+ Group<clang_i_Group>, Flags<[CC1Option]>, MetaVarName<"<prefix>">,
+ HelpText<"Treat all #include paths starting with <prefix> as including a "
+ "system header.">;
+def : Separate<["--"], "system-header-prefix">, Alias<system_header_prefix>;
+def no_system_header_prefix : Joined<["--"], "no-system-header-prefix=">,
+ Group<clang_i_Group>, Flags<[CC1Option]>, MetaVarName<"<prefix>">,
+ HelpText<"Treat all #include paths starting with <prefix> as not including a "
+ "system header.">;
+def : Separate<["--"], "no-system-header-prefix">, Alias<no_system_header_prefix>;
+def s : Flag<["-"], "s">;
+def target : Joined<["--"], "target=">, Flags<[DriverOption, CoreOption]>,
+ HelpText<"Generate code for the given target">;
+def gcc_toolchain : Joined<["--"], "gcc-toolchain=">, Flags<[DriverOption]>,
+ HelpText<"Use the gcc toolchain at the given directory">;
+def time : Flag<["-"], "time">,
+ HelpText<"Time individual commands">;
+def traditional_cpp : Flag<["-", "--"], "traditional-cpp">, Flags<[CC1Option]>,
+ HelpText<"Enable some traditional CPP emulation">;
+def traditional : Flag<["-", "--"], "traditional">;
+def trigraphs : Flag<["-", "--"], "trigraphs">, Alias<ftrigraphs>,
+ HelpText<"Process trigraph sequences">;
+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>, Flags<[CC1Option]>,
+ HelpText<"undef all system defines">;
+def unexported__symbols__list : Separate<["-"], "unexported_symbols_list">;
+def u : JoinedOrSeparate<["-"], "u">, Group<u_Group>;
+def v : Flag<["-"], "v">, Flags<[CC1Option, CoreOption]>,
+ HelpText<"Show commands to run and use verbose output">;
+def verify_debug_info : Flag<["--"], "verify-debug-info">, Flags<[DriverOption]>,
+ HelpText<"Verify the binary representation of debug 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">, HelpText<"Suppress all warnings">, Flags<[CC1Option]>;
+def x : JoinedOrSeparate<["-"], "x">, Flags<[DriverOption,CC1Option]>,
+ HelpText<"Treat subsequent input files as having type <language>">,
+ MetaVarName<"<language>">;
+def y : Joined<["-"], "y">;
+
+def fintegrated_as : Flag<["-"], "fintegrated-as">, Flags<[DriverOption]>,
+ Group<f_Group>, HelpText<"Enable the integrated assembler">;
+def fno_integrated_as : Flag<["-"], "fno-integrated-as">,
+ Flags<[CC1Option, DriverOption]>, Group<f_Group>,
+ HelpText<"Disable the integrated assembler">;
+def : Flag<["-"], "integrated-as">, Alias<fintegrated_as>, Flags<[DriverOption]>;
+def : Flag<["-"], "no-integrated-as">, Alias<fno_integrated_as>,
+ Flags<[CC1Option, DriverOption]>;
+
+def working_directory : JoinedOrSeparate<["-"], "working-directory">, Flags<[CC1Option]>,
+ HelpText<"Resolve file paths relative to the specified directory">;
+def working_directory_EQ : Joined<["-"], "working-directory=">, Flags<[CC1Option]>,
+ Alias<working_directory>;
+
+// Double dash options, which are usually an alias for one of the previous
+// options.
+
+def _mhwdiv_EQ : Joined<["--"], "mhwdiv=">, Alias<mhwdiv_EQ>;
+def _mhwdiv : Separate<["--"], "mhwdiv">, Alias<mhwdiv_EQ>;
+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, CoreOption]>,
+ HelpText<"Run the static analyzer">;
+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 _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 _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 _dyld_prefix_EQ : Joined<["--"], "dyld-prefix=">;
+def _dyld_prefix : Separate<["--"], "dyld-prefix">, Alias<_dyld_prefix_EQ>;
+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 _imacros_EQ : Joined<["--"], "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 _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 _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">, Group<CompileOnly_Group>;
+def _param_EQ : Joined<["--"], "param=">, Alias<_param>;
+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 : Separate<["--"], "print-file-name">, Alias<print_file_name_EQ>;
+def _print_missing_file_dependencies : Flag<["--"], "print-missing-file-dependencies">, Alias<MG>;
+def _print_prog_name : Separate<["--"], "print-prog-name">, Alias<print_prog_name_EQ>;
+def _profile_blocks : Flag<["--"], "profile-blocks">, Alias<a>;
+def _profile : Flag<["--"], "profile">, Alias<p>;
+def _resource_EQ : Joined<["--"], "resource=">, Alias<fcompile_resource_EQ>;
+def _resource : Separate<["--"], "resource">, Alias<fcompile_resource_EQ>;
+def _rtlib : Separate<["--"], "rtlib">, Alias<rtlib_EQ>;
+def _serialize_diags : Separate<["-", "--"], "serialize-diagnostics">, Flags<[DriverOption]>,
+ HelpText<"Serialize compiler diagnostics to a file">;
+// We give --version different semantics from -version.
+def _version : Flag<["--"], "version">, Flags<[CC1Option]>;
+def _signed_char : Flag<["--"], "signed-char">, Alias<fsigned_char>;
+def _std : Separate<["--"], "std">, Alias<std_EQ>;
+def _stdlib : Separate<["--"], "stdlib">, Alias<stdlib_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 _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 _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]>;
+
+def mieee_rnd_near : Flag<["-"], "mieee-rnd-near">, Group<m_hexagon_Features_Group>;
+def mv4 : Flag<["-"], "mv4">, Group<m_hexagon_Features_Group>,
+ Alias<mcpu_EQ>, AliasArgs<["v4"]>;
+def mv5 : Flag<["-"], "mv5">, Group<m_hexagon_Features_Group>, Alias<mcpu_EQ>,
+ AliasArgs<["v5"]>;
+def mv55 : Flag<["-"], "mv55">, Group<m_hexagon_Features_Group>,
+ Alias<mcpu_EQ>, AliasArgs<["v55"]>;
+def mv60 : Flag<["-"], "mv60">, Group<m_hexagon_Features_Group>,
+ Alias<mcpu_EQ>, AliasArgs<["v60"]>;
+def mhexagon_hvx : Flag<["-"], "mhvx">, Group<m_hexagon_Features_Group>,
+ Flags<[CC1Option]>, HelpText<"Enable Hexagon Vector eXtensions">;
+def mno_hexagon_hvx : Flag<["-"], "mno-hvx">, Group<m_hexagon_Features_Group>,
+ Flags<[CC1Option]>, HelpText<"Disable Hexagon Vector eXtensions">;
+def mhexagon_hvx_double : Flag<["-"], "mhvx-double">, Group<m_hexagon_Features_Group>,
+ Flags<[CC1Option]>, HelpText<"Enable Hexagon Double Vector eXtensions">;
+def mno_hexagon_hvx_double : Flag<["-"], "mno-hvx-double">, Group<m_hexagon_Features_Group>,
+ Flags<[CC1Option]>, HelpText<"Disable Hexagon Double Vector eXtensions">;
+
+// These are legacy user-facing driver-level option spellings. They are always
+// aliases for options that are spelled using the more common Unix / GNU flag
+// style of double-dash and equals-joined flags.
+def gcc_toolchain_legacy_spelling : Separate<["-"], "gcc-toolchain">, Alias<gcc_toolchain>;
+def target_legacy_spelling : Separate<["-"], "target">, Alias<target>;
+
+// 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>;
+
+// Ignored options
+// FIXME: multiclasess produce suffixes, not prefixes. This is fine for now
+// since it is only used in ignored options.
+multiclass BooleanFFlag<string name> {
+ def _f : Flag<["-"], "f"#name>;
+ def _fno : Flag<["-"], "fno-"#name>;
+}
+
+defm : BooleanFFlag<"keep-inline-functions">, Group<clang_ignored_gcc_optimization_f_Group>;
+
+def fprofile_dir : Joined<["-"], "fprofile-dir=">, Group<clang_ignored_gcc_optimization_f_Group>;
+
+def fuse_ld_EQ : Joined<["-"], "fuse-ld=">, Group<f_Group>;
+
+defm align_functions : BooleanFFlag<"align-functions">, Group<clang_ignored_gcc_optimization_f_Group>;
+def falign_functions_EQ : Joined<["-"], "falign-functions=">, Group<clang_ignored_gcc_optimization_f_Group>;
+defm align_labels : BooleanFFlag<"align-labels">, Group<clang_ignored_gcc_optimization_f_Group>;
+def falign_labels_EQ : Joined<["-"], "falign-labels=">, Group<clang_ignored_gcc_optimization_f_Group>;
+defm align_loops : BooleanFFlag<"align-loops">, Group<clang_ignored_gcc_optimization_f_Group>;
+def falign_loops_EQ : Joined<["-"], "falign-loops=">, Group<clang_ignored_gcc_optimization_f_Group>;
+defm align_jumps : BooleanFFlag<"align-jumps">, Group<clang_ignored_gcc_optimization_f_Group>;
+def falign_jumps_EQ : Joined<["-"], "falign-jumps=">, Group<clang_ignored_gcc_optimization_f_Group>;
+
+// FIXME: This option should be supported and wired up to our diognostics, but
+// ignore it for now to avoid breaking builds that use it.
+def fdiagnostics_show_location_EQ : Joined<["-"], "fdiagnostics-show-location=">, Group<clang_ignored_f_Group>;
+
+defm fcheck_new : BooleanFFlag<"check-new">, Group<clang_ignored_f_Group>;
+defm caller_saves : BooleanFFlag<"caller-saves">, Group<clang_ignored_gcc_optimization_f_Group>;
+defm reorder_blocks : BooleanFFlag<"reorder-blocks">, Group<clang_ignored_gcc_optimization_f_Group>;
+defm eliminate_unused_debug_types : BooleanFFlag<"eliminate-unused-debug-types">, Group<clang_ignored_f_Group>;
+defm branch_count_reg : BooleanFFlag<"branch-count-reg">, Group<clang_ignored_gcc_optimization_f_Group>;
+defm default_inline : BooleanFFlag<"default-inline">, Group<clang_ignored_gcc_optimization_f_Group>;
+defm delete_null_pointer_checks : BooleanFFlag<"delete-null-pointer-checks">,
+ Group<clang_ignored_gcc_optimization_f_Group>;
+defm fat_lto_objects : BooleanFFlag<"fat-lto-objects">, Group<clang_ignored_gcc_optimization_f_Group>;
+defm float_store : BooleanFFlag<"float-store">, Group<clang_ignored_gcc_optimization_f_Group>;
+defm friend_injection : BooleanFFlag<"friend-injection">, Group<clang_ignored_f_Group>;
+defm function_attribute_list : BooleanFFlag<"function-attribute-list">, Group<clang_ignored_f_Group>;
+defm gcse : BooleanFFlag<"gcse">, Group<clang_ignored_gcc_optimization_f_Group>;
+defm gcse_after_reload: BooleanFFlag<"gcse-after-reload">, Group<clang_ignored_gcc_optimization_f_Group>;
+defm gcse_las: BooleanFFlag<"gcse-las">, Group<clang_ignored_gcc_optimization_f_Group>;
+defm gcse_sm: BooleanFFlag<"gcse-sm">, Group<clang_ignored_gcc_optimization_f_Group>;
+defm gnu : BooleanFFlag<"gnu">, Group<clang_ignored_f_Group>;
+defm ident : BooleanFFlag<"ident">, Group<clang_ignored_f_Group>;
+defm implicit_templates : BooleanFFlag<"implicit-templates">, Group<clang_ignored_f_Group>;
+defm implement_inlines : BooleanFFlag<"implement-inlines">, Group<clang_ignored_f_Group>;
+defm merge_constants : BooleanFFlag<"merge-constants">, Group<clang_ignored_gcc_optimization_f_Group>;
+defm modulo_sched : BooleanFFlag<"modulo-sched">, Group<clang_ignored_gcc_optimization_f_Group>;
+defm modulo_sched_allow_regmoves : BooleanFFlag<"modulo-sched-allow-regmoves">,
+ Group<clang_ignored_gcc_optimization_f_Group>;
+defm inline_functions_called_once : BooleanFFlag<"inline-functions-called-once">,
+ Group<clang_ignored_gcc_optimization_f_Group>;
+def finline_limit_EQ : Joined<["-"], "finline-limit=">, Group<clang_ignored_gcc_optimization_f_Group>;
+defm finline_limit : BooleanFFlag<"inline-limit">, Group<clang_ignored_gcc_optimization_f_Group>;
+defm inline_small_functions : BooleanFFlag<"inline-small-functions">,
+ Group<clang_ignored_gcc_optimization_f_Group>;
+defm ipa_cp : BooleanFFlag<"ipa-cp">,
+ Group<clang_ignored_gcc_optimization_f_Group>;
+defm ivopts : BooleanFFlag<"ivopts">, Group<clang_ignored_gcc_optimization_f_Group>;
+defm non_call_exceptions : BooleanFFlag<"non-call-exceptions">, Group<clang_ignored_f_Group>;
+defm peel_loops : BooleanFFlag<"peel-loops">, Group<clang_ignored_gcc_optimization_f_Group>;
+defm permissive : BooleanFFlag<"permissive">, Group<clang_ignored_f_Group>;
+defm prefetch_loop_arrays : BooleanFFlag<"prefetch-loop-arrays">, Group<clang_ignored_gcc_optimization_f_Group>;
+defm printf : BooleanFFlag<"printf">, Group<clang_ignored_f_Group>;
+defm profile : BooleanFFlag<"profile">, Group<clang_ignored_f_Group>;
+defm profile_correction : BooleanFFlag<"profile-correction">, Group<clang_ignored_gcc_optimization_f_Group>;
+defm profile_generate_sampling : BooleanFFlag<"profile-generate-sampling">, Group<clang_ignored_f_Group>;
+defm profile_reusedist : BooleanFFlag<"profile-reusedist">, Group<clang_ignored_f_Group>;
+defm profile_values : BooleanFFlag<"profile-values">, Group<clang_ignored_gcc_optimization_f_Group>;
+defm regs_graph : BooleanFFlag<"regs-graph">, Group<clang_ignored_f_Group>;
+defm rename_registers : BooleanFFlag<"rename-registers">, Group<clang_ignored_gcc_optimization_f_Group>;
+defm ripa : BooleanFFlag<"ripa">, Group<clang_ignored_f_Group>;
+defm rounding_math : BooleanFFlag<"rounding-math">, Group<clang_ignored_gcc_optimization_f_Group>;
+defm schedule_insns : BooleanFFlag<"schedule-insns">, Group<clang_ignored_gcc_optimization_f_Group>;
+defm schedule_insns2 : BooleanFFlag<"schedule-insns2">, Group<clang_ignored_gcc_optimization_f_Group>;
+defm see : BooleanFFlag<"see">, Group<clang_ignored_f_Group>;
+defm signaling_nans : BooleanFFlag<"signaling-nans">, Group<clang_ignored_gcc_optimization_f_Group>;
+defm single_precision_constant : BooleanFFlag<"single-precision-constant">,
+ Group<clang_ignored_gcc_optimization_f_Group>;
+defm spec_constr_count : BooleanFFlag<"spec-constr-count">, Group<clang_ignored_f_Group>;
+defm stack_check : BooleanFFlag<"stack-check">, Group<clang_ignored_f_Group>;
+defm strength_reduce :
+ BooleanFFlag<"strength-reduce">, Group<clang_ignored_gcc_optimization_f_Group>;
+defm tls_model : BooleanFFlag<"tls-model">, Group<clang_ignored_f_Group>;
+defm tracer : BooleanFFlag<"tracer">, Group<clang_ignored_gcc_optimization_f_Group>;
+defm tree_dce : BooleanFFlag<"tree-dce">, Group<clang_ignored_gcc_optimization_f_Group>;
+defm tree_loop_im : BooleanFFlag<"tree_loop_im">, Group<clang_ignored_gcc_optimization_f_Group>;
+defm tree_loop_ivcanon : BooleanFFlag<"tree_loop_ivcanon">, Group<clang_ignored_gcc_optimization_f_Group>;
+defm tree_loop_linear : BooleanFFlag<"tree_loop_linear">, Group<clang_ignored_gcc_optimization_f_Group>;
+defm tree_salias : BooleanFFlag<"tree-salias">, Group<clang_ignored_f_Group>;
+defm tree_ter : BooleanFFlag<"tree-ter">, Group<clang_ignored_gcc_optimization_f_Group>;
+defm tree_vectorizer_verbose : BooleanFFlag<"tree-vectorizer-verbose">, Group<clang_ignored_f_Group>;
+defm tree_vrp : BooleanFFlag<"tree-vrp">, Group<clang_ignored_gcc_optimization_f_Group>;
+defm unroll_all_loops : BooleanFFlag<"unroll-all-loops">, Group<clang_ignored_gcc_optimization_f_Group>;
+defm unsafe_loop_optimizations : BooleanFFlag<"unsafe-loop-optimizations">,
+ Group<clang_ignored_gcc_optimization_f_Group>;
+defm unswitch_loops : BooleanFFlag<"unswitch-loops">, Group<clang_ignored_gcc_optimization_f_Group>;
+defm use_linker_plugin : BooleanFFlag<"use-linker-plugin">, Group<clang_ignored_gcc_optimization_f_Group>;
+defm vect_cost_model : BooleanFFlag<"vect-cost-model">, Group<clang_ignored_gcc_optimization_f_Group>;
+defm variable_expansion_in_unroller : BooleanFFlag<"variable-expansion-in-unroller">,
+ Group<clang_ignored_gcc_optimization_f_Group>;
+defm web : BooleanFFlag<"web">, Group<clang_ignored_gcc_optimization_f_Group>;
+defm whole_program : BooleanFFlag<"whole-program">, Group<clang_ignored_gcc_optimization_f_Group>;
+defm devirtualize : BooleanFFlag<"devirtualize">, Group<clang_ignored_gcc_optimization_f_Group>;
+defm devirtualize_speculatively : BooleanFFlag<"devirtualize-speculatively">,
+ Group<clang_ignored_gcc_optimization_f_Group>;
+
+// gfortran options that we recognize in the driver and pass along when
+// invoking GCC to compile Fortran code.
+def gfortran_Group : OptionGroup<"gfortran Group">;
+
+// Generic gfortran options.
+def A_DASH : Joined<["-"], "A-">, Group<gfortran_Group>;
+def J : JoinedOrSeparate<["-"], "J">, Flags<[RenderJoined]>, Group<gfortran_Group>;
+def cpp : Flag<["-"], "cpp">, Group<gfortran_Group>;
+def nocpp : Flag<["-"], "nocpp">, Group<gfortran_Group>;
+def static_libgfortran : Flag<["-"], "static-libgfortran">, Group<gfortran_Group>;
+
+// "f" options with values for gfortran.
+def fblas_matmul_limit_EQ : Joined<["-"], "fblas-matmul-limit=">, Group<gfortran_Group>;
+def fcheck_EQ : Joined<["-"], "fcheck=">, Group<gfortran_Group>;
+def fcoarray_EQ : Joined<["-"], "fcoarray=">, Group<gfortran_Group>;
+def fconvert_EQ : Joined<["-"], "fconvert=">, Group<gfortran_Group>;
+def ffixed_line_length_VALUE : Joined<["-"], "ffixed-line-length-">, Group<gfortran_Group>;
+def ffpe_trap_EQ : Joined<["-"], "ffpe-trap=">, Group<gfortran_Group>;
+def ffree_line_length_VALUE : Joined<["-"], "ffree-line-length-">, Group<gfortran_Group>;
+def finit_character_EQ : Joined<["-"], "finit-character=">, Group<gfortran_Group>;
+def finit_integer_EQ : Joined<["-"], "finit-integer=">, Group<gfortran_Group>;
+def finit_logical_EQ : Joined<["-"], "finit-logical=">, Group<gfortran_Group>;
+def finit_real_EQ : Joined<["-"], "finit-real=">, Group<gfortran_Group>;
+def fmax_array_constructor_EQ : Joined<["-"], "fmax-array-constructor=">, Group<gfortran_Group>;
+def fmax_errors_EQ : Joined<["-"], "fmax-errors=">, Group<gfortran_Group>;
+def fmax_stack_var_size_EQ : Joined<["-"], "fmax-stack-var-size=">, Group<gfortran_Group>;
+def fmax_subrecord_length_EQ : Joined<["-"], "fmax-subrecord-length=">, Group<gfortran_Group>;
+def frecord_marker_EQ : Joined<["-"], "frecord-marker=">, Group<gfortran_Group>;
+
+// "f" flags for gfortran.
+defm aggressive_function_elimination : BooleanFFlag<"aggressive-function-elimination">, Group<gfortran_Group>;
+defm align_commons : BooleanFFlag<"align-commons">, Group<gfortran_Group>;
+defm all_intrinsics : BooleanFFlag<"all-intrinsics">, Group<gfortran_Group>;
+defm automatic : BooleanFFlag<"automatic">, Group<gfortran_Group>;
+defm backslash : BooleanFFlag<"backslash">, Group<gfortran_Group>;
+defm backtrace : BooleanFFlag<"backtrace">, Group<gfortran_Group>;
+defm bounds_check : BooleanFFlag<"bounds-check">, Group<gfortran_Group>;
+defm check_array_temporaries : BooleanFFlag<"check-array-temporaries">, Group<gfortran_Group>;
+defm cray_pointer : BooleanFFlag<"cray-pointer">, Group<gfortran_Group>;
+defm d_lines_as_code : BooleanFFlag<"d-lines-as-code">, Group<gfortran_Group>;
+defm d_lines_as_comments : BooleanFFlag<"d-lines-as-comments">, Group<gfortran_Group>;
+defm default_double_8 : BooleanFFlag<"default-double-8">, Group<gfortran_Group>;
+defm default_integer_8 : BooleanFFlag<"default-integer-8">, Group<gfortran_Group>;
+defm default_real_8 : BooleanFFlag<"default-real-8">, Group<gfortran_Group>;
+defm dollar_ok : BooleanFFlag<"dollar-ok">, Group<gfortran_Group>;
+defm dump_fortran_optimized : BooleanFFlag<"dump-fortran-optimized">, Group<gfortran_Group>;
+defm dump_fortran_original : BooleanFFlag<"dump-fortran-original">, Group<gfortran_Group>;
+defm dump_parse_tree : BooleanFFlag<"dump-parse-tree">, Group<gfortran_Group>;
+defm external_blas : BooleanFFlag<"external-blas">, Group<gfortran_Group>;
+defm f2c : BooleanFFlag<"f2c">, Group<gfortran_Group>;
+defm fixed_form : BooleanFFlag<"fixed-form">, Group<gfortran_Group>;
+defm free_form : BooleanFFlag<"free-form">, Group<gfortran_Group>;
+defm frontend_optimize : BooleanFFlag<"frontend-optimize">, Group<gfortran_Group>;
+defm implicit_none : BooleanFFlag<"implicit-none">, Group<gfortran_Group>;
+defm init_local_zero : BooleanFFlag<"init-local-zero">, Group<gfortran_Group>;
+defm integer_4_integer_8 : BooleanFFlag<"integer-4-integer-8">, Group<gfortran_Group>;
+defm intrinsic_modules_path : BooleanFFlag<"intrinsic-modules-path">, Group<gfortran_Group>;
+defm max_identifier_length : BooleanFFlag<"max-identifier-length">, Group<gfortran_Group>;
+defm module_private : BooleanFFlag<"module-private">, Group<gfortran_Group>;
+defm pack_derived : BooleanFFlag<"pack-derived">, Group<gfortran_Group>;
+defm protect_parens : BooleanFFlag<"protect-parens">, Group<gfortran_Group>;
+defm range_check : BooleanFFlag<"range-check">, Group<gfortran_Group>;
+defm real_4_real_10 : BooleanFFlag<"real-4-real-10">, Group<gfortran_Group>;
+defm real_4_real_16 : BooleanFFlag<"real-4-real-16">, Group<gfortran_Group>;
+defm real_4_real_8 : BooleanFFlag<"real-4-real-8">, Group<gfortran_Group>;
+defm real_8_real_10 : BooleanFFlag<"real-8-real-10">, Group<gfortran_Group>;
+defm real_8_real_16 : BooleanFFlag<"real-8-real-16">, Group<gfortran_Group>;
+defm real_8_real_4 : BooleanFFlag<"real-8-real-4">, Group<gfortran_Group>;
+defm realloc_lhs : BooleanFFlag<"realloc-lhs">, Group<gfortran_Group>;
+defm recursive : BooleanFFlag<"recursive">, Group<gfortran_Group>;
+defm repack_arrays : BooleanFFlag<"repack-arrays">, Group<gfortran_Group>;
+defm second_underscore : BooleanFFlag<"second-underscore">, Group<gfortran_Group>;
+defm sign_zero : BooleanFFlag<"sign-zero">, Group<gfortran_Group>;
+defm stack_arrays : BooleanFFlag<"stack-arrays">, Group<gfortran_Group>;
+defm underscoring : BooleanFFlag<"underscoring">, Group<gfortran_Group>;
+defm whole_file : BooleanFFlag<"whole-file">, Group<gfortran_Group>;
+
+
+include "CC1Options.td"
+
+include "CLCompatOptions.td"
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..cd6b5b5
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Driver/Phases.h
@@ -0,0 +1,37 @@
+//===--- 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 LLVM_CLANG_DRIVER_PHASES_H
+#define LLVM_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,
+ Backend,
+ Assemble,
+ Link
+ };
+
+ enum {
+ MaxNumberOfPhases = Link + 1
+ };
+
+ 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/SanitizerArgs.h b/contrib/llvm/tools/clang/include/clang/Driver/SanitizerArgs.h
new file mode 100644
index 0000000..c2611b5
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Driver/SanitizerArgs.h
@@ -0,0 +1,73 @@
+//===--- SanitizerArgs.h - Arguments for sanitizer tools -------*- 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_DRIVER_SANITIZERARGS_H
+#define LLVM_CLANG_DRIVER_SANITIZERARGS_H
+
+#include "clang/Basic/Sanitizers.h"
+#include "clang/Driver/Types.h"
+#include "llvm/Option/Arg.h"
+#include "llvm/Option/ArgList.h"
+#include <string>
+#include <vector>
+
+namespace clang {
+namespace driver {
+
+class ToolChain;
+
+class SanitizerArgs {
+ SanitizerSet Sanitizers;
+ SanitizerSet RecoverableSanitizers;
+ SanitizerSet TrapSanitizers;
+
+ std::vector<std::string> BlacklistFiles;
+ std::vector<std::string> ExtraDeps;
+ int CoverageFeatures;
+ int MsanTrackOrigins;
+ bool MsanUseAfterDtor;
+ bool CfiCrossDso;
+ int AsanFieldPadding;
+ bool AsanSharedRuntime;
+ bool LinkCXXRuntimes;
+ bool NeedPIE;
+
+ public:
+ /// Parses the sanitizer arguments from an argument list.
+ SanitizerArgs(const ToolChain &TC, const llvm::opt::ArgList &Args);
+
+ bool needsAsanRt() const { return Sanitizers.has(SanitizerKind::Address); }
+ bool needsSharedAsanRt() const { return AsanSharedRuntime; }
+ bool needsTsanRt() const { return Sanitizers.has(SanitizerKind::Thread); }
+ bool needsMsanRt() const { return Sanitizers.has(SanitizerKind::Memory); }
+ bool needsLsanRt() const {
+ return Sanitizers.has(SanitizerKind::Leak) &&
+ !Sanitizers.has(SanitizerKind::Address);
+ }
+ bool needsUbsanRt() const;
+ bool needsDfsanRt() const { return Sanitizers.has(SanitizerKind::DataFlow); }
+ bool needsSafeStackRt() const {
+ return Sanitizers.has(SanitizerKind::SafeStack);
+ }
+ bool needsCfiRt() const;
+ bool needsCfiDiagRt() const;
+
+ bool requiresPIE() const;
+ bool needsUnwindTables() const;
+ bool linkCXXRuntimes() const { return LinkCXXRuntimes; }
+ void addArgs(const ToolChain &TC, const llvm::opt::ArgList &Args,
+ llvm::opt::ArgStringList &CmdArgs, types::ID InputType) const;
+
+ private:
+ void clear();
+};
+
+} // namespace driver
+} // 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..b9eac1c
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Driver/Tool.h
@@ -0,0 +1,137 @@
+//===--- 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 LLVM_CLANG_DRIVER_TOOL_H
+#define LLVM_CLANG_DRIVER_TOOL_H
+
+#include "clang/Basic/LLVM.h"
+#include "llvm/Support/Program.h"
+
+namespace llvm {
+namespace opt {
+ class ArgList;
+}
+}
+
+namespace clang {
+namespace driver {
+
+ class Compilation;
+ class InputInfo;
+ class Job;
+ class JobAction;
+ class ToolChain;
+
+ typedef SmallVector<InputInfo, 4> InputInfoList;
+
+/// Tool - Information on a specific compilation tool.
+class Tool {
+public:
+ // Documents the level of support for response files in this tool.
+ // Response files are necessary if the command line gets too large,
+ // requiring the arguments to be transfered to a file.
+ enum ResponseFileSupport {
+ // Provides full support for response files, which means we can transfer
+ // all tool input arguments to a file. E.g.: clang, gcc, binutils and MSVC
+ // tools.
+ RF_Full,
+ // Input file names can live in a file, but flags can't. E.g.: ld64 (Mac
+ // OS X linker).
+ RF_FileList,
+ // Does not support response files: all arguments must be passed via
+ // command line.
+ RF_None
+ };
+
+private:
+ /// 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;
+
+ /// The level of support for response files seen in this tool
+ const ResponseFileSupport ResponseSupport;
+
+ /// The encoding to use when writing response files for this tool on Windows
+ const llvm::sys::WindowsEncodingMethod ResponseEncoding;
+
+ /// The flag used to pass a response file via command line to this tool
+ const char *const ResponseFlag;
+
+public:
+ Tool(const char *Name, const char *ShortName, const ToolChain &TC,
+ ResponseFileSupport ResponseSupport = RF_None,
+ llvm::sys::WindowsEncodingMethod ResponseEncoding = llvm::sys::WEM_UTF8,
+ const char *ResponseFlag = "@");
+
+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 canEmitIR() const { return false; }
+ virtual bool hasIntegratedCPP() const = 0;
+ virtual bool isLinkJob() const { return false; }
+ virtual bool isDsymutilJob() const { return false; }
+ /// \brief Returns the level of support for response files of this tool,
+ /// whether it accepts arguments to be passed via a file on disk.
+ ResponseFileSupport getResponseFilesSupport() const {
+ return ResponseSupport;
+ }
+ /// \brief Returns which encoding the response file should use. This is only
+ /// relevant on Windows platforms where there are different encodings being
+ /// accepted for different tools. On UNIX, UTF8 is universal.
+ ///
+ /// Windows use cases: - GCC and Binutils on mingw only accept ANSI response
+ /// files encoded with the system current code page.
+ /// - MSVC's CL.exe and LINK.exe accept UTF16 on Windows.
+ /// - Clang accepts both UTF8 and UTF16.
+ ///
+ /// FIXME: When GNU tools learn how to parse UTF16 on Windows, we should
+ /// always use UTF16 for Windows, which is the Windows official encoding for
+ /// international characters.
+ llvm::sys::WindowsEncodingMethod getResponseFileEncoding() const {
+ return ResponseEncoding;
+ }
+ /// \brief Returns which prefix to use when passing the name of a response
+ /// file as a parameter to this tool.
+ const char *getResponseFileFlag() const { return ResponseFlag; }
+
+ /// \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 \p JA,
+ /// writing to \p Output and with \p Inputs, and add the jobs to
+ /// \p C.
+ ///
+ /// \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 llvm::opt::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..ed73107
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Driver/ToolChain.h
@@ -0,0 +1,418 @@
+//===--- 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 LLVM_CLANG_DRIVER_TOOLCHAIN_H
+#define LLVM_CLANG_DRIVER_TOOLCHAIN_H
+
+#include "clang/Basic/Sanitizers.h"
+#include "clang/Driver/Action.h"
+#include "clang/Driver/Multilib.h"
+#include "clang/Driver/Types.h"
+#include "clang/Driver/Util.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/Triple.h"
+#include "llvm/Support/Path.h"
+#include "llvm/Target/TargetOptions.h"
+#include <memory>
+#include <string>
+
+namespace llvm {
+namespace opt {
+ class ArgList;
+ class DerivedArgList;
+ class InputArgList;
+}
+}
+
+namespace clang {
+class ObjCRuntime;
+namespace vfs {
+class FileSystem;
+}
+
+namespace driver {
+ class Compilation;
+ class Driver;
+ class JobAction;
+ class SanitizerArgs;
+ class Tool;
+
+/// ToolChain - Access to tools for a single platform.
+class ToolChain {
+public:
+ typedef SmallVector<std::string, 16> path_list;
+
+ enum CXXStdlibType {
+ CST_Libcxx,
+ CST_Libstdcxx
+ };
+
+ enum RuntimeLibType {
+ RLT_CompilerRT,
+ RLT_Libgcc
+ };
+
+ enum RTTIMode {
+ RM_EnabledExplicitly,
+ RM_EnabledImplicitly,
+ RM_DisabledExplicitly,
+ RM_DisabledImplicitly
+ };
+
+private:
+ const Driver &D;
+ const llvm::Triple Triple;
+ const llvm::opt::ArgList &Args;
+ // We need to initialize CachedRTTIArg before CachedRTTIMode
+ const llvm::opt::Arg *const CachedRTTIArg;
+ const RTTIMode CachedRTTIMode;
+
+ /// 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;
+
+ mutable std::unique_ptr<Tool> Clang;
+ mutable std::unique_ptr<Tool> Assemble;
+ mutable std::unique_ptr<Tool> Link;
+ Tool *getClang() const;
+ Tool *getAssemble() const;
+ Tool *getLink() const;
+ Tool *getClangAs() const;
+
+ mutable std::unique_ptr<SanitizerArgs> SanitizerArguments;
+
+protected:
+ MultilibSet Multilibs;
+ const char *DefaultLinker = "ld";
+
+ ToolChain(const Driver &D, const llvm::Triple &T,
+ const llvm::opt::ArgList &Args);
+
+ virtual Tool *buildAssembler() const;
+ virtual Tool *buildLinker() const;
+ virtual Tool *getTool(Action::ActionClass AC) const;
+
+ /// \name Utilities for implementing subclasses.
+ ///@{
+ static void addSystemInclude(const llvm::opt::ArgList &DriverArgs,
+ llvm::opt::ArgStringList &CC1Args,
+ const Twine &Path);
+ static void addExternCSystemInclude(const llvm::opt::ArgList &DriverArgs,
+ llvm::opt::ArgStringList &CC1Args,
+ const Twine &Path);
+ static void
+ addExternCSystemIncludeIfExists(const llvm::opt::ArgList &DriverArgs,
+ llvm::opt::ArgStringList &CC1Args,
+ const Twine &Path);
+ static void addSystemIncludes(const llvm::opt::ArgList &DriverArgs,
+ llvm::opt::ArgStringList &CC1Args,
+ ArrayRef<StringRef> Paths);
+ ///@}
+
+public:
+ virtual ~ToolChain();
+
+ // Accessors
+
+ const Driver &getDriver() const { return D; }
+ vfs::FileSystem &getVFS() const;
+ const llvm::Triple &getTriple() const { return Triple; }
+
+ llvm::Triple::ArchType getArch() const { return Triple.getArch(); }
+ StringRef getArchName() const { return Triple.getArchName(); }
+ StringRef getPlatform() const { return Triple.getVendorName(); }
+ StringRef getOS() const { return Triple.getOSName(); }
+
+ /// \brief Provide the default architecture name (as expected by -arch) for
+ /// this toolchain. Note t
+ StringRef getDefaultUniversalArchName() const;
+
+ 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; }
+
+ const MultilibSet &getMultilibs() const { return Multilibs; }
+
+ const SanitizerArgs& getSanitizerArgs() const;
+
+ // Returns the Arg * that explicitly turned on/off rtti, or nullptr.
+ const llvm::opt::Arg *getRTTIArg() const { return CachedRTTIArg; }
+
+ // Returns the RTTIMode for the toolchain with the current arguments.
+ RTTIMode getRTTIMode() const { return CachedRTTIMode; }
+
+ /// \brief Return any implicit target and/or mode flag for an invocation of
+ /// the compiler driver as `ProgName`.
+ ///
+ /// For example, when called with i686-linux-android-g++, the first element
+ /// of the return value will be set to `"i686-linux-android"` and the second
+ /// will be set to "--driver-mode=g++"`.
+ ///
+ /// \pre `llvm::InitializeAllTargets()` has been called.
+ /// \param ProgName The name the Clang driver was invoked with (from,
+ /// e.g., argv[0])
+ /// \return A pair of (`target`, `mode-flag`), where one or both may be empty.
+ static std::pair<std::string, std::string>
+ getTargetAndModeFromProgramName(StringRef ProgName);
+
+ // 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 llvm::opt::DerivedArgList *
+ TranslateArgs(const llvm::opt::DerivedArgList &Args,
+ const char *BoundArch) const {
+ return nullptr;
+ }
+
+ /// Choose a tool to use to handle the action \p JA.
+ ///
+ /// This can be overridden when a particular ToolChain needs to use
+ /// a compiler other than Clang.
+ virtual Tool *SelectTool(const JobAction &JA) const;
+
+ // Helper methods
+
+ std::string GetFilePath(const char *Name) const;
+ std::string GetProgramPath(const char *Name) const;
+
+ /// Returns the linker path, respecting the -fuse-ld= argument to determine
+ /// the linker suffix or name.
+ std::string GetLinkerPath() const;
+
+ /// \brief Dispatch to the specific toolchain for verbose printing.
+ ///
+ /// This is used when handling the verbose option to print detailed,
+ /// toolchain-specific information useful for understanding the behavior of
+ /// the driver on a specific platform.
+ virtual void printVerboseInfo(raw_ostream &OS) const {}
+
+ // Platform defaults information
+
+ /// \brief Returns true if the toolchain is targeting a non-native
+ /// architecture.
+ virtual bool isCrossCompiling() const;
+
+ /// 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; }
+
+ /// \brief Check if the toolchain should use the integrated assembler.
+ bool useIntegratedAs() const;
+
+ /// IsMathErrnoDefault - Does this tool chain use -fmath-errno by default.
+ virtual bool IsMathErrnoDefault() const { return true; }
+
+ /// IsEncodeExtendedBlockSignatureDefault - Does this tool chain enable
+ /// -fencode-extended-block-signature by default.
+ virtual bool IsEncodeExtendedBlockSignatureDefault() const { return false; }
+
+ /// IsObjCNonFragileABIDefault - Does this tool chain set
+ /// -fobjc-nonfragile-abi by default.
+ virtual bool IsObjCNonFragileABIDefault() 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=strong, 3=all).
+ virtual unsigned GetDefaultStackProtectorLevel(bool KernelOrKext) const {
+ return 0;
+ }
+
+ /// GetDefaultRuntimeLibType - Get the default runtime library variant to use.
+ virtual RuntimeLibType GetDefaultRuntimeLibType() const {
+ return ToolChain::RLT_Libgcc;
+ }
+
+ virtual std::string getCompilerRT(const llvm::opt::ArgList &Args,
+ StringRef Component,
+ bool Shared = false) const;
+
+ const char *getCompilerRTArgString(const llvm::opt::ArgList &Args,
+ StringRef Component,
+ bool Shared = false) const;
+ /// needsProfileRT - returns true if instrumentation profile is on.
+ static bool needsProfileRT(const llvm::opt::ArgList &Args);
+
+ /// IsUnwindTablesDefault - Does this tool chain use -funwind-tables
+ /// by default.
+ virtual bool IsUnwindTablesDefault() const;
+
+ /// \brief Test whether this toolchain defaults to PIC.
+ virtual bool isPICDefault() const = 0;
+
+ /// \brief Test whether this toolchain defaults to PIE.
+ virtual bool isPIEDefault() const = 0;
+
+ /// \brief Tests whether this toolchain forces its default for PIC, PIE or
+ /// non-PIC. If this returns true, any PIC related flags should be ignored
+ /// and instead the results of \c isPICDefault() and \c isPIEDefault() are
+ /// used exclusively.
+ virtual bool isPICDefaultForced() const = 0;
+
+ /// SupportsProfiling - Does this tool chain support -pg.
+ virtual bool SupportsProfiling() const { return true; }
+
+ /// Does this tool chain support Objective-C garbage collection.
+ virtual bool SupportsObjCGC() const { return true; }
+
+ /// Complain if this tool chain doesn't support Objective-C ARC.
+ virtual void CheckObjCARC() const {}
+
+ /// UseDwarfDebugFlags - Embed the compile options to clang into the Dwarf
+ /// compile unit information.
+ virtual bool UseDwarfDebugFlags() const { return false; }
+
+ // Return the DWARF version to emit, in the absence of arguments
+ // to the contrary.
+ virtual unsigned GetDefaultDwarfVersion() const { return 4; }
+
+ // True if the driver should assume "-fstandalone-debug"
+ // in the absence of an option specifying otherwise,
+ // provided that debugging was requested in the first place.
+ // i.e. a value of 'true' does not imply that debugging is wanted.
+ virtual bool GetDefaultStandaloneDebug() const { return false; }
+
+ // Return the default debugger "tuning."
+ virtual llvm::DebuggerKind getDefaultDebuggerTuning() const {
+ return llvm::DebuggerKind::GDB;
+ }
+
+ /// UseSjLjExceptions - Does this tool chain use SjLj exceptions.
+ virtual bool UseSjLjExceptions(const llvm::opt::ArgList &Args) const {
+ return false;
+ }
+
+ /// getThreadModel() - Which thread model does this target use?
+ virtual std::string getThreadModel() const { return "posix"; }
+
+ /// isThreadModelSupported() - Does this target support a thread model?
+ virtual bool isThreadModelSupported(const StringRef Model) const;
+
+ /// ComputeLLVMTriple - Return the LLVM target triple to use, after taking
+ /// command line arguments into account.
+ virtual std::string
+ ComputeLLVMTriple(const llvm::opt::ArgList &Args,
+ types::ID InputType = types::TY_INVALID) 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 llvm::opt::ArgList &Args,
+ types::ID InputType = types::TY_INVALID) const;
+
+ /// getDefaultObjCRuntime - Return the default Objective-C runtime
+ /// for this platform.
+ ///
+ /// FIXME: this really belongs on some sort of DeploymentTarget abstraction
+ virtual ObjCRuntime getDefaultObjCRuntime(bool isNonFragile) const;
+
+ /// hasBlocksRuntime - Given that the user is compiling with
+ /// -fblocks, does this tool chain guarantee the existence of a
+ /// blocks runtime?
+ ///
+ /// FIXME: this really belongs on some sort of DeploymentTarget abstraction
+ virtual bool hasBlocksRuntime() const { return true; }
+
+ /// \brief Add the clang cc1 arguments for system include paths.
+ ///
+ /// This routine is responsible for adding the necessary cc1 arguments to
+ /// include headers from standard system header directories.
+ virtual void
+ AddClangSystemIncludeArgs(const llvm::opt::ArgList &DriverArgs,
+ llvm::opt::ArgStringList &CC1Args) const;
+
+ /// \brief Add options that need to be passed to cc1 for this target.
+ virtual void addClangTargetOptions(const llvm::opt::ArgList &DriverArgs,
+ llvm::opt::ArgStringList &CC1Args) const;
+
+ /// \brief Add warning options that need to be passed to cc1 for this target.
+ virtual void addClangWarningOptions(llvm::opt::ArgStringList &CC1Args) const;
+
+ // GetRuntimeLibType - Determine the runtime library type to use with the
+ // given compilation arguments.
+ virtual RuntimeLibType
+ GetRuntimeLibType(const llvm::opt::ArgList &Args) const;
+
+ // GetCXXStdlibType - Determine the C++ standard library type to use with the
+ // given compilation arguments.
+ virtual CXXStdlibType GetCXXStdlibType(const llvm::opt::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 llvm::opt::ArgList &DriverArgs,
+ llvm::opt::ArgStringList &CC1Args) const;
+
+ /// AddCXXStdlibLibArgs - Add the system specific linker arguments to use
+ /// for the given C++ standard library type.
+ virtual void AddCXXStdlibLibArgs(const llvm::opt::ArgList &Args,
+ llvm::opt::ArgStringList &CmdArgs) const;
+
+ /// AddFilePathLibArgs - Add each thing in getFilePaths() as a "-L" option.
+ void AddFilePathLibArgs(const llvm::opt::ArgList &Args,
+ llvm::opt::ArgStringList &CmdArgs) const;
+
+ /// AddCCKextLibArgs - Add the system specific linker arguments to use
+ /// for kernel extensions (Darwin-specific).
+ virtual void AddCCKextLibArgs(const llvm::opt::ArgList &Args,
+ llvm::opt::ArgStringList &CmdArgs) const;
+
+ /// AddFastMathRuntimeIfAvailable - If a runtime library exists that sets
+ /// global flags for unsafe floating point math, add it and return true.
+ ///
+ /// This checks for presence of the -Ofast, -ffast-math or -funsafe-math flags.
+ virtual bool AddFastMathRuntimeIfAvailable(
+ const llvm::opt::ArgList &Args, llvm::opt::ArgStringList &CmdArgs) const;
+ /// addProfileRTLibs - When -fprofile-instr-profile is specified, try to pass
+ /// a suitable profile runtime library to the linker.
+ virtual void addProfileRTLibs(const llvm::opt::ArgList &Args,
+ llvm::opt::ArgStringList &CmdArgs) const;
+
+ /// \brief Add arguments to use system-specific CUDA includes.
+ virtual void AddCudaIncludeArgs(const llvm::opt::ArgList &DriverArgs,
+ llvm::opt::ArgStringList &CC1Args) const;
+
+ /// \brief Return sanitizers which are available in this toolchain.
+ virtual SanitizerMask getSupportedSanitizers() 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..d1b6915
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Driver/Types.def
@@ -0,0 +1,96 @@
+//===--- 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 containing 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, "c", "u")
+TYPE("cl", CL, PP_C, "cl", "u")
+TYPE("cuda-cpp-output", PP_CUDA, INVALID, "cui", "u")
+TYPE("cuda", CUDA, PP_CUDA, "cu", "u")
+TYPE("cuda", CUDA_DEVICE, PP_CUDA, "cu", "")
+TYPE("objective-c-cpp-output", PP_ObjC, INVALID, "mi", "u")
+TYPE("objc-cpp-output", PP_ObjC_Alias, INVALID, "mi", "u")
+TYPE("objective-c", ObjC, PP_ObjC, "m", "u")
+TYPE("c++-cpp-output", PP_CXX, INVALID, "ii", "u")
+TYPE("c++", CXX, PP_CXX, "cpp", "u")
+TYPE("objective-c++-cpp-output", PP_ObjCXX, INVALID, "mii", "u")
+TYPE("objc++-cpp-output", PP_ObjCXX_Alias, INVALID, "mii", "u")
+TYPE("objective-c++", ObjCXX, PP_ObjCXX, "mm", "u")
+
+// C family input files to precompile.
+TYPE("c-header-cpp-output", PP_CHeader, INVALID, "i", "p")
+TYPE("c-header", CHeader, PP_CHeader, "h", "pu")
+TYPE("cl-header", CLHeader, PP_CHeader, "h", "pu")
+TYPE("objective-c-header-cpp-output", PP_ObjCHeader, INVALID, "mi", "p")
+TYPE("objective-c-header", ObjCHeader, PP_ObjCHeader, "h", "pu")
+TYPE("c++-header-cpp-output", PP_CXXHeader, INVALID, "ii", "p")
+TYPE("c++-header", CXXHeader, PP_CXXHeader, "hh", "pu")
+TYPE("objective-c++-header-cpp-output", PP_ObjCXXHeader, INVALID, "mii", "p")
+TYPE("objective-c++-header", ObjCXXHeader, PP_ObjCXXHeader, "h", "pu")
+
+// Other languages.
+TYPE("ada", Ada, INVALID, nullptr, "u")
+TYPE("assembler", PP_Asm, INVALID, "s", "au")
+TYPE("assembler-with-cpp", Asm, PP_Asm, "S", "au")
+TYPE("f95", PP_Fortran, INVALID, nullptr, "u")
+TYPE("f95-cpp-input", Fortran, PP_Fortran, nullptr, "u")
+TYPE("java", Java, INVALID, nullptr, "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("pcm", ModuleFile, INVALID, "pcm", "u")
+TYPE("plist", Plist, INVALID, "plist", "")
+TYPE("rewritten-objc", RewrittenObjC,INVALID, "cpp", "")
+TYPE("rewritten-legacy-objc", RewrittenLegacyObjC,INVALID, "cpp", "")
+TYPE("remap", Remap, INVALID, "remap", "")
+TYPE("precompiled-header", PCH, INVALID, "gch", "A")
+TYPE("object", Object, INVALID, "o", "")
+TYPE("treelang", Treelang, INVALID, nullptr, "u")
+TYPE("image", Image, INVALID, "out", "")
+TYPE("dSYM", dSYM, INVALID, "dSYM", "A")
+TYPE("dependencies", Dependencies, INVALID, "d", "")
+TYPE("none", Nothing, INVALID, nullptr, "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..22122c7
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Driver/Types.h
@@ -0,0 +1,97 @@
+//===--- 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 LLVM_CLANG_DRIVER_TYPES_H
+#define LLVM_CLANG_DRIVER_TYPES_H
+
+#include "clang/Driver/Phases.h"
+#include "llvm/ADT/SmallVector.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 \p 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, bool CLMode = false);
+
+ /// 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);
+
+ /// isCXX - Is this a "C++" input (C++ and Obj-C++ sources and headers).
+ bool isCXX(ID Id);
+
+ /// Is this LLVM IR.
+ bool isLLVMIR(ID Id);
+
+ /// isCuda - Is this a CUDA input.
+ bool isCuda(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 \p Ext.
+ ID lookupTypeForExtension(const char *Ext);
+
+ /// lookupTypeForTypSpecifier - Lookup the type to use for a user
+ /// specified type name.
+ ID lookupTypeForTypeSpecifier(const char *Name);
+
+ /// getCompilationPhases - Get the list of compilation phases ('Phases') to be
+ /// done for type 'Id'.
+ void getCompilationPhases(
+ ID Id,
+ llvm::SmallVectorImpl<phases::ID> &Phases);
+
+ /// 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..07495a1
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Driver/Util.h
@@ -0,0 +1,32 @@
+//===--- 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 LLVM_CLANG_DRIVER_UTIL_H
+#define LLVM_CLANG_DRIVER_UTIL_H
+
+#include "clang/Basic/LLVM.h"
+#include "llvm/ADT/DenseMap.h"
+
+namespace clang {
+class DiagnosticsEngine;
+
+namespace driver {
+ class Action;
+ class JobAction;
+
+ /// ArgStringMap - Type used to map a JobAction to its result file.
+ typedef llvm::DenseMap<const JobAction*, const char*> ArgStringMap;
+
+ /// ActionList - Type used for lists of actions.
+ typedef SmallVector<Action*, 3> ActionList;
+
+} // end namespace driver
+} // end namespace clang
+
+#endif
diff --git a/contrib/llvm/tools/clang/include/clang/Edit/Commit.h b/contrib/llvm/tools/clang/include/clang/Edit/Commit.h
new file mode 100644
index 0000000..ac4bb47
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Edit/Commit.h
@@ -0,0 +1,143 @@
+//===----- Commit.h - A unit of edits ---------------------------*- 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_EDIT_COMMIT_H
+#define LLVM_CLANG_EDIT_COMMIT_H
+
+#include "clang/Edit/FileOffset.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/Support/Allocator.h"
+
+namespace clang {
+ class LangOptions;
+ class PPConditionalDirectiveRecord;
+
+namespace edit {
+ class EditedSource;
+
+class Commit {
+public:
+ enum EditKind {
+ Act_Insert,
+ Act_InsertFromRange,
+ Act_Remove
+ };
+
+ struct Edit {
+ EditKind Kind;
+ StringRef Text;
+ SourceLocation OrigLoc;
+ FileOffset Offset;
+ FileOffset InsertFromRangeOffs;
+ unsigned Length;
+ bool BeforePrev;
+
+ SourceLocation getFileLocation(SourceManager &SM) const;
+ CharSourceRange getFileRange(SourceManager &SM) const;
+ CharSourceRange getInsertFromRange(SourceManager &SM) const;
+ };
+
+private:
+ const SourceManager &SourceMgr;
+ const LangOptions &LangOpts;
+ const PPConditionalDirectiveRecord *PPRec;
+ EditedSource *Editor;
+
+ bool IsCommitable;
+ SmallVector<Edit, 8> CachedEdits;
+
+ llvm::BumpPtrAllocator StrAlloc;
+
+public:
+ explicit Commit(EditedSource &Editor);
+ Commit(const SourceManager &SM, const LangOptions &LangOpts,
+ const PPConditionalDirectiveRecord *PPRec = nullptr)
+ : SourceMgr(SM), LangOpts(LangOpts), PPRec(PPRec), Editor(nullptr),
+ IsCommitable(true) { }
+
+ bool isCommitable() const { return IsCommitable; }
+
+ bool insert(SourceLocation loc, StringRef text, bool afterToken = false,
+ bool beforePreviousInsertions = false);
+ bool insertAfterToken(SourceLocation loc, StringRef text,
+ bool beforePreviousInsertions = false) {
+ return insert(loc, text, /*afterToken=*/true, beforePreviousInsertions);
+ }
+ bool insertBefore(SourceLocation loc, StringRef text) {
+ return insert(loc, text, /*afterToken=*/false,
+ /*beforePreviousInsertions=*/true);
+ }
+ bool insertFromRange(SourceLocation loc, CharSourceRange range,
+ bool afterToken = false,
+ bool beforePreviousInsertions = false);
+ bool insertWrap(StringRef before, CharSourceRange range, StringRef after);
+
+ bool remove(CharSourceRange range);
+
+ bool replace(CharSourceRange range, StringRef text);
+ bool replaceWithInner(CharSourceRange range, CharSourceRange innerRange);
+ bool replaceText(SourceLocation loc, StringRef text,
+ StringRef replacementText);
+
+ bool insertFromRange(SourceLocation loc, SourceRange TokenRange,
+ bool afterToken = false,
+ bool beforePreviousInsertions = false) {
+ return insertFromRange(loc, CharSourceRange::getTokenRange(TokenRange),
+ afterToken, beforePreviousInsertions);
+ }
+ bool insertWrap(StringRef before, SourceRange TokenRange, StringRef after) {
+ return insertWrap(before, CharSourceRange::getTokenRange(TokenRange), after);
+ }
+ bool remove(SourceRange TokenRange) {
+ return remove(CharSourceRange::getTokenRange(TokenRange));
+ }
+ bool replace(SourceRange TokenRange, StringRef text) {
+ return replace(CharSourceRange::getTokenRange(TokenRange), text);
+ }
+ bool replaceWithInner(SourceRange TokenRange, SourceRange TokenInnerRange) {
+ return replaceWithInner(CharSourceRange::getTokenRange(TokenRange),
+ CharSourceRange::getTokenRange(TokenInnerRange));
+ }
+
+ typedef SmallVectorImpl<Edit>::const_iterator edit_iterator;
+ edit_iterator edit_begin() const { return CachedEdits.begin(); }
+ edit_iterator edit_end() const { return CachedEdits.end(); }
+
+private:
+ void addInsert(SourceLocation OrigLoc,
+ FileOffset Offs, StringRef text, bool beforePreviousInsertions);
+ void addInsertFromRange(SourceLocation OrigLoc, FileOffset Offs,
+ FileOffset RangeOffs, unsigned RangeLen,
+ bool beforePreviousInsertions);
+ void addRemove(SourceLocation OrigLoc, FileOffset Offs, unsigned Len);
+
+ bool canInsert(SourceLocation loc, FileOffset &Offset);
+ bool canInsertAfterToken(SourceLocation loc, FileOffset &Offset,
+ SourceLocation &AfterLoc);
+ bool canInsertInOffset(SourceLocation OrigLoc, FileOffset Offs);
+ bool canRemoveRange(CharSourceRange range, FileOffset &Offs, unsigned &Len);
+ bool canReplaceText(SourceLocation loc, StringRef text,
+ FileOffset &Offs, unsigned &Len);
+
+ void commitInsert(FileOffset offset, StringRef text,
+ bool beforePreviousInsertions);
+ void commitRemove(FileOffset offset, unsigned length);
+
+ bool isAtStartOfMacroExpansion(SourceLocation loc,
+ SourceLocation *MacroBegin = nullptr) const;
+ bool isAtEndOfMacroExpansion(SourceLocation loc,
+ SourceLocation *MacroEnd = nullptr) const;
+};
+
+}
+
+} // end namespace clang
+
+#endif
diff --git a/contrib/llvm/tools/clang/include/clang/Edit/EditedSource.h b/contrib/llvm/tools/clang/include/clang/Edit/EditedSource.h
new file mode 100644
index 0000000..b6ec8b8
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Edit/EditedSource.h
@@ -0,0 +1,97 @@
+//===----- EditedSource.h - Collection of source edits ----------*- 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_EDIT_EDITEDSOURCE_H
+#define LLVM_CLANG_EDIT_EDITEDSOURCE_H
+
+#include "clang/Basic/IdentifierTable.h"
+#include "clang/Edit/FileOffset.h"
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/ADT/TinyPtrVector.h"
+#include "llvm/Support/Allocator.h"
+#include <map>
+
+namespace clang {
+ class LangOptions;
+ class PPConditionalDirectiveRecord;
+
+namespace edit {
+ class Commit;
+ class EditsReceiver;
+
+class EditedSource {
+ const SourceManager &SourceMgr;
+ const LangOptions &LangOpts;
+ const PPConditionalDirectiveRecord *PPRec;
+
+ struct FileEdit {
+ StringRef Text;
+ unsigned RemoveLen;
+
+ FileEdit() : RemoveLen(0) {}
+ };
+
+ typedef std::map<FileOffset, FileEdit> FileEditsTy;
+ FileEditsTy FileEdits;
+
+ llvm::DenseMap<unsigned, llvm::TinyPtrVector<IdentifierInfo*>>
+ ExpansionToArgMap;
+ SmallVector<std::pair<SourceLocation, IdentifierInfo*>, 2>
+ CurrCommitMacroArgExps;
+
+ IdentifierTable IdentTable;
+ llvm::BumpPtrAllocator StrAlloc;
+
+public:
+ EditedSource(const SourceManager &SM, const LangOptions &LangOpts,
+ const PPConditionalDirectiveRecord *PPRec = nullptr)
+ : SourceMgr(SM), LangOpts(LangOpts), PPRec(PPRec), IdentTable(LangOpts),
+ StrAlloc() { }
+
+ const SourceManager &getSourceManager() const { return SourceMgr; }
+ const LangOptions &getLangOpts() const { return LangOpts; }
+ const PPConditionalDirectiveRecord *getPPCondDirectiveRecord() const {
+ return PPRec;
+ }
+
+ bool canInsertInOffset(SourceLocation OrigLoc, FileOffset Offs);
+
+ bool commit(const Commit &commit);
+
+ void applyRewrites(EditsReceiver &receiver);
+ void clearRewrites();
+
+ StringRef copyString(StringRef str) { return str.copy(StrAlloc); }
+ StringRef copyString(const Twine &twine);
+
+private:
+ bool commitInsert(SourceLocation OrigLoc, FileOffset Offs, StringRef text,
+ bool beforePreviousInsertions);
+ bool commitInsertFromRange(SourceLocation OrigLoc, FileOffset Offs,
+ FileOffset InsertFromRangeOffs, unsigned Len,
+ bool beforePreviousInsertions);
+ void commitRemove(SourceLocation OrigLoc, FileOffset BeginOffs, unsigned Len);
+
+ StringRef getSourceText(FileOffset BeginOffs, FileOffset EndOffs,
+ bool &Invalid);
+ FileEditsTy::iterator getActionForOffset(FileOffset Offs);
+ void deconstructMacroArgLoc(SourceLocation Loc,
+ SourceLocation &ExpansionLoc,
+ IdentifierInfo *&II);
+
+ void startingCommit();
+ void finishedCommit();
+};
+
+}
+
+} // end namespace clang
+
+#endif
diff --git a/contrib/llvm/tools/clang/include/clang/Edit/EditsReceiver.h b/contrib/llvm/tools/clang/include/clang/Edit/EditsReceiver.h
new file mode 100644
index 0000000..600ac28
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Edit/EditsReceiver.h
@@ -0,0 +1,35 @@
+//===----- EditedSource.h - Collection of source edits ----------*- 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_EDIT_EDITSRECEIVER_H
+#define LLVM_CLANG_EDIT_EDITSRECEIVER_H
+
+#include "clang/Basic/LLVM.h"
+
+namespace clang {
+ class SourceLocation;
+ class CharSourceRange;
+
+namespace edit {
+
+class EditsReceiver {
+public:
+ virtual ~EditsReceiver() { }
+
+ virtual void insert(SourceLocation loc, StringRef text) = 0;
+ virtual void replace(CharSourceRange range, StringRef text) = 0;
+ /// \brief By default it calls replace with an empty string.
+ virtual void remove(CharSourceRange range);
+};
+
+}
+
+} // end namespace clang
+
+#endif
diff --git a/contrib/llvm/tools/clang/include/clang/Edit/FileOffset.h b/contrib/llvm/tools/clang/include/clang/Edit/FileOffset.h
new file mode 100644
index 0000000..0c1e72b
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Edit/FileOffset.h
@@ -0,0 +1,61 @@
+//===----- FileOffset.h - Offset in a file ----------------------*- 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_EDIT_FILEOFFSET_H
+#define LLVM_CLANG_EDIT_FILEOFFSET_H
+
+#include "clang/Basic/SourceLocation.h"
+
+namespace clang {
+
+namespace edit {
+
+class FileOffset {
+ FileID FID;
+ unsigned Offs;
+public:
+ FileOffset() : Offs(0) { }
+ FileOffset(FileID fid, unsigned offs) : FID(fid), Offs(offs) { }
+
+ bool isInvalid() const { return FID.isInvalid(); }
+
+ FileID getFID() const { return FID; }
+ unsigned getOffset() const { return Offs; }
+
+ FileOffset getWithOffset(unsigned offset) const {
+ FileOffset NewOffs = *this;
+ NewOffs.Offs += offset;
+ return NewOffs;
+ }
+
+ friend bool operator==(FileOffset LHS, FileOffset RHS) {
+ return LHS.FID == RHS.FID && LHS.Offs == RHS.Offs;
+ }
+ friend bool operator!=(FileOffset LHS, FileOffset RHS) {
+ return !(LHS == RHS);
+ }
+ friend bool operator<(FileOffset LHS, FileOffset RHS) {
+ return std::tie(LHS.FID, LHS.Offs) < std::tie(RHS.FID, RHS.Offs);
+ }
+ friend bool operator>(FileOffset LHS, FileOffset RHS) {
+ return RHS < LHS;
+ }
+ friend bool operator>=(FileOffset LHS, FileOffset RHS) {
+ return !(LHS < RHS);
+ }
+ friend bool operator<=(FileOffset LHS, FileOffset RHS) {
+ return !(RHS < LHS);
+ }
+};
+
+}
+
+} // end namespace clang
+
+#endif
diff --git a/contrib/llvm/tools/clang/include/clang/Edit/Rewriters.h b/contrib/llvm/tools/clang/include/clang/Edit/Rewriters.h
new file mode 100644
index 0000000..5e3425f
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Edit/Rewriters.h
@@ -0,0 +1,41 @@
+//===--- Rewriters.h - Rewritings ---------------------------*- 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_EDIT_REWRITERS_H
+#define LLVM_CLANG_EDIT_REWRITERS_H
+#include "llvm/ADT/SmallVector.h"
+
+namespace clang {
+ class ObjCMessageExpr;
+ class ObjCMethodDecl;
+ class ObjCInterfaceDecl;
+ class ObjCProtocolDecl;
+ class NSAPI;
+ class EnumDecl;
+ class TypedefDecl;
+ class ParentMap;
+
+namespace edit {
+ class Commit;
+
+bool rewriteObjCRedundantCallWithLiteral(const ObjCMessageExpr *Msg,
+ const NSAPI &NS, Commit &commit);
+
+bool rewriteToObjCLiteralSyntax(const ObjCMessageExpr *Msg,
+ const NSAPI &NS, Commit &commit,
+ const ParentMap *PMap);
+
+bool rewriteToObjCSubscriptSyntax(const ObjCMessageExpr *Msg,
+ const NSAPI &NS, Commit &commit);
+
+}
+
+} // end namespace clang
+
+#endif
diff --git a/contrib/llvm/tools/clang/include/clang/Format/Format.h b/contrib/llvm/tools/clang/include/clang/Format/Format.h
new file mode 100644
index 0000000..6d051e0
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Format/Format.h
@@ -0,0 +1,792 @@
+//===--- Format.h - Format C++ code -----------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+///
+/// \file
+/// Various functions to configurably format source code.
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_FORMAT_FORMAT_H
+#define LLVM_CLANG_FORMAT_FORMAT_H
+
+#include "clang/Basic/LangOptions.h"
+#include "clang/Tooling/Core/Replacement.h"
+#include "llvm/ADT/ArrayRef.h"
+#include <system_error>
+
+namespace clang {
+
+class Lexer;
+class SourceManager;
+class DiagnosticConsumer;
+
+namespace format {
+
+enum class ParseError { Success = 0, Error, Unsuitable };
+class ParseErrorCategory final : public std::error_category {
+public:
+ const char *name() const LLVM_NOEXCEPT override;
+ std::string message(int EV) const override;
+};
+const std::error_category &getParseCategory();
+std::error_code make_error_code(ParseError e);
+
+/// \brief The \c FormatStyle is used to configure the formatting to follow
+/// specific guidelines.
+struct FormatStyle {
+ /// \brief The extra indent or outdent of access modifiers, e.g. \c public:.
+ int AccessModifierOffset;
+
+ /// \brief Different styles for aligning after open brackets.
+ enum BracketAlignmentStyle {
+ /// \brief Align parameters on the open bracket, e.g.:
+ /// \code
+ /// someLongFunction(argument1,
+ /// argument2);
+ /// \endcode
+ BAS_Align,
+ /// \brief Don't align, instead use \c ContinuationIndentWidth, e.g.:
+ /// \code
+ /// someLongFunction(argument1,
+ /// argument2);
+ /// \endcode
+ BAS_DontAlign,
+ /// \brief Always break after an open bracket, if the parameters don't fit
+ /// on a single line, e.g.:
+ /// \code
+ /// someLongFunction(
+ /// argument1, argument2);
+ /// \endcode
+ BAS_AlwaysBreak,
+ };
+
+ /// \brief If \c true, horizontally aligns arguments after an open bracket.
+ ///
+ /// This applies to round brackets (parentheses), angle brackets and square
+ /// brackets.
+ BracketAlignmentStyle AlignAfterOpenBracket;
+
+ /// \brief If \c true, aligns consecutive assignments.
+ ///
+ /// This will align the assignment operators of consecutive lines. This
+ /// will result in formattings like
+ /// \code
+ /// int aaaa = 12;
+ /// int b = 23;
+ /// int ccc = 23;
+ /// \endcode
+ bool AlignConsecutiveAssignments;
+
+ /// \brief If \c true, aligns consecutive declarations.
+ ///
+ /// This will align the declaration names of consecutive lines. This
+ /// will result in formattings like
+ /// \code
+ /// int aaaa = 12;
+ /// float b = 23;
+ /// std::string ccc = 23;
+ /// \endcode
+ bool AlignConsecutiveDeclarations;
+
+ /// \brief If \c true, aligns escaped newlines as far left as possible.
+ /// Otherwise puts them into the right-most column.
+ bool AlignEscapedNewlinesLeft;
+
+ /// \brief If \c true, horizontally align operands of binary and ternary
+ /// expressions.
+ ///
+ /// Specifically, this aligns operands of a single expression that needs to be
+ /// split over multiple lines, e.g.:
+ /// \code
+ /// int aaa = bbbbbbbbbbbbbbb +
+ /// ccccccccccccccc;
+ /// \endcode
+ bool AlignOperands;
+
+ /// \brief If \c true, aligns trailing comments.
+ bool AlignTrailingComments;
+
+ /// \brief Allow putting all parameters of a function declaration onto
+ /// the next line even if \c BinPackParameters is \c false.
+ bool AllowAllParametersOfDeclarationOnNextLine;
+
+ /// \brief Allows contracting simple braced statements to a single line.
+ ///
+ /// E.g., this allows <tt>if (a) { return; }</tt> to be put on a single line.
+ bool AllowShortBlocksOnASingleLine;
+
+ /// \brief If \c true, short case labels will be contracted to a single line.
+ bool AllowShortCaseLabelsOnASingleLine;
+
+ /// \brief Different styles for merging short functions containing at most one
+ /// statement.
+ enum ShortFunctionStyle {
+ /// \brief Never merge functions into a single line.
+ SFS_None,
+ /// \brief Only merge empty functions.
+ SFS_Empty,
+ /// \brief Only merge functions defined inside a class. Implies "empty".
+ SFS_Inline,
+ /// \brief Merge all functions fitting on a single line.
+ SFS_All,
+ };
+
+ /// \brief Dependent on the value, <tt>int f() { return 0; }</tt> can be put
+ /// on a single line.
+ ShortFunctionStyle AllowShortFunctionsOnASingleLine;
+
+ /// \brief If \c true, <tt>if (a) return;</tt> can be put on a single
+ /// line.
+ bool AllowShortIfStatementsOnASingleLine;
+
+ /// \brief If \c true, <tt>while (true) continue;</tt> can be put on a
+ /// single line.
+ bool AllowShortLoopsOnASingleLine;
+
+ /// \brief Different ways to break after the function definition return type.
+ enum DefinitionReturnTypeBreakingStyle {
+ /// Break after return type automatically.
+ /// \c PenaltyReturnTypeOnItsOwnLine is taken into account.
+ DRTBS_None,
+ /// Always break after the return type.
+ DRTBS_All,
+ /// Always break after the return types of top-level functions.
+ DRTBS_TopLevel,
+ };
+
+ /// \brief Different ways to break after the function definition or
+ /// declaration return type.
+ enum ReturnTypeBreakingStyle {
+ /// Break after return type automatically.
+ /// \c PenaltyReturnTypeOnItsOwnLine is taken into account.
+ RTBS_None,
+ /// Always break after the return type.
+ RTBS_All,
+ /// Always break after the return types of top-level functions.
+ RTBS_TopLevel,
+ /// Always break after the return type of function definitions.
+ RTBS_AllDefinitions,
+ /// Always break after the return type of top-level definitions.
+ RTBS_TopLevelDefinitions,
+ };
+
+ /// \brief The function definition return type breaking style to use. This
+ /// option is deprecated and is retained for backwards compatibility.
+ DefinitionReturnTypeBreakingStyle AlwaysBreakAfterDefinitionReturnType;
+
+ /// \brief The function declaration return type breaking style to use.
+ ReturnTypeBreakingStyle AlwaysBreakAfterReturnType;
+
+ /// \brief If \c true, always break before multiline string literals.
+ ///
+ /// This flag is mean to make cases where there are multiple multiline strings
+ /// in a file look more consistent. Thus, it will only take effect if wrapping
+ /// the string at that point leads to it being indented
+ /// \c ContinuationIndentWidth spaces from the start of the line.
+ bool AlwaysBreakBeforeMultilineStrings;
+
+ /// \brief If \c true, always break after the <tt>template<...></tt> of a
+ /// template declaration.
+ bool AlwaysBreakTemplateDeclarations;
+
+ /// \brief If \c false, a function call's arguments will either be all on the
+ /// same line or will have one line each.
+ bool BinPackArguments;
+
+ /// \brief If \c false, a function declaration's or function definition's
+ /// parameters will either all be on the same line or will have one line each.
+ bool BinPackParameters;
+
+ /// \brief The style of breaking before or after binary operators.
+ enum BinaryOperatorStyle {
+ /// Break after operators.
+ BOS_None,
+ /// Break before operators that aren't assignments.
+ BOS_NonAssignment,
+ /// Break before operators.
+ BOS_All,
+ };
+
+ /// \brief The way to wrap binary operators.
+ BinaryOperatorStyle BreakBeforeBinaryOperators;
+
+ /// \brief Different ways to attach braces to their surrounding context.
+ enum BraceBreakingStyle {
+ /// Always attach braces to surrounding context.
+ BS_Attach,
+ /// Like \c Attach, but break before braces on function, namespace and
+ /// class definitions.
+ BS_Linux,
+ /// Like ``Attach``, but break before braces on enum, function, and record
+ /// definitions.
+ BS_Mozilla,
+ /// Like \c Attach, but break before function definitions, 'catch', and 'else'.
+ BS_Stroustrup,
+ /// Always break before braces.
+ BS_Allman,
+ /// Always break before braces and add an extra level of indentation to
+ /// braces of control statements, not to those of class, function
+ /// or other definitions.
+ BS_GNU,
+ /// Like ``Attach``, but break before functions.
+ BS_WebKit,
+ /// Configure each individual brace in \c BraceWrapping.
+ BS_Custom
+ };
+
+ /// \brief The brace breaking style to use.
+ BraceBreakingStyle BreakBeforeBraces;
+
+ /// \brief Precise control over the wrapping of braces.
+ struct BraceWrappingFlags {
+ /// \brief Wrap class definitions.
+ bool AfterClass;
+ /// \brief Wrap control statements (if/for/while/switch/..).
+ bool AfterControlStatement;
+ /// \brief Wrap enum definitions.
+ bool AfterEnum;
+ /// \brief Wrap function definitions.
+ bool AfterFunction;
+ /// \brief Wrap namespace definitions.
+ bool AfterNamespace;
+ /// \brief Wrap ObjC definitions (@autoreleasepool, interfaces, ..).
+ bool AfterObjCDeclaration;
+ /// \brief Wrap struct definitions.
+ bool AfterStruct;
+ /// \brief Wrap union definitions.
+ bool AfterUnion;
+ /// \brief Wrap before \c catch.
+ bool BeforeCatch;
+ /// \brief Wrap before \c else.
+ bool BeforeElse;
+ /// \brief Indent the wrapped braces themselves.
+ bool IndentBraces;
+ };
+
+ /// \brief Control of individual brace wrapping cases.
+ ///
+ /// If \c BreakBeforeBraces is set to \c custom, use this to specify how each
+ /// individual brace case should be handled. Otherwise, this is ignored.
+ BraceWrappingFlags BraceWrapping;
+
+ /// \brief If \c true, ternary operators will be placed after line breaks.
+ bool BreakBeforeTernaryOperators;
+
+ /// \brief Always break constructor initializers before commas and align
+ /// the commas with the colon.
+ bool BreakConstructorInitializersBeforeComma;
+
+ /// \brief Break after each annotation on a field in Java files.
+ bool BreakAfterJavaFieldAnnotations;
+
+ /// \brief The column limit.
+ ///
+ /// A column limit of \c 0 means that there is no column limit. In this case,
+ /// clang-format will respect the input's line breaking decisions within
+ /// statements unless they contradict other rules.
+ unsigned ColumnLimit;
+
+ /// \brief A regular expression that describes comments with special meaning,
+ /// which should not be split into lines or otherwise changed.
+ std::string CommentPragmas;
+
+ /// \brief If the constructor initializers don't fit on a line, put each
+ /// initializer on its own line.
+ bool ConstructorInitializerAllOnOneLineOrOnePerLine;
+
+ /// \brief The number of characters to use for indentation of constructor
+ /// initializer lists.
+ unsigned ConstructorInitializerIndentWidth;
+
+ /// \brief Indent width for line continuations.
+ unsigned ContinuationIndentWidth;
+
+ /// \brief If \c true, format braced lists as best suited for C++11 braced
+ /// lists.
+ ///
+ /// Important differences:
+ /// - No spaces inside the braced list.
+ /// - No line break before the closing brace.
+ /// - Indentation with the continuation indent, not with the block indent.
+ ///
+ /// Fundamentally, C++11 braced lists are formatted exactly like function
+ /// calls would be formatted in their place. If the braced list follows a name
+ /// (e.g. a type or variable name), clang-format formats as if the \c {} were
+ /// the parentheses of a function call with that name. If there is no name,
+ /// a zero-length name is assumed.
+ bool Cpp11BracedListStyle;
+
+ /// \brief If \c true, analyze the formatted file for the most common
+ /// alignment of & and *. \c PointerAlignment is then used only as fallback.
+ bool DerivePointerAlignment;
+
+ /// \brief Disables formatting completely.
+ bool DisableFormat;
+
+ /// \brief If \c true, clang-format detects whether function calls and
+ /// definitions are formatted with one parameter per line.
+ ///
+ /// Each call can be bin-packed, one-per-line or inconclusive. If it is
+ /// inconclusive, e.g. completely on one line, but a decision needs to be
+ /// made, clang-format analyzes whether there are other bin-packed cases in
+ /// the input file and act accordingly.
+ ///
+ /// NOTE: This is an experimental flag, that might go away or be renamed. Do
+ /// not use this in config files, etc. Use at your own risk.
+ bool ExperimentalAutoDetectBinPacking;
+
+ /// \brief A vector of macros that should be interpreted as foreach loops
+ /// instead of as function calls.
+ ///
+ /// These are expected to be macros of the form:
+ /// \code
+ /// FOREACH(<variable-declaration>, ...)
+ /// <loop-body>
+ /// \endcode
+ ///
+ /// In the .clang-format configuration file, this can be configured like:
+ /// \code
+ /// ForEachMacros: ['RANGES_FOR', 'FOREACH']
+ /// \endcode
+ ///
+ /// For example: BOOST_FOREACH.
+ std::vector<std::string> ForEachMacros;
+
+ /// \brief See documentation of \c IncludeCategories.
+ struct IncludeCategory {
+ /// \brief The regular expression that this category matches.
+ std::string Regex;
+ /// \brief The priority to assign to this category.
+ int Priority;
+ bool operator==(const IncludeCategory &Other) const {
+ return Regex == Other.Regex && Priority == Other.Priority;
+ }
+ };
+
+ /// \brief Regular expressions denoting the different #include categories used
+ /// for ordering #includes.
+ ///
+ /// These regular expressions are matched against the filename of an include
+ /// (including the <> or "") in order. The value belonging to the first
+ /// matching regular expression is assigned and #includes are sorted first
+ /// according to increasing category number and then alphabetically within
+ /// each category.
+ ///
+ /// If none of the regular expressions match, INT_MAX is assigned as
+ /// category. The main header for a source file automatically gets category 0.
+ /// so that it is generally kept at the beginning of the #includes
+ /// (http://llvm.org/docs/CodingStandards.html#include-style). However, you
+ /// can also assign negative priorities if you have certain headers that
+ /// always need to be first.
+ ///
+ /// To configure this in the .clang-format file, use:
+ /// \code
+ /// IncludeCategories:
+ /// - Regex: '^"(llvm|llvm-c|clang|clang-c)/'
+ /// Priority: 2
+ /// - Regex: '^(<|"(gtest|isl|json)/)'
+ /// Priority: 3
+ /// - Regex: '.*'
+ /// Priority: 1
+ /// \endcode
+ std::vector<IncludeCategory> IncludeCategories;
+
+ /// \brief Indent case labels one level from the switch statement.
+ ///
+ /// When \c false, use the same indentation level as for the switch statement.
+ /// Switch statement body is always indented one level more than case labels.
+ bool IndentCaseLabels;
+
+ /// \brief The number of columns to use for indentation.
+ unsigned IndentWidth;
+
+ /// \brief Indent if a function definition or declaration is wrapped after the
+ /// type.
+ bool IndentWrappedFunctionNames;
+
+ /// \brief If true, empty lines at the start of blocks are kept.
+ bool KeepEmptyLinesAtTheStartOfBlocks;
+
+ /// \brief Supported languages. When stored in a configuration file, specifies
+ /// the language, that the configuration targets. When passed to the
+ /// reformat() function, enables syntax features specific to the language.
+ enum LanguageKind {
+ /// Do not use.
+ LK_None,
+ /// Should be used for C, C++, ObjectiveC, ObjectiveC++.
+ LK_Cpp,
+ /// Should be used for Java.
+ LK_Java,
+ /// Should be used for JavaScript.
+ LK_JavaScript,
+ /// Should be used for Protocol Buffers
+ /// (https://developers.google.com/protocol-buffers/).
+ LK_Proto,
+ /// Should be used for TableGen code.
+ LK_TableGen
+ };
+
+ /// \brief Language, this format style is targeted at.
+ LanguageKind Language;
+
+ /// \brief A regular expression matching macros that start a block.
+ std::string MacroBlockBegin;
+
+ /// \brief A regular expression matching macros that end a block.
+ std::string MacroBlockEnd;
+
+ /// \brief The maximum number of consecutive empty lines to keep.
+ unsigned MaxEmptyLinesToKeep;
+
+ /// \brief Different ways to indent namespace contents.
+ enum NamespaceIndentationKind {
+ /// Don't indent in namespaces.
+ NI_None,
+ /// Indent only in inner namespaces (nested in other namespaces).
+ NI_Inner,
+ /// Indent in all namespaces.
+ NI_All
+ };
+
+ /// \brief The indentation used for namespaces.
+ NamespaceIndentationKind NamespaceIndentation;
+
+ /// \brief The number of characters to use for indentation of ObjC blocks.
+ unsigned ObjCBlockIndentWidth;
+
+ /// \brief Add a space after \c @property in Objective-C, i.e. use
+ /// <tt>\@property (readonly)</tt> instead of <tt>\@property(readonly)</tt>.
+ bool ObjCSpaceAfterProperty;
+
+ /// \brief Add a space in front of an Objective-C protocol list, i.e. use
+ /// <tt>Foo <Protocol></tt> instead of \c Foo<Protocol>.
+ bool ObjCSpaceBeforeProtocolList;
+
+ /// \brief The penalty for breaking a function call after "call(".
+ unsigned PenaltyBreakBeforeFirstCallParameter;
+
+ /// \brief The penalty for each line break introduced inside a comment.
+ unsigned PenaltyBreakComment;
+
+ /// \brief The penalty for breaking before the first \c <<.
+ unsigned PenaltyBreakFirstLessLess;
+
+ /// \brief The penalty for each line break introduced inside a string literal.
+ unsigned PenaltyBreakString;
+
+ /// \brief The penalty for each character outside of the column limit.
+ unsigned PenaltyExcessCharacter;
+
+ /// \brief Penalty for putting the return type of a function onto its own
+ /// line.
+ unsigned PenaltyReturnTypeOnItsOwnLine;
+
+ /// \brief The & and * alignment style.
+ enum PointerAlignmentStyle {
+ /// Align pointer to the left.
+ PAS_Left,
+ /// Align pointer to the right.
+ PAS_Right,
+ /// Align pointer in the middle.
+ PAS_Middle
+ };
+
+ /// \brief Pointer and reference alignment style.
+ PointerAlignmentStyle PointerAlignment;
+
+ /// \brief If true, clang-format will attempt to re-flow comments.
+ bool ReflowComments;
+
+ /// \brief If true, clang-format will sort #includes.
+ bool SortIncludes;
+
+ /// \brief If \c true, a space may be inserted after C style casts.
+ bool SpaceAfterCStyleCast;
+
+ /// \brief If \c false, spaces will be removed before assignment operators.
+ bool SpaceBeforeAssignmentOperators;
+
+ /// \brief Different ways to put a space before opening parentheses.
+ enum SpaceBeforeParensOptions {
+ /// Never put a space before opening parentheses.
+ SBPO_Never,
+ /// Put a space before opening parentheses only after control statement
+ /// keywords (<tt>for/if/while...</tt>).
+ SBPO_ControlStatements,
+ /// Always put a space before opening parentheses, except when it's
+ /// prohibited by the syntax rules (in function-like macro definitions) or
+ /// when determined by other style rules (after unary operators, opening
+ /// parentheses, etc.)
+ SBPO_Always
+ };
+
+ /// \brief Defines in which cases to put a space before opening parentheses.
+ SpaceBeforeParensOptions SpaceBeforeParens;
+
+ /// \brief If \c true, spaces may be inserted into '()'.
+ bool SpaceInEmptyParentheses;
+
+ /// \brief The number of spaces before trailing line comments
+ /// (\c // - comments).
+ ///
+ /// This does not affect trailing block comments (\c /**/ - comments) as those
+ /// commonly have different usage patterns and a number of special cases.
+ unsigned SpacesBeforeTrailingComments;
+
+ /// \brief If \c true, spaces will be inserted after '<' and before '>' in
+ /// template argument lists
+ bool SpacesInAngles;
+
+ /// \brief If \c true, spaces are inserted inside container literals (e.g.
+ /// ObjC and Javascript array and dict literals).
+ bool SpacesInContainerLiterals;
+
+ /// \brief If \c true, spaces may be inserted into C style casts.
+ bool SpacesInCStyleCastParentheses;
+
+ /// \brief If \c true, spaces will be inserted after '(' and before ')'.
+ bool SpacesInParentheses;
+
+ /// \brief If \c true, spaces will be inserted after '[' and before ']'.
+ bool SpacesInSquareBrackets;
+
+ /// \brief Supported language standards.
+ enum LanguageStandard {
+ /// Use C++03-compatible syntax.
+ LS_Cpp03,
+ /// Use features of C++11 (e.g. \c A<A<int>> instead of
+ /// <tt>A<A<int> ></tt>).
+ LS_Cpp11,
+ /// Automatic detection based on the input.
+ LS_Auto
+ };
+
+ /// \brief Format compatible with this standard, e.g. use
+ /// <tt>A<A<int> ></tt> instead of \c A<A<int>> for LS_Cpp03.
+ LanguageStandard Standard;
+
+ /// \brief The number of columns used for tab stops.
+ unsigned TabWidth;
+
+ /// \brief Different ways to use tab in formatting.
+ enum UseTabStyle {
+ /// Never use tab.
+ UT_Never,
+ /// Use tabs only for indentation.
+ UT_ForIndentation,
+ /// Use tabs whenever we need to fill whitespace that spans at least from
+ /// one tab stop to the next one.
+ UT_Always
+ };
+
+ /// \brief The way to use tab characters in the resulting file.
+ UseTabStyle UseTab;
+
+ bool operator==(const FormatStyle &R) const {
+ return AccessModifierOffset == R.AccessModifierOffset &&
+ AlignAfterOpenBracket == R.AlignAfterOpenBracket &&
+ AlignConsecutiveAssignments == R.AlignConsecutiveAssignments &&
+ AlignConsecutiveDeclarations == R.AlignConsecutiveDeclarations &&
+ AlignEscapedNewlinesLeft == R.AlignEscapedNewlinesLeft &&
+ AlignOperands == R.AlignOperands &&
+ AlignTrailingComments == R.AlignTrailingComments &&
+ AllowAllParametersOfDeclarationOnNextLine ==
+ R.AllowAllParametersOfDeclarationOnNextLine &&
+ AllowShortBlocksOnASingleLine == R.AllowShortBlocksOnASingleLine &&
+ AllowShortCaseLabelsOnASingleLine ==
+ R.AllowShortCaseLabelsOnASingleLine &&
+ AllowShortFunctionsOnASingleLine ==
+ R.AllowShortFunctionsOnASingleLine &&
+ AllowShortIfStatementsOnASingleLine ==
+ R.AllowShortIfStatementsOnASingleLine &&
+ AllowShortLoopsOnASingleLine == R.AllowShortLoopsOnASingleLine &&
+ AlwaysBreakAfterReturnType == R.AlwaysBreakAfterReturnType &&
+ AlwaysBreakBeforeMultilineStrings ==
+ R.AlwaysBreakBeforeMultilineStrings &&
+ AlwaysBreakTemplateDeclarations ==
+ R.AlwaysBreakTemplateDeclarations &&
+ BinPackArguments == R.BinPackArguments &&
+ BinPackParameters == R.BinPackParameters &&
+ BreakBeforeBinaryOperators == R.BreakBeforeBinaryOperators &&
+ BreakBeforeBraces == R.BreakBeforeBraces &&
+ BreakBeforeTernaryOperators == R.BreakBeforeTernaryOperators &&
+ BreakConstructorInitializersBeforeComma ==
+ R.BreakConstructorInitializersBeforeComma &&
+ BreakAfterJavaFieldAnnotations == R.BreakAfterJavaFieldAnnotations &&
+ ColumnLimit == R.ColumnLimit && CommentPragmas == R.CommentPragmas &&
+ ConstructorInitializerAllOnOneLineOrOnePerLine ==
+ R.ConstructorInitializerAllOnOneLineOrOnePerLine &&
+ ConstructorInitializerIndentWidth ==
+ R.ConstructorInitializerIndentWidth &&
+ ContinuationIndentWidth == R.ContinuationIndentWidth &&
+ Cpp11BracedListStyle == R.Cpp11BracedListStyle &&
+ DerivePointerAlignment == R.DerivePointerAlignment &&
+ DisableFormat == R.DisableFormat &&
+ ExperimentalAutoDetectBinPacking ==
+ R.ExperimentalAutoDetectBinPacking &&
+ ForEachMacros == R.ForEachMacros &&
+ IncludeCategories == R.IncludeCategories &&
+ IndentCaseLabels == R.IndentCaseLabels &&
+ IndentWidth == R.IndentWidth && Language == R.Language &&
+ IndentWrappedFunctionNames == R.IndentWrappedFunctionNames &&
+ KeepEmptyLinesAtTheStartOfBlocks ==
+ R.KeepEmptyLinesAtTheStartOfBlocks &&
+ MacroBlockBegin == R.MacroBlockBegin &&
+ MacroBlockEnd == R.MacroBlockEnd &&
+ MaxEmptyLinesToKeep == R.MaxEmptyLinesToKeep &&
+ NamespaceIndentation == R.NamespaceIndentation &&
+ ObjCBlockIndentWidth == R.ObjCBlockIndentWidth &&
+ ObjCSpaceAfterProperty == R.ObjCSpaceAfterProperty &&
+ ObjCSpaceBeforeProtocolList == R.ObjCSpaceBeforeProtocolList &&
+ PenaltyBreakBeforeFirstCallParameter ==
+ R.PenaltyBreakBeforeFirstCallParameter &&
+ PenaltyBreakComment == R.PenaltyBreakComment &&
+ PenaltyBreakFirstLessLess == R.PenaltyBreakFirstLessLess &&
+ PenaltyBreakString == R.PenaltyBreakString &&
+ PenaltyExcessCharacter == R.PenaltyExcessCharacter &&
+ PenaltyReturnTypeOnItsOwnLine == R.PenaltyReturnTypeOnItsOwnLine &&
+ PointerAlignment == R.PointerAlignment &&
+ SpaceAfterCStyleCast == R.SpaceAfterCStyleCast &&
+ SpaceBeforeAssignmentOperators == R.SpaceBeforeAssignmentOperators &&
+ SpaceBeforeParens == R.SpaceBeforeParens &&
+ SpaceInEmptyParentheses == R.SpaceInEmptyParentheses &&
+ SpacesBeforeTrailingComments == R.SpacesBeforeTrailingComments &&
+ SpacesInAngles == R.SpacesInAngles &&
+ SpacesInContainerLiterals == R.SpacesInContainerLiterals &&
+ SpacesInCStyleCastParentheses == R.SpacesInCStyleCastParentheses &&
+ SpacesInParentheses == R.SpacesInParentheses &&
+ SpacesInSquareBrackets == R.SpacesInSquareBrackets &&
+ Standard == R.Standard && TabWidth == R.TabWidth &&
+ UseTab == R.UseTab;
+ }
+};
+
+/// \brief Returns a format style complying with the LLVM coding standards:
+/// http://llvm.org/docs/CodingStandards.html.
+FormatStyle getLLVMStyle();
+
+/// \brief Returns a format style complying with one of Google's style guides:
+/// http://google-styleguide.googlecode.com/svn/trunk/cppguide.xml.
+/// http://google-styleguide.googlecode.com/svn/trunk/javascriptguide.xml.
+/// https://developers.google.com/protocol-buffers/docs/style.
+FormatStyle getGoogleStyle(FormatStyle::LanguageKind Language);
+
+/// \brief Returns a format style complying with Chromium's style guide:
+/// http://www.chromium.org/developers/coding-style.
+FormatStyle getChromiumStyle(FormatStyle::LanguageKind Language);
+
+/// \brief Returns a format style complying with Mozilla's style guide:
+/// https://developer.mozilla.org/en-US/docs/Developer_Guide/Coding_Style.
+FormatStyle getMozillaStyle();
+
+/// \brief Returns a format style complying with Webkit's style guide:
+/// http://www.webkit.org/coding/coding-style.html
+FormatStyle getWebKitStyle();
+
+/// \brief Returns a format style complying with GNU Coding Standards:
+/// http://www.gnu.org/prep/standards/standards.html
+FormatStyle getGNUStyle();
+
+/// \brief Returns style indicating formatting should be not applied at all.
+FormatStyle getNoStyle();
+
+/// \brief Gets a predefined style for the specified language by name.
+///
+/// Currently supported names: LLVM, Google, Chromium, Mozilla. Names are
+/// compared case-insensitively.
+///
+/// Returns \c true if the Style has been set.
+bool getPredefinedStyle(StringRef Name, FormatStyle::LanguageKind Language,
+ FormatStyle *Style);
+
+/// \brief Parse configuration from YAML-formatted text.
+///
+/// Style->Language is used to get the base style, if the \c BasedOnStyle
+/// option is present.
+///
+/// When \c BasedOnStyle is not present, options not present in the YAML
+/// document, are retained in \p Style.
+std::error_code parseConfiguration(StringRef Text, FormatStyle *Style);
+
+/// \brief Gets configuration in a YAML string.
+std::string configurationAsText(const FormatStyle &Style);
+
+/// \brief Returns the replacements necessary to sort all #include blocks that
+/// are affected by 'Ranges'.
+tooling::Replacements sortIncludes(const FormatStyle &Style, StringRef Code,
+ ArrayRef<tooling::Range> Ranges,
+ StringRef FileName,
+ unsigned *Cursor = nullptr);
+
+/// \brief Reformats the given \p Ranges in the file \p ID.
+///
+/// Each range is extended on either end to its next bigger logic unit, i.e.
+/// everything that might influence its formatting or might be influenced by its
+/// formatting.
+///
+/// Returns the \c Replacements necessary to make all \p Ranges comply with
+/// \p Style.
+///
+/// If \c IncompleteFormat is non-null, its value will be set to true if any
+/// of the affected ranges were not formatted due to a non-recoverable syntax
+/// error.
+tooling::Replacements reformat(const FormatStyle &Style,
+ SourceManager &SourceMgr, FileID ID,
+ ArrayRef<CharSourceRange> Ranges,
+ bool *IncompleteFormat = nullptr);
+
+/// \brief Reformats the given \p Ranges in \p Code.
+///
+/// Otherwise identical to the reformat() function using a file ID.
+tooling::Replacements reformat(const FormatStyle &Style, StringRef Code,
+ ArrayRef<tooling::Range> Ranges,
+ StringRef FileName = "<stdin>",
+ bool *IncompleteFormat = nullptr);
+
+/// \brief Returns the \c LangOpts that the formatter expects you to set.
+///
+/// \param Style determines specific settings for lexing mode.
+LangOptions getFormattingLangOpts(const FormatStyle &Style = getLLVMStyle());
+
+/// \brief Description to be used for help text for a llvm::cl option for
+/// specifying format style. The description is closely related to the operation
+/// of getStyle().
+extern const char *StyleOptionHelpDescription;
+
+/// \brief Construct a FormatStyle based on \c StyleName.
+///
+/// \c StyleName can take several forms:
+/// \li "{<key>: <value>, ...}" - Set specic style parameters.
+/// \li "<style name>" - One of the style names supported by
+/// getPredefinedStyle().
+/// \li "file" - Load style configuration from a file called '.clang-format'
+/// located in one of the parent directories of \c FileName or the current
+/// directory if \c FileName is empty.
+///
+/// \param[in] StyleName Style name to interpret according to the description
+/// above.
+/// \param[in] FileName Path to start search for .clang-format if \c StyleName
+/// == "file".
+/// \param[in] FallbackStyle The name of a predefined style used to fallback to
+/// in case the style can't be determined from \p StyleName.
+///
+/// \returns FormatStyle as specified by \c StyleName. If no style could be
+/// determined, the default is LLVM Style (see getLLVMStyle()).
+FormatStyle getStyle(StringRef StyleName, StringRef FileName,
+ StringRef FallbackStyle);
+
+} // end namespace format
+} // end namespace clang
+
+namespace std {
+template <>
+struct is_error_code_enum<clang::format::ParseError> : std::true_type {};
+}
+
+#endif // LLVM_CLANG_FORMAT_FORMAT_H
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..757fcae
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Frontend/ASTConsumers.h
@@ -0,0 +1,58 @@
+//===--- 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 LLVM_CLANG_FRONTEND_ASTCONSUMERS_H
+#define LLVM_CLANG_FRONTEND_ASTCONSUMERS_H
+
+#include "clang/Basic/LLVM.h"
+#include <memory>
+
+namespace clang {
+
+class ASTConsumer;
+class CodeGenOptions;
+class DiagnosticsEngine;
+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.
+std::unique_ptr<ASTConsumer> CreateASTPrinter(raw_ostream *OS,
+ StringRef FilterString);
+
+// AST dumper: dumps the raw AST in human-readable form to stderr; this is
+// intended for debugging.
+std::unique_ptr<ASTConsumer> CreateASTDumper(StringRef FilterString,
+ bool DumpDecls,
+ bool DumpLookups);
+
+// AST Decl node lister: prints qualified names of all filterable AST Decl
+// nodes.
+std::unique_ptr<ASTConsumer> CreateASTDeclNodeLister();
+
+// 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.
+std::unique_ptr<ASTConsumer> CreateASTViewer();
+
+// DeclContext printer: prints out the DeclContext tree in human-readable form
+// to stderr; this is intended for debugging.
+std::unique_ptr<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..a5f7af5
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Frontend/ASTUnit.h
@@ -0,0 +1,924 @@
+//===--- 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-c/Index.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/Basic/FileManager.h"
+#include "clang/Basic/FileSystemOptions.h"
+#include "clang/Basic/LangOptions.h"
+#include "clang/Basic/SourceManager.h"
+#include "clang/Basic/TargetOptions.h"
+#include "clang/Lex/HeaderSearchOptions.h"
+#include "clang/Lex/ModuleLoader.h"
+#include "clang/Lex/PreprocessingRecord.h"
+#include "clang/Sema/CodeCompleteConsumer.h"
+#include "clang/Serialization/ASTBitCodes.h"
+#include "llvm/ADT/IntrusiveRefCntPtr.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/StringMap.h"
+#include "llvm/Support/MD5.h"
+#include "llvm/Support/Path.h"
+#include <cassert>
+#include <map>
+#include <memory>
+#include <string>
+#include <sys/types.h>
+#include <utility>
+#include <vector>
+
+namespace llvm {
+ class MemoryBuffer;
+}
+
+namespace clang {
+class Sema;
+class ASTContext;
+class ASTReader;
+class CodeCompleteConsumer;
+class CompilerInvocation;
+class CompilerInstance;
+class Decl;
+class DiagnosticsEngine;
+class FileEntry;
+class FileManager;
+class HeaderSearch;
+class Preprocessor;
+class PCHContainerOperations;
+class PCHContainerReader;
+class SourceManager;
+class TargetInfo;
+class ASTFrontendAction;
+class ASTDeserializationListener;
+
+/// \brief Utility class for loading a ASTContext from an AST file.
+///
+class ASTUnit : public ModuleLoader {
+public:
+ struct StandaloneFixIt {
+ std::pair<unsigned, unsigned> RemoveRange;
+ std::pair<unsigned, unsigned> InsertFromRange;
+ std::string CodeToInsert;
+ bool BeforePreviousInsertions;
+ };
+
+ struct StandaloneDiagnostic {
+ unsigned ID;
+ DiagnosticsEngine::Level Level;
+ std::string Message;
+ std::string Filename;
+ unsigned LocOffset;
+ std::vector<std::pair<unsigned, unsigned> > Ranges;
+ std::vector<StandaloneFixIt> FixIts;
+ };
+
+private:
+ std::shared_ptr<LangOptions> LangOpts;
+ IntrusiveRefCntPtr<DiagnosticsEngine> Diagnostics;
+ IntrusiveRefCntPtr<FileManager> FileMgr;
+ IntrusiveRefCntPtr<SourceManager> SourceMgr;
+ std::unique_ptr<HeaderSearch> HeaderInfo;
+ IntrusiveRefCntPtr<TargetInfo> Target;
+ IntrusiveRefCntPtr<Preprocessor> PP;
+ IntrusiveRefCntPtr<ASTContext> Ctx;
+ std::shared_ptr<TargetOptions> TargetOpts;
+ IntrusiveRefCntPtr<HeaderSearchOptions> HSOpts;
+ IntrusiveRefCntPtr<ASTReader> Reader;
+ bool HadModuleLoaderFatalFailure;
+
+ struct ASTWriterData;
+ std::unique_ptr<ASTWriterData> WriterData;
+
+ FileSystemOptions FileSystemOpts;
+
+ /// \brief The AST consumer that received information about the translation
+ /// unit as it was parsed or loaded.
+ std::unique_ptr<ASTConsumer> Consumer;
+
+ /// \brief The semantic analysis object used to type-check the translation
+ /// unit.
+ std::unique_ptr<Sema> TheSema;
+
+ /// Optional owned invocation, just used to make the invocation used in
+ /// LoadFromCommandLine available.
+ IntrusiveRefCntPtr<CompilerInvocation> Invocation;
+
+ // OnlyLocalDecls - when true, walking this AST should only visit declarations
+ // that come from the AST itself, not from included precompiled headers.
+ // FIXME: This is temporary; eventually, CIndex will always do this.
+ bool OnlyLocalDecls;
+
+ /// \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 What kind of translation unit this AST represents.
+ TranslationUnitKind TUKind;
+
+ /// \brief Whether we should time each operation.
+ bool WantTiming;
+
+ /// \brief Whether the ASTUnit should delete the remapped buffers.
+ bool OwnsRemappedFileBuffers;
+
+ /// 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 Sorted (by file offset) vector of pairs of file offset/Decl.
+ typedef SmallVector<std::pair<unsigned, Decl *>, 64> LocDeclsTy;
+ typedef llvm::DenseMap<FileID, LocDeclsTy *> FileDeclsTy;
+
+ /// \brief Map from FileID to the file-level declarations that it contains.
+ /// The files and decls are only local (and non-preamble) ones.
+ FileDeclsTy FileDecls;
+
+ /// The name of the original source file used to generate this ASTUnit.
+ std::string OriginalSourceFile;
+
+ /// \brief The set of diagnostics produced when creating the preamble.
+ SmallVector<StandaloneDiagnostic, 4> PreambleDiagnostics;
+
+ /// \brief The set of diagnostics produced when creating this
+ /// translation unit.
+ SmallVector<StoredDiagnostic, 4> StoredDiagnostics;
+
+ /// \brief The set of diagnostics produced when failing to parse, e.g. due
+ /// to failure to load the PCH.
+ SmallVector<StoredDiagnostic, 4> FailedParseDiagnostics;
+
+ /// \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 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;
+
+public:
+ class PreambleData {
+ const FileEntry *File;
+ std::vector<char> Buffer;
+ mutable unsigned NumLines;
+
+ public:
+ PreambleData() : File(nullptr), NumLines(0) { }
+
+ void assign(const FileEntry *F, const char *begin, const char *end) {
+ File = F;
+ Buffer.assign(begin, end);
+ NumLines = 0;
+ }
+
+ void clear() { Buffer.clear(); File = nullptr; NumLines = 0; }
+
+ size_t size() const { return Buffer.size(); }
+ bool empty() const { return Buffer.empty(); }
+
+ const char *getBufferStart() const { return &Buffer[0]; }
+
+ unsigned getNumLines() const {
+ if (NumLines)
+ return NumLines;
+ countLines();
+ return NumLines;
+ }
+
+ SourceRange getSourceRange(const SourceManager &SM) const {
+ SourceLocation FileLoc = SM.getLocForStartOfFile(SM.getPreambleFileID());
+ return SourceRange(FileLoc, FileLoc.getLocWithOffset(size()-1));
+ }
+
+ private:
+ void countLines() const;
+ };
+
+ const PreambleData &getPreambleData() const {
+ return Preamble;
+ }
+
+ /// Data used to determine if a file used in the preamble has been changed.
+ struct PreambleFileHash {
+ /// All files have size set.
+ off_t Size;
+
+ /// Modification time is set for files that are on disk. For memory
+ /// buffers it is zero.
+ time_t ModTime;
+
+ /// Memory buffers have MD5 instead of modification time. We don't
+ /// compute MD5 for on-disk files because we hope that modification time is
+ /// enough to tell if the file was changed.
+ llvm::MD5::MD5Result MD5;
+
+ static PreambleFileHash createForFile(off_t Size, time_t ModTime);
+ static PreambleFileHash
+ createForMemoryBuffer(const llvm::MemoryBuffer *Buffer);
+
+ friend bool operator==(const PreambleFileHash &LHS,
+ const PreambleFileHash &RHS);
+
+ friend bool operator!=(const PreambleFileHash &LHS,
+ const PreambleFileHash &RHS) {
+ return !(LHS == RHS);
+ }
+ };
+
+private:
+ /// \brief The contents of the preamble that has been precompiled to
+ /// \c PreambleFile.
+ PreambleData 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 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<PreambleFileHash> 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.
+ std::unique_ptr<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.
+ std::unique_ptr<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 DiagnosticsEngine
+ /// 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 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 Whether we should be caching code-completion results.
+ bool ShouldCacheCodeCompletionResults : 1;
+
+ /// \brief Whether to include brief documentation within the set of code
+ /// completions cached.
+ bool IncludeBriefCommentsInCodeCompletion : 1;
+
+ /// \brief True if non-system source files should be treated as volatile
+ /// (likely to change while trying to use them).
+ bool UserFilesAreVolatile : 1;
+
+ /// \brief The language options used when we load an AST file.
+ LangOptions ASTFileLangOpts;
+
+ static void ConfigureDiags(IntrusiveRefCntPtr<DiagnosticsEngine> Diags,
+ ASTUnit &AST, bool CaptureDiagnostics);
+
+ void TranslateStoredDiagnostics(FileManager &FileMgr,
+ SourceManager &SrcMan,
+ const SmallVectorImpl<StandaloneDiagnostic> &Diags,
+ SmallVectorImpl<StoredDiagnostic> &Out);
+
+ void clearFileLevelDecls();
+
+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, shift 1 by that number of bits. Many completions can occur in
+ /// several different contexts.
+ uint64_t 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.
+ IntrusiveRefCntPtr<GlobalCodeCompletionAllocator>
+ getCachedCompletionAllocator() {
+ return CachedCompletionAllocator;
+ }
+
+ CodeCompletionTUInfo &getCodeCompletionTUInfo() {
+ if (!CCTUInfo)
+ CCTUInfo.reset(new CodeCompletionTUInfo(
+ new GlobalCodeCompletionAllocator));
+ return *CCTUInfo;
+ }
+
+private:
+ /// \brief Allocator used to store cached code completions.
+ IntrusiveRefCntPtr<GlobalCodeCompletionAllocator>
+ CachedCompletionAllocator;
+
+ std::unique_ptr<CodeCompletionTUInfo> CCTUInfo;
+
+ /// \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 &) = delete;
+ void operator=(const ASTUnit &) = delete;
+
+ explicit ASTUnit(bool MainFileIsAST);
+
+ void CleanTemporaryFiles();
+ bool Parse(std::shared_ptr<PCHContainerOperations> PCHContainerOps,
+ std::unique_ptr<llvm::MemoryBuffer> OverrideMainBuffer);
+
+ struct ComputedPreamble {
+ llvm::MemoryBuffer *Buffer;
+ std::unique_ptr<llvm::MemoryBuffer> Owner;
+ unsigned Size;
+ bool PreambleEndsAtStartOfLine;
+ ComputedPreamble(llvm::MemoryBuffer *Buffer,
+ std::unique_ptr<llvm::MemoryBuffer> Owner, unsigned Size,
+ bool PreambleEndsAtStartOfLine)
+ : Buffer(Buffer), Owner(std::move(Owner)), Size(Size),
+ PreambleEndsAtStartOfLine(PreambleEndsAtStartOfLine) {}
+ ComputedPreamble(ComputedPreamble &&C)
+ : Buffer(C.Buffer), Owner(std::move(C.Owner)), Size(C.Size),
+ PreambleEndsAtStartOfLine(C.PreambleEndsAtStartOfLine) {}
+ };
+ ComputedPreamble ComputePreamble(CompilerInvocation &Invocation,
+ unsigned MaxLines);
+
+ std::unique_ptr<llvm::MemoryBuffer> getMainBufferWithPrecompiledPreamble(
+ std::shared_ptr<PCHContainerOperations> PCHContainerOps,
+ const CompilerInvocation &PreambleInvocationIn, bool AllowRebuild = true,
+ unsigned MaxLines = 0);
+ void RealizeTopLevelDeclsFromPreamble();
+
+ /// \brief Transfers ownership of the objects (like SourceManager) from
+ /// \param CI to this ASTUnit.
+ void transferASTDataFromCompilerInstance(CompilerInstance &CI);
+
+ /// \brief Allows 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.
+ /// Becomes a noop in release mode; only useful for debug mode checking.
+ class ConcurrencyState {
+ void *Mutex; // a llvm::sys::MutexImpl in debug;
+
+ public:
+ ConcurrencyState();
+ ~ConcurrencyState();
+
+ void start();
+ void finish();
+ };
+ ConcurrencyState ConcurrencyCheckValue;
+
+public:
+ class ConcurrencyCheck {
+ ASTUnit &Self;
+
+ public:
+ explicit ConcurrencyCheck(ASTUnit &Self)
+ : Self(Self)
+ {
+ Self.ConcurrencyCheckValue.start();
+ }
+ ~ConcurrencyCheck() {
+ Self.ConcurrencyCheckValue.finish();
+ }
+ };
+ friend class ConcurrencyCheck;
+
+ ~ASTUnit() override;
+
+ bool isMainFileAST() const { return MainFileIsAST; }
+
+ bool isUnsafeToFree() const { return UnsafeToFree; }
+ void setUnsafeToFree(bool Value) { UnsafeToFree = Value; }
+
+ const DiagnosticsEngine &getDiagnostics() const { return *Diagnostics; }
+ DiagnosticsEngine &getDiagnostics() { return *Diagnostics; }
+
+ const SourceManager &getSourceManager() const { return *SourceMgr; }
+ SourceManager &getSourceManager() { return *SourceMgr; }
+
+ const Preprocessor &getPreprocessor() const { return *PP; }
+ Preprocessor &getPreprocessor() { return *PP; }
+
+ const ASTContext &getASTContext() const { return *Ctx; }
+ ASTContext &getASTContext() { return *Ctx; }
+
+ void setASTContext(ASTContext *ctx) { Ctx = ctx; }
+ void setPreprocessor(Preprocessor *pp);
+
+ bool hasSema() const { return (bool)TheSema; }
+ Sema &getSema() const {
+ assert(TheSema && "ASTUnit does not have a Sema object!");
+ return *TheSema;
+ }
+
+ const LangOptions &getLangOpts() const {
+ assert(LangOpts && " ASTUnit does not have language options");
+ return *LangOpts;
+ }
+
+ const FileManager &getFileManager() const { return *FileMgr; }
+ FileManager &getFileManager() { return *FileMgr; }
+
+ const FileSystemOptions &getFileSystemOpts() const { return FileSystemOpts; }
+
+ StringRef getOriginalSourceFileName() {
+ return OriginalSourceFile;
+ }
+
+ ASTMutationListener *getASTMutationListener();
+ ASTDeserializationListener *getDeserializationListener();
+
+ /// \brief Add a temporary file that the ASTUnit depends on.
+ ///
+ /// This file will be erased when the ASTUnit is destroyed.
+ void addTemporaryFile(StringRef TempFile);
+
+ bool getOnlyLocalDecls() const { return OnlyLocalDecls; }
+
+ bool getOwnsRemappedFileBuffers() const { return OwnsRemappedFileBuffers; }
+ void setOwnsRemappedFileBuffers(bool val) { OwnsRemappedFileBuffers = val; }
+
+ StringRef getMainFileName() const;
+
+ /// \brief If this ASTUnit came from an AST file, returns the filename for it.
+ StringRef getASTFileName() 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 local file-level declaration.
+ void addFileLevelDecl(Decl *D);
+
+ /// \brief Get the decls that are contained in a file in the Offset/Length
+ /// range. \p Length can be 0 to indicate a point at \p Offset instead of
+ /// a range.
+ void findFileRegionDecls(FileID File, unsigned Offset, unsigned Length,
+ SmallVectorImpl<Decl *> &Decls);
+
+ /// \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; }
+
+ /// \brief Get the source location for the given file:line:col triplet.
+ ///
+ /// The difference with SourceManager::getLocation is that this method checks
+ /// whether the requested location points inside the precompiled preamble
+ /// in which case the returned source location will be a "loaded" one.
+ SourceLocation getLocation(const FileEntry *File,
+ unsigned Line, unsigned Col) const;
+
+ /// \brief Get the source location for the given file:offset pair.
+ SourceLocation getLocation(const FileEntry *File, unsigned Offset) const;
+
+ /// \brief If \p Loc is a loaded location from the preamble, returns
+ /// the corresponding local location of the main file, otherwise it returns
+ /// \p Loc.
+ SourceLocation mapLocationFromPreamble(SourceLocation Loc);
+
+ /// \brief If \p Loc is a local location of the main file but inside the
+ /// preamble chunk, returns the corresponding loaded location from the
+ /// preamble, otherwise it returns \p Loc.
+ SourceLocation mapLocationToPreamble(SourceLocation Loc);
+
+ bool isInPreambleFileID(SourceLocation Loc);
+ bool isInMainFileID(SourceLocation Loc);
+ SourceLocation getStartOfMainFileID();
+ SourceLocation getEndOfPreambleFileID();
+
+ /// \see mapLocationFromPreamble.
+ SourceRange mapRangeFromPreamble(SourceRange R) {
+ return SourceRange(mapLocationFromPreamble(R.getBegin()),
+ mapLocationFromPreamble(R.getEnd()));
+ }
+
+ /// \see mapLocationToPreamble.
+ SourceRange mapRangeToPreamble(SourceRange R) {
+ return SourceRange(mapLocationToPreamble(R.getBegin()),
+ mapLocationToPreamble(R.getEnd()));
+ }
+
+ // Retrieve the diagnostics associated with this AST
+ typedef StoredDiagnostic *stored_diag_iterator;
+ typedef const StoredDiagnostic *stored_diag_const_iterator;
+ stored_diag_const_iterator stored_diag_begin() const {
+ return StoredDiagnostics.begin();
+ }
+ stored_diag_iterator stored_diag_begin() {
+ return StoredDiagnostics.begin();
+ }
+ stored_diag_const_iterator stored_diag_end() const {
+ return StoredDiagnostics.end();
+ }
+ stored_diag_iterator stored_diag_end() {
+ return StoredDiagnostics.end();
+ }
+ unsigned stored_diag_size() const { return StoredDiagnostics.size(); }
+
+ stored_diag_iterator stored_diag_afterDriver_begin() {
+ if (NumStoredDiagnosticsFromDriver > StoredDiagnostics.size())
+ NumStoredDiagnosticsFromDriver = 0;
+ return StoredDiagnostics.begin() + NumStoredDiagnosticsFromDriver;
+ }
+
+ typedef std::vector<CachedCodeCompletionResult>::iterator
+ cached_completion_iterator;
+
+ cached_completion_iterator cached_completion_begin() {
+ return CachedCompletionResults.begin();
+ }
+
+ cached_completion_iterator cached_completion_end() {
+ return CachedCompletionResults.end();
+ }
+
+ unsigned cached_completion_size() const {
+ return CachedCompletionResults.size();
+ }
+
+ /// \brief Returns an iterator range for the local preprocessing entities
+ /// of the local Preprocessor, if this is a parsed source file, or the loaded
+ /// preprocessing entities of the primary module if this is an AST file.
+ llvm::iterator_range<PreprocessingRecord::iterator>
+ getLocalPreprocessingEntities() const;
+
+ /// \brief Type for a function iterating over a number of declarations.
+ /// \returns true to continue iteration and false to abort.
+ typedef bool (*DeclVisitorFn)(void *context, const Decl *D);
+
+ /// \brief Iterate over local declarations (locally parsed if this is a parsed
+ /// source file or the loaded declarations of the primary module if this is an
+ /// AST file).
+ /// \returns true if the iteration was complete or false if it was aborted.
+ bool visitLocalTopLevelDecls(void *context, DeclVisitorFn Fn);
+
+ /// \brief Get the PCH file if one was included.
+ const FileEntry *getPCHFile();
+
+ /// \brief Returns true if the ASTUnit was constructed from a serialized
+ /// module file.
+ bool isModuleFile();
+
+ std::unique_ptr<llvm::MemoryBuffer>
+ getBufferForFile(StringRef Filename, std::string *ErrorStr = nullptr);
+
+ /// \brief Determine what kind of translation unit this AST represents.
+ TranslationUnitKind getTranslationUnitKind() const { return TUKind; }
+
+ /// \brief A mapping from a file name to the memory buffer that stores the
+ /// remapped contents of that file.
+ typedef std::pair<std::string, llvm::MemoryBuffer *> RemappedFile;
+
+ /// \brief Create a ASTUnit. Gets ownership of the passed CompilerInvocation.
+ static ASTUnit *create(CompilerInvocation *CI,
+ IntrusiveRefCntPtr<DiagnosticsEngine> Diags,
+ bool CaptureDiagnostics,
+ bool UserFilesAreVolatile);
+
+ /// \brief Create a ASTUnit from an AST file.
+ ///
+ /// \param Filename - The AST file to load.
+ ///
+ /// \param PCHContainerRdr - The PCHContainerOperations to use for loading and
+ /// creating modules.
+ /// \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 std::unique_ptr<ASTUnit> LoadFromASTFile(
+ const std::string &Filename, const PCHContainerReader &PCHContainerRdr,
+ IntrusiveRefCntPtr<DiagnosticsEngine> Diags,
+ const FileSystemOptions &FileSystemOpts, bool UseDebugInfo = false,
+ bool OnlyLocalDecls = false, ArrayRef<RemappedFile> RemappedFiles = None,
+ bool CaptureDiagnostics = false, bool AllowPCHWithCompilerErrors = false,
+ bool UserFilesAreVolatile = false);
+
+private:
+ /// \brief Helper function for \c LoadFromCompilerInvocation() and
+ /// \c LoadFromCommandLine(), which loads an AST from a compiler invocation.
+ ///
+ /// \param PrecompilePreambleAfterNParses After how many parses the preamble
+ /// of this translation unit should be precompiled, to improve the performance
+ /// of reparsing. Set to zero to disable preambles.
+ ///
+ /// \returns \c true if a catastrophic failure occurred (which means that the
+ /// \c ASTUnit itself is invalid), or \c false otherwise.
+ bool LoadFromCompilerInvocation(
+ std::shared_ptr<PCHContainerOperations> PCHContainerOps,
+ unsigned PrecompilePreambleAfterNParses);
+
+public:
+
+ /// \brief Create an ASTUnit from a source file, via a CompilerInvocation
+ /// object, by invoking the optionally provided ASTFrontendAction.
+ ///
+ /// \param CI - The compiler invocation to use; it must have exactly one input
+ /// source file. The ASTUnit takes ownership of the CompilerInvocation object.
+ ///
+ /// \param PCHContainerOps - The PCHContainerOperations to use for loading and
+ /// creating modules.
+ ///
+ /// \param Diags - The diagnostics engine to use for reporting errors; its
+ /// lifetime is expected to extend past that of the returned ASTUnit.
+ ///
+ /// \param Action - The ASTFrontendAction to invoke. Its ownership is not
+ /// transferred.
+ ///
+ /// \param Unit - optionally an already created ASTUnit. Its ownership is not
+ /// transferred.
+ ///
+ /// \param Persistent - if true the returned ASTUnit will be complete.
+ /// false means the caller is only interested in getting info through the
+ /// provided \see Action.
+ ///
+ /// \param ErrAST - If non-null and parsing failed without any AST to return
+ /// (e.g. because the PCH could not be loaded), this accepts the ASTUnit
+ /// mainly to allow the caller to see the diagnostics.
+ /// This will only receive an ASTUnit if a new one was created. If an already
+ /// created ASTUnit was passed in \p Unit then the caller can check that.
+ ///
+ static ASTUnit *LoadFromCompilerInvocationAction(
+ CompilerInvocation *CI,
+ std::shared_ptr<PCHContainerOperations> PCHContainerOps,
+ IntrusiveRefCntPtr<DiagnosticsEngine> Diags,
+ ASTFrontendAction *Action = nullptr, ASTUnit *Unit = nullptr,
+ bool Persistent = true, StringRef ResourceFilesPath = StringRef(),
+ bool OnlyLocalDecls = false, bool CaptureDiagnostics = false,
+ unsigned PrecompilePreambleAfterNParses = 0,
+ bool CacheCodeCompletionResults = false,
+ bool IncludeBriefCommentsInCodeCompletion = false,
+ bool UserFilesAreVolatile = false,
+ std::unique_ptr<ASTUnit> *ErrAST = nullptr);
+
+ /// 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 PCHContainerOps - The PCHContainerOperations to use for loading and
+ /// creating modules.
+ ///
+ /// \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 std::unique_ptr<ASTUnit> LoadFromCompilerInvocation(
+ CompilerInvocation *CI,
+ std::shared_ptr<PCHContainerOperations> PCHContainerOps,
+ IntrusiveRefCntPtr<DiagnosticsEngine> Diags, FileManager *FileMgr,
+ bool OnlyLocalDecls = false, bool CaptureDiagnostics = false,
+ unsigned PrecompilePreambleAfterNParses = 0,
+ TranslationUnitKind TUKind = TU_Complete,
+ bool CacheCodeCompletionResults = false,
+ bool IncludeBriefCommentsInCodeCompletion = false,
+ bool UserFilesAreVolatile = 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 PCHContainerOps - The PCHContainerOperations to use for loading and
+ /// creating modules.
+ ///
+ /// \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.
+ ///
+ /// \param ModuleFormat - If provided, uses the specific module format.
+ ///
+ /// \param ErrAST - If non-null and parsing failed without any AST to return
+ /// (e.g. because the PCH could not be loaded), this accepts the ASTUnit
+ /// mainly to allow the caller to see the diagnostics.
+ ///
+ // 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,
+ std::shared_ptr<PCHContainerOperations> PCHContainerOps,
+ IntrusiveRefCntPtr<DiagnosticsEngine> Diags, StringRef ResourceFilesPath,
+ bool OnlyLocalDecls = false, bool CaptureDiagnostics = false,
+ ArrayRef<RemappedFile> RemappedFiles = None,
+ bool RemappedFilesKeepOriginalName = true,
+ unsigned PrecompilePreambleAfterNParses = 0,
+ TranslationUnitKind TUKind = TU_Complete,
+ bool CacheCodeCompletionResults = false,
+ bool IncludeBriefCommentsInCodeCompletion = false,
+ bool AllowPCHWithCompilerErrors = false, bool SkipFunctionBodies = false,
+ bool UserFilesAreVolatile = false, bool ForSerialization = false,
+ llvm::Optional<StringRef> ModuleFormat = llvm::None,
+ std::unique_ptr<ASTUnit> *ErrAST = nullptr);
+
+ /// \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(std::shared_ptr<PCHContainerOperations> PCHContainerOps,
+ ArrayRef<RemappedFile> RemappedFiles = None);
+
+ /// \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.
+ ///
+ /// \param IncludeBriefComments Whether to include brief documentation within
+ /// the set of code completions returned.
+ ///
+ /// FIXME: The Diag, LangOpts, SourceMgr, FileMgr, StoredDiagnostics, and
+ /// OwnedBuffers parameters are all disgusting hacks. They will go away.
+ void CodeComplete(StringRef File, unsigned Line, unsigned Column,
+ ArrayRef<RemappedFile> RemappedFiles, bool IncludeMacros,
+ bool IncludeCodePatterns, bool IncludeBriefComments,
+ CodeCompleteConsumer &Consumer,
+ std::shared_ptr<PCHContainerOperations> PCHContainerOps,
+ DiagnosticsEngine &Diag, LangOptions &LangOpts,
+ SourceManager &SourceMgr, FileManager &FileMgr,
+ SmallVectorImpl<StoredDiagnostic> &StoredDiagnostics,
+ SmallVectorImpl<const llvm::MemoryBuffer *> &OwnedBuffers);
+
+ /// \brief Save this translation unit to a file with the given name.
+ ///
+ /// \returns true if there was a file error or false if the save was
+ /// successful.
+ bool Save(StringRef File);
+
+ /// \brief Serialize this translation unit with the given output stream.
+ ///
+ /// \returns True if an error occurred, false otherwise.
+ bool serialize(raw_ostream &OS);
+
+ ModuleLoadResult loadModule(SourceLocation ImportLoc, ModuleIdPath Path,
+ Module::NameVisibilityKind Visibility,
+ bool IsInclusionDirective) override {
+ // ASTUnit doesn't know how to load modules (not that this matters).
+ return ModuleLoadResult();
+ }
+
+ void makeModuleVisible(Module *Mod, Module::NameVisibilityKind Visibility,
+ SourceLocation ImportLoc) override {}
+
+ GlobalModuleIndex *loadGlobalModuleIndex(SourceLocation TriggerLoc) override
+ { return nullptr; }
+ bool lookupMissingImports(StringRef Name, SourceLocation TriggerLoc) override
+ { return 0; }
+};
+
+} // namespace clang
+
+#endif
diff --git a/contrib/llvm/tools/clang/include/clang/Frontend/ChainedDiagnosticConsumer.h b/contrib/llvm/tools/clang/include/clang/Frontend/ChainedDiagnosticConsumer.h
new file mode 100644
index 0000000..eb33273
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Frontend/ChainedDiagnosticConsumer.h
@@ -0,0 +1,72 @@
+//===- ChainedDiagnosticConsumer.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_CHAINEDDIAGNOSTICCONSUMER_H
+#define LLVM_CLANG_FRONTEND_CHAINEDDIAGNOSTICCONSUMER_H
+
+#include "clang/Basic/Diagnostic.h"
+#include <memory>
+
+namespace clang {
+class LangOptions;
+
+/// ChainedDiagnosticConsumer - 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 ChainedDiagnosticConsumer : public DiagnosticConsumer {
+ virtual void anchor();
+ std::unique_ptr<DiagnosticConsumer> OwningPrimary;
+ DiagnosticConsumer *Primary;
+ std::unique_ptr<DiagnosticConsumer> Secondary;
+
+public:
+ ChainedDiagnosticConsumer(std::unique_ptr<DiagnosticConsumer> Primary,
+ std::unique_ptr<DiagnosticConsumer> Secondary)
+ : OwningPrimary(std::move(Primary)), Primary(OwningPrimary.get()),
+ Secondary(std::move(Secondary)) {}
+
+ /// \brief Construct without taking ownership of \c Primary.
+ ChainedDiagnosticConsumer(DiagnosticConsumer *Primary,
+ std::unique_ptr<DiagnosticConsumer> Secondary)
+ : Primary(Primary), Secondary(std::move(Secondary)) {}
+
+ void BeginSourceFile(const LangOptions &LO,
+ const Preprocessor *PP) override {
+ Primary->BeginSourceFile(LO, PP);
+ Secondary->BeginSourceFile(LO, PP);
+ }
+
+ void EndSourceFile() override {
+ Secondary->EndSourceFile();
+ Primary->EndSourceFile();
+ }
+
+ void finish() override {
+ Secondary->finish();
+ Primary->finish();
+ }
+
+ bool IncludeInDiagnosticCounts() const override {
+ return Primary->IncludeInDiagnosticCounts();
+ }
+
+ void HandleDiagnostic(DiagnosticsEngine::Level DiagLevel,
+ const Diagnostic &Info) override {
+ // Default implementation (Warnings/errors count).
+ DiagnosticConsumer::HandleDiagnostic(DiagLevel, Info);
+
+ Primary->HandleDiagnostic(DiagLevel, Info);
+ Secondary->HandleDiagnostic(DiagLevel, Info);
+ }
+};
+
+} // end namspace clang
+
+#endif
diff --git a/contrib/llvm/tools/clang/include/clang/Frontend/CodeGenOptions.def b/contrib/llvm/tools/clang/include/clang/Frontend/CodeGenOptions.def
new file mode 100644
index 0000000..d9f6ab7
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Frontend/CodeGenOptions.def
@@ -0,0 +1,212 @@
+//===--- CodeGenOptions.def - Code generation option 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 code generation options. Users of this file
+// must define the CODEGENOPT macro to make use of this information.
+// Optionally, the user may also define ENUM_CODEGENOPT (for options
+// that have enumeration type and VALUE_CODEGENOPT is a code
+// generation option that describes a value rather than a flag.
+//
+//===----------------------------------------------------------------------===//
+#ifndef CODEGENOPT
+# error Define the CODEGENOPT macro to handle language options
+#endif
+
+#ifndef VALUE_CODEGENOPT
+# define VALUE_CODEGENOPT(Name, Bits, Default) \
+CODEGENOPT(Name, Bits, Default)
+#endif
+
+#ifndef ENUM_CODEGENOPT
+# define ENUM_CODEGENOPT(Name, Type, Bits, Default) \
+CODEGENOPT(Name, Bits, Default)
+#endif
+
+CODEGENOPT(DisableIntegratedAS, 1, 0) ///< -no-integrated-as
+CODEGENOPT(CompressDebugSections, 1, 0) ///< -Wa,-compress-debug-sections
+CODEGENOPT(Autolink , 1, 1) ///< -fno-autolink
+CODEGENOPT(AsmVerbose , 1, 0) ///< -dA, -fverbose-asm.
+CODEGENOPT(ObjCAutoRefCountExceptions , 1, 0) ///< Whether ARC should be EH-safe.
+CODEGENOPT(CoverageExtraChecksum, 1, 0) ///< Whether we need a second checksum for functions in GCNO files.
+CODEGENOPT(CoverageNoFunctionNamesInData, 1, 0) ///< Do not include function names in GCDA files.
+CODEGENOPT(CoverageExitBlockBeforeBody, 1, 0) ///< Whether to emit the exit block before the body blocks in GCNO files.
+CODEGENOPT(CXAAtExit , 1, 1) ///< Use __cxa_atexit for calling destructors.
+CODEGENOPT(CXXCtorDtorAliases, 1, 0) ///< Emit complete ctors/dtors as linker
+ ///< aliases to base ctors when possible.
+CODEGENOPT(DataSections , 1, 0) ///< Set when -fdata-sections is enabled.
+CODEGENOPT(UniqueSectionNames, 1, 1) ///< Set for -funique-section-names.
+CODEGENOPT(DisableFPElim , 1, 0) ///< Set when -fomit-frame-pointer is enabled.
+CODEGENOPT(DisableFree , 1, 0) ///< Don't free memory.
+CODEGENOPT(DisableGCov , 1, 0) ///< Don't run the GCov pass, for testing.
+CODEGENOPT(DisableLLVMOpts , 1, 0) ///< Don't run any optimizations, for use in
+ ///< getting .bc files that correspond to the
+ ///< internal state before optimizations are
+ ///< done.
+CODEGENOPT(DisableLLVMPasses , 1, 0) ///< Don't run any LLVM IR passes to get
+ ///< the pristine IR generated by the
+ ///< frontend.
+CODEGENOPT(DisableRedZone , 1, 0) ///< Set when -mno-red-zone is enabled.
+CODEGENOPT(DisableTailCalls , 1, 0) ///< Do not emit tail calls.
+CODEGENOPT(EmitDeclMetadata , 1, 0) ///< Emit special metadata indicating what
+ ///< Decl* various IR entities came from.
+ ///< Only useful when running CodeGen as a
+ ///< subroutine.
+CODEGENOPT(EmitGcovArcs , 1, 0) ///< Emit coverage data files, aka. GCDA.
+CODEGENOPT(EmitGcovNotes , 1, 0) ///< Emit coverage "notes" files, aka GCNO.
+CODEGENOPT(EmitOpenCLArgMetadata , 1, 0) ///< Emit OpenCL kernel arg metadata.
+CODEGENOPT(EmulatedTLS , 1, 0) ///< Set when -femulated-tls is enabled.
+/// \brief FP_CONTRACT mode (on/off/fast).
+ENUM_CODEGENOPT(FPContractMode, FPContractModeKind, 2, FPC_On)
+CODEGENOPT(ForbidGuardVariables , 1, 0) ///< Issue errors if C++ guard variables
+ ///< are required.
+CODEGENOPT(FunctionSections , 1, 0) ///< Set when -ffunction-sections is enabled.
+CODEGENOPT(InstrumentFunctions , 1, 0) ///< Set when -finstrument-functions is
+ ///< enabled.
+CODEGENOPT(InstrumentForProfiling , 1, 0) ///< Set when -pg is enabled.
+CODEGENOPT(LessPreciseFPMAD , 1, 0) ///< Enable less precise MAD instructions to
+ ///< be generated.
+CODEGENOPT(PrepareForLTO , 1, 0) ///< Set when -flto is enabled on the
+ ///< compile step.
+CODEGENOPT(EmitFunctionSummary, 1, 0) ///< Set when -flto=thin is enabled on the
+ ///< compile step.
+CODEGENOPT(IncrementalLinkerCompatible, 1, 0) ///< Emit an object file which can
+ ///< be used with an incremental
+ ///< linker.
+CODEGENOPT(MergeAllConstants , 1, 1) ///< Merge identical constants.
+CODEGENOPT(MergeFunctions , 1, 0) ///< Set when -fmerge-functions is enabled.
+CODEGENOPT(MSVolatile , 1, 0) ///< Set when /volatile:ms is enabled.
+CODEGENOPT(NoCommon , 1, 0) ///< Set when -fno-common or C++ is enabled.
+CODEGENOPT(NoDwarfDirectoryAsm , 1, 0) ///< Set when -fno-dwarf-directory-asm is
+ ///< enabled.
+CODEGENOPT(NoExecStack , 1, 0) ///< Set when -Wa,--noexecstack is enabled.
+CODEGENOPT(FatalWarnings , 1, 0) ///< Set when -Wa,--fatal-warnings is
+ ///< enabled.
+CODEGENOPT(EnableSegmentedStacks , 1, 0) ///< Set when -fsplit-stack is enabled.
+CODEGENOPT(NoImplicitFloat , 1, 0) ///< Set when -mno-implicit-float is enabled.
+CODEGENOPT(NoInfsFPMath , 1, 0) ///< Assume FP arguments, results not +-Inf.
+CODEGENOPT(NoSignedZeros , 1, 0) ///< Allow ignoring the signedness of FP zero
+CODEGENOPT(ReciprocalMath , 1, 0) ///< Allow FP divisions to be reassociated.
+CODEGENOPT(NoInline , 1, 0) ///< Set when -fno-inline is enabled.
+ ///< Disables use of the inline keyword.
+CODEGENOPT(NoNaNsFPMath , 1, 0) ///< Assume FP arguments, results not NaN.
+CODEGENOPT(NoZeroInitializedInBSS , 1, 0) ///< -fno-zero-initialized-in-bss.
+/// \brief Method of Objective-C dispatch to use.
+ENUM_CODEGENOPT(ObjCDispatchMethod, ObjCDispatchMethodKind, 2, Legacy)
+CODEGENOPT(OmitLeafFramePointer , 1, 0) ///< Set when -momit-leaf-frame-pointer is
+ ///< enabled.
+VALUE_CODEGENOPT(OptimizationLevel, 2, 0) ///< The -O[0-3] option specified.
+VALUE_CODEGENOPT(OptimizeSize, 2, 0) ///< If -Os (==1) or -Oz (==2) is specified.
+
+CODEGENOPT(ProfileInstrGenerate , 1, 0) ///< Instrument code to generate
+ ///< execution counts to use with PGO.
+CODEGENOPT(CoverageMapping , 1, 0) ///< Generate coverage mapping regions to
+ ///< enable code coverage analysis.
+CODEGENOPT(DumpCoverageMapping , 1, 0) ///< Dump the generated coverage mapping
+ ///< regions.
+
+ /// If -fpcc-struct-return or -freg-struct-return is specified.
+ENUM_CODEGENOPT(StructReturnConvention, StructReturnConventionKind, 2, SRCK_Default)
+
+CODEGENOPT(RelaxAll , 1, 0) ///< Relax all machine code instructions.
+CODEGENOPT(RelaxedAliasing , 1, 0) ///< Set when -fno-strict-aliasing is enabled.
+CODEGENOPT(StructPathTBAA , 1, 0) ///< Whether or not to use struct-path TBAA.
+CODEGENOPT(SaveTempLabels , 1, 0) ///< Save temporary labels.
+CODEGENOPT(SanitizeAddressZeroBaseShadow , 1, 0) ///< Map shadow memory at zero
+ ///< offset in AddressSanitizer.
+CODEGENOPT(SanitizeMemoryTrackOrigins, 2, 0) ///< Enable tracking origins in
+ ///< MemorySanitizer
+CODEGENOPT(SanitizeMemoryUseAfterDtor, 1, 0) ///< Enable use-after-delete detection
+ ///< in MemorySanitizer
+CODEGENOPT(SanitizeCfiCrossDso, 1, 0) ///< Enable cross-dso support in CFI.
+CODEGENOPT(SanitizeCoverageType, 2, 0) ///< Type of sanitizer coverage
+ ///< instrumentation.
+CODEGENOPT(SanitizeCoverageIndirectCalls, 1, 0) ///< Enable sanitizer coverage
+ ///< for indirect calls.
+CODEGENOPT(SanitizeCoverageTraceBB, 1, 0) ///< Enable basic block tracing in
+ ///< in sanitizer coverage.
+CODEGENOPT(SanitizeCoverageTraceCmp, 1, 0) ///< Enable cmp instruction tracing
+ ///< in sanitizer coverage.
+CODEGENOPT(SanitizeCoverage8bitCounters, 1, 0) ///< Use 8-bit frequency counters
+ ///< in sanitizer coverage.
+CODEGENOPT(SimplifyLibCalls , 1, 1) ///< Set when -fbuiltin is enabled.
+CODEGENOPT(SoftFloat , 1, 0) ///< -soft-float.
+CODEGENOPT(StrictEnums , 1, 0) ///< Optimize based on strict enum definition.
+CODEGENOPT(StrictVTablePointers, 1, 0) ///< Optimize based on the strict vtable pointers
+CODEGENOPT(TimePasses , 1, 0) ///< Set when -ftime-report is enabled.
+CODEGENOPT(UnitAtATime , 1, 1) ///< Unused. For mirroring GCC optimization
+ ///< selection.
+CODEGENOPT(UnrollLoops , 1, 0) ///< Control whether loops are unrolled.
+CODEGENOPT(RerollLoops , 1, 0) ///< Control whether loops are rerolled.
+CODEGENOPT(UnsafeFPMath , 1, 0) ///< Allow unsafe floating point optzns.
+CODEGENOPT(UnwindTables , 1, 0) ///< Emit unwind tables.
+CODEGENOPT(VectorizeBB , 1, 0) ///< Run basic block vectorizer.
+CODEGENOPT(VectorizeLoop , 1, 0) ///< Run loop vectorizer.
+CODEGENOPT(VectorizeSLP , 1, 0) ///< Run SLP vectorizer.
+
+ /// Attempt to use register sized accesses to bit-fields in structures, when
+ /// possible.
+CODEGENOPT(UseRegisterSizedBitfieldAccess , 1, 0)
+
+CODEGENOPT(VerifyModule , 1, 1) ///< Control whether the module should be run
+ ///< through the LLVM Verifier.
+
+CODEGENOPT(StackRealignment , 1, 0) ///< Control whether to force stack
+ ///< realignment.
+CODEGENOPT(UseInitArray , 1, 0) ///< Control whether to use .init_array or
+ ///< .ctors.
+VALUE_CODEGENOPT(StackAlignment , 32, 0) ///< Overrides default stack
+ ///< alignment, if not 0.
+VALUE_CODEGENOPT(StackProbeSize , 32, 4096) ///< Overrides default stack
+ ///< probe size, even if 0.
+CODEGENOPT(DebugColumnInfo, 1, 0) ///< Whether or not to use column information
+ ///< in debug info.
+
+CODEGENOPT(DebugTypeExtRefs, 1, 0) ///< Whether or not debug info should contain
+ ///< external references to a PCH or module.
+
+CODEGENOPT(DebugExplicitImport, 1, 0) ///< Whether or not debug info should
+ ///< contain explicit imports for
+ ///< anonymous namespaces
+
+CODEGENOPT(EmitLLVMUseLists, 1, 0) ///< Control whether to serialize use-lists.
+
+/// The user specified number of registers to be used for integral arguments,
+/// or 0 if unspecified.
+VALUE_CODEGENOPT(NumRegisterParameters, 32, 0)
+
+/// The lower bound for a buffer to be considered for stack protection.
+VALUE_CODEGENOPT(SSPBufferSize, 32, 0)
+
+/// The kind of generated debug info.
+ENUM_CODEGENOPT(DebugInfo, DebugInfoKind, 3, NoDebugInfo)
+
+/// Tune the debug info for this debugger.
+ENUM_CODEGENOPT(DebuggerTuning, DebuggerKind, 2, DebuggerKindDefault)
+
+/// Dwarf version. Version zero indicates to LLVM that no DWARF should be
+/// emitted.
+VALUE_CODEGENOPT(DwarfVersion, 3, 0)
+
+/// Whether we should emit CodeView debug information. It's possible to emit
+/// CodeView and DWARF into the same object.
+CODEGENOPT(EmitCodeView, 1, 0)
+
+/// The kind of inlining to perform.
+ENUM_CODEGENOPT(Inlining, InliningMethod, 2, NoInlining)
+
+// Vector functions library to use.
+ENUM_CODEGENOPT(VecLib, VectorLibrary, 1, NoLibrary)
+
+/// The default TLS model to use.
+ENUM_CODEGENOPT(DefaultTLSModel, TLSModel, 2, GeneralDynamicTLSModel)
+
+#undef CODEGENOPT
+#undef ENUM_CODEGENOPT
+#undef VALUE_CODEGENOPT
+
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..7550e6f
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Frontend/CodeGenOptions.h
@@ -0,0 +1,245 @@
+//===--- 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 "clang/Basic/Sanitizers.h"
+#include "llvm/Support/Regex.h"
+#include <map>
+#include <memory>
+#include <string>
+#include <vector>
+
+namespace clang {
+
+/// \brief Bitfields of CodeGenOptions, split out from CodeGenOptions to ensure
+/// that this large collection of bitfields is a trivial class type.
+class CodeGenOptionsBase {
+public:
+#define CODEGENOPT(Name, Bits, Default) unsigned Name : Bits;
+#define ENUM_CODEGENOPT(Name, Type, Bits, Default)
+#include "clang/Frontend/CodeGenOptions.def"
+
+protected:
+#define CODEGENOPT(Name, Bits, Default)
+#define ENUM_CODEGENOPT(Name, Type, Bits, Default) unsigned Name : Bits;
+#include "clang/Frontend/CodeGenOptions.def"
+};
+
+/// CodeGenOptions - Track various options which control how the code
+/// is optimized and passed to the backend.
+class CodeGenOptions : public CodeGenOptionsBase {
+public:
+ enum InliningMethod {
+ NoInlining, // Perform no inlining whatsoever.
+ NormalInlining, // Use the standard function inlining pass.
+ OnlyAlwaysInlining // Only run the always inlining pass.
+ };
+
+ enum VectorLibrary {
+ NoLibrary, // Don't use any vector library.
+ Accelerate // Use the Accelerate framework.
+ };
+
+ enum ObjCDispatchMethodKind {
+ Legacy = 0,
+ NonLegacy = 1,
+ Mixed = 2
+ };
+
+ enum DebugInfoKind {
+ NoDebugInfo, /// Don't generate debug info.
+
+ LocTrackingOnly, /// Emit location information but do not generate
+ /// debug info in the output. This is useful in
+ /// cases where the backend wants to track source
+ /// locations for instructions without actually
+ /// emitting debug info for them (e.g., when -Rpass
+ /// is used).
+
+ DebugLineTablesOnly, /// Emit only debug info necessary for generating
+ /// line number tables (-gline-tables-only).
+
+ LimitedDebugInfo, /// Limit generated debug info to reduce size
+ /// (-fno-standalone-debug). This emits
+ /// forward decls for types that could be
+ /// replaced with forward decls in the source
+ /// code. For dynamic C++ classes type info
+ /// is only emitted int the module that
+ /// contains the classe's vtable.
+
+ FullDebugInfo /// Generate complete debug info.
+ };
+
+ enum DebuggerKind {
+ DebuggerKindDefault,
+ DebuggerKindGDB,
+ DebuggerKindLLDB,
+ DebuggerKindSCE
+ };
+
+ enum TLSModel {
+ GeneralDynamicTLSModel,
+ LocalDynamicTLSModel,
+ InitialExecTLSModel,
+ LocalExecTLSModel
+ };
+
+ enum FPContractModeKind {
+ FPC_Off, // Form fused FP ops only where result will not be affected.
+ FPC_On, // Form fused FP ops according to FP_CONTRACT rules.
+ FPC_Fast // Aggressively fuse FP ops (E.g. FMA).
+ };
+
+ enum StructReturnConventionKind {
+ SRCK_Default, // No special option was passed.
+ SRCK_OnStack, // Small structs on the stack (-fpcc-struct-return).
+ SRCK_InRegs // Small structs in registers (-freg-struct-return).
+ };
+
+ /// The code model to use (-mcmodel).
+ std::string CodeModel;
+
+ /// The filename with path we use for coverage files. The extension will be
+ /// replaced.
+ std::string CoverageFile;
+
+ /// The version string to put into coverage files.
+ char CoverageVersion[4];
+
+ /// Enable additional debugging information.
+ std::string DebugPass;
+
+ /// The string to embed in debug information as the current working directory.
+ std::string DebugCompilationDir;
+
+ /// The string to embed in the debug information for the compile unit, if
+ /// non-empty.
+ std::string DwarfDebugFlags;
+
+ std::map<std::string, std::string> DebugPrefixMap;
+
+ /// 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 name of the bitcode file to link before optzns.
+ std::vector<std::pair<unsigned, std::string>> LinkBitcodeFiles;
+
+ /// 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 for the split debug info file that we'll break out. This is used
+ /// in the backend for setting the name in the skeleton cu.
+ std::string SplitDwarfFile;
+
+ /// The name of the relocation model to use.
+ std::string RelocationModel;
+
+ /// The thread model to use
+ std::string ThreadModel;
+
+ /// If not an empty string, trap intrinsics are lowered to calls to this
+ /// function instead of to trap instructions.
+ std::string TrapFuncName;
+
+ /// A list of command-line options to forward to the LLVM backend.
+ std::vector<std::string> BackendOptions;
+
+ /// A list of dependent libraries.
+ std::vector<std::string> DependentLibraries;
+
+ /// Name of the profile file to use as output for -fprofile-instr-generate
+ /// and -fprofile-generate.
+ std::string InstrProfileOutput;
+
+ /// Name of the profile file to use with -fprofile-sample-use.
+ std::string SampleProfileFile;
+
+ /// Name of the profile file to use as input for -fprofile-instr-use
+ std::string InstrProfileInput;
+
+ /// Name of the function summary index file to use for ThinLTO function
+ /// importing.
+ std::string ThinLTOIndexFile;
+
+ /// The EABI version to use
+ std::string EABIVersion;
+
+ /// A list of file names passed with -fcuda-include-gpubinary options to
+ /// forward to CUDA runtime back-end for incorporating them into host-side
+ /// object file.
+ std::vector<std::string> CudaGpuBinaryFileNames;
+
+ /// Regular expression to select optimizations for which we should enable
+ /// optimization remarks. Transformation passes whose name matches this
+ /// expression (and support this feature), will emit a diagnostic
+ /// whenever they perform a transformation. This is enabled by the
+ /// -Rpass=regexp flag.
+ std::shared_ptr<llvm::Regex> OptimizationRemarkPattern;
+
+ /// Regular expression to select optimizations for which we should enable
+ /// missed optimization remarks. Transformation passes whose name matches this
+ /// expression (and support this feature), will emit a diagnostic
+ /// whenever they tried but failed to perform a transformation. This is
+ /// enabled by the -Rpass-missed=regexp flag.
+ std::shared_ptr<llvm::Regex> OptimizationRemarkMissedPattern;
+
+ /// Regular expression to select optimizations for which we should enable
+ /// optimization analyses. Transformation passes whose name matches this
+ /// expression (and support this feature), will emit a diagnostic
+ /// whenever they want to explain why they decided to apply or not apply
+ /// a given transformation. This is enabled by the -Rpass-analysis=regexp
+ /// flag.
+ std::shared_ptr<llvm::Regex> OptimizationRemarkAnalysisPattern;
+
+ /// Set of files definining the rules for the symbol rewriting.
+ std::vector<std::string> RewriteMapFiles;
+
+ /// Set of sanitizer checks that are non-fatal (i.e. execution should be
+ /// continued when possible).
+ SanitizerSet SanitizeRecover;
+
+ /// Set of sanitizer checks that trap rather than diagnose.
+ SanitizerSet SanitizeTrap;
+
+ /// \brief A list of all -fno-builtin-* function names (e.g., memset).
+ std::vector<std::string> NoBuiltinFuncs;
+
+public:
+ // Define accessors/mutators for code generation options of enumeration type.
+#define CODEGENOPT(Name, Bits, Default)
+#define ENUM_CODEGENOPT(Name, Type, Bits, Default) \
+ Type get##Name() const { return static_cast<Type>(Name); } \
+ void set##Name(Type Value) { Name = static_cast<unsigned>(Value); }
+#include "clang/Frontend/CodeGenOptions.def"
+
+ CodeGenOptions();
+
+ /// \brief Is this a libc/libm function that is no longer recognized as a
+ /// builtin because a -fno-builtin-* option has been specified?
+ bool isNoBuiltinFunc(const char *Name) const;
+
+ const std::vector<std::string> &getNoBuiltinFuncs() const {
+ return NoBuiltinFuncs;
+ }
+};
+
+} // 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..a78c96d
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Frontend/CommandLineSourceLoc.h
@@ -0,0 +1,87 @@
+
+//===--- 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 "clang/Basic/LLVM.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(StringRef Str) {
+ ParsedSourceLocation PSL;
+ std::pair<StringRef, StringRef> ColSplit = Str.rsplit(':');
+ std::pair<StringRef, 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> final
+ : 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..83eed2c
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Frontend/CompilerInstance.h
@@ -0,0 +1,785 @@
+//===-- 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/AST/ASTConsumer.h"
+#include "clang/Frontend/PCHContainerOperations.h"
+#include "clang/Basic/Diagnostic.h"
+#include "clang/Basic/SourceManager.h"
+#include "clang/Frontend/CompilerInvocation.h"
+#include "clang/Frontend/Utils.h"
+#include "clang/Lex/ModuleLoader.h"
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/IntrusiveRefCntPtr.h"
+#include "llvm/ADT/StringRef.h"
+#include <cassert>
+#include <list>
+#include <memory>
+#include <string>
+#include <utility>
+
+namespace llvm {
+class raw_fd_ostream;
+class Timer;
+class TimerGroup;
+}
+
+namespace clang {
+class ASTContext;
+class ASTConsumer;
+class ASTReader;
+class CodeCompleteConsumer;
+class DiagnosticsEngine;
+class DiagnosticConsumer;
+class ExternalASTSource;
+class FileEntry;
+class FileManager;
+class FrontendAction;
+class Module;
+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 : public ModuleLoader {
+ /// The options used in this compiler instance.
+ IntrusiveRefCntPtr<CompilerInvocation> Invocation;
+
+ /// The diagnostics engine instance.
+ IntrusiveRefCntPtr<DiagnosticsEngine> Diagnostics;
+
+ /// The target being compiled for.
+ IntrusiveRefCntPtr<TargetInfo> Target;
+
+ /// Auxiliary Target info.
+ IntrusiveRefCntPtr<TargetInfo> AuxTarget;
+
+ /// The virtual file system.
+ IntrusiveRefCntPtr<vfs::FileSystem> VirtualFileSystem;
+
+ /// The file manager.
+ IntrusiveRefCntPtr<FileManager> FileMgr;
+
+ /// The source manager.
+ IntrusiveRefCntPtr<SourceManager> SourceMgr;
+
+ /// The preprocessor.
+ IntrusiveRefCntPtr<Preprocessor> PP;
+
+ /// The AST context.
+ IntrusiveRefCntPtr<ASTContext> Context;
+
+ /// The AST consumer.
+ std::unique_ptr<ASTConsumer> Consumer;
+
+ /// The code completion consumer.
+ std::unique_ptr<CodeCompleteConsumer> CompletionConsumer;
+
+ /// \brief The semantic analysis object.
+ std::unique_ptr<Sema> TheSema;
+
+ /// \brief The frontend timer group.
+ std::unique_ptr<llvm::TimerGroup> FrontendTimerGroup;
+
+ /// \brief The frontend timer.
+ std::unique_ptr<llvm::Timer> FrontendTimer;
+
+ /// \brief The ASTReader, if one exists.
+ IntrusiveRefCntPtr<ASTReader> ModuleManager;
+
+ /// \brief The module dependency collector for crashdumps
+ std::shared_ptr<ModuleDependencyCollector> ModuleDepCollector;
+
+ /// \brief The module provider.
+ std::shared_ptr<PCHContainerOperations> ThePCHContainerOperations;
+
+ /// \brief The dependency file generator.
+ std::unique_ptr<DependencyFileGenerator> TheDependencyFileGenerator;
+
+ std::vector<std::shared_ptr<DependencyCollector>> DependencyCollectors;
+
+ /// \brief The set of top-level modules that has already been loaded,
+ /// along with the module map
+ llvm::DenseMap<const IdentifierInfo *, Module *> KnownModules;
+
+ /// \brief The location of the module-import keyword for the last module
+ /// import.
+ SourceLocation LastModuleImportLoc;
+
+ /// \brief The result of the last module import.
+ ///
+ ModuleLoadResult LastModuleImportResult;
+
+ /// \brief Whether we should (re)build the global module index once we
+ /// have finished with this translation unit.
+ bool BuildGlobalModuleIndex;
+
+ /// \brief We have a full global module index, with all modules.
+ bool HaveFullGlobalModuleIndex;
+
+ /// \brief One or more modules failed to build.
+ bool ModuleBuildFailed;
+
+ /// \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;
+ std::unique_ptr<raw_ostream> OS;
+
+ OutputFile(std::string filename, std::string tempFilename,
+ std::unique_ptr<raw_ostream> OS)
+ : Filename(std::move(filename)), TempFilename(std::move(tempFilename)),
+ OS(std::move(OS)) {}
+ OutputFile(OutputFile &&O)
+ : Filename(std::move(O.Filename)),
+ TempFilename(std::move(O.TempFilename)), OS(std::move(O.OS)) {}
+ };
+
+ /// If the output doesn't support seeking (terminal, pipe). we switch
+ /// the stream to a buffer_ostream. These are the buffer and the original
+ /// stream.
+ std::unique_ptr<llvm::raw_fd_ostream> NonSeekStream;
+
+ /// The list of active output files.
+ std::list<OutputFile> OutputFiles;
+
+ CompilerInstance(const CompilerInstance &) = delete;
+ void operator=(const CompilerInstance &) = delete;
+public:
+ explicit CompilerInstance(
+ std::shared_ptr<PCHContainerOperations> PCHContainerOps =
+ std::make_shared<PCHContainerOperations>(),
+ bool BuildingModule = false);
+ ~CompilerInstance() override;
+
+ /// @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 != nullptr; }
+
+ CompilerInvocation &getInvocation() {
+ assert(Invocation && "Compiler instance has no invocation!");
+ return *Invocation;
+ }
+
+ /// setInvocation - Replace the current invocation.
+ void setInvocation(CompilerInvocation *Value);
+
+ /// \brief Indicates whether we should (re)build the global module index.
+ bool shouldBuildGlobalModuleIndex() const;
+
+ /// \brief Set the flag indicating whether we should (re)build the global
+ /// module index.
+ void setBuildGlobalModuleIndex(bool Build) {
+ BuildGlobalModuleIndex = Build;
+ }
+
+ /// }
+ /// @name Forwarding Methods
+ /// {
+
+ AnalyzerOptionsRef getAnalyzerOpts() {
+ 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();
+ }
+
+ FileSystemOptions &getFileSystemOpts() {
+ return Invocation->getFileSystemOpts();
+ }
+ 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 != nullptr; }
+
+ /// Get the current diagnostics engine.
+ DiagnosticsEngine &getDiagnostics() const {
+ assert(Diagnostics && "Compiler instance has no diagnostics!");
+ return *Diagnostics;
+ }
+
+ /// setDiagnostics - Replace the current diagnostics engine.
+ void setDiagnostics(DiagnosticsEngine *Value);
+
+ DiagnosticConsumer &getDiagnosticClient() const {
+ assert(Diagnostics && Diagnostics->getClient() &&
+ "Compiler instance has no diagnostic client!");
+ return *Diagnostics->getClient();
+ }
+
+ /// }
+ /// @name Target Info
+ /// {
+
+ bool hasTarget() const { return Target != nullptr; }
+
+ TargetInfo &getTarget() const {
+ assert(Target && "Compiler instance has no target!");
+ return *Target;
+ }
+
+ /// Replace the current Target.
+ void setTarget(TargetInfo *Value);
+
+ /// }
+ /// @name AuxTarget Info
+ /// {
+
+ TargetInfo *getAuxTarget() const { return AuxTarget.get(); }
+
+ /// Replace the current AuxTarget.
+ void setAuxTarget(TargetInfo *Value);
+
+ /// }
+ /// @name Virtual File System
+ /// {
+
+ bool hasVirtualFileSystem() const { return VirtualFileSystem != nullptr; }
+
+ vfs::FileSystem &getVirtualFileSystem() const {
+ assert(hasVirtualFileSystem() &&
+ "Compiler instance has no virtual file system");
+ return *VirtualFileSystem;
+ }
+
+ /// \brief Replace the current virtual file system.
+ ///
+ /// \note Most clients should use setFileManager, which will implicitly reset
+ /// the virtual file system to the one contained in the file manager.
+ void setVirtualFileSystem(IntrusiveRefCntPtr<vfs::FileSystem> FS) {
+ VirtualFileSystem = FS;
+ }
+
+ /// }
+ /// @name File Manager
+ /// {
+
+ bool hasFileManager() const { return FileMgr != nullptr; }
+
+ /// Return the current file manager to the caller.
+ FileManager &getFileManager() const {
+ assert(FileMgr && "Compiler instance has no file manager!");
+ return *FileMgr;
+ }
+
+ void resetAndLeakFileManager() {
+ BuryPointer(FileMgr.get());
+ FileMgr.resetWithoutRelease();
+ }
+
+ /// \brief Replace the current file manager and virtual file system.
+ void setFileManager(FileManager *Value);
+
+ /// }
+ /// @name Source Manager
+ /// {
+
+ bool hasSourceManager() const { return SourceMgr != nullptr; }
+
+ /// Return the current source manager.
+ SourceManager &getSourceManager() const {
+ assert(SourceMgr && "Compiler instance has no source manager!");
+ return *SourceMgr;
+ }
+
+ void resetAndLeakSourceManager() {
+ BuryPointer(SourceMgr.get());
+ SourceMgr.resetWithoutRelease();
+ }
+
+ /// setSourceManager - Replace the current source manager.
+ void setSourceManager(SourceManager *Value);
+
+ /// }
+ /// @name Preprocessor
+ /// {
+
+ bool hasPreprocessor() const { return PP != nullptr; }
+
+ /// Return the current preprocessor.
+ Preprocessor &getPreprocessor() const {
+ assert(PP && "Compiler instance has no preprocessor!");
+ return *PP;
+ }
+
+ void resetAndLeakPreprocessor() {
+ BuryPointer(PP.get());
+ PP.resetWithoutRelease();
+ }
+
+ /// Replace the current preprocessor.
+ void setPreprocessor(Preprocessor *Value);
+
+ /// }
+ /// @name ASTContext
+ /// {
+
+ bool hasASTContext() const { return Context != nullptr; }
+
+ ASTContext &getASTContext() const {
+ assert(Context && "Compiler instance has no AST context!");
+ return *Context;
+ }
+
+ void resetAndLeakASTContext() {
+ BuryPointer(Context.get());
+ Context.resetWithoutRelease();
+ }
+
+ /// setASTContext - Replace the current AST context.
+ 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 (bool)Consumer; }
+
+ 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.
+ std::unique_ptr<ASTConsumer> takeASTConsumer() { return std::move(Consumer); }
+
+ /// setASTConsumer - Replace the current AST consumer; the compiler instance
+ /// takes ownership of \p Value.
+ void setASTConsumer(std::unique_ptr<ASTConsumer> Value);
+
+ /// }
+ /// @name Semantic analysis
+ /// {
+ bool hasSema() const { return (bool)TheSema; }
+
+ Sema &getSema() const {
+ assert(TheSema && "Compiler instance has no Sema object!");
+ return *TheSema;
+ }
+
+ std::unique_ptr<Sema> takeSema();
+ void resetAndLeakSema();
+
+ /// }
+ /// @name Module Management
+ /// {
+
+ IntrusiveRefCntPtr<ASTReader> getModuleManager() const;
+ void setModuleManager(IntrusiveRefCntPtr<ASTReader> Reader);
+
+ std::shared_ptr<ModuleDependencyCollector> getModuleDepCollector() const;
+ void setModuleDepCollector(
+ std::shared_ptr<ModuleDependencyCollector> Collector);
+
+ std::shared_ptr<PCHContainerOperations> getPCHContainerOperations() const {
+ return ThePCHContainerOperations;
+ }
+
+ /// Return the appropriate PCHContainerWriter depending on the
+ /// current CodeGenOptions.
+ const PCHContainerWriter &getPCHContainerWriter() const {
+ assert(Invocation && "cannot determine module format without invocation");
+ StringRef Format = getHeaderSearchOpts().ModuleFormat;
+ auto *Writer = ThePCHContainerOperations->getWriterOrNull(Format);
+ if (!Writer) {
+ if (Diagnostics)
+ Diagnostics->Report(diag::err_module_format_unhandled) << Format;
+ llvm::report_fatal_error("unknown module format");
+ }
+ return *Writer;
+ }
+
+ /// Return the appropriate PCHContainerReader depending on the
+ /// current CodeGenOptions.
+ const PCHContainerReader &getPCHContainerReader() const {
+ assert(Invocation && "cannot determine module format without invocation");
+ StringRef Format = getHeaderSearchOpts().ModuleFormat;
+ auto *Reader = ThePCHContainerOperations->getReaderOrNull(Format);
+ if (!Reader) {
+ if (Diagnostics)
+ Diagnostics->Report(diag::err_module_format_unhandled) << Format;
+ llvm::report_fatal_error("unknown module format");
+ }
+ return *Reader;
+ }
+
+ /// }
+ /// @name Code Completion
+ /// {
+
+ bool hasCodeCompletionConsumer() const { return (bool)CompletionConsumer; }
+
+ CodeCompleteConsumer &getCodeCompletionConsumer() const {
+ assert(CompletionConsumer &&
+ "Compiler instance has no code completion consumer!");
+ return *CompletionConsumer;
+ }
+
+ /// setCodeCompletionConsumer - Replace the current code completion consumer;
+ /// the compiler instance takes ownership of \p Value.
+ void setCodeCompletionConsumer(CodeCompleteConsumer *Value);
+
+ /// }
+ /// @name Frontend timer
+ /// {
+
+ bool hasFrontendTimer() const { return (bool)FrontendTimer; }
+
+ 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(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 DiagnosticsEngine inside this AST
+ /// unit.
+ ///
+ /// \param ShouldOwnClient If Client is non-NULL, specifies whether
+ /// the diagnostic object should take ownership of the client.
+ void createDiagnostics(DiagnosticConsumer *Client = nullptr,
+ bool ShouldOwnClient = true);
+
+ /// Create a DiagnosticsEngine object with a the TextDiagnosticPrinter.
+ ///
+ /// If no diagnostic client is provided, this creates a
+ /// DiagnosticConsumer that is owned by the returned diagnostic
+ /// object, if using directly the caller is responsible for
+ /// releasing the returned DiagnosticsEngine's client eventually.
+ ///
+ /// \param Opts - The diagnostic options; note that the created text
+ /// diagnostic object contains a reference to these options.
+ ///
+ /// \param Client If non-NULL, a diagnostic client that will be
+ /// attached to (and, then, owned by) the returned DiagnosticsEngine
+ /// object.
+ ///
+ /// \param CodeGenOpts If non-NULL, the code gen options in use, which may be
+ /// used by some diagnostics printers (for logging purposes only).
+ ///
+ /// \return The new object on success, or null on failure.
+ static IntrusiveRefCntPtr<DiagnosticsEngine>
+ createDiagnostics(DiagnosticOptions *Opts,
+ DiagnosticConsumer *Client = nullptr,
+ bool ShouldOwnClient = true,
+ const CodeGenOptions *CodeGenOpts = nullptr);
+
+ /// 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(TranslationUnitKind TUKind);
+
+ std::string getSpecificModuleCachePath();
+
+ /// 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(StringRef Path, bool DisablePCHValidation,
+ bool AllowPCHWithCompilerErrors,
+ void *DeserializationListener,
+ bool OwnDeserializationListener);
+
+ /// Create an external AST source to read a PCH file.
+ ///
+ /// \return - The new object on success, or null on failure.
+ static IntrusiveRefCntPtr<ASTReader> createPCHExternalASTSource(
+ StringRef Path, StringRef Sysroot, bool DisablePCHValidation,
+ bool AllowPCHWithCompilerErrors, Preprocessor &PP, ASTContext &Context,
+ const PCHContainerReader &PCHContainerRdr,
+ ArrayRef<IntrusiveRefCntPtr<ModuleFileExtension>> Extensions,
+ void *DeserializationListener, bool OwnDeserializationListener,
+ bool Preamble, bool UseGlobalModuleIndex);
+
+ /// 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
+ /// \p Filename, \p Line, and \p Column, to the given output stream \p OS.
+ static CodeCompleteConsumer *createCodeCompletionConsumer(
+ Preprocessor &PP, StringRef Filename, unsigned Line, unsigned Column,
+ const CodeCompleteOptions &Opts, raw_ostream &OS);
+
+ /// \brief Create the Sema object to be used for parsing.
+ void createSema(TranslationUnitKind TUKind,
+ 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.
+ ///
+ /// The files created by this function always use temporary files to write to
+ /// their result (that is, the data is written to a temporary file which will
+ /// atomically replace the target output on success).
+ ///
+ /// \return - Null on error.
+ raw_pwrite_stream *createDefaultOutputFile(bool Binary = true,
+ StringRef BaseInput = "",
+ 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.
+ raw_pwrite_stream *createOutputFile(StringRef OutputPath, bool Binary,
+ bool RemoveFileOnSignal,
+ StringRef BaseInput, StringRef Extension,
+ bool UseTemporary,
+ bool CreateMissingDirectories = false);
+
+ /// Create a new output file, optionally deriving the output path name.
+ ///
+ /// If \p OutputPath is empty, then createOutputFile will derive an output
+ /// path location as \p BaseInput, with any suffix removed, and \p Extension
+ /// appended. If \p OutputPath is not stdout and \p UseTemporary
+ /// is true, createOutputFile will create a new temporary file that must be
+ /// renamed to \p OutputPath in the end.
+ ///
+ /// \param OutputPath - If given, the path to the output file.
+ /// \param Error [out] - On failure, the error.
+ /// \param BaseInput - If \p 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 UseTemporary - Create a new temporary file that must be renamed to
+ /// OutputPath in the end.
+ /// \param CreateMissingDirectories - When \p UseTemporary is true, create
+ /// missing directories in the output path.
+ /// \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.
+ std::unique_ptr<raw_pwrite_stream>
+ createOutputFile(StringRef OutputPath, std::error_code &Error, bool Binary,
+ bool RemoveFileOnSignal, StringRef BaseInput,
+ StringRef Extension, bool UseTemporary,
+ bool CreateMissingDirectories, std::string *ResultPathName,
+ std::string *TempPathName);
+
+ llvm::raw_null_ostream *createNullOutputFile();
+
+ /// }
+ /// @name Initialization Utility Methods
+ /// {
+
+ /// InitializeSourceManager - Initialize the source manager to set InputFile
+ /// as the main file.
+ ///
+ /// \return True on success.
+ bool InitializeSourceManager(const FrontendInputFile &Input);
+
+ /// InitializeSourceManager - Initialize the source manager to set InputFile
+ /// as the main file.
+ ///
+ /// \return True on success.
+ static bool InitializeSourceManager(const FrontendInputFile &Input,
+ DiagnosticsEngine &Diags,
+ FileManager &FileMgr,
+ SourceManager &SourceMgr,
+ const FrontendOptions &Opts);
+
+ /// }
+
+ // Create module manager.
+ void createModuleManager();
+
+ bool loadModuleFile(StringRef FileName);
+
+ ModuleLoadResult loadModule(SourceLocation ImportLoc, ModuleIdPath Path,
+ Module::NameVisibilityKind Visibility,
+ bool IsInclusionDirective) override;
+
+ void makeModuleVisible(Module *Mod, Module::NameVisibilityKind Visibility,
+ SourceLocation ImportLoc) override;
+
+ bool hadModuleLoaderFatalFailure() const {
+ return ModuleLoader::HadFatalFailure;
+ }
+
+ GlobalModuleIndex *loadGlobalModuleIndex(SourceLocation TriggerLoc) override;
+
+ bool lookupMissingImports(StringRef Name, SourceLocation TriggerLoc) override;
+
+ void addDependencyCollector(std::shared_ptr<DependencyCollector> Listener) {
+ DependencyCollectors.push_back(std::move(Listener));
+ }
+};
+
+} // 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..0b4a1e5
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Frontend/CompilerInvocation.h
@@ -0,0 +1,219 @@
+//===-- 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/DiagnosticOptions.h"
+#include "clang/Basic/FileSystemOptions.h"
+#include "clang/Basic/LangOptions.h"
+#include "clang/Basic/TargetOptions.h"
+#include "clang/Frontend/CodeGenOptions.h"
+#include "clang/Frontend/DependencyOutputOptions.h"
+#include "clang/Frontend/FrontendOptions.h"
+#include "clang/Frontend/LangStandard.h"
+#include "clang/Frontend/MigratorOptions.h"
+#include "clang/Frontend/PreprocessorOutputOptions.h"
+#include "clang/Lex/HeaderSearchOptions.h"
+#include "clang/Lex/PreprocessorOptions.h"
+#include "clang/StaticAnalyzer/Core/AnalyzerOptions.h"
+#include "llvm/ADT/IntrusiveRefCntPtr.h"
+#include "llvm/ADT/StringMap.h"
+#include "llvm/ADT/StringRef.h"
+#include <string>
+#include <vector>
+
+namespace llvm {
+namespace opt {
+class ArgList;
+}
+}
+
+namespace clang {
+class CompilerInvocation;
+class DiagnosticsEngine;
+
+/// \brief Fill out Opts based on the options given in Args.
+///
+/// Args must have been created from the OptTable returned by
+/// createCC1OptTable().
+///
+/// When errors are encountered, return false and, if Diags is non-null,
+/// report the error(s).
+bool ParseDiagnosticArgs(DiagnosticOptions &Opts, llvm::opt::ArgList &Args,
+ DiagnosticsEngine *Diags = nullptr);
+
+class CompilerInvocationBase : public RefCountedBase<CompilerInvocation> {
+ void operator=(const CompilerInvocationBase &) = delete;
+
+public:
+ /// Options controlling the language variant.
+ std::shared_ptr<LangOptions> LangOpts;
+
+ /// Options controlling the target.
+ std::shared_ptr<TargetOptions> TargetOpts;
+
+ /// Options controlling the diagnostic engine.
+ IntrusiveRefCntPtr<DiagnosticOptions> DiagnosticOpts;
+
+ /// Options controlling the \#include directive.
+ IntrusiveRefCntPtr<HeaderSearchOptions> HeaderSearchOpts;
+
+ /// Options controlling the preprocessor (aside from \#include handling).
+ IntrusiveRefCntPtr<PreprocessorOptions> PreprocessorOpts;
+
+ CompilerInvocationBase();
+ ~CompilerInvocationBase();
+
+ CompilerInvocationBase(const CompilerInvocationBase &X);
+
+ LangOptions *getLangOpts() { return LangOpts.get(); }
+ const LangOptions *getLangOpts() const { return LangOpts.get(); }
+
+ TargetOptions &getTargetOpts() { return *TargetOpts.get(); }
+ const TargetOptions &getTargetOpts() const {
+ return *TargetOpts.get();
+ }
+
+ DiagnosticOptions &getDiagnosticOpts() const { return *DiagnosticOpts; }
+
+ HeaderSearchOptions &getHeaderSearchOpts() { return *HeaderSearchOpts; }
+ const HeaderSearchOptions &getHeaderSearchOpts() const {
+ return *HeaderSearchOpts;
+ }
+
+ PreprocessorOptions &getPreprocessorOpts() { return *PreprocessorOpts; }
+ const PreprocessorOptions &getPreprocessorOpts() const {
+ return *PreprocessorOpts;
+ }
+};
+
+/// \brief 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 : public CompilerInvocationBase {
+ /// Options controlling the static analyzer.
+ AnalyzerOptionsRef AnalyzerOpts;
+
+ MigratorOptions MigratorOpts;
+
+ /// Options controlling IRgen and the backend.
+ CodeGenOptions CodeGenOpts;
+
+ /// Options controlling dependency output.
+ DependencyOutputOptions DependencyOutputOpts;
+
+ /// Options controlling file system operations.
+ FileSystemOptions FileSystemOpts;
+
+ /// Options controlling the frontend itself.
+ FrontendOptions FrontendOpts;
+
+ /// Options controlling preprocessed output.
+ PreprocessorOutputOptions PreprocessorOutputOpts;
+
+public:
+ CompilerInvocation() : AnalyzerOpts(new AnalyzerOptions()) {}
+
+ /// @name Utility Methods
+ /// @{
+
+ /// \brief Create a compiler invocation from a list of input options.
+ /// \returns true on success.
+ ///
+ /// \param [out] Res - 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 bool CreateFromArgs(CompilerInvocation &Res,
+ const char* const *ArgBegin,
+ const char* const *ArgEnd,
+ DiagnosticsEngine &Diags);
+
+ /// \brief 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);
+
+ /// \brief Set language defaults for the given input language and
+ /// language standard in the given LangOptions object.
+ ///
+ /// \param Opts - 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);
+
+ /// \brief Retrieve a module hash string that is suitable for uniquely
+ /// identifying the conditions under which the module was built.
+ std::string getModuleHash() const;
+
+ /// @}
+ /// @name Option Subgroups
+ /// @{
+
+ AnalyzerOptionsRef getAnalyzerOpts() const {
+ return AnalyzerOpts;
+ }
+
+ MigratorOptions &getMigratorOpts() { return MigratorOpts; }
+ const MigratorOptions &getMigratorOpts() const {
+ return MigratorOpts;
+ }
+
+ CodeGenOptions &getCodeGenOpts() { return CodeGenOpts; }
+ const CodeGenOptions &getCodeGenOpts() const {
+ return CodeGenOpts;
+ }
+
+ DependencyOutputOptions &getDependencyOutputOpts() {
+ return DependencyOutputOpts;
+ }
+ const DependencyOutputOptions &getDependencyOutputOpts() const {
+ return DependencyOutputOpts;
+ }
+
+ FileSystemOptions &getFileSystemOpts() { return FileSystemOpts; }
+ const FileSystemOptions &getFileSystemOpts() const {
+ return FileSystemOpts;
+ }
+
+ FrontendOptions &getFrontendOpts() { return FrontendOpts; }
+ const FrontendOptions &getFrontendOpts() const {
+ return FrontendOpts;
+ }
+
+ PreprocessorOutputOptions &getPreprocessorOutputOpts() {
+ return PreprocessorOutputOpts;
+ }
+ const PreprocessorOutputOptions &getPreprocessorOutputOpts() const {
+ return PreprocessorOutputOpts;
+ }
+
+ /// @}
+};
+
+namespace vfs {
+ class FileSystem;
+}
+
+IntrusiveRefCntPtr<vfs::FileSystem>
+createVFSFromCompilerInvocation(const CompilerInvocation &CI,
+ DiagnosticsEngine &Diags);
+
+} // end namespace clang
+
+#endif
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..129b534
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Frontend/DependencyOutputOptions.h
@@ -0,0 +1,73 @@
+//===--- 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 {
+
+/// DependencyOutputFormat - Format for the compiler dependency file.
+enum class DependencyOutputFormat { Make, NMake };
+
+/// 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.
+ unsigned AddMissingHeaderDeps : 1; ///< Add missing headers to dependency list
+ unsigned PrintShowIncludes : 1; ///< Print cl.exe style /showIncludes info.
+ unsigned IncludeModuleFiles : 1; ///< Include module file dependencies.
+
+ /// The format for the dependency file.
+ DependencyOutputFormat OutputFormat;
+
+ /// 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;
+
+ /// A list of filenames to be used as extra dependencies for every target.
+ std::vector<std::string> ExtraDeps;
+
+ /// \brief The file to write GraphViz-formatted header dependencies to.
+ std::string DOTOutputFile;
+
+ /// \brief The directory to copy module dependencies to when collecting them.
+ std::string ModuleDependencyOutputDir;
+
+public:
+ DependencyOutputOptions() {
+ IncludeSystemHeaders = 0;
+ ShowHeaderIncludes = 0;
+ UsePhonyTargets = 0;
+ AddMissingHeaderDeps = 0;
+ PrintShowIncludes = 0;
+ IncludeModuleFiles = 0;
+ OutputFormat = DependencyOutputFormat::Make;
+ }
+};
+
+} // end namespace clang
+
+#endif
diff --git a/contrib/llvm/tools/clang/include/clang/Frontend/DiagnosticRenderer.h b/contrib/llvm/tools/clang/include/clang/Frontend/DiagnosticRenderer.h
new file mode 100644
index 0000000..c372fdd
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Frontend/DiagnosticRenderer.h
@@ -0,0 +1,178 @@
+//===--- DiagnosticRenderer.h - Diagnostic Pretty-Printing ------*- 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 utility class that provides support for pretty-printing of
+// diagnostics. It is used to implement the different code paths which require
+// such functionality in a consistent way.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_FRONTEND_DIAGNOSTICRENDERER_H
+#define LLVM_CLANG_FRONTEND_DIAGNOSTICRENDERER_H
+
+#include "clang/Basic/Diagnostic.h"
+#include "clang/Basic/LLVM.h"
+#include "clang/Basic/SourceLocation.h"
+#include "llvm/ADT/Optional.h"
+#include "llvm/ADT/PointerUnion.h"
+
+namespace clang {
+
+class DiagnosticOptions;
+class LangOptions;
+class SourceManager;
+
+typedef llvm::PointerUnion<const Diagnostic *,
+ const StoredDiagnostic *> DiagOrStoredDiag;
+
+/// \brief Class to encapsulate the logic for formatting a diagnostic message.
+///
+/// Actual "printing" logic is implemented by subclasses.
+///
+/// This class provides an interface for building and emitting
+/// diagnostic, including all of the macro backtraces, caret diagnostics, FixIt
+/// Hints, and code snippets. In the presence of macros this involves
+/// a recursive process, synthesizing notes for each macro expansion.
+///
+/// A brief worklist:
+/// FIXME: Sink the recursive printing of template instantiations into this
+/// class.
+class DiagnosticRenderer {
+protected:
+ const LangOptions &LangOpts;
+ IntrusiveRefCntPtr<DiagnosticOptions> DiagOpts;
+
+ /// \brief The location of the previous diagnostic if known.
+ ///
+ /// This will be invalid in cases where there is no (known) previous
+ /// diagnostic location, or that location itself is invalid or comes from
+ /// a different source manager than SM.
+ SourceLocation LastLoc;
+
+ /// \brief The location of the last include whose stack was printed if known.
+ ///
+ /// Same restriction as LastLoc essentially, but tracking include stack
+ /// root locations rather than diagnostic locations.
+ SourceLocation LastIncludeLoc;
+
+ /// \brief The level of the last diagnostic emitted.
+ ///
+ /// The level of the last diagnostic emitted. Used to detect level changes
+ /// which change the amount of information displayed.
+ DiagnosticsEngine::Level LastLevel;
+
+ DiagnosticRenderer(const LangOptions &LangOpts,
+ DiagnosticOptions *DiagOpts);
+
+ virtual ~DiagnosticRenderer();
+
+ virtual void emitDiagnosticMessage(SourceLocation Loc, PresumedLoc PLoc,
+ DiagnosticsEngine::Level Level,
+ StringRef Message,
+ ArrayRef<CharSourceRange> Ranges,
+ const SourceManager *SM,
+ DiagOrStoredDiag Info) = 0;
+
+ virtual void emitDiagnosticLoc(SourceLocation Loc, PresumedLoc PLoc,
+ DiagnosticsEngine::Level Level,
+ ArrayRef<CharSourceRange> Ranges,
+ const SourceManager &SM) = 0;
+
+ virtual void emitCodeContext(SourceLocation Loc,
+ DiagnosticsEngine::Level Level,
+ SmallVectorImpl<CharSourceRange>& Ranges,
+ ArrayRef<FixItHint> Hints,
+ const SourceManager &SM) = 0;
+
+ virtual void emitIncludeLocation(SourceLocation Loc, PresumedLoc PLoc,
+ const SourceManager &SM) = 0;
+ virtual void emitImportLocation(SourceLocation Loc, PresumedLoc PLoc,
+ StringRef ModuleName,
+ const SourceManager &SM) = 0;
+ virtual void emitBuildingModuleLocation(SourceLocation Loc, PresumedLoc PLoc,
+ StringRef ModuleName,
+ const SourceManager &SM) = 0;
+
+ virtual void beginDiagnostic(DiagOrStoredDiag D,
+ DiagnosticsEngine::Level Level) {}
+ virtual void endDiagnostic(DiagOrStoredDiag D,
+ DiagnosticsEngine::Level Level) {}
+
+
+private:
+ void emitBasicNote(StringRef Message);
+ void emitIncludeStack(SourceLocation Loc, PresumedLoc PLoc,
+ DiagnosticsEngine::Level Level, const SourceManager &SM);
+ void emitIncludeStackRecursively(SourceLocation Loc, const SourceManager &SM);
+ void emitImportStack(SourceLocation Loc, const SourceManager &SM);
+ void emitImportStackRecursively(SourceLocation Loc, StringRef ModuleName,
+ const SourceManager &SM);
+ void emitModuleBuildStack(const SourceManager &SM);
+ void emitCaret(SourceLocation Loc, DiagnosticsEngine::Level Level,
+ ArrayRef<CharSourceRange> Ranges, ArrayRef<FixItHint> Hints,
+ const SourceManager &SM);
+ void emitSingleMacroExpansion(SourceLocation Loc,
+ DiagnosticsEngine::Level Level,
+ ArrayRef<CharSourceRange> Ranges,
+ const SourceManager &SM);
+ void emitMacroExpansions(SourceLocation Loc,
+ DiagnosticsEngine::Level Level,
+ ArrayRef<CharSourceRange> Ranges,
+ ArrayRef<FixItHint> Hints,
+ const SourceManager &SM);
+public:
+ /// \brief Emit a diagnostic.
+ ///
+ /// This is the primary entry point for emitting diagnostic messages.
+ /// It handles formatting and rendering the message as well as any ancillary
+ /// information needed based on macros whose expansions impact the
+ /// diagnostic.
+ ///
+ /// \param Loc The location for this caret.
+ /// \param Level The level of the diagnostic to be emitted.
+ /// \param Message The diagnostic message to emit.
+ /// \param Ranges The underlined ranges for this code snippet.
+ /// \param FixItHints The FixIt hints active for this diagnostic.
+ /// \param SM The SourceManager; will be null if the diagnostic came from the
+ /// frontend, thus \p Loc will be invalid.
+ void emitDiagnostic(SourceLocation Loc, DiagnosticsEngine::Level Level,
+ StringRef Message, ArrayRef<CharSourceRange> Ranges,
+ ArrayRef<FixItHint> FixItHints,
+ const SourceManager *SM,
+ DiagOrStoredDiag D = (Diagnostic *)nullptr);
+
+ void emitStoredDiagnostic(StoredDiagnostic &Diag);
+};
+
+/// Subclass of DiagnosticRender that turns all subdiagostics into explicit
+/// notes. It is up to subclasses to further define the behavior.
+class DiagnosticNoteRenderer : public DiagnosticRenderer {
+public:
+ DiagnosticNoteRenderer(const LangOptions &LangOpts,
+ DiagnosticOptions *DiagOpts)
+ : DiagnosticRenderer(LangOpts, DiagOpts) {}
+
+ ~DiagnosticNoteRenderer() override;
+
+ void emitIncludeLocation(SourceLocation Loc, PresumedLoc PLoc,
+ const SourceManager &SM) override;
+
+ void emitImportLocation(SourceLocation Loc, PresumedLoc PLoc,
+ StringRef ModuleName,
+ const SourceManager &SM) override;
+
+ void emitBuildingModuleLocation(SourceLocation Loc, PresumedLoc PLoc,
+ StringRef ModuleName,
+ const SourceManager &SM) override;
+
+ virtual void emitNote(SourceLocation Loc, StringRef Message,
+ const SourceManager *SM) = 0;
+};
+} // end clang namespace
+#endif
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..c407ff8
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Frontend/FrontendAction.h
@@ -0,0 +1,298 @@
+//===-- 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.
+//
+//===----------------------------------------------------------------------===//
+///
+/// \file
+/// \brief Defines the clang::FrontendAction interface and various convenience
+/// abstract classes (clang::ASTFrontendAction, clang::PluginASTAction,
+/// clang::PreprocessorFrontendAction, and clang::WrapperFrontendAction)
+/// derived from it.
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_FRONTEND_FRONTENDACTION_H
+#define LLVM_CLANG_FRONTEND_FRONTENDACTION_H
+
+#include "clang/AST/ASTConsumer.h"
+#include "clang/Basic/LLVM.h"
+#include "clang/Basic/LangOptions.h"
+#include "clang/Frontend/ASTUnit.h"
+#include "clang/Frontend/FrontendOptions.h"
+#include "llvm/ADT/StringRef.h"
+#include <memory>
+#include <string>
+#include <vector>
+
+namespace clang {
+class ASTMergeAction;
+class CompilerInstance;
+
+/// Abstract base class for actions which can be performed by the frontend.
+class FrontendAction {
+ FrontendInputFile CurrentInput;
+ std::unique_ptr<ASTUnit> CurrentASTUnit;
+ CompilerInstance *Instance;
+ friend class ASTMergeAction;
+ friend class WrapperFrontendAction;
+
+private:
+ std::unique_ptr<ASTConsumer> CreateWrappedASTConsumer(CompilerInstance &CI,
+ StringRef InFile);
+
+protected:
+ /// @name Implementation Action Interface
+ /// @{
+
+ /// \brief Create the AST consumer object for this action, if supported.
+ ///
+ /// This routine is called as part of BeginSourceFile(), 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 null on failure.
+ virtual std::unique_ptr<ASTConsumer> CreateASTConsumer(CompilerInstance &CI,
+ StringRef InFile) = 0;
+
+ /// \brief Callback before starting processing a single input, giving the
+ /// opportunity to modify the CompilerInvocation or do some other action
+ /// before BeginSourceFileAction is called.
+ ///
+ /// \return True on success; on failure BeginSourceFileAction(),
+ /// ExecuteAction() and EndSourceFileAction() will not be called.
+ virtual bool BeginInvocation(CompilerInstance &CI) { return true; }
+
+ /// \brief Callback at the start of processing a single input.
+ ///
+ /// \return True on success; on failure ExecutionAction() and
+ /// EndSourceFileAction() will not be called.
+ virtual bool BeginSourceFileAction(CompilerInstance &CI,
+ StringRef Filename) {
+ return true;
+ }
+
+ /// \brief Callback to run the program action, using the initialized
+ /// compiler instance.
+ ///
+ /// This is guaranteed to only be called between BeginSourceFileAction()
+ /// and EndSourceFileAction().
+ virtual void ExecuteAction() = 0;
+
+ /// \brief Callback at the end of processing a single input.
+ ///
+ /// This is guaranteed to only be called following a successful call to
+ /// BeginSourceFileAction (and BeginSourceFile).
+ virtual void EndSourceFileAction() {}
+
+ /// \brief Callback at the end of processing a single input, to determine
+ /// if the output files should be erased or not.
+ ///
+ /// By default it returns true if a compiler error occurred.
+ /// This is guaranteed to only be called following a successful call to
+ /// BeginSourceFileAction (and BeginSourceFile).
+ virtual bool shouldEraseOutputFiles();
+
+ /// @}
+
+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(!CurrentInput.isEmpty() && "No current file!");
+ return (bool)CurrentASTUnit;
+ }
+
+ const FrontendInputFile &getCurrentInput() const {
+ return CurrentInput;
+ }
+
+ const StringRef getCurrentFile() const {
+ assert(!CurrentInput.isEmpty() && "No current file!");
+ return CurrentInput.getFile();
+ }
+
+ InputKind getCurrentFileKind() const {
+ assert(!CurrentInput.isEmpty() && "No current file!");
+ return CurrentInput.getKind();
+ }
+
+ ASTUnit &getCurrentASTUnit() const {
+ assert(CurrentASTUnit && "No current AST unit!");
+ return *CurrentASTUnit;
+ }
+
+ std::unique_ptr<ASTUnit> takeCurrentASTUnit() {
+ return std::move(CurrentASTUnit);
+ }
+
+ void setCurrentInput(const FrontendInputFile &CurrentInput,
+ std::unique_ptr<ASTUnit> AST = nullptr);
+
+ /// @}
+ /// @name Supported Modes
+ /// @{
+
+ /// \brief Is this action invoked on a model file?
+ ///
+ /// Model files are incomplete translation units that relies on type
+ /// information from another translation unit. Check ParseModelFileAction for
+ /// details.
+ virtual bool isModelParsingAction() const { return false; }
+
+ /// \brief 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;
+
+ /// \brief For AST-based actions, the kind of translation unit we're handling.
+ virtual TranslationUnitKind getTranslationUnitKind() { return TU_Complete; }
+
+ /// \brief Does this action support use with PCH?
+ virtual bool hasPCHSupport() const { return !usesPreprocessorOnly(); }
+
+ /// \brief Does this action support use with AST files?
+ virtual bool hasASTFileSupport() const { return !usesPreprocessorOnly(); }
+
+ /// \brief Does this action support use with IR files?
+ virtual bool hasIRSupport() const { return false; }
+
+ /// \brief Does this action support use with code completion?
+ virtual bool hasCodeCompletionSupport() const { return false; }
+
+ /// @}
+ /// @name Public Action Interface
+ /// @{
+
+ /// \brief Prepare the action for processing the input file \p Input.
+ ///
+ /// 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 Input - The input filename and kind. 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
+ /// BeginSourceFile() and EndSourceFile().
+ ///
+ /// \return True on success; on failure the compilation of this file should
+ /// be aborted and neither Execute() nor EndSourceFile() should be called.
+ bool BeginSourceFile(CompilerInstance &CI, const FrontendInputFile &Input);
+
+ /// \brief Set the source manager's main input file, and run the action.
+ bool Execute();
+
+ /// \brief Perform any per-file post processing, deallocate per-file
+ /// objects, and run statistics and output file cleanup code.
+ void EndSourceFile();
+
+ /// @}
+};
+
+/// \brief Abstract base class to use for AST consumer-based frontend actions.
+class ASTFrontendAction : public FrontendAction {
+protected:
+ /// \brief 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.
+ void ExecuteAction() override;
+
+public:
+ ASTFrontendAction() {}
+ bool usesPreprocessorOnly() const override { return false; }
+};
+
+class PluginASTAction : public ASTFrontendAction {
+ virtual void anchor();
+public:
+ std::unique_ptr<ASTConsumer> CreateASTConsumer(CompilerInstance &CI,
+ StringRef InFile) override = 0;
+
+ /// \brief 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;
+};
+
+/// \brief Abstract base class to use for preprocessor-based frontend actions.
+class PreprocessorFrontendAction : public FrontendAction {
+protected:
+ /// \brief Provide a default implementation which returns aborts;
+ /// this method should never be called by FrontendAction clients.
+ std::unique_ptr<ASTConsumer> CreateASTConsumer(CompilerInstance &CI,
+ StringRef InFile) override;
+
+public:
+ bool usesPreprocessorOnly() const override { return true; }
+};
+
+/// \brief A frontend action which simply wraps some other runtime-specified
+/// frontend action.
+///
+/// Deriving from this class allows an action to inject custom logic around
+/// some existing action's behavior. It implements every virtual method in
+/// the FrontendAction interface by forwarding to the wrapped action.
+class WrapperFrontendAction : public FrontendAction {
+ std::unique_ptr<FrontendAction> WrappedAction;
+
+protected:
+ std::unique_ptr<ASTConsumer> CreateASTConsumer(CompilerInstance &CI,
+ StringRef InFile) override;
+ bool BeginInvocation(CompilerInstance &CI) override;
+ bool BeginSourceFileAction(CompilerInstance &CI, StringRef Filename) override;
+ void ExecuteAction() override;
+ void EndSourceFileAction() override;
+
+public:
+ /// Construct a WrapperFrontendAction from an existing action, taking
+ /// ownership of it.
+ WrapperFrontendAction(FrontendAction *WrappedAction);
+
+ bool usesPreprocessorOnly() const override;
+ TranslationUnitKind getTranslationUnitKind() override;
+ bool hasPCHSupport() const override;
+ bool hasASTFileSupport() const override;
+ bool hasIRSupport() const override;
+ bool hasCodeCompletionSupport() const override;
+};
+
+} // 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..f61775f
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Frontend/FrontendActions.h
@@ -0,0 +1,241 @@
+//===-- 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 {
+
+class Module;
+class FileEntry;
+
+//===----------------------------------------------------------------------===//
+// Custom Consumer Actions
+//===----------------------------------------------------------------------===//
+
+class InitOnlyAction : public FrontendAction {
+ void ExecuteAction() override;
+
+ std::unique_ptr<ASTConsumer> CreateASTConsumer(CompilerInstance &CI,
+ StringRef InFile) override;
+
+public:
+ // Don't claim to only use the preprocessor, we want to follow the AST path,
+ // but do nothing.
+ bool usesPreprocessorOnly() const override { return false; }
+};
+
+//===----------------------------------------------------------------------===//
+// AST Consumer Actions
+//===----------------------------------------------------------------------===//
+
+class ASTPrintAction : public ASTFrontendAction {
+protected:
+ std::unique_ptr<ASTConsumer> CreateASTConsumer(CompilerInstance &CI,
+ StringRef InFile) override;
+};
+
+class ASTDumpAction : public ASTFrontendAction {
+protected:
+ std::unique_ptr<ASTConsumer> CreateASTConsumer(CompilerInstance &CI,
+ StringRef InFile) override;
+};
+
+class ASTDeclListAction : public ASTFrontendAction {
+protected:
+ std::unique_ptr<ASTConsumer> CreateASTConsumer(CompilerInstance &CI,
+ StringRef InFile) override;
+};
+
+class ASTViewAction : public ASTFrontendAction {
+protected:
+ std::unique_ptr<ASTConsumer> CreateASTConsumer(CompilerInstance &CI,
+ StringRef InFile) override;
+};
+
+class DeclContextPrintAction : public ASTFrontendAction {
+protected:
+ std::unique_ptr<ASTConsumer> CreateASTConsumer(CompilerInstance &CI,
+ StringRef InFile) override;
+};
+
+class GeneratePCHAction : public ASTFrontendAction {
+protected:
+ std::unique_ptr<ASTConsumer> CreateASTConsumer(CompilerInstance &CI,
+ StringRef InFile) override;
+
+ TranslationUnitKind getTranslationUnitKind() override {
+ return TU_Prefix;
+ }
+
+ bool hasASTFileSupport() const override { 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 raw_pwrite_stream *
+ ComputeASTConsumerArguments(CompilerInstance &CI, StringRef InFile,
+ std::string &Sysroot, std::string &OutputFile);
+};
+
+class GenerateModuleAction : public ASTFrontendAction {
+ clang::Module *Module;
+ const FileEntry *ModuleMapForUniquing;
+ bool IsSystem;
+
+protected:
+ std::unique_ptr<ASTConsumer> CreateASTConsumer(CompilerInstance &CI,
+ StringRef InFile) override;
+
+ TranslationUnitKind getTranslationUnitKind() override {
+ return TU_Module;
+ }
+
+ bool hasASTFileSupport() const override { return false; }
+
+public:
+ GenerateModuleAction(const FileEntry *ModuleMap = nullptr,
+ bool IsSystem = false)
+ : ASTFrontendAction(), ModuleMapForUniquing(ModuleMap), IsSystem(IsSystem)
+ { }
+
+ bool BeginSourceFileAction(CompilerInstance &CI, StringRef Filename) override;
+
+ /// \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.
+ raw_pwrite_stream *ComputeASTConsumerArguments(CompilerInstance &CI,
+ StringRef InFile,
+ std::string &Sysroot,
+ std::string &OutputFile);
+};
+
+class SyntaxOnlyAction : public ASTFrontendAction {
+protected:
+ std::unique_ptr<ASTConsumer> CreateASTConsumer(CompilerInstance &CI,
+ StringRef InFile) override;
+
+public:
+ bool hasCodeCompletionSupport() const override { return true; }
+};
+
+/// \brief Dump information about the given module file, to be used for
+/// basic debugging and discovery.
+class DumpModuleInfoAction : public ASTFrontendAction {
+protected:
+ std::unique_ptr<ASTConsumer> CreateASTConsumer(CompilerInstance &CI,
+ StringRef InFile) override;
+ void ExecuteAction() override;
+
+public:
+ bool hasPCHSupport() const override { return false; }
+ bool hasASTFileSupport() const override { return true; }
+ bool hasIRSupport() const override { return false; }
+ bool hasCodeCompletionSupport() const override { return false; }
+};
+
+class VerifyPCHAction : public ASTFrontendAction {
+protected:
+ std::unique_ptr<ASTConsumer> CreateASTConsumer(CompilerInstance &CI,
+ StringRef InFile) override;
+
+ void ExecuteAction() override;
+
+public:
+ bool hasCodeCompletionSupport() const override { return false; }
+};
+
+/**
+ * \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:
+ std::unique_ptr<ASTConsumer> CreateASTConsumer(CompilerInstance &CI,
+ StringRef InFile) override;
+
+ bool BeginSourceFileAction(CompilerInstance &CI,
+ StringRef Filename) override;
+
+ void ExecuteAction() override;
+ void EndSourceFileAction() override;
+
+public:
+ ASTMergeAction(FrontendAction *AdaptedAction, ArrayRef<std::string> ASTFiles);
+ ~ASTMergeAction() override;
+
+ bool usesPreprocessorOnly() const override;
+ TranslationUnitKind getTranslationUnitKind() override;
+ bool hasPCHSupport() const override;
+ bool hasASTFileSupport() const override;
+ bool hasCodeCompletionSupport() const override;
+};
+
+class PrintPreambleAction : public FrontendAction {
+protected:
+ void ExecuteAction() override;
+ std::unique_ptr<ASTConsumer> CreateASTConsumer(CompilerInstance &,
+ StringRef) override {
+ return nullptr;
+ }
+
+ bool usesPreprocessorOnly() const override { return true; }
+};
+
+//===----------------------------------------------------------------------===//
+// Preprocessor Actions
+//===----------------------------------------------------------------------===//
+
+class DumpRawTokensAction : public PreprocessorFrontendAction {
+protected:
+ void ExecuteAction() override;
+};
+
+class DumpTokensAction : public PreprocessorFrontendAction {
+protected:
+ void ExecuteAction() override;
+};
+
+class GeneratePTHAction : public PreprocessorFrontendAction {
+protected:
+ void ExecuteAction() override;
+};
+
+class PreprocessOnlyAction : public PreprocessorFrontendAction {
+protected:
+ void ExecuteAction() override;
+};
+
+class PrintPreprocessedAction : public PreprocessorFrontendAction {
+protected:
+ void ExecuteAction() override;
+
+ bool hasPCHSupport() const override { 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..0f37b7e
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Frontend/FrontendDiagnostic.h
@@ -0,0 +1,28 @@
+//===--- 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_FRONTEND_FRONTENDDIAGNOSTIC_H
+#define LLVM_CLANG_FRONTEND_FRONTENDDIAGNOSTIC_H
+
+#include "clang/Basic/Diagnostic.h"
+
+namespace clang {
+ namespace diag {
+ enum {
+#define DIAG(ENUM,FLAGS,DEFAULT_MAPPING,DESC,GROUP,\
+ SFINAE,NOWERROR,SHOWINSYSHEADER,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..c800a51
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Frontend/FrontendOptions.h
@@ -0,0 +1,292 @@
+//===--- 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/Serialization/ModuleFileExtension.h"
+#include "clang/Sema/CodeCompleteOptions.h"
+#include "llvm/ADT/StringRef.h"
+#include <string>
+#include <vector>
+
+namespace llvm {
+class MemoryBuffer;
+}
+
+namespace clang {
+
+namespace frontend {
+ enum ActionKind {
+ ASTDeclList, ///< Parse ASTs and list Decl nodes.
+ ASTDump, ///< Parse ASTs and dump them.
+ ASTPrint, ///< Parse ASTs and print them.
+ ASTView, ///< Parse ASTs and view them in Graphviz.
+ 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.
+ GenerateModule, ///< Generate pre-compiled module.
+ GeneratePCH, ///< Generate pre-compiled header.
+ GeneratePTH, ///< Generate pre-tokenized header.
+ InitOnly, ///< Only execute frontend initialization.
+ ModuleFileInfo, ///< Dump information about a module file.
+ VerifyPCH, ///< Load and verify that a PCH file is usable.
+ 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.
+ MigrateSource, ///< Run migrator.
+ RunPreprocessorOnly ///< Just lex, no output.
+ };
+}
+
+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_PreprocessedCuda,
+ IK_AST,
+ IK_LLVM_IR
+};
+
+
+/// \brief An input file for the front end.
+class FrontendInputFile {
+ /// \brief The file name, or "-" to read from standard input.
+ std::string File;
+
+ llvm::MemoryBuffer *Buffer;
+
+ /// \brief The kind of input, e.g., C source, AST file, LLVM IR.
+ InputKind Kind;
+
+ /// \brief Whether we're dealing with a 'system' input (vs. a 'user' input).
+ bool IsSystem;
+
+public:
+ FrontendInputFile() : Buffer(nullptr), Kind(IK_None), IsSystem(false) { }
+ FrontendInputFile(StringRef File, InputKind Kind, bool IsSystem = false)
+ : File(File.str()), Buffer(nullptr), Kind(Kind), IsSystem(IsSystem) { }
+ FrontendInputFile(llvm::MemoryBuffer *buffer, InputKind Kind,
+ bool IsSystem = false)
+ : Buffer(buffer), Kind(Kind), IsSystem(IsSystem) { }
+
+ InputKind getKind() const { return Kind; }
+ bool isSystem() const { return IsSystem; }
+
+ bool isEmpty() const { return File.empty() && Buffer == nullptr; }
+ bool isFile() const { return !isBuffer(); }
+ bool isBuffer() const { return Buffer != nullptr; }
+
+ StringRef getFile() const {
+ assert(isFile());
+ return File;
+ }
+ llvm::MemoryBuffer *getBuffer() const {
+ assert(isBuffer());
+ return Buffer;
+ }
+};
+
+/// 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 ShowHelp : 1; ///< Show the -help text.
+ 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.
+ unsigned FixOnlyWarnings : 1; ///< Apply fixes only for warnings.
+ unsigned FixAndRecompile : 1; ///< Apply fixes and recompile.
+ unsigned FixToTemporaries : 1; ///< Apply fixes to temporary files.
+ unsigned ARCMTMigrateEmitARCErrors : 1; /// Emit ARC errors even if the
+ /// migrator can fix them
+ unsigned SkipFunctionBodies : 1; ///< Skip over function bodies to
+ /// speed up parsing in cases you do
+ /// not need them (e.g. with code
+ /// completion).
+ unsigned UseGlobalModuleIndex : 1; ///< Whether we can use the
+ ///< global module index if available.
+ unsigned GenerateGlobalModuleIndex : 1; ///< Whether we can generate the
+ ///< global module index if needed.
+ unsigned ASTDumpDecls : 1; ///< Whether we include declaration
+ ///< dumps in AST dumps.
+ unsigned ASTDumpLookups : 1; ///< Whether we include lookup table
+ ///< dumps in AST dumps.
+ unsigned BuildingImplicitModule : 1; ///< Whether we are performing an
+ ///< implicit module build.
+ unsigned ModulesEmbedAllFiles : 1; ///< Whether we should embed all used
+ ///< files into the PCM file.
+
+ CodeCompleteOptions CodeCompleteOpts;
+
+ enum {
+ ARCMT_None,
+ ARCMT_Check,
+ ARCMT_Modify,
+ ARCMT_Migrate
+ } ARCMTAction;
+
+ enum {
+ ObjCMT_None = 0,
+ /// \brief Enable migration to modern ObjC literals.
+ ObjCMT_Literals = 0x1,
+ /// \brief Enable migration to modern ObjC subscripting.
+ ObjCMT_Subscripting = 0x2,
+ /// \brief Enable migration to modern ObjC readonly property.
+ ObjCMT_ReadonlyProperty = 0x4,
+ /// \brief Enable migration to modern ObjC readwrite property.
+ ObjCMT_ReadwriteProperty = 0x8,
+ /// \brief Enable migration to modern ObjC property.
+ ObjCMT_Property = (ObjCMT_ReadonlyProperty | ObjCMT_ReadwriteProperty),
+ /// \brief Enable annotation of ObjCMethods of all kinds.
+ ObjCMT_Annotation = 0x10,
+ /// \brief Enable migration of ObjC methods to 'instancetype'.
+ ObjCMT_Instancetype = 0x20,
+ /// \brief Enable migration to NS_ENUM/NS_OPTIONS macros.
+ ObjCMT_NsMacros = 0x40,
+ /// \brief Enable migration to add conforming protocols.
+ ObjCMT_ProtocolConformance = 0x80,
+ /// \brief prefer 'atomic' property over 'nonatomic'.
+ ObjCMT_AtomicProperty = 0x100,
+ /// \brief annotate property with NS_RETURNS_INNER_POINTER
+ ObjCMT_ReturnsInnerPointerProperty = 0x200,
+ /// \brief use NS_NONATOMIC_IOSONLY for property 'atomic' attribute
+ ObjCMT_NsAtomicIOSOnlyProperty = 0x400,
+ /// \brief Enable inferring NS_DESIGNATED_INITIALIZER for ObjC methods.
+ ObjCMT_DesignatedInitializer = 0x800,
+ /// \brief Enable converting setter/getter expressions to property-dot syntx.
+ ObjCMT_PropertyDotSyntax = 0x1000,
+ ObjCMT_MigrateDecls = (ObjCMT_ReadonlyProperty | ObjCMT_ReadwriteProperty |
+ ObjCMT_Annotation | ObjCMT_Instancetype |
+ ObjCMT_NsMacros | ObjCMT_ProtocolConformance |
+ ObjCMT_NsAtomicIOSOnlyProperty |
+ ObjCMT_DesignatedInitializer),
+ ObjCMT_MigrateAll = (ObjCMT_Literals | ObjCMT_Subscripting |
+ ObjCMT_MigrateDecls | ObjCMT_PropertyDotSyntax)
+ };
+ unsigned ObjCMTAction;
+ std::string ObjCMTWhiteListPath;
+
+ std::string MTMigrateDir;
+ std::string ARCMTMigrateReportOut;
+
+ /// The input files and their types.
+ std::vector<FrontendInputFile> Inputs;
+
+ /// The output file, if any.
+ std::string OutputFile;
+
+ /// If given, the new suffix for fix-it rewritten files.
+ std::string FixItSuffix;
+
+ /// If given, filter dumped AST Decl nodes by this substring.
+ std::string ASTDumpFilter;
+
+ /// 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;
+
+ /// The list of module file extensions.
+ std::vector<IntrusiveRefCntPtr<ModuleFileExtension>> ModuleFileExtensions;
+
+ /// \brief The list of module map files to load before processing the input.
+ std::vector<std::string> ModuleMapFiles;
+
+ /// \brief The list of additional prebuilt module files to load before
+ /// processing the input.
+ std::vector<std::string> ModuleFiles;
+
+ /// \brief The list of files to embed into the compiled module file.
+ std::vector<std::string> ModulesEmbedFiles;
+
+ /// \brief The list of AST files to merge.
+ std::vector<std::string> ASTMergeFiles;
+
+ /// \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;
+
+ /// \brief File name of the file that will provide record layouts
+ /// (in the format produced by -fdump-record-layouts).
+ std::string OverrideRecordLayoutsFile;
+
+ /// \brief Auxiliary triple for CUDA compilation.
+ std::string AuxTriple;
+
+public:
+ FrontendOptions() :
+ DisableFree(false), RelocatablePCH(false), ShowHelp(false),
+ ShowStats(false), ShowTimers(false), ShowVersion(false),
+ FixWhatYouCan(false), FixOnlyWarnings(false), FixAndRecompile(false),
+ FixToTemporaries(false), ARCMTMigrateEmitARCErrors(false),
+ SkipFunctionBodies(false), UseGlobalModuleIndex(true),
+ GenerateGlobalModuleIndex(true), ASTDumpDecls(false), ASTDumpLookups(false),
+ BuildingImplicitModule(false), ModulesEmbedAllFiles(false),
+ ARCMTAction(ARCMT_None), ObjCMTAction(ObjCMT_None),
+ ProgramAction(frontend::ParseSyntaxOnly)
+ {}
+
+ /// 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(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..ecab630
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Frontend/FrontendPluginRegistry.h
@@ -0,0 +1,26 @@
+//===-- 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_FRONTENDPLUGINREGISTRY_H
+#define LLVM_CLANG_FRONTEND_FRONTENDPLUGINREGISTRY_H
+
+#include "clang/Frontend/FrontendAction.h"
+#include "llvm/Support/Registry.h"
+
+// Instantiated in FrontendAction.cpp.
+extern template class llvm::Registry<clang::PluginASTAction>;
+
+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/LangStandard.h b/contrib/llvm/tools/clang/include/clang/Frontend/LangStandard.h
new file mode 100644
index 0000000..8021d08
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Frontend/LangStandard.h
@@ -0,0 +1,100 @@
+//===--- 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 "clang/Basic/LLVM.h"
+#include "llvm/ADT/StringRef.h"
+
+namespace clang {
+
+namespace frontend {
+
+enum LangFeatures {
+ LineComment = (1 << 0),
+ C89 = (1 << 1),
+ C99 = (1 << 2),
+ C11 = (1 << 3),
+ CPlusPlus = (1 << 4),
+ CPlusPlus11 = (1 << 5),
+ CPlusPlus14 = (1 << 6),
+ CPlusPlus1z = (1 << 7),
+ Digraphs = (1 << 8),
+ GNUMode = (1 << 9),
+ HexFloat = (1 << 10),
+ ImplicitInt = (1 << 11)
+};
+
+}
+
+/// 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; }
+
+ /// Language supports '//' comments.
+ bool hasLineComments() const { return Flags & frontend::LineComment; }
+
+ /// isC89 - Language is a superset of C89.
+ bool isC89() const { return Flags & frontend::C89; }
+
+ /// isC99 - Language is a superset of C99.
+ bool isC99() const { return Flags & frontend::C99; }
+
+ /// isC11 - Language is a superset of C11.
+ bool isC11() const { return Flags & frontend::C11; }
+
+ /// isCPlusPlus - Language is a C++ variant.
+ bool isCPlusPlus() const { return Flags & frontend::CPlusPlus; }
+
+ /// isCPlusPlus11 - Language is a C++11 variant (or later).
+ bool isCPlusPlus11() const { return Flags & frontend::CPlusPlus11; }
+
+ /// isCPlusPlus14 - Language is a C++14 variant (or later).
+ bool isCPlusPlus14() const { return Flags & frontend::CPlusPlus14; }
+
+ /// isCPlusPlus1z - Language is a C++17 variant (or later).
+ bool isCPlusPlus1z() const { return Flags & frontend::CPlusPlus1z; }
+
+ /// 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(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..cac9c3c
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Frontend/LangStandards.def
@@ -0,0 +1,153 @@
+//===-- 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",
+ C89 | ImplicitInt)
+LANGSTANDARD(c90, "c90",
+ "ISO C 1990",
+ C89 | ImplicitInt)
+LANGSTANDARD(iso9899_1990, "iso9899:1990",
+ "ISO C 1990",
+ C89 | ImplicitInt)
+
+LANGSTANDARD(c94, "iso9899:199409",
+ "ISO C 1990 with amendment 1",
+ C89 | Digraphs | ImplicitInt)
+
+LANGSTANDARD(gnu89, "gnu89",
+ "ISO C 1990 with GNU extensions",
+ LineComment | C89 | Digraphs | GNUMode | ImplicitInt)
+LANGSTANDARD(gnu90, "gnu90",
+ "ISO C 1990 with GNU extensions",
+ LineComment | C89 | Digraphs | GNUMode | ImplicitInt)
+
+// C99-ish modes
+LANGSTANDARD(c99, "c99",
+ "ISO C 1999",
+ LineComment | C99 | Digraphs | HexFloat)
+LANGSTANDARD(c9x, "c9x",
+ "ISO C 1999",
+ LineComment | C99 | Digraphs | HexFloat)
+LANGSTANDARD(iso9899_1999,
+ "iso9899:1999", "ISO C 1999",
+ LineComment | C99 | Digraphs | HexFloat)
+LANGSTANDARD(iso9899_199x,
+ "iso9899:199x", "ISO C 1999",
+ LineComment | C99 | Digraphs | HexFloat)
+
+LANGSTANDARD(gnu99, "gnu99",
+ "ISO C 1999 with GNU extensions",
+ LineComment | C99 | Digraphs | GNUMode | HexFloat)
+LANGSTANDARD(gnu9x, "gnu9x",
+ "ISO C 1999 with GNU extensions",
+ LineComment | C99 | Digraphs | GNUMode | HexFloat)
+
+// C11 modes
+LANGSTANDARD(c11, "c11",
+ "ISO C 2011",
+ LineComment | C99 | C11 | Digraphs | HexFloat)
+LANGSTANDARD(c1x, "c1x",
+ "ISO C 2011",
+ LineComment | C99 | C11 | Digraphs | HexFloat)
+LANGSTANDARD(iso9899_2011,
+ "iso9899:2011", "ISO C 2011",
+ LineComment | C99 | C11 | Digraphs | HexFloat)
+LANGSTANDARD(iso9899_201x,
+ "iso9899:2011", "ISO C 2011",
+ LineComment | C99 | C11 | Digraphs | HexFloat)
+
+LANGSTANDARD(gnu11, "gnu11",
+ "ISO C 2011 with GNU extensions",
+ LineComment | C99 | C11 | Digraphs | GNUMode | HexFloat)
+LANGSTANDARD(gnu1x, "gnu1x",
+ "ISO C 2011 with GNU extensions",
+ LineComment | C99 | C11 | Digraphs | GNUMode | HexFloat)
+
+// C++ modes
+LANGSTANDARD(cxx98, "c++98",
+ "ISO C++ 1998 with amendments",
+ LineComment | CPlusPlus | Digraphs)
+LANGSTANDARD(cxx03, "c++03",
+ "ISO C++ 1998 with amendments",
+ LineComment | CPlusPlus | Digraphs)
+LANGSTANDARD(gnucxx98, "gnu++98",
+ "ISO C++ 1998 with amendments and GNU extensions",
+ LineComment | CPlusPlus | Digraphs | GNUMode)
+
+LANGSTANDARD(cxx0x, "c++0x",
+ "ISO C++ 2011 with amendments",
+ LineComment | CPlusPlus | CPlusPlus11 | Digraphs)
+LANGSTANDARD(cxx11, "c++11",
+ "ISO C++ 2011 with amendments",
+ LineComment | CPlusPlus | CPlusPlus11 | Digraphs)
+LANGSTANDARD(gnucxx0x, "gnu++0x",
+ "ISO C++ 2011 with amendments and GNU extensions",
+ LineComment | CPlusPlus | CPlusPlus11 | Digraphs | GNUMode)
+LANGSTANDARD(gnucxx11, "gnu++11",
+ "ISO C++ 2011 with amendments and GNU extensions",
+ LineComment | CPlusPlus | CPlusPlus11 | Digraphs | GNUMode)
+
+LANGSTANDARD(cxx1y, "c++1y",
+ "ISO C++ 2014 with amendments",
+ LineComment | CPlusPlus | CPlusPlus11 | CPlusPlus14 | Digraphs)
+LANGSTANDARD(cxx14, "c++14",
+ "ISO C++ 2014 with amendments",
+ LineComment | CPlusPlus | CPlusPlus11 | CPlusPlus14 | Digraphs)
+LANGSTANDARD(gnucxx1y, "gnu++1y",
+ "ISO C++ 2014 with amendments and GNU extensions",
+ LineComment | CPlusPlus | CPlusPlus11 | CPlusPlus14 | Digraphs |
+ GNUMode)
+LANGSTANDARD(gnucxx14, "gnu++14",
+ "ISO C++ 2014 with amendments and GNU extensions",
+ LineComment | CPlusPlus | CPlusPlus11 | CPlusPlus14 | Digraphs |
+ GNUMode)
+
+LANGSTANDARD(cxx1z, "c++1z",
+ "Working draft for ISO C++ 2017",
+ LineComment | CPlusPlus | CPlusPlus11 | CPlusPlus14 | CPlusPlus1z |
+ Digraphs)
+LANGSTANDARD(gnucxx1z, "gnu++1z",
+ "Working draft for ISO C++ 2017 with GNU extensions",
+ LineComment | CPlusPlus | CPlusPlus11 | CPlusPlus14 | CPlusPlus1z |
+ Digraphs | GNUMode)
+
+// OpenCL
+LANGSTANDARD(opencl, "cl",
+ "OpenCL 1.0",
+ LineComment | C99 | Digraphs | HexFloat)
+LANGSTANDARD(opencl11, "CL1.1",
+ "OpenCL 1.1",
+ LineComment | C99 | Digraphs | HexFloat)
+LANGSTANDARD(opencl12, "CL1.2",
+ "OpenCL 1.2",
+ LineComment | C99 | Digraphs | HexFloat)
+LANGSTANDARD(opencl20, "CL2.0",
+ "OpenCL 2.0",
+ LineComment | C99 | Digraphs | HexFloat)
+
+// CUDA
+LANGSTANDARD(cuda, "cuda",
+ "NVIDIA CUDA(tm)",
+ LineComment | CPlusPlus | Digraphs)
+
+#undef LANGSTANDARD
diff --git a/contrib/llvm/tools/clang/include/clang/Frontend/LayoutOverrideSource.h b/contrib/llvm/tools/clang/include/clang/Frontend/LayoutOverrideSource.h
new file mode 100644
index 0000000..16d032b
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Frontend/LayoutOverrideSource.h
@@ -0,0 +1,63 @@
+//===--- LayoutOverrideSource.h --Override Record Layouts -----------------===//
+//
+// 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_LAYOUTOVERRIDESOURCE_H
+#define LLVM_CLANG_FRONTEND_LAYOUTOVERRIDESOURCE_H
+
+#include "clang/AST/ExternalASTSource.h"
+#include "clang/Basic/LLVM.h"
+#include "llvm/ADT/StringMap.h"
+#include "llvm/ADT/StringRef.h"
+
+namespace clang {
+ /// \brief An external AST source that overrides the layout of
+ /// a specified set of record types.
+ ///
+ /// This class is used only for testing the ability of external AST sources
+ /// to override the layout of record types. Its input is the output format
+ /// of the command-line argument -fdump-record-layouts.
+ class LayoutOverrideSource : public ExternalASTSource {
+ /// \brief The layout of a given record.
+ struct Layout {
+ /// \brief The size of the record.
+ uint64_t Size;
+
+ /// \brief The alignment of the record.
+ uint64_t Align;
+
+ /// \brief The offsets of the fields, in source order.
+ SmallVector<uint64_t, 8> FieldOffsets;
+ };
+
+ /// \brief The set of layouts that will be overridden.
+ llvm::StringMap<Layout> Layouts;
+
+ public:
+ /// \brief Create a new AST source that overrides the layout of some
+ /// set of record types.
+ ///
+ /// The file is the result of passing -fdump-record-layouts to a file.
+ explicit LayoutOverrideSource(StringRef Filename);
+
+ /// \brief If this particular record type has an overridden layout,
+ /// return that layout.
+ bool
+ layoutRecordType(const RecordDecl *Record,
+ uint64_t &Size, uint64_t &Alignment,
+ llvm::DenseMap<const FieldDecl *, uint64_t> &FieldOffsets,
+ llvm::DenseMap<const CXXRecordDecl *, CharUnits> &BaseOffsets,
+ llvm::DenseMap<const CXXRecordDecl *,
+ CharUnits> &VirtualBaseOffsets) override;
+
+ /// \brief Dump the overridden layouts.
+ void dump();
+ };
+}
+
+#endif
diff --git a/contrib/llvm/tools/clang/include/clang/Frontend/LogDiagnosticPrinter.h b/contrib/llvm/tools/clang/include/clang/Frontend/LogDiagnosticPrinter.h
new file mode 100644
index 0000000..98adf65
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Frontend/LogDiagnosticPrinter.h
@@ -0,0 +1,85 @@
+//===--- LogDiagnosticPrinter.h - Log 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_LOGDIAGNOSTICPRINTER_H
+#define LLVM_CLANG_FRONTEND_LOGDIAGNOSTICPRINTER_H
+
+#include "clang/Basic/Diagnostic.h"
+#include "clang/Basic/SourceLocation.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/StringRef.h"
+
+namespace clang {
+class DiagnosticOptions;
+class LangOptions;
+
+class LogDiagnosticPrinter : public DiagnosticConsumer {
+ struct DiagEntry {
+ /// The primary message line of the diagnostic.
+ std::string Message;
+
+ /// The source file name, if available.
+ std::string Filename;
+
+ /// The source file line number, if available.
+ unsigned Line;
+
+ /// The source file column number, if available.
+ unsigned Column;
+
+ /// The ID of the diagnostic.
+ unsigned DiagnosticID;
+
+ /// The Option Flag for the diagnostic
+ std::string WarningOption;
+
+ /// The level of the diagnostic.
+ DiagnosticsEngine::Level DiagnosticLevel;
+ };
+
+ void EmitDiagEntry(llvm::raw_ostream &OS,
+ const LogDiagnosticPrinter::DiagEntry &DE);
+
+ // Conditional ownership (when StreamOwner is non-null, it's keeping OS
+ // alive). We might want to replace this with a wrapper for conditional
+ // ownership eventually - it seems to pop up often enough.
+ raw_ostream &OS;
+ std::unique_ptr<raw_ostream> StreamOwner;
+ const LangOptions *LangOpts;
+ IntrusiveRefCntPtr<DiagnosticOptions> DiagOpts;
+
+ SourceLocation LastWarningLoc;
+ FullSourceLoc LastLoc;
+
+ SmallVector<DiagEntry, 8> Entries;
+
+ std::string MainFilename;
+ std::string DwarfDebugFlags;
+
+public:
+ LogDiagnosticPrinter(raw_ostream &OS, DiagnosticOptions *Diags,
+ std::unique_ptr<raw_ostream> StreamOwner);
+
+ void setDwarfDebugFlags(StringRef Value) {
+ DwarfDebugFlags = Value;
+ }
+
+ void BeginSourceFile(const LangOptions &LO, const Preprocessor *PP) override {
+ LangOpts = &LO;
+ }
+
+ void EndSourceFile() override;
+
+ void HandleDiagnostic(DiagnosticsEngine::Level DiagLevel,
+ const Diagnostic &Info) override;
+};
+
+} // end namespace clang
+
+#endif
diff --git a/contrib/llvm/tools/clang/include/clang/Frontend/MigratorOptions.h b/contrib/llvm/tools/clang/include/clang/Frontend/MigratorOptions.h
new file mode 100644
index 0000000..8eb71b1
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Frontend/MigratorOptions.h
@@ -0,0 +1,31 @@
+//===--- MigratorOptions.h - MigratorOptions 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 migration analysis.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_FRONTEND_MIGRATOROPTIONS_H
+#define LLVM_CLANG_FRONTEND_MIGRATOROPTIONS_H
+
+namespace clang {
+
+class MigratorOptions {
+public:
+ unsigned NoNSAllocReallocError : 1;
+ unsigned NoFinalizeRemoval : 1;
+ MigratorOptions() {
+ NoNSAllocReallocError = 0;
+ NoFinalizeRemoval = 0;
+ }
+};
+
+}
+#endif
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..873af03
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Frontend/MultiplexConsumer.h
@@ -0,0 +1,69 @@
+//===-- 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.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_FRONTEND_MULTIPLEXCONSUMER_H
+#define LLVM_CLANG_FRONTEND_MULTIPLEXCONSUMER_H
+
+#include "clang/Basic/LLVM.h"
+#include "clang/Sema/SemaConsumer.h"
+#include <memory>
+#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(std::vector<std::unique_ptr<ASTConsumer>> C);
+ ~MultiplexConsumer() override;
+
+ // ASTConsumer
+ void Initialize(ASTContext &Context) override;
+ void HandleCXXStaticMemberVarInstantiation(VarDecl *VD) override;
+ bool HandleTopLevelDecl(DeclGroupRef D) override;
+ void HandleInlineMethodDefinition(CXXMethodDecl *D) override;
+ void HandleInterestingDecl(DeclGroupRef D) override;
+ void HandleTranslationUnit(ASTContext &Ctx) override;
+ void HandleTagDeclDefinition(TagDecl *D) override;
+ void HandleTagDeclRequiredDefinition(const TagDecl *D) override;
+ void HandleCXXImplicitFunctionInstantiation(FunctionDecl *D) override;
+ void HandleTopLevelDeclInObjCContainer(DeclGroupRef D) override;
+ void HandleImplicitImportDecl(ImportDecl *D) override;
+ void HandleLinkerOptionPragma(llvm::StringRef Opts) override;
+ void HandleDetectMismatch(llvm::StringRef Name,
+ llvm::StringRef Value) override;
+ void HandleDependentLibrary(llvm::StringRef Lib) override;
+ void CompleteTentativeDefinition(VarDecl *D) override;
+ void HandleVTable(CXXRecordDecl *RD) override;
+ ASTMutationListener *GetASTMutationListener() override;
+ ASTDeserializationListener *GetASTDeserializationListener() override;
+ void PrintStats() override;
+
+ // SemaConsumer
+ void InitializeSema(Sema &S) override;
+ void ForgetSema() override;
+
+private:
+ std::vector<std::unique_ptr<ASTConsumer>> Consumers; // Owns these.
+ std::unique_ptr<MultiplexASTMutationListener> MutationListener;
+ std::unique_ptr<MultiplexASTDeserializationListener> DeserializationListener;
+};
+
+} // end namespace clang
+
+#endif
diff --git a/contrib/llvm/tools/clang/include/clang/Frontend/PCHContainerOperations.h b/contrib/llvm/tools/clang/include/clang/Frontend/PCHContainerOperations.h
new file mode 100644
index 0000000..67c36cf
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Frontend/PCHContainerOperations.h
@@ -0,0 +1,118 @@
+//===--- Frontend/PCHContainerOperations.h - PCH Containers -----*- 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_PCH_CONTAINER_OPERATIONS_H
+#define LLVM_CLANG_PCH_CONTAINER_OPERATIONS_H
+
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/StringMap.h"
+#include "llvm/Support/MemoryBuffer.h"
+#include <memory>
+
+namespace llvm {
+class raw_pwrite_stream;
+class BitstreamReader;
+}
+
+using llvm::StringRef;
+
+namespace clang {
+
+class ASTConsumer;
+class CodeGenOptions;
+class DiagnosticsEngine;
+class CompilerInstance;
+
+struct PCHBuffer {
+ uint64_t Signature;
+ llvm::SmallVector<char, 0> Data;
+ bool IsComplete;
+};
+
+/// This abstract interface provides operations for creating
+/// containers for serialized ASTs (precompiled headers and clang
+/// modules).
+class PCHContainerWriter {
+public:
+ virtual ~PCHContainerWriter() = 0;
+ virtual StringRef getFormat() const = 0;
+
+ /// Return an ASTConsumer that can be chained with a
+ /// PCHGenerator that produces a wrapper file format containing a
+ /// serialized AST bitstream.
+ virtual std::unique_ptr<ASTConsumer> CreatePCHContainerGenerator(
+ CompilerInstance &CI, const std::string &MainFileName,
+ const std::string &OutputFileName, llvm::raw_pwrite_stream *OS,
+ std::shared_ptr<PCHBuffer> Buffer) const = 0;
+};
+
+/// This abstract interface provides operations for unwrapping
+/// containers for serialized ASTs (precompiled headers and clang
+/// modules).
+class PCHContainerReader {
+public:
+ virtual ~PCHContainerReader() = 0;
+ /// Equivalent to the format passed to -fmodule-format=
+ virtual StringRef getFormat() const = 0;
+
+ /// Initialize an llvm::BitstreamReader with the serialized AST inside
+ /// the PCH container Buffer.
+ virtual void ExtractPCH(llvm::MemoryBufferRef Buffer,
+ llvm::BitstreamReader &StreamFile) const = 0;
+};
+
+/// Implements write operations for a raw pass-through PCH container.
+class RawPCHContainerWriter : public PCHContainerWriter {
+ StringRef getFormat() const override { return "raw"; }
+
+ /// Return an ASTConsumer that can be chained with a
+ /// PCHGenerator that writes the module to a flat file.
+ std::unique_ptr<ASTConsumer> CreatePCHContainerGenerator(
+ CompilerInstance &CI, const std::string &MainFileName,
+ const std::string &OutputFileName, llvm::raw_pwrite_stream *OS,
+ std::shared_ptr<PCHBuffer> Buffer) const override;
+};
+
+/// Implements read operations for a raw pass-through PCH container.
+class RawPCHContainerReader : public PCHContainerReader {
+ StringRef getFormat() const override { return "raw"; }
+
+ /// Initialize an llvm::BitstreamReader with Buffer.
+ void ExtractPCH(llvm::MemoryBufferRef Buffer,
+ llvm::BitstreamReader &StreamFile) const override;
+};
+
+/// A registry of PCHContainerWriter and -Reader objects for different formats.
+class PCHContainerOperations {
+ llvm::StringMap<std::unique_ptr<PCHContainerWriter>> Writers;
+ llvm::StringMap<std::unique_ptr<PCHContainerReader>> Readers;
+public:
+ /// Automatically registers a RawPCHContainerWriter and
+ /// RawPCHContainerReader.
+ PCHContainerOperations();
+ void registerWriter(std::unique_ptr<PCHContainerWriter> Writer) {
+ Writers[Writer->getFormat()] = std::move(Writer);
+ }
+ void registerReader(std::unique_ptr<PCHContainerReader> Reader) {
+ Readers[Reader->getFormat()] = std::move(Reader);
+ }
+ const PCHContainerWriter *getWriterOrNull(StringRef Format) {
+ return Writers[Format].get();
+ }
+ const PCHContainerReader *getReaderOrNull(StringRef Format) {
+ return Readers[Format].get();
+ }
+ const PCHContainerReader &getRawReader() {
+ return *getReaderOrNull("raw");
+ }
+};
+
+}
+
+#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..f86c490
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Frontend/PreprocessorOutputOptions.h
@@ -0,0 +1,41 @@
+//===--- 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 UseLineDirectives : 1; ///< Use \#line instead of GCC-style \# N.
+ unsigned ShowMacroComments : 1; ///< Show comments, even in macros.
+ unsigned ShowMacros : 1; ///< Print macro definitions.
+ unsigned RewriteIncludes : 1; ///< Preprocess include directives only.
+
+public:
+ PreprocessorOutputOptions() {
+ ShowCPP = 0;
+ ShowComments = 0;
+ ShowLineMarkers = 1;
+ UseLineDirectives = 0;
+ ShowMacroComments = 0;
+ ShowMacros = 0;
+ RewriteIncludes = 0;
+ }
+};
+
+} // end namespace clang
+
+#endif
diff --git a/contrib/llvm/tools/clang/include/clang/Frontend/SerializedDiagnosticPrinter.h b/contrib/llvm/tools/clang/include/clang/Frontend/SerializedDiagnosticPrinter.h
new file mode 100644
index 0000000..4c57e9d
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Frontend/SerializedDiagnosticPrinter.h
@@ -0,0 +1,43 @@
+//===--- SerializedDiagnosticPrinter.h - Serializer for diagnostics -------===//
+//
+// 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_SERIALIZEDDIAGNOSTICPRINTER_H
+#define LLVM_CLANG_FRONTEND_SERIALIZEDDIAGNOSTICPRINTER_H
+
+#include "clang/Basic/LLVM.h"
+#include "clang/Frontend/SerializedDiagnostics.h"
+#include "llvm/Bitcode/BitstreamWriter.h"
+
+namespace llvm {
+class raw_ostream;
+}
+
+namespace clang {
+class DiagnosticConsumer;
+class DiagnosticsEngine;
+class DiagnosticOptions;
+
+namespace serialized_diags {
+
+/// \brief Returns a DiagnosticConsumer that serializes diagnostics to
+/// a bitcode file.
+///
+/// The created DiagnosticConsumer is designed for quick and lightweight
+/// transfer of of diagnostics to the enclosing build system (e.g., an IDE).
+/// This allows wrapper tools for Clang to get diagnostics from Clang
+/// (via libclang) without needing to parse Clang's command line output.
+///
+std::unique_ptr<DiagnosticConsumer> create(StringRef OutputFile,
+ DiagnosticOptions *Diags,
+ bool MergeChildRecords = false);
+
+} // end serialized_diags namespace
+} // end clang namespace
+
+#endif
diff --git a/contrib/llvm/tools/clang/include/clang/Frontend/SerializedDiagnosticReader.h b/contrib/llvm/tools/clang/include/clang/Frontend/SerializedDiagnosticReader.h
new file mode 100644
index 0000000..3db362b
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Frontend/SerializedDiagnosticReader.h
@@ -0,0 +1,131 @@
+//===--- SerializedDiagnosticReader.h - Reads diagnostics -------*- 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_SERIALIZED_DIAGNOSTIC_READER_H_
+#define LLVM_CLANG_FRONTEND_SERIALIZED_DIAGNOSTIC_READER_H_
+
+#include "clang/Basic/LLVM.h"
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/Bitcode/BitstreamReader.h"
+#include "llvm/Support/ErrorOr.h"
+
+namespace clang {
+namespace serialized_diags {
+
+enum class SDError {
+ CouldNotLoad = 1,
+ InvalidSignature,
+ InvalidDiagnostics,
+ MalformedTopLevelBlock,
+ MalformedSubBlock,
+ MalformedBlockInfoBlock,
+ MalformedMetadataBlock,
+ MalformedDiagnosticBlock,
+ MalformedDiagnosticRecord,
+ MissingVersion,
+ VersionMismatch,
+ UnsupportedConstruct,
+ /// A generic error for subclass handlers that don't want or need to define
+ /// their own error_category.
+ HandlerFailed
+};
+
+const std::error_category &SDErrorCategory();
+
+inline std::error_code make_error_code(SDError E) {
+ return std::error_code(static_cast<int>(E), SDErrorCategory());
+}
+
+/// \brief A location that is represented in the serialized diagnostics.
+struct Location {
+ unsigned FileID;
+ unsigned Line;
+ unsigned Col;
+ unsigned Offset;
+ Location(unsigned FileID, unsigned Line, unsigned Col, unsigned Offset)
+ : FileID(FileID), Line(Line), Col(Col), Offset(Offset) {}
+};
+
+/// \brief A base class that handles reading serialized diagnostics from a file.
+///
+/// Subclasses should override the visit* methods with their logic for handling
+/// the various constructs that are found in serialized diagnostics.
+class SerializedDiagnosticReader {
+public:
+ SerializedDiagnosticReader() {}
+ virtual ~SerializedDiagnosticReader() {}
+
+ /// \brief Read the diagnostics in \c File
+ std::error_code readDiagnostics(StringRef File);
+
+private:
+ enum class Cursor;
+
+ /// \brief Read to the next record or block to process.
+ llvm::ErrorOr<Cursor> skipUntilRecordOrBlock(llvm::BitstreamCursor &Stream,
+ unsigned &BlockOrRecordId);
+
+ /// \brief Read a metadata block from \c Stream.
+ std::error_code readMetaBlock(llvm::BitstreamCursor &Stream);
+
+ /// \brief Read a diagnostic block from \c Stream.
+ std::error_code readDiagnosticBlock(llvm::BitstreamCursor &Stream);
+
+protected:
+ /// \brief Visit the start of a diagnostic block.
+ virtual std::error_code visitStartOfDiagnostic() {
+ return std::error_code();
+ }
+ /// \brief Visit the end of a diagnostic block.
+ virtual std::error_code visitEndOfDiagnostic() { return std::error_code(); }
+ /// \brief Visit a category. This associates the category \c ID to a \c Name.
+ virtual std::error_code visitCategoryRecord(unsigned ID, StringRef Name) {
+ return std::error_code();
+ }
+ /// \brief Visit a flag. This associates the flag's \c ID to a \c Name.
+ virtual std::error_code visitDiagFlagRecord(unsigned ID, StringRef Name) {
+ return std::error_code();
+ }
+ /// \brief Visit a diagnostic.
+ virtual std::error_code
+ visitDiagnosticRecord(unsigned Severity, const Location &Location,
+ unsigned Category, unsigned Flag, StringRef Message) {
+ return std::error_code();
+ }
+ /// \brief Visit a filename. This associates the file's \c ID to a \c Name.
+ virtual std::error_code visitFilenameRecord(unsigned ID, unsigned Size,
+ unsigned Timestamp,
+ StringRef Name) {
+ return std::error_code();
+ }
+ /// \brief Visit a fixit hint.
+ virtual std::error_code
+ visitFixitRecord(const Location &Start, const Location &End, StringRef Text) {
+ return std::error_code();
+ }
+ /// \brief Visit a source range.
+ virtual std::error_code visitSourceRangeRecord(const Location &Start,
+ const Location &End) {
+ return std::error_code();
+ }
+ /// \brief Visit the version of the set of diagnostics.
+ virtual std::error_code visitVersionRecord(unsigned Version) {
+ return std::error_code();
+ }
+};
+
+} // end serialized_diags namespace
+} // end clang namespace
+
+namespace std {
+template <>
+struct is_error_code_enum<clang::serialized_diags::SDError> : std::true_type {};
+}
+
+#endif
diff --git a/contrib/llvm/tools/clang/include/clang/Frontend/SerializedDiagnostics.h b/contrib/llvm/tools/clang/include/clang/Frontend/SerializedDiagnostics.h
new file mode 100644
index 0000000..2032cd3
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Frontend/SerializedDiagnostics.h
@@ -0,0 +1,59 @@
+//===--- SerializedDiagnostics.h - Common data for serialized diagnostics -===//
+//
+// 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_SERIALIZE_DIAGNOSTICS_H_
+#define LLVM_CLANG_FRONTEND_SERIALIZE_DIAGNOSTICS_H_
+
+#include "llvm/Bitcode/BitCodes.h"
+
+namespace clang {
+namespace serialized_diags {
+
+enum BlockIDs {
+ /// \brief A top-level block which represents any meta data associated
+ /// with the diagostics, including versioning of the format.
+ BLOCK_META = llvm::bitc::FIRST_APPLICATION_BLOCKID,
+
+ /// \brief The this block acts as a container for all the information
+ /// for a specific diagnostic.
+ BLOCK_DIAG
+};
+
+enum RecordIDs {
+ RECORD_VERSION = 1,
+ RECORD_DIAG,
+ RECORD_SOURCE_RANGE,
+ RECORD_DIAG_FLAG,
+ RECORD_CATEGORY,
+ RECORD_FILENAME,
+ RECORD_FIXIT,
+ RECORD_FIRST = RECORD_VERSION,
+ RECORD_LAST = RECORD_FIXIT
+};
+
+/// \brief A stable version of DiagnosticIDs::Level.
+///
+/// Do not change the order of values in this enum, and please increment the
+/// serialized diagnostics version number when you add to it.
+enum Level {
+ Ignored = 0,
+ Note,
+ Warning,
+ Error,
+ Fatal,
+ Remark
+};
+
+/// \brief The serialized diagnostics version number.
+enum { VersionNumber = 2 };
+
+} // end serialized_diags namespace
+} // end clang namespace
+
+#endif
diff --git a/contrib/llvm/tools/clang/include/clang/Frontend/TextDiagnostic.h b/contrib/llvm/tools/clang/include/clang/Frontend/TextDiagnostic.h
new file mode 100644
index 0000000..d41f15a
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Frontend/TextDiagnostic.h
@@ -0,0 +1,122 @@
+//===--- TextDiagnostic.h - Text Diagnostic Pretty-Printing -----*- 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 utility class that provides support for textual pretty-printing of
+// diagnostics. It is used to implement the different code paths which require
+// such functionality in a consistent way.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_FRONTEND_TEXTDIAGNOSTIC_H
+#define LLVM_CLANG_FRONTEND_TEXTDIAGNOSTIC_H
+
+#include "clang/Frontend/DiagnosticRenderer.h"
+
+namespace clang {
+
+/// \brief Class to encapsulate the logic for formatting and printing a textual
+/// diagnostic message.
+///
+/// This class provides an interface for building and emitting a textual
+/// diagnostic, including all of the macro backtraces, caret diagnostics, FixIt
+/// Hints, and code snippets. In the presence of macros this involves
+/// a recursive process, synthesizing notes for each macro expansion.
+///
+/// The purpose of this class is to isolate the implementation of printing
+/// beautiful text diagnostics from any particular interfaces. The Clang
+/// DiagnosticClient is implemented through this class as is diagnostic
+/// printing coming out of libclang.
+class TextDiagnostic : public DiagnosticRenderer {
+ raw_ostream &OS;
+
+public:
+ TextDiagnostic(raw_ostream &OS,
+ const LangOptions &LangOpts,
+ DiagnosticOptions *DiagOpts);
+
+ ~TextDiagnostic() override;
+
+ /// \brief Print the diagonstic level to a raw_ostream.
+ ///
+ /// This is a static helper that handles colorizing the level and formatting
+ /// it into an arbitrary output stream. This is used internally by the
+ /// TextDiagnostic emission code, but it can also be used directly by
+ /// consumers that don't have a source manager or other state that the full
+ /// TextDiagnostic logic requires.
+ static void printDiagnosticLevel(raw_ostream &OS,
+ DiagnosticsEngine::Level Level,
+ bool ShowColors,
+ bool CLFallbackMode = false);
+
+ /// \brief Pretty-print a diagnostic message to a raw_ostream.
+ ///
+ /// This is a static helper to handle the line wrapping, colorizing, and
+ /// rendering of a diagnostic message to a particular ostream. It is
+ /// publicly visible so that clients which do not have sufficient state to
+ /// build a complete TextDiagnostic object can still get consistent
+ /// formatting of their diagnostic messages.
+ ///
+ /// \param OS Where the message is printed
+ /// \param IsSupplemental true if this is a continuation note diagnostic
+ /// \param Message The text actually printed
+ /// \param CurrentColumn The starting column of the first line, accounting
+ /// for any prefix.
+ /// \param Columns The number of columns to use in line-wrapping, 0 disables
+ /// all line-wrapping.
+ /// \param ShowColors Enable colorizing of the message.
+ static void printDiagnosticMessage(raw_ostream &OS, bool IsSupplemental,
+ StringRef Message, unsigned CurrentColumn,
+ unsigned Columns, bool ShowColors);
+
+protected:
+ void emitDiagnosticMessage(SourceLocation Loc,PresumedLoc PLoc,
+ DiagnosticsEngine::Level Level,
+ StringRef Message,
+ ArrayRef<CharSourceRange> Ranges,
+ const SourceManager *SM,
+ DiagOrStoredDiag D) override;
+
+ void emitDiagnosticLoc(SourceLocation Loc, PresumedLoc PLoc,
+ DiagnosticsEngine::Level Level,
+ ArrayRef<CharSourceRange> Ranges,
+ const SourceManager &SM) override;
+
+ void emitCodeContext(SourceLocation Loc,
+ DiagnosticsEngine::Level Level,
+ SmallVectorImpl<CharSourceRange>& Ranges,
+ ArrayRef<FixItHint> Hints,
+ const SourceManager &SM) override {
+ emitSnippetAndCaret(Loc, Level, Ranges, Hints, SM);
+ }
+
+ void emitIncludeLocation(SourceLocation Loc, PresumedLoc PLoc,
+ const SourceManager &SM) override;
+
+ void emitImportLocation(SourceLocation Loc, PresumedLoc PLoc,
+ StringRef ModuleName,
+ const SourceManager &SM) override;
+
+ void emitBuildingModuleLocation(SourceLocation Loc, PresumedLoc PLoc,
+ StringRef ModuleName,
+ const SourceManager &SM) override;
+
+private:
+ void emitSnippetAndCaret(SourceLocation Loc, DiagnosticsEngine::Level Level,
+ SmallVectorImpl<CharSourceRange>& Ranges,
+ ArrayRef<FixItHint> Hints,
+ const SourceManager &SM);
+
+ void emitSnippet(StringRef SourceLine);
+
+ void emitParseableFixits(ArrayRef<FixItHint> Hints, const SourceManager &SM);
+};
+
+} // end namespace clang
+
+#endif
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..3bcf824
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Frontend/TextDiagnosticBuffer.h
@@ -0,0 +1,55 @@
+//===--- 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_TEXTDIAGNOSTICBUFFER_H
+#define LLVM_CLANG_FRONTEND_TEXTDIAGNOSTICBUFFER_H
+
+#include "clang/Basic/Diagnostic.h"
+#include <vector>
+
+namespace clang {
+
+class Preprocessor;
+class SourceManager;
+
+class TextDiagnosticBuffer : public DiagnosticConsumer {
+public:
+ typedef std::vector<std::pair<SourceLocation, std::string> > DiagList;
+ typedef DiagList::iterator iterator;
+ typedef DiagList::const_iterator const_iterator;
+private:
+ DiagList Errors, Warnings, Remarks, 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 remark_begin() const { return Remarks.begin(); }
+ const_iterator remark_end() const { return Remarks.end(); }
+
+ const_iterator note_begin() const { return Notes.begin(); }
+ const_iterator note_end() const { return Notes.end(); }
+
+ void HandleDiagnostic(DiagnosticsEngine::Level DiagLevel,
+ const Diagnostic &Info) override;
+
+ /// FlushDiagnostics - Flush the buffered diagnostics to an given
+ /// diagnostic engine.
+ void FlushDiagnostics(DiagnosticsEngine &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..04a5705
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Frontend/TextDiagnosticPrinter.h
@@ -0,0 +1,58 @@
+//===--- 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_TEXTDIAGNOSTICPRINTER_H
+#define LLVM_CLANG_FRONTEND_TEXTDIAGNOSTICPRINTER_H
+
+#include "clang/Basic/Diagnostic.h"
+#include "clang/Basic/LLVM.h"
+#include "llvm/ADT/IntrusiveRefCntPtr.h"
+#include <memory>
+
+namespace clang {
+class DiagnosticOptions;
+class LangOptions;
+class TextDiagnostic;
+
+class TextDiagnosticPrinter : public DiagnosticConsumer {
+ raw_ostream &OS;
+ IntrusiveRefCntPtr<DiagnosticOptions> DiagOpts;
+
+ /// \brief Handle to the currently active text diagnostic emitter.
+ std::unique_ptr<TextDiagnostic> TextDiag;
+
+ /// A string to prefix to error messages.
+ std::string Prefix;
+
+ unsigned OwnsOutputStream : 1;
+
+public:
+ TextDiagnosticPrinter(raw_ostream &os, DiagnosticOptions *diags,
+ bool OwnsOutputStream = false);
+ ~TextDiagnosticPrinter() override;
+
+ /// 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) override;
+ void EndSourceFile() override;
+ void HandleDiagnostic(DiagnosticsEngine::Level Level,
+ const Diagnostic &Info) override;
+};
+
+} // end namespace clang
+
+#endif
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..a5f667e
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Frontend/Utils.h
@@ -0,0 +1,220 @@
+//===--- 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 "clang/Basic/Diagnostic.h"
+#include "clang/Basic/VirtualFileSystem.h"
+#include "llvm/ADT/IntrusiveRefCntPtr.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/ADT/StringSet.h"
+#include "llvm/Option/OptSpecifier.h"
+
+namespace llvm {
+class raw_fd_ostream;
+class Triple;
+
+namespace opt {
+class ArgList;
+}
+}
+
+namespace clang {
+class ASTConsumer;
+class ASTReader;
+class CompilerInstance;
+class CompilerInvocation;
+class Decl;
+class DependencyOutputOptions;
+class DiagnosticsEngine;
+class DiagnosticOptions;
+class ExternalSemaSource;
+class FileManager;
+class HeaderSearch;
+class HeaderSearchOptions;
+class IdentifierTable;
+class LangOptions;
+class PCHContainerReader;
+class Preprocessor;
+class PreprocessorOptions;
+class PreprocessorOutputOptions;
+class SourceManager;
+class Stmt;
+class TargetInfo;
+class FrontendOptions;
+
+/// 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 PCHContainerReader &PCHContainerRdr,
+ const FrontendOptions &FEOpts);
+
+/// DoPrintPreprocessedInput - Implement -E mode.
+void DoPrintPreprocessedInput(Preprocessor &PP, raw_ostream* OS,
+ const PreprocessorOutputOptions &Opts);
+
+/// An interface for collecting the dependencies of a compilation. Users should
+/// use \c attachToPreprocessor and \c attachToASTReader to get all of the
+/// dependencies.
+// FIXME: Migrate DependencyFileGen, DependencyGraphGen, ModuleDepCollectory to
+// use this interface.
+class DependencyCollector {
+public:
+ void attachToPreprocessor(Preprocessor &PP);
+ void attachToASTReader(ASTReader &R);
+ llvm::ArrayRef<std::string> getDependencies() const { return Dependencies; }
+
+ /// Called when a new file is seen. Return true if \p Filename should be added
+ /// to the list of dependencies.
+ ///
+ /// The default implementation ignores <built-in> and system files.
+ virtual bool sawDependency(StringRef Filename, bool FromModule,
+ bool IsSystem, bool IsModuleFile, bool IsMissing);
+ /// Called when the end of the main file is reached.
+ virtual void finishedMainFile() { }
+ /// Return true if system files should be passed to sawDependency().
+ virtual bool needSystemDependencies() { return false; }
+ virtual ~DependencyCollector();
+
+public: // implementation detail
+ /// Add a dependency \p Filename if it has not been seen before and
+ /// sawDependency() returns true.
+ void maybeAddDependency(StringRef Filename, bool FromModule, bool IsSystem,
+ bool IsModuleFile, bool IsMissing);
+private:
+ llvm::StringSet<> Seen;
+ std::vector<std::string> Dependencies;
+};
+
+/// Builds a depdenency file when attached to a Preprocessor (for includes) and
+/// ASTReader (for module imports), and writes it out at the end of processing
+/// a source file. Users should attach to the ast reader whenever a module is
+/// loaded.
+class DependencyFileGenerator {
+ void *Impl; // Opaque implementation
+ DependencyFileGenerator(void *Impl);
+public:
+ static DependencyFileGenerator *CreateAndAttachToPreprocessor(
+ Preprocessor &PP, const DependencyOutputOptions &Opts);
+ void AttachToASTReader(ASTReader &R);
+};
+
+/// Collects the dependencies for imported modules into a directory. Users
+/// should attach to the AST reader whenever a module is loaded.
+class ModuleDependencyCollector {
+ std::string DestDir;
+ bool HasErrors;
+ llvm::StringSet<> Seen;
+ vfs::YAMLVFSWriter VFSWriter;
+
+public:
+ StringRef getDest() { return DestDir; }
+ bool insertSeen(StringRef Filename) { return Seen.insert(Filename).second; }
+ void setHasErrors() { HasErrors = true; }
+ void addFileMapping(StringRef VPath, StringRef RPath) {
+ VFSWriter.addFileMapping(VPath, RPath);
+ }
+
+ void attachToASTReader(ASTReader &R);
+ void writeFileMap();
+ bool hasErrors() { return HasErrors; }
+ ModuleDependencyCollector(std::string DestDir)
+ : DestDir(DestDir), HasErrors(false) {}
+ ~ModuleDependencyCollector() { writeFileMap(); }
+};
+
+/// AttachDependencyGraphGen - Create a dependency graph generator, and attach
+/// it to the given preprocessor.
+ void AttachDependencyGraphGen(Preprocessor &PP, StringRef OutputFile,
+ StringRef SysRoot);
+
+/// AttachHeaderIncludeGen - Create a header include list generator, and attach
+/// it to the given preprocessor.
+///
+/// \param ExtraHeaders - If not empty, will write the header filenames, just
+/// like they were included during a regular preprocessing. Useful for
+/// implicit include dependencies, like sanitizer blacklists.
+/// \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.
+/// \param ShowDepth - Whether to indent to show the nesting of the includes.
+/// \param MSStyle - Whether to print in cl.exe /showIncludes style.
+void AttachHeaderIncludeGen(Preprocessor &PP,
+ const std::vector<std::string> &ExtraHeaders,
+ bool ShowAllHeaders = false,
+ StringRef OutputPath = "",
+ bool ShowDepth = true, bool MSStyle = false);
+
+/// Cache tokens for use with PCH. Note that this requires a seekable stream.
+void CacheTokens(Preprocessor &PP, raw_pwrite_stream *OS);
+
+/// The ChainedIncludesSource class converts headers to chained PCHs in
+/// memory, mainly for testing.
+IntrusiveRefCntPtr<ExternalSemaSource>
+createChainedIncludesSource(CompilerInstance &CI,
+ IntrusiveRefCntPtr<ExternalSemaSource> &Reader);
+
+/// createInvocationFromCommandLine - Construct a compiler invocation object for
+/// a command line argument vector.
+///
+/// \return A CompilerInvocation, or 0 if none was built for the given
+/// argument vector.
+CompilerInvocation *
+createInvocationFromCommandLine(ArrayRef<const char *> Args,
+ IntrusiveRefCntPtr<DiagnosticsEngine> Diags =
+ IntrusiveRefCntPtr<DiagnosticsEngine>());
+
+/// Return the value of the last argument as an integer, or a default. If Diags
+/// is non-null, emits an error if the argument is given, but non-integral.
+int getLastArgIntValue(const llvm::opt::ArgList &Args,
+ llvm::opt::OptSpecifier Id, int Default,
+ DiagnosticsEngine *Diags = nullptr);
+
+inline int getLastArgIntValue(const llvm::opt::ArgList &Args,
+ llvm::opt::OptSpecifier Id, int Default,
+ DiagnosticsEngine &Diags) {
+ return getLastArgIntValue(Args, Id, Default, &Diags);
+}
+
+uint64_t getLastArgUInt64Value(const llvm::opt::ArgList &Args,
+ llvm::opt::OptSpecifier Id, uint64_t Default,
+ DiagnosticsEngine *Diags = nullptr);
+
+inline uint64_t getLastArgUInt64Value(const llvm::opt::ArgList &Args,
+ llvm::opt::OptSpecifier Id,
+ uint64_t Default,
+ DiagnosticsEngine &Diags) {
+ return getLastArgUInt64Value(Args, Id, Default, &Diags);
+}
+
+// When Clang->getFrontendOpts().DisableFree is set we don't delete some of the
+// global objects, but we don't want LeakDetectors to complain, so we bury them
+// in a globally visible array.
+void BuryPointer(const void *Ptr);
+template <typename T> void BuryPointer(std::unique_ptr<T> Ptr) {
+ BuryPointer(Ptr.release());
+}
+
+} // end namespace clang
+
+#endif
diff --git a/contrib/llvm/tools/clang/include/clang/Frontend/VerifyDiagnosticConsumer.h b/contrib/llvm/tools/clang/include/clang/Frontend/VerifyDiagnosticConsumer.h
new file mode 100644
index 0000000..475f07f
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Frontend/VerifyDiagnosticConsumer.h
@@ -0,0 +1,278 @@
+//===- VerifyDiagnosticConsumer.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_VERIFYDIAGNOSTICCONSUMER_H
+#define LLVM_CLANG_FRONTEND_VERIFYDIAGNOSTICCONSUMER_H
+
+#include "clang/Basic/Diagnostic.h"
+#include "clang/Lex/Preprocessor.h"
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/PointerIntPair.h"
+#include "llvm/ADT/STLExtras.h"
+#include <climits>
+#include <memory>
+
+namespace clang {
+
+class DiagnosticsEngine;
+class TextDiagnosticBuffer;
+class FileEntry;
+
+/// VerifyDiagnosticConsumer - 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:
+///
+/// \code
+/// expected-{error,warning,remark,note}
+/// \endcode
+///
+/// to tag if it's an expected error, remark 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:
+///
+/// \code
+/// int A = B; // expected-error {{use of undeclared identifier 'B'}}
+/// \endcode
+///
+/// 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.
+///
+/// Alternatively, it is possible to specify the line on which the diagnostic
+/// should appear by appending "@<line>" to "expected-<type>", for example:
+///
+/// \code
+/// #warning some text
+/// // expected-warning@10 {{some text}}
+/// \endcode
+///
+/// The line number may be absolute (as above), or relative to the current
+/// line by prefixing the number with either '+' or '-'.
+///
+/// If the diagnostic is generated in a separate file, for example in a shared
+/// header file, it may be beneficial to be able to declare the file in which
+/// the diagnostic will appear, rather than placing the expected-* directive in
+/// the actual file itself. This can be done using the following syntax:
+///
+/// \code
+/// // expected-error@path/include.h:15 {{error message}}
+/// \endcode
+///
+/// The path can be absolute or relative and the same search paths will be used
+/// as for #include directives. The line number in an external file may be
+/// substituted with '*' meaning that any line number will match (useful where
+/// the included file is, for example, a system header where the actual line
+/// number may change and is not critical).
+///
+/// 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:
+///
+/// \code
+/// void f(); // expected-note 2 {{previous declaration is here}}
+/// \endcode
+///
+/// Where the diagnostic is expected to occur a minimum number of times, this
+/// can be specified by appending a '+' to the number. Example:
+///
+/// \code
+/// void f(); // expected-note 0+ {{previous declaration is here}}
+/// void g(); // expected-note 1+ {{previous declaration is here}}
+/// \endcode
+///
+/// In the first example, the diagnostic becomes optional, i.e. it will be
+/// swallowed if it occurs, but will not generate an error if it does not
+/// occur. In the second example, the diagnostic must occur at least once.
+/// As a short-hand, "one or more" can be specified simply by '+'. Example:
+///
+/// \code
+/// void g(); // expected-note + {{previous declaration is here}}
+/// \endcode
+///
+/// A range can also be specified by "<n>-<m>". Example:
+///
+/// \code
+/// void f(); // expected-note 0-1 {{previous declaration is here}}
+/// \endcode
+///
+/// In this example, the diagnostic may appear only once, if at all.
+///
+/// Regex matching mode may be selected by appending '-re' to type and
+/// including regexes wrapped in double curly braces in the directive, such as:
+///
+/// \code
+/// expected-error-re {{format specifies type 'wchar_t **' (aka '{{.+}}')}}
+/// \endcode
+///
+/// Examples matching error: "variable has incomplete type 'struct s'"
+///
+/// \code
+/// // expected-error {{variable has incomplete type 'struct s'}}
+/// // expected-error {{variable has incomplete type}}
+///
+/// // expected-error-re {{variable has type 'struct {{.}}'}}
+/// // expected-error-re {{variable has type 'struct {{.*}}'}}
+/// // expected-error-re {{variable has type 'struct {{(.*)}}'}}
+/// // expected-error-re {{variable has type 'struct{{[[:space:]](.*)}}'}}
+/// \endcode
+///
+/// VerifyDiagnosticConsumer expects at least one expected-* directive to
+/// be found inside the source code. If no diagnostics are expected the
+/// following directive can be used to indicate this:
+///
+/// \code
+/// // expected-no-diagnostics
+/// \endcode
+///
+class VerifyDiagnosticConsumer: public DiagnosticConsumer,
+ public CommentHandler {
+public:
+ /// Directive - Abstract class representing a parsed verify directive.
+ ///
+ class Directive {
+ public:
+ static std::unique_ptr<Directive> create(bool RegexKind,
+ SourceLocation DirectiveLoc,
+ SourceLocation DiagnosticLoc,
+ bool MatchAnyLine, StringRef Text,
+ unsigned Min, unsigned Max);
+
+ public:
+ /// Constant representing n or more matches.
+ static const unsigned MaxCount = UINT_MAX;
+
+ SourceLocation DirectiveLoc;
+ SourceLocation DiagnosticLoc;
+ const std::string Text;
+ unsigned Min, Max;
+ bool MatchAnyLine;
+
+ 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(StringRef S) = 0;
+
+ protected:
+ Directive(SourceLocation DirectiveLoc, SourceLocation DiagnosticLoc,
+ bool MatchAnyLine, StringRef Text, unsigned Min, unsigned Max)
+ : DirectiveLoc(DirectiveLoc), DiagnosticLoc(DiagnosticLoc),
+ Text(Text), Min(Min), Max(Max), MatchAnyLine(MatchAnyLine) {
+ assert(!DirectiveLoc.isInvalid() && "DirectiveLoc is invalid!");
+ assert(!DiagnosticLoc.isInvalid() && "DiagnosticLoc is invalid!");
+ }
+
+ private:
+ Directive(const Directive &) = delete;
+ void operator=(const Directive &) = delete;
+ };
+
+ typedef std::vector<std::unique_ptr<Directive>> DirectiveList;
+
+ /// ExpectedData - owns directive objects and deletes on destructor.
+ ///
+ struct ExpectedData {
+ DirectiveList Errors;
+ DirectiveList Warnings;
+ DirectiveList Remarks;
+ DirectiveList Notes;
+
+ void Reset() {
+ Errors.clear();
+ Warnings.clear();
+ Remarks.clear();
+ Notes.clear();
+ }
+ };
+
+ enum DirectiveStatus {
+ HasNoDirectives,
+ HasNoDirectivesReported,
+ HasExpectedNoDiagnostics,
+ HasOtherExpectedDirectives
+ };
+
+private:
+ DiagnosticsEngine &Diags;
+ DiagnosticConsumer *PrimaryClient;
+ std::unique_ptr<DiagnosticConsumer> PrimaryClientOwner;
+ std::unique_ptr<TextDiagnosticBuffer> Buffer;
+ const Preprocessor *CurrentPreprocessor;
+ const LangOptions *LangOpts;
+ SourceManager *SrcManager;
+ unsigned ActiveSourceFiles;
+ DirectiveStatus Status;
+ ExpectedData ED;
+
+ void CheckDiagnostics();
+ void setSourceManager(SourceManager &SM) {
+ assert((!SrcManager || SrcManager == &SM) && "SourceManager changed!");
+ SrcManager = &SM;
+ }
+
+ // These facilities are used for validation in debug builds.
+ class UnparsedFileStatus {
+ llvm::PointerIntPair<const FileEntry *, 1, bool> Data;
+ public:
+ UnparsedFileStatus(const FileEntry *File, bool FoundDirectives)
+ : Data(File, FoundDirectives) {}
+ const FileEntry *getFile() const { return Data.getPointer(); }
+ bool foundDirectives() const { return Data.getInt(); }
+ };
+ typedef llvm::DenseMap<FileID, const FileEntry *> ParsedFilesMap;
+ typedef llvm::DenseMap<FileID, UnparsedFileStatus> UnparsedFilesMap;
+ ParsedFilesMap ParsedFiles;
+ UnparsedFilesMap UnparsedFiles;
+
+public:
+ /// Create a new verifying diagnostic client, which will issue errors to
+ /// the currently-attached diagnostic client when a diagnostic does not match
+ /// what is expected (as indicated in the source file).
+ VerifyDiagnosticConsumer(DiagnosticsEngine &Diags);
+ ~VerifyDiagnosticConsumer() override;
+
+ void BeginSourceFile(const LangOptions &LangOpts,
+ const Preprocessor *PP) override;
+
+ void EndSourceFile() override;
+
+ enum ParsedStatus {
+ /// File has been processed via HandleComment.
+ IsParsed,
+
+ /// File has diagnostics and may have directives.
+ IsUnparsed,
+
+ /// File has diagnostics but guaranteed no directives.
+ IsUnparsedNoDirectives
+ };
+
+ /// \brief Update lists of parsed and unparsed files.
+ void UpdateParsedFileStatus(SourceManager &SM, FileID FID, ParsedStatus PS);
+
+ bool HandleComment(Preprocessor &PP, SourceRange Comment) override;
+
+ void HandleDiagnostic(DiagnosticsEngine::Level DiagLevel,
+ const Diagnostic &Info) override;
+};
+
+} // 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/CommentToXML.h b/contrib/llvm/tools/clang/include/clang/Index/CommentToXML.h
new file mode 100644
index 0000000..bb7b71a
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Index/CommentToXML.h
@@ -0,0 +1,52 @@
+//===--- CommentToXML.h - Convert comments to XML representation ----------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_INDEX_COMMENTTOXML_H
+#define LLVM_CLANG_INDEX_COMMENTTOXML_H
+
+#include "clang/Basic/LLVM.h"
+#include <memory>
+
+namespace clang {
+class ASTContext;
+
+namespace comments {
+class FullComment;
+class HTMLTagComment;
+}
+
+namespace index {
+class SimpleFormatContext;
+
+class CommentToXMLConverter {
+ std::unique_ptr<SimpleFormatContext> FormatContext;
+ unsigned FormatInMemoryUniqueId;
+
+public:
+ CommentToXMLConverter();
+ ~CommentToXMLConverter();
+
+ void convertCommentToHTML(const comments::FullComment *FC,
+ SmallVectorImpl<char> &HTML,
+ const ASTContext &Context);
+
+ void convertHTMLTagNodeToText(const comments::HTMLTagComment *HTC,
+ SmallVectorImpl<char> &Text,
+ const ASTContext &Context);
+
+ void convertCommentToXML(const comments::FullComment *FC,
+ SmallVectorImpl<char> &XML,
+ const ASTContext &Context);
+};
+
+} // namespace index
+} // namespace clang
+
+#endif // LLVM_CLANG_INDEX_COMMENTTOXML_H
+
diff --git a/contrib/llvm/tools/clang/include/clang/Index/USRGeneration.h b/contrib/llvm/tools/clang/include/clang/Index/USRGeneration.h
new file mode 100644
index 0000000..55e35cc
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Index/USRGeneration.h
@@ -0,0 +1,62 @@
+//===- USRGeneration.h - Routines for USR generation ----------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_INDEX_USRGENERATION_H
+#define LLVM_CLANG_INDEX_USRGENERATION_H
+
+#include "clang/Basic/LLVM.h"
+#include "llvm/ADT/StringRef.h"
+
+namespace clang {
+class Decl;
+class MacroDefinitionRecord;
+class SourceManager;
+
+namespace index {
+
+static inline StringRef getUSRSpacePrefix() {
+ return "c:";
+}
+
+/// \brief Generate a USR for a Decl, including the USR prefix.
+/// \returns true if the results should be ignored, false otherwise.
+bool generateUSRForDecl(const Decl *D, SmallVectorImpl<char> &Buf);
+
+/// \brief Generate a USR fragment for an Objective-C class.
+void generateUSRForObjCClass(StringRef Cls, raw_ostream &OS);
+
+/// \brief Generate a USR fragment for an Objective-C class category.
+void generateUSRForObjCCategory(StringRef Cls, StringRef Cat, raw_ostream &OS);
+
+/// \brief Generate a USR fragment for an Objective-C instance variable. The
+/// complete USR can be created by concatenating the USR for the
+/// encompassing class with this USR fragment.
+void generateUSRForObjCIvar(StringRef Ivar, raw_ostream &OS);
+
+/// \brief Generate a USR fragment for an Objective-C method.
+void generateUSRForObjCMethod(StringRef Sel, bool IsInstanceMethod,
+ raw_ostream &OS);
+
+/// \brief Generate a USR fragment for an Objective-C property.
+void generateUSRForObjCProperty(StringRef Prop, raw_ostream &OS);
+
+/// \brief Generate a USR fragment for an Objective-C protocol.
+void generateUSRForObjCProtocol(StringRef Prot, raw_ostream &OS);
+
+/// \brief Generate a USR for a macro, including the USR prefix.
+///
+/// \returns true on error, false on success.
+bool generateUSRForMacro(const MacroDefinitionRecord *MD,
+ const SourceManager &SM, SmallVectorImpl<char> &Buf);
+
+} // namespace index
+} // namespace clang
+
+#endif // LLVM_CLANG_IDE_USRGENERATION_H
+
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..91c3b78
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Lex/CodeCompletionHandler.h
@@ -0,0 +1,71 @@
+//===--- 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.
+ ///
+ /// There will be another callback invocation after the macro arguments are
+ /// parsed, so this callback should generally be used to note that the next
+ /// callback is invoked inside a 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..20c4bb0
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Lex/DirectoryLookup.h
@@ -0,0 +1,196 @@
+//===--- 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/LLVM.h"
+#include "clang/Basic/SourceManager.h"
+#include "clang/Lex/ModuleMap.h"
+
+namespace clang {
+class HeaderMap;
+class DirectoryEntry;
+class FileEntry;
+class HeaderSearch;
+class Module;
+
+/// 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;
+
+ /// LookupType - This indicates whether this DirectoryLookup object is a
+ /// normal directory, a framework, or a headermap.
+ unsigned LookupType : 2;
+
+ /// \brief Whether this is a header map used when building a framework.
+ unsigned IsIndexHeaderMap : 1;
+
+ /// \brief Whether we've performed an exhaustive search for module maps
+ /// within the subdirectories of this directory.
+ unsigned SearchedAllModuleMaps : 1;
+
+public:
+ /// DirectoryLookup ctor - Note that this ctor *does not take ownership* of
+ /// 'dir'.
+ DirectoryLookup(const DirectoryEntry *dir, SrcMgr::CharacteristicKind DT,
+ bool isFramework)
+ : DirCharacteristic(DT),
+ LookupType(isFramework ? LT_Framework : LT_NormalDir),
+ IsIndexHeaderMap(false), SearchedAllModuleMaps(false) {
+ u.Dir = dir;
+ }
+
+ /// DirectoryLookup ctor - Note that this ctor *does not take ownership* of
+ /// 'map'.
+ DirectoryLookup(const HeaderMap *map, SrcMgr::CharacteristicKind DT,
+ bool isIndexHeaderMap)
+ : DirCharacteristic(DT), LookupType(LT_HeaderMap),
+ IsIndexHeaderMap(isIndexHeaderMap), SearchedAllModuleMaps(false) {
+ 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 : nullptr;
+ }
+
+ /// getFrameworkDir - Return the directory that this framework refers to.
+ ///
+ const DirectoryEntry *getFrameworkDir() const {
+ return isFramework() ? u.Dir : nullptr;
+ }
+
+ /// getHeaderMap - Return the directory that this entry refers to.
+ ///
+ const HeaderMap *getHeaderMap() const {
+ return isHeaderMap() ? u.Map : nullptr;
+ }
+
+ /// 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; }
+
+ /// \brief Determine whether we have already searched this entire
+ /// directory for module maps.
+ bool haveSearchedAllModuleMaps() const { return SearchedAllModuleMaps; }
+
+ /// \brief Specify whether we have already searched all of the subdirectories
+ /// for module maps.
+ void setSearchedAllModuleMaps(bool SAMM) {
+ SearchedAllModuleMaps = SAMM;
+ }
+
+ /// DirCharacteristic - The type of directory this is, one of the DirType enum
+ /// values.
+ SrcMgr::CharacteristicKind getDirCharacteristic() const {
+ return (SrcMgr::CharacteristicKind)DirCharacteristic;
+ }
+
+ /// \brief Whether this describes a system header directory.
+ bool isSystemHeaderDirectory() const {
+ return getDirCharacteristic() != SrcMgr::C_User;
+ }
+
+ /// \brief Whether this header map is building a framework or not.
+ bool isIndexHeaderMap() const {
+ return isHeaderMap() && IsIndexHeaderMap;
+ }
+
+ /// LookupFile - Lookup the specified file in this search path, returning it
+ /// if it exists or returning null if not.
+ ///
+ /// \param Filename The file to look up relative to the search paths.
+ ///
+ /// \param HS The header search instance to search with.
+ ///
+ /// \param SearchPath If not NULL, will be set to the search path relative
+ /// to which the file was found.
+ ///
+ /// \param RelativePath If not NULL, will be set to the path relative to
+ /// SearchPath at which the file was found. This only differs from the
+ /// Filename for framework includes.
+ ///
+ /// \param RequestingModule The module in which the lookup was performed.
+ ///
+ /// \param SuggestedModule If non-null, and the file found is semantically
+ /// part of a known module, this will be set to the module that should
+ /// be imported instead of preprocessing/parsing the file found.
+ ///
+ /// \param [out] InUserSpecifiedSystemFramework If the file is found,
+ /// set to true if the file is located in a framework that has been
+ /// user-specified to be treated as a system framework.
+ ///
+ /// \param [out] MappedName if this is a headermap which maps the filename to
+ /// a framework include ("Foo.h" -> "Foo/Foo.h"), set the new name to this
+ /// vector and point Filename to it.
+ const FileEntry *LookupFile(StringRef &Filename, HeaderSearch &HS,
+ SmallVectorImpl<char> *SearchPath,
+ SmallVectorImpl<char> *RelativePath,
+ Module *RequestingModule,
+ ModuleMap::KnownHeader *SuggestedModule,
+ bool &InUserSpecifiedSystemFramework,
+ bool &HasBeenMapped,
+ SmallVectorImpl<char> &MappedName) const;
+
+private:
+ const FileEntry *DoFrameworkLookup(
+ StringRef Filename, HeaderSearch &HS,
+ SmallVectorImpl<char> *SearchPath,
+ SmallVectorImpl<char> *RelativePath,
+ Module *RequestingModule,
+ ModuleMap::KnownHeader *SuggestedModule,
+ bool &InUserSpecifiedSystemHeader) 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..adf8e71
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Lex/ExternalPreprocessorSource.h
@@ -0,0 +1,48 @@
+//===- 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_EXTERNALPREPROCESSORSOURCE_H
+#define LLVM_CLANG_LEX_EXTERNALPREPROCESSORSOURCE_H
+
+namespace clang {
+
+class IdentifierInfo;
+class Module;
+
+/// \brief Abstract interface for external sources of preprocessor
+/// information.
+///
+/// This abstract class allows an external sources (such as the \c ASTReader)
+/// to provide additional preprocessing information.
+class ExternalPreprocessorSource {
+public:
+ virtual ~ExternalPreprocessorSource();
+
+ /// \brief Read the set of macros defined by this external macro source.
+ virtual void ReadDefinedMacros() = 0;
+
+ /// \brief Update an out-of-date identifier.
+ virtual void updateOutOfDateIdentifier(IdentifierInfo &II) = 0;
+
+ /// \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;
+
+ /// \brief Map a module ID to a module.
+ virtual Module *getModule(unsigned ModuleID) = 0;
+};
+
+}
+
+#endif
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..183361e
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Lex/HeaderMap.h
@@ -0,0 +1,76 @@
+//===--- 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
+
+#include "clang/Basic/LLVM.h"
+#include "llvm/Support/Compiler.h"
+#include <memory>
+
+namespace llvm {
+ class MemoryBuffer;
+}
+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 &) = delete;
+ void operator=(const HeaderMap &) = delete;
+
+ std::unique_ptr<const llvm::MemoryBuffer> FileBuffer;
+ bool NeedsBSwap;
+
+ HeaderMap(std::unique_ptr<const llvm::MemoryBuffer> File, bool BSwap)
+ : FileBuffer(std::move(File)), NeedsBSwap(BSwap) {}
+public:
+ /// 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.
+ /// If RawPath is not NULL and the file is found, RawPath will be set to the
+ /// raw path at which the file was found in the file system. For example,
+ /// for a search path ".." and a filename "../file.h" this would be
+ /// "../../file.h".
+ const FileEntry *LookupFile(StringRef Filename, FileManager &FM) const;
+
+ /// If the specified relative filename is located in this HeaderMap return
+ /// the filename it is mapped to, otherwise return an empty StringRef.
+ StringRef lookupFilename(StringRef Filename,
+ SmallVectorImpl<char> &DestPath) 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..6d592e1
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Lex/HeaderSearch.h
@@ -0,0 +1,688 @@
+//===--- 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 "clang/Lex/ModuleMap.h"
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/IntrusiveRefCntPtr.h"
+#include "llvm/ADT/StringMap.h"
+#include "llvm/ADT/StringSet.h"
+#include "llvm/Support/Allocator.h"
+#include <memory>
+#include <vector>
+
+namespace clang {
+
+class DiagnosticsEngine;
+class ExternalPreprocessorSource;
+class FileEntry;
+class FileManager;
+class HeaderSearchOptions;
+class IdentifierInfo;
+class Preprocessor;
+
+/// \brief The preprocessor keeps track of this information for each
+/// file that is \#included.
+struct HeaderFileInfo {
+ /// \brief True if this is a \#import'd or \#pragma once file.
+ unsigned isImport : 1;
+
+ /// \brief True if this is a \#pragma once file.
+ unsigned isPragmaOnce : 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,
+ /// and has not changed since.
+ unsigned External : 1;
+
+ /// \brief Whether this header is part of a module.
+ unsigned isModuleHeader : 1;
+
+ /// \brief Whether this header is part of the module that we are building.
+ unsigned isCompilingModuleHeader : 1;
+
+ /// \brief Whether this structure is considered to already have been
+ /// "resolved", meaning that it was loaded from the external source.
+ unsigned Resolved : 1;
+
+ /// \brief Whether this is a header inside a framework that is currently
+ /// being built.
+ ///
+ /// When a framework is being built, the headers have not yet been placed
+ /// into the appropriate framework subdirectories, and therefore are
+ /// provided via a header map. This bit indicates when this is one of
+ /// those framework headers.
+ unsigned IndexHeaderMapHeader : 1;
+
+ /// \brief Whether this file has been looked up as a header.
+ unsigned IsValid : 1;
+
+ /// \brief 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;
+
+ /// 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;
+
+ /// \brief If this header came from a framework include, this is the name
+ /// of the framework.
+ StringRef Framework;
+
+ HeaderFileInfo()
+ : isImport(false), isPragmaOnce(false), DirInfo(SrcMgr::C_User),
+ External(false), isModuleHeader(false), isCompilingModuleHeader(false),
+ Resolved(false), IndexHeaderMapHeader(false), IsValid(0),
+ NumIncludes(0), ControllingMacroID(0), ControllingMacro(nullptr) {}
+
+ /// \brief Retrieve the controlling macro for this header file, if
+ /// any.
+ const IdentifierInfo *
+ getControllingMacro(ExternalPreprocessorSource *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 || isPragmaOnce || 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;
+};
+
+/// \brief Encapsulates the information needed to find the file referenced
+/// by a \#include or \#include_next, (sub-)framework lookup, etc.
+class HeaderSearch {
+ /// This structure is used to record entries in our framework cache.
+ struct FrameworkCacheEntry {
+ /// The directory entry which should be used for the cached framework.
+ const DirectoryEntry *Directory;
+
+ /// Whether this framework has been "user-specified" to be treated as if it
+ /// were a system framework (even if it was found outside a system framework
+ /// directory).
+ bool IsUserSpecifiedSystemFramework;
+ };
+
+ /// \brief Header-search options used to initialize this header search.
+ IntrusiveRefCntPtr<HeaderSearchOptions> HSOpts;
+
+ DiagnosticsEngine &Diags;
+ FileManager &FileMgr;
+ /// \#include search path information. Requests for \#include "x" search the
+ /// directory of the \#including file first, then each directory in SearchDirs
+ /// consecutively. Requests for <x> search the current dir first, then each
+ /// directory in SearchDirs, starting at AngledDirIdx, consecutively. If
+ /// NoCurDirSearch is true, then the check for the file in the current
+ /// directory is suppressed.
+ std::vector<DirectoryLookup> SearchDirs;
+ unsigned AngledDirIdx;
+ unsigned SystemDirIdx;
+ bool NoCurDirSearch;
+
+ /// \brief \#include prefixes for which the 'system header' property is
+ /// overridden.
+ ///
+ /// For a \#include "x" or \#include \<x> directive, the last string in this
+ /// list which is a prefix of 'x' determines whether the file is treated as
+ /// a system header.
+ std::vector<std::pair<std::string, bool> > SystemHeaderPrefixes;
+
+ /// \brief The path to the module cache.
+ std::string ModuleCachePath;
+
+ /// \brief All of the preprocessor-specific data about files that are
+ /// included, indexed by the FileEntry's UID.
+ mutable std::vector<HeaderFileInfo> FileInfo;
+
+ /// Keeps track of each lookup performed by LookupFile.
+ struct LookupFileCacheInfo {
+ /// 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.
+ unsigned StartIdx;
+ /// The entry in SearchDirs that satisfied the query.
+ unsigned HitIdx;
+ /// This is non-null if the original filename was mapped to a framework
+ /// include via a headermap.
+ const char *MappedName;
+
+ /// Default constructor -- Initialize all members with zero.
+ LookupFileCacheInfo(): StartIdx(0), HitIdx(0), MappedName(nullptr) {}
+
+ void reset(unsigned StartIdx) {
+ this->StartIdx = StartIdx;
+ this->MappedName = nullptr;
+ }
+ };
+ llvm::StringMap<LookupFileCacheInfo, llvm::BumpPtrAllocator> LookupFileCache;
+
+ /// \brief Collection mapping a framework or subframework
+ /// name like "Carbon" to the Carbon.framework directory.
+ llvm::StringMap<FrameworkCacheEntry, llvm::BumpPtrAllocator> FrameworkMap;
+
+ /// IncludeAliases - maps include file names (including the quotes or
+ /// angle brackets) to other include file names. This is used to support the
+ /// include_alias pragma for Microsoft compatibility.
+ typedef llvm::StringMap<std::string, llvm::BumpPtrAllocator>
+ IncludeAliasMap;
+ std::unique_ptr<IncludeAliasMap> IncludeAliases;
+
+ /// 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 The mapping between modules and headers.
+ mutable ModuleMap ModMap;
+
+ /// \brief Describes whether a given directory has a module map in it.
+ llvm::DenseMap<const DirectoryEntry *, bool> DirectoryHasModuleMap;
+
+ /// \brief Set of module map files we've already loaded, and a flag indicating
+ /// whether they were valid or not.
+ llvm::DenseMap<const FileEntry *, bool> LoadedModuleMaps;
+
+ /// \brief Uniqued set of framework names, which is used to track which
+ /// headers were included as framework headers.
+ llvm::StringSet<llvm::BumpPtrAllocator> FrameworkNames;
+
+ /// \brief Entity used to resolve the identifier IDs of controlling
+ /// macros into IdentifierInfo pointers, and keep the identifire up to date,
+ /// as needed.
+ ExternalPreprocessorSource *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;
+
+ const LangOptions &LangOpts;
+
+ // HeaderSearch doesn't support default or copy construction.
+ HeaderSearch(const HeaderSearch&) = delete;
+ void operator=(const HeaderSearch&) = delete;
+
+ friend class DirectoryLookup;
+
+public:
+ HeaderSearch(IntrusiveRefCntPtr<HeaderSearchOptions> HSOpts,
+ SourceManager &SourceMgr, DiagnosticsEngine &Diags,
+ const LangOptions &LangOpts, const TargetInfo *Target);
+ ~HeaderSearch();
+
+ /// \brief Retrieve the header-search options with which this header search
+ /// was initialized.
+ HeaderSearchOptions &getHeaderSearchOpts() const { return *HSOpts; }
+
+ FileManager &getFileMgr() const { return FileMgr; }
+
+ /// \brief Interface for setting the file search paths.
+ void SetSearchPaths(const std::vector<DirectoryLookup> &dirs,
+ unsigned angledDirIdx, unsigned systemDirIdx,
+ bool noCurDirSearch) {
+ assert(angledDirIdx <= systemDirIdx && systemDirIdx <= dirs.size() &&
+ "Directory indicies are unordered");
+ SearchDirs = dirs;
+ AngledDirIdx = angledDirIdx;
+ SystemDirIdx = systemDirIdx;
+ NoCurDirSearch = noCurDirSearch;
+ //LookupFileCache.clear();
+ }
+
+ /// \brief Add an additional search path.
+ void AddSearchPath(const DirectoryLookup &dir, bool isAngled) {
+ unsigned idx = isAngled ? SystemDirIdx : AngledDirIdx;
+ SearchDirs.insert(SearchDirs.begin() + idx, dir);
+ if (!isAngled)
+ AngledDirIdx++;
+ SystemDirIdx++;
+ }
+
+ /// \brief Set the list of system header prefixes.
+ void SetSystemHeaderPrefixes(ArrayRef<std::pair<std::string, bool> > P) {
+ SystemHeaderPrefixes.assign(P.begin(), P.end());
+ }
+
+ /// \brief Checks whether the map exists or not.
+ bool HasIncludeAliasMap() const { return (bool)IncludeAliases; }
+
+ /// \brief Map the source include name to the dest include name.
+ ///
+ /// The Source should include the angle brackets or quotes, the dest
+ /// should not. This allows for distinction between <> and "" headers.
+ void AddIncludeAlias(StringRef Source, StringRef Dest) {
+ if (!IncludeAliases)
+ IncludeAliases.reset(new IncludeAliasMap);
+ (*IncludeAliases)[Source] = Dest;
+ }
+
+ /// MapHeaderToIncludeAlias - Maps one header file name to a different header
+ /// file name, for use with the include_alias pragma. Note that the source
+ /// file name should include the angle brackets or quotes. Returns StringRef
+ /// as null if the header cannot be mapped.
+ StringRef MapHeaderToIncludeAlias(StringRef Source) {
+ assert(IncludeAliases && "Trying to map headers when there's no map");
+
+ // Do any filename replacements before anything else
+ IncludeAliasMap::const_iterator Iter = IncludeAliases->find(Source);
+ if (Iter != IncludeAliases->end())
+ return Iter->second;
+ return StringRef();
+ }
+
+ /// \brief Set the path to the module cache.
+ void setModuleCachePath(StringRef CachePath) {
+ ModuleCachePath = CachePath;
+ }
+
+ /// \brief Retrieve the path to the module cache.
+ StringRef getModuleCachePath() const { return ModuleCachePath; }
+
+ /// \brief Consider modules when including files from this directory.
+ void setDirectoryHasModuleMap(const DirectoryEntry* Dir) {
+ DirectoryHasModuleMap[Dir] = true;
+ }
+
+ /// \brief Forget everything we know about headers so far.
+ void ClearFileInfo() {
+ FileInfo.clear();
+ }
+
+ void SetExternalLookup(ExternalPreprocessorSource *EPS) {
+ ExternalLookup = EPS;
+ }
+
+ ExternalPreprocessorSource *getExternalLookup() const {
+ return ExternalLookup;
+ }
+
+ /// \brief Set the external source of header information.
+ void SetExternalSource(ExternalHeaderFileInfoSource *ES) {
+ ExternalSource = ES;
+ }
+
+ /// \brief Set the target information for the header search, if not
+ /// already known.
+ void setTarget(const TargetInfo &Target);
+
+ /// \brief Given a "foo" or \<foo> reference, look up the indicated file,
+ /// return null on failure.
+ ///
+ /// \returns If successful, this returns 'UsedDir', the DirectoryLookup member
+ /// the file was found in, or null if not applicable.
+ ///
+ /// \param IncludeLoc Used for diagnostics if valid.
+ ///
+ /// \param isAngled indicates whether the file reference is a <> reference.
+ ///
+ /// \param CurDir If non-null, the file was found in the specified directory
+ /// search location. This is used to implement \#include_next.
+ ///
+ /// \param Includers Indicates where the \#including file(s) are, in case
+ /// relative searches are needed. In reverse order of inclusion.
+ ///
+ /// \param SearchPath If non-null, will be set to the search path relative
+ /// to which the file was found. If the include path is absolute, SearchPath
+ /// will be set to an empty string.
+ ///
+ /// \param RelativePath If non-null, will be set to the path relative to
+ /// SearchPath at which the file was found. This only differs from the
+ /// Filename for framework includes.
+ ///
+ /// \param SuggestedModule If non-null, and the file found is semantically
+ /// part of a known module, this will be set to the module that should
+ /// be imported instead of preprocessing/parsing the file found.
+ const FileEntry *LookupFile(
+ StringRef Filename, SourceLocation IncludeLoc, bool isAngled,
+ const DirectoryLookup *FromDir, const DirectoryLookup *&CurDir,
+ ArrayRef<std::pair<const FileEntry *, const DirectoryEntry *>> Includers,
+ SmallVectorImpl<char> *SearchPath, SmallVectorImpl<char> *RelativePath,
+ Module *RequestingModule, ModuleMap::KnownHeader *SuggestedModule,
+ bool SkipCache = false);
+
+ /// \brief 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(
+ StringRef Filename, const FileEntry *RelativeFileEnt,
+ SmallVectorImpl<char> *SearchPath, SmallVectorImpl<char> *RelativePath,
+ Module *RequestingModule, ModuleMap::KnownHeader *SuggestedModule);
+
+ /// \brief Look up the specified framework name in our framework cache.
+ /// \returns The DirectoryEntry it is in if we know, null otherwise.
+ FrameworkCacheEntry &LookupFrameworkCache(StringRef FWName) {
+ return FrameworkMap[FWName];
+ }
+
+ /// \brief 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(Preprocessor &PP, const FileEntry *File,
+ bool isImport, Module *CorrespondingModule);
+
+ /// \brief 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;
+ }
+
+ /// \brief Mark the specified file as a "once only" file, e.g. due to
+ /// \#pragma once.
+ void MarkFileIncludeOnce(const FileEntry *File) {
+ HeaderFileInfo &FI = getFileInfo(File);
+ FI.isImport = true;
+ FI.isPragmaOnce = true;
+ }
+
+ /// \brief 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;
+ }
+
+ /// \brief Mark the specified file as part of a module.
+ void MarkFileModuleHeader(const FileEntry *File,
+ ModuleMap::ModuleHeaderRole Role,
+ bool IsCompiledModuleHeader);
+
+ /// \brief Increment the count for the number of times the specified
+ /// FileEntry has been entered.
+ void IncrementIncludeCount(const FileEntry *File) {
+ ++getFileInfo(File).NumIncludes;
+ }
+
+ /// \brief 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;
+ }
+
+ /// \brief Return true if this is the first time encountering this header.
+ bool FirstTimeLexingFile(const FileEntry *File) {
+ return getFileInfo(File).NumIncludes == 1;
+ }
+
+ /// \brief Determine whether this file is intended to be safe from
+ /// multiple inclusions, e.g., it has \#pragma once or a controlling
+ /// macro.
+ ///
+ /// This routine does not consider the effect of \#import
+ bool isFileMultipleIncludeGuarded(const FileEntry *File);
+
+ /// CreateHeaderMap - This method returns a HeaderMap for the specified
+ /// FileEntry, uniquing them through the 'HeaderMaps' datastructure.
+ const HeaderMap *CreateHeaderMap(const FileEntry *FE);
+
+ /// \brief Retrieve the name of the module file that should be used to
+ /// load the given module.
+ ///
+ /// \param Module The module whose module file name will be returned.
+ ///
+ /// \returns The name of the module file that corresponds to this module,
+ /// or an empty string if this module does not correspond to any module file.
+ std::string getModuleFileName(Module *Module);
+
+ /// \brief Retrieve the name of the module file that should be used to
+ /// load a module with the given name.
+ ///
+ /// \param ModuleName The module whose module file name will be returned.
+ ///
+ /// \param ModuleMapPath A path that when combined with \c ModuleName
+ /// uniquely identifies this module. See Module::ModuleMap.
+ ///
+ /// \returns The name of the module file that corresponds to this module,
+ /// or an empty string if this module does not correspond to any module file.
+ std::string getModuleFileName(StringRef ModuleName, StringRef ModuleMapPath);
+
+ /// \brief Lookup a module Search for a module with the given name.
+ ///
+ /// \param ModuleName The name of the module we're looking for.
+ ///
+ /// \param AllowSearch Whether we are allowed to search in the various
+ /// search directories to produce a module definition. If not, this lookup
+ /// will only return an already-known module.
+ ///
+ /// \returns The module with the given name.
+ Module *lookupModule(StringRef ModuleName, bool AllowSearch = true);
+
+ /// \brief Try to find a module map file in the given directory, returning
+ /// \c nullptr if none is found.
+ const FileEntry *lookupModuleMapFile(const DirectoryEntry *Dir,
+ bool IsFramework);
+
+ void IncrementFrameworkLookupCount() { ++NumFrameworkLookups; }
+
+ /// \brief Determine whether there is a module map that may map the header
+ /// with the given file name to a (sub)module.
+ /// Always returns false if modules are disabled.
+ ///
+ /// \param Filename The name of the file.
+ ///
+ /// \param Root The "root" directory, at which we should stop looking for
+ /// module maps.
+ ///
+ /// \param IsSystem Whether the directories we're looking at are system
+ /// header directories.
+ bool hasModuleMap(StringRef Filename, const DirectoryEntry *Root,
+ bool IsSystem);
+
+ /// \brief Retrieve the module that corresponds to the given file, if any.
+ ///
+ /// \param File The header that we wish to map to a module.
+ ModuleMap::KnownHeader findModuleForHeader(const FileEntry *File) const;
+
+ /// \brief Read the contents of the given module map file.
+ ///
+ /// \param File The module map file.
+ /// \param IsSystem Whether this file is in a system header directory.
+ ///
+ /// \returns true if an error occurred, false otherwise.
+ bool loadModuleMapFile(const FileEntry *File, bool IsSystem);
+
+ /// \brief Collect the set of all known, top-level modules.
+ ///
+ /// \param Modules Will be filled with the set of known, top-level modules.
+ void collectAllModules(SmallVectorImpl<Module *> &Modules);
+
+ /// \brief Load all known, top-level system modules.
+ void loadTopLevelSystemModules();
+
+private:
+ /// \brief Retrieve a module with the given name, which may be part of the
+ /// given framework.
+ ///
+ /// \param Name The name of the module to retrieve.
+ ///
+ /// \param Dir The framework directory (e.g., ModuleName.framework).
+ ///
+ /// \param IsSystem Whether the framework directory is part of the system
+ /// frameworks.
+ ///
+ /// \returns The module, if found; otherwise, null.
+ Module *loadFrameworkModule(StringRef Name,
+ const DirectoryEntry *Dir,
+ bool IsSystem);
+
+ /// \brief Load all of the module maps within the immediate subdirectories
+ /// of the given search directory.
+ void loadSubdirectoryModuleMaps(DirectoryLookup &SearchDir);
+
+ /// \brief Find and suggest a usable module for the given file.
+ ///
+ /// \return \c true if the file can be used, \c false if we are not permitted to
+ /// find this file due to requirements from \p RequestingModule.
+ bool findUsableModuleForHeader(const FileEntry *File,
+ const DirectoryEntry *Root,
+ Module *RequestingModule,
+ ModuleMap::KnownHeader *SuggestedModule,
+ bool IsSystemHeaderDir);
+
+ /// \brief Find and suggest a usable module for the given file, which is part of
+ /// the specified framework.
+ ///
+ /// \return \c true if the file can be used, \c false if we are not permitted to
+ /// find this file due to requirements from \p RequestingModule.
+ bool findUsableModuleForFrameworkHeader(
+ const FileEntry *File, StringRef FrameworkDir, Module *RequestingModule,
+ ModuleMap::KnownHeader *SuggestedModule, bool IsSystemFramework);
+
+ /// \brief Look up the file with the specified name and determine its owning
+ /// module.
+ const FileEntry *
+ getFileAndSuggestModule(StringRef FileName, const DirectoryEntry *Dir,
+ bool IsSystemHeaderDir, Module *RequestingModule,
+ ModuleMap::KnownHeader *SuggestedModule);
+
+public:
+ /// \brief Retrieve the module map.
+ ModuleMap &getModuleMap() { return ModMap; }
+
+ /// \brief Retrieve the module map.
+ const ModuleMap &getModuleMap() const { return ModMap; }
+
+ unsigned header_file_size() const { return FileInfo.size(); }
+
+ /// \brief Return the HeaderFileInfo structure for the specified FileEntry,
+ /// in preparation for updating it in some way.
+ HeaderFileInfo &getFileInfo(const FileEntry *FE);
+
+ /// \brief Return the HeaderFileInfo structure for the specified FileEntry,
+ /// if it has ever been filled in.
+ /// \param WantExternal Whether the caller wants purely-external header file
+ /// info (where \p External is true).
+ const HeaderFileInfo *getExistingFileInfo(const FileEntry *FE,
+ bool WantExternal = true) const;
+
+ // Used by external tools
+ typedef std::vector<DirectoryLookup>::const_iterator search_dir_iterator;
+ search_dir_iterator search_dir_begin() const { return SearchDirs.begin(); }
+ search_dir_iterator search_dir_end() const { return SearchDirs.end(); }
+ unsigned search_dir_size() const { return SearchDirs.size(); }
+
+ search_dir_iterator quoted_dir_begin() const {
+ return SearchDirs.begin();
+ }
+ search_dir_iterator quoted_dir_end() const {
+ return SearchDirs.begin() + AngledDirIdx;
+ }
+
+ search_dir_iterator angled_dir_begin() const {
+ return SearchDirs.begin() + AngledDirIdx;
+ }
+ search_dir_iterator angled_dir_end() const {
+ return SearchDirs.begin() + SystemDirIdx;
+ }
+
+ search_dir_iterator system_dir_begin() const {
+ return SearchDirs.begin() + SystemDirIdx;
+ }
+ search_dir_iterator system_dir_end() const { return SearchDirs.end(); }
+
+ /// \brief Retrieve a uniqued framework name.
+ StringRef getUniqueFrameworkName(StringRef Framework);
+
+ void PrintStats();
+
+ size_t getTotalMemory() const;
+
+ static std::string NormalizeDashIncludePath(StringRef File,
+ FileManager &FileMgr);
+
+private:
+ /// \brief Describes what happened when we tried to load a module map file.
+ enum LoadModuleMapResult {
+ /// \brief The module map file had already been loaded.
+ LMM_AlreadyLoaded,
+ /// \brief The module map file was loaded by this invocation.
+ LMM_NewlyLoaded,
+ /// \brief There is was directory with the given name.
+ LMM_NoDirectory,
+ /// \brief There was either no module map file or the module map file was
+ /// invalid.
+ LMM_InvalidModuleMap
+ };
+
+ LoadModuleMapResult loadModuleMapFileImpl(const FileEntry *File,
+ bool IsSystem,
+ const DirectoryEntry *Dir);
+
+ /// \brief Try to load the module map file in the given directory.
+ ///
+ /// \param DirName The name of the directory where we will look for a module
+ /// map file.
+ /// \param IsSystem Whether this is a system header directory.
+ /// \param IsFramework Whether this is a framework directory.
+ ///
+ /// \returns The result of attempting to load the module map file from the
+ /// named directory.
+ LoadModuleMapResult loadModuleMapFile(StringRef DirName, bool IsSystem,
+ bool IsFramework);
+
+ /// \brief Try to load the module map file in the given directory.
+ ///
+ /// \param Dir The directory where we will look for a module map file.
+ /// \param IsSystem Whether this is a system header directory.
+ /// \param IsFramework Whether this is a framework directory.
+ ///
+ /// \returns The result of attempting to load the module map file from the
+ /// named directory.
+ LoadModuleMapResult loadModuleMapFile(const DirectoryEntry *Dir,
+ bool IsSystem, bool IsFramework);
+};
+
+} // end namespace clang
+
+#endif
diff --git a/contrib/llvm/tools/clang/include/clang/Lex/HeaderSearchOptions.h b/contrib/llvm/tools/clang/include/clang/Lex/HeaderSearchOptions.h
new file mode 100644
index 0000000..915dbf7
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Lex/HeaderSearchOptions.h
@@ -0,0 +1,206 @@
+//===--- 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_LEX_HEADERSEARCHOPTIONS_H
+#define LLVM_CLANG_LEX_HEADERSEARCHOPTIONS_H
+
+#include "clang/Basic/LLVM.h"
+#include "llvm/ADT/IntrusiveRefCntPtr.h"
+#include "llvm/ADT/SetVector.h"
+#include "llvm/ADT/StringRef.h"
+#include <string>
+#include <vector>
+
+namespace clang {
+
+namespace frontend {
+ /// IncludeDirGroup - Identifies the group an include Entry belongs to,
+ /// representing its relative positive in the search list.
+ /// \#include directives whose paths are enclosed by string quotes ("")
+ /// start searching at the Quoted group (specified by '-iquote'),
+ /// then search the Angled group, then the System group, etc.
+ enum IncludeDirGroup {
+ Quoted = 0, ///< '\#include ""' paths, added by 'gcc -iquote'.
+ Angled, ///< Paths for '\#include <>' added by '-I'.
+ IndexHeaderMap, ///< Like Angled, but marks header maps used when
+ /// building frameworks.
+ System, ///< Like Angled, but marks system directories.
+ ExternCSystem, ///< Like System, but headers are implicitly wrapped in
+ /// extern "C".
+ CSystem, ///< Like System, but only used for C.
+ CXXSystem, ///< Like System, but only used for C++.
+ ObjCSystem, ///< Like System, but only used for ObjC.
+ ObjCXXSystem, ///< Like System, but only used for ObjC++.
+ 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 RefCountedBase<HeaderSearchOptions> {
+public:
+ struct Entry {
+ std::string Path;
+ frontend::IncludeDirGroup Group;
+ unsigned IsFramework : 1;
+
+ /// IgnoreSysRoot - This is false if an absolute path should be treated
+ /// relative to the sysroot, or true if it should always be the absolute
+ /// path.
+ unsigned IgnoreSysRoot : 1;
+
+ Entry(StringRef path, frontend::IncludeDirGroup group, bool isFramework,
+ bool ignoreSysRoot)
+ : Path(path), Group(group), IsFramework(isFramework),
+ IgnoreSysRoot(ignoreSysRoot) {}
+ };
+
+ struct SystemHeaderPrefix {
+ /// A prefix to be matched against paths in \#include directives.
+ std::string Prefix;
+
+ /// True if paths beginning with this prefix should be treated as system
+ /// headers.
+ bool IsSystemHeader;
+
+ SystemHeaderPrefix(StringRef Prefix, bool IsSystemHeader)
+ : Prefix(Prefix), IsSystemHeader(IsSystemHeader) {}
+ };
+
+ /// 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;
+
+ /// User-specified system header prefixes.
+ std::vector<SystemHeaderPrefix> SystemHeaderPrefixes;
+
+ /// The directory which holds the compiler resource files (builtin includes,
+ /// etc.).
+ std::string ResourceDir;
+
+ /// \brief The directory used for the module cache.
+ std::string ModuleCachePath;
+
+ /// \brief The directory used for a user build.
+ std::string ModuleUserBuildPath;
+
+ /// The module/pch container format.
+ std::string ModuleFormat;
+
+ /// \brief Whether we should disable the use of the hash string within the
+ /// module cache.
+ ///
+ /// Note: Only used for testing!
+ unsigned DisableModuleHash : 1;
+
+ /// \brief Implicit module maps. This option is enabld by default when
+ /// modules is enabled.
+ unsigned ImplicitModuleMaps : 1;
+
+ /// \brief Set the 'home directory' of a module map file to the current
+ /// working directory (or the home directory of the module map file that
+ /// contained the 'extern module' directive importing this module map file
+ /// if any) rather than the directory containing the module map file.
+ //
+ /// The home directory is where we look for files named in the module map
+ /// file.
+ unsigned ModuleMapFileHomeIsCwd : 1;
+
+ /// \brief The interval (in seconds) between pruning operations.
+ ///
+ /// This operation is expensive, because it requires Clang to walk through
+ /// the directory structure of the module cache, stat()'ing and removing
+ /// files.
+ ///
+ /// The default value is large, e.g., the operation runs once a week.
+ unsigned ModuleCachePruneInterval;
+
+ /// \brief The time (in seconds) after which an unused module file will be
+ /// considered unused and will, therefore, be pruned.
+ ///
+ /// When the module cache is pruned, any module file that has not been
+ /// accessed in this many seconds will be removed. The default value is
+ /// large, e.g., a month, to avoid forcing infrequently-used modules to be
+ /// regenerated often.
+ unsigned ModuleCachePruneAfter;
+
+ /// \brief The time in seconds when the build session started.
+ ///
+ /// This time is used by other optimizations in header search and module
+ /// loading.
+ uint64_t BuildSessionTimestamp;
+
+ /// \brief The set of macro names that should be ignored for the purposes
+ /// of computing the module hash.
+ llvm::SmallSetVector<std::string, 16> ModulesIgnoreMacros;
+
+ /// \brief The set of user-provided virtual filesystem overlay files.
+ std::vector<std::string> VFSOverlayFiles;
+
+ /// Include the compiler builtin includes.
+ unsigned UseBuiltinIncludes : 1;
+
+ /// Include the system standard include search directories.
+ unsigned UseStandardSystemIncludes : 1;
+
+ /// Include the system standard C++ library include search directories.
+ unsigned UseStandardCXXIncludes : 1;
+
+ /// Use libc++ instead of the default libstdc++.
+ unsigned UseLibcxx : 1;
+
+ /// Whether header search information should be output as for -v.
+ unsigned Verbose : 1;
+
+ /// \brief If true, skip verifying input files used by modules if the
+ /// module was already verified during this build session (see
+ /// \c BuildSessionTimestamp).
+ unsigned ModulesValidateOncePerBuildSession : 1;
+
+ /// \brief Whether to validate system input files when a module is loaded.
+ unsigned ModulesValidateSystemHeaders : 1;
+
+ /// Whether the module includes debug information (-gmodules).
+ unsigned UseDebugInfo : 1;
+
+ HeaderSearchOptions(StringRef _Sysroot = "/")
+ : Sysroot(_Sysroot), ModuleFormat("raw"), DisableModuleHash(0),
+ ImplicitModuleMaps(0), ModuleMapFileHomeIsCwd(0),
+ ModuleCachePruneInterval(7 * 24 * 60 * 60),
+ ModuleCachePruneAfter(31 * 24 * 60 * 60), BuildSessionTimestamp(0),
+ UseBuiltinIncludes(true), UseStandardSystemIncludes(true),
+ UseStandardCXXIncludes(true), UseLibcxx(false), Verbose(false),
+ ModulesValidateOncePerBuildSession(false),
+ ModulesValidateSystemHeaders(false),
+ UseDebugInfo(false) {}
+
+ /// AddPath - Add the \p Path path to the specified \p Group list.
+ void AddPath(StringRef Path, frontend::IncludeDirGroup Group,
+ bool IsFramework, bool IgnoreSysRoot) {
+ UserEntries.emplace_back(Path, Group, IsFramework, IgnoreSysRoot);
+ }
+
+ /// AddSystemHeaderPrefix - Override whether \#include directives naming a
+ /// path starting with \p Prefix should be considered as naming a system
+ /// header.
+ void AddSystemHeaderPrefix(StringRef Prefix, bool IsSystemHeader) {
+ SystemHeaderPrefixes.emplace_back(Prefix, IsSystemHeader);
+ }
+
+ void AddVFSOverlayFile(StringRef Name) {
+ VFSOverlayFiles.push_back(Name);
+ }
+};
+
+} // 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..5d724c0
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Lex/LexDiagnostic.h
@@ -0,0 +1,28 @@
+//===--- 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_LEX_LEXDIAGNOSTIC_H
+#define LLVM_CLANG_LEX_LEXDIAGNOSTIC_H
+
+#include "clang/Basic/Diagnostic.h"
+
+namespace clang {
+ namespace diag {
+ enum {
+#define DIAG(ENUM,FLAGS,DEFAULT_MAPPING,DESC,GROUP,\
+ SFINAE,NOWERROR,SHOWINSYSHEADER,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..12565d0
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Lex/Lexer.h
@@ -0,0 +1,665 @@
+//===--- 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_LEX_LEXER_H
+#define LLVM_CLANG_LEX_LEXER_H
+
+#include "clang/Basic/LangOptions.h"
+#include "clang/Lex/PreprocessorLexer.h"
+#include "llvm/ADT/SmallVector.h"
+#include <cassert>
+#include <string>
+
+namespace clang {
+class DiagnosticsEngine;
+class SourceManager;
+class Preprocessor;
+class DiagnosticBuilder;
+
+/// ConflictMarkerKind - Kinds of conflict marker which the lexer might be
+/// recovering from.
+enum ConflictMarkerKind {
+ /// Not within a conflict marker.
+ CMK_None,
+ /// A normal or diff3 conflict marker, initiated by at least 7 "<"s,
+ /// separated by at least 7 "="s or "|"s, and terminated by at least 7 ">"s.
+ CMK_Normal,
+ /// A Perforce-style conflict marker, initiated by 4 ">"s,
+ /// separated by 4 "="s, and terminated by 4 "<"s.
+ CMK_Perforce
+};
+
+/// 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 {
+ void anchor() override;
+
+ //===--------------------------------------------------------------------===//
+ // 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 LangOpts; // LangOpts enabled by this language (cache).
+ bool Is_PragmaLexer; // True if lexer for _Pragma handling.
+
+ //===--------------------------------------------------------------------===//
+ // 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;
+
+ bool IsAtPhysicalStartOfLine;
+
+ bool HasLeadingSpace;
+
+ bool HasLeadingEmptyMacro;
+
+ // CurrentConflictMarkerState - The kind of conflict marker we are handling.
+ ConflictMarkerKind CurrentConflictMarkerState;
+
+ Lexer(const Lexer &) = delete;
+ void operator=(const Lexer &) = delete;
+ 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 'LexFromRawLexer'. This lexer assumes that the
+ /// text range will outlive it, so it doesn't take ownership of it.
+ Lexer(SourceLocation FileLoc, const LangOptions &LangOpts,
+ 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 'LexFromRawLexer'. 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 &LangOpts);
+
+ /// 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 ExpansionLocStart,
+ SourceLocation ExpansionLocEnd,
+ unsigned TokLen, Preprocessor &PP);
+
+
+ /// getLangOpts - Return the language features currently enabled.
+ /// NOTE: this lexer modifies features as a file is parsed!
+ const LangOptions &getLangOpts() const { return LangOpts; }
+
+ /// 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; }
+
+private:
+ /// Lex - Return the next token in the file. If this is the end of file, it
+ /// return the tok::eof token. This implicitly involves the preprocessor.
+ bool Lex(Token &Result);
+
+public:
+ /// isPragmaLexer - Returns true if this Lexer is being used to lex a pragma.
+ bool isPragmaLexer() const { return Is_PragmaLexer; }
+
+private:
+ /// IndirectLex - An indirect call to 'Lex' that can be invoked via
+ /// the PreprocessorLexer interface.
+ void IndirectLex(Token &Result) override { Lex(Result); }
+
+public:
+ /// 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 || LangOpts.TraditionalCPP) &&
+ "Can only retain whitespace in raw mode or -traditional-cpp");
+ 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;
+ }
+
+ /// Sets the extended token mode back to its initial value, according to the
+ /// language options and preprocessor. This controls whether the lexer
+ /// produces comment and whitespace tokens.
+ ///
+ /// This requires the lexer to have an associated preprocessor. A standalone
+ /// lexer has nothing to reset to.
+ void resetExtendedTokenMode();
+
+ /// Gets source code buffer.
+ StringRef getBuffer() const {
+ return StringRef(BufferStart, BufferEnd - BufferStart);
+ }
+
+ /// ReadToEndOfLine - Read the rest of the current preprocessor line as an
+ /// uninterpreted string. This switches the lexer out of directive mode.
+ void ReadToEndOfLine(SmallVectorImpl<char> *Result = nullptr);
+
+
+ /// 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() override {
+ 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(StringRef 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(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 &LangOpts,
+ bool *Invalid = nullptr);
+
+ /// 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 &LangOpts,
+ bool *Invalid = nullptr);
+
+ /// getSpelling - This method is used to get the spelling of the
+ /// token at the given source location. If, as is usually true, it
+ /// is not necessary to copy any data, then the returned string may
+ /// not point into the provided buffer.
+ ///
+ /// This method lexes at the expansion depth of the given
+ /// location and does not jump to the expansion or spelling
+ /// location.
+ static StringRef getSpelling(SourceLocation loc,
+ SmallVectorImpl<char> &buffer,
+ const SourceManager &SourceMgr,
+ const LangOptions &LangOpts,
+ bool *invalid = nullptr);
+
+ /// 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 Relex the token at the specified location.
+ /// \returns true if there was a failure, false on success.
+ static bool getRawToken(SourceLocation Loc, Token &Result,
+ const SourceManager &SM,
+ const LangOptions &LangOpts,
+ bool IgnoreWhiteSpace = false);
+
+ /// \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.
+ 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 &LangOpts);
+
+ /// \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 &LangOpts);
+
+ /// \brief Given a token range, produce a corresponding CharSourceRange that
+ /// is not a token range. This allows the source range to be used by
+ /// components that don't have access to the lexer and thus can't find the
+ /// end of the range for themselves.
+ static CharSourceRange getAsCharRange(SourceRange Range,
+ const SourceManager &SM,
+ const LangOptions &LangOpts) {
+ SourceLocation End = getLocForEndOfToken(Range.getEnd(), 0, SM, LangOpts);
+ return End.isInvalid() ? CharSourceRange()
+ : CharSourceRange::getCharRange(
+ Range.getBegin(), End.getLocWithOffset(-1));
+ }
+ static CharSourceRange getAsCharRange(CharSourceRange Range,
+ const SourceManager &SM,
+ const LangOptions &LangOpts) {
+ return Range.isTokenRange()
+ ? getAsCharRange(Range.getAsRange(), SM, LangOpts)
+ : Range;
+ }
+
+ /// \brief Returns true if the given MacroID location points at the first
+ /// token of the macro expansion.
+ ///
+ /// \param MacroBegin If non-null and function returns true, it is set to
+ /// begin location of the macro.
+ static bool isAtStartOfMacroExpansion(SourceLocation loc,
+ const SourceManager &SM,
+ const LangOptions &LangOpts,
+ SourceLocation *MacroBegin = nullptr);
+
+ /// \brief Returns true if the given MacroID location points at the last
+ /// token of the macro expansion.
+ ///
+ /// \param MacroEnd If non-null and function returns true, it is set to
+ /// end location of the macro.
+ static bool isAtEndOfMacroExpansion(SourceLocation loc,
+ const SourceManager &SM,
+ const LangOptions &LangOpts,
+ SourceLocation *MacroEnd = nullptr);
+
+ /// \brief Accepts a range and returns a character range with file locations.
+ ///
+ /// Returns a null range if a part of the range resides inside a macro
+ /// expansion or the range does not reside on the same FileID.
+ ///
+ /// This function is trying to deal with macros and return a range based on
+ /// file locations. The cases where it can successfully handle macros are:
+ ///
+ /// -begin or end range lies at the start or end of a macro expansion, in
+ /// which case the location will be set to the expansion point, e.g:
+ /// \#define M 1 2
+ /// a M
+ /// If you have a range [a, 2] (where 2 came from the macro), the function
+ /// will return a range for "a M"
+ /// if you have range [a, 1], the function will fail because the range
+ /// overlaps with only a part of the macro
+ ///
+ /// -The macro is a function macro and the range can be mapped to the macro
+ /// arguments, e.g:
+ /// \#define M 1 2
+ /// \#define FM(x) x
+ /// FM(a b M)
+ /// if you have range [b, 2], the function will return the file range "b M"
+ /// inside the macro arguments.
+ /// if you have range [a, 2], the function will return the file range
+ /// "FM(a b M)" since the range includes all of the macro expansion.
+ static CharSourceRange makeFileCharRange(CharSourceRange Range,
+ const SourceManager &SM,
+ const LangOptions &LangOpts);
+
+ /// \brief Returns a string for the source that the range encompasses.
+ static StringRef getSourceText(CharSourceRange Range,
+ const SourceManager &SM,
+ const LangOptions &LangOpts,
+ bool *Invalid = nullptr);
+
+ /// \brief Retrieve the name of the immediate macro expansion.
+ ///
+ /// This routine starts from a source location, and finds the name of the macro
+ /// responsible for its immediate expansion. It looks through any intervening
+ /// macro argument expansions to compute this. It returns a StringRef which
+ /// refers to the SourceManager-owned buffer of the source where that macro
+ /// name is spelled. Thus, the result shouldn't out-live that SourceManager.
+ static StringRef getImmediateMacroName(SourceLocation Loc,
+ const SourceManager &SM,
+ const LangOptions &LangOpts);
+
+ /// \brief Compute the preamble of the given file.
+ ///
+ /// The preamble of a file contains the initial comments, include directives,
+ /// and other preprocessor directives that occur before the code in this
+ /// particular file actually begins. The preamble of the main source file is
+ /// a potential prefix header.
+ ///
+ /// \param Buffer The memory buffer containing the file's contents.
+ ///
+ /// \param MaxLines If non-zero, restrict the length of the preamble
+ /// to fewer than this number of lines.
+ ///
+ /// \returns The offset into the file where the preamble ends and the rest
+ /// of the file begins along with a boolean value indicating whether
+ /// the preamble ends at the beginning of a new line.
+ static std::pair<unsigned, bool> ComputePreamble(StringRef Buffer,
+ const LangOptions &LangOpts,
+ unsigned MaxLines = 0);
+
+ /// \brief Checks that the given token is the first token that occurs after
+ /// the given location (this excludes comments and whitespace). Returns the
+ /// location immediately after the specified token. If the token is not found
+ /// or the location is inside a macro, the returned source location will be
+ /// invalid.
+ static SourceLocation findLocationAfterToken(SourceLocation loc,
+ tok::TokenKind TKind,
+ const SourceManager &SM,
+ const LangOptions &LangOpts,
+ bool SkipTrailingWhitespaceAndNewLine);
+
+ /// \brief Returns true if the given character could appear in an identifier.
+ static bool isIdentifierBodyChar(char c, const LangOptions &LangOpts);
+
+ /// getCharAndSizeNoWarn - Like the getCharAndSize method, but does not ever
+ /// emit a warning.
+ static inline char getCharAndSizeNoWarn(const char *Ptr, unsigned &Size,
+ const LangOptions &LangOpts) {
+ // 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, LangOpts);
+ }
+
+ //===--------------------------------------------------------------------===//
+ // Internal implementation interfaces.
+private:
+
+ /// LexTokenInternal - Internal interface to lex a preprocessing token. Called
+ /// by Lex.
+ ///
+ bool LexTokenInternal(Token &Result, bool TokAtPhysicalStartOfLine);
+
+ bool CheckUnicodeWhitespace(Token &Result, uint32_t C, const char *CurPtr);
+
+ /// Given that a token begins with the Unicode character \p C, figure out
+ /// what kind of token it is and dispatch to the appropriate lexing helper
+ /// function.
+ bool LexUnicode(Token &Result, uint32_t C, const char *CurPtr);
+
+ /// 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.
+
+ // 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;
+ }
+
+ /// 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 = nullptr);
+
+ /// 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);
+
+ /// getCharAndSizeSlowNoWarn - Same as getCharAndSizeSlow, but never emits a
+ /// diagnostic.
+ static char getCharAndSizeSlowNoWarn(const char *Ptr, unsigned &Size,
+ const LangOptions &LangOpts);
+
+ //===--------------------------------------------------------------------===//
+ // Other lexer functions.
+
+ void SkipBytes(unsigned Bytes, bool StartOfLine);
+
+ void PropagateLineStartLeadingSpaceInfo(Token &Result);
+
+ const char *LexUDSuffix(Token &Result, const char *CurPtr,
+ bool IsStringLiteral);
+
+ // Helper functions to lex the remainder of a token of the specific type.
+ bool LexIdentifier (Token &Result, const char *CurPtr);
+ bool LexNumericConstant (Token &Result, const char *CurPtr);
+ bool LexStringLiteral (Token &Result, const char *CurPtr,
+ tok::TokenKind Kind);
+ bool LexRawStringLiteral (Token &Result, const char *CurPtr,
+ tok::TokenKind Kind);
+ bool LexAngledStringLiteral(Token &Result, const char *CurPtr);
+ bool LexCharConstant (Token &Result, const char *CurPtr,
+ tok::TokenKind Kind);
+ bool LexEndOfFile (Token &Result, const char *CurPtr);
+ bool SkipWhitespace (Token &Result, const char *CurPtr,
+ bool &TokAtPhysicalStartOfLine);
+ bool SkipLineComment (Token &Result, const char *CurPtr,
+ bool &TokAtPhysicalStartOfLine);
+ bool SkipBlockComment (Token &Result, const char *CurPtr,
+ bool &TokAtPhysicalStartOfLine);
+ bool SaveLineComment (Token &Result, const char *CurPtr);
+
+ bool IsStartOfConflictMarker(const char *CurPtr);
+ bool HandleEndOfConflictMarker(const char *CurPtr);
+
+ bool isCodeCompletionPoint(const char *CurPtr) const;
+ void cutOffLexing() { BufferPtr = BufferEnd; }
+
+ bool isHexaLiteral(const char *Start, const LangOptions &LangOpts);
+
+
+ /// Read a universal character name.
+ ///
+ /// \param CurPtr The position in the source buffer after the initial '\'.
+ /// If the UCN is syntactically well-formed (but not necessarily
+ /// valid), this parameter will be updated to point to the
+ /// character after the UCN.
+ /// \param SlashLoc The position in the source buffer of the '\'.
+ /// \param Tok The token being formed. Pass \c NULL to suppress diagnostics
+ /// and handle token formation in the caller.
+ ///
+ /// \return The Unicode codepoint specified by the UCN, or 0 if the UCN is
+ /// invalid.
+ uint32_t tryReadUCN(const char *&CurPtr, const char *SlashLoc, Token *Tok);
+
+ /// \brief Try to consume a UCN as part of an identifier at the current
+ /// location.
+ /// \param CurPtr Initially points to the range of characters in the source
+ /// buffer containing the '\'. Updated to point past the end of
+ /// the UCN on success.
+ /// \param Size The number of characters occupied by the '\' (including
+ /// trigraphs and escaped newlines).
+ /// \param Result The token being produced. Marked as containing a UCN on
+ /// success.
+ /// \return \c true if a UCN was lexed and it produced an acceptable
+ /// identifier character, \c false otherwise.
+ bool tryConsumeIdentifierUCN(const char *&CurPtr, unsigned Size,
+ Token &Result);
+
+ /// \brief Try to consume an identifier character encoded in UTF-8.
+ /// \param CurPtr Points to the start of the (potential) UTF-8 code unit
+ /// sequence. On success, updated to point past the end of it.
+ /// \return \c true if a UTF-8 sequence mapping to an acceptable identifier
+ /// character was lexed, \c false otherwise.
+ bool tryConsumeIdentifierUTF8Char(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..5210e3f
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Lex/LiteralSupport.h
@@ -0,0 +1,260 @@
+//===--- 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 LLVM_CLANG_LEX_LITERALSUPPORT_H
+#define LLVM_CLANG_LEX_LITERALSUPPORT_H
+
+#include "clang/Basic/CharInfo.h"
+#include "clang/Basic/LLVM.h"
+#include "clang/Basic/TokenKinds.h"
+#include "llvm/ADT/APFloat.h"
+#include "llvm/ADT/SmallString.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/Support/DataTypes.h"
+
+namespace clang {
+
+class DiagnosticsEngine;
+class Preprocessor;
+class Token;
+class SourceLocation;
+class TargetInfo;
+class SourceManager;
+class LangOptions;
+
+/// Copy characters from Input to Buf, expanding any UCNs.
+void expandUCNs(SmallVectorImpl<char> &Buf, StringRef Input);
+
+/// 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, saw_ud_suffix;
+
+ SmallString<32> UDSuffixBuf;
+
+public:
+ NumericLiteralParser(StringRef TokSpelling,
+ SourceLocation TokLoc,
+ Preprocessor &PP);
+ bool hadError : 1;
+ bool isUnsigned : 1;
+ bool isLong : 1; // This is *not* set for long long.
+ bool isLongLong : 1;
+ bool isFloat : 1; // 1.0f
+ bool isImaginary : 1; // 1.0i
+ uint8_t MicrosoftInteger; // 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 hasUDSuffix() const {
+ return saw_ud_suffix;
+ }
+ StringRef getUDSuffix() const {
+ assert(saw_ud_suffix);
+ return UDSuffixBuf;
+ }
+ unsigned getUDSuffixOffset() const {
+ assert(saw_ud_suffix);
+ return SuffixBegin - ThisTokBegin;
+ }
+
+ static bool isValidUDSuffix(const LangOptions &LangOpts, StringRef Suffix);
+
+ 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);
+
+ static bool isDigitSeparator(char C) { return C == '\''; }
+
+ enum CheckSeparatorKind { CSK_BeforeDigits, CSK_AfterDigits };
+
+ /// \brief Ensure that we don't have a digit separator here.
+ void checkSeparator(SourceLocation TokLoc, const char *Pos,
+ CheckSeparatorKind IsAfterDigits);
+
+ /// 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 && (isHexDigit(*ptr) || isDigitSeparator(*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') || isDigitSeparator(*ptr)))
+ 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) || isDigitSeparator(*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' || isDigitSeparator(*ptr)))
+ ptr++;
+ return ptr;
+ }
+
+};
+
+/// CharLiteralParser - Perform interpretation and semantic analysis of a
+/// character literal.
+class CharLiteralParser {
+ uint64_t Value;
+ tok::TokenKind Kind;
+ bool IsMultiChar;
+ bool HadError;
+ SmallString<32> UDSuffixBuf;
+ unsigned UDSuffixOffset;
+public:
+ CharLiteralParser(const char *begin, const char *end,
+ SourceLocation Loc, Preprocessor &PP,
+ tok::TokenKind kind);
+
+ bool hadError() const { return HadError; }
+ bool isAscii() const { return Kind == tok::char_constant; }
+ bool isWide() const { return Kind == tok::wide_char_constant; }
+ bool isUTF16() const { return Kind == tok::utf16_char_constant; }
+ bool isUTF32() const { return Kind == tok::utf32_char_constant; }
+ bool isMultiChar() const { return IsMultiChar; }
+ uint64_t getValue() const { return Value; }
+ StringRef getUDSuffix() const { return UDSuffixBuf; }
+ unsigned getUDSuffixOffset() const {
+ assert(!UDSuffixBuf.empty() && "no ud-suffix");
+ return UDSuffixOffset;
+ }
+};
+
+/// 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;
+ DiagnosticsEngine *Diags;
+
+ unsigned MaxTokenLength;
+ unsigned SizeBound;
+ unsigned CharByteWidth;
+ tok::TokenKind Kind;
+ SmallString<512> ResultBuf;
+ char *ResultPtr; // cursor
+ SmallString<32> UDSuffixBuf;
+ unsigned UDSuffixToken;
+ unsigned UDSuffixOffset;
+public:
+ StringLiteralParser(ArrayRef<Token> StringToks,
+ Preprocessor &PP, bool Complain = true);
+ StringLiteralParser(ArrayRef<Token> StringToks,
+ const SourceManager &sm, const LangOptions &features,
+ const TargetInfo &target,
+ DiagnosticsEngine *diags = nullptr)
+ : SM(sm), Features(features), Target(target), Diags(diags),
+ MaxTokenLength(0), SizeBound(0), CharByteWidth(0), Kind(tok::unknown),
+ ResultPtr(ResultBuf.data()), hadError(false), Pascal(false) {
+ init(StringToks);
+ }
+
+
+ bool hadError;
+ bool Pascal;
+
+ StringRef GetString() const {
+ return StringRef(ResultBuf.data(), GetStringLength());
+ }
+ unsigned GetStringLength() const { return ResultPtr-ResultBuf.data(); }
+
+ unsigned GetNumStringChars() const {
+ return GetStringLength() / CharByteWidth;
+ }
+ /// 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;
+
+ bool isAscii() const { return Kind == tok::string_literal; }
+ bool isWide() const { return Kind == tok::wide_string_literal; }
+ bool isUTF8() const { return Kind == tok::utf8_string_literal; }
+ bool isUTF16() const { return Kind == tok::utf16_string_literal; }
+ bool isUTF32() const { return Kind == tok::utf32_string_literal; }
+ bool isPascal() const { return Pascal; }
+
+ StringRef getUDSuffix() const { return UDSuffixBuf; }
+
+ /// Get the index of a token containing a ud-suffix.
+ unsigned getUDSuffixToken() const {
+ assert(!UDSuffixBuf.empty() && "no ud-suffix");
+ return UDSuffixToken;
+ }
+ /// Get the spelling offset of the first byte of the ud-suffix.
+ unsigned getUDSuffixOffset() const {
+ assert(!UDSuffixBuf.empty() && "no ud-suffix");
+ return UDSuffixOffset;
+ }
+
+private:
+ void init(ArrayRef<Token> StringToks);
+ bool CopyStringFragment(const Token &Tok, const char *TokBegin,
+ StringRef Fragment);
+ void DiagnoseLexingError(SourceLocation Loc);
+};
+
+} // end namespace clang
+
+#endif
diff --git a/contrib/llvm/tools/clang/include/clang/Lex/MacroArgs.h b/contrib/llvm/tools/clang/include/clang/Lex/MacroArgs.h
new file mode 100644
index 0000000..243b143
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Lex/MacroArgs.h
@@ -0,0 +1,127 @@
+//===--- 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_LEX_MACROARGS_H
+#define LLVM_CLANG_LEX_MACROARGS_H
+
+#include "clang/Basic/LLVM.h"
+#include "llvm/ADT/ArrayRef.h"
+#include <vector>
+
+namespace clang {
+ class MacroInfo;
+ class Preprocessor;
+ class Token;
+ class SourceLocation;
+
+/// 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(nullptr) {}
+ ~MacroArgs() = default;
+
+public:
+ /// MacroArgs ctor function - Create a new MacroArgs object with the specified
+ /// macro and argument info.
+ static MacroArgs *create(const MacroInfo *MI,
+ ArrayRef<Token> UnexpArgTokens,
+ 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,
+ SourceLocation ExpansionLocStart,
+ SourceLocation ExpansionLocEnd);
+
+ /// 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,
+ SourceLocation ExpansionLocStart,
+ SourceLocation ExpansionLocEnd);
+
+
+ /// 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/include/clang/Lex/MacroInfo.h b/contrib/llvm/tools/clang/include/clang/Lex/MacroInfo.h
new file mode 100644
index 0000000..320645e
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Lex/MacroInfo.h
@@ -0,0 +1,609 @@
+//===--- 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.
+//
+//===----------------------------------------------------------------------===//
+///
+/// \file
+/// \brief Defines the clang::MacroInfo and clang::MacroDirective classes.
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_LEX_MACROINFO_H
+#define LLVM_CLANG_LEX_MACROINFO_H
+
+#include "clang/Lex/Token.h"
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/FoldingSet.h"
+#include "llvm/ADT/PointerIntPair.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/Support/Allocator.h"
+#include <cassert>
+
+namespace clang {
+class Module;
+class ModuleMacro;
+class Preprocessor;
+
+/// \brief Encapsulates the data about a macro definition (e.g. its tokens).
+///
+/// There's an instance of this class for every #define.
+class MacroInfo {
+ //===--------------------------------------------------------------------===//
+ // State set when the macro is defined.
+
+ /// \brief The location the macro is defined.
+ SourceLocation Location;
+ /// \brief The location of the last token in the macro.
+ SourceLocation EndLocation;
+
+ /// \brief The list of arguments for a function-like macro.
+ ///
+ /// ArgumentList points to the first of NumArguments pointers.
+ ///
+ /// This can be empty, for, e.g. "#define X()". In a C99-style variadic
+ /// macro, this includes the \c __VA_ARGS__ identifier on the list.
+ IdentifierInfo **ArgumentList;
+
+ /// \see ArgumentList
+ unsigned NumArguments;
+
+ /// \brief This is the list of tokens that the macro is defined to.
+ SmallVector<Token, 8> ReplacementTokens;
+
+ /// \brief Length in characters of the macro definition.
+ mutable unsigned DefinitionLength;
+ mutable bool IsDefinitionLengthCached : 1;
+
+ /// \brief True if this macro is function-like, false if it is object-like.
+ bool IsFunctionLike : 1;
+
+ /// \brief 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;
+
+ /// \brief 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;
+
+ /// \brief True if this macro requires processing before expansion.
+ ///
+ /// This is the case for builtin macros such as __LINE__, so long as they have
+ /// not been redefined, but not for regular predefined macros from the
+ /// "<built-in>" memory buffer (see Preprocessing::getPredefinesFileID).
+ bool IsBuiltinMacro : 1;
+
+ /// \brief Whether this macro contains the sequence ", ## __VA_ARGS__"
+ bool HasCommaPasting : 1;
+
+ //===--------------------------------------------------------------------===//
+ // State that changes as the macro is used.
+
+ /// \brief True if we have started an expansion of this macro already.
+ ///
+ /// This disables recursive expansion, which would be quite bad for things
+ /// like \#define A A.
+ bool IsDisabled : 1;
+
+ /// \brief 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;
+
+ /// \brief 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;
+
+ /// \brief Whether this macro info was loaded from an AST file.
+ unsigned FromASTFile : 1;
+
+ /// \brief Whether this macro was used as header guard.
+ bool UsedForHeaderGuard : 1;
+
+ // Only the Preprocessor gets to create and destroy these.
+ MacroInfo(SourceLocation DefLoc);
+ ~MacroInfo() = default;
+
+public:
+ /// \brief Return the location that the macro was defined at.
+ SourceLocation getDefinitionLoc() const { return Location; }
+
+ /// \brief Set the location of the last token in the macro.
+ void setDefinitionEndLoc(SourceLocation EndLoc) { EndLocation = EndLoc; }
+
+ /// \brief Return the location of the last token in the macro.
+ SourceLocation getDefinitionEndLoc() const { return EndLocation; }
+
+ /// \brief Get length in characters of the macro definition.
+ unsigned getDefinitionLength(SourceManager &SM) const {
+ if (IsDefinitionLengthCached)
+ return DefinitionLength;
+ return getDefinitionLengthSlow(SM);
+ }
+
+ /// \brief Return true if the specified macro definition is equal to
+ /// this macro in spelling, arguments, and whitespace.
+ ///
+ /// \param Syntactically if true, the macro definitions can be identical even
+ /// if they use different identifiers for the function macro parameters.
+ /// Otherwise the comparison is lexical and this implements the rules in
+ /// C99 6.10.3.
+ bool isIdenticalTo(const MacroInfo &Other, Preprocessor &PP,
+ bool Syntactically) const;
+
+ /// \brief Set or clear the isBuiltinMacro flag.
+ void setIsBuiltinMacro(bool Val = true) { IsBuiltinMacro = Val; }
+
+ /// \brief Set the value of the IsUsed flag.
+ void setIsUsed(bool Val) { IsUsed = Val; }
+
+ /// \brief 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; }
+
+ /// \brief Set the specified list of identifiers as the argument list for
+ /// this macro.
+ void setArgumentList(ArrayRef<IdentifierInfo *> List,
+ llvm::BumpPtrAllocator &PPAllocator) {
+ assert(ArgumentList == nullptr && NumArguments == 0 &&
+ "Argument list already set!");
+ if (List.empty())
+ return;
+
+ NumArguments = List.size();
+ ArgumentList = PPAllocator.Allocate<IdentifierInfo *>(List.size());
+ std::copy(List.begin(), List.end(), ArgumentList);
+ }
+
+ /// 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; }
+ ArrayRef<const IdentifierInfo *> args() const {
+ return ArrayRef<const IdentifierInfo *>(ArgumentList, NumArguments);
+ }
+
+ /// \brief Return the argument number of the specified identifier,
+ /// or -1 if the identifier is not a formal argument identifier.
+ int getArgumentNum(const 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; }
+
+ /// \brief Return true if this macro requires processing before expansion.
+ ///
+ /// This is true only for builtin macro, such as \__LINE__, whose values
+ /// are not given by fixed textual expansions. Regular predefined macros
+ /// from the "<built-in>" buffer are not reported as builtins by this
+ /// function.
+ bool isBuiltinMacro() const { return IsBuiltinMacro; }
+
+ bool hasCommaPasting() const { return HasCommaPasting; }
+ void setHasCommaPasting() { HasCommaPasting = true; }
+
+ /// \brief Return false if this macro is defined in the main file and has
+ /// not yet been used.
+ bool isUsed() const { return IsUsed; }
+
+ /// \brief 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; }
+
+ /// \brief 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 SmallVectorImpl<Token>::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(); }
+ ArrayRef<Token> tokens() const { return ReplacementTokens; }
+
+ /// \brief Add the specified token to the replacement text for the macro.
+ void AddTokenToBody(const Token &Tok) {
+ assert(
+ !IsDefinitionLengthCached &&
+ "Changing replacement tokens after definition length got calculated");
+ ReplacementTokens.push_back(Tok);
+ }
+
+ /// \brief 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;
+ }
+
+ /// \brief Determine whether this macro info came from an AST file (such as
+ /// a precompiled header or module) rather than having been parsed.
+ bool isFromASTFile() const { return FromASTFile; }
+
+ /// \brief Determine whether this macro was used for a header guard.
+ bool isUsedForHeaderGuard() const { return UsedForHeaderGuard; }
+
+ void setUsedForHeaderGuard(bool Val) { UsedForHeaderGuard = Val; }
+
+ /// \brief Retrieve the global ID of the module that owns this particular
+ /// macro info.
+ unsigned getOwningModuleID() const {
+ if (isFromASTFile())
+ return *(const unsigned *)(this + 1);
+
+ return 0;
+ }
+
+ void dump() const;
+
+private:
+ unsigned getDefinitionLengthSlow(SourceManager &SM) const;
+
+ void setOwningModuleID(unsigned ID) {
+ assert(isFromASTFile());
+ *(unsigned *)(this + 1) = ID;
+ }
+
+ friend class Preprocessor;
+};
+
+class DefMacroDirective;
+
+/// \brief Encapsulates changes to the "macros namespace" (the location where
+/// the macro name became active, the location where it was undefined, etc.).
+///
+/// MacroDirectives, associated with an identifier, are used to model the macro
+/// history. Usually a macro definition (MacroInfo) is where a macro name
+/// becomes active (MacroDirective) but #pragma push_macro / pop_macro can
+/// create additional DefMacroDirectives for the same MacroInfo.
+class MacroDirective {
+public:
+ enum Kind { MD_Define, MD_Undefine, MD_Visibility };
+
+protected:
+ /// \brief Previous macro directive for the same identifier, or NULL.
+ MacroDirective *Previous;
+
+ SourceLocation Loc;
+
+ /// \brief MacroDirective kind.
+ unsigned MDKind : 2;
+
+ /// \brief True if the macro directive was loaded from a PCH file.
+ bool IsFromPCH : 1;
+
+ // Used by VisibilityMacroDirective ----------------------------------------//
+
+ /// \brief Whether the macro has public visibility (when described in a
+ /// module).
+ bool IsPublic : 1;
+
+ MacroDirective(Kind K, SourceLocation Loc)
+ : Previous(nullptr), Loc(Loc), MDKind(K), IsFromPCH(false),
+ IsPublic(true) {}
+
+public:
+ Kind getKind() const { return Kind(MDKind); }
+
+ SourceLocation getLocation() const { return Loc; }
+
+ /// \brief Set previous definition of the macro with the same name.
+ void setPrevious(MacroDirective *Prev) { Previous = Prev; }
+
+ /// \brief Get previous definition of the macro with the same name.
+ const MacroDirective *getPrevious() const { return Previous; }
+
+ /// \brief Get previous definition of the macro with the same name.
+ MacroDirective *getPrevious() { return Previous; }
+
+ /// \brief Return true if the macro directive was loaded from a PCH file.
+ bool isFromPCH() const { return IsFromPCH; }
+
+ void setIsFromPCH() { IsFromPCH = true; }
+
+ class DefInfo {
+ DefMacroDirective *DefDirective;
+ SourceLocation UndefLoc;
+ bool IsPublic;
+
+ public:
+ DefInfo() : DefDirective(nullptr), IsPublic(true) {}
+
+ DefInfo(DefMacroDirective *DefDirective, SourceLocation UndefLoc,
+ bool isPublic)
+ : DefDirective(DefDirective), UndefLoc(UndefLoc), IsPublic(isPublic) {}
+
+ const DefMacroDirective *getDirective() const { return DefDirective; }
+ DefMacroDirective *getDirective() { return DefDirective; }
+
+ inline SourceLocation getLocation() const;
+ inline MacroInfo *getMacroInfo();
+ const MacroInfo *getMacroInfo() const {
+ return const_cast<DefInfo *>(this)->getMacroInfo();
+ }
+
+ SourceLocation getUndefLocation() const { return UndefLoc; }
+ bool isUndefined() const { return UndefLoc.isValid(); }
+
+ bool isPublic() const { return IsPublic; }
+
+ bool isValid() const { return DefDirective != nullptr; }
+ bool isInvalid() const { return !isValid(); }
+
+ explicit operator bool() const { return isValid(); }
+
+ inline DefInfo getPreviousDefinition();
+ const DefInfo getPreviousDefinition() const {
+ return const_cast<DefInfo *>(this)->getPreviousDefinition();
+ }
+ };
+
+ /// \brief Traverses the macro directives history and returns the next
+ /// macro definition directive along with info about its undefined location
+ /// (if there is one) and if it is public or private.
+ DefInfo getDefinition();
+ const DefInfo getDefinition() const {
+ return const_cast<MacroDirective *>(this)->getDefinition();
+ }
+
+ bool isDefined() const {
+ if (const DefInfo Def = getDefinition())
+ return !Def.isUndefined();
+ return false;
+ }
+
+ const MacroInfo *getMacroInfo() const {
+ return getDefinition().getMacroInfo();
+ }
+ MacroInfo *getMacroInfo() { return getDefinition().getMacroInfo(); }
+
+ /// \brief Find macro definition active in the specified source location. If
+ /// this macro was not defined there, return NULL.
+ const DefInfo findDirectiveAtLoc(SourceLocation L, SourceManager &SM) const;
+
+ void dump() const;
+
+ static bool classof(const MacroDirective *) { return true; }
+};
+
+/// \brief A directive for a defined macro or a macro imported from a module.
+class DefMacroDirective : public MacroDirective {
+ MacroInfo *Info;
+
+public:
+ DefMacroDirective(MacroInfo *MI, SourceLocation Loc)
+ : MacroDirective(MD_Define, Loc), Info(MI) {
+ assert(MI && "MacroInfo is null");
+ }
+ explicit DefMacroDirective(MacroInfo *MI)
+ : DefMacroDirective(MI, MI->getDefinitionLoc()) {}
+
+ /// \brief The data for the macro definition.
+ const MacroInfo *getInfo() const { return Info; }
+ MacroInfo *getInfo() { return Info; }
+
+ static bool classof(const MacroDirective *MD) {
+ return MD->getKind() == MD_Define;
+ }
+ static bool classof(const DefMacroDirective *) { return true; }
+};
+
+/// \brief A directive for an undefined macro.
+class UndefMacroDirective : public MacroDirective {
+public:
+ explicit UndefMacroDirective(SourceLocation UndefLoc)
+ : MacroDirective(MD_Undefine, UndefLoc) {
+ assert(UndefLoc.isValid() && "Invalid UndefLoc!");
+ }
+
+ static bool classof(const MacroDirective *MD) {
+ return MD->getKind() == MD_Undefine;
+ }
+ static bool classof(const UndefMacroDirective *) { return true; }
+};
+
+/// \brief A directive for setting the module visibility of a macro.
+class VisibilityMacroDirective : public MacroDirective {
+public:
+ explicit VisibilityMacroDirective(SourceLocation Loc, bool Public)
+ : MacroDirective(MD_Visibility, Loc) {
+ IsPublic = Public;
+ }
+
+ /// \brief Determine whether this macro is part of the public API of its
+ /// module.
+ bool isPublic() const { return IsPublic; }
+
+ static bool classof(const MacroDirective *MD) {
+ return MD->getKind() == MD_Visibility;
+ }
+ static bool classof(const VisibilityMacroDirective *) { return true; }
+};
+
+inline SourceLocation MacroDirective::DefInfo::getLocation() const {
+ if (isInvalid())
+ return SourceLocation();
+ return DefDirective->getLocation();
+}
+
+inline MacroInfo *MacroDirective::DefInfo::getMacroInfo() {
+ if (isInvalid())
+ return nullptr;
+ return DefDirective->getInfo();
+}
+
+inline MacroDirective::DefInfo
+MacroDirective::DefInfo::getPreviousDefinition() {
+ if (isInvalid() || DefDirective->getPrevious() == nullptr)
+ return DefInfo();
+ return DefDirective->getPrevious()->getDefinition();
+}
+
+/// \brief Represents a macro directive exported by a module.
+///
+/// There's an instance of this class for every macro #define or #undef that is
+/// the final directive for a macro name within a module. These entities also
+/// represent the macro override graph.
+///
+/// These are stored in a FoldingSet in the preprocessor.
+class ModuleMacro : public llvm::FoldingSetNode {
+ /// The name defined by the macro.
+ IdentifierInfo *II;
+ /// The body of the #define, or nullptr if this is a #undef.
+ MacroInfo *Macro;
+ /// The module that exports this macro.
+ Module *OwningModule;
+ /// The number of module macros that override this one.
+ unsigned NumOverriddenBy;
+ /// The number of modules whose macros are directly overridden by this one.
+ unsigned NumOverrides;
+ // ModuleMacro *OverriddenMacros[NumOverrides];
+
+ friend class Preprocessor;
+
+ ModuleMacro(Module *OwningModule, IdentifierInfo *II, MacroInfo *Macro,
+ ArrayRef<ModuleMacro *> Overrides)
+ : II(II), Macro(Macro), OwningModule(OwningModule), NumOverriddenBy(0),
+ NumOverrides(Overrides.size()) {
+ std::copy(Overrides.begin(), Overrides.end(),
+ reinterpret_cast<ModuleMacro **>(this + 1));
+ }
+
+public:
+ static ModuleMacro *create(Preprocessor &PP, Module *OwningModule,
+ IdentifierInfo *II, MacroInfo *Macro,
+ ArrayRef<ModuleMacro *> Overrides);
+
+ void Profile(llvm::FoldingSetNodeID &ID) const {
+ return Profile(ID, OwningModule, II);
+ }
+ static void Profile(llvm::FoldingSetNodeID &ID, Module *OwningModule,
+ IdentifierInfo *II) {
+ ID.AddPointer(OwningModule);
+ ID.AddPointer(II);
+ }
+
+ /// Get the ID of the module that exports this macro.
+ Module *getOwningModule() const { return OwningModule; }
+
+ /// Get definition for this exported #define, or nullptr if this
+ /// represents a #undef.
+ MacroInfo *getMacroInfo() const { return Macro; }
+
+ /// Iterators over the overridden module IDs.
+ /// \{
+ typedef ModuleMacro *const *overrides_iterator;
+ overrides_iterator overrides_begin() const {
+ return reinterpret_cast<overrides_iterator>(this + 1);
+ }
+ overrides_iterator overrides_end() const {
+ return overrides_begin() + NumOverrides;
+ }
+ ArrayRef<ModuleMacro *> overrides() const {
+ return llvm::makeArrayRef(overrides_begin(), overrides_end());
+ }
+ /// \}
+
+ /// Get the number of macros that override this one.
+ unsigned getNumOverridingMacros() const { return NumOverriddenBy; }
+};
+
+/// \brief A description of the current definition of a macro.
+///
+/// The definition of a macro comprises a set of (at least one) defining
+/// entities, which are either local MacroDirectives or imported ModuleMacros.
+class MacroDefinition {
+ llvm::PointerIntPair<DefMacroDirective *, 1, bool> LatestLocalAndAmbiguous;
+ ArrayRef<ModuleMacro *> ModuleMacros;
+
+public:
+ MacroDefinition() : LatestLocalAndAmbiguous(), ModuleMacros() {}
+ MacroDefinition(DefMacroDirective *MD, ArrayRef<ModuleMacro *> MMs,
+ bool IsAmbiguous)
+ : LatestLocalAndAmbiguous(MD, IsAmbiguous), ModuleMacros(MMs) {}
+
+ /// \brief Determine whether there is a definition of this macro.
+ explicit operator bool() const {
+ return getLocalDirective() || !ModuleMacros.empty();
+ }
+
+ /// \brief Get the MacroInfo that should be used for this definition.
+ MacroInfo *getMacroInfo() const {
+ if (!ModuleMacros.empty())
+ return ModuleMacros.back()->getMacroInfo();
+ if (auto *MD = getLocalDirective())
+ return MD->getMacroInfo();
+ return nullptr;
+ }
+
+ /// \brief \c true if the definition is ambiguous, \c false otherwise.
+ bool isAmbiguous() const { return LatestLocalAndAmbiguous.getInt(); }
+
+ /// \brief Get the latest non-imported, non-\#undef'd macro definition
+ /// for this macro.
+ DefMacroDirective *getLocalDirective() const {
+ return LatestLocalAndAmbiguous.getPointer();
+ }
+
+ /// \brief Get the active module macros for this macro.
+ ArrayRef<ModuleMacro *> getModuleMacros() const { return ModuleMacros; }
+
+ template <typename Fn> void forAllDefinitions(Fn F) const {
+ if (auto *MD = getLocalDirective())
+ F(MD->getMacroInfo());
+ for (auto *MM : getModuleMacros())
+ F(MM->getMacroInfo());
+ }
+};
+
+} // end namespace clang
+
+#endif
diff --git a/contrib/llvm/tools/clang/include/clang/Lex/ModuleLoader.h b/contrib/llvm/tools/clang/include/clang/Lex/ModuleLoader.h
new file mode 100644
index 0000000..ae79650
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Lex/ModuleLoader.h
@@ -0,0 +1,129 @@
+//===--- ModuleLoader.h - Module Loader 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 ModuleLoader interface, which is responsible for
+// loading named modules.
+//
+//===----------------------------------------------------------------------===//
+#ifndef LLVM_CLANG_LEX_MODULELOADER_H
+#define LLVM_CLANG_LEX_MODULELOADER_H
+
+#include "clang/Basic/Module.h"
+#include "clang/Basic/SourceLocation.h"
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/PointerIntPair.h"
+
+namespace clang {
+
+class GlobalModuleIndex;
+class IdentifierInfo;
+class Module;
+
+/// \brief A sequence of identifier/location pairs used to describe a particular
+/// module or submodule, e.g., std.vector.
+typedef ArrayRef<std::pair<IdentifierInfo *, SourceLocation> > ModuleIdPath;
+
+/// \brief Describes the result of attempting to load a module.
+class ModuleLoadResult {
+ llvm::PointerIntPair<Module *, 1, bool> Storage;
+
+public:
+ ModuleLoadResult() : Storage() { }
+
+ ModuleLoadResult(Module *module, bool missingExpected)
+ : Storage(module, missingExpected) { }
+
+ operator Module *() const { return Storage.getPointer(); }
+
+ /// \brief Determines whether the module, which failed to load, was
+ /// actually a submodule that we expected to see (based on implying the
+ /// submodule from header structure), but didn't materialize in the actual
+ /// module.
+ bool isMissingExpected() const { return Storage.getInt(); }
+};
+
+/// \brief Abstract interface for a module loader.
+///
+/// This abstract interface describes a module loader, which is responsible
+/// for resolving a module name (e.g., "std") to an actual module file, and
+/// then loading that module.
+class ModuleLoader {
+ // Building a module if true.
+ bool BuildingModule;
+public:
+ explicit ModuleLoader(bool BuildingModule = false) :
+ BuildingModule(BuildingModule),
+ HadFatalFailure(false) {}
+
+ virtual ~ModuleLoader();
+
+ /// \brief Returns true if this instance is building a module.
+ bool buildingModule() const {
+ return BuildingModule;
+ }
+ /// \brief Flag indicating whether this instance is building a module.
+ void setBuildingModule(bool BuildingModuleFlag) {
+ BuildingModule = BuildingModuleFlag;
+ }
+
+ /// \brief Attempt to load the given module.
+ ///
+ /// This routine attempts to load the module described by the given
+ /// parameters.
+ ///
+ /// \param ImportLoc The location of the 'import' keyword.
+ ///
+ /// \param Path The identifiers (and their locations) of the module
+ /// "path", e.g., "std.vector" would be split into "std" and "vector".
+ ///
+ /// \param Visibility The visibility provided for the names in the loaded
+ /// module.
+ ///
+ /// \param IsInclusionDirective Indicates that this module is being loaded
+ /// implicitly, due to the presence of an inclusion directive. Otherwise,
+ /// it is being loaded due to an import declaration.
+ ///
+ /// \returns If successful, returns the loaded module. Otherwise, returns
+ /// NULL to indicate that the module could not be loaded.
+ virtual ModuleLoadResult loadModule(SourceLocation ImportLoc,
+ ModuleIdPath Path,
+ Module::NameVisibilityKind Visibility,
+ bool IsInclusionDirective) = 0;
+
+ /// \brief Make the given module visible.
+ virtual void makeModuleVisible(Module *Mod,
+ Module::NameVisibilityKind Visibility,
+ SourceLocation ImportLoc) = 0;
+
+ /// \brief Load, create, or return global module.
+ /// This function returns an existing global module index, if one
+ /// had already been loaded or created, or loads one if it
+ /// exists, or creates one if it doesn't exist.
+ /// Also, importantly, if the index doesn't cover all the modules
+ /// in the module map, it will be update to do so here, because
+ /// of its use in searching for needed module imports and
+ /// associated fixit messages.
+ /// \param TriggerLoc The location for what triggered the load.
+ /// \returns Returns null if load failed.
+ virtual GlobalModuleIndex *loadGlobalModuleIndex(
+ SourceLocation TriggerLoc) = 0;
+
+ /// Check global module index for missing imports.
+ /// \param Name The symbol name to look for.
+ /// \param TriggerLoc The location for what triggered the load.
+ /// \returns Returns true if any modules with that symbol found.
+ virtual bool lookupMissingImports(StringRef Name,
+ SourceLocation TriggerLoc) = 0;
+
+ bool HadFatalFailure;
+};
+
+}
+
+#endif
diff --git a/contrib/llvm/tools/clang/include/clang/Lex/ModuleMap.h b/contrib/llvm/tools/clang/include/clang/Lex/ModuleMap.h
new file mode 100644
index 0000000..155943e
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Lex/ModuleMap.h
@@ -0,0 +1,514 @@
+//===--- ModuleMap.h - Describe the layout of modules -----------*- C++ -*-===//
+//
+// 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 ModuleMap interface, which describes the layout of a
+// module as it relates to headers.
+//
+//===----------------------------------------------------------------------===//
+
+
+#ifndef LLVM_CLANG_LEX_MODULEMAP_H
+#define LLVM_CLANG_LEX_MODULEMAP_H
+
+#include "clang/Basic/LangOptions.h"
+#include "clang/Basic/Module.h"
+#include "clang/Basic/SourceManager.h"
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/IntrusiveRefCntPtr.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/StringMap.h"
+#include "llvm/ADT/StringRef.h"
+#include <string>
+
+namespace clang {
+
+class DirectoryEntry;
+class FileEntry;
+class FileManager;
+class DiagnosticConsumer;
+class DiagnosticsEngine;
+class HeaderSearch;
+class ModuleMapParser;
+
+/// \brief A mechanism to observe the actions of the module map parser as it
+/// reads module map files.
+class ModuleMapCallbacks {
+public:
+ virtual ~ModuleMapCallbacks() {}
+
+ /// \brief Called when a module map file has been read.
+ ///
+ /// \param FileStart A SourceLocation referring to the start of the file's
+ /// contents.
+ /// \param File The file itself.
+ /// \param IsSystem Whether this is a module map from a system include path.
+ virtual void moduleMapFileRead(SourceLocation FileStart,
+ const FileEntry &File, bool IsSystem) {}
+};
+
+class ModuleMap {
+ SourceManager &SourceMgr;
+ DiagnosticsEngine &Diags;
+ const LangOptions &LangOpts;
+ const TargetInfo *Target;
+ HeaderSearch &HeaderInfo;
+
+ llvm::SmallVector<std::unique_ptr<ModuleMapCallbacks>, 1> Callbacks;
+
+ /// \brief The directory used for Clang-supplied, builtin include headers,
+ /// such as "stdint.h".
+ const DirectoryEntry *BuiltinIncludeDir;
+
+ /// \brief Language options used to parse the module map itself.
+ ///
+ /// These are always simple C language options.
+ LangOptions MMapLangOpts;
+
+ // The module that we are building; related to \c LangOptions::CurrentModule.
+ Module *CompilingModule;
+
+public:
+ // The module that the .cc source file is associated with.
+ Module *SourceModule;
+ std::string SourceModuleName;
+
+private:
+ /// \brief The top-level modules that are known.
+ llvm::StringMap<Module *> Modules;
+
+ /// \brief The number of modules we have created in total.
+ unsigned NumCreatedModules;
+
+public:
+ /// \brief Flags describing the role of a module header.
+ enum ModuleHeaderRole {
+ /// \brief This header is normally included in the module.
+ NormalHeader = 0x0,
+ /// \brief This header is included but private.
+ PrivateHeader = 0x1,
+ /// \brief This header is part of the module (for layering purposes) but
+ /// should be textually included.
+ TextualHeader = 0x2,
+ // Caution: Adding an enumerator needs other changes.
+ // Adjust the number of bits for KnownHeader::Storage.
+ // Adjust the bitfield HeaderFileInfo::HeaderRole size.
+ // Adjust the HeaderFileInfoTrait::ReadData streaming.
+ // Adjust the HeaderFileInfoTrait::EmitData streaming.
+ // Adjust ModuleMap::addHeader.
+ };
+
+ /// \brief A header that is known to reside within a given module,
+ /// whether it was included or excluded.
+ class KnownHeader {
+ llvm::PointerIntPair<Module *, 2, ModuleHeaderRole> Storage;
+
+ public:
+ KnownHeader() : Storage(nullptr, NormalHeader) { }
+ KnownHeader(Module *M, ModuleHeaderRole Role) : Storage(M, Role) { }
+
+ friend bool operator==(const KnownHeader &A, const KnownHeader &B) {
+ return A.Storage == B.Storage;
+ }
+ friend bool operator!=(const KnownHeader &A, const KnownHeader &B) {
+ return A.Storage != B.Storage;
+ }
+
+ /// \brief Retrieve the module the header is stored in.
+ Module *getModule() const { return Storage.getPointer(); }
+
+ /// \brief The role of this header within the module.
+ ModuleHeaderRole getRole() const { return Storage.getInt(); }
+
+ /// \brief Whether this header is available in the module.
+ bool isAvailable() const {
+ return getModule()->isAvailable();
+ }
+
+ // \brief Whether this known header is valid (i.e., it has an
+ // associated module).
+ explicit operator bool() const {
+ return Storage.getPointer() != nullptr;
+ }
+ };
+
+ typedef llvm::SmallPtrSet<const FileEntry *, 1> AdditionalModMapsSet;
+
+private:
+ typedef llvm::DenseMap<const FileEntry *, SmallVector<KnownHeader, 1> >
+ HeadersMap;
+
+ /// \brief Mapping from each header to the module that owns the contents of
+ /// that header.
+ HeadersMap Headers;
+
+ /// \brief Mapping from directories with umbrella headers to the module
+ /// that is generated from the umbrella header.
+ ///
+ /// This mapping is used to map headers that haven't explicitly been named
+ /// in the module map over to the module that includes them via its umbrella
+ /// header.
+ llvm::DenseMap<const DirectoryEntry *, Module *> UmbrellaDirs;
+
+ /// \brief The set of attributes that can be attached to a module.
+ struct Attributes {
+ Attributes() : IsSystem(), IsExternC(), IsExhaustive() {}
+
+ /// \brief Whether this is a system module.
+ unsigned IsSystem : 1;
+
+ /// \brief Whether this is an extern "C" module.
+ unsigned IsExternC : 1;
+
+ /// \brief Whether this is an exhaustive set of configuration macros.
+ unsigned IsExhaustive : 1;
+ };
+
+ /// \brief A directory for which framework modules can be inferred.
+ struct InferredDirectory {
+ InferredDirectory() : InferModules() {}
+
+ /// \brief Whether to infer modules from this directory.
+ unsigned InferModules : 1;
+
+ /// \brief The attributes to use for inferred modules.
+ Attributes Attrs;
+
+ /// \brief If \c InferModules is non-zero, the module map file that allowed
+ /// inferred modules. Otherwise, nullptr.
+ const FileEntry *ModuleMapFile;
+
+ /// \brief The names of modules that cannot be inferred within this
+ /// directory.
+ SmallVector<std::string, 2> ExcludedModules;
+ };
+
+ /// \brief A mapping from directories to information about inferring
+ /// framework modules from within those directories.
+ llvm::DenseMap<const DirectoryEntry *, InferredDirectory> InferredDirectories;
+
+ /// A mapping from an inferred module to the module map that allowed the
+ /// inference.
+ llvm::DenseMap<const Module *, const FileEntry *> InferredModuleAllowedBy;
+
+ llvm::DenseMap<const Module *, AdditionalModMapsSet> AdditionalModMaps;
+
+ /// \brief Describes whether we haved parsed a particular file as a module
+ /// map.
+ llvm::DenseMap<const FileEntry *, bool> ParsedModuleMap;
+
+ friend class ModuleMapParser;
+
+ /// \brief Resolve the given export declaration into an actual export
+ /// declaration.
+ ///
+ /// \param Mod The module in which we're resolving the export declaration.
+ ///
+ /// \param Unresolved The export declaration to resolve.
+ ///
+ /// \param Complain Whether this routine should complain about unresolvable
+ /// exports.
+ ///
+ /// \returns The resolved export declaration, which will have a NULL pointer
+ /// if the export could not be resolved.
+ Module::ExportDecl
+ resolveExport(Module *Mod, const Module::UnresolvedExportDecl &Unresolved,
+ bool Complain) const;
+
+ /// \brief Resolve the given module id to an actual module.
+ ///
+ /// \param Id The module-id to resolve.
+ ///
+ /// \param Mod The module in which we're resolving the module-id.
+ ///
+ /// \param Complain Whether this routine should complain about unresolvable
+ /// module-ids.
+ ///
+ /// \returns The resolved module, or null if the module-id could not be
+ /// resolved.
+ Module *resolveModuleId(const ModuleId &Id, Module *Mod, bool Complain) const;
+
+ /// \brief Looks up the modules that \p File corresponds to.
+ ///
+ /// If \p File represents a builtin header within Clang's builtin include
+ /// directory, this also loads all of the module maps to see if it will get
+ /// associated with a specific module (e.g. in /usr/include).
+ HeadersMap::iterator findKnownHeader(const FileEntry *File);
+
+ /// \brief Searches for a module whose umbrella directory contains \p File.
+ ///
+ /// \param File The header to search for.
+ ///
+ /// \param IntermediateDirs On success, contains the set of directories
+ /// searched before finding \p File.
+ KnownHeader findHeaderInUmbrellaDirs(const FileEntry *File,
+ SmallVectorImpl<const DirectoryEntry *> &IntermediateDirs);
+
+ /// \brief Given that \p File is not in the Headers map, look it up within
+ /// umbrella directories and find or create a module for it.
+ KnownHeader findOrCreateModuleForHeaderInUmbrellaDir(const FileEntry *File);
+
+ /// \brief A convenience method to determine if \p File is (possibly nested)
+ /// in an umbrella directory.
+ bool isHeaderInUmbrellaDirs(const FileEntry *File) {
+ SmallVector<const DirectoryEntry *, 2> IntermediateDirs;
+ return static_cast<bool>(findHeaderInUmbrellaDirs(File, IntermediateDirs));
+ }
+
+ Module *inferFrameworkModule(const DirectoryEntry *FrameworkDir,
+ Attributes Attrs, Module *Parent);
+
+public:
+ /// \brief Construct a new module map.
+ ///
+ /// \param SourceMgr The source manager used to find module files and headers.
+ /// This source manager should be shared with the header-search mechanism,
+ /// since they will refer to the same headers.
+ ///
+ /// \param Diags A diagnostic engine used for diagnostics.
+ ///
+ /// \param LangOpts Language options for this translation unit.
+ ///
+ /// \param Target The target for this translation unit.
+ ModuleMap(SourceManager &SourceMgr, DiagnosticsEngine &Diags,
+ const LangOptions &LangOpts, const TargetInfo *Target,
+ HeaderSearch &HeaderInfo);
+
+ /// \brief Destroy the module map.
+ ///
+ ~ModuleMap();
+
+ /// \brief Set the target information.
+ void setTarget(const TargetInfo &Target);
+
+ /// \brief Set the directory that contains Clang-supplied include
+ /// files, such as our stdarg.h or tgmath.h.
+ void setBuiltinIncludeDir(const DirectoryEntry *Dir) {
+ BuiltinIncludeDir = Dir;
+ }
+
+ /// \brief Add a module map callback.
+ void addModuleMapCallbacks(std::unique_ptr<ModuleMapCallbacks> Callback) {
+ Callbacks.push_back(std::move(Callback));
+ }
+
+ /// \brief Retrieve the module that owns the given header file, if any.
+ ///
+ /// \param File The header file that is likely to be included.
+ ///
+ /// \returns The module KnownHeader, which provides the module that owns the
+ /// given header file. The KnownHeader is default constructed to indicate
+ /// that no module owns this header file.
+ KnownHeader findModuleForHeader(const FileEntry *File);
+
+ /// \brief Retrieve all the modules that contain the given header file. This
+ /// may not include umbrella modules, nor information from external sources,
+ /// if they have not yet been inferred / loaded.
+ ///
+ /// Typically, \ref findModuleForHeader should be used instead, as it picks
+ /// the preferred module for the header.
+ ArrayRef<KnownHeader> findAllModulesForHeader(const FileEntry *File) const;
+
+ /// \brief Reports errors if a module must not include a specific file.
+ ///
+ /// \param RequestingModule The module including a file.
+ ///
+ /// \param FilenameLoc The location of the inclusion's filename.
+ ///
+ /// \param Filename The included filename as written.
+ ///
+ /// \param File The included file.
+ void diagnoseHeaderInclusion(Module *RequestingModule,
+ SourceLocation FilenameLoc, StringRef Filename,
+ const FileEntry *File);
+
+ /// \brief Determine whether the given header is part of a module
+ /// marked 'unavailable'.
+ bool isHeaderInUnavailableModule(const FileEntry *Header) const;
+
+ /// \brief Determine whether the given header is unavailable as part
+ /// of the specified module.
+ bool isHeaderUnavailableInModule(const FileEntry *Header,
+ const Module *RequestingModule) const;
+
+ /// \brief Retrieve a module with the given name.
+ ///
+ /// \param Name The name of the module to look up.
+ ///
+ /// \returns The named module, if known; otherwise, returns null.
+ Module *findModule(StringRef Name) const;
+
+ /// \brief Retrieve a module with the given name using lexical name lookup,
+ /// starting at the given context.
+ ///
+ /// \param Name The name of the module to look up.
+ ///
+ /// \param Context The module context, from which we will perform lexical
+ /// name lookup.
+ ///
+ /// \returns The named module, if known; otherwise, returns null.
+ Module *lookupModuleUnqualified(StringRef Name, Module *Context) const;
+
+ /// \brief Retrieve a module with the given name within the given context,
+ /// using direct (qualified) name lookup.
+ ///
+ /// \param Name The name of the module to look up.
+ ///
+ /// \param Context The module for which we will look for a submodule. If
+ /// null, we will look for a top-level module.
+ ///
+ /// \returns The named submodule, if known; otherwose, returns null.
+ Module *lookupModuleQualified(StringRef Name, Module *Context) const;
+
+ /// \brief Find a new module or submodule, or create it if it does not already
+ /// exist.
+ ///
+ /// \param Name The name of the module to find or create.
+ ///
+ /// \param Parent The module that will act as the parent of this submodule,
+ /// or NULL to indicate that this is a top-level module.
+ ///
+ /// \param IsFramework Whether this is a framework module.
+ ///
+ /// \param IsExplicit Whether this is an explicit submodule.
+ ///
+ /// \returns The found or newly-created module, along with a boolean value
+ /// that will be true if the module is newly-created.
+ std::pair<Module *, bool> findOrCreateModule(StringRef Name, Module *Parent,
+ bool IsFramework,
+ bool IsExplicit);
+
+ /// \brief Infer the contents of a framework module map from the given
+ /// framework directory.
+ Module *inferFrameworkModule(const DirectoryEntry *FrameworkDir,
+ bool IsSystem, Module *Parent);
+
+ /// \brief Retrieve the module map file containing the definition of the given
+ /// module.
+ ///
+ /// \param Module The module whose module map file will be returned, if known.
+ ///
+ /// \returns The file entry for the module map file containing the given
+ /// module, or NULL if the module definition was inferred.
+ const FileEntry *getContainingModuleMapFile(const Module *Module) const;
+
+ /// \brief Get the module map file that (along with the module name) uniquely
+ /// identifies this module.
+ ///
+ /// The particular module that \c Name refers to may depend on how the module
+ /// was found in header search. However, the combination of \c Name and
+ /// this module map will be globally unique for top-level modules. In the case
+ /// of inferred modules, returns the module map that allowed the inference
+ /// (e.g. contained 'module *'). Otherwise, returns
+ /// getContainingModuleMapFile().
+ const FileEntry *getModuleMapFileForUniquing(const Module *M) const;
+
+ void setInferredModuleAllowedBy(Module *M, const FileEntry *ModuleMap);
+
+ /// \brief Get any module map files other than getModuleMapFileForUniquing(M)
+ /// that define submodules of a top-level module \p M. This is cheaper than
+ /// getting the module map file for each submodule individually, since the
+ /// expected number of results is very small.
+ AdditionalModMapsSet *getAdditionalModuleMapFiles(const Module *M) {
+ auto I = AdditionalModMaps.find(M);
+ if (I == AdditionalModMaps.end())
+ return nullptr;
+ return &I->second;
+ }
+
+ void addAdditionalModuleMapFile(const Module *M, const FileEntry *ModuleMap) {
+ AdditionalModMaps[M].insert(ModuleMap);
+ }
+
+ /// \brief Resolve all of the unresolved exports in the given module.
+ ///
+ /// \param Mod The module whose exports should be resolved.
+ ///
+ /// \param Complain Whether to emit diagnostics for failures.
+ ///
+ /// \returns true if any errors were encountered while resolving exports,
+ /// false otherwise.
+ bool resolveExports(Module *Mod, bool Complain);
+
+ /// \brief Resolve all of the unresolved uses in the given module.
+ ///
+ /// \param Mod The module whose uses should be resolved.
+ ///
+ /// \param Complain Whether to emit diagnostics for failures.
+ ///
+ /// \returns true if any errors were encountered while resolving uses,
+ /// false otherwise.
+ bool resolveUses(Module *Mod, bool Complain);
+
+ /// \brief Resolve all of the unresolved conflicts in the given module.
+ ///
+ /// \param Mod The module whose conflicts should be resolved.
+ ///
+ /// \param Complain Whether to emit diagnostics for failures.
+ ///
+ /// \returns true if any errors were encountered while resolving conflicts,
+ /// false otherwise.
+ bool resolveConflicts(Module *Mod, bool Complain);
+
+ /// \brief Infers the (sub)module based on the given source location and
+ /// source manager.
+ ///
+ /// \param Loc The location within the source that we are querying, along
+ /// with its source manager.
+ ///
+ /// \returns The module that owns this source location, or null if no
+ /// module owns this source location.
+ Module *inferModuleFromLocation(FullSourceLoc Loc);
+
+ /// \brief Sets the umbrella header of the given module to the given
+ /// header.
+ void setUmbrellaHeader(Module *Mod, const FileEntry *UmbrellaHeader,
+ Twine NameAsWritten);
+
+ /// \brief Sets the umbrella directory of the given module to the given
+ /// directory.
+ void setUmbrellaDir(Module *Mod, const DirectoryEntry *UmbrellaDir,
+ Twine NameAsWritten);
+
+ /// \brief Adds this header to the given module.
+ /// \param Role The role of the header wrt the module.
+ void addHeader(Module *Mod, Module::Header Header,
+ ModuleHeaderRole Role, bool Imported = false);
+
+ /// \brief Marks this header as being excluded from the given module.
+ void excludeHeader(Module *Mod, Module::Header Header);
+
+ /// \brief Parse the given module map file, and record any modules we
+ /// encounter.
+ ///
+ /// \param File The file to be parsed.
+ ///
+ /// \param IsSystem Whether this module map file is in a system header
+ /// directory, and therefore should be considered a system module.
+ ///
+ /// \param HomeDir The directory in which relative paths within this module
+ /// map file will be resolved.
+ ///
+ /// \param ExternModuleLoc The location of the "extern module" declaration
+ /// that caused us to load this module map file, if any.
+ ///
+ /// \returns true if an error occurred, false otherwise.
+ bool parseModuleMapFile(const FileEntry *File, bool IsSystem,
+ const DirectoryEntry *HomeDir,
+ SourceLocation ExternModuleLoc = SourceLocation());
+
+ /// \brief Dump the contents of the module map, for debugging purposes.
+ void dump();
+
+ typedef llvm::StringMap<Module *>::const_iterator module_iterator;
+ module_iterator module_begin() const { return Modules.begin(); }
+ module_iterator module_end() const { return Modules.end(); }
+};
+
+}
+#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..83e6f99
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Lex/MultipleIncludeOpt.h
@@ -0,0 +1,181 @@
+//===--- 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.
+//
+//===----------------------------------------------------------------------===//
+///
+/// \file
+/// \brief Defines the MultipleIncludeOpt interface.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_LEX_MULTIPLEINCLUDEOPT_H
+#define LLVM_CLANG_LEX_MULTIPLEINCLUDEOPT_H
+
+#include "clang/Basic/SourceLocation.h"
+
+namespace clang {
+class IdentifierInfo;
+
+/// \brief 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;
+
+ /// ImmediatelyAfterTopLevelIfndef - This is true when the only tokens
+ /// processed in the file so far is an #ifndef and an identifier. Used in
+ /// the detection of header guards in a file.
+ bool ImmediatelyAfterTopLevelIfndef;
+
+ /// 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;
+
+ /// DefinedMacro - The macro defined right after TheMacro, if any.
+ const IdentifierInfo *DefinedMacro;
+
+ SourceLocation MacroLoc;
+ SourceLocation DefinedLoc;
+public:
+ MultipleIncludeOpt() {
+ ReadAnyTokens = false;
+ ImmediatelyAfterTopLevelIfndef = false;
+ DidMacroExpansion = false;
+ TheMacro = nullptr;
+ DefinedMacro = nullptr;
+ }
+
+ SourceLocation GetMacroLocation() const {
+ return MacroLoc;
+ }
+
+ SourceLocation GetDefinedLocation() const {
+ return DefinedLoc;
+ }
+
+ void resetImmediatelyAfterTopLevelIfndef() {
+ ImmediatelyAfterTopLevelIfndef = false;
+ }
+
+ void SetDefinedMacro(IdentifierInfo *M, SourceLocation Loc) {
+ DefinedMacro = M;
+ DefinedLoc = Loc;
+ }
+
+ /// Invalidate - Permanently 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;
+ ImmediatelyAfterTopLevelIfndef = false;
+ DefinedMacro = nullptr;
+ TheMacro = nullptr;
+ }
+
+ /// 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; }
+
+ /// getImmediatelyAfterTopLevelIfndef - returns true if the last directive
+ /// was an #ifndef at the beginning of the file.
+ bool getImmediatelyAfterTopLevelIfndef() const {
+ return ImmediatelyAfterTopLevelIfndef;
+ }
+
+ // If a token is read, remember that we have seen a side-effect in this file.
+ void ReadToken() {
+ ReadAnyTokens = true;
+ ImmediatelyAfterTopLevelIfndef = false;
+ }
+
+ /// 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; }
+
+ /// \brief Called when entering a top-level \#ifndef directive (or the
+ /// "\#if !defined" equivalent) without any preceding tokens.
+ ///
+ /// 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, SourceLocation Loc) {
+ // 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;
+ ImmediatelyAfterTopLevelIfndef = true;
+ TheMacro = M;
+ MacroLoc = Loc;
+ }
+
+ /// \brief 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();
+ }
+
+ /// \brief 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;
+ ImmediatelyAfterTopLevelIfndef = false;
+ }
+
+ /// \brief 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 nullptr;
+ }
+
+ /// \brief If the ControllingMacro is followed by a macro definition, return
+ /// the macro that was defined.
+ const IdentifierInfo *GetDefinedMacro() const {
+ return DefinedMacro;
+ }
+};
+
+} // 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..68b8f1c
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Lex/PPCallbacks.h
@@ -0,0 +1,509 @@
+//===--- 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.
+//
+//===----------------------------------------------------------------------===//
+///
+/// \file
+/// \brief Defines the PPCallbacks interface.
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_LEX_PPCALLBACKS_H
+#define LLVM_CLANG_LEX_PPCALLBACKS_H
+
+#include "clang/Basic/DiagnosticIDs.h"
+#include "clang/Basic/SourceLocation.h"
+#include "clang/Lex/DirectoryLookup.h"
+#include "clang/Lex/ModuleLoader.h"
+#include "clang/Lex/Pragma.h"
+#include "llvm/ADT/StringRef.h"
+#include <string>
+
+namespace clang {
+ class SourceLocation;
+ class Token;
+ class IdentifierInfo;
+ class MacroDefinition;
+ class MacroDirective;
+ class MacroArgs;
+
+/// \brief 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
+ };
+
+ /// \brief Callback invoked whenever a source file is entered or exited.
+ ///
+ /// \param Loc Indicates the new location.
+ /// \param PrevFID the file that was exited if \p Reason is ExitFile.
+ virtual void FileChanged(SourceLocation Loc, FileChangeReason Reason,
+ SrcMgr::CharacteristicKind FileType,
+ FileID PrevFID = FileID()) {
+ }
+
+ /// \brief Callback invoked whenever a source file is skipped as the result
+ /// of header guard optimization.
+ ///
+ /// \param SkippedFile The file that is skipped instead of entering \#include
+ ///
+ /// \param FilenameTok The file name token in \#include "FileName" directive
+ /// or macro expanded file name token from \#include MACRO(PARAMS) directive.
+ /// Note that FilenameTok contains corresponding quotes/angles symbols.
+ virtual void FileSkipped(const FileEntry &SkippedFile,
+ const Token &FilenameTok,
+ SrcMgr::CharacteristicKind FileType) {
+ }
+
+ /// \brief Callback invoked whenever an inclusion directive results in a
+ /// file-not-found error.
+ ///
+ /// \param FileName The name of the file being included, as written in the
+ /// source code.
+ ///
+ /// \param RecoveryPath If this client indicates that it can recover from
+ /// this missing file, the client should set this as an additional header
+ /// search patch.
+ ///
+ /// \returns true to indicate that the preprocessor should attempt to recover
+ /// by adding \p RecoveryPath as a header search path.
+ virtual bool FileNotFound(StringRef FileName,
+ SmallVectorImpl<char> &RecoveryPath) {
+ return false;
+ }
+
+ /// \brief Callback 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 FilenameRange The character range of the quotes or angle brackets
+ /// for the written file name.
+ ///
+ /// \param File The actual file that may be included by this inclusion
+ /// directive.
+ ///
+ /// \param SearchPath Contains the search path which was used to find the file
+ /// in the file system. If the file was found via an absolute include path,
+ /// SearchPath will be empty. For framework includes, the SearchPath and
+ /// RelativePath will be split up. For example, if an include of "Some/Some.h"
+ /// is found via the framework path
+ /// "path/to/Frameworks/Some.framework/Headers/Some.h", SearchPath will be
+ /// "path/to/Frameworks/Some.framework/Headers" and RelativePath will be
+ /// "Some.h".
+ ///
+ /// \param RelativePath The path relative to SearchPath, at which the include
+ /// file was found. This is equal to FileName except for framework includes.
+ ///
+ /// \param Imported The module, whenever an inclusion directive was
+ /// automatically turned into a module import or null otherwise.
+ ///
+ virtual void InclusionDirective(SourceLocation HashLoc,
+ const Token &IncludeTok,
+ StringRef FileName,
+ bool IsAngled,
+ CharSourceRange FilenameRange,
+ const FileEntry *File,
+ StringRef SearchPath,
+ StringRef RelativePath,
+ const Module *Imported) {
+ }
+
+ /// \brief Callback invoked whenever there was an explicit module-import
+ /// syntax.
+ ///
+ /// \param ImportLoc The location of import directive token.
+ ///
+ /// \param Path The identifiers (and their locations) of the module
+ /// "path", e.g., "std.vector" would be split into "std" and "vector".
+ ///
+ /// \param Imported The imported module; can be null if importing failed.
+ ///
+ virtual void moduleImport(SourceLocation ImportLoc,
+ ModuleIdPath Path,
+ const Module *Imported) {
+ }
+
+ /// \brief Callback invoked when the end of the main file is reached.
+ ///
+ /// No subsequent callbacks will be made.
+ virtual void EndOfMainFile() {
+ }
+
+ /// \brief Callback 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, StringRef str) {
+ }
+
+ /// \brief Callback invoked when start reading any pragma directive.
+ virtual void PragmaDirective(SourceLocation Loc,
+ PragmaIntroducerKind Introducer) {
+ }
+
+ /// \brief Callback invoked when a \#pragma comment directive is read.
+ virtual void PragmaComment(SourceLocation Loc, const IdentifierInfo *Kind,
+ StringRef Str) {
+ }
+
+ /// \brief Callback invoked when a \#pragma detect_mismatch directive is
+ /// read.
+ virtual void PragmaDetectMismatch(SourceLocation Loc, StringRef Name,
+ StringRef Value) {
+ }
+
+ /// \brief Callback invoked when a \#pragma clang __debug directive is read.
+ /// \param Loc The location of the debug directive.
+ /// \param DebugType The identifier following __debug.
+ virtual void PragmaDebug(SourceLocation Loc, StringRef DebugType) {
+ }
+
+ /// \brief Determines the kind of \#pragma invoking a call to PragmaMessage.
+ enum PragmaMessageKind {
+ /// \brief \#pragma message has been invoked.
+ PMK_Message,
+
+ /// \brief \#pragma GCC warning has been invoked.
+ PMK_Warning,
+
+ /// \brief \#pragma GCC error has been invoked.
+ PMK_Error
+ };
+
+ /// \brief Callback invoked when a \#pragma message directive is read.
+ /// \param Loc The location of the message directive.
+ /// \param Namespace The namespace of the message directive.
+ /// \param Kind The type of the message directive.
+ /// \param Str The text of the message directive.
+ virtual void PragmaMessage(SourceLocation Loc, StringRef Namespace,
+ PragmaMessageKind Kind, StringRef Str) {
+ }
+
+ /// \brief Callback invoked when a \#pragma gcc diagnostic push directive
+ /// is read.
+ virtual void PragmaDiagnosticPush(SourceLocation Loc,
+ StringRef Namespace) {
+ }
+
+ /// \brief Callback invoked when a \#pragma gcc diagnostic pop directive
+ /// is read.
+ virtual void PragmaDiagnosticPop(SourceLocation Loc,
+ StringRef Namespace) {
+ }
+
+ /// \brief Callback invoked when a \#pragma gcc diagnostic directive is read.
+ virtual void PragmaDiagnostic(SourceLocation Loc, StringRef Namespace,
+ diag::Severity mapping, StringRef Str) {}
+
+ /// \brief Called when an OpenCL extension is either disabled or
+ /// enabled with a pragma.
+ virtual void PragmaOpenCLExtension(SourceLocation NameLoc,
+ const IdentifierInfo *Name,
+ SourceLocation StateLoc, unsigned State) {
+ }
+
+ /// \brief Callback invoked when a \#pragma warning directive is read.
+ virtual void PragmaWarning(SourceLocation Loc, StringRef WarningSpec,
+ ArrayRef<int> Ids) {
+ }
+
+ /// \brief Callback invoked when a \#pragma warning(push) directive is read.
+ virtual void PragmaWarningPush(SourceLocation Loc, int Level) {
+ }
+
+ /// \brief Callback invoked when a \#pragma warning(pop) directive is read.
+ virtual void PragmaWarningPop(SourceLocation Loc) {
+ }
+
+ /// \brief Called by Preprocessor::HandleMacroExpandedIdentifier when a
+ /// macro invocation is found.
+ virtual void MacroExpands(const Token &MacroNameTok,
+ const MacroDefinition &MD, SourceRange Range,
+ const MacroArgs *Args) {}
+
+ /// \brief Hook called whenever a macro definition is seen.
+ virtual void MacroDefined(const Token &MacroNameTok,
+ const MacroDirective *MD) {
+ }
+
+ /// \brief Hook called whenever a macro \#undef is seen.
+ ///
+ /// MD is released immediately following this callback.
+ virtual void MacroUndefined(const Token &MacroNameTok,
+ const MacroDefinition &MD) {
+ }
+
+ /// \brief Hook called whenever the 'defined' operator is seen.
+ /// \param MD The MacroDirective if the name was a macro, null otherwise.
+ virtual void Defined(const Token &MacroNameTok, const MacroDefinition &MD,
+ SourceRange Range) {
+ }
+
+ /// \brief Hook called when a source range is skipped.
+ /// \param Range The SourceRange that was skipped. The range begins at the
+ /// \#if/\#else directive and ends after the \#endif/\#else directive.
+ virtual void SourceRangeSkipped(SourceRange Range) {
+ }
+
+ enum ConditionValueKind {
+ CVK_NotEvaluated, CVK_False, CVK_True
+ };
+
+ /// \brief Hook called whenever an \#if is seen.
+ /// \param Loc the source location of the directive.
+ /// \param ConditionRange The SourceRange of the expression being tested.
+ /// \param ConditionValue The evaluated value of the condition.
+ ///
+ // FIXME: better to pass in a list (or tree!) of Tokens.
+ virtual void If(SourceLocation Loc, SourceRange ConditionRange,
+ ConditionValueKind ConditionValue) {
+ }
+
+ /// \brief Hook called whenever an \#elif is seen.
+ /// \param Loc the source location of the directive.
+ /// \param ConditionRange The SourceRange of the expression being tested.
+ /// \param ConditionValue The evaluated value of the condition.
+ /// \param IfLoc the source location of the \#if/\#ifdef/\#ifndef directive.
+ // FIXME: better to pass in a list (or tree!) of Tokens.
+ virtual void Elif(SourceLocation Loc, SourceRange ConditionRange,
+ ConditionValueKind ConditionValue, SourceLocation IfLoc) {
+ }
+
+ /// \brief Hook called whenever an \#ifdef is seen.
+ /// \param Loc the source location of the directive.
+ /// \param MacroNameTok Information on the token being tested.
+ /// \param MD The MacroDefinition if the name was a macro, null otherwise.
+ virtual void Ifdef(SourceLocation Loc, const Token &MacroNameTok,
+ const MacroDefinition &MD) {
+ }
+
+ /// \brief Hook called whenever an \#ifndef is seen.
+ /// \param Loc the source location of the directive.
+ /// \param MacroNameTok Information on the token being tested.
+ /// \param MD The MacroDefiniton if the name was a macro, null otherwise.
+ virtual void Ifndef(SourceLocation Loc, const Token &MacroNameTok,
+ const MacroDefinition &MD) {
+ }
+
+ /// \brief Hook called whenever an \#else is seen.
+ /// \param Loc the source location of the directive.
+ /// \param IfLoc the source location of the \#if/\#ifdef/\#ifndef directive.
+ virtual void Else(SourceLocation Loc, SourceLocation IfLoc) {
+ }
+
+ /// \brief Hook called whenever an \#endif is seen.
+ /// \param Loc the source location of the directive.
+ /// \param IfLoc the source location of the \#if/\#ifdef/\#ifndef directive.
+ virtual void Endif(SourceLocation Loc, SourceLocation IfLoc) {
+ }
+};
+
+/// \brief Simple wrapper class for chaining callbacks.
+class PPChainedCallbacks : public PPCallbacks {
+ virtual void anchor();
+ std::unique_ptr<PPCallbacks> First, Second;
+
+public:
+ PPChainedCallbacks(std::unique_ptr<PPCallbacks> _First,
+ std::unique_ptr<PPCallbacks> _Second)
+ : First(std::move(_First)), Second(std::move(_Second)) {}
+
+ void FileChanged(SourceLocation Loc, FileChangeReason Reason,
+ SrcMgr::CharacteristicKind FileType,
+ FileID PrevFID) override {
+ First->FileChanged(Loc, Reason, FileType, PrevFID);
+ Second->FileChanged(Loc, Reason, FileType, PrevFID);
+ }
+
+ void FileSkipped(const FileEntry &SkippedFile,
+ const Token &FilenameTok,
+ SrcMgr::CharacteristicKind FileType) override {
+ First->FileSkipped(SkippedFile, FilenameTok, FileType);
+ Second->FileSkipped(SkippedFile, FilenameTok, FileType);
+ }
+
+ bool FileNotFound(StringRef FileName,
+ SmallVectorImpl<char> &RecoveryPath) override {
+ return First->FileNotFound(FileName, RecoveryPath) ||
+ Second->FileNotFound(FileName, RecoveryPath);
+ }
+
+ void InclusionDirective(SourceLocation HashLoc, const Token &IncludeTok,
+ StringRef FileName, bool IsAngled,
+ CharSourceRange FilenameRange, const FileEntry *File,
+ StringRef SearchPath, StringRef RelativePath,
+ const Module *Imported) override {
+ First->InclusionDirective(HashLoc, IncludeTok, FileName, IsAngled,
+ FilenameRange, File, SearchPath, RelativePath,
+ Imported);
+ Second->InclusionDirective(HashLoc, IncludeTok, FileName, IsAngled,
+ FilenameRange, File, SearchPath, RelativePath,
+ Imported);
+ }
+
+ void moduleImport(SourceLocation ImportLoc, ModuleIdPath Path,
+ const Module *Imported) override {
+ First->moduleImport(ImportLoc, Path, Imported);
+ Second->moduleImport(ImportLoc, Path, Imported);
+ }
+
+ void EndOfMainFile() override {
+ First->EndOfMainFile();
+ Second->EndOfMainFile();
+ }
+
+ void Ident(SourceLocation Loc, StringRef str) override {
+ First->Ident(Loc, str);
+ Second->Ident(Loc, str);
+ }
+
+ void PragmaComment(SourceLocation Loc, const IdentifierInfo *Kind,
+ StringRef Str) override {
+ First->PragmaComment(Loc, Kind, Str);
+ Second->PragmaComment(Loc, Kind, Str);
+ }
+
+ void PragmaDetectMismatch(SourceLocation Loc, StringRef Name,
+ StringRef Value) override {
+ First->PragmaDetectMismatch(Loc, Name, Value);
+ Second->PragmaDetectMismatch(Loc, Name, Value);
+ }
+
+ void PragmaMessage(SourceLocation Loc, StringRef Namespace,
+ PragmaMessageKind Kind, StringRef Str) override {
+ First->PragmaMessage(Loc, Namespace, Kind, Str);
+ Second->PragmaMessage(Loc, Namespace, Kind, Str);
+ }
+
+ void PragmaDiagnosticPush(SourceLocation Loc, StringRef Namespace) override {
+ First->PragmaDiagnosticPush(Loc, Namespace);
+ Second->PragmaDiagnosticPush(Loc, Namespace);
+ }
+
+ void PragmaDiagnosticPop(SourceLocation Loc, StringRef Namespace) override {
+ First->PragmaDiagnosticPop(Loc, Namespace);
+ Second->PragmaDiagnosticPop(Loc, Namespace);
+ }
+
+ void PragmaDiagnostic(SourceLocation Loc, StringRef Namespace,
+ diag::Severity mapping, StringRef Str) override {
+ First->PragmaDiagnostic(Loc, Namespace, mapping, Str);
+ Second->PragmaDiagnostic(Loc, Namespace, mapping, Str);
+ }
+
+ void PragmaOpenCLExtension(SourceLocation NameLoc, const IdentifierInfo *Name,
+ SourceLocation StateLoc, unsigned State) override {
+ First->PragmaOpenCLExtension(NameLoc, Name, StateLoc, State);
+ Second->PragmaOpenCLExtension(NameLoc, Name, StateLoc, State);
+ }
+
+ void PragmaWarning(SourceLocation Loc, StringRef WarningSpec,
+ ArrayRef<int> Ids) override {
+ First->PragmaWarning(Loc, WarningSpec, Ids);
+ Second->PragmaWarning(Loc, WarningSpec, Ids);
+ }
+
+ void PragmaWarningPush(SourceLocation Loc, int Level) override {
+ First->PragmaWarningPush(Loc, Level);
+ Second->PragmaWarningPush(Loc, Level);
+ }
+
+ void PragmaWarningPop(SourceLocation Loc) override {
+ First->PragmaWarningPop(Loc);
+ Second->PragmaWarningPop(Loc);
+ }
+
+ void MacroExpands(const Token &MacroNameTok, const MacroDefinition &MD,
+ SourceRange Range, const MacroArgs *Args) override {
+ First->MacroExpands(MacroNameTok, MD, Range, Args);
+ Second->MacroExpands(MacroNameTok, MD, Range, Args);
+ }
+
+ void MacroDefined(const Token &MacroNameTok, const MacroDirective *MD) override {
+ First->MacroDefined(MacroNameTok, MD);
+ Second->MacroDefined(MacroNameTok, MD);
+ }
+
+ void MacroUndefined(const Token &MacroNameTok,
+ const MacroDefinition &MD) override {
+ First->MacroUndefined(MacroNameTok, MD);
+ Second->MacroUndefined(MacroNameTok, MD);
+ }
+
+ void Defined(const Token &MacroNameTok, const MacroDefinition &MD,
+ SourceRange Range) override {
+ First->Defined(MacroNameTok, MD, Range);
+ Second->Defined(MacroNameTok, MD, Range);
+ }
+
+ void SourceRangeSkipped(SourceRange Range) override {
+ First->SourceRangeSkipped(Range);
+ Second->SourceRangeSkipped(Range);
+ }
+
+ /// \brief Hook called whenever an \#if is seen.
+ void If(SourceLocation Loc, SourceRange ConditionRange,
+ ConditionValueKind ConditionValue) override {
+ First->If(Loc, ConditionRange, ConditionValue);
+ Second->If(Loc, ConditionRange, ConditionValue);
+ }
+
+ /// \brief Hook called whenever an \#elif is seen.
+ void Elif(SourceLocation Loc, SourceRange ConditionRange,
+ ConditionValueKind ConditionValue, SourceLocation IfLoc) override {
+ First->Elif(Loc, ConditionRange, ConditionValue, IfLoc);
+ Second->Elif(Loc, ConditionRange, ConditionValue, IfLoc);
+ }
+
+ /// \brief Hook called whenever an \#ifdef is seen.
+ void Ifdef(SourceLocation Loc, const Token &MacroNameTok,
+ const MacroDefinition &MD) override {
+ First->Ifdef(Loc, MacroNameTok, MD);
+ Second->Ifdef(Loc, MacroNameTok, MD);
+ }
+
+ /// \brief Hook called whenever an \#ifndef is seen.
+ void Ifndef(SourceLocation Loc, const Token &MacroNameTok,
+ const MacroDefinition &MD) override {
+ First->Ifndef(Loc, MacroNameTok, MD);
+ Second->Ifndef(Loc, MacroNameTok, MD);
+ }
+
+ /// \brief Hook called whenever an \#else is seen.
+ void Else(SourceLocation Loc, SourceLocation IfLoc) override {
+ First->Else(Loc, IfLoc);
+ Second->Else(Loc, IfLoc);
+ }
+
+ /// \brief Hook called whenever an \#endif is seen.
+ void Endif(SourceLocation Loc, SourceLocation IfLoc) override {
+ First->Endif(Loc, IfLoc);
+ Second->Endif(Loc, IfLoc);
+ }
+};
+
+} // end namespace clang
+
+#endif
diff --git a/contrib/llvm/tools/clang/include/clang/Lex/PPConditionalDirectiveRecord.h b/contrib/llvm/tools/clang/include/clang/Lex/PPConditionalDirectiveRecord.h
new file mode 100644
index 0000000..8c52275
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Lex/PPConditionalDirectiveRecord.h
@@ -0,0 +1,103 @@
+//===--- PPConditionalDirectiveRecord.h - Preprocessing Directives-*- C++ -*-=//
+//
+// 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 PPConditionalDirectiveRecord class, which maintains
+// a record of conditional directive regions.
+//
+//===----------------------------------------------------------------------===//
+#ifndef LLVM_CLANG_LEX_PPCONDITIONALDIRECTIVERECORD_H
+#define LLVM_CLANG_LEX_PPCONDITIONALDIRECTIVERECORD_H
+
+#include "clang/Basic/SourceLocation.h"
+#include "clang/Lex/PPCallbacks.h"
+#include "llvm/ADT/SmallVector.h"
+#include <vector>
+
+namespace clang {
+
+/// \brief Records preprocessor conditional directive regions and allows
+/// querying in which region source locations belong to.
+class PPConditionalDirectiveRecord : public PPCallbacks {
+ SourceManager &SourceMgr;
+
+ SmallVector<SourceLocation, 6> CondDirectiveStack;
+
+ class CondDirectiveLoc {
+ SourceLocation Loc;
+ SourceLocation RegionLoc;
+
+ public:
+ CondDirectiveLoc(SourceLocation Loc, SourceLocation RegionLoc)
+ : Loc(Loc), RegionLoc(RegionLoc) {}
+
+ SourceLocation getLoc() const { return Loc; }
+ SourceLocation getRegionLoc() const { return RegionLoc; }
+
+ class Comp {
+ SourceManager &SM;
+ public:
+ explicit Comp(SourceManager &SM) : SM(SM) {}
+ bool operator()(const CondDirectiveLoc &LHS,
+ const CondDirectiveLoc &RHS) {
+ return SM.isBeforeInTranslationUnit(LHS.getLoc(), RHS.getLoc());
+ }
+ bool operator()(const CondDirectiveLoc &LHS, SourceLocation RHS) {
+ return SM.isBeforeInTranslationUnit(LHS.getLoc(), RHS);
+ }
+ bool operator()(SourceLocation LHS, const CondDirectiveLoc &RHS) {
+ return SM.isBeforeInTranslationUnit(LHS, RHS.getLoc());
+ }
+ };
+ };
+
+ typedef std::vector<CondDirectiveLoc> CondDirectiveLocsTy;
+ /// \brief The locations of conditional directives in source order.
+ CondDirectiveLocsTy CondDirectiveLocs;
+
+ void addCondDirectiveLoc(CondDirectiveLoc DirLoc);
+
+public:
+ /// \brief Construct a new preprocessing record.
+ explicit PPConditionalDirectiveRecord(SourceManager &SM);
+
+ size_t getTotalMemory() const;
+
+ SourceManager &getSourceManager() const { return SourceMgr; }
+
+ /// \brief Returns true if the given range intersects with a conditional
+ /// directive. if a \#if/\#endif block is fully contained within the range,
+ /// this function will return false.
+ bool rangeIntersectsConditionalDirective(SourceRange Range) const;
+
+ /// \brief Returns true if the given locations are in different regions,
+ /// separated by conditional directive blocks.
+ bool areInDifferentConditionalDirectiveRegion(SourceLocation LHS,
+ SourceLocation RHS) const {
+ return findConditionalDirectiveRegionLoc(LHS) !=
+ findConditionalDirectiveRegionLoc(RHS);
+ }
+
+ SourceLocation findConditionalDirectiveRegionLoc(SourceLocation Loc) const;
+
+private:
+ void If(SourceLocation Loc, SourceRange ConditionRange,
+ ConditionValueKind ConditionValue) override;
+ void Elif(SourceLocation Loc, SourceRange ConditionRange,
+ ConditionValueKind ConditionValue, SourceLocation IfLoc) override;
+ void Ifdef(SourceLocation Loc, const Token &MacroNameTok,
+ const MacroDefinition &MD) override;
+ void Ifndef(SourceLocation Loc, const Token &MacroNameTok,
+ const MacroDefinition &MD) override;
+ void Else(SourceLocation Loc, SourceLocation IfLoc) override;
+ void Endif(SourceLocation Loc, SourceLocation IfLoc) override;
+};
+
+} // end namespace clang
+
+#endif // LLVM_CLANG_LEX_PPCONDITIONALDIRECTIVERECORD_H
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..904be79
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Lex/PTHLexer.h
@@ -0,0 +1,104 @@
+//===--- 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_LEX_PTHLEXER_H
+#define LLVM_CLANG_LEX_PTHLEXER_H
+
+#include "clang/Lex/PreprocessorLexer.h"
+
+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 &) = delete;
+ void operator=(const PTHLexer &) = delete;
+
+ /// 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() override {}
+
+ /// Lex - Return the next token.
+ bool 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) override { Lex(Result); }
+
+ /// getSourceLocation - Return a source location for the token in
+ /// the current file.
+ SourceLocation getSourceLocation() override;
+
+ /// 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..26178ed
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Lex/PTHManager.h
@@ -0,0 +1,150 @@
+//===--- 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_LEX_PTHMANAGER_H
+#define LLVM_CLANG_LEX_PTHMANAGER_H
+
+#include "clang/Basic/Diagnostic.h"
+#include "clang/Basic/IdentifierTable.h"
+#include "clang/Basic/LangOptions.h"
+#include "clang/Lex/PTHLexer.h"
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/Support/Allocator.h"
+#include "llvm/Support/OnDiskHashTable.h"
+#include <string>
+
+namespace llvm {
+ class MemoryBuffer;
+}
+
+namespace clang {
+
+class FileEntry;
+class PTHLexer;
+class DiagnosticsEngine;
+class FileSystemStatCache;
+
+class PTHManager : public IdentifierInfoLookup {
+ friend class PTHLexer;
+
+ friend class PTHStatCache;
+
+ class PTHStringLookupTrait;
+ class PTHFileLookupTrait;
+ typedef llvm::OnDiskChainedHashTable<PTHStringLookupTrait> PTHStringIdLookup;
+ typedef llvm::OnDiskChainedHashTable<PTHFileLookupTrait> PTHFileLookup;
+
+ /// The memory mapped PTH file.
+ std::unique_ptr<const llvm::MemoryBuffer> Buf;
+
+ /// Alloc - Allocator used for IdentifierInfo objects.
+ llvm::BumpPtrAllocator Alloc;
+
+ /// IdMap - A lazily generated cache mapping from persistent identifiers to
+ /// IdentifierInfo*.
+ std::unique_ptr<IdentifierInfo *[], llvm::FreeDeleter> PerIDCache;
+
+ /// FileLookup - Abstract data structure used for mapping between files
+ /// and token data in the PTH file.
+ std::unique_ptr<PTHFileLookup> 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().
+ std::unique_ptr<PTHStringIdLookup> 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(std::unique_ptr<const llvm::MemoryBuffer> buf,
+ std::unique_ptr<PTHFileLookup> fileLookup,
+ const unsigned char *idDataTable,
+ std::unique_ptr<IdentifierInfo *[], llvm::FreeDeleter> perIDCache,
+ std::unique_ptr<PTHStringIdLookup> stringIdLookup, unsigned numIds,
+ const unsigned char *spellingBase, const char *originalSourceFile);
+
+ PTHManager(const PTHManager &) = delete;
+ void operator=(const PTHManager &) = delete;
+
+ /// 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 = 10 };
+
+ ~PTHManager() override;
+
+ /// 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(StringRef Name) override;
+
+ /// 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(StringRef file, DiagnosticsEngine &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.
+ std::unique_ptr<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..274f0da
--- /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_LEX_PRAGMA_H
+#define LLVM_CLANG_LEX_PRAGMA_H
+
+#include "clang/Basic/LLVM.h"
+#include "llvm/ADT/StringMap.h"
+#include "llvm/ADT/StringRef.h"
+#include <cassert>
+
+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(StringRef name) : Name(name) {}
+ PragmaHandler() {}
+ virtual ~PragmaHandler();
+
+ 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 nullptr; }
+};
+
+/// EmptyPragmaHandler - A pragma handler which takes no action, which can be
+/// used to ignore particular pragmas.
+class EmptyPragmaHandler : public PragmaHandler {
+public:
+ explicit EmptyPragmaHandler(StringRef Name = StringRef());
+
+ void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
+ Token &FirstToken) override;
+};
+
+/// 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(StringRef Name) : PragmaHandler(Name) {}
+ ~PragmaNamespace() override;
+
+ /// 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(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();
+ }
+
+ void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
+ Token &FirstToken) override;
+
+ PragmaNamespace *getIfNamespace() override { 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..87b8ce1
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Lex/PreprocessingRecord.h
@@ -0,0 +1,536 @@
+//===--- 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/Basic/IdentifierTable.h"
+#include "clang/Basic/SourceLocation.h"
+#include "clang/Lex/PPCallbacks.h"
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/Optional.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/iterator.h"
+#include "llvm/Support/Allocator.h"
+#include "llvm/Support/Compiler.h"
+#include <vector>
+
+namespace clang {
+ class IdentifierInfo;
+ class MacroInfo;
+ class PreprocessingRecord;
+}
+
+/// \brief Allocates memory within a Clang preprocessing record.
+void *operator new(size_t bytes, clang::PreprocessingRecord &PR,
+ unsigned alignment = 8) LLVM_NOEXCEPT;
+
+/// \brief Frees memory allocated in a Clang preprocessing record.
+void operator delete(void *ptr, clang::PreprocessingRecord &PR,
+ unsigned) LLVM_NOEXCEPT;
+
+namespace clang {
+ class MacroDefinitionRecord;
+ class FileEntry;
+
+ /// \brief Base class that describes a preprocessed entity, which may be a
+ /// preprocessor directive or macro expansion.
+ class PreprocessedEntity {
+ public:
+ /// \brief The kind of preprocessed entity an object describes.
+ enum EntityKind {
+ /// \brief Indicates a problem trying to load the preprocessed entity.
+ InvalidKind,
+
+ /// \brief A macro expansion.
+ MacroExpansionKind,
+
+ /// \defgroup Preprocessing directives
+ /// @{
+
+ /// \brief A macro definition.
+ MacroDefinitionKind,
+
+ /// \brief An inclusion directive, such as \c \#include, \c
+ /// \#import, or \c \#include_next.
+ InclusionDirectiveKind,
+
+ /// @}
+
+ FirstPreprocessingDirective = MacroDefinitionKind,
+ 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) { }
+
+ friend class PreprocessingRecord;
+
+ 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 LLVM_READONLY { return Range; }
+
+ /// \brief Returns true if there was a problem loading the preprocessed
+ /// entity.
+ bool isInvalid() const { return Kind == InvalidKind; }
+
+ // 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) LLVM_NOEXCEPT {
+ return ::operator new(bytes, PR, alignment);
+ }
+
+ void *operator new(size_t bytes, void *mem) LLVM_NOEXCEPT { return mem; }
+
+ void operator delete(void *ptr, PreprocessingRecord &PR,
+ unsigned alignment) LLVM_NOEXCEPT {
+ return ::operator delete(ptr, PR, alignment);
+ }
+
+ void operator delete(void *, std::size_t) LLVM_NOEXCEPT {}
+ void operator delete(void *, void *) LLVM_NOEXCEPT {}
+
+ private:
+ // Make vanilla 'new' and 'delete' illegal for preprocessed entities.
+ void *operator new(size_t bytes) LLVM_NOEXCEPT;
+ void operator delete(void *data) LLVM_NOEXCEPT;
+ };
+
+ /// \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;
+ }
+ };
+
+ /// \brief Record the location of a macro definition.
+ class MacroDefinitionRecord : public PreprocessingDirective {
+ /// \brief The name of the macro being defined.
+ const IdentifierInfo *Name;
+
+ public:
+ explicit MacroDefinitionRecord(const IdentifierInfo *Name,
+ SourceRange Range)
+ : PreprocessingDirective(MacroDefinitionKind, Range), Name(Name) {}
+
+ /// \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 getSourceRange().getBegin(); }
+
+ // Implement isa/cast/dyncast/etc.
+ static bool classof(const PreprocessedEntity *PE) {
+ return PE->getKind() == MacroDefinitionKind;
+ }
+ };
+
+ /// \brief Records the location of a macro expansion.
+ class MacroExpansion : public PreprocessedEntity {
+ /// \brief The definition of this macro or the name of the macro if it is
+ /// a builtin macro.
+ llvm::PointerUnion<IdentifierInfo *, MacroDefinitionRecord *> NameOrDef;
+
+ public:
+ MacroExpansion(IdentifierInfo *BuiltinName, SourceRange Range)
+ : PreprocessedEntity(MacroExpansionKind, Range),
+ NameOrDef(BuiltinName) {}
+
+ MacroExpansion(MacroDefinitionRecord *Definition, SourceRange Range)
+ : PreprocessedEntity(MacroExpansionKind, Range), NameOrDef(Definition) {
+ }
+
+ /// \brief True if it is a builtin macro.
+ bool isBuiltinMacro() const { return NameOrDef.is<IdentifierInfo *>(); }
+
+ /// \brief The name of the macro being expanded.
+ const IdentifierInfo *getName() const {
+ if (MacroDefinitionRecord *Def = getDefinition())
+ return Def->getName();
+ return NameOrDef.get<IdentifierInfo *>();
+ }
+
+ /// \brief The definition of the macro being expanded. May return null if
+ /// this is a builtin macro.
+ MacroDefinitionRecord *getDefinition() const {
+ return NameOrDef.dyn_cast<MacroDefinitionRecord *>();
+ }
+
+ // Implement isa/cast/dyncast/etc.
+ static bool classof(const PreprocessedEntity *PE) {
+ return PE->getKind() == MacroExpansionKind;
+ }
+ };
+
+ /// \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.
+ 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 Whether the inclusion directive was automatically turned into
+ /// a module import.
+ unsigned ImportedModule : 1;
+
+ /// \brief The file that was included.
+ const FileEntry *File;
+
+ public:
+ InclusionDirective(PreprocessingRecord &PPRec,
+ InclusionKind Kind, StringRef FileName,
+ bool InQuotes, bool ImportedModule,
+ 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.
+ 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 Determine whether the inclusion directive was automatically
+ /// turned into a module import.
+ bool importedModule() const { return ImportedModule; }
+
+ /// \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;
+ }
+ };
+
+ /// \brief An abstract class that should be subclassed by any external source
+ /// of preprocessing record entries.
+ class ExternalPreprocessingRecordSource {
+ public:
+ virtual ~ExternalPreprocessingRecordSource();
+
+ /// \brief Read a preallocated preprocessed entity from the external source.
+ ///
+ /// \returns null if an error occurred that prevented the preprocessed
+ /// entity from being loaded.
+ virtual PreprocessedEntity *ReadPreprocessedEntity(unsigned Index) = 0;
+
+ /// \brief Returns a pair of [Begin, End) indices of preallocated
+ /// preprocessed entities that \p Range encompasses.
+ virtual std::pair<unsigned, unsigned>
+ findPreprocessedEntitiesInRange(SourceRange Range) = 0;
+
+ /// \brief Optionally returns true or false if the preallocated preprocessed
+ /// entity with index \p Index came from file \p FID.
+ virtual Optional<bool> isPreprocessedEntityInFileID(unsigned Index,
+ FileID FID) {
+ return None;
+ }
+ };
+
+ /// \brief A record of the steps taken while preprocessing a source file,
+ /// including the various preprocessing directives processed, macros
+ /// expanded, etc.
+ class PreprocessingRecord : public PPCallbacks {
+ SourceManager &SourceMgr;
+
+ /// \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 The set of preprocessed entities in this record that have been
+ /// loaded from external sources.
+ ///
+ /// The entries in this vector are loaded lazily from the external source,
+ /// and are referenced by the iterator using negative indices.
+ std::vector<PreprocessedEntity *> LoadedPreprocessedEntities;
+
+ /// \brief The set of ranges that were skipped by the preprocessor,
+ std::vector<SourceRange> SkippedRanges;
+
+ /// \brief Global (loaded or local) ID for a preprocessed entity.
+ /// Negative values are used to indicate preprocessed entities
+ /// loaded from the external source while non-negative values are used to
+ /// indicate preprocessed entities introduced by the current preprocessor.
+ /// Value -1 corresponds to element 0 in the loaded entities vector,
+ /// value -2 corresponds to element 1 in the loaded entities vector, etc.
+ /// Value 0 is an invalid value, the index to local entities is 1-based,
+ /// value 1 corresponds to element 0 in the local entities vector,
+ /// value 2 corresponds to element 1 in the local entities vector, etc.
+ class PPEntityID {
+ int ID;
+ explicit PPEntityID(int ID) : ID(ID) {}
+ friend class PreprocessingRecord;
+ public:
+ PPEntityID() : ID(0) {}
+ };
+
+ static PPEntityID getPPEntityID(unsigned Index, bool isLoaded) {
+ return isLoaded ? PPEntityID(-int(Index)-1) : PPEntityID(Index+1);
+ }
+
+ /// \brief Mapping from MacroInfo structures to their definitions.
+ llvm::DenseMap<const MacroInfo *, MacroDefinitionRecord *> MacroDefinitions;
+
+ /// \brief External source of preprocessed entities.
+ ExternalPreprocessingRecordSource *ExternalSource;
+
+ /// \brief Retrieve the preprocessed entity at the given ID.
+ PreprocessedEntity *getPreprocessedEntity(PPEntityID PPID);
+
+ /// \brief Retrieve the loaded preprocessed entity at the given index.
+ PreprocessedEntity *getLoadedPreprocessedEntity(unsigned Index);
+
+ /// \brief Determine the number of preprocessed entities that were
+ /// loaded (or can be loaded) from an external source.
+ unsigned getNumLoadedPreprocessedEntities() const {
+ return LoadedPreprocessedEntities.size();
+ }
+
+ /// \brief Returns a pair of [Begin, End) indices of local preprocessed
+ /// entities that \p Range encompasses.
+ std::pair<unsigned, unsigned>
+ findLocalPreprocessedEntitiesInRange(SourceRange Range) const;
+ unsigned findBeginLocalPreprocessedEntity(SourceLocation Loc) const;
+ unsigned findEndLocalPreprocessedEntity(SourceLocation Loc) const;
+
+ /// \brief Allocate space for a new set of loaded preprocessed entities.
+ ///
+ /// \returns The index into the set of loaded preprocessed entities, which
+ /// corresponds to the first newly-allocated entity.
+ unsigned allocateLoadedEntities(unsigned NumEntities);
+
+ /// \brief Register a new macro definition.
+ void RegisterMacroDefinition(MacroInfo *Macro, MacroDefinitionRecord *Def);
+
+ public:
+ /// \brief Construct a new preprocessing record.
+ explicit PreprocessingRecord(SourceManager &SM);
+
+ /// \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) { }
+
+ size_t getTotalMemory() const;
+
+ SourceManager &getSourceManager() const { return SourceMgr; }
+
+ /// Iteration over the preprocessed entities.
+ ///
+ /// In a complete iteration, the iterator walks the range [-M, N),
+ /// where negative values are used to indicate preprocessed entities
+ /// loaded from the external source while non-negative values are used to
+ /// indicate preprocessed entities introduced by the current preprocessor.
+ /// However, to provide iteration in source order (for, e.g., chained
+ /// precompiled headers), dereferencing the iterator flips the negative
+ /// values (corresponding to loaded entities), so that position -M
+ /// corresponds to element 0 in the loaded entities vector, position -M+1
+ /// corresponds to element 1 in the loaded entities vector, etc. This
+ /// gives us a reasonably efficient, source-order walk.
+ ///
+ /// We define this as a wrapping iterator around an int. The
+ /// iterator_adaptor_base class forwards the iterator methods to basic
+ /// integer arithmetic.
+ class iterator : public llvm::iterator_adaptor_base<
+ iterator, int, std::random_access_iterator_tag,
+ PreprocessedEntity *, int, PreprocessedEntity *,
+ PreprocessedEntity *> {
+ PreprocessingRecord *Self;
+
+ iterator(PreprocessingRecord *Self, int Position)
+ : iterator::iterator_adaptor_base(Position), Self(Self) {}
+ friend class PreprocessingRecord;
+
+ public:
+ iterator() : iterator(nullptr, 0) {}
+
+ PreprocessedEntity *operator*() const {
+ bool isLoaded = this->I < 0;
+ unsigned Index = isLoaded ?
+ Self->LoadedPreprocessedEntities.size() + this->I : this->I;
+ PPEntityID ID = Self->getPPEntityID(Index, isLoaded);
+ return Self->getPreprocessedEntity(ID);
+ }
+ PreprocessedEntity *operator->() const { return **this; }
+ };
+
+ /// \brief Begin iterator for all preprocessed entities.
+ iterator begin() {
+ return iterator(this, -(int)LoadedPreprocessedEntities.size());
+ }
+
+ /// \brief End iterator for all preprocessed entities.
+ iterator end() {
+ return iterator(this, PreprocessedEntities.size());
+ }
+
+ /// \brief Begin iterator for local, non-loaded, preprocessed entities.
+ iterator local_begin() {
+ return iterator(this, 0);
+ }
+
+ /// \brief End iterator for local, non-loaded, preprocessed entities.
+ iterator local_end() {
+ return iterator(this, PreprocessedEntities.size());
+ }
+
+ /// \brief iterator range for the given range of loaded
+ /// preprocessed entities.
+ llvm::iterator_range<iterator> getIteratorsForLoadedRange(unsigned start,
+ unsigned count) {
+ unsigned end = start + count;
+ assert(end <= LoadedPreprocessedEntities.size());
+ return llvm::make_range(
+ iterator(this, int(start) - LoadedPreprocessedEntities.size()),
+ iterator(this, int(end) - LoadedPreprocessedEntities.size()));
+ }
+
+ /// \brief Returns a range of preprocessed entities that source range \p R
+ /// encompasses.
+ ///
+ /// \param R the range to look for preprocessed entities.
+ ///
+ llvm::iterator_range<iterator>
+ getPreprocessedEntitiesInRange(SourceRange R);
+
+ /// \brief Returns true if the preprocessed entity that \p PPEI iterator
+ /// points to is coming from the file \p FID.
+ ///
+ /// Can be used to avoid implicit deserializations of preallocated
+ /// preprocessed entities if we only care about entities of a specific file
+ /// and not from files \#included in the range given at
+ /// \see getPreprocessedEntitiesInRange.
+ bool isEntityInFileID(iterator PPEI, FileID FID);
+
+ /// \brief Add a new preprocessed entity to this record.
+ PPEntityID addPreprocessedEntity(PreprocessedEntity *Entity);
+
+ /// \brief Set the external source for preprocessed entities.
+ void SetExternalSource(ExternalPreprocessingRecordSource &Source);
+
+ /// \brief Retrieve the external source for preprocessed entities.
+ ExternalPreprocessingRecordSource *getExternalSource() const {
+ return ExternalSource;
+ }
+
+ /// \brief Retrieve the macro definition that corresponds to the given
+ /// \c MacroInfo.
+ MacroDefinitionRecord *findMacroDefinition(const MacroInfo *MI);
+
+ /// \brief Retrieve all ranges that got skipped while preprocessing.
+ const std::vector<SourceRange> &getSkippedRanges() const {
+ return SkippedRanges;
+ }
+
+ private:
+ void MacroExpands(const Token &Id, const MacroDefinition &MD,
+ SourceRange Range, const MacroArgs *Args) override;
+ void MacroDefined(const Token &Id, const MacroDirective *MD) override;
+ void MacroUndefined(const Token &Id, const MacroDefinition &MD) override;
+ void InclusionDirective(SourceLocation HashLoc, const Token &IncludeTok,
+ StringRef FileName, bool IsAngled,
+ CharSourceRange FilenameRange,
+ const FileEntry *File, StringRef SearchPath,
+ StringRef RelativePath,
+ const Module *Imported) override;
+ void Ifdef(SourceLocation Loc, const Token &MacroNameTok,
+ const MacroDefinition &MD) override;
+ void Ifndef(SourceLocation Loc, const Token &MacroNameTok,
+ const MacroDefinition &MD) override;
+ /// \brief Hook called whenever the 'defined' operator is seen.
+ void Defined(const Token &MacroNameTok, const MacroDefinition &MD,
+ SourceRange Range) override;
+
+ void SourceRangeSkipped(SourceRange Range) override;
+
+ void addMacroExpansion(const Token &Id, const MacroInfo *MI,
+ SourceRange Range);
+
+ /// \brief Cached result of the last \see getPreprocessedEntitiesInRange
+ /// query.
+ struct {
+ SourceRange Range;
+ std::pair<int, int> Result;
+ } CachedRangeQuery;
+
+ std::pair<int, int> getPreprocessedEntitiesInRangeSlow(SourceRange R);
+
+ friend class ASTReader;
+ friend class ASTWriter;
+ };
+} // end namespace clang
+
+inline void *operator new(size_t bytes, clang::PreprocessingRecord &PR,
+ unsigned alignment) LLVM_NOEXCEPT {
+ return PR.Allocate(bytes, alignment);
+}
+
+inline void operator delete(void *ptr, clang::PreprocessingRecord &PR,
+ unsigned) LLVM_NOEXCEPT {
+ 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..f6154b6
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Lex/Preprocessor.h
@@ -0,0 +1,1911 @@
+//===--- 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.
+//
+//===----------------------------------------------------------------------===//
+///
+/// \file
+/// \brief Defines the clang::Preprocessor interface.
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_LEX_PREPROCESSOR_H
+#define LLVM_CLANG_LEX_PREPROCESSOR_H
+
+#include "clang/Basic/Builtins.h"
+#include "clang/Basic/Diagnostic.h"
+#include "clang/Basic/IdentifierTable.h"
+#include "clang/Basic/SourceLocation.h"
+#include "clang/Lex/Lexer.h"
+#include "clang/Lex/MacroInfo.h"
+#include "clang/Lex/ModuleMap.h"
+#include "clang/Lex/PPCallbacks.h"
+#include "clang/Lex/PTHLexer.h"
+#include "clang/Lex/TokenLexer.h"
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/IntrusiveRefCntPtr.h"
+#include "llvm/ADT/SmallPtrSet.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/TinyPtrVector.h"
+#include "llvm/Support/Allocator.h"
+#include <memory>
+#include <vector>
+
+namespace llvm {
+ template<unsigned InternalLen> class SmallString;
+}
+
+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;
+class ModuleLoader;
+class PTHManager;
+class PreprocessorOptions;
+
+/// \brief Stores token information for comparing actual tokens with
+/// predefined values. Only handles simple tokens and identifiers.
+class TokenValue {
+ tok::TokenKind Kind;
+ IdentifierInfo *II;
+
+public:
+ TokenValue(tok::TokenKind Kind) : Kind(Kind), II(nullptr) {
+ assert(Kind != tok::raw_identifier && "Raw identifiers are not supported.");
+ assert(Kind != tok::identifier &&
+ "Identifiers should be created by TokenValue(IdentifierInfo *)");
+ assert(!tok::isLiteral(Kind) && "Literals are not supported.");
+ assert(!tok::isAnnotation(Kind) && "Annotations are not supported.");
+ }
+ TokenValue(IdentifierInfo *II) : Kind(tok::identifier), II(II) {}
+ bool operator==(const Token &Tok) const {
+ return Tok.getKind() == Kind &&
+ (!II || II == Tok.getIdentifierInfo());
+ }
+};
+
+/// \brief Context in which macro name is used.
+enum MacroUse {
+ MU_Other = 0, // other than #define or #undef
+ MU_Define = 1, // macro name specified in #define
+ MU_Undef = 2 // macro name specified in #undef
+};
+
+/// \brief 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 : public RefCountedBase<Preprocessor> {
+ IntrusiveRefCntPtr<PreprocessorOptions> PPOpts;
+ DiagnosticsEngine *Diags;
+ LangOptions &LangOpts;
+ const TargetInfo *Target;
+ const TargetInfo *AuxTarget;
+ FileManager &FileMgr;
+ SourceManager &SourceMgr;
+ std::unique_ptr<ScratchBuffer> ScratchBuf;
+ HeaderSearch &HeaderInfo;
+ ModuleLoader &TheModuleLoader;
+
+ /// \brief External source of macros.
+ ExternalPreprocessorSource *ExternalSource;
+
+
+ /// An optional PTHManager object used for getting tokens from
+ /// a token cache rather than lexing the original source file.
+ std::unique_ptr<PTHManager> PTH;
+
+ /// 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__identifier; // __identifier
+ IdentifierInfo *Ident__VA_ARGS__; // __VA_ARGS__
+ IdentifierInfo *Ident__has_feature; // __has_feature
+ IdentifierInfo *Ident__has_extension; // __has_extension
+ 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
+ IdentifierInfo *Ident__has_warning; // __has_warning
+ IdentifierInfo *Ident__is_identifier; // __is_identifier
+ IdentifierInfo *Ident__building_module; // __building_module
+ IdentifierInfo *Ident__MODULE__; // __MODULE__
+ IdentifierInfo *Ident__has_cpp_attribute; // __has_cpp_attribute
+ IdentifierInfo *Ident__has_declspec; // __has_declspec_attribute
+
+ SourceLocation DATELoc, TIMELoc;
+ unsigned CounterValue; // Next __COUNTER__ value.
+
+ enum {
+ /// \brief Maximum depth of \#includes.
+ MaxAllowedIncludeStackDepth = 200
+ };
+
+ // State that is set before the preprocessor begins.
+ bool KeepComments : 1;
+ bool KeepMacroComments : 1;
+ bool SuppressIncludeNotFoundError : 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;
+
+ /// True if macro expansion is disabled.
+ bool DisableMacroExpansion : 1;
+
+ /// Temporarily disables DisableMacroExpansion (i.e. enables expansion)
+ /// when parsing preprocessor directives.
+ bool MacroExpansionInDirectivesOverride : 1;
+
+ class ResetMacroExpansionHelper;
+
+ /// \brief Whether we have already loaded macros from the external source.
+ mutable bool ReadMacrosFromExternalSource : 1;
+
+ /// \brief True if pragmas are enabled.
+ bool PragmasEnabled : 1;
+
+ /// \brief True if the current build action is a preprocessing action.
+ bool PreprocessedOutput : 1;
+
+ /// \brief True if we are currently preprocessing a #if or #elif directive
+ bool ParsingIfOrElifDirective;
+
+ /// \brief True if we are pre-expanding macro arguments.
+ bool InMacroArgPreExpansion;
+
+ /// \brief Mapping/lookup information for all identifiers in
+ /// the program, including program keywords.
+ mutable IdentifierTable Identifiers;
+
+ /// \brief This table contains all the selectors in the program.
+ ///
+ /// Unlike IdentifierTable above, this table *isn't* populated by the
+ /// preprocessor. It is declared/expanded here because its role/lifetime is
+ /// conceptually similar to 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;
+
+ /// \brief Information about builtins.
+ Builtin::Context BuiltinInfo;
+
+ /// \brief Tracks all of the pragmas that the client registered
+ /// with this preprocessor.
+ std::unique_ptr<PragmaNamespace> PragmaHandlers;
+
+ /// \brief Pragma handlers of the original source is stored here during the
+ /// parsing of a model file.
+ std::unique_ptr<PragmaNamespace> PragmaHandlersBackup;
+
+ /// \brief Tracks all of the comment handlers that the client registered
+ /// with this preprocessor.
+ std::vector<CommentHandler *> CommentHandlers;
+
+ /// \brief True if we want to ignore EOF token and continue later on (thus
+ /// avoid tearing the Lexer and etc. down).
+ bool IncrementalProcessing;
+
+ /// The kind of translation unit we are processing.
+ TranslationUnitKind TUKind;
+
+ /// \brief The code-completion handler.
+ CodeCompletionHandler *CodeComplete;
+
+ /// \brief The file that we're performing code-completion for, if any.
+ const FileEntry *CodeCompletionFile;
+
+ /// \brief The offset in file for the code-completion point.
+ unsigned CodeCompletionOffset;
+
+ /// \brief The location for the code-completion point. This gets instantiated
+ /// when the CodeCompletionFile gets \#include'ed for preprocessing.
+ SourceLocation CodeCompletionLoc;
+
+ /// \brief The start location for the file of the code-completion point.
+ ///
+ /// This gets instantiated when the CodeCompletionFile gets \#include'ed
+ /// for preprocessing.
+ SourceLocation CodeCompletionFileLoc;
+
+ /// \brief The source location of the \c import contextual keyword we just
+ /// lexed, if any.
+ SourceLocation ModuleImportLoc;
+
+ /// \brief The module import path that we're currently processing.
+ SmallVector<std::pair<IdentifierInfo *, SourceLocation>, 2> ModuleImportPath;
+
+ /// \brief Whether the last token we lexed was an '@'.
+ bool LastTokenWasAt;
+
+ /// \brief Whether the module import expects an identifier next. Otherwise,
+ /// it expects a '.' or ';'.
+ bool ModuleImportExpectsIdentifier;
+
+ /// \brief The source location of the currently-active
+ /// \#pragma clang arc_cf_code_audited begin.
+ SourceLocation PragmaARCCFCodeAuditedLoc;
+
+ /// \brief The source location of the currently-active
+ /// \#pragma clang assume_nonnull begin.
+ SourceLocation PragmaAssumeNonNullLoc;
+
+ /// \brief True if we hit the code-completion point.
+ bool CodeCompletionReached;
+
+ /// \brief The directory that the main file should be considered to occupy,
+ /// if it does not correspond to a real file (as happens when building a
+ /// module).
+ const DirectoryEntry *MainFileDir;
+
+ /// \brief The number of bytes that we will initially skip when entering the
+ /// main file, along with a flag that indicates whether skipping this number
+ /// of bytes will place the lexer at the start of a line.
+ ///
+ /// This is used when loading a precompiled preamble.
+ std::pair<int, bool> SkipMainFilePreamble;
+
+ /// \brief 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.
+ std::unique_ptr<Lexer> CurLexer;
+
+ /// \brief 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.
+ std::unique_ptr<PTHLexer> CurPTHLexer;
+
+ /// \brief 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;
+
+ /// \brief 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;
+
+ /// \brief The current macro we are expanding, if we are expanding a macro.
+ ///
+ /// One of CurLexer and CurTokenLexer must be null.
+ std::unique_ptr<TokenLexer> CurTokenLexer;
+
+ /// \brief The kind of lexer we're currently working with.
+ enum CurLexerKind {
+ CLK_Lexer,
+ CLK_PTHLexer,
+ CLK_TokenLexer,
+ CLK_CachingLexer,
+ CLK_LexAfterModuleImport
+ } CurLexerKind;
+
+ /// \brief If the current lexer is for a submodule that is being built, this
+ /// is that submodule.
+ Module *CurSubmodule;
+
+ /// \brief Keeps track of the stack of files currently
+ /// \#included, and macros currently being expanded from, not counting
+ /// CurLexer/CurTokenLexer.
+ struct IncludeStackInfo {
+ enum CurLexerKind CurLexerKind;
+ Module *TheSubmodule;
+ std::unique_ptr<Lexer> TheLexer;
+ std::unique_ptr<PTHLexer> ThePTHLexer;
+ PreprocessorLexer *ThePPLexer;
+ std::unique_ptr<TokenLexer> TheTokenLexer;
+ const DirectoryLookup *TheDirLookup;
+
+ // The following constructors are completely useless copies of the default
+ // versions, only needed to pacify MSVC.
+ IncludeStackInfo(enum CurLexerKind CurLexerKind, Module *TheSubmodule,
+ std::unique_ptr<Lexer> &&TheLexer,
+ std::unique_ptr<PTHLexer> &&ThePTHLexer,
+ PreprocessorLexer *ThePPLexer,
+ std::unique_ptr<TokenLexer> &&TheTokenLexer,
+ const DirectoryLookup *TheDirLookup)
+ : CurLexerKind(std::move(CurLexerKind)),
+ TheSubmodule(std::move(TheSubmodule)), TheLexer(std::move(TheLexer)),
+ ThePTHLexer(std::move(ThePTHLexer)),
+ ThePPLexer(std::move(ThePPLexer)),
+ TheTokenLexer(std::move(TheTokenLexer)),
+ TheDirLookup(std::move(TheDirLookup)) {}
+ IncludeStackInfo(IncludeStackInfo &&RHS)
+ : CurLexerKind(std::move(RHS.CurLexerKind)),
+ TheSubmodule(std::move(RHS.TheSubmodule)),
+ TheLexer(std::move(RHS.TheLexer)),
+ ThePTHLexer(std::move(RHS.ThePTHLexer)),
+ ThePPLexer(std::move(RHS.ThePPLexer)),
+ TheTokenLexer(std::move(RHS.TheTokenLexer)),
+ TheDirLookup(std::move(RHS.TheDirLookup)) {}
+ };
+ std::vector<IncludeStackInfo> IncludeMacroStack;
+
+ /// \brief Actions invoked when some preprocessor activity is
+ /// encountered (e.g. a file is \#included, etc).
+ std::unique_ptr<PPCallbacks> Callbacks;
+
+ struct MacroExpandsInfo {
+ Token Tok;
+ MacroDefinition MD;
+ SourceRange Range;
+ MacroExpandsInfo(Token Tok, MacroDefinition MD, SourceRange Range)
+ : Tok(Tok), MD(MD), Range(Range) { }
+ };
+ SmallVector<MacroExpandsInfo, 2> DelayedMacroExpandsCallbacks;
+
+ /// Information about a name that has been used to define a module macro.
+ struct ModuleMacroInfo {
+ ModuleMacroInfo(MacroDirective *MD)
+ : MD(MD), ActiveModuleMacrosGeneration(0), IsAmbiguous(false) {}
+
+ /// The most recent macro directive for this identifier.
+ MacroDirective *MD;
+ /// The active module macros for this identifier.
+ llvm::TinyPtrVector<ModuleMacro*> ActiveModuleMacros;
+ /// The generation number at which we last updated ActiveModuleMacros.
+ /// \see Preprocessor::VisibleModules.
+ unsigned ActiveModuleMacrosGeneration;
+ /// Whether this macro name is ambiguous.
+ bool IsAmbiguous;
+ /// The module macros that are overridden by this macro.
+ llvm::TinyPtrVector<ModuleMacro*> OverriddenMacros;
+ };
+
+ /// The state of a macro for an identifier.
+ class MacroState {
+ mutable llvm::PointerUnion<MacroDirective *, ModuleMacroInfo *> State;
+
+ ModuleMacroInfo *getModuleInfo(Preprocessor &PP,
+ const IdentifierInfo *II) const {
+ // FIXME: Find a spare bit on IdentifierInfo and store a
+ // HasModuleMacros flag.
+ if (!II->hasMacroDefinition() ||
+ (!PP.getLangOpts().Modules &&
+ !PP.getLangOpts().ModulesLocalVisibility) ||
+ !PP.CurSubmoduleState->VisibleModules.getGeneration())
+ return nullptr;
+
+ auto *Info = State.dyn_cast<ModuleMacroInfo*>();
+ if (!Info) {
+ Info = new (PP.getPreprocessorAllocator())
+ ModuleMacroInfo(State.get<MacroDirective *>());
+ State = Info;
+ }
+
+ if (PP.CurSubmoduleState->VisibleModules.getGeneration() !=
+ Info->ActiveModuleMacrosGeneration)
+ PP.updateModuleMacroInfo(II, *Info);
+ return Info;
+ }
+
+ public:
+ MacroState() : MacroState(nullptr) {}
+ MacroState(MacroDirective *MD) : State(MD) {}
+ MacroState(MacroState &&O) LLVM_NOEXCEPT : State(O.State) {
+ O.State = (MacroDirective *)nullptr;
+ }
+ MacroState &operator=(MacroState &&O) LLVM_NOEXCEPT {
+ auto S = O.State;
+ O.State = (MacroDirective *)nullptr;
+ State = S;
+ return *this;
+ }
+ ~MacroState() {
+ if (auto *Info = State.dyn_cast<ModuleMacroInfo*>())
+ Info->~ModuleMacroInfo();
+ }
+
+ MacroDirective *getLatest() const {
+ if (auto *Info = State.dyn_cast<ModuleMacroInfo*>())
+ return Info->MD;
+ return State.get<MacroDirective*>();
+ }
+ void setLatest(MacroDirective *MD) {
+ if (auto *Info = State.dyn_cast<ModuleMacroInfo*>())
+ Info->MD = MD;
+ else
+ State = MD;
+ }
+
+ bool isAmbiguous(Preprocessor &PP, const IdentifierInfo *II) const {
+ auto *Info = getModuleInfo(PP, II);
+ return Info ? Info->IsAmbiguous : false;
+ }
+ ArrayRef<ModuleMacro *>
+ getActiveModuleMacros(Preprocessor &PP, const IdentifierInfo *II) const {
+ if (auto *Info = getModuleInfo(PP, II))
+ return Info->ActiveModuleMacros;
+ return None;
+ }
+
+ MacroDirective::DefInfo findDirectiveAtLoc(SourceLocation Loc,
+ SourceManager &SourceMgr) const {
+ // FIXME: Incorporate module macros into the result of this.
+ if (auto *Latest = getLatest())
+ return Latest->findDirectiveAtLoc(Loc, SourceMgr);
+ return MacroDirective::DefInfo();
+ }
+
+ void overrideActiveModuleMacros(Preprocessor &PP, IdentifierInfo *II) {
+ if (auto *Info = getModuleInfo(PP, II)) {
+ Info->OverriddenMacros.insert(Info->OverriddenMacros.end(),
+ Info->ActiveModuleMacros.begin(),
+ Info->ActiveModuleMacros.end());
+ Info->ActiveModuleMacros.clear();
+ Info->IsAmbiguous = false;
+ }
+ }
+ ArrayRef<ModuleMacro*> getOverriddenMacros() const {
+ if (auto *Info = State.dyn_cast<ModuleMacroInfo*>())
+ return Info->OverriddenMacros;
+ return None;
+ }
+ void setOverriddenMacros(Preprocessor &PP,
+ ArrayRef<ModuleMacro *> Overrides) {
+ auto *Info = State.dyn_cast<ModuleMacroInfo*>();
+ if (!Info) {
+ if (Overrides.empty())
+ return;
+ Info = new (PP.getPreprocessorAllocator())
+ ModuleMacroInfo(State.get<MacroDirective *>());
+ State = Info;
+ }
+ Info->OverriddenMacros.clear();
+ Info->OverriddenMacros.insert(Info->OverriddenMacros.end(),
+ Overrides.begin(), Overrides.end());
+ Info->ActiveModuleMacrosGeneration = 0;
+ }
+ };
+
+ /// For each IdentifierInfo that was associated with a macro, we
+ /// keep a mapping to the history of all macro definitions and #undefs in
+ /// the reverse order (the latest one is in the head of the list).
+ ///
+ /// This mapping lives within the \p CurSubmoduleState.
+ typedef llvm::DenseMap<const IdentifierInfo *, MacroState> MacroMap;
+
+ friend class ASTReader;
+
+ struct SubmoduleState;
+
+ /// \brief Information about a submodule that we're currently building.
+ struct BuildingSubmoduleInfo {
+ BuildingSubmoduleInfo(Module *M, SourceLocation ImportLoc,
+ SubmoduleState *OuterSubmoduleState)
+ : M(M), ImportLoc(ImportLoc), OuterSubmoduleState(OuterSubmoduleState) {
+ }
+
+ /// The module that we are building.
+ Module *M;
+ /// The location at which the module was included.
+ SourceLocation ImportLoc;
+ /// The previous SubmoduleState.
+ SubmoduleState *OuterSubmoduleState;
+ };
+ SmallVector<BuildingSubmoduleInfo, 8> BuildingSubmoduleStack;
+
+ /// \brief Information about a submodule's preprocessor state.
+ struct SubmoduleState {
+ /// The macros for the submodule.
+ MacroMap Macros;
+ /// The set of modules that are visible within the submodule.
+ VisibleModuleSet VisibleModules;
+ // FIXME: CounterValue?
+ // FIXME: PragmaPushMacroInfo?
+ };
+ std::map<Module*, SubmoduleState> Submodules;
+
+ /// The preprocessor state for preprocessing outside of any submodule.
+ SubmoduleState NullSubmoduleState;
+
+ /// The current submodule state. Will be \p NullSubmoduleState if we're not
+ /// in a submodule.
+ SubmoduleState *CurSubmoduleState;
+
+ /// The set of known macros exported from modules.
+ llvm::FoldingSet<ModuleMacro> ModuleMacros;
+
+ /// The list of module macros, for each identifier, that are not overridden by
+ /// any other module macro.
+ llvm::DenseMap<const IdentifierInfo *, llvm::TinyPtrVector<ModuleMacro*>>
+ LeafModuleMacros;
+
+ /// \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 of
+ /// 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;
+
+ /// \brief A "freelist" of MacroArg objects that can be
+ /// reused for quick allocation.
+ MacroArgs *MacroArgCache;
+ friend class MacroArgs;
+
+ /// For each IdentifierInfo used in a \#pragma push_macro directive,
+ /// we keep a MacroInfo stack used to restore the previous macro value.
+ llvm::DenseMap<IdentifierInfo*, std::vector<MacroInfo*> > PragmaPushMacroInfo;
+
+ // Various statistics we track for performance analysis.
+ unsigned NumDirectives, NumDefined, NumUndefined, NumPragma;
+ unsigned NumIf, NumElse, NumEndif;
+ unsigned NumEnteredSourceFiles, MaxIncludeStackDepth;
+ unsigned NumMacroExpanded, NumFnMacroExpanded, NumBuiltinMacroExpanded;
+ unsigned NumFastMacroExpanded, NumTokenPaste, NumFastTokenPaste;
+ unsigned NumSkipped;
+
+ /// \brief The predefined macros that preprocessor should use from the
+ /// command line etc.
+ std::string Predefines;
+
+ /// \brief The file ID for the preprocessor predefines.
+ FileID PredefinesFileID;
+
+ /// \{
+ /// \brief Cache of macro expanders to reduce malloc traffic.
+ enum { TokenLexerCacheSize = 8 };
+ unsigned NumCachedTokenLexers;
+ std::unique_ptr<TokenLexer> TokenLexerCache[TokenLexerCacheSize];
+ /// \}
+
+ /// \brief Keeps macro expanded tokens for TokenLexers.
+ //
+ /// Works like a stack; a TokenLexer adds the macro expanded tokens that is
+ /// going to lex in the cache and when it finishes the tokens are removed
+ /// from the end of the cache.
+ SmallVector<Token, 16> MacroExpandedTokens;
+ std::vector<std::pair<TokenLexer *, size_t> > MacroExpandingLexersStack;
+
+ /// \brief A record of the macro definitions and expansions that
+ /// occurred during preprocessing.
+ ///
+ /// This is an optional side structure that can be enabled with
+ /// \c createPreprocessingRecord() prior to preprocessing.
+ PreprocessingRecord *Record;
+
+ /// Cached tokens state.
+ typedef SmallVector<Token, 1> CachedTokensTy;
+
+ /// \brief Cached tokens are stored here when we do backtracking or
+ /// lookahead. They are "lexed" by the CachingLex() method.
+ CachedTokensTy CachedTokens;
+
+ /// \brief 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;
+
+ /// \brief 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;
+ };
+
+ /// MacroInfos are managed as a chain for easy disposal. This is the head
+ /// of that list.
+ MacroInfoChain *MIChainHead;
+
+ struct DeserializedMacroInfoChain {
+ MacroInfo MI;
+ unsigned OwningModuleID; // MUST be immediately after the MacroInfo object
+ // so it can be accessed by MacroInfo::getOwningModuleID().
+ DeserializedMacroInfoChain *Next;
+ };
+ DeserializedMacroInfoChain *DeserialMIChainHead;
+
+public:
+ Preprocessor(IntrusiveRefCntPtr<PreprocessorOptions> PPOpts,
+ DiagnosticsEngine &diags, LangOptions &opts,
+ SourceManager &SM, HeaderSearch &Headers,
+ ModuleLoader &TheModuleLoader,
+ IdentifierInfoLookup *IILookup = nullptr,
+ bool OwnsHeaderSearch = false,
+ TranslationUnitKind TUKind = TU_Complete);
+
+ ~Preprocessor();
+
+ /// \brief Initialize the preprocessor using information about the target.
+ ///
+ /// \param Target is owned by the caller and must remain valid for the
+ /// lifetime of the preprocessor.
+ /// \param AuxTarget is owned by the caller and must remain valid for
+ /// the lifetime of the preprocessor.
+ void Initialize(const TargetInfo &Target,
+ const TargetInfo *AuxTarget = nullptr);
+
+ /// \brief Initialize the preprocessor to parse a model file
+ ///
+ /// To parse model files the preprocessor of the original source is reused to
+ /// preserver the identifier table. However to avoid some duplicate
+ /// information in the preprocessor some cleanup is needed before it is used
+ /// to parse model files. This method does that cleanup.
+ void InitializeForModelFile();
+
+ /// \brief Cleanup after model file parsing
+ void FinalizeForModelFile();
+
+ /// \brief Retrieve the preprocessor options used to initialize this
+ /// preprocessor.
+ PreprocessorOptions &getPreprocessorOpts() const { return *PPOpts; }
+
+ DiagnosticsEngine &getDiagnostics() const { return *Diags; }
+ void setDiagnostics(DiagnosticsEngine &D) { Diags = &D; }
+
+ const LangOptions &getLangOpts() const { return LangOpts; }
+ const TargetInfo &getTargetInfo() const { return *Target; }
+ const TargetInfo *getAuxTargetInfo() const { return AuxTarget; }
+ FileManager &getFileManager() const { return FileMgr; }
+ SourceManager &getSourceManager() const { return SourceMgr; }
+ HeaderSearch &getHeaderSearchInfo() const { return HeaderInfo; }
+
+ IdentifierTable &getIdentifierTable() { return Identifiers; }
+ const IdentifierTable &getIdentifierTable() const { 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;
+ }
+
+ /// \brief Retrieve the module loader associated with this preprocessor.
+ ModuleLoader &getModuleLoader() const { return TheModuleLoader; }
+
+ bool hadModuleLoaderFatalFailure() const {
+ return TheModuleLoader.HadFatalFailure;
+ }
+
+ /// \brief True if we are currently preprocessing a #if or #elif directive
+ bool isParsingIfOrElifDirective() const {
+ return ParsingIfOrElifDirective;
+ }
+
+ /// \brief Control whether the preprocessor retains comments in output.
+ void SetCommentRetentionState(bool KeepComments, bool KeepMacroComments) {
+ this->KeepComments = KeepComments | KeepMacroComments;
+ this->KeepMacroComments = KeepMacroComments;
+ }
+
+ bool getCommentRetentionState() const { return KeepComments; }
+
+ void setPragmasEnabled(bool Enabled) { PragmasEnabled = Enabled; }
+ bool getPragmasEnabled() const { return PragmasEnabled; }
+
+ void SetSuppressIncludeNotFoundError(bool Suppress) {
+ SuppressIncludeNotFoundError = Suppress;
+ }
+
+ bool GetSuppressIncludeNotFoundError() {
+ return SuppressIncludeNotFoundError;
+ }
+
+ /// Sets whether the preprocessor is responsible for producing output or if
+ /// it is producing tokens to be consumed by Parse and Sema.
+ void setPreprocessedOutput(bool IsPreprocessedOutput) {
+ PreprocessedOutput = IsPreprocessedOutput;
+ }
+
+ /// Returns true if the preprocessor is responsible for generating output,
+ /// false if it is producing tokens to be consumed by Parse and Sema.
+ bool isPreprocessedOutput() const { return PreprocessedOutput; }
+
+ /// \brief Return true if we are lexing directly from the specified lexer.
+ bool isCurrentLexer(const PreprocessorLexer *L) const {
+ return CurPPLexer == L;
+ }
+
+ /// \brief 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; }
+
+ /// \brief 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;
+
+ /// \brief Return the submodule owning the file being lexed.
+ Module *getCurrentSubmodule() const { return CurSubmodule; }
+
+ /// \brief Returns the FileID for the preprocessor predefines.
+ FileID getPredefinesFileID() const { return PredefinesFileID; }
+
+ /// \{
+ /// \brief Accessors for preprocessor callbacks.
+ ///
+ /// Note that this class takes ownership of any PPCallbacks object given to
+ /// it.
+ PPCallbacks *getPPCallbacks() const { return Callbacks.get(); }
+ void addPPCallbacks(std::unique_ptr<PPCallbacks> C) {
+ if (Callbacks)
+ C = llvm::make_unique<PPChainedCallbacks>(std::move(C),
+ std::move(Callbacks));
+ Callbacks = std::move(C);
+ }
+ /// \}
+
+ bool isMacroDefined(StringRef Id) {
+ return isMacroDefined(&Identifiers.get(Id));
+ }
+ bool isMacroDefined(const IdentifierInfo *II) {
+ return II->hasMacroDefinition() &&
+ (!getLangOpts().Modules || (bool)getMacroDefinition(II));
+ }
+
+ /// \brief Determine whether II is defined as a macro within the module M,
+ /// if that is a module that we've already preprocessed. Does not check for
+ /// macros imported into M.
+ bool isMacroDefinedInLocalModule(const IdentifierInfo *II, Module *M) {
+ if (!II->hasMacroDefinition())
+ return false;
+ auto I = Submodules.find(M);
+ if (I == Submodules.end())
+ return false;
+ auto J = I->second.Macros.find(II);
+ if (J == I->second.Macros.end())
+ return false;
+ auto *MD = J->second.getLatest();
+ return MD && MD->isDefined();
+ }
+
+ MacroDefinition getMacroDefinition(const IdentifierInfo *II) {
+ if (!II->hasMacroDefinition())
+ return MacroDefinition();
+
+ MacroState &S = CurSubmoduleState->Macros[II];
+ auto *MD = S.getLatest();
+ while (MD && isa<VisibilityMacroDirective>(MD))
+ MD = MD->getPrevious();
+ return MacroDefinition(dyn_cast_or_null<DefMacroDirective>(MD),
+ S.getActiveModuleMacros(*this, II),
+ S.isAmbiguous(*this, II));
+ }
+
+ MacroDefinition getMacroDefinitionAtLoc(const IdentifierInfo *II,
+ SourceLocation Loc) {
+ if (!II->hadMacroDefinition())
+ return MacroDefinition();
+
+ MacroState &S = CurSubmoduleState->Macros[II];
+ MacroDirective::DefInfo DI;
+ if (auto *MD = S.getLatest())
+ DI = MD->findDirectiveAtLoc(Loc, getSourceManager());
+ // FIXME: Compute the set of active module macros at the specified location.
+ return MacroDefinition(DI.getDirective(),
+ S.getActiveModuleMacros(*this, II),
+ S.isAmbiguous(*this, II));
+ }
+
+ /// \brief Given an identifier, return its latest non-imported MacroDirective
+ /// if it is \#define'd and not \#undef'd, or null if it isn't \#define'd.
+ MacroDirective *getLocalMacroDirective(const IdentifierInfo *II) const {
+ if (!II->hasMacroDefinition())
+ return nullptr;
+
+ auto *MD = getLocalMacroDirectiveHistory(II);
+ if (!MD || MD->getDefinition().isUndefined())
+ return nullptr;
+
+ return MD;
+ }
+
+ const MacroInfo *getMacroInfo(const IdentifierInfo *II) const {
+ return const_cast<Preprocessor*>(this)->getMacroInfo(II);
+ }
+
+ MacroInfo *getMacroInfo(const IdentifierInfo *II) {
+ if (!II->hasMacroDefinition())
+ return nullptr;
+ if (auto MD = getMacroDefinition(II))
+ return MD.getMacroInfo();
+ return nullptr;
+ }
+
+ /// \brief Given an identifier, return the latest non-imported macro
+ /// directive for that identifier.
+ ///
+ /// One can iterate over all previous macro directives from the most recent
+ /// one.
+ MacroDirective *getLocalMacroDirectiveHistory(const IdentifierInfo *II) const;
+
+ /// \brief Add a directive to the macro directive history for this identifier.
+ void appendMacroDirective(IdentifierInfo *II, MacroDirective *MD);
+ DefMacroDirective *appendDefMacroDirective(IdentifierInfo *II, MacroInfo *MI,
+ SourceLocation Loc) {
+ DefMacroDirective *MD = AllocateDefMacroDirective(MI, Loc);
+ appendMacroDirective(II, MD);
+ return MD;
+ }
+ DefMacroDirective *appendDefMacroDirective(IdentifierInfo *II,
+ MacroInfo *MI) {
+ return appendDefMacroDirective(II, MI, MI->getDefinitionLoc());
+ }
+ /// \brief Set a MacroDirective that was loaded from a PCH file.
+ void setLoadedMacroDirective(IdentifierInfo *II, MacroDirective *MD);
+
+ /// \brief Register an exported macro for a module and identifier.
+ ModuleMacro *addModuleMacro(Module *Mod, IdentifierInfo *II, MacroInfo *Macro,
+ ArrayRef<ModuleMacro *> Overrides, bool &IsNew);
+ ModuleMacro *getModuleMacro(Module *Mod, IdentifierInfo *II);
+
+ /// \brief Get the list of leaf (non-overridden) module macros for a name.
+ ArrayRef<ModuleMacro*> getLeafModuleMacros(const IdentifierInfo *II) const {
+ auto I = LeafModuleMacros.find(II);
+ if (I != LeafModuleMacros.end())
+ return I->second;
+ return None;
+ }
+
+ /// \{
+ /// Iterators for the macro history table. Currently defined macros have
+ /// IdentifierInfo::hasMacroDefinition() set and an empty
+ /// MacroInfo::getUndefLoc() at the head of the list.
+ typedef MacroMap::const_iterator macro_iterator;
+ macro_iterator macro_begin(bool IncludeExternalMacros = true) const;
+ macro_iterator macro_end(bool IncludeExternalMacros = true) const;
+ llvm::iterator_range<macro_iterator>
+ macros(bool IncludeExternalMacros = true) const {
+ return llvm::make_range(macro_begin(IncludeExternalMacros),
+ macro_end(IncludeExternalMacros));
+ }
+ /// \}
+
+ /// \brief Return the name of the macro defined before \p Loc that has
+ /// spelling \p Tokens. If there are multiple macros with same spelling,
+ /// return the last one defined.
+ StringRef getLastMacroWithSpelling(SourceLocation Loc,
+ ArrayRef<TokenValue> Tokens) const;
+
+ const std::string &getPredefines() const { return Predefines; }
+ /// \brief 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(StringRef P) { Predefines = P; }
+
+ /// Return information about the specified preprocessor
+ /// identifier token.
+ IdentifierInfo *getIdentifierInfo(StringRef Name) const {
+ return &Identifiers.get(Name);
+ }
+
+ /// \brief Add the specified pragma handler to this preprocessor.
+ ///
+ /// If \p 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(StringRef Namespace, PragmaHandler *Handler);
+ void AddPragmaHandler(PragmaHandler *Handler) {
+ AddPragmaHandler(StringRef(), Handler);
+ }
+
+ /// \brief Remove the specific pragma handler from this preprocessor.
+ ///
+ /// If \p Namespace is non-null, then it should be the namespace that
+ /// \p Handler was added to. It is an error to remove a handler that
+ /// has not been registered.
+ void RemovePragmaHandler(StringRef Namespace, PragmaHandler *Handler);
+ void RemovePragmaHandler(PragmaHandler *Handler) {
+ RemovePragmaHandler(StringRef(), Handler);
+ }
+
+ /// Install empty handlers for all pragmas (making them ignored).
+ void IgnorePragmas();
+
+ /// \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 = nullptr;
+ }
+
+ /// \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();
+
+ /// \brief Enter the specified FileID as the main source file,
+ /// which implicitly adds the builtin defines etc.
+ void EnterMainSourceFile();
+
+ /// \brief Inform the preprocessor callbacks that processing is complete.
+ void EndSourceFile();
+
+ /// \brief Add a source file to the top of the include stack and
+ /// start lexing tokens from it instead of the current buffer.
+ ///
+ /// Emits a diagnostic, doesn't enter the file, and returns true on error.
+ bool EnterSourceFile(FileID CurFileID, const DirectoryLookup *Dir,
+ SourceLocation Loc);
+
+ /// \brief Add a Macro to the top of the include stack and start lexing
+ /// tokens from it instead of the current buffer.
+ ///
+ /// \param Args specifies the tokens input to a function-like macro.
+ /// \param 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, MacroInfo *Macro,
+ MacroArgs *Args);
+
+ /// \brief Add a "macro" context to the top of the include stack,
+ /// which will cause the lexer to start returning the specified tokens.
+ ///
+ /// If \p 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 \p 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
+ /// \c new[] and must be freed.
+ void EnterTokenStream(const Token *Toks, unsigned NumToks,
+ bool DisableMacroExpansion, bool OwnsTokens);
+
+ /// \brief 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();
+
+ /// 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();
+
+ /// \brief Disable the last EnableBacktrackAtThisPos call.
+ void CommitBacktrackedTokens();
+
+ /// \brief Make Preprocessor re-lex the tokens that were lexed since
+ /// EnableBacktrackAtThisPos() was previously called.
+ void Backtrack();
+
+ /// \brief True if EnableBacktrackAtThisPos() was called and
+ /// caching of tokens is on.
+ bool isBacktrackEnabled() const { return !BacktrackPositions.empty(); }
+
+ /// \brief Lex the next token for this preprocessor.
+ void Lex(Token &Result);
+
+ void LexAfterModuleImport(Token &Result);
+
+ void makeModuleVisible(Module *M, SourceLocation Loc);
+
+ SourceLocation getModuleImportLoc(Module *M) const {
+ return CurSubmoduleState->VisibleModules.getImportLoc(M);
+ }
+
+ /// \brief Lex a string literal, which may be the concatenation of multiple
+ /// string literals and may even come from macro expansion.
+ /// \returns true on success, false if a error diagnostic has been generated.
+ bool LexStringLiteral(Token &Result, std::string &String,
+ const char *DiagnosticTag, bool AllowMacroExpansion) {
+ if (AllowMacroExpansion)
+ Lex(Result);
+ else
+ LexUnexpandedToken(Result);
+ return FinishLexStringLiteral(Result, String, DiagnosticTag,
+ AllowMacroExpansion);
+ }
+
+ /// \brief Complete the lexing of a string literal where the first token has
+ /// already been lexed (see LexStringLiteral).
+ bool FinishLexStringLiteral(Token &Result, std::string &String,
+ const char *DiagnosticTag,
+ bool AllowMacroExpansion);
+
+ /// \brief 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);
+ }
+
+ /// \brief Just like Lex, but 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;
+ }
+
+ /// \brief Like LexNonComment, but this disables macro expansion of
+ /// identifier tokens.
+ void LexUnexpandedNonComment(Token &Result) {
+ do
+ LexUnexpandedToken(Result);
+ while (Result.getKind() == tok::comment);
+ }
+
+ /// \brief Parses a simple integer literal to get its numeric value. Floating
+ /// point literals and user defined literals are rejected. Used primarily to
+ /// handle pragmas that accept integer arguments.
+ bool parseSimpleIntegerLiteral(Token &Tok, uint64_t &Value);
+
+ /// Disables macro expansion everywhere except for preprocessor directives.
+ void SetMacroExpansionOnlyInDirectives() {
+ DisableMacroExpansion = true;
+ MacroExpansionInDirectivesOverride = true;
+ }
+
+ /// \brief 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);
+ }
+
+ /// \brief 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;
+ }
+
+ /// \brief 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);
+ }
+
+ /// 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);
+ }
+
+ /// Get the location of the last cached token, suitable for setting the end
+ /// location of an annotation token.
+ SourceLocation getLastCachedTokenLocation() const {
+ assert(CachedLexPos != 0);
+ return CachedTokens[CachedLexPos-1].getLastLoc();
+ }
+
+ /// \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;
+ }
+
+ /// Update the current token to represent the provided
+ /// identifier, in order to cache an action performed by typo correction.
+ void TypoCorrectToken(const Token &Tok) {
+ assert(Tok.getIdentifierInfo() && "Expected identifier token");
+ if (CachedLexPos != 0 && isBacktrackEnabled())
+ CachedTokens[CachedLexPos-1] = Tok;
+ }
+
+ /// \brief Recompute the current lexer kind based on the CurLexer/CurPTHLexer/
+ /// CurTokenLexer pointers.
+ void recomputeCurLexerKind();
+
+ /// \brief Returns true if incremental processing is enabled
+ bool isIncrementalProcessingEnabled() const { return IncrementalProcessing; }
+
+ /// \brief Enables the incremental processing
+ void enableIncrementalProcessing(bool value = true) {
+ IncrementalProcessing = value;
+ }
+
+ /// \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 we are performing code completion.
+ bool isCodeCompletionEnabled() const { return CodeCompletionFile != nullptr; }
+
+ /// \brief Returns the location of the code-completion point.
+ ///
+ /// Returns an invalid location if code-completion is not enabled or the file
+ /// containing the code-completion point has not been lexed yet.
+ SourceLocation getCodeCompletionLoc() const { return CodeCompletionLoc; }
+
+ /// \brief Returns the start location of the file of code-completion point.
+ ///
+ /// Returns an invalid location if code-completion is not enabled or the file
+ /// containing the code-completion point has not been lexed yet.
+ SourceLocation getCodeCompletionFileLoc() const {
+ return CodeCompletionFileLoc;
+ }
+
+ /// \brief Returns true if code-completion is enabled and we have hit the
+ /// code-completion point.
+ bool isCodeCompletionReached() const { return CodeCompletionReached; }
+
+ /// \brief Note that we hit the code-completion point.
+ void setCodeCompletionReached() {
+ assert(isCodeCompletionEnabled() && "Code-completion not enabled!");
+ CodeCompletionReached = true;
+ // Silence any diagnostics that occur after we hit the code-completion.
+ getDiagnostics().setSuppressAllDiagnostics(true);
+ }
+
+ /// \brief The location of the currently-active \#pragma clang
+ /// arc_cf_code_audited begin.
+ ///
+ /// Returns an invalid location if there is no such pragma active.
+ SourceLocation getPragmaARCCFCodeAuditedLoc() const {
+ return PragmaARCCFCodeAuditedLoc;
+ }
+
+ /// \brief Set the location of the currently-active \#pragma clang
+ /// arc_cf_code_audited begin. An invalid location ends the pragma.
+ void setPragmaARCCFCodeAuditedLoc(SourceLocation Loc) {
+ PragmaARCCFCodeAuditedLoc = Loc;
+ }
+
+ /// \brief The location of the currently-active \#pragma clang
+ /// assume_nonnull begin.
+ ///
+ /// Returns an invalid location if there is no such pragma active.
+ SourceLocation getPragmaAssumeNonNullLoc() const {
+ return PragmaAssumeNonNullLoc;
+ }
+
+ /// \brief Set the location of the currently-active \#pragma clang
+ /// assume_nonnull begin. An invalid location ends the pragma.
+ void setPragmaAssumeNonNullLoc(SourceLocation Loc) {
+ PragmaAssumeNonNullLoc = Loc;
+ }
+
+ /// \brief Set the directory in which the main file should be considered
+ /// to have been found, if it is not a real file.
+ void setMainFileDir(const DirectoryEntry *Dir) {
+ MainFileDir = Dir;
+ }
+
+ /// \brief Instruct the preprocessor to skip part of the main source file.
+ ///
+ /// \param Bytes The number of bytes in the preamble to skip.
+ ///
+ /// \param 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;
+ }
+
+ /// 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) const {
+ return Diags->Report(Loc, DiagID);
+ }
+
+ DiagnosticBuilder Diag(const Token &Tok, unsigned DiagID) const {
+ return Diags->Report(Tok.getLocation(), DiagID);
+ }
+
+ /// Return the 'spelling' of the token at the given
+ /// location; does not go up to the spelling location or down to the
+ /// expansion location.
+ ///
+ /// \param buffer A buffer which will be used only if the token requires
+ /// "cleaning", e.g. if it contains trigraphs or escaped newlines
+ /// \param invalid If non-null, will be set \c true if an error occurs.
+ StringRef getSpelling(SourceLocation loc,
+ SmallVectorImpl<char> &buffer,
+ bool *invalid = nullptr) const {
+ return Lexer::getSpelling(loc, buffer, SourceMgr, LangOpts, invalid);
+ }
+
+ /// \brief 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 = nullptr) const {
+ return Lexer::getSpelling(Tok, SourceMgr, LangOpts, Invalid);
+ }
+
+ /// \brief 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 = nullptr) const {
+ return Lexer::getSpelling(Tok, Buffer, SourceMgr, LangOpts, Invalid);
+ }
+
+ /// \brief 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.
+ StringRef getSpelling(const Token &Tok,
+ SmallVectorImpl<char> &Buffer,
+ bool *Invalid = nullptr) const;
+
+ /// \brief Relex the token at the specified location.
+ /// \returns true if there was a failure, false on success.
+ bool getRawToken(SourceLocation Loc, Token &Result,
+ bool IgnoreWhiteSpace = false) {
+ return Lexer::getRawToken(Loc, Result, SourceMgr, LangOpts, IgnoreWhiteSpace);
+ }
+
+ /// \brief Given a Token \p Tok that is a numeric constant with length 1,
+ /// return the character.
+ char
+ getSpellingOfSingleCharacterNumericConstant(const Token &Tok,
+ bool *Invalid = nullptr) 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);
+ }
+
+ /// \brief Retrieve the name of the immediate macro expansion.
+ ///
+ /// This routine starts from a source location, and finds the name of the
+ /// macro responsible for its immediate expansion. It looks through any
+ /// intervening macro argument expansions to compute this. It returns a
+ /// StringRef that refers to the SourceManager-owned buffer of the source
+ /// where that macro name is spelled. Thus, the result shouldn't out-live
+ /// the SourceManager.
+ StringRef getImmediateMacroName(SourceLocation Loc) {
+ return Lexer::getImmediateMacroName(Loc, SourceMgr, getLangOpts());
+ }
+
+ /// \brief 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 expansion
+ /// point of the token.
+ void CreateString(StringRef Str, Token &Tok,
+ SourceLocation ExpansionLocStart = SourceLocation(),
+ SourceLocation ExpansionLocEnd = 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, LangOpts);
+ }
+
+ /// \brief Returns true if the given MacroID location points at the first
+ /// token of the macro expansion.
+ ///
+ /// \param MacroBegin If non-null and function returns true, it is set to
+ /// begin location of the macro.
+ bool isAtStartOfMacroExpansion(SourceLocation loc,
+ SourceLocation *MacroBegin = nullptr) const {
+ return Lexer::isAtStartOfMacroExpansion(loc, SourceMgr, LangOpts,
+ MacroBegin);
+ }
+
+ /// \brief Returns true if the given MacroID location points at the last
+ /// token of the macro expansion.
+ ///
+ /// \param MacroEnd If non-null and function returns true, it is set to
+ /// end location of the macro.
+ bool isAtEndOfMacroExpansion(SourceLocation loc,
+ SourceLocation *MacroEnd = nullptr) const {
+ return Lexer::isAtEndOfMacroExpansion(loc, SourceMgr, LangOpts, MacroEnd);
+ }
+
+ /// \brief 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;
+ void dumpMacroInfo(const IdentifierInfo *II);
+
+ /// \brief 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, LangOpts);
+ }
+
+ /// \brief 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();
+
+ size_t getTotalMemory() const;
+
+ /// 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.
+
+ /// 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;
+
+private:
+ llvm::DenseMap<IdentifierInfo*,unsigned> PoisonReasons;
+
+public:
+
+ /// \brief Specifies the reason for poisoning an identifier.
+ ///
+ /// If that identifier is accessed while poisoned, then this reason will be
+ /// used instead of the default "poisoned" diagnostic.
+ void SetPoisonReason(IdentifierInfo *II, unsigned DiagID);
+
+ /// \brief Display reason for poisoned identifier.
+ void HandlePoisonedIdentifier(Token & Tok);
+
+ void MaybeHandlePoisonedIdentifier(Token & Identifier) {
+ if(IdentifierInfo * II = Identifier.getIdentifierInfo()) {
+ if(II->isPoisoned()) {
+ HandlePoisonedIdentifier(Identifier);
+ }
+ }
+ }
+
+private:
+ /// Identifiers used for SEH handling in Borland. These are only
+ /// allowed in particular circumstances
+ // __except block
+ IdentifierInfo *Ident__exception_code,
+ *Ident___exception_code,
+ *Ident_GetExceptionCode;
+ // __except filter expression
+ IdentifierInfo *Ident__exception_info,
+ *Ident___exception_info,
+ *Ident_GetExceptionInfo;
+ // __finally
+ IdentifierInfo *Ident__abnormal_termination,
+ *Ident___abnormal_termination,
+ *Ident_AbnormalTermination;
+
+ const char *getCurLexerEndPos();
+
+public:
+ void PoisonSEHIdentifiers(bool Poison = true); // Borland
+
+ /// \brief Callback 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').
+ ///
+ /// \returns true if we actually computed a token, false if we need to
+ /// lex again.
+ bool HandleIdentifier(Token &Identifier);
+
+
+ /// \brief Callback 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);
+
+ /// \brief Callback invoked when the current TokenLexer hits the end of its
+ /// token stream.
+ bool HandleEndOfTokenLexer(Token &Result);
+
+ /// \brief Callback 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);
+
+ /// \brief Ensure that the next token is a tok::eod token.
+ ///
+ /// If not, emit a diagnostic and consume up until the eod.
+ /// If \p EnableMacros is true, then we consider macros that expand to zero
+ /// tokens as being ok.
+ void CheckEndOfDirective(const char *Directive, bool EnableMacros = false);
+
+ /// \brief Read and discard all tokens remaining on the current line until
+ /// the tok::eod token is found.
+ void DiscardUntilEndOfDirective();
+
+ /// \brief 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; }
+
+ /// \brief Retrieves the module that we're currently building, if any.
+ Module *getCurrentModule();
+
+ /// \brief Allocate a new MacroInfo object with the provided SourceLocation.
+ MacroInfo *AllocateMacroInfo(SourceLocation L);
+
+ /// \brief Allocate a new MacroInfo object loaded from an AST file.
+ MacroInfo *AllocateDeserializedMacroInfo(SourceLocation L,
+ unsigned SubModuleID);
+
+ /// \brief Turn the specified lexer token into a fully checked and spelled
+ /// filename, e.g. as an operand of \#include.
+ ///
+ /// 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.
+ ///
+ /// \returns true if the input filename was in <>'s or false if it was
+ /// in ""'s.
+ bool GetIncludeFilenameSpelling(SourceLocation Loc,StringRef &Filename);
+
+ /// \brief Given a "foo" or \<foo> reference, look up the indicated file.
+ ///
+ /// Returns null on failure. \p isAngled indicates whether the file
+ /// reference is for system \#include's or not (i.e. using <> instead of "").
+ const FileEntry *LookupFile(SourceLocation FilenameLoc, StringRef Filename,
+ bool isAngled, const DirectoryLookup *FromDir,
+ const FileEntry *FromFile,
+ const DirectoryLookup *&CurDir,
+ SmallVectorImpl<char> *SearchPath,
+ SmallVectorImpl<char> *RelativePath,
+ ModuleMap::KnownHeader *SuggestedModule,
+ bool SkipCache = false);
+
+ /// \brief Get 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; }
+
+ /// \brief Return true if we're in the top-level file, not in a \#include.
+ bool isInPrimaryFile() const;
+
+ /// \brief 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:
+ /// \code
+ /// \#define FOO <x/y.h>
+ /// \#include FOO
+ /// \endcode
+ /// because in this case, "<x/y.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 EOD marker.
+ bool ConcatenateIncludeName(SmallString<128> &FilenameBuffer,
+ SourceLocation &End);
+
+ /// \brief Lex an on-off-switch (C99 6.10.6p2) and verify that it is
+ /// followed by EOD. Return true if the token is not a valid on-off-switch.
+ bool LexOnOffSwitch(tok::OnOffSwitch &OOS);
+
+ bool CheckMacroName(Token &MacroNameTok, MacroUse isDefineUndef,
+ bool *ShadowFlag = nullptr);
+
+private:
+
+ void PushIncludeMacroStack() {
+ assert(CurLexerKind != CLK_CachingLexer && "cannot push a caching lexer");
+ IncludeMacroStack.emplace_back(
+ CurLexerKind, CurSubmodule, std::move(CurLexer), std::move(CurPTHLexer),
+ CurPPLexer, std::move(CurTokenLexer), CurDirLookup);
+ CurPPLexer = nullptr;
+ }
+
+ void PopIncludeMacroStack() {
+ CurLexer = std::move(IncludeMacroStack.back().TheLexer);
+ CurPTHLexer = std::move(IncludeMacroStack.back().ThePTHLexer);
+ CurPPLexer = IncludeMacroStack.back().ThePPLexer;
+ CurTokenLexer = std::move(IncludeMacroStack.back().TheTokenLexer);
+ CurDirLookup = IncludeMacroStack.back().TheDirLookup;
+ CurSubmodule = IncludeMacroStack.back().TheSubmodule;
+ CurLexerKind = IncludeMacroStack.back().CurLexerKind;
+ IncludeMacroStack.pop_back();
+ }
+
+ void PropagateLineStartLeadingSpaceInfo(Token &Result);
+
+ void EnterSubmodule(Module *M, SourceLocation ImportLoc);
+ void LeaveSubmodule();
+
+ /// Update the set of active module macros and ambiguity flag for a module
+ /// macro name.
+ void updateModuleMacroInfo(const IdentifierInfo *II, ModuleMacroInfo &Info);
+
+ /// \brief Allocate a new MacroInfo object.
+ MacroInfo *AllocateMacroInfo();
+
+ DefMacroDirective *AllocateDefMacroDirective(MacroInfo *MI,
+ SourceLocation Loc);
+ UndefMacroDirective *AllocateUndefMacroDirective(SourceLocation UndefLoc);
+ VisibilityMacroDirective *AllocateVisibilityMacroDirective(SourceLocation Loc,
+ bool isPublic);
+
+ /// \brief Lex and validate a macro name, which occurs after a
+ /// \#define or \#undef.
+ ///
+ /// \param MacroNameTok Token that represents the name defined or undefined.
+ /// \param IsDefineUndef Kind if preprocessor directive.
+ /// \param ShadowFlag Points to flag that is set if macro name shadows
+ /// a keyword.
+ ///
+ /// This emits a diagnostic, sets the token kind to eod,
+ /// and discards the rest of the macro line if the macro name is invalid.
+ void ReadMacroName(Token &MacroNameTok, MacroUse IsDefineUndef = MU_Other,
+ bool *ShadowFlag = nullptr);
+
+ /// The ( starting an argument list of a macro definition has just been read.
+ /// Lex the rest of the arguments and the closing ), updating \p MI with
+ /// what we learn and saving in \p LastTok the last token read.
+ /// Return true if an error occurs parsing the arg list.
+ bool ReadMacroDefinitionArgList(MacroInfo *MI, Token& LastTok);
+
+ /// 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 \p
+ /// FoundNonSkipPortion is true, then we have already emitted code for part of
+ /// this \#if directive, so \#else/\#elif blocks should never be entered. If
+ /// \p 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,
+ SourceLocation ElseLoc = SourceLocation());
+
+ /// \brief A fast PTH version of SkipExcludedConditionalBlock.
+ void PTHSkipExcludedConditionalBlock();
+
+ /// \brief 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);
+
+ /// \brief Install the standard preprocessor pragmas:
+ /// \#pragma GCC poison/system_header/dependency and \#pragma once.
+ void RegisterBuiltinPragmas();
+
+ /// \brief Register builtin macros such as __LINE__ with the identifier table.
+ void RegisterBuiltinMacros();
+
+ /// If an identifier token is read that is to be expanded as a macro, handle
+ /// it and return the next token as 'Tok'. If we lexed a token, return true;
+ /// otherwise the caller should lex again.
+ bool HandleMacroExpandedIdentifier(Token &Tok, const MacroDefinition &MD);
+
+ /// \brief Cache macro expanded tokens for TokenLexers.
+ //
+ /// Works like a stack; a TokenLexer adds the macro expanded tokens that is
+ /// going to lex in the cache and when it finishes the tokens are removed
+ /// from the end of the cache.
+ Token *cacheMacroExpandedTokens(TokenLexer *tokLexer,
+ ArrayRef<Token> tokens);
+ void removeCachedMacroExpandedTokensOfLastLexer();
+ friend void TokenLexer::ExpandFunctionArguments();
+
+ /// 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();
+
+ /// After reading "MACRO(", this method is invoked to read all of the formal
+ /// arguments specified for the macro invocation. Returns null on error.
+ MacroArgs *ReadFunctionLikeMacroArgs(Token &MacroName, MacroInfo *MI,
+ SourceLocation &ExpansionEnd);
+
+ /// \brief 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);
+
+ /// \brief Read a \c _Pragma directive, slice it up, process it, then
+ /// return the first token after the directive.
+ /// This assumes that the \c _Pragma token has just been read into \p Tok.
+ void Handle_Pragma(Token &Tok);
+
+ /// \brief Like Handle_Pragma except the pragma text is not enclosed within
+ /// a string literal.
+ void HandleMicrosoft__pragma(Token &Tok);
+
+ /// \brief 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);
+
+ /// \brief 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);
+
+ /// \brief Set the FileID for the preprocessor predefines.
+ void setPredefinesFileID(FileID FID) {
+ assert(PredefinesFileID.isInvalid() && "PredefinesFileID already set!");
+ PredefinesFileID = FID;
+ }
+
+ /// \brief 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 != nullptr;
+ }
+
+ static bool IsFileLexer(const IncludeStackInfo& I) {
+ return IsFileLexer(I.TheLexer.get(), 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 && !CurTokenLexer && !CurPTHLexer &&
+ !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);
+ void HandleMacroPublicDirective(Token &Tok);
+ void HandleMacroPrivateDirective(Token &Tok);
+
+ // File inclusion.
+ void HandleIncludeDirective(SourceLocation HashLoc,
+ Token &Tok,
+ const DirectoryLookup *LookupFrom = nullptr,
+ const FileEntry *LookupFromFile = nullptr,
+ bool isImport = false);
+ void HandleIncludeNextDirective(SourceLocation HashLoc, Token &Tok);
+ void HandleIncludeMacrosDirective(SourceLocation HashLoc, Token &Tok);
+ void HandleImportDirective(SourceLocation HashLoc, Token &Tok);
+ void HandleMicrosoftImportDirective(Token &Tok);
+
+public:
+ // Module inclusion testing.
+ /// \brief Find the module that owns the source or header file that
+ /// \p Loc points to. If the location is in a file that was included
+ /// into a module, or is outside any module, returns nullptr.
+ Module *getModuleForLocation(SourceLocation Loc);
+
+ /// \brief Find the module that contains the specified location, either
+ /// directly or indirectly.
+ Module *getModuleContainingLocation(SourceLocation Loc);
+
+private:
+ // Macro handling.
+ void HandleDefineDirective(Token &Tok, bool ImmediatelyAfterTopLevelIfndef);
+ 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(SourceLocation IntroducerLoc,
+ PragmaIntroducerKind Introducer);
+public:
+ void HandlePragmaOnce(Token &OnceTok);
+ void HandlePragmaMark();
+ void HandlePragmaPoison(Token &PoisonTok);
+ void HandlePragmaSystemHeader(Token &SysHeaderTok);
+ void HandlePragmaDependency(Token &DependencyTok);
+ void HandlePragmaPushMacro(Token &Tok);
+ void HandlePragmaPopMacro(Token &Tok);
+ void HandlePragmaIncludeAlias(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..6d6cf05
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Lex/PreprocessorLexer.h
@@ -0,0 +1,183 @@
+//===--- 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.
+//
+//===----------------------------------------------------------------------===//
+///
+/// \file
+/// \brief Defines the PreprocessorLexer interface.
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_LEX_PREPROCESSORLEXER_H
+#define LLVM_CLANG_LEX_PREPROCESSORLEXER_H
+
+#include "clang/Lex/MultipleIncludeOpt.h"
+#include "clang/Lex/Token.h"
+#include "llvm/ADT/SmallVector.h"
+
+namespace clang {
+
+class FileEntry;
+class Preprocessor;
+
+class PreprocessorLexer {
+ virtual void anchor();
+protected:
+ Preprocessor *PP; // Preprocessor object controlling lexing.
+
+ /// The SourceManager FileID corresponding to the file being lexed.
+ const FileID FID;
+
+ /// \brief Number of SLocEntries before lexing the file.
+ unsigned InitialNumSLocEntries;
+
+ //===--------------------------------------------------------------------===//
+ // Context-specific lexing flags set by the preprocessor.
+ //===--------------------------------------------------------------------===//
+
+ /// \brief True when parsing \#XXX; turns '\\n' into a tok::eod token.
+ bool ParsingPreprocessorDirective;
+
+ /// \brief True after \#include; turns \<xx> into a tok::angle_string_literal
+ /// token.
+ bool ParsingFilename;
+
+ /// \brief True if in raw mode.
+ ///
+ /// Raw mode 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;
+
+ /// \brief A state machine that detects the \#ifndef-wrapping a file
+ /// idiom for the multiple-include optimization.
+ MultipleIncludeOpt MIOpt;
+
+ /// \brief Information about the set of \#if/\#ifdef/\#ifndef blocks
+ /// we are currently in.
+ SmallVector<PPConditionalInfo, 4> ConditionalStack;
+
+ PreprocessorLexer(const PreprocessorLexer &) = delete;
+ void operator=(const PreprocessorLexer &) = delete;
+ friend class Preprocessor;
+
+ PreprocessorLexer(Preprocessor *pp, FileID fid);
+
+ PreprocessorLexer()
+ : PP(nullptr), InitialNumSLocEntries(0),
+ ParsingPreprocessorDirective(false),
+ ParsingFilename(false),
+ LexingRawMode(false) {}
+
+ virtual ~PreprocessorLexer() {}
+
+ virtual void IndirectLex(Token& Result) = 0;
+
+ /// \brief 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.pop_back_val();
+ return false;
+ }
+
+ /// \brief Return the top of the conditional stack.
+ /// \pre 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.
+
+ /// \brief 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 EOD token.
+ void LexIncludeFilename(Token &Result);
+
+ /// \brief Inform the lexer whether or not we are currently lexing a
+ /// preprocessor directive.
+ void setParsingPreprocessorDirective(bool f) {
+ ParsingPreprocessorDirective = f;
+ }
+
+ /// \brief Return true if this lexer is in raw mode or not.
+ bool isLexingRawMode() const { return LexingRawMode; }
+
+ /// \brief 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;
+ }
+
+ /// \brief Number of SLocEntries before lexing the file.
+ unsigned getInitialNumSLocEntries() const {
+ return InitialNumSLocEntries;
+ }
+
+ /// 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 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/PreprocessorOptions.h b/contrib/llvm/tools/clang/include/clang/Lex/PreprocessorOptions.h
new file mode 100644
index 0000000..963d95d
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Lex/PreprocessorOptions.h
@@ -0,0 +1,185 @@
+//===--- PreprocessorOptions.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_LEX_PREPROCESSOROPTIONS_H_
+#define LLVM_CLANG_LEX_PREPROCESSOROPTIONS_H_
+
+#include "clang/Basic/SourceLocation.h"
+#include "llvm/ADT/IntrusiveRefCntPtr.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/ADT/StringSet.h"
+#include <cassert>
+#include <set>
+#include <string>
+#include <utility>
+#include <vector>
+
+namespace llvm {
+ class MemoryBuffer;
+}
+
+namespace clang {
+
+class Preprocessor;
+class LangOptions;
+
+/// \brief Enumerate the kinds of standard library that
+enum ObjCXXARCStandardLibraryKind {
+ ARCXX_nolib,
+ /// \brief libc++
+ ARCXX_libcxx,
+ /// \brief libstdc++
+ ARCXX_libstdcxx
+};
+
+/// PreprocessorOptions - This class is used for passing the various options
+/// used in preprocessor initialization to InitializePreprocessor().
+class PreprocessorOptions : public RefCountedBase<PreprocessorOptions> {
+public:
+ std::vector<std::pair<std::string, bool/*isUndef*/> > Macros;
+ std::vector<std::string> Includes;
+ std::vector<std::string> MacroIncludes;
+
+ /// \brief Initialize the preprocessor with the compiler and target specific
+ /// predefines.
+ unsigned UsePredefines : 1;
+
+ /// \brief Whether we should maintain a detailed record of all macro
+ /// definitions and expansions.
+ unsigned DetailedRecord : 1;
+
+ /// The implicit PCH included at the start of the translation unit, or empty.
+ std::string ImplicitPCHInclude;
+
+ /// \brief Headers that will be converted to chained PCHs in memory.
+ std::vector<std::string> ChainedIncludes;
+
+ /// \brief When true, disables most of the normal validation performed on
+ /// precompiled headers.
+ bool DisablePCHValidation;
+
+ /// \brief When true, a PCH with compiler errors will not be rejected.
+ bool AllowPCHWithCompilerErrors;
+
+ /// \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 True if the SourceManager should report the original file name for
+ /// contents of files that were remapped to other files. Defaults to true.
+ bool RemappedFilesKeepOriginalName;
+
+ /// \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, 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;
+
+ /// \brief The Objective-C++ ARC standard library that we should support,
+ /// by providing appropriate definitions to retrofit the standard library
+ /// with support for lifetime-qualified pointers.
+ ObjCXXARCStandardLibraryKind ObjCXXARCStandardLibrary;
+
+ /// \brief Records the set of modules
+ class FailedModulesSet : public RefCountedBase<FailedModulesSet> {
+ llvm::StringSet<> Failed;
+
+ public:
+ bool hasAlreadyFailed(StringRef module) {
+ return Failed.count(module) > 0;
+ }
+
+ void addFailed(StringRef module) {
+ Failed.insert(module);
+ }
+ };
+
+ /// \brief The set of modules that failed to build.
+ ///
+ /// This pointer will be shared among all of the compiler instances created
+ /// to (re)build modules, so that once a module fails to build anywhere,
+ /// other instances will see that the module has failed and won't try to
+ /// build it again.
+ IntrusiveRefCntPtr<FailedModulesSet> FailedModules;
+
+public:
+ PreprocessorOptions() : UsePredefines(true), DetailedRecord(false),
+ DisablePCHValidation(false),
+ AllowPCHWithCompilerErrors(false),
+ DumpDeserializedPCHDecls(false),
+ PrecompiledPreambleBytes(0, true),
+ RemappedFilesKeepOriginalName(true),
+ RetainRemappedFileBuffers(false),
+ ObjCXXARCStandardLibrary(ARCXX_nolib) { }
+
+ void addMacroDef(StringRef Name) { Macros.emplace_back(Name, false); }
+ void addMacroUndef(StringRef Name) { Macros.emplace_back(Name, true); }
+ void addRemappedFile(StringRef From, StringRef To) {
+ RemappedFiles.emplace_back(From, To);
+ }
+
+ void addRemappedFile(StringRef From, llvm::MemoryBuffer *To) {
+ RemappedFileBuffers.emplace_back(From, To);
+ }
+
+ void clearRemappedFiles() {
+ RemappedFiles.clear();
+ RemappedFileBuffers.clear();
+ }
+
+ /// \brief Reset any options that are not considered when building a
+ /// module.
+ void resetNonModularOptions() {
+ Includes.clear();
+ MacroIncludes.clear();
+ ChainedIncludes.clear();
+ DumpDeserializedPCHDecls = false;
+ ImplicitPCHInclude.clear();
+ ImplicitPTHInclude.clear();
+ TokenCache.clear();
+ RetainRemappedFileBuffers = true;
+ PrecompiledPreambleBytes.first = 0;
+ PrecompiledPreambleBytes.second = 0;
+ }
+};
+
+} // 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..a3d6096
--- /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_LEX_SCRATCHBUFFER_H
+#define LLVM_CLANG_LEX_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..7ba22b2
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Lex/Token.h
@@ -0,0 +1,328 @@
+//===--- 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_LEX_TOKEN_H
+#define LLVM_CLANG_LEX_TOKEN_H
+
+#include "clang/Basic/OperatorKinds.h"
+#include "clang/Basic/SourceLocation.h"
+#include "clang/Basic/TemplateKinds.h"
+#include "clang/Basic/TokenKinds.h"
+#include "llvm/ADT/StringRef.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. This is actually a SourceLocation.
+ unsigned 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.
+ /// Eof:
+ // This is a pointer to a Decl.
+ /// Other:
+ /// This is null.
+ void *PtrData;
+
+ /// Kind - The actual flavor of token this is.
+ tok::TokenKind Kind;
+
+ /// Flags - Bits we track about this token, members of the TokenFlags enum.
+ unsigned short Flags;
+public:
+
+ // Various flags set per token:
+ enum TokenFlags {
+ StartOfLine = 0x01, // At start of line or only after whitespace
+ // (considering the line after macro expansion).
+ LeadingSpace = 0x02, // Whitespace exists before this token (considering
+ // whitespace after macro expansion).
+ 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.
+ HasUDSuffix = 0x20, // This string or character literal has a ud-suffix.
+ HasUCN = 0x40, // This identifier contains a UCN.
+ IgnoredComma = 0x80, // This comma is not a macro argument separator (MS).
+ StringifiedInMacro = 0x100, // This string or character literal is formed by
+ // macro stringizing or charizing operator.
+ };
+
+ tok::TokenKind getKind() const { return 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 == K; }
+ bool isNot(tok::TokenKind K) const { return Kind != K; }
+ bool isOneOf(tok::TokenKind K1, tok::TokenKind K2) const {
+ return is(K1) || is(K2);
+ }
+ template <typename... Ts>
+ bool isOneOf(tok::TokenKind K1, tok::TokenKind K2, Ts... Ks) const {
+ return is(K1) || isOneOf(K2, Ks...);
+ }
+
+ /// \brief 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 tok::isAnyIdentifier(getKind());
+ }
+
+ /// \brief Return true if this is a "literal", like a numeric
+ /// constant, string, etc.
+ bool isLiteral() const {
+ return tok::isLiteral(getKind());
+ }
+
+ /// \brief Return true if this is any of tok::annot_* kind tokens.
+ bool isAnnotation() const {
+ return tok::isAnnotation(getKind());
+ }
+
+ /// \brief Return a source location identifier for the specified
+ /// offset in the current file.
+ SourceLocation getLocation() const {
+ return SourceLocation::getFromRawEncoding(Loc);
+ }
+ unsigned getLength() const {
+ assert(!isAnnotation() && "Annotation tokens have no length field");
+ return UintData;
+ }
+
+ void setLocation(SourceLocation L) { Loc = L.getRawEncoding(); }
+ 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 ? UintData : Loc);
+ }
+ void setAnnotationEndLoc(SourceLocation L) {
+ assert(isAnnotation() && "Used AnnotEndLocID on non-annotation token");
+ UintData = L.getRawEncoding();
+ }
+
+ SourceLocation getLastLoc() const {
+ return isAnnotation() ? getAnnotationEndLoc() : getLocation();
+ }
+
+ SourceLocation getEndLoc() const {
+ return isAnnotation() ? getAnnotationEndLoc()
+ : getLocation().getLocWithOffset(getLength());
+ }
+
+ /// \brief 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(Kind); }
+
+ /// \brief Reset all flags to cleared.
+ void startToken() {
+ Kind = tok::unknown;
+ Flags = 0;
+ PtrData = nullptr;
+ UintData = 0;
+ Loc = SourceLocation().getRawEncoding();
+ }
+
+ 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 nullptr;
+ if (is(tok::eof)) return nullptr;
+ return (IdentifierInfo*) PtrData;
+ }
+ void setIdentifierInfo(IdentifierInfo *II) {
+ PtrData = (void*) II;
+ }
+
+ const void *getEofData() const {
+ assert(is(tok::eof));
+ return reinterpret_cast<const void *>(PtrData);
+ }
+ void setEofData(const void *D) {
+ assert(is(tok::eof));
+ assert(!PtrData);
+ PtrData = const_cast<void *>(D);
+ }
+
+ /// getRawIdentifier - For a raw identifier token (i.e., an identifier
+ /// lexed in raw mode), returns a reference to the text substring in the
+ /// buffer if known.
+ StringRef getRawIdentifier() const {
+ assert(is(tok::raw_identifier));
+ return StringRef(reinterpret_cast<const char *>(PtrData), getLength());
+ }
+ 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;
+ }
+
+ /// \brief Set the specified flag.
+ void setFlag(TokenFlags Flag) {
+ Flags |= Flag;
+ }
+
+ /// \brief Unset the specified flag.
+ void clearFlag(TokenFlags Flag) {
+ Flags &= ~Flag;
+ }
+
+ /// \brief Return the internal represtation of the flags.
+ ///
+ /// This is only intended for low-level operations such as writing tokens to
+ /// disk.
+ unsigned getFlags() const {
+ return Flags;
+ }
+
+ /// \brief 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; }
+
+ /// \brief Return true if this token has whitespace before it.
+ ///
+ bool hasLeadingSpace() const { return (Flags & LeadingSpace) ? true : false; }
+
+ /// \brief 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;
+ }
+
+ /// \brief Return true if we have an ObjC keyword identifier.
+ bool isObjCAtKeyword(tok::ObjCKeywordKind objcKey) const;
+
+ /// \brief Return the ObjC keyword kind.
+ tok::ObjCKeywordKind getObjCKeywordID() const;
+
+ /// \brief 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;
+ }
+
+ /// \brief Return true if this token is a string or character literal which
+ /// has a ud-suffix.
+ bool hasUDSuffix() const { return (Flags & HasUDSuffix) ? true : false; }
+
+ /// Returns true if this token contains a universal character name.
+ bool hasUCN() const { return (Flags & HasUCN) ? true : false; }
+
+ /// Returns true if this token is formed by macro by stringizing or charizing
+ /// operator.
+ bool stringifiedInMacro() const {
+ return (Flags & StringifiedInMacro) ? true : false;
+ }
+};
+
+/// \brief Information about the conditional stack (\#if directives)
+/// currently active.
+struct PPConditionalInfo {
+ /// \brief Location where the conditional started.
+ SourceLocation IfLoc;
+
+ /// \brief True if this was contained in a skipping directive, e.g.,
+ /// in a "\#if 0" block.
+ bool WasSkipping;
+
+ /// \brief True if we have emitted tokens already, and now we're in
+ /// an \#else block or something. Only useful in Skipping blocks.
+ bool FoundNonSkip;
+
+ /// \brief 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..a2d98b0
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Lex/TokenConcatenation.h
@@ -0,0 +1,72 @@
+//===--- 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 LLVM_CLANG_LEX_TOKENCONCATENATION_H
+#define LLVM_CLANG_LEX_TOKENCONCATENATION_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:
+ /// IsIdentifierStringPrefix - Return true if the spelling of the token
+ /// is literally 'L', 'u', 'U', or 'u8'.
+ bool IsIdentifierStringPrefix(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..fdeed44
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Lex/TokenLexer.h
@@ -0,0 +1,205 @@
+//===--- 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_LEX_TOKENLEXER_H
+#define LLVM_CLANG_LEX_TOKENLEXER_H
+
+#include "clang/Basic/SourceLocation.h"
+
+namespace clang {
+ class MacroInfo;
+ class Preprocessor;
+ class Token;
+ class MacroArgs;
+
+/// TokenLexer - This implements a lexer that returns tokens 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 cache buffer that is owned by
+ /// the preprocessor, or some other buffer that we may or may not own
+ /// (depending on OwnsTokens).
+ /// Note that if it points into Preprocessor's cache buffer, the Preprocessor
+ /// may update the pointer as needed.
+ const Token *Tokens;
+ friend class Preprocessor;
+
+ /// NumTokens - This is the length of the Tokens array.
+ ///
+ unsigned NumTokens;
+
+ /// CurToken - This is the next token that Lex will return.
+ ///
+ unsigned CurToken;
+
+ /// ExpandLocStart/End - The source location range where this macro was
+ /// expanded.
+ SourceLocation ExpandLocStart, ExpandLocEnd;
+
+ /// \brief Source location pointing at the source location entry chunk that
+ /// was reserved for the current macro expansion.
+ SourceLocation MacroExpansionStart;
+
+ /// \brief The offset of the macro expansion in the
+ /// "source location address space".
+ unsigned MacroStartSLocOffset;
+
+ /// \brief Location of the macro definition.
+ SourceLocation MacroDefStart;
+ /// \brief Length of the macro definition.
+ unsigned MacroDefLength;
+
+ /// 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;
+
+ // NextTokGetsSpace - When this is true, the next token appended to the
+ // output list during function argument expansion will get a leading space,
+ // regardless of whether it had one to begin with or not. This is used for
+ // placemarker support. If still true after function argument expansion, the
+ // leading space will be applied to the first token following the macro
+ // expansion.
+ bool NextTokGetsSpace : 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 &) = delete;
+ void operator=(const TokenLexer &) = delete;
+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, MacroInfo *MI,
+ MacroArgs *ActualArgs, Preprocessor &pp)
+ : Macro(nullptr), ActualArgs(nullptr), PP(pp), OwnsTokens(false) {
+ Init(Tok, ILEnd, MI, 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, MacroInfo *MI,
+ 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(nullptr), ActualArgs(nullptr), 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.
+ bool Lex(Token &Tok);
+
+ /// isParsingPreprocessorDirective - Return true if we are in the middle of a
+ /// preprocessor directive.
+ bool isParsingPreprocessorDirective() const;
+
+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 expanded buffer. Handle this by returning the
+ /// first token on the next line.
+ void HandleMicrosoftCommentPaste(Token &Tok, SourceLocation OpLoc);
+
+ /// \brief If \p loc is a FileID and points inside the current macro
+ /// definition, returns the appropriate source location pointing at the
+ /// macro expansion source location entry.
+ SourceLocation getExpansionLocForMacroDefLoc(SourceLocation loc) const;
+
+ /// \brief Creates SLocEntries and updates the locations of macro argument
+ /// tokens to their new expanded locations.
+ ///
+ /// \param ArgIdSpellLoc the location of the macro argument id inside the
+ /// macro definition.
+ void updateLocForMacroArgTokens(SourceLocation ArgIdSpellLoc,
+ Token *begin_tokens, Token *end_tokens);
+
+ /// Remove comma ahead of __VA_ARGS__, if present, according to compiler
+ /// dialect settings. Returns true if the comma is removed.
+ bool MaybeRemoveCommaBeforeVaArgs(SmallVectorImpl<Token> &ResultToks,
+ bool HasPasteOperator,
+ MacroInfo *Macro, unsigned MacroArgNo,
+ Preprocessor &PP);
+
+ void PropagateLineStartLeadingSpaceInfo(Token &Result);
+};
+
+} // 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..21f9701
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Parse/ParseAST.h
@@ -0,0 +1,49 @@
+//===--- 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
+
+#include "clang/Basic/LangOptions.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 TUKind The kind of translation unit being parsed.
+ ///
+ /// \param CompletionConsumer If given, an object to consume code completion
+ /// results.
+ void ParseAST(Preprocessor &pp, ASTConsumer *C,
+ ASTContext &Ctx, bool PrintStats = false,
+ TranslationUnitKind TUKind = TU_Complete,
+ CodeCompleteConsumer *CompletionConsumer = nullptr,
+ bool SkipFunctionBodies = false);
+
+ /// \brief Parse the main file known to the preprocessor, producing an
+ /// abstract syntax tree.
+ void ParseAST(Sema &S, bool PrintStats = false,
+ bool SkipFunctionBodies = 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..f3a7f3b
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Parse/ParseDiagnostic.h
@@ -0,0 +1,28 @@
+//===--- 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_PARSE_PARSEDIAGNOSTIC_H
+#define LLVM_CLANG_PARSE_PARSEDIAGNOSTIC_H
+
+#include "clang/Basic/Diagnostic.h"
+
+namespace clang {
+ namespace diag {
+ enum {
+#define DIAG(ENUM,FLAGS,DEFAULT_MAPPING,DESC,GROUP,\
+ SFINAE,NOWERROR,SHOWINSYSHEADER,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..82b7798
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Parse/Parser.h
@@ -0,0 +1,2593 @@
+//===--- 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/OpenMPKinds.h"
+#include "clang/Basic/OperatorPrecedence.h"
+#include "clang/Basic/Specifiers.h"
+#include "clang/Lex/CodeCompletionHandler.h"
+#include "clang/Lex/Preprocessor.h"
+#include "clang/Sema/DeclSpec.h"
+#include "clang/Sema/LoopHint.h"
+#include "clang/Sema/Sema.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/Support/Compiler.h"
+#include "llvm/Support/PrettyStackTrace.h"
+#include "llvm/Support/SaveAndRestore.h"
+#include <memory>
+#include <stack>
+
+namespace clang {
+ class PragmaHandler;
+ class Scope;
+ class BalancedDelimiterTracker;
+ class CorrectionCandidateCallback;
+ class DeclGroupRef;
+ class DiagnosticBuilder;
+ class Parser;
+ class ParsingDeclRAIIObject;
+ class ParsingDeclSpec;
+ class ParsingDeclarator;
+ class ParsingFieldDeclarator;
+ class ColonProtectionRAIIObject;
+ class InMessageExpressionRAIIObject;
+ class PoisonSEHIdentifiersRAIIObject;
+ class VersionTuple;
+ class OMPClause;
+ class ObjCTypeParamList;
+ class ObjCTypeParameter;
+
+/// 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 ColonProtectionRAIIObject;
+ friend class InMessageExpressionRAIIObject;
+ friend class PoisonSEHIdentifiersRAIIObject;
+ friend class ObjCDeclContextSwitch;
+ friend class ParenBraceBracketBalancer;
+ friend class BalancedDelimiterTracker;
+
+ 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;
+
+ DiagnosticsEngine &Diags;
+
+ /// ScopeCache - Cache scopes to reduce malloc traffic.
+ enum { ScopeCacheSize = 16 };
+ unsigned NumCachedScopes;
+ Scope *ScopeCache[ScopeCacheSize];
+
+ /// Identifiers used for SEH handling in Borland. These are only
+ /// allowed in particular circumstances
+ // __except block
+ IdentifierInfo *Ident__exception_code,
+ *Ident___exception_code,
+ *Ident_GetExceptionCode;
+ // __except filter expression
+ IdentifierInfo *Ident__exception_info,
+ *Ident___exception_info,
+ *Ident_GetExceptionInfo;
+ // __finally
+ IdentifierInfo *Ident__abnormal_termination,
+ *Ident___abnormal_termination,
+ *Ident_AbnormalTermination;
+
+ /// Contextual keywords for Microsoft extensions.
+ IdentifierInfo *Ident__except;
+ mutable IdentifierInfo *Ident_sealed;
+
+ /// Ident_super - IdentifierInfo for "super", to support fast
+ /// comparison.
+ IdentifierInfo *Ident_super;
+ /// Ident_vector, Ident_bool - cached IdentifierInfos for "vector" and
+ /// "bool" fast comparison. Only present if AltiVec or ZVector are enabled.
+ IdentifierInfo *Ident_vector;
+ IdentifierInfo *Ident_bool;
+ /// Ident_pixel - cached IdentifierInfos for "pixel" fast comparison.
+ /// Only present if AltiVec enabled.
+ IdentifierInfo *Ident_pixel;
+
+ /// Objective-C contextual keywords.
+ mutable IdentifierInfo *Ident_instancetype;
+
+ /// \brief Identifier for "introduced".
+ IdentifierInfo *Ident_introduced;
+
+ /// \brief Identifier for "deprecated".
+ IdentifierInfo *Ident_deprecated;
+
+ /// \brief Identifier for "obsoleted".
+ IdentifierInfo *Ident_obsoleted;
+
+ /// \brief Identifier for "unavailable".
+ IdentifierInfo *Ident_unavailable;
+
+ /// \brief Identifier for "message".
+ IdentifierInfo *Ident_message;
+
+ /// C++0x contextual keywords.
+ mutable IdentifierInfo *Ident_final;
+ mutable IdentifierInfo *Ident_override;
+
+ // C++ type trait keywords that can be reverted to identifiers and still be
+ // used as type traits.
+ llvm::SmallDenseMap<IdentifierInfo *, tok::TokenKind> RevertibleTypeTraits;
+
+ std::unique_ptr<PragmaHandler> AlignHandler;
+ std::unique_ptr<PragmaHandler> GCCVisibilityHandler;
+ std::unique_ptr<PragmaHandler> OptionsHandler;
+ std::unique_ptr<PragmaHandler> PackHandler;
+ std::unique_ptr<PragmaHandler> MSStructHandler;
+ std::unique_ptr<PragmaHandler> UnusedHandler;
+ std::unique_ptr<PragmaHandler> WeakHandler;
+ std::unique_ptr<PragmaHandler> RedefineExtnameHandler;
+ std::unique_ptr<PragmaHandler> FPContractHandler;
+ std::unique_ptr<PragmaHandler> OpenCLExtensionHandler;
+ std::unique_ptr<PragmaHandler> OpenMPHandler;
+ std::unique_ptr<PragmaHandler> MSCommentHandler;
+ std::unique_ptr<PragmaHandler> MSDetectMismatchHandler;
+ std::unique_ptr<PragmaHandler> MSPointersToMembers;
+ std::unique_ptr<PragmaHandler> MSVtorDisp;
+ std::unique_ptr<PragmaHandler> MSInitSeg;
+ std::unique_ptr<PragmaHandler> MSDataSeg;
+ std::unique_ptr<PragmaHandler> MSBSSSeg;
+ std::unique_ptr<PragmaHandler> MSConstSeg;
+ std::unique_ptr<PragmaHandler> MSCodeSeg;
+ std::unique_ptr<PragmaHandler> MSSection;
+ std::unique_ptr<PragmaHandler> MSRuntimeChecks;
+ std::unique_ptr<PragmaHandler> OptimizeHandler;
+ std::unique_ptr<PragmaHandler> LoopHintHandler;
+ std::unique_ptr<PragmaHandler> UnrollHintHandler;
+ std::unique_ptr<PragmaHandler> NoUnrollHintHandler;
+
+ std::unique_ptr<CommentHandler> CommentSemaHandler;
+
+ /// 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 Objective-C message
+ /// 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;
+
+ /// \brief RAII class that manages the template parameter depth.
+ class TemplateParameterDepthRAII {
+ unsigned &Depth;
+ unsigned AddedLevels;
+ public:
+ explicit TemplateParameterDepthRAII(unsigned &Depth)
+ : Depth(Depth), AddedLevels(0) {}
+
+ ~TemplateParameterDepthRAII() {
+ Depth -= AddedLevels;
+ }
+
+ void operator++() {
+ ++Depth;
+ ++AddedLevels;
+ }
+ void addDepth(unsigned D) {
+ Depth += D;
+ AddedLevels += D;
+ }
+ unsigned getDepth() const { return Depth; }
+ };
+
+ /// Factory object for creating AttributeList objects.
+ AttributeFactory AttrFactory;
+
+ /// \brief Gathers and cleans up TemplateIdAnnotations when parsing of a
+ /// top-level declaration is finished.
+ SmallVector<TemplateIdAnnotation *, 16> TemplateIds;
+
+ /// \brief Identifiers which have been declared within a tentative parse.
+ SmallVector<IdentifierInfo *, 8> TentativelyDeclaredIdentifiers;
+
+ IdentifierInfo *getSEHExceptKeyword();
+
+ /// True if we are within an Objective-C container while parsing C-like decls.
+ ///
+ /// This is necessary because Sema thinks we have left the container
+ /// to parse the C-like decls, meaning Actions.getObjCDeclContext() will
+ /// be NULL.
+ bool ParsingInObjCContainer;
+
+ bool SkipFunctionBodies;
+
+public:
+ Parser(Preprocessor &PP, Sema &Actions, bool SkipFunctionBodies);
+ ~Parser() override;
+
+ const LangOptions &getLangOpts() const { return PP.getLangOpts(); }
+ const TargetInfo &getTargetInfo() const { return PP.getTargetInfo(); }
+ Preprocessor &getPreprocessor() const { return PP; }
+ Sema &getActions() const { return Actions; }
+ AttributeFactory &getAttrFactory() { return AttrFactory; }
+
+ const Token &getCurToken() const { return Tok; }
+ Scope *getCurScope() const { return Actions.getCurScope(); }
+ void incrementMSManglingNumber() const {
+ return Actions.incrementMSManglingNumber();
+ }
+
+ Decl *getObjCDeclContext() const { return Actions.getObjCDeclContext(); }
+
+ // Type forwarding. All of these are statically 'void*', but they may all be
+ // different actual classes based on the actions in place.
+ typedef OpaquePtr<DeclGroupRef> DeclGroupPtrTy;
+ typedef OpaquePtr<TemplateName> TemplateTy;
+
+ typedef SmallVector<TemplateParameterList *, 4> TemplateParameterLists;
+
+ typedef Sema::FullExprArg FullExprArg;
+
+ // Parsing methods.
+
+ /// Initialize - Warm up the parser.
+ ///
+ void Initialize();
+
+ /// ParseTopLevelDecl - Parse one top-level declaration. Returns true if
+ /// the EOF was encountered.
+ bool ParseTopLevelDecl(DeclGroupPtrTy &Result);
+ bool ParseTopLevelDecl() {
+ DeclGroupPtrTy Result;
+ return ParseTopLevelDecl(Result);
+ }
+
+ /// ConsumeToken - Consume the current 'peek token' and lex the next one.
+ /// This does not work with special tokens: string literals, code completion
+ /// and balanced tokens must be handled using the specific consume methods.
+ /// Returns the location of the consumed token.
+ SourceLocation ConsumeToken() {
+ assert(!isTokenSpecial() &&
+ "Should consume special tokens with Consume*Token");
+ PrevTokLocation = Tok.getLocation();
+ PP.Lex(Tok);
+ return PrevTokLocation;
+ }
+
+ bool TryConsumeToken(tok::TokenKind Expected) {
+ if (Tok.isNot(Expected))
+ return false;
+ assert(!isTokenSpecial() &&
+ "Should consume special tokens with Consume*Token");
+ PrevTokLocation = Tok.getLocation();
+ PP.Lex(Tok);
+ return true;
+ }
+
+ bool TryConsumeToken(tok::TokenKind Expected, SourceLocation &Loc) {
+ if (!TryConsumeToken(Expected))
+ return false;
+ Loc = PrevTokLocation;
+ return true;
+ }
+
+ /// Retrieve the underscored keyword (_Nonnull, _Nullable) that corresponds
+ /// to the given nullability kind.
+ IdentifierInfo *getNullabilityKeyword(NullabilityKind nullability) {
+ return Actions.getNullabilityKeyword(nullability);
+ }
+
+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::isStringLiteral(Tok.getKind());
+ }
+ /// isTokenSpecial - True if this token requires special consumption methods.
+ bool isTokenSpecial() const {
+ return isTokenStringLiteral() || isTokenParen() || isTokenBracket() ||
+ isTokenBrace() || Tok.is(tok::code_completion);
+ }
+
+ /// \brief Returns true if the current token is '=' or is a type of '='.
+ /// For typos, give a fixit to '='
+ bool isTokenEqualOrEqualTypo();
+
+ /// \brief Return the current token to the token stream and make the given
+ /// token the current token.
+ void UnconsumeToken(Token &Consumed) {
+ Token Next = Tok;
+ PP.EnterToken(Consumed);
+ PP.Lex(Tok);
+ PP.EnterToken(Next);
+ }
+
+ /// 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(bool ConsumeCodeCompletionTok = false) {
+ if (isTokenParen())
+ return ConsumeParen();
+ if (isTokenBracket())
+ return ConsumeBracket();
+ if (isTokenBrace())
+ return ConsumeBrace();
+ if (isTokenStringLiteral())
+ return ConsumeStringToken();
+ if (Tok.is(tok::code_completion))
+ return ConsumeCodeCompletionTok ? ConsumeCodeCompletionToken()
+ : handleUnexpectedCodeCompletionToken();
+ 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 can be called to consume the code-completion token and
+ /// continue processing in special cases where \c cutOffParsing() isn't
+ /// desired, such as token caching or completion with lookahead.
+ 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 without having
+ /// matched specific position in the grammar, provide code-completion results
+ /// based on context.
+ ///
+ /// \returns the source location of the code-completion token.
+ SourceLocation handleUnexpectedCodeCompletionToken();
+
+ /// \brief Abruptly cut off parsing; mainly used when we have reached the
+ /// code-completion point.
+ void cutOffParsing() {
+ if (PP.isCodeCompletionEnabled())
+ PP.setCodeCompletionReached();
+ // Cut off parsing by acting as if we reached the end-of-file.
+ Tok.setKind(tok::eof);
+ }
+
+ /// \brief Determine if we're at the end of the file or at a transition
+ /// between modules.
+ bool isEofOrEom() {
+ tok::TokenKind Kind = Tok.getKind();
+ return Kind == tok::eof || Kind == tok::annot_module_begin ||
+ Kind == tok::annot_module_end || Kind == tok::annot_module_include;
+ }
+
+ /// \brief Initialize all pragma handlers.
+ void initializePragmaHandlers();
+
+ /// \brief Destroy and reset all pragma handlers.
+ void resetPragmaHandlers();
+
+ /// \brief Handle the annotation token produced for #pragma unused(...)
+ void HandlePragmaUnused();
+
+ /// \brief Handle the annotation token produced for
+ /// #pragma GCC visibility...
+ void HandlePragmaVisibility();
+
+ /// \brief Handle the annotation token produced for
+ /// #pragma pack...
+ void HandlePragmaPack();
+
+ /// \brief Handle the annotation token produced for
+ /// #pragma ms_struct...
+ void HandlePragmaMSStruct();
+
+ /// \brief Handle the annotation token produced for
+ /// #pragma comment...
+ void HandlePragmaMSComment();
+
+ void HandlePragmaMSPointersToMembers();
+
+ void HandlePragmaMSVtorDisp();
+
+ void HandlePragmaMSPragma();
+ bool HandlePragmaMSSection(StringRef PragmaName,
+ SourceLocation PragmaLocation);
+ bool HandlePragmaMSSegment(StringRef PragmaName,
+ SourceLocation PragmaLocation);
+ bool HandlePragmaMSInitSeg(StringRef PragmaName,
+ SourceLocation PragmaLocation);
+
+ /// \brief Handle the annotation token produced for
+ /// #pragma align...
+ void HandlePragmaAlign();
+
+ /// \brief Handle the annotation token produced for
+ /// #pragma weak id...
+ void HandlePragmaWeak();
+
+ /// \brief Handle the annotation token produced for
+ /// #pragma weak id = id...
+ void HandlePragmaWeakAlias();
+
+ /// \brief Handle the annotation token produced for
+ /// #pragma redefine_extname...
+ void HandlePragmaRedefineExtname();
+
+ /// \brief Handle the annotation token produced for
+ /// #pragma STDC FP_CONTRACT...
+ void HandlePragmaFPContract();
+
+ /// \brief Handle the annotation token produced for
+ /// #pragma OPENCL EXTENSION...
+ void HandlePragmaOpenCLExtension();
+
+ /// \brief Handle the annotation token produced for
+ /// #pragma clang __debug captured
+ StmtResult HandlePragmaCaptured();
+
+ /// \brief Handle the annotation token produced for
+ /// #pragma clang loop and #pragma unroll.
+ bool HandlePragmaLoopHint(LoopHint &Hint);
+
+ /// 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);
+ }
+
+public:
+ /// 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());
+ }
+
+private:
+ static void setTypeAnnotation(Token &Tok, ParsedType T) {
+ Tok.setAnnotationValue(T.getAsOpaquePtr());
+ }
+
+ /// \brief Read an already-translated primary expression out of an annotation
+ /// token.
+ static ExprResult getExprAnnotation(Token &Tok) {
+ return ExprResult::getFromOpaquePointer(Tok.getAnnotationValue());
+ }
+
+ /// \brief Set the primary expression corresponding to the given annotation
+ /// token.
+ static void setExprAnnotation(Token &Tok, ExprResult ER) {
+ Tok.setAnnotationValue(ER.getAsOpaquePointer());
+ }
+
+public:
+ // If NeedType is true, then TryAnnotateTypeOrScopeToken will try harder to
+ // find a type name by attempting typo correction.
+ bool TryAnnotateTypeOrScopeToken(bool EnteringContext = false,
+ bool NeedType = false);
+ bool TryAnnotateTypeOrScopeTokenAfterScopeSpec(bool EnteringContext,
+ bool NeedType,
+ CXXScopeSpec &SS,
+ bool IsNewScope);
+ bool TryAnnotateCXXScopeToken(bool EnteringContext = false);
+
+private:
+ enum AnnotatedNameKind {
+ /// Annotation has failed and emitted an error.
+ ANK_Error,
+ /// The identifier is a tentatively-declared name.
+ ANK_TentativeDecl,
+ /// The identifier is a template name. FIXME: Add an annotation for that.
+ ANK_TemplateName,
+ /// The identifier can't be resolved.
+ ANK_Unresolved,
+ /// Annotation was successful.
+ ANK_Success
+ };
+ AnnotatedNameKind
+ TryAnnotateName(bool IsAddressOfOperand,
+ std::unique_ptr<CorrectionCandidateCallback> CCC = nullptr);
+
+ /// Push a tok::annot_cxxscope token onto the token stream.
+ void AnnotateScopeToken(CXXScopeSpec &SS, bool IsNewAnnotation);
+
+ /// 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 (!getLangOpts().AltiVec && !getLangOpts().ZVector)
+ return false;
+
+ if (Tok.getIdentifierInfo() != Ident_vector &&
+ Tok.getIdentifierInfo() != Ident_bool &&
+ (!getLangOpts().AltiVec || 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 ((!getLangOpts().AltiVec && !getLangOpts().ZVector) ||
+ Tok.getIdentifierInfo() != Ident_vector) return false;
+ return TryAltiVecVectorTokenOutOfLine();
+ }
+
+ bool TryAltiVecVectorTokenOutOfLine();
+ bool TryAltiVecTokenOutOfLine(DeclSpec &DS, SourceLocation Loc,
+ const char *&PrevSpec, unsigned &DiagID,
+ bool &isInvalid);
+
+ /// Returns true if the current token is the identifier 'instancetype'.
+ ///
+ /// Should only be used in Objective-C language modes.
+ bool isObjCInstancetype() {
+ assert(getLangOpts().ObjC1);
+ if (!Ident_instancetype)
+ Ident_instancetype = PP.getIdentifierInfo("instancetype");
+ return Tok.getIdentifierInfo() == Ident_instancetype;
+ }
+
+ /// TryKeywordIdentFallback - For compatibility with system headers using
+ /// keywords as identifiers, attempt to convert the current token to an
+ /// identifier and optionally disable the keyword for the remainder of the
+ /// translation unit. This returns false if the token was not replaced,
+ /// otherwise emits a diagnostic and returns true.
+ bool TryKeywordIdentFallback(bool DisableKeyword);
+
+ /// \brief Get the TemplateIdAnnotation from the token.
+ TemplateIdAnnotation *takeTemplateIdAnnotation(const Token &tok);
+
+ /// 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;
+ size_t PrevTentativelyDeclaredIdentifierCount;
+ unsigned short PrevParenCount, PrevBracketCount, PrevBraceCount;
+ bool isActive;
+
+ public:
+ explicit TentativeParsingAction(Parser& p) : P(p) {
+ PrevTok = P.Tok;
+ PrevTentativelyDeclaredIdentifierCount =
+ P.TentativelyDeclaredIdentifiers.size();
+ PrevParenCount = P.ParenCount;
+ PrevBracketCount = P.BracketCount;
+ PrevBraceCount = P.BraceCount;
+ P.PP.EnableBacktrackAtThisPos();
+ isActive = true;
+ }
+ void Commit() {
+ assert(isActive && "Parsing action was finished!");
+ P.TentativelyDeclaredIdentifiers.resize(
+ PrevTentativelyDeclaredIdentifierCount);
+ P.PP.CommitBacktrackedTokens();
+ isActive = false;
+ }
+ void Revert() {
+ assert(isActive && "Parsing action was finished!");
+ P.PP.Backtrack();
+ P.Tok = PrevTok;
+ P.TentativelyDeclaredIdentifiers.resize(
+ PrevTentativelyDeclaredIdentifierCount);
+ P.ParenCount = PrevParenCount;
+ P.BracketCount = PrevBracketCount;
+ P.BraceCount = PrevBraceCount;
+ isActive = false;
+ }
+ ~TentativeParsingAction() {
+ assert(!isActive && "Forgot to call Commit or Revert!");
+ }
+ };
+ class UnannotatedTentativeParsingAction;
+
+ /// ObjCDeclContextSwitch - An object used to switch context from
+ /// an objective-c decl context to its enclosing decl context and
+ /// back.
+ class ObjCDeclContextSwitch {
+ Parser &P;
+ Decl *DC;
+ SaveAndRestore<bool> WithinObjCContainer;
+ public:
+ explicit ObjCDeclContextSwitch(Parser &p)
+ : P(p), DC(p.getObjCDeclContext()),
+ WithinObjCContainer(P.ParsingInObjCContainer, DC != nullptr) {
+ if (DC)
+ P.Actions.ActOnObjCTemporaryExitContainerContext(cast<DeclContext>(DC));
+ }
+ ~ObjCDeclContextSwitch() {
+ if (DC)
+ P.Actions.ActOnObjCReenterContainerContext(cast<DeclContext>(DC));
+ }
+ };
+
+ /// ExpectAndConsume - The parser expects that 'ExpectedTok' is next in the
+ /// input. If so, it is consumed and false is returned.
+ ///
+ /// If a trivial punctuator misspelling is encountered, a FixIt error
+ /// diagnostic is issued and false is returned after recovery.
+ ///
+ /// If the input is malformed, this emits the specified diagnostic and true is
+ /// returned.
+ bool ExpectAndConsume(tok::TokenKind ExpectedTok,
+ unsigned Diag = diag::err_expected,
+ StringRef DiagMsg = "");
+
+ /// \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);
+
+ /// \brief The kind of extra semi diagnostic to emit.
+ enum ExtraSemiKind {
+ OutsideFunction = 0,
+ InsideStruct = 1,
+ InstanceVariableList = 2,
+ AfterMemberFunctionDefinition = 3
+ };
+
+ /// \brief Consume any extra semi-colons until the end of the line.
+ void ConsumeExtraSemi(ExtraSemiKind Kind, unsigned TST = TST_unspecified);
+
+public:
+ //===--------------------------------------------------------------------===//
+ // 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 &) = delete;
+ void operator=(const ParseScope &) = delete;
+
+ 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 we aren't about to enter a compound statement.
+ ParseScope(Parser *Self, unsigned ScopeFlags, bool EnteredScope = true,
+ bool BeforeCompoundStmt = false)
+ : Self(Self) {
+ if (EnteredScope && !BeforeCompoundStmt)
+ Self->EnterScope(ScopeFlags);
+ else {
+ if (BeforeCompoundStmt)
+ Self->incrementMSManglingNumber();
+
+ this->Self = nullptr;
+ }
+ }
+
+ // Exit - Exit the scope associated with this object now, rather
+ // than waiting until the object is destroyed.
+ void Exit() {
+ if (Self) {
+ Self->ExitScope();
+ Self = nullptr;
+ }
+ }
+
+ ~ParseScope() {
+ Exit();
+ }
+ };
+
+ /// EnterScope - Start a new scope.
+ void EnterScope(unsigned ScopeFlags);
+
+ /// ExitScope - Pop a scope off the scope stack.
+ void ExitScope();
+
+private:
+ /// \brief RAII object used to modify the scope flags for the current scope.
+ class ParseScopeFlags {
+ Scope *CurScope;
+ unsigned OldFlags;
+ ParseScopeFlags(const ParseScopeFlags &) = delete;
+ void operator=(const ParseScopeFlags &) = delete;
+
+ public:
+ ParseScopeFlags(Parser *Self, unsigned ScopeFlags, bool ManageFlags = true);
+ ~ParseScopeFlags();
+ };
+
+ //===--------------------------------------------------------------------===//
+ // Diagnostic Emission and Error recovery.
+
+public:
+ DiagnosticBuilder Diag(SourceLocation Loc, unsigned DiagID);
+ DiagnosticBuilder Diag(const Token &Tok, unsigned DiagID);
+ DiagnosticBuilder Diag(unsigned DiagID) {
+ return Diag(Tok, DiagID);
+ }
+
+private:
+ void SuggestParentheses(SourceLocation Loc, unsigned DK,
+ SourceRange ParenRange);
+ void CheckNestedObjCContexts(SourceLocation AtLoc);
+
+public:
+
+ /// \brief Control flags for SkipUntil functions.
+ enum SkipUntilFlags {
+ StopAtSemi = 1 << 0, ///< Stop skipping at semicolon
+ /// \brief Stop skipping at specified token, but don't skip the token itself
+ StopBeforeMatch = 1 << 1,
+ StopAtCodeCompletion = 1 << 2 ///< Stop at code completion
+ };
+
+ friend LLVM_CONSTEXPR SkipUntilFlags operator|(SkipUntilFlags L,
+ SkipUntilFlags R) {
+ return static_cast<SkipUntilFlags>(static_cast<unsigned>(L) |
+ static_cast<unsigned>(R));
+ }
+
+ /// SkipUntil - Read tokens until we get to the specified token, then consume
+ /// it (unless StopBeforeMatch is specified). Because we cannot guarantee
+ /// that the token will ever occur, this skips to the next token, or to some
+ /// likely good stopping point. If Flags has StopAtSemi flag, skipping will
+ /// stop at a ';' character.
+ ///
+ /// If SkipUntil finds the specified token, it returns true, otherwise it
+ /// returns false.
+ bool SkipUntil(tok::TokenKind T,
+ SkipUntilFlags Flags = static_cast<SkipUntilFlags>(0)) {
+ return SkipUntil(llvm::makeArrayRef(T), Flags);
+ }
+ bool SkipUntil(tok::TokenKind T1, tok::TokenKind T2,
+ SkipUntilFlags Flags = static_cast<SkipUntilFlags>(0)) {
+ tok::TokenKind TokArray[] = {T1, T2};
+ return SkipUntil(TokArray, Flags);
+ }
+ bool SkipUntil(tok::TokenKind T1, tok::TokenKind T2, tok::TokenKind T3,
+ SkipUntilFlags Flags = static_cast<SkipUntilFlags>(0)) {
+ tok::TokenKind TokArray[] = {T1, T2, T3};
+ return SkipUntil(TokArray, Flags);
+ }
+ bool SkipUntil(ArrayRef<tok::TokenKind> Toks,
+ SkipUntilFlags Flags = static_cast<SkipUntilFlags>(0));
+
+ /// SkipMalformedDecl - Read tokens until we get to some likely good stopping
+ /// point for skipping past a simple-declaration.
+ void SkipMalformedDecl();
+
+private:
+ //===--------------------------------------------------------------------===//
+ // 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 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 ParseLexedMemberInitializers();
+ virtual void ParseLexedMethodDefs();
+ virtual void ParseLexedAttributes();
+ };
+
+ /// Inner node of the LateParsedDeclaration tree that parses
+ /// all its members recursively.
+ class LateParsedClass : public LateParsedDeclaration {
+ public:
+ LateParsedClass(Parser *P, ParsingClass *C);
+ ~LateParsedClass() override;
+
+ void ParseLexedMethodDeclarations() override;
+ void ParseLexedMemberInitializers() override;
+ void ParseLexedMethodDefs() override;
+ void ParseLexedAttributes() override;
+
+ private:
+ Parser *Self;
+ ParsingClass *Class;
+ };
+
+ /// Contains the lexed tokens of an attribute with arguments that
+ /// may reference member variables and so need to be parsed at the
+ /// end of the class declaration after parsing all other member
+ /// member declarations.
+ /// FIXME: Perhaps we should change the name of LateParsedDeclaration to
+ /// LateParsedTokens.
+ struct LateParsedAttribute : public LateParsedDeclaration {
+ Parser *Self;
+ CachedTokens Toks;
+ IdentifierInfo &AttrName;
+ SourceLocation AttrNameLoc;
+ SmallVector<Decl*, 2> Decls;
+
+ explicit LateParsedAttribute(Parser *P, IdentifierInfo &Name,
+ SourceLocation Loc)
+ : Self(P), AttrName(Name), AttrNameLoc(Loc) {}
+
+ void ParseLexedAttributes() override;
+
+ void addDecl(Decl *D) { Decls.push_back(D); }
+ };
+
+ // A list of late-parsed attributes. Used by ParseGNUAttributes.
+ class LateParsedAttrList: public SmallVector<LateParsedAttribute *, 2> {
+ public:
+ LateParsedAttrList(bool PSoon = false) : ParseSoon(PSoon) { }
+
+ bool parseSoon() { return ParseSoon; }
+
+ private:
+ bool ParseSoon; // Are we planning to parse these shortly after creation?
+ };
+
+ /// 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.
+ /// otherwise, it is a member function declaration.
+ bool TemplateScope;
+
+ explicit LexedMethod(Parser* P, Decl *MD)
+ : Self(P), D(MD), TemplateScope(false) {}
+
+ void ParseLexedMethodDefs() override;
+ };
+
+ /// 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 = nullptr)
+ : 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),
+ ExceptionSpecTokens(nullptr) {}
+
+ void ParseLexedMethodDeclarations() override;
+
+ 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.
+ SmallVector<LateParsedDefaultArgument, 8> DefaultArgs;
+
+ /// \brief The set of tokens that make up an exception-specification that
+ /// has not yet been parsed.
+ CachedTokens *ExceptionSpecTokens;
+ };
+
+ /// LateParsedMemberInitializer - An initializer for a non-static class data
+ /// member whose parsing must to be delayed until the class is completely
+ /// defined (C++11 [class.mem]p2).
+ struct LateParsedMemberInitializer : public LateParsedDeclaration {
+ LateParsedMemberInitializer(Parser *P, Decl *FD)
+ : Self(P), Field(FD) { }
+
+ void ParseLexedMemberInitializers() override;
+
+ Parser *Self;
+
+ /// Field - The field declaration.
+ Decl *Field;
+
+ /// CachedTokens - The sequence of tokens that comprises the initializer,
+ /// including any leading '='.
+ CachedTokens Toks;
+ };
+
+ /// LateParsedDeclarationsContainer - During parsing of a top (non-nested)
+ /// C++ class, its method declarations that contain parts that won't be
+ /// parsed until after the definition 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 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, bool IsInterface)
+ : TopLevelClass(TopLevelClass), TemplateScope(false),
+ IsInterface(IsInterface), 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 Whether this class is an __interface.
+ bool IsInterface : 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 manage the parsing of a class definition.
+ class ParsingClassDefinition {
+ Parser &P;
+ bool Popped;
+ Sema::ParsingClassState State;
+
+ public:
+ ParsingClassDefinition(Parser &P, Decl *TagOrTemplate, bool TopLevelClass,
+ bool IsInterface)
+ : P(P), Popped(false),
+ State(P.PushParsingClass(TagOrTemplate, TopLevelClass, IsInterface)) {
+ }
+
+ /// \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(nullptr), 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(nullptr),
+ 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 LLVM_READONLY;
+ };
+
+ void LexTemplateFunctionForLateParsing(CachedTokens &Toks);
+ void ParseLateTemplatedFuncDef(LateParsedTemplate &LPT);
+
+ static void LateTemplateParserCallback(void *P, LateParsedTemplate &LPT);
+ static void LateTemplateParserCleanupCallback(void *P);
+
+ Sema::ParsingClassState
+ PushParsingClass(Decl *TagOrTemplate, bool TopLevelClass, bool IsInterface);
+ void DeallocateParsedClasses(ParsingClass *Class);
+ void PopParsingClass(Sema::ParsingClassState);
+
+ enum CachedInitKind {
+ CIK_DefaultArgument,
+ CIK_DefaultInitializer
+ };
+
+ NamedDecl *ParseCXXInlineMethodDef(AccessSpecifier AS,
+ AttributeList *AccessAttrs,
+ ParsingDeclarator &D,
+ const ParsedTemplateInfo &TemplateInfo,
+ const VirtSpecifiers& VS,
+ SourceLocation PureSpecLoc);
+ void ParseCXXNonStaticMemberInitializer(Decl *VarD);
+ void ParseLexedAttributes(ParsingClass &Class);
+ void ParseLexedAttributeList(LateParsedAttrList &LAs, Decl *D,
+ bool EnterScope, bool OnDefinition);
+ void ParseLexedAttribute(LateParsedAttribute &LA,
+ bool EnterScope, bool OnDefinition);
+ void ParseLexedMethodDeclarations(ParsingClass &Class);
+ void ParseLexedMethodDeclaration(LateParsedMethodDeclaration &LM);
+ void ParseLexedMethodDefs(ParsingClass &Class);
+ void ParseLexedMethodDef(LexedMethod &LM);
+ void ParseLexedMemberInitializers(ParsingClass &Class);
+ void ParseLexedMemberInitializer(LateParsedMemberInitializer &MI);
+ void ParseLexedObjCMethodDefs(LexedMethod &LM, bool parseMethod);
+ bool ConsumeAndStoreFunctionPrologue(CachedTokens &Toks);
+ bool ConsumeAndStoreInitializer(CachedTokens &Toks, CachedInitKind CIK);
+ bool ConsumeAndStoreConditional(CachedTokens &Toks);
+ 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 {
+ ParsedAttributesWithRange(AttributeFactory &factory)
+ : ParsedAttributes(factory) {}
+
+ SourceRange Range;
+ };
+
+ DeclGroupPtrTy ParseExternalDeclaration(ParsedAttributesWithRange &attrs,
+ ParsingDeclSpec *DS = nullptr);
+ bool isDeclarationAfterDeclarator();
+ bool isStartOfFunctionDefinition(const ParsingDeclarator &Declarator);
+ DeclGroupPtrTy ParseDeclarationOrFunctionDefinition(
+ ParsedAttributesWithRange &attrs,
+ ParsingDeclSpec *DS = nullptr,
+ AccessSpecifier AS = AS_none);
+ DeclGroupPtrTy ParseDeclOrFunctionDefInternal(ParsedAttributesWithRange &attrs,
+ ParsingDeclSpec &DS,
+ AccessSpecifier AS);
+
+ void SkipFunctionBody();
+ Decl *ParseFunctionDefinition(ParsingDeclarator &D,
+ const ParsedTemplateInfo &TemplateInfo = ParsedTemplateInfo(),
+ LateParsedAttrList *LateParsedAttrs = nullptr);
+ 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 = nullptr);
+ ExprResult ParseAsmStringLiteral();
+
+ // Objective-C External Declarations
+ void MaybeSkipAttributes(tok::ObjCKeywordKind Kind);
+ DeclGroupPtrTy ParseObjCAtDirectives();
+ DeclGroupPtrTy ParseObjCAtClassDeclaration(SourceLocation atLoc);
+ Decl *ParseObjCAtInterfaceDeclaration(SourceLocation AtLoc,
+ ParsedAttributes &prefixAttrs);
+ class ObjCTypeParamListScope;
+ ObjCTypeParamList *parseObjCTypeParamList();
+ ObjCTypeParamList *parseObjCTypeParamListOrProtocolRefs(
+ ObjCTypeParamListScope &Scope, SourceLocation &lAngleLoc,
+ SmallVectorImpl<IdentifierLocPair> &protocolIdents,
+ SourceLocation &rAngleLoc, bool mayBeProtocolList = true);
+
+ void HelperActionsForIvarDeclarations(Decl *interfaceDecl, SourceLocation atLoc,
+ BalancedDelimiterTracker &T,
+ SmallVectorImpl<Decl *> &AllIvarDecls,
+ bool RBraceMissing);
+ void ParseObjCClassInstanceVariables(Decl *interfaceDecl,
+ tok::ObjCKeywordKind visibility,
+ SourceLocation atLoc);
+ bool ParseObjCProtocolReferences(SmallVectorImpl<Decl *> &P,
+ SmallVectorImpl<SourceLocation> &PLocs,
+ bool WarnOnDeclarations,
+ bool ForObjCContainer,
+ SourceLocation &LAngleLoc,
+ SourceLocation &EndProtoLoc,
+ bool consumeLastToken);
+
+ /// Parse the first angle-bracket-delimited clause for an
+ /// Objective-C object or object pointer type, which may be either
+ /// type arguments or protocol qualifiers.
+ void parseObjCTypeArgsOrProtocolQualifiers(
+ ParsedType baseType,
+ SourceLocation &typeArgsLAngleLoc,
+ SmallVectorImpl<ParsedType> &typeArgs,
+ SourceLocation &typeArgsRAngleLoc,
+ SourceLocation &protocolLAngleLoc,
+ SmallVectorImpl<Decl *> &protocols,
+ SmallVectorImpl<SourceLocation> &protocolLocs,
+ SourceLocation &protocolRAngleLoc,
+ bool consumeLastToken,
+ bool warnOnIncompleteProtocols);
+
+ /// Parse either Objective-C type arguments or protocol qualifiers; if the
+ /// former, also parse protocol qualifiers afterward.
+ void parseObjCTypeArgsAndProtocolQualifiers(
+ ParsedType baseType,
+ SourceLocation &typeArgsLAngleLoc,
+ SmallVectorImpl<ParsedType> &typeArgs,
+ SourceLocation &typeArgsRAngleLoc,
+ SourceLocation &protocolLAngleLoc,
+ SmallVectorImpl<Decl *> &protocols,
+ SmallVectorImpl<SourceLocation> &protocolLocs,
+ SourceLocation &protocolRAngleLoc,
+ bool consumeLastToken);
+
+ /// Parse a protocol qualifier type such as '<NSCopying>', which is
+ /// an anachronistic way of writing 'id<NSCopying>'.
+ TypeResult parseObjCProtocolQualifierType(SourceLocation &rAngleLoc);
+
+ /// Parse Objective-C type arguments and protocol qualifiers, extending the
+ /// current type with the parsed result.
+ TypeResult parseObjCTypeArgsAndProtocolQualifiers(SourceLocation loc,
+ ParsedType type,
+ bool consumeLastToken,
+ SourceLocation &endLoc);
+
+ void ParseObjCInterfaceDeclList(tok::ObjCKeywordKind contextKey,
+ Decl *CDecl);
+ DeclGroupPtrTy ParseObjCAtProtocolDeclaration(SourceLocation atLoc,
+ ParsedAttributes &prefixAttrs);
+
+ struct ObjCImplParsingDataRAII {
+ Parser &P;
+ Decl *Dcl;
+ bool HasCFunction;
+ typedef SmallVector<LexedMethod*, 8> LateParsedObjCMethodContainer;
+ LateParsedObjCMethodContainer LateParsedObjCMethods;
+
+ ObjCImplParsingDataRAII(Parser &parser, Decl *D)
+ : P(parser), Dcl(D), HasCFunction(false) {
+ P.CurParsedObjCImpl = this;
+ Finished = false;
+ }
+ ~ObjCImplParsingDataRAII();
+
+ void finish(SourceRange AtEnd);
+ bool isFinished() const { return Finished; }
+
+ private:
+ bool Finished;
+ };
+ ObjCImplParsingDataRAII *CurParsedObjCImpl;
+ void StashAwayMethodOrFunctionBodyTokens(Decl *MDecl);
+
+ DeclGroupPtrTy ParseObjCAtImplementationDeclaration(SourceLocation AtLoc);
+ DeclGroupPtrTy 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_nonnull, objc_nullable, objc_null_unspecified,
+ objc_NumQuals
+ };
+ IdentifierInfo *ObjCTypeQuals[objc_NumQuals];
+
+ bool isTokIdentifier_in() const;
+
+ ParsedType ParseObjCTypeName(ObjCDeclSpec &DS, Declarator::TheContext Ctx,
+ ParsedAttributes *ParamAttrs);
+ void ParseObjCMethodRequirement();
+ Decl *ParseObjCMethodPrototype(
+ tok::ObjCKeywordKind MethodImplKind = tok::objc_not_keyword,
+ bool MethodDefinition = true);
+ Decl *ParseObjCMethodDecl(SourceLocation mLoc, tok::TokenKind mType,
+ tok::ObjCKeywordKind MethodImplKind = tok::objc_not_keyword,
+ bool MethodDefinition=true);
+ void ParseObjCPropertyAttribute(ObjCDeclSpec &DS);
+
+ Decl *ParseObjCMethodDefinition();
+
+public:
+ //===--------------------------------------------------------------------===//
+ // C99 6.5: Expressions.
+
+ /// TypeCastState - State whether an expression is or may be a type cast.
+ enum TypeCastState {
+ NotTypeCast = 0,
+ MaybeTypeCast,
+ IsTypeCast
+ };
+
+ ExprResult ParseExpression(TypeCastState isTypeCast = NotTypeCast);
+ ExprResult ParseConstantExpression(TypeCastState isTypeCast = NotTypeCast);
+ ExprResult ParseConstraintExpression();
+ // Expr that doesn't include commas.
+ ExprResult ParseAssignmentExpression(TypeCastState isTypeCast = NotTypeCast);
+
+ ExprResult ParseMSAsmIdentifier(llvm::SmallVectorImpl<Token> &LineToks,
+ unsigned &NumLineToksConsumed,
+ void *Info,
+ bool IsUnevaluated);
+
+private:
+ ExprResult ParseExpressionWithLeadingAt(SourceLocation AtLoc);
+
+ ExprResult ParseExpressionWithLeadingExtension(SourceLocation ExtLoc);
+
+ ExprResult ParseRHSOfBinaryExpression(ExprResult LHS,
+ prec::Level MinPrec);
+ ExprResult ParseCastExpression(bool isUnaryExpression,
+ bool isAddressOfOperand,
+ bool &NotCastExpr,
+ TypeCastState isTypeCast);
+ ExprResult ParseCastExpression(bool isUnaryExpression,
+ bool isAddressOfOperand = false,
+ TypeCastState isTypeCast = NotTypeCast);
+
+ /// Returns true if the next token cannot start an expression.
+ bool isNotExpressionStart();
+
+ /// 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 ParseUnaryExprOrTypeTraitExpression();
+ ExprResult ParseBuiltinPrimaryExpression();
+
+ ExprResult ParseExprAfterUnaryExprOrTypeTrait(const Token &OpTok,
+ bool &isCastExpr,
+ ParsedType &CastTy,
+ SourceRange &CastRange);
+
+ typedef SmallVector<Expr*, 20> ExprListTy;
+ typedef SmallVector<SourceLocation, 20> CommaLocsTy;
+
+ /// ParseExpressionList - Used for C/C++ (argument-)expression-list.
+ bool ParseExpressionList(SmallVectorImpl<Expr *> &Exprs,
+ SmallVectorImpl<SourceLocation> &CommaLocs,
+ std::function<void()> Completer = nullptr);
+
+ /// ParseSimpleExpressionList - A simple comma-separated list of expressions,
+ /// used for misc language extensions.
+ bool ParseSimpleExpressionList(SmallVectorImpl<Expr*> &Exprs,
+ SmallVectorImpl<SourceLocation> &CommaLocs);
+
+
+ /// 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,
+ bool isTypeCast,
+ ParsedType &CastTy,
+ SourceLocation &RParenLoc);
+
+ ExprResult ParseCXXAmbiguousParenExpression(
+ ParenParseOption &ExprType, ParsedType &CastTy,
+ BalancedDelimiterTracker &Tracker, ColonProtectionRAIIObject &ColonProt);
+ ExprResult ParseCompoundLiteralExpression(ParsedType Ty,
+ SourceLocation LParenLoc,
+ SourceLocation RParenLoc);
+
+ ExprResult ParseStringLiteralExpression(bool AllowUserDefinedLiteral = false);
+
+ ExprResult ParseGenericSelectionExpression();
+
+ ExprResult ParseObjCBoolLiteral();
+
+ ExprResult ParseFoldExpression(ExprResult LHS, BalancedDelimiterTracker &T);
+
+ //===--------------------------------------------------------------------===//
+ // C++ Expressions
+ ExprResult tryParseCXXIdExpression(CXXScopeSpec &SS, bool isAddressOfOperand,
+ Token &Replacement);
+ ExprResult ParseCXXIdExpression(bool isAddressOfOperand = false);
+
+ bool areTokensAdjacent(const Token &A, const Token &B);
+
+ void CheckForTemplateAndDigraph(Token &Next, ParsedType ObjectTypePtr,
+ bool EnteringContext, IdentifierInfo &II,
+ CXXScopeSpec &SS);
+
+ bool ParseOptionalCXXScopeSpecifier(CXXScopeSpec &SS,
+ ParsedType ObjectType,
+ bool EnteringContext,
+ bool *MayBePseudoDestructor = nullptr,
+ bool IsTypename = false,
+ IdentifierInfo **LastII = nullptr);
+
+ void CheckForLParenAfterColonColon();
+
+ //===--------------------------------------------------------------------===//
+ // C++0x 5.1.2: Lambda expressions
+
+ // [...] () -> type {...}
+ ExprResult ParseLambdaExpression();
+ ExprResult TryParseLambdaExpression();
+ Optional<unsigned> ParseLambdaIntroducer(LambdaIntroducer &Intro,
+ bool *SkippedInits = nullptr);
+ bool TryParseLambdaIntroducer(LambdaIntroducer &Intro);
+ ExprResult ParseLambdaExpressionAfterIntroducer(
+ LambdaIntroducer &Intro);
+
+ //===--------------------------------------------------------------------===//
+ // 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(Expr *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();
+
+ ExceptionSpecificationType tryParseExceptionSpecification(
+ bool Delayed,
+ SourceRange &SpecificationRange,
+ SmallVectorImpl<ParsedType> &DynamicExceptions,
+ SmallVectorImpl<SourceRange> &DynamicExceptionRanges,
+ ExprResult &NoexceptExpr,
+ CachedTokens *&ExceptionSpecTokens);
+
+ // EndLoc is filled with the location of the last token of the specification.
+ ExceptionSpecificationType ParseDynamicExceptionSpecification(
+ SourceRange &SpecificationRange,
+ SmallVectorImpl<ParsedType> &Exceptions,
+ SmallVectorImpl<SourceRange> &Ranges);
+
+ //===--------------------------------------------------------------------===//
+ // C++0x 8: Function declaration trailing-return-type
+ TypeResult ParseTrailingReturnType(SourceRange &Range);
+
+ //===--------------------------------------------------------------------===//
+ // C++ 2.13.5: C++ Boolean Literals
+ ExprResult ParseCXXBoolLiteral();
+
+ //===--------------------------------------------------------------------===//
+ // C++ 5.2.3: Explicit type conversion (functional notation)
+ ExprResult ParseCXXTypeConstructExpression(const DeclSpec &DS);
+
+ /// 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(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++ Coroutines
+
+ ExprResult ParseCoyieldExpression();
+
+ //===--------------------------------------------------------------------===//
+ // 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();
+ }
+ bool MayBeDesignationStart();
+ ExprResult ParseBraceInitializer();
+ ExprResult ParseInitializerWithPotentialDesignator();
+
+ //===--------------------------------------------------------------------===//
+ // clang Expressions
+
+ ExprResult ParseBlockLiteralExpression(); // ^{...}
+
+ //===--------------------------------------------------------------------===//
+ // Objective-C Expressions
+ ExprResult ParseObjCAtExpression(SourceLocation AtLocation);
+ ExprResult ParseObjCStringLiteral(SourceLocation AtLoc);
+ ExprResult ParseObjCCharacterLiteral(SourceLocation AtLoc);
+ ExprResult ParseObjCNumericLiteral(SourceLocation AtLoc);
+ ExprResult ParseObjCBooleanLiteral(SourceLocation AtLoc, bool ArgValue);
+ ExprResult ParseObjCArrayLiteral(SourceLocation AtLoc);
+ ExprResult ParseObjCDictionaryLiteral(SourceLocation AtLoc);
+ ExprResult ParseObjCBoxedExpr(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,
+ Expr *ReceiverExpr);
+ ExprResult ParseAssignmentExprWithObjCMessageExprStart(
+ SourceLocation LBracloc, SourceLocation SuperLoc,
+ ParsedType ReceiverType, Expr *ReceiverExpr);
+ bool ParseObjCXXMessageReceiver(bool &IsExpr, void *&TypeOrExpr);
+
+ //===--------------------------------------------------------------------===//
+ // C99 6.8: Statements and Blocks.
+
+ /// A SmallVector of statements, with stack size 32 (as that is the only one
+ /// used.)
+ typedef SmallVector<Stmt*, 32> StmtVector;
+ /// A SmallVector of expressions, with stack size 12 (the maximum used.)
+ typedef SmallVector<Expr*, 12> ExprVector;
+ /// A SmallVector of types.
+ typedef SmallVector<ParsedType, 12> TypeVector;
+
+ StmtResult ParseStatement(SourceLocation *TrailingElseLoc = nullptr);
+ StmtResult
+ ParseStatementOrDeclaration(StmtVector &Stmts, bool OnlyStatement,
+ SourceLocation *TrailingElseLoc = nullptr);
+ StmtResult ParseStatementOrDeclarationAfterAttributes(
+ StmtVector &Stmts,
+ bool OnlyStatement,
+ SourceLocation *TrailingElseLoc,
+ ParsedAttributesWithRange &Attrs);
+ StmtResult ParseExprStatement();
+ StmtResult ParseLabeledStatement(ParsedAttributesWithRange &attrs);
+ StmtResult ParseCaseStatement(bool MissingCase = false,
+ ExprResult Expr = ExprResult());
+ StmtResult ParseDefaultStatement();
+ StmtResult ParseCompoundStatement(bool isStmtExpr = false);
+ StmtResult ParseCompoundStatement(bool isStmtExpr,
+ unsigned ScopeFlags);
+ void ParseCompoundStatementLeadingPragmas();
+ StmtResult ParseCompoundStatementBody(bool isStmtExpr = false);
+ bool ParseParenExprOrCondition(ExprResult &ExprResult,
+ Decl *&DeclResult,
+ SourceLocation Loc,
+ bool ConvertToBoolean);
+ StmtResult ParseIfStatement(SourceLocation *TrailingElseLoc);
+ StmtResult ParseSwitchStatement(SourceLocation *TrailingElseLoc);
+ StmtResult ParseWhileStatement(SourceLocation *TrailingElseLoc);
+ StmtResult ParseDoStatement();
+ StmtResult ParseForStatement(SourceLocation *TrailingElseLoc);
+ StmtResult ParseGotoStatement();
+ StmtResult ParseContinueStatement();
+ StmtResult ParseBreakStatement();
+ StmtResult ParseReturnStatement();
+ StmtResult ParseAsmStatement(bool &msAsm);
+ StmtResult ParseMicrosoftAsmStatement(SourceLocation AsmLoc);
+ StmtResult ParsePragmaLoopHint(StmtVector &Stmts, bool OnlyStatement,
+ SourceLocation *TrailingElseLoc,
+ ParsedAttributesWithRange &Attrs);
+
+ /// \brief Describes the behavior that should be taken for an __if_exists
+ /// block.
+ enum IfExistsBehavior {
+ /// \brief Parse the block; this code is always used.
+ IEB_Parse,
+ /// \brief Skip the block entirely; this code is never used.
+ IEB_Skip,
+ /// \brief Parse the block as a dependent block, which may be used in
+ /// some template instantiations but not others.
+ IEB_Dependent
+ };
+
+ /// \brief Describes the condition of a Microsoft __if_exists or
+ /// __if_not_exists block.
+ struct IfExistsCondition {
+ /// \brief The location of the initial keyword.
+ SourceLocation KeywordLoc;
+ /// \brief Whether this is an __if_exists block (rather than an
+ /// __if_not_exists block).
+ bool IsIfExists;
+
+ /// \brief Nested-name-specifier preceding the name.
+ CXXScopeSpec SS;
+
+ /// \brief The name we're looking for.
+ UnqualifiedId Name;
+
+ /// \brief The behavior of this __if_exists or __if_not_exists block
+ /// should.
+ IfExistsBehavior Behavior;
+ };
+
+ bool ParseMicrosoftIfExistsCondition(IfExistsCondition& Result);
+ void ParseMicrosoftIfExistsStatement(StmtVector &Stmts);
+ void ParseMicrosoftIfExistsExternalDeclaration();
+ void ParseMicrosoftIfExistsClassDeclaration(DeclSpec::TST TagType,
+ AccessSpecifier& CurAS);
+ bool ParseMicrosoftIfExistsBraceInitializer(ExprVector &InitExprs,
+ bool &InitExprsOk);
+ bool ParseAsmOperandsOpt(SmallVectorImpl<IdentifierInfo *> &Names,
+ SmallVectorImpl<Expr *> &Constraints,
+ SmallVectorImpl<Expr *> &Exprs);
+
+ //===--------------------------------------------------------------------===//
+ // C++ 6: Statements and Blocks
+
+ StmtResult ParseCXXTryBlock();
+ StmtResult ParseCXXTryBlockCommon(SourceLocation TryLoc, bool FnTry = false);
+ StmtResult ParseCXXCatchBlock(bool FnCatch = false);
+
+ //===--------------------------------------------------------------------===//
+ // MS: SEH Statements and Blocks
+
+ StmtResult ParseSEHTryBlock();
+ StmtResult ParseSEHExceptBlock(SourceLocation Loc);
+ StmtResult ParseSEHFinallyBlock(SourceLocation Loc);
+ StmtResult ParseSEHLeaveStatement();
+
+ //===--------------------------------------------------------------------===//
+ // Objective-C Statements
+
+ StmtResult ParseObjCAtStatement(SourceLocation atLoc);
+ StmtResult ParseObjCTryStmt(SourceLocation atLoc);
+ StmtResult ParseObjCThrowStmt(SourceLocation atLoc);
+ StmtResult ParseObjCSynchronizedStmt(SourceLocation atLoc);
+ StmtResult ParseObjCAutoreleasePoolStmt(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_type_specifier, // C++ type-specifier-seq or C specifier-qualifier-list
+ DSC_trailing, // C++11 trailing-type-specifier in a trailing return type
+ DSC_alias_declaration, // C++11 type-specifier-seq in an alias-declaration
+ DSC_top_level, // top-level/namespace declaration context
+ DSC_template_type_arg, // template type argument context
+ DSC_objc_method_result, // ObjC method result context, enables 'instancetype'
+ DSC_condition // condition declaration context
+ };
+
+ /// Is this a context in which we are parsing just a type-specifier (or
+ /// trailing-type-specifier)?
+ static bool isTypeSpecifier(DeclSpecContext DSC) {
+ switch (DSC) {
+ case DSC_normal:
+ case DSC_class:
+ case DSC_top_level:
+ case DSC_objc_method_result:
+ case DSC_condition:
+ return false;
+
+ case DSC_template_type_arg:
+ case DSC_type_specifier:
+ case DSC_trailing:
+ case DSC_alias_declaration:
+ return true;
+ }
+ llvm_unreachable("Missing DeclSpecContext case");
+ }
+
+ /// Information on a C++0x for-range-initializer found while parsing a
+ /// declaration which turns out to be a for-range-declaration.
+ struct ForRangeInit {
+ SourceLocation ColonLoc;
+ ExprResult RangeExpr;
+
+ bool ParsedForRangeDecl() { return !ColonLoc.isInvalid(); }
+ };
+
+ DeclGroupPtrTy ParseDeclaration(unsigned Context, SourceLocation &DeclEnd,
+ ParsedAttributesWithRange &attrs);
+ DeclGroupPtrTy ParseSimpleDeclaration(unsigned Context,
+ SourceLocation &DeclEnd,
+ ParsedAttributesWithRange &attrs,
+ bool RequireSemi,
+ ForRangeInit *FRI = nullptr);
+ bool MightBeDeclarator(unsigned Context);
+ DeclGroupPtrTy ParseDeclGroup(ParsingDeclSpec &DS, unsigned Context,
+ SourceLocation *DeclEnd = nullptr,
+ ForRangeInit *FRI = nullptr);
+ Decl *ParseDeclarationAfterDeclarator(Declarator &D,
+ const ParsedTemplateInfo &TemplateInfo = ParsedTemplateInfo());
+ bool ParseAsmAttributesAfterDeclarator(Declarator &D);
+ Decl *ParseDeclarationAfterDeclaratorAndAttributes(
+ Declarator &D,
+ const ParsedTemplateInfo &TemplateInfo = ParsedTemplateInfo(),
+ ForRangeInit *FRI = nullptr);
+ Decl *ParseFunctionStatementBody(Decl *Decl, ParseScope &BodyScope);
+ Decl *ParseFunctionTryBlock(Decl *Decl, ParseScope &BodyScope);
+
+ /// \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 trySkippingFunctionBody();
+
+ bool ParseImplicitInt(DeclSpec &DS, CXXScopeSpec *SS,
+ const ParsedTemplateInfo &TemplateInfo,
+ AccessSpecifier AS, DeclSpecContext DSC,
+ ParsedAttributesWithRange &Attrs);
+ DeclSpecContext getDeclSpecContextFromDeclaratorContext(unsigned Context);
+ void ParseDeclarationSpecifiers(DeclSpec &DS,
+ const ParsedTemplateInfo &TemplateInfo = ParsedTemplateInfo(),
+ AccessSpecifier AS = AS_none,
+ DeclSpecContext DSC = DSC_normal,
+ LateParsedAttrList *LateAttrs = nullptr);
+ bool DiagnoseMissingSemiAfterTagDefinition(DeclSpec &DS, AccessSpecifier AS,
+ DeclSpecContext DSContext,
+ LateParsedAttrList *LateAttrs = nullptr);
+
+ void ParseSpecifierQualifierList(DeclSpec &DS, AccessSpecifier AS = AS_none,
+ DeclSpecContext DSC = DSC_normal);
+
+ void ParseObjCTypeQualifierList(ObjCDeclSpec &DS,
+ Declarator::TheContext Context);
+
+ void ParseEnumSpecifier(SourceLocation TagLoc, DeclSpec &DS,
+ const ParsedTemplateInfo &TemplateInfo,
+ AccessSpecifier AS, DeclSpecContext DSC);
+ void ParseEnumBody(SourceLocation StartLoc, Decl *TagDecl);
+ void ParseStructUnionBody(SourceLocation StartLoc, unsigned TagType,
+ Decl *TagDecl);
+
+ void ParseStructDeclaration(
+ ParsingDeclSpec &DS,
+ llvm::function_ref<void(ParsingFieldDeclarator &)> FieldsCallback);
+
+ 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;
+
+ /// \brief Return true if we know that we are definitely looking at a
+ /// decl-specifier, and isn't part of an expression such as a function-style
+ /// cast. Return false if it's no a decl-specifier, or we're not sure.
+ bool isKnownToBeDeclarationSpecifier() {
+ if (getLangOpts().CPlusPlus)
+ return isCXXDeclarationSpecifier() == TPResult::True;
+ return isDeclarationSpecifier(true);
+ }
+
+ /// isDeclarationStatement - Disambiguates between a declaration or an
+ /// expression statement, when parsing function bodies.
+ /// Returns true for declaration, false for expression.
+ bool isDeclarationStatement() {
+ if (getLangOpts().CPlusPlus)
+ return isCXXDeclarationStatement();
+ return isDeclarationSpecifier(true);
+ }
+
+ /// isForInitDeclaration - Disambiguates between a declaration or an
+ /// expression in the context of the C 'clause-1' or the C++
+ // 'for-init-statement' part of a 'for' statement.
+ /// Returns true for declaration, false for expression.
+ bool isForInitDeclaration() {
+ if (getLangOpts().CPlusPlus)
+ return isCXXSimpleDeclaration(/*AllowForRangeDecl=*/true);
+ return isDeclarationSpecifier(true);
+ }
+
+ /// \brief Determine whether this is a C++1z for-range-identifier.
+ bool isForRangeIdentifier();
+
+ /// \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(bool Unqualified);
+
+ /// \brief Specifies the context in which type-id/expression
+ /// disambiguation will occur.
+ enum TentativeCXXTypeIdContext {
+ TypeIdInParens,
+ TypeIdUnambiguous,
+ 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 (getLangOpts().CPlusPlus)
+ return isCXXTypeId(TypeIdInParens, isAmbiguous);
+ isAmbiguous = false;
+ return isTypeSpecifierQualifier();
+ }
+ bool isTypeIdInParens() {
+ bool isAmbiguous;
+ return isTypeIdInParens(isAmbiguous);
+ }
+
+ /// \brief Checks if the current tokens form type-id or expression.
+ /// It is similar to isTypeIdInParens but does not suppose that type-id
+ /// is in parenthesis.
+ bool isTypeIdUnambiguously() {
+ bool IsAmbiguous;
+ if (getLangOpts().CPlusPlus)
+ return isCXXTypeId(TypeIdUnambiguous, IsAmbiguous);
+ return isTypeSpecifierQualifier();
+ }
+
+ /// 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(bool AllowForRangeDecl);
+
+ /// 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. Sets 'IsAmbiguous' to true to indicate that this declaration
+ /// might be a 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.
+ bool isCXXFunctionDeclarator(bool *IsAmbiguous = nullptr);
+
+ /// 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.
+ enum class TPResult {
+ True, False, Ambiguous, Error
+ };
+
+ /// \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. If it could be a braced C++11 function-style cast, returns
+ /// BracedCastResult.
+ /// Doesn't consume tokens.
+ TPResult
+ isCXXDeclarationSpecifier(TPResult BracedCastResult = TPResult::False,
+ bool *HasMissingTypename = nullptr);
+
+ /// Given that isCXXDeclarationSpecifier returns \c TPResult::True or
+ /// \c TPResult::Ambiguous, determine whether the decl-specifier would be
+ /// a type-specifier other than a cv-qualifier.
+ bool isCXXDeclarationSpecifierAType();
+
+ /// \brief Determine whether an identifier has been tentatively declared as a
+ /// non-type. Such tentative declarations should not be found to name a type
+ /// during a tentative parse, but also should not be annotated as a non-type.
+ bool isTentativelyDeclared(IdentifierInfo *II);
+
+ // "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 TryParseSimpleDeclaration(bool AllowForRangeDecl);
+ TPResult TryParseTypeofSpecifier();
+ TPResult TryParseProtocolQualifiers();
+ TPResult TryParsePtrOperatorSeq();
+ TPResult TryParseOperatorId();
+ TPResult TryParseInitDeclaratorList();
+ TPResult TryParseDeclarator(bool mayBeAbstract, bool mayHaveIdentifier=true);
+ TPResult
+ TryParseParameterDeclarationClause(bool *InvalidAsDeclaration = nullptr,
+ bool VersusTemplateArg = false);
+ TPResult TryParseFunctionDeclarator();
+ TPResult TryParseBracketDeclarator();
+ TPResult TryConsumeDeclarationSpecifier();
+
+public:
+ TypeResult ParseTypeName(SourceRange *Range = nullptr,
+ Declarator::TheContext Context
+ = Declarator::TypeNameContext,
+ AccessSpecifier AS = AS_none,
+ Decl **OwnedType = nullptr,
+ ParsedAttributes *Attrs = nullptr);
+
+private:
+ void ParseBlockId(SourceLocation CaretLoc);
+
+ // Check for the start of a C++11 attribute-specifier-seq in a context where
+ // an attribute is not allowed.
+ bool CheckProhibitedCXX11Attribute() {
+ assert(Tok.is(tok::l_square));
+ if (!getLangOpts().CPlusPlus11 || NextToken().isNot(tok::l_square))
+ return false;
+ return DiagnoseProhibitedCXX11Attribute();
+ }
+ bool DiagnoseProhibitedCXX11Attribute();
+ void CheckMisplacedCXX11Attribute(ParsedAttributesWithRange &Attrs,
+ SourceLocation CorrectLocation) {
+ if (!getLangOpts().CPlusPlus11)
+ return;
+ if ((Tok.isNot(tok::l_square) || NextToken().isNot(tok::l_square)) &&
+ Tok.isNot(tok::kw_alignas))
+ return;
+ DiagnoseMisplacedCXX11Attribute(Attrs, CorrectLocation);
+ }
+ void DiagnoseMisplacedCXX11Attribute(ParsedAttributesWithRange &Attrs,
+ SourceLocation CorrectLocation);
+
+ void handleDeclspecAlignBeforeClassKey(ParsedAttributesWithRange &Attrs,
+ DeclSpec &DS, Sema::TagUseKind TUK);
+
+ void ProhibitAttributes(ParsedAttributesWithRange &attrs) {
+ if (!attrs.Range.isValid()) return;
+ DiagnoseProhibitedAttributes(attrs);
+ attrs.clear();
+ }
+ void DiagnoseProhibitedAttributes(ParsedAttributesWithRange &attrs);
+
+ // Forbid C++11 attributes that appear on certain syntactic
+ // locations which standard permits but we don't supported yet,
+ // for example, attributes appertain to decl specifiers.
+ void ProhibitCXX11Attributes(ParsedAttributesWithRange &attrs);
+
+ /// \brief Skip C++11 attributes and return the end location of the last one.
+ /// \returns SourceLocation() if there are no attributes.
+ SourceLocation SkipCXX11Attributes();
+
+ /// \brief Diagnose and skip C++11 attributes that appear in syntactic
+ /// locations where attributes are not allowed.
+ void DiagnoseAndSkipCXX11Attributes();
+
+ /// \brief Parses syntax-generic attribute arguments for attributes which are
+ /// known to the implementation, and adds them to the given ParsedAttributes
+ /// list with the given attribute syntax. Returns the number of arguments
+ /// parsed for the attribute.
+ unsigned
+ ParseAttributeArgsCommon(IdentifierInfo *AttrName, SourceLocation AttrNameLoc,
+ ParsedAttributes &Attrs, SourceLocation *EndLoc,
+ IdentifierInfo *ScopeName, SourceLocation ScopeLoc,
+ AttributeList::Syntax Syntax);
+
+ void MaybeParseGNUAttributes(Declarator &D,
+ LateParsedAttrList *LateAttrs = nullptr) {
+ if (Tok.is(tok::kw___attribute)) {
+ ParsedAttributes attrs(AttrFactory);
+ SourceLocation endLoc;
+ ParseGNUAttributes(attrs, &endLoc, LateAttrs, &D);
+ D.takeAttributes(attrs, endLoc);
+ }
+ }
+ void MaybeParseGNUAttributes(ParsedAttributes &attrs,
+ SourceLocation *endLoc = nullptr,
+ LateParsedAttrList *LateAttrs = nullptr) {
+ if (Tok.is(tok::kw___attribute))
+ ParseGNUAttributes(attrs, endLoc, LateAttrs);
+ }
+ void ParseGNUAttributes(ParsedAttributes &attrs,
+ SourceLocation *endLoc = nullptr,
+ LateParsedAttrList *LateAttrs = nullptr,
+ Declarator *D = nullptr);
+ void ParseGNUAttributeArgs(IdentifierInfo *AttrName,
+ SourceLocation AttrNameLoc,
+ ParsedAttributes &Attrs,
+ SourceLocation *EndLoc,
+ IdentifierInfo *ScopeName,
+ SourceLocation ScopeLoc,
+ AttributeList::Syntax Syntax,
+ Declarator *D);
+ IdentifierLoc *ParseIdentifierLoc();
+
+ void MaybeParseCXX11Attributes(Declarator &D) {
+ if (getLangOpts().CPlusPlus11 && isCXX11AttributeSpecifier()) {
+ ParsedAttributesWithRange attrs(AttrFactory);
+ SourceLocation endLoc;
+ ParseCXX11Attributes(attrs, &endLoc);
+ D.takeAttributes(attrs, endLoc);
+ }
+ }
+ void MaybeParseCXX11Attributes(ParsedAttributes &attrs,
+ SourceLocation *endLoc = nullptr) {
+ if (getLangOpts().CPlusPlus11 && isCXX11AttributeSpecifier()) {
+ ParsedAttributesWithRange attrsWithRange(AttrFactory);
+ ParseCXX11Attributes(attrsWithRange, endLoc);
+ attrs.takeAllFrom(attrsWithRange);
+ }
+ }
+ void MaybeParseCXX11Attributes(ParsedAttributesWithRange &attrs,
+ SourceLocation *endLoc = nullptr,
+ bool OuterMightBeMessageSend = false) {
+ if (getLangOpts().CPlusPlus11 &&
+ isCXX11AttributeSpecifier(false, OuterMightBeMessageSend))
+ ParseCXX11Attributes(attrs, endLoc);
+ }
+
+ void ParseCXX11AttributeSpecifier(ParsedAttributes &attrs,
+ SourceLocation *EndLoc = nullptr);
+ void ParseCXX11Attributes(ParsedAttributesWithRange &attrs,
+ SourceLocation *EndLoc = nullptr);
+ /// \brief Parses a C++-style attribute argument list. Returns true if this
+ /// results in adding an attribute to the ParsedAttributes list.
+ bool ParseCXX11AttributeArgs(IdentifierInfo *AttrName,
+ SourceLocation AttrNameLoc,
+ ParsedAttributes &Attrs, SourceLocation *EndLoc,
+ IdentifierInfo *ScopeName,
+ SourceLocation ScopeLoc);
+
+ IdentifierInfo *TryParseCXX11AttributeIdentifier(SourceLocation &Loc);
+
+ void MaybeParseMicrosoftAttributes(ParsedAttributes &attrs,
+ SourceLocation *endLoc = nullptr) {
+ if (getLangOpts().MicrosoftExt && Tok.is(tok::l_square))
+ ParseMicrosoftAttributes(attrs, endLoc);
+ }
+ void ParseMicrosoftAttributes(ParsedAttributes &attrs,
+ SourceLocation *endLoc = nullptr);
+ void MaybeParseMicrosoftDeclSpecs(ParsedAttributes &Attrs,
+ SourceLocation *End = nullptr) {
+ const auto &LO = getLangOpts();
+ if (LO.DeclSpecKeyword && Tok.is(tok::kw___declspec))
+ ParseMicrosoftDeclSpecs(Attrs, End);
+ }
+ void ParseMicrosoftDeclSpecs(ParsedAttributes &Attrs,
+ SourceLocation *End = nullptr);
+ bool ParseMicrosoftDeclSpecArgs(IdentifierInfo *AttrName,
+ SourceLocation AttrNameLoc,
+ ParsedAttributes &Attrs);
+ void ParseMicrosoftTypeAttributes(ParsedAttributes &attrs);
+ void DiagnoseAndSkipExtendedMicrosoftTypeAttributes();
+ SourceLocation SkipExtendedMicrosoftTypeAttributes();
+ void ParseMicrosoftInheritanceClassAttributes(ParsedAttributes &attrs);
+ void ParseBorlandTypeAttributes(ParsedAttributes &attrs);
+ void ParseOpenCLAttributes(ParsedAttributes &attrs);
+ void ParseOpenCLQualifiers(ParsedAttributes &Attrs);
+ void ParseNullabilityTypeSpecifiers(ParsedAttributes &attrs);
+
+ VersionTuple ParseVersionTuple(SourceRange &Range);
+ void ParseAvailabilityAttribute(IdentifierInfo &Availability,
+ SourceLocation AvailabilityLoc,
+ ParsedAttributes &attrs,
+ SourceLocation *endLoc,
+ IdentifierInfo *ScopeName,
+ SourceLocation ScopeLoc,
+ AttributeList::Syntax Syntax);
+
+ void ParseObjCBridgeRelatedAttribute(IdentifierInfo &ObjCBridgeRelated,
+ SourceLocation ObjCBridgeRelatedLoc,
+ ParsedAttributes &attrs,
+ SourceLocation *endLoc,
+ IdentifierInfo *ScopeName,
+ SourceLocation ScopeLoc,
+ AttributeList::Syntax Syntax);
+
+ void ParseTypeTagForDatatypeAttribute(IdentifierInfo &AttrName,
+ SourceLocation AttrNameLoc,
+ ParsedAttributes &Attrs,
+ SourceLocation *EndLoc,
+ IdentifierInfo *ScopeName,
+ SourceLocation ScopeLoc,
+ AttributeList::Syntax Syntax);
+
+ void ParseAttributeWithTypeArg(IdentifierInfo &AttrName,
+ SourceLocation AttrNameLoc,
+ ParsedAttributes &Attrs,
+ SourceLocation *EndLoc,
+ IdentifierInfo *ScopeName,
+ SourceLocation ScopeLoc,
+ AttributeList::Syntax Syntax);
+
+ void ParseTypeofSpecifier(DeclSpec &DS);
+ SourceLocation ParseDecltypeSpecifier(DeclSpec &DS);
+ void AnnotateExistingDecltypeSpecifier(const DeclSpec &DS,
+ SourceLocation StartLoc,
+ SourceLocation EndLoc);
+ void ParseUnderlyingTypeSpecifier(DeclSpec &DS);
+ void ParseAtomicSpecifier(DeclSpec &DS);
+
+ ExprResult ParseAlignArgument(SourceLocation Start,
+ SourceLocation &EllipsisLoc);
+ void ParseAlignmentSpecifier(ParsedAttributes &Attrs,
+ SourceLocation *endLoc = nullptr);
+
+ VirtSpecifiers::Specifier isCXX11VirtSpecifier(const Token &Tok) const;
+ VirtSpecifiers::Specifier isCXX11VirtSpecifier() const {
+ return isCXX11VirtSpecifier(Tok);
+ }
+ void ParseOptionalCXX11VirtSpecifierSeq(VirtSpecifiers &VS, bool IsInterface,
+ SourceLocation FriendLoc);
+
+ bool isCXX11FinalKeyword() const;
+
+ /// 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);
+
+ enum AttrRequirements {
+ AR_NoAttributesParsed = 0, ///< No attributes are diagnosed.
+ AR_GNUAttributesParsedAndRejected = 1 << 0, ///< Diagnose GNU attributes.
+ AR_GNUAttributesParsed = 1 << 1,
+ AR_CXX11AttributesParsed = 1 << 2,
+ AR_DeclspecAttributesParsed = 1 << 3,
+ AR_AllAttributesParsed = AR_GNUAttributesParsed |
+ AR_CXX11AttributesParsed |
+ AR_DeclspecAttributesParsed,
+ AR_VendorAttributesParsed = AR_GNUAttributesParsed |
+ AR_DeclspecAttributesParsed
+ };
+
+ void ParseTypeQualifierListOpt(DeclSpec &DS,
+ unsigned AttrReqs = AR_AllAttributesParsed,
+ bool AtomicAllowed = true,
+ bool IdentifierRequired = false);
+ void ParseDirectDeclarator(Declarator &D);
+ void ParseParenDeclarator(Declarator &D);
+ void ParseFunctionDeclarator(Declarator &D,
+ ParsedAttributes &attrs,
+ BalancedDelimiterTracker &Tracker,
+ bool IsAmbiguous,
+ bool RequiresArg = false);
+ bool ParseRefQualifier(bool &RefQualifierIsLValueRef,
+ SourceLocation &RefQualifierLoc);
+ bool isFunctionDeclaratorIdentifierList();
+ void ParseFunctionDeclaratorIdentifierList(
+ Declarator &D,
+ SmallVectorImpl<DeclaratorChunk::ParamInfo> &ParamInfo);
+ void ParseParameterDeclarationClause(
+ Declarator &D,
+ ParsedAttributes &attrs,
+ SmallVectorImpl<DeclaratorChunk::ParamInfo> &ParamInfo,
+ SourceLocation &EllipsisLoc);
+ void ParseBracketDeclarator(Declarator &D);
+ void ParseMisplacedBracketDeclarator(Declarator &D);
+
+ //===--------------------------------------------------------------------===//
+ // C++ 7: Declarations [dcl.dcl]
+
+ /// The kind of attribute specifier we have found.
+ enum CXX11AttributeKind {
+ /// This is not an attribute specifier.
+ CAK_NotAttributeSpecifier,
+ /// This should be treated as an attribute-specifier.
+ CAK_AttributeSpecifier,
+ /// The next tokens are '[[', but this is not an attribute-specifier. This
+ /// is ill-formed by C++11 [dcl.attr.grammar]p6.
+ CAK_InvalidAttributeSpecifier
+ };
+ CXX11AttributeKind
+ isCXX11AttributeSpecifier(bool Disambiguate = false,
+ bool OuterMightBeMessageSend = false);
+
+ void DiagnoseUnexpectedNamespace(NamedDecl *Context);
+
+ DeclGroupPtrTy ParseNamespace(unsigned Context, SourceLocation &DeclEnd,
+ SourceLocation InlineLoc = SourceLocation());
+ void ParseInnerNamespace(std::vector<SourceLocation>& IdentLoc,
+ std::vector<IdentifierInfo*>& Ident,
+ std::vector<SourceLocation>& NamespaceLoc,
+ unsigned int index, SourceLocation& InlineLoc,
+ ParsedAttributes& attrs,
+ BalancedDelimiterTracker &Tracker);
+ Decl *ParseLinkage(ParsingDeclSpec &DS, unsigned Context);
+ Decl *ParseUsingDirectiveOrDeclaration(unsigned Context,
+ const ParsedTemplateInfo &TemplateInfo,
+ SourceLocation &DeclEnd,
+ ParsedAttributesWithRange &attrs,
+ Decl **OwnedType = nullptr);
+ 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 **OwnedType = nullptr);
+ Decl *ParseStaticAssertDeclaration(SourceLocation &DeclEnd);
+ Decl *ParseNamespaceAlias(SourceLocation NamespaceLoc,
+ SourceLocation AliasLoc, IdentifierInfo *Alias,
+ SourceLocation &DeclEnd);
+
+ //===--------------------------------------------------------------------===//
+ // C++ 9: classes [class] and C structs/unions.
+ bool isValidAfterTypeSpecifier(bool CouldBeBitfield);
+ void ParseClassSpecifier(tok::TokenKind TagTokKind, SourceLocation TagLoc,
+ DeclSpec &DS, const ParsedTemplateInfo &TemplateInfo,
+ AccessSpecifier AS, bool EnteringContext,
+ DeclSpecContext DSC,
+ ParsedAttributesWithRange &Attributes);
+ void SkipCXXMemberSpecification(SourceLocation StartLoc,
+ SourceLocation AttrFixitLoc,
+ unsigned TagType,
+ Decl *TagDecl);
+ void ParseCXXMemberSpecification(SourceLocation StartLoc,
+ SourceLocation AttrFixitLoc,
+ ParsedAttributesWithRange &Attrs,
+ unsigned TagType,
+ Decl *TagDecl);
+ ExprResult ParseCXXMemberInitializer(Decl *D, bool IsFunction,
+ SourceLocation &EqualLoc);
+ bool ParseCXXMemberDeclaratorBeforeInitializer(Declarator &DeclaratorInfo,
+ VirtSpecifiers &VS,
+ ExprResult &BitfieldSize,
+ LateParsedAttrList &LateAttrs);
+ void MaybeParseAndDiagnoseDeclSpecAfterCXX11VirtSpecifierSeq(Declarator &D,
+ VirtSpecifiers &VS);
+ DeclGroupPtrTy ParseCXXClassMemberDeclaration(
+ AccessSpecifier AS, AttributeList *Attr,
+ const ParsedTemplateInfo &TemplateInfo = ParsedTemplateInfo(),
+ ParsingDeclRAIIObject *DiagsFromTParams = nullptr);
+ DeclGroupPtrTy ParseCXXClassMemberDeclarationWithPragmas(
+ AccessSpecifier &AS, ParsedAttributesWithRange &AccessAttrs,
+ DeclSpec::TST TagType, Decl *TagDecl);
+ void ParseConstructorInitializer(Decl *ConstructorDecl);
+ MemInitResult ParseMemInitializer(Decl *ConstructorDecl);
+ void HandleMemberFunctionDeclDelays(Declarator& DeclaratorInfo,
+ Decl *ThisDecl);
+
+ //===--------------------------------------------------------------------===//
+ // C++ 10: Derived classes [class.derived]
+ TypeResult ParseBaseTypeSpecifier(SourceLocation &BaseLoc,
+ SourceLocation &EndLocation);
+ void ParseBaseClause(Decl *ClassDecl);
+ BaseResult ParseBaseSpecifier(Decl *ClassDecl);
+ AccessSpecifier getAccessSpecifierIfPresent() const;
+
+ bool ParseUnqualifiedIdTemplateId(CXXScopeSpec &SS,
+ SourceLocation TemplateKWLoc,
+ IdentifierInfo *Name,
+ SourceLocation NameLoc,
+ bool EnteringContext,
+ ParsedType ObjectType,
+ UnqualifiedId &Id,
+ bool AssumeTemplateId);
+ bool ParseUnqualifiedIdOperator(CXXScopeSpec &SS, bool EnteringContext,
+ ParsedType ObjectType,
+ UnqualifiedId &Result);
+
+ //===--------------------------------------------------------------------===//
+ // OpenMP: Directives and clauses.
+ /// \brief Parses declarative OpenMP directives.
+ DeclGroupPtrTy ParseOpenMPDeclarativeDirective();
+ /// \brief Parses simple list of variables.
+ ///
+ /// \param Kind Kind of the directive.
+ /// \param [out] VarList List of referenced variables.
+ /// \param AllowScopeSpecifier true, if the variables can have fully
+ /// qualified names.
+ ///
+ bool ParseOpenMPSimpleVarList(OpenMPDirectiveKind Kind,
+ SmallVectorImpl<Expr *> &VarList,
+ bool AllowScopeSpecifier);
+ /// \brief Parses declarative or executable directive.
+ ///
+ /// \param StandAloneAllowed true if allowed stand-alone directives,
+ /// false - otherwise
+ ///
+ StmtResult
+ ParseOpenMPDeclarativeOrExecutableDirective(bool StandAloneAllowed);
+ /// \brief Parses clause of kind \a CKind for directive of a kind \a Kind.
+ ///
+ /// \param DKind Kind of current directive.
+ /// \param CKind Kind of current clause.
+ /// \param FirstClause true, if this is the first clause of a kind \a CKind
+ /// in current directive.
+ ///
+ OMPClause *ParseOpenMPClause(OpenMPDirectiveKind DKind,
+ OpenMPClauseKind CKind, bool FirstClause);
+ /// \brief Parses clause with a single expression of a kind \a Kind.
+ ///
+ /// \param Kind Kind of current clause.
+ ///
+ OMPClause *ParseOpenMPSingleExprClause(OpenMPClauseKind Kind);
+ /// \brief Parses simple clause of a kind \a Kind.
+ ///
+ /// \param Kind Kind of current clause.
+ ///
+ OMPClause *ParseOpenMPSimpleClause(OpenMPClauseKind Kind);
+ /// \brief Parses clause with a single expression and an additional argument
+ /// of a kind \a Kind.
+ ///
+ /// \param Kind Kind of current clause.
+ ///
+ OMPClause *ParseOpenMPSingleExprWithArgClause(OpenMPClauseKind Kind);
+ /// \brief Parses clause without any additional arguments.
+ ///
+ /// \param Kind Kind of current clause.
+ ///
+ OMPClause *ParseOpenMPClause(OpenMPClauseKind Kind);
+ /// \brief Parses clause with the list of variables of a kind \a Kind.
+ ///
+ /// \param Kind Kind of current clause.
+ ///
+ OMPClause *ParseOpenMPVarListClause(OpenMPDirectiveKind DKind,
+ OpenMPClauseKind Kind);
+
+public:
+ bool ParseUnqualifiedId(CXXScopeSpec &SS, bool EnteringContext,
+ bool AllowDestructorName,
+ bool AllowConstructorName,
+ ParsedType ObjectType,
+ SourceLocation& TemplateKWLoc,
+ UnqualifiedId &Result);
+
+private:
+ //===--------------------------------------------------------------------===//
+ // C++ 14: Templates [temp]
+
+ // C++ 14.1: Template Parameters [temp.param]
+ Decl *ParseDeclarationStartingWithTemplate(unsigned Context,
+ SourceLocation &DeclEnd,
+ AccessSpecifier AS = AS_none,
+ AttributeList *AccessAttrs = nullptr);
+ Decl *ParseTemplateDeclarationOrSpecialization(unsigned Context,
+ SourceLocation &DeclEnd,
+ AccessSpecifier AS,
+ AttributeList *AccessAttrs);
+ Decl *ParseSingleDeclarationAfterTemplate(
+ unsigned Context,
+ const ParsedTemplateInfo &TemplateInfo,
+ ParsingDeclRAIIObject &DiagsFromParams,
+ SourceLocation &DeclEnd,
+ AccessSpecifier AS=AS_none,
+ AttributeList *AccessAttrs = nullptr);
+ bool ParseTemplateParameters(unsigned Depth,
+ SmallVectorImpl<Decl*> &TemplateParams,
+ SourceLocation &LAngleLoc,
+ SourceLocation &RAngleLoc);
+ bool ParseTemplateParameterList(unsigned Depth,
+ 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);
+ void DiagnoseMisplacedEllipsis(SourceLocation EllipsisLoc,
+ SourceLocation CorrectLoc,
+ bool AlreadyHasEllipsis,
+ bool IdentifierHasName);
+ void DiagnoseMisplacedEllipsisInDeclarator(SourceLocation EllipsisLoc,
+ Declarator &D);
+ // C++ 14.3: Template arguments [temp.arg]
+ typedef SmallVector<ParsedTemplateArgument, 16> TemplateArgList;
+
+ bool ParseGreaterThanInTemplateList(SourceLocation &RAngleLoc,
+ bool ConsumeLastToken,
+ bool ObjCGenericList);
+ bool ParseTemplateIdAfterTemplateName(TemplateTy Template,
+ SourceLocation TemplateNameLoc,
+ const CXXScopeSpec &SS,
+ bool ConsumeLastToken,
+ SourceLocation &LAngleLoc,
+ TemplateArgList &TemplateArgs,
+ SourceLocation &RAngleLoc);
+
+ bool AnnotateTemplateIdToken(TemplateTy Template, TemplateNameKind TNK,
+ CXXScopeSpec &SS,
+ SourceLocation TemplateKWLoc,
+ UnqualifiedId &TemplateName,
+ bool AllowTypeAnnotation = true);
+ void AnnotateTemplateIdTokenAsType();
+ bool IsTemplateArgumentList(unsigned Skip = 0);
+ bool ParseTemplateArgumentList(TemplateArgList &TemplateArgs);
+ ParsedTemplateArgument ParseTemplateTemplateArgument();
+ ParsedTemplateArgument ParseTemplateArgument();
+ Decl *ParseExplicitInstantiation(unsigned Context,
+ SourceLocation ExternLoc,
+ SourceLocation TemplateLoc,
+ SourceLocation &DeclEnd,
+ AccessSpecifier AS = AS_none);
+
+ //===--------------------------------------------------------------------===//
+ // Modules
+ DeclGroupPtrTy ParseModuleImport(SourceLocation AtLoc);
+ bool parseMisplacedModuleImport();
+ bool tryParseMisplacedModuleImport() {
+ tok::TokenKind Kind = Tok.getKind();
+ if (Kind == tok::annot_module_begin || Kind == tok::annot_module_end ||
+ Kind == tok::annot_module_include)
+ return parseMisplacedModuleImport();
+ return false;
+ }
+
+ //===--------------------------------------------------------------------===//
+ // C++11/G++: Type Traits [Type-Traits.html in the GCC manual]
+ ExprResult ParseTypeTrait();
+
+ //===--------------------------------------------------------------------===//
+ // Embarcadero: Arary and Expression Traits
+ ExprResult ParseArrayTypeTrait();
+ ExprResult ParseExpressionTrait();
+
+ //===--------------------------------------------------------------------===//
+ // Preprocessor code-completion pass-through
+ void CodeCompleteDirective(bool InConditional) override;
+ void CodeCompleteInConditionalExclusion() override;
+ void CodeCompleteMacroName(bool IsDefinition) override;
+ void CodeCompletePreprocessorExpression() override;
+ void CodeCompleteMacroArgument(IdentifierInfo *Macro, MacroInfo *MacroInfo,
+ unsigned ArgumentIndex) override;
+ void CodeCompleteNaturalLanguage() override;
+};
+
+} // end namespace clang
+
+#endif
diff --git a/contrib/llvm/tools/clang/include/clang/Rewrite/Core/DeltaTree.h b/contrib/llvm/tools/clang/include/clang/Rewrite/Core/DeltaTree.h
new file mode 100644
index 0000000..fbffb38
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Rewrite/Core/DeltaTree.h
@@ -0,0 +1,50 @@
+//===--- 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 LLVM_CLANG_REWRITE_CORE_DELTATREE_H
+#define LLVM_CLANG_REWRITE_CORE_DELTATREE_H
+
+#include "llvm/Support/Compiler.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 &) = delete;
+ 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/Core/HTMLRewrite.h b/contrib/llvm/tools/clang/include/clang/Rewrite/Core/HTMLRewrite.h
new file mode 100644
index 0000000..dafdf51
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Rewrite/Core/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_REWRITE_CORE_HTMLREWRITE_H
+#define LLVM_CLANG_REWRITE_CORE_HTMLREWRITE_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(StringRef s,
+ bool EscapeSpaces = false, bool ReplaceTabs = false);
+
+ void AddLineNumbers(Rewriter& R, FileID FID);
+
+ void AddHeaderFooterInternalBuiltinCSS(Rewriter& R, FileID FID,
+ const char *title = nullptr);
+
+ /// 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/Core/RewriteBuffer.h b/contrib/llvm/tools/clang/include/clang/Rewrite/Core/RewriteBuffer.h
new file mode 100644
index 0000000..d69c69b
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Rewrite/Core/RewriteBuffer.h
@@ -0,0 +1,117 @@
+//===--- RewriteBuffer.h - Buffer rewriting 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_REWRITE_CORE_REWRITEBUFFER_H
+#define LLVM_CLANG_REWRITE_CORE_REWRITEBUFFER_H
+
+#include "clang/Basic/LLVM.h"
+#include "clang/Rewrite/Core/DeltaTree.h"
+#include "clang/Rewrite/Core/RewriteRope.h"
+#include "llvm/ADT/StringRef.h"
+
+namespace clang {
+ class Rewriter;
+
+/// 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;
+ RewriteRope Buffer;
+public:
+ typedef RewriteRope::const_iterator iterator;
+ iterator begin() const { return Buffer.begin(); }
+ iterator end() const { return Buffer.end(); }
+ unsigned size() const { return Buffer.size(); }
+
+ /// 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);
+ }
+ void Initialize(StringRef Input) {
+ Initialize(Input.begin(), Input.end());
+ }
+
+ /// \brief Write to \p Stream the result of applying all changes to the
+ /// original buffer.
+ /// Note that it isn't safe to use this function to overwrite memory mapped
+ /// files in-place (PR17960). Consider using a higher-level utility such as
+ /// Rewriter::overwriteChangedFiles() instead.
+ ///
+ /// The original buffer is not actually changed.
+ raw_ostream &write(raw_ostream &Stream) const;
+
+ /// RemoveText - Remove the specified text.
+ void RemoveText(unsigned OrigOffset, unsigned Size,
+ bool removeLineIfEmpty = false);
+
+ /// 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, 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, 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, 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,
+ StringRef NewStr);
+
+private: // Methods only usable by Rewriter.
+
+ /// 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);
+ }
+};
+
+} // end namespace clang
+
+#endif
diff --git a/contrib/llvm/tools/clang/include/clang/Rewrite/Core/RewriteRope.h b/contrib/llvm/tools/clang/include/clang/Rewrite/Core/RewriteRope.h
new file mode 100644
index 0000000..5002554
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Rewrite/Core/RewriteRope.h
@@ -0,0 +1,214 @@
+//===--- 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_REWRITE_CORE_REWRITEROPE_H
+#define LLVM_CLANG_REWRITE_CORE_REWRITEROPE_H
+
+#include "llvm/ADT/IntrusiveRefCntPtr.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/Support/Compiler.h"
+#include <cassert>
+#include <cstddef>
+#include <cstring>
+#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 Retain() { ++RefCount; }
+
+ void Release() {
+ assert(RefCount > 0 && "Reference count is already zero.");
+ if (--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 {
+ llvm::IntrusiveRefCntPtr<RopeRefCountString> StrData;
+ unsigned StartOffs;
+ unsigned EndOffs;
+
+ RopePiece() : StrData(nullptr), StartOffs(0), EndOffs(0) {}
+
+ RopePiece(llvm::IntrusiveRefCntPtr<RopeRefCountString> Str, unsigned Start,
+ unsigned End)
+ : StrData(std::move(Str)), StartOffs(Start), EndOffs(End) {}
+
+ 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(nullptr), CurPiece(nullptr), 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;
+ }
+
+ llvm::StringRef piece() const {
+ return llvm::StringRef(&(*CurPiece)[0], CurPiece->size());
+ }
+
+ void MoveToNextPiece();
+ };
+
+ //===--------------------------------------------------------------------===//
+ // RopePieceBTree Class
+ //===--------------------------------------------------------------------===//
+
+ class RopePieceBTree {
+ void /*RopePieceBTreeNode*/ *Root;
+ void operator=(const RopePieceBTree &) = delete;
+ 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.
+ llvm::IntrusiveRefCntPtr<RopeRefCountString> AllocBuffer;
+ unsigned AllocOffs;
+ enum { AllocChunkSize = 4080 };
+
+public:
+ RewriteRope() : AllocBuffer(nullptr), AllocOffs(AllocChunkSize) {}
+ RewriteRope(const RewriteRope &RHS)
+ : Chunks(RHS.Chunks), AllocBuffer(nullptr), AllocOffs(AllocChunkSize) {
+ }
+
+ 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/Core/Rewriter.h b/contrib/llvm/tools/clang/include/clang/Rewrite/Core/Rewriter.h
new file mode 100644
index 0000000..800372e
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Rewrite/Core/Rewriter.h
@@ -0,0 +1,195 @@
+//===--- 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_REWRITE_CORE_REWRITER_H
+#define LLVM_CLANG_REWRITE_CORE_REWRITER_H
+
+#include "clang/Basic/SourceLocation.h"
+#include "clang/Rewrite/Core/RewriteBuffer.h"
+#include <cstring>
+#include <map>
+#include <string>
+
+namespace clang {
+ class LangOptions;
+ class SourceManager;
+
+/// 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:
+ struct RewriteOptions {
+ /// \brief Given a source range, true to include previous inserts at the
+ /// beginning of the range as part of the range itself (true by default).
+ bool IncludeInsertsAtBeginOfRange;
+ /// \brief Given a source range, true to include previous inserts at the
+ /// end of the range as part of the range itself (true by default).
+ bool IncludeInsertsAtEndOfRange;
+ /// \brief If true and removing some text leaves a blank line
+ /// also remove the empty line (false by default).
+ bool RemoveLineIfEmpty;
+
+ RewriteOptions()
+ : IncludeInsertsAtBeginOfRange(true),
+ IncludeInsertsAtEndOfRange(true),
+ RemoveLineIfEmpty(false) { }
+ };
+
+ typedef std::map<FileID, RewriteBuffer>::iterator buffer_iterator;
+ typedef std::map<FileID, RewriteBuffer>::const_iterator const_buffer_iterator;
+
+ explicit Rewriter(SourceManager &SM, const LangOptions &LO)
+ : SourceMgr(&SM), LangOpts(&LO) {}
+ explicit Rewriter() : SourceMgr(nullptr), LangOpts(nullptr) {}
+
+ void setSourceMgr(SourceManager &SM, const LangOptions &LO) {
+ SourceMgr = &SM;
+ LangOpts = &LO;
+ }
+ SourceManager &getSourceMgr() const { return *SourceMgr; }
+ const LangOptions &getLangOpts() const { 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,
+ RewriteOptions opts = RewriteOptions()) const;
+ int getRangeSize(const CharSourceRange &Range,
+ RewriteOptions opts = RewriteOptions()) 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.
+ ///
+ /// \param indentNewLines if true new lines in the string are indented
+ /// using the indentation of the source line in position \p Loc.
+ bool InsertText(SourceLocation Loc, StringRef Str,
+ bool InsertAfter = true, bool indentNewLines = false);
+
+ /// 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, StringRef Str) {
+ return InsertText(Loc, Str);
+ }
+
+ /// \brief Insert the specified string after the token in the
+ /// specified location.
+ bool InsertTextAfterToken(SourceLocation Loc, StringRef 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, StringRef Str) {
+ return InsertText(Loc, Str, false);
+ }
+
+ /// RemoveText - Remove the specified text region.
+ bool RemoveText(SourceLocation Start, unsigned Length,
+ RewriteOptions opts = RewriteOptions());
+
+ /// \brief Remove the specified text region.
+ bool RemoveText(CharSourceRange range,
+ RewriteOptions opts = RewriteOptions()) {
+ return RemoveText(range.getBegin(), getRangeSize(range, opts), opts);
+ }
+
+ /// \brief Remove the specified text region.
+ bool RemoveText(SourceRange range, RewriteOptions opts = RewriteOptions()) {
+ return RemoveText(range.getBegin(), getRangeSize(range, opts), opts);
+ }
+
+ /// 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,
+ StringRef NewStr);
+
+ /// 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(SourceRange range, StringRef NewStr) {
+ return ReplaceText(range.getBegin(), getRangeSize(range), NewStr);
+ }
+
+ /// 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(SourceRange range, SourceRange replacementRange);
+
+ /// \brief Increase indentation for the lines between the given source range.
+ /// To determine what the indentation should be, 'parentIndent' is used
+ /// that should be at a source location with an indentation one degree
+ /// lower than the given range.
+ bool IncreaseIndentation(CharSourceRange range, SourceLocation parentIndent);
+ bool IncreaseIndentation(SourceRange range, SourceLocation parentIndent) {
+ return IncreaseIndentation(CharSourceRange::getTokenRange(range),
+ parentIndent);
+ }
+
+ /// 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() ? nullptr : &I->second;
+ }
+
+ // Iterators over rewrite buffers.
+ buffer_iterator buffer_begin() { return RewriteBuffers.begin(); }
+ buffer_iterator buffer_end() { return RewriteBuffers.end(); }
+ const_buffer_iterator buffer_begin() const { return RewriteBuffers.begin(); }
+ const_buffer_iterator buffer_end() const { return RewriteBuffers.end(); }
+
+ /// overwriteChangedFiles - Save all changed files to disk.
+ ///
+ /// Returns true if any files were not saved successfully.
+ /// Outputs diagnostics via the source manager's diagnostic engine
+ /// in case of an error.
+ bool overwriteChangedFiles();
+
+private:
+ unsigned getLocationOffsetAndFileID(SourceLocation Loc, FileID &FID) const;
+};
+
+} // end namespace clang
+
+#endif
diff --git a/contrib/llvm/tools/clang/include/clang/Rewrite/Core/TokenRewriter.h b/contrib/llvm/tools/clang/include/clang/Rewrite/Core/TokenRewriter.h
new file mode 100644
index 0000000..0f71e81
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Rewrite/Core/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_REWRITE_CORE_TOKENREWRITER_H
+#define LLVM_CLANG_REWRITE_CORE_TOKENREWRITER_H
+
+#include "clang/Basic/SourceLocation.h"
+#include "clang/Lex/Token.h"
+#include <list>
+#include <map>
+#include <memory>
+
+namespace clang {
+ 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.
+ ///
+ std::unique_ptr<ScratchBuffer> ScratchBuf;
+
+ TokenRewriter(const TokenRewriter &) = delete;
+ void operator=(const TokenRewriter &) = delete;
+ 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/Rewrite/Frontend/ASTConsumers.h b/contrib/llvm/tools/clang/include/clang/Rewrite/Frontend/ASTConsumers.h
new file mode 100644
index 0000000..c9df889
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Rewrite/Frontend/ASTConsumers.h
@@ -0,0 +1,48 @@
+//===--- 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 LLVM_CLANG_REWRITE_FRONTEND_ASTCONSUMERS_H
+#define LLVM_CLANG_REWRITE_FRONTEND_ASTCONSUMERS_H
+
+#include "clang/Basic/LLVM.h"
+#include <memory>
+#include <string>
+
+namespace clang {
+
+class ASTConsumer;
+class DiagnosticsEngine;
+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.
+std::unique_ptr<ASTConsumer>
+CreateObjCRewriter(const std::string &InFile, raw_ostream *OS,
+ DiagnosticsEngine &Diags, const LangOptions &LOpts,
+ bool SilenceRewriteMacroWarning);
+std::unique_ptr<ASTConsumer>
+CreateModernObjCRewriter(const std::string &InFile, raw_ostream *OS,
+ DiagnosticsEngine &Diags, const LangOptions &LOpts,
+ bool SilenceRewriteMacroWarning, bool LineInfo);
+
+/// CreateHTMLPrinter - Create an AST consumer which rewrites source code to
+/// HTML with syntax highlighting suitable for viewing in a web-browser.
+std::unique_ptr<ASTConsumer> CreateHTMLPrinter(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/Frontend/FixItRewriter.h b/contrib/llvm/tools/clang/include/clang/Rewrite/Frontend/FixItRewriter.h
new file mode 100644
index 0000000..3b1b31e
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Rewrite/Frontend/FixItRewriter.h
@@ -0,0 +1,132 @@
+//===--- 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_FRONTEND_FIXITREWRITER_H
+#define LLVM_CLANG_REWRITE_FRONTEND_FIXITREWRITER_H
+
+#include "clang/Basic/Diagnostic.h"
+#include "clang/Basic/SourceLocation.h"
+#include "clang/Edit/EditedSource.h"
+#include "clang/Rewrite/Core/Rewriter.h"
+
+namespace clang {
+
+class SourceManager;
+class FileEntry;
+
+class FixItOptions {
+public:
+ FixItOptions() : InPlace(false), FixWhatYouCan(false),
+ FixOnlyWarnings(false), Silent(false) { }
+
+ virtual ~FixItOptions();
+
+ /// \brief This file is about to be rewritten. Return the name of the file
+ /// that is okay to write to.
+ ///
+ /// \param fd out parameter for file descriptor. After the call it may be set
+ /// to an open file descriptor for the returned filename, or it will be -1
+ /// otherwise.
+ ///
+ virtual std::string RewriteFilename(const std::string &Filename, int &fd) = 0;
+
+ /// True if files should be updated in place. RewriteFilename is only called
+ /// if this is false.
+ bool InPlace;
+
+ /// \brief Whether to abort fixing a file when not all errors could be fixed.
+ bool FixWhatYouCan;
+
+ /// \brief Whether to only fix warnings and not errors.
+ bool FixOnlyWarnings;
+
+ /// \brief If true, only pass the diagnostic to the actual diagnostic consumer
+ /// if it is an error or a fixit was applied as part of the diagnostic.
+ /// It basically silences warnings without accompanying fixits.
+ bool Silent;
+};
+
+class FixItRewriter : public DiagnosticConsumer {
+ /// \brief The diagnostics machinery.
+ DiagnosticsEngine &Diags;
+
+ edit::EditedSource Editor;
+
+ /// \brief The rewriter used to perform the various code
+ /// modifications.
+ Rewriter Rewrite;
+
+ /// \brief The diagnostic client that performs the actual formatting
+ /// of error messages.
+ DiagnosticConsumer *Client;
+ std::unique_ptr<DiagnosticConsumer> Owner;
+
+ /// \brief Turn an input path into an output path. NULL implies overwriting
+ /// the original.
+ FixItOptions *FixItOpts;
+
+ /// \brief The number of rewriter failures.
+ unsigned NumFailures;
+
+ /// \brief Whether the previous diagnostic was not passed to the consumer.
+ bool PrevDiagSilenced;
+
+public:
+ typedef Rewriter::buffer_iterator iterator;
+
+ /// \brief Initialize a new fix-it rewriter.
+ FixItRewriter(DiagnosticsEngine &Diags, SourceManager &SourceMgr,
+ const LangOptions &LangOpts, FixItOptions *FixItOpts);
+
+ /// \brief Destroy the fix-it rewriter.
+ ~FixItRewriter() override;
+
+ /// \brief Check whether there are modifications for a given file.
+ bool IsModified(FileID ID) const {
+ return Rewrite.getRewriteBufferFor(ID) != nullptr;
+ }
+
+ // 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, raw_ostream &OS);
+
+ /// \brief Write the modified source files.
+ ///
+ /// \returns true if there was an error, false otherwise.
+ bool WriteFixedFiles(
+ std::vector<std::pair<std::string, std::string> > *RewrittenFiles=nullptr);
+
+ /// IncludeInDiagnosticCounts - This method (whose default implementation
+ /// returns true) indicates whether the diagnostics handled by this
+ /// DiagnosticConsumer should be included in the number of diagnostics
+ /// reported by DiagnosticsEngine.
+ bool IncludeInDiagnosticCounts() const override;
+
+ /// HandleDiagnostic - Handle this diagnostic, reporting it to the user or
+ /// capturing it to a log as needed.
+ void HandleDiagnostic(DiagnosticsEngine::Level DiagLevel,
+ const Diagnostic &Info) override;
+
+ /// \brief Emit a diagnostic via the adapted diagnostic client.
+ void Diag(SourceLocation Loc, unsigned DiagID);
+};
+
+}
+
+#endif
diff --git a/contrib/llvm/tools/clang/include/clang/Rewrite/Frontend/FrontendActions.h b/contrib/llvm/tools/clang/include/clang/Rewrite/Frontend/FrontendActions.h
new file mode 100644
index 0000000..6c290e4
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Rewrite/Frontend/FrontendActions.h
@@ -0,0 +1,83 @@
+//===-- 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_FRONTEND_FRONTENDACTIONS_H
+#define LLVM_CLANG_REWRITE_FRONTEND_FRONTENDACTIONS_H
+
+#include "clang/Frontend/FrontendAction.h"
+
+namespace clang {
+class FixItRewriter;
+class FixItOptions;
+
+//===----------------------------------------------------------------------===//
+// AST Consumer Actions
+//===----------------------------------------------------------------------===//
+
+class HTMLPrintAction : public ASTFrontendAction {
+protected:
+ std::unique_ptr<ASTConsumer> CreateASTConsumer(CompilerInstance &CI,
+ StringRef InFile) override;
+};
+
+class FixItAction : public ASTFrontendAction {
+protected:
+ std::unique_ptr<FixItRewriter> Rewriter;
+ std::unique_ptr<FixItOptions> FixItOpts;
+
+ std::unique_ptr<ASTConsumer> CreateASTConsumer(CompilerInstance &CI,
+ StringRef InFile) override;
+
+ bool BeginSourceFileAction(CompilerInstance &CI,
+ StringRef Filename) override;
+
+ void EndSourceFileAction() override;
+
+ bool hasASTFileSupport() const override { return false; }
+
+public:
+ FixItAction();
+ ~FixItAction() override;
+};
+
+/// \brief Emits changes to temporary files and uses them for the original
+/// frontend action.
+class FixItRecompile : public WrapperFrontendAction {
+public:
+ FixItRecompile(FrontendAction *WrappedAction)
+ : WrapperFrontendAction(WrappedAction) {}
+
+protected:
+ bool BeginInvocation(CompilerInstance &CI) override;
+};
+
+class RewriteObjCAction : public ASTFrontendAction {
+protected:
+ std::unique_ptr<ASTConsumer> CreateASTConsumer(CompilerInstance &CI,
+ StringRef InFile) override;
+};
+
+class RewriteMacrosAction : public PreprocessorFrontendAction {
+protected:
+ void ExecuteAction() override;
+};
+
+class RewriteTestAction : public PreprocessorFrontendAction {
+protected:
+ void ExecuteAction() override;
+};
+
+class RewriteIncludesAction : public PreprocessorFrontendAction {
+protected:
+ void ExecuteAction() override;
+};
+
+} // end namespace clang
+
+#endif
diff --git a/contrib/llvm/tools/clang/include/clang/Rewrite/Frontend/Rewriters.h b/contrib/llvm/tools/clang/include/clang/Rewrite/Frontend/Rewriters.h
new file mode 100644
index 0000000..3ad76df
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Rewrite/Frontend/Rewriters.h
@@ -0,0 +1,35 @@
+//===--- 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_FRONTEND_REWRITERS_H
+#define LLVM_CLANG_REWRITE_FRONTEND_REWRITERS_H
+
+#include "clang/Basic/LLVM.h"
+
+namespace clang {
+class Preprocessor;
+class PreprocessorOutputOptions;
+
+/// RewriteMacrosInInput - Implement -rewrite-macros mode.
+void RewriteMacrosInInput(Preprocessor &PP, raw_ostream *OS);
+
+/// DoRewriteTest - A simple test for the TokenRewriter class.
+void DoRewriteTest(Preprocessor &PP, raw_ostream *OS);
+
+/// RewriteIncludesInInput - Implement -frewrite-includes mode.
+void RewriteIncludesInInput(Preprocessor &PP, raw_ostream *OS,
+ const PreprocessorOutputOptions &Opts);
+
+} // 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..64dd2d3
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Sema/AnalysisBasedWarnings.h
@@ -0,0 +1,103 @@
+//=- 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_ANALYSISBASEDWARNINGS_H
+#define LLVM_CLANG_SEMA_ANALYSISBASEDWARNINGS_H
+
+#include "llvm/ADT/DenseMap.h"
+
+namespace clang {
+
+class BlockExpr;
+class Decl;
+class FunctionDecl;
+class ObjCMethodDecl;
+class QualType;
+class Sema;
+namespace sema {
+ class FunctionScopeInfo;
+}
+
+namespace sema {
+
+class AnalysisBasedWarnings {
+public:
+ class Policy {
+ friend class AnalysisBasedWarnings;
+ // The warnings to run.
+ unsigned enableCheckFallThrough : 1;
+ unsigned enableCheckUnreachable : 1;
+ unsigned enableThreadSafetyAnalysis : 1;
+ unsigned enableConsumedAnalysis : 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;
+
+ /// \name Statistics
+ /// @{
+
+ /// \brief Number of function CFGs built and analyzed.
+ unsigned NumFunctionsAnalyzed;
+
+ /// \brief Number of functions for which the CFG could not be successfully
+ /// built.
+ unsigned NumFunctionsWithBadCFGs;
+
+ /// \brief Total number of blocks across all CFGs.
+ unsigned NumCFGBlocks;
+
+ /// \brief Largest number of CFG blocks for a single function analyzed.
+ unsigned MaxCFGBlocksPerFunction;
+
+ /// \brief Total number of CFGs with variables analyzed for uninitialized
+ /// uses.
+ unsigned NumUninitAnalysisFunctions;
+
+ /// \brief Total number of variables analyzed for uninitialized uses.
+ unsigned NumUninitAnalysisVariables;
+
+ /// \brief Max number of variables analyzed for uninitialized uses in a single
+ /// function.
+ unsigned MaxUninitAnalysisVariablesPerFunction;
+
+ /// \brief Total number of block visits during uninitialized use analysis.
+ unsigned NumUninitAnalysisBlockVisits;
+
+ /// \brief Max number of block visits during uninitialized use analysis of
+ /// a single function.
+ unsigned MaxUninitAnalysisBlockVisitsPerFunction;
+
+ /// @}
+
+public:
+ AnalysisBasedWarnings(Sema &s);
+
+ void IssueWarnings(Policy P, FunctionScopeInfo *fscope,
+ const Decl *D, const BlockExpr *blkExpr);
+
+ Policy getDefaultPolicy() { return DefaultPolicy; }
+
+ void PrintStats() const;
+};
+
+}} // 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..e32781d
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Sema/AttributeList.h
@@ -0,0 +1,863 @@
+//===--- 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_ATTRIBUTELIST_H
+#define LLVM_CLANG_SEMA_ATTRIBUTELIST_H
+
+#include "clang/Basic/SourceLocation.h"
+#include "clang/Basic/TargetInfo.h"
+#include "clang/Basic/VersionTuple.h"
+#include "clang/Sema/Ownership.h"
+#include "llvm/ADT/PointerUnion.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/Support/Allocator.h"
+#include <cassert>
+
+namespace clang {
+ class ASTContext;
+ class IdentifierInfo;
+ class Expr;
+
+/// \brief Represents information about a change in availability for
+/// an entity, which is part of the encoding of the 'availability'
+/// attribute.
+struct AvailabilityChange {
+ /// \brief The location of the keyword indicating the kind of change.
+ SourceLocation KeywordLoc;
+
+ /// \brief The version number at which the change occurred.
+ VersionTuple Version;
+
+ /// \brief The source range covering the version number.
+ SourceRange VersionRange;
+
+ /// \brief Determine whether this availability change is valid.
+ bool isValid() const { return !Version.empty(); }
+};
+
+/// \brief Wraps an identifier and optional source location for the identifier.
+struct IdentifierLoc {
+ SourceLocation Loc;
+ IdentifierInfo *Ident;
+
+ static IdentifierLoc *create(ASTContext &Ctx, SourceLocation Loc,
+ IdentifierInfo *Ident);
+};
+
+/// \brief A union of the various pointer types that can be passed to an
+/// AttributeList as an argument.
+typedef llvm::PointerUnion<Expr*, IdentifierLoc*> ArgsUnion;
+typedef llvm::SmallVector<ArgsUnion, 12U> ArgsVector;
+
+/// AttributeList - Represents a syntactic attribute.
+///
+/// For a GNU attribute, there are four forms of this construct:
+///
+/// 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 { // TODO: This should really be called ParsedAttribute
+public:
+ /// The style used to specify an attribute.
+ enum Syntax {
+ /// __attribute__((...))
+ AS_GNU,
+ /// [[...]]
+ AS_CXX11,
+ /// __declspec(...)
+ AS_Declspec,
+ /// __ptr16, alignas(...), etc.
+ AS_Keyword,
+ /// Context-sensitive version of a keyword attribute.
+ AS_ContextSensitiveKeyword,
+ /// #pragma ...
+ AS_Pragma
+ };
+
+private:
+ IdentifierInfo *AttrName;
+ IdentifierInfo *ScopeName;
+ SourceRange AttrRange;
+ SourceLocation ScopeLoc;
+ SourceLocation EllipsisLoc;
+
+ /// The number of expression arguments this attribute has.
+ /// The expressions themselves are stored after the object.
+ unsigned NumArgs : 15;
+
+ /// Corresponds to the Syntax enum.
+ unsigned SyntaxUsed : 3;
+
+ /// True if already diagnosed as invalid.
+ mutable unsigned Invalid : 1;
+
+ /// True if this attribute was used as a type attribute.
+ mutable unsigned UsedAsTypeAttr : 1;
+
+ /// True if this has the extra information associated with an
+ /// availability attribute.
+ unsigned IsAvailability : 1;
+
+ /// True if this has extra information associated with a
+ /// type_tag_for_datatype attribute.
+ unsigned IsTypeTagForDatatype : 1;
+
+ /// True if this has extra information associated with a
+ /// Microsoft __delcspec(property) attribute.
+ unsigned IsProperty : 1;
+
+ /// True if this has a ParsedType
+ unsigned HasParsedType : 1;
+
+ unsigned AttrKind : 8;
+
+ /// \brief The location of the 'unavailable' keyword in an
+ /// availability attribute.
+ SourceLocation UnavailableLoc;
+
+ const Expr *MessageExpr;
+
+ /// The next attribute in the current position.
+ AttributeList *NextInPosition;
+
+ /// The next attribute allocated in the current Pool.
+ AttributeList *NextInPool;
+
+ /// Arguments, if any, are stored immediately following the object.
+ ArgsUnion *getArgsBuffer() { return reinterpret_cast<ArgsUnion *>(this + 1); }
+ ArgsUnion const *getArgsBuffer() const {
+ return reinterpret_cast<ArgsUnion const *>(this + 1);
+ }
+
+ enum AvailabilitySlot {
+ IntroducedSlot, DeprecatedSlot, ObsoletedSlot
+ };
+
+ /// Availability information is stored immediately following the arguments,
+ /// if any, at the end of the object.
+ AvailabilityChange &getAvailabilitySlot(AvailabilitySlot index) {
+ return reinterpret_cast<AvailabilityChange*>(getArgsBuffer()
+ + NumArgs)[index];
+ }
+ const AvailabilityChange &getAvailabilitySlot(AvailabilitySlot index) const {
+ return reinterpret_cast<const AvailabilityChange*>(getArgsBuffer()
+ + NumArgs)[index];
+ }
+
+public:
+ struct TypeTagForDatatypeData {
+ ParsedType *MatchingCType;
+ unsigned LayoutCompatible : 1;
+ unsigned MustBeNull : 1;
+ };
+ struct PropertyData {
+ IdentifierInfo *GetterId, *SetterId;
+ PropertyData(IdentifierInfo *getterId, IdentifierInfo *setterId)
+ : GetterId(getterId), SetterId(setterId) {}
+ };
+
+private:
+ /// Type tag information is stored immediately following the arguments, if
+ /// any, at the end of the object. They are mutually exlusive with
+ /// availability slots.
+ TypeTagForDatatypeData &getTypeTagForDatatypeDataSlot() {
+ return *reinterpret_cast<TypeTagForDatatypeData*>(getArgsBuffer()+NumArgs);
+ }
+
+ const TypeTagForDatatypeData &getTypeTagForDatatypeDataSlot() const {
+ return *reinterpret_cast<const TypeTagForDatatypeData*>(getArgsBuffer()
+ + NumArgs);
+ }
+
+ /// The type buffer immediately follows the object and are mutually exclusive
+ /// with arguments.
+ ParsedType &getTypeBuffer() {
+ return *reinterpret_cast<ParsedType *>(this + 1);
+ }
+
+ const ParsedType &getTypeBuffer() const {
+ return *reinterpret_cast<const ParsedType *>(this + 1);
+ }
+
+ /// The property data immediately follows the object is is mutually exclusive
+ /// with arguments.
+ PropertyData &getPropertyDataBuffer() {
+ assert(IsProperty);
+ return *reinterpret_cast<PropertyData*>(this + 1);
+ }
+
+ const PropertyData &getPropertyDataBuffer() const {
+ assert(IsProperty);
+ return *reinterpret_cast<const PropertyData*>(this + 1);
+ }
+
+ AttributeList(const AttributeList &) = delete;
+ void operator=(const AttributeList &) = delete;
+ void operator delete(void *) = delete;
+ ~AttributeList() = delete;
+
+ size_t allocated_size() const;
+
+ /// Constructor for attributes with expression arguments.
+ AttributeList(IdentifierInfo *attrName, SourceRange attrRange,
+ IdentifierInfo *scopeName, SourceLocation scopeLoc,
+ ArgsUnion *args, unsigned numArgs,
+ Syntax syntaxUsed, SourceLocation ellipsisLoc)
+ : AttrName(attrName), ScopeName(scopeName), AttrRange(attrRange),
+ ScopeLoc(scopeLoc), EllipsisLoc(ellipsisLoc), NumArgs(numArgs),
+ SyntaxUsed(syntaxUsed), Invalid(false), UsedAsTypeAttr(false),
+ IsAvailability(false), IsTypeTagForDatatype(false), IsProperty(false),
+ HasParsedType(false), NextInPosition(nullptr), NextInPool(nullptr) {
+ if (numArgs) memcpy(getArgsBuffer(), args, numArgs * sizeof(ArgsUnion));
+ AttrKind = getKind(getName(), getScopeName(), syntaxUsed);
+ }
+
+ /// Constructor for availability attributes.
+ AttributeList(IdentifierInfo *attrName, SourceRange attrRange,
+ IdentifierInfo *scopeName, SourceLocation scopeLoc,
+ IdentifierLoc *Parm, const AvailabilityChange &introduced,
+ const AvailabilityChange &deprecated,
+ const AvailabilityChange &obsoleted,
+ SourceLocation unavailable,
+ const Expr *messageExpr,
+ Syntax syntaxUsed)
+ : AttrName(attrName), ScopeName(scopeName), AttrRange(attrRange),
+ ScopeLoc(scopeLoc), EllipsisLoc(), NumArgs(1), SyntaxUsed(syntaxUsed),
+ Invalid(false), UsedAsTypeAttr(false), IsAvailability(true),
+ IsTypeTagForDatatype(false), IsProperty(false), HasParsedType(false),
+ UnavailableLoc(unavailable), MessageExpr(messageExpr),
+ NextInPosition(nullptr), NextInPool(nullptr) {
+ ArgsUnion PVal(Parm);
+ memcpy(getArgsBuffer(), &PVal, sizeof(ArgsUnion));
+ new (&getAvailabilitySlot(IntroducedSlot)) AvailabilityChange(introduced);
+ new (&getAvailabilitySlot(DeprecatedSlot)) AvailabilityChange(deprecated);
+ new (&getAvailabilitySlot(ObsoletedSlot)) AvailabilityChange(obsoleted);
+ AttrKind = getKind(getName(), getScopeName(), syntaxUsed);
+ }
+
+ /// Constructor for objc_bridge_related attributes.
+ AttributeList(IdentifierInfo *attrName, SourceRange attrRange,
+ IdentifierInfo *scopeName, SourceLocation scopeLoc,
+ IdentifierLoc *Parm1,
+ IdentifierLoc *Parm2,
+ IdentifierLoc *Parm3,
+ Syntax syntaxUsed)
+ : AttrName(attrName), ScopeName(scopeName), AttrRange(attrRange),
+ ScopeLoc(scopeLoc), EllipsisLoc(), NumArgs(3), SyntaxUsed(syntaxUsed),
+ Invalid(false), UsedAsTypeAttr(false), IsAvailability(false),
+ IsTypeTagForDatatype(false), IsProperty(false), HasParsedType(false),
+ NextInPosition(nullptr), NextInPool(nullptr) {
+ ArgsVector Args;
+ Args.push_back(Parm1);
+ Args.push_back(Parm2);
+ Args.push_back(Parm3);
+ memcpy(getArgsBuffer(), &Args[0], 3 * sizeof(ArgsUnion));
+ AttrKind = getKind(getName(), getScopeName(), syntaxUsed);
+ }
+
+ /// Constructor for type_tag_for_datatype attribute.
+ AttributeList(IdentifierInfo *attrName, SourceRange attrRange,
+ IdentifierInfo *scopeName, SourceLocation scopeLoc,
+ IdentifierLoc *ArgKind, ParsedType matchingCType,
+ bool layoutCompatible, bool mustBeNull, Syntax syntaxUsed)
+ : AttrName(attrName), ScopeName(scopeName), AttrRange(attrRange),
+ ScopeLoc(scopeLoc), EllipsisLoc(), NumArgs(1), SyntaxUsed(syntaxUsed),
+ Invalid(false), UsedAsTypeAttr(false), IsAvailability(false),
+ IsTypeTagForDatatype(true), IsProperty(false), HasParsedType(false),
+ NextInPosition(nullptr), NextInPool(nullptr) {
+ ArgsUnion PVal(ArgKind);
+ memcpy(getArgsBuffer(), &PVal, sizeof(ArgsUnion));
+ TypeTagForDatatypeData &ExtraData = getTypeTagForDatatypeDataSlot();
+ new (&ExtraData.MatchingCType) ParsedType(matchingCType);
+ ExtraData.LayoutCompatible = layoutCompatible;
+ ExtraData.MustBeNull = mustBeNull;
+ AttrKind = getKind(getName(), getScopeName(), syntaxUsed);
+ }
+
+ /// Constructor for attributes with a single type argument.
+ AttributeList(IdentifierInfo *attrName, SourceRange attrRange,
+ IdentifierInfo *scopeName, SourceLocation scopeLoc,
+ ParsedType typeArg, Syntax syntaxUsed)
+ : AttrName(attrName), ScopeName(scopeName), AttrRange(attrRange),
+ ScopeLoc(scopeLoc), EllipsisLoc(), NumArgs(0), SyntaxUsed(syntaxUsed),
+ Invalid(false), UsedAsTypeAttr(false), IsAvailability(false),
+ IsTypeTagForDatatype(false), IsProperty(false), HasParsedType(true),
+ NextInPosition(nullptr), NextInPool(nullptr) {
+ new (&getTypeBuffer()) ParsedType(typeArg);
+ AttrKind = getKind(getName(), getScopeName(), syntaxUsed);
+ }
+
+ /// Constructor for microsoft __declspec(property) attribute.
+ AttributeList(IdentifierInfo *attrName, SourceRange attrRange,
+ IdentifierInfo *scopeName, SourceLocation scopeLoc,
+ IdentifierInfo *getterId, IdentifierInfo *setterId,
+ Syntax syntaxUsed)
+ : AttrName(attrName), ScopeName(scopeName), AttrRange(attrRange),
+ ScopeLoc(scopeLoc), EllipsisLoc(), NumArgs(0), SyntaxUsed(syntaxUsed),
+ Invalid(false), UsedAsTypeAttr(false), IsAvailability(false),
+ IsTypeTagForDatatype(false), IsProperty(true), HasParsedType(false),
+ NextInPosition(nullptr), NextInPool(nullptr) {
+ new (&getPropertyDataBuffer()) PropertyData(getterId, setterId);
+ AttrKind = getKind(getName(), getScopeName(), syntaxUsed);
+ }
+
+ friend class AttributePool;
+ friend class AttributeFactory;
+
+public:
+ enum Kind {
+ #define PARSED_ATTR(NAME) AT_##NAME,
+ #include "clang/Sema/AttrParsedAttrList.inc"
+ #undef PARSED_ATTR
+ IgnoredAttribute,
+ UnknownAttribute
+ };
+
+ IdentifierInfo *getName() const { return AttrName; }
+ SourceLocation getLoc() const { return AttrRange.getBegin(); }
+ SourceRange getRange() const { return AttrRange; }
+
+ bool hasScope() const { return ScopeName; }
+ IdentifierInfo *getScopeName() const { return ScopeName; }
+ SourceLocation getScopeLoc() const { return ScopeLoc; }
+
+ bool hasParsedType() const { return HasParsedType; }
+
+ /// Is this the Microsoft __declspec(property) attribute?
+ bool isDeclspecPropertyAttribute() const {
+ return IsProperty;
+ }
+
+ bool isAlignasAttribute() const {
+ // FIXME: Use a better mechanism to determine this.
+ return getKind() == AT_Aligned && isKeywordAttribute();
+ }
+
+ bool isDeclspecAttribute() const { return SyntaxUsed == AS_Declspec; }
+ bool isCXX11Attribute() const {
+ return SyntaxUsed == AS_CXX11 || isAlignasAttribute();
+ }
+ bool isKeywordAttribute() const {
+ return SyntaxUsed == AS_Keyword || SyntaxUsed == AS_ContextSensitiveKeyword;
+ }
+
+ bool isContextSensitiveKeywordAttribute() const {
+ return SyntaxUsed == AS_ContextSensitiveKeyword;
+ }
+
+ bool isInvalid() const { return Invalid; }
+ void setInvalid(bool b = true) const { Invalid = b; }
+
+ bool isUsedAsTypeAttr() const { return UsedAsTypeAttr; }
+ void setUsedAsTypeAttr() { UsedAsTypeAttr = true; }
+
+ bool isPackExpansion() const { return EllipsisLoc.isValid(); }
+ SourceLocation getEllipsisLoc() const { return EllipsisLoc; }
+
+ Kind getKind() const { return Kind(AttrKind); }
+ static Kind getKind(const IdentifierInfo *Name, const IdentifierInfo *Scope,
+ Syntax SyntaxUsed);
+
+ AttributeList *getNext() const { return NextInPosition; }
+ void setNext(AttributeList *N) { NextInPosition = N; }
+
+ /// getNumArgs - Return the number of actual arguments to this attribute.
+ unsigned getNumArgs() const { return NumArgs; }
+
+ /// getArg - Return the specified argument.
+ ArgsUnion getArg(unsigned Arg) const {
+ assert(Arg < NumArgs && "Arg access out of range!");
+ return getArgsBuffer()[Arg];
+ }
+
+ bool isArgExpr(unsigned Arg) const {
+ return Arg < NumArgs && getArg(Arg).is<Expr*>();
+ }
+ Expr *getArgAsExpr(unsigned Arg) const {
+ return getArg(Arg).get<Expr*>();
+ }
+
+ bool isArgIdent(unsigned Arg) const {
+ return Arg < NumArgs && getArg(Arg).is<IdentifierLoc*>();
+ }
+ IdentifierLoc *getArgAsIdent(unsigned Arg) const {
+ return getArg(Arg).get<IdentifierLoc*>();
+ }
+
+ const AvailabilityChange &getAvailabilityIntroduced() const {
+ assert(getKind() == AT_Availability && "Not an availability attribute");
+ return getAvailabilitySlot(IntroducedSlot);
+ }
+
+ const AvailabilityChange &getAvailabilityDeprecated() const {
+ assert(getKind() == AT_Availability && "Not an availability attribute");
+ return getAvailabilitySlot(DeprecatedSlot);
+ }
+
+ const AvailabilityChange &getAvailabilityObsoleted() const {
+ assert(getKind() == AT_Availability && "Not an availability attribute");
+ return getAvailabilitySlot(ObsoletedSlot);
+ }
+
+ SourceLocation getUnavailableLoc() const {
+ assert(getKind() == AT_Availability && "Not an availability attribute");
+ return UnavailableLoc;
+ }
+
+ const Expr * getMessageExpr() const {
+ assert(getKind() == AT_Availability && "Not an availability attribute");
+ return MessageExpr;
+ }
+
+ const ParsedType &getMatchingCType() const {
+ assert(getKind() == AT_TypeTagForDatatype &&
+ "Not a type_tag_for_datatype attribute");
+ return *getTypeTagForDatatypeDataSlot().MatchingCType;
+ }
+
+ bool getLayoutCompatible() const {
+ assert(getKind() == AT_TypeTagForDatatype &&
+ "Not a type_tag_for_datatype attribute");
+ return getTypeTagForDatatypeDataSlot().LayoutCompatible;
+ }
+
+ bool getMustBeNull() const {
+ assert(getKind() == AT_TypeTagForDatatype &&
+ "Not a type_tag_for_datatype attribute");
+ return getTypeTagForDatatypeDataSlot().MustBeNull;
+ }
+
+ const ParsedType &getTypeArg() const {
+ assert(HasParsedType && "Not a type attribute");
+ return getTypeBuffer();
+ }
+
+ const PropertyData &getPropertyData() const {
+ assert(isDeclspecPropertyAttribute() && "Not a __delcspec(property) attribute");
+ return getPropertyDataBuffer();
+ }
+
+ /// \brief Get an index into the attribute spelling list
+ /// defined in Attr.td. This index is used by an attribute
+ /// to pretty print itself.
+ unsigned getAttributeSpellingListIndex() const;
+
+ bool isTargetSpecificAttr() const;
+ bool isTypeAttr() const;
+
+ bool hasCustomParsing() const;
+ unsigned getMinArgs() const;
+ unsigned getMaxArgs() const;
+ bool hasVariadicArg() const;
+ bool diagnoseAppertainsTo(class Sema &S, const Decl *D) const;
+ bool diagnoseLangOpts(class Sema &S) const;
+ bool existsInTarget(const TargetInfo &Target) const;
+ bool isKnownToGCC() const;
+
+ /// \brief If the parsed attribute has a semantic equivalent, and it would
+ /// have a semantic Spelling enumeration (due to having semantically-distinct
+ /// spelling variations), return the value of that semantic spelling. If the
+ /// parsed attribute does not have a semantic equivalent, or would not have
+ /// a Spelling enumeration, the value UINT_MAX is returned.
+ unsigned getSemanticSpelling() const;
+};
+
+/// A factory, from which one makes pools, from which one creates
+/// individual attributes which are deallocated with the pool.
+///
+/// Note that it's tolerably cheap to create and destroy one of
+/// these as long as you don't actually allocate anything in it.
+class AttributeFactory {
+public:
+ enum {
+ /// The required allocation size of an availability attribute,
+ /// which we want to ensure is a multiple of sizeof(void*).
+ AvailabilityAllocSize =
+ sizeof(AttributeList)
+ + ((3 * sizeof(AvailabilityChange) + sizeof(void*) +
+ sizeof(ArgsUnion) - 1)
+ / sizeof(void*) * sizeof(void*)),
+ TypeTagForDatatypeAllocSize =
+ sizeof(AttributeList)
+ + (sizeof(AttributeList::TypeTagForDatatypeData) + sizeof(void *) +
+ sizeof(ArgsUnion) - 1)
+ / sizeof(void*) * sizeof(void*),
+ PropertyAllocSize =
+ sizeof(AttributeList)
+ + (sizeof(AttributeList::PropertyData) + sizeof(void *) - 1)
+ / sizeof(void*) * sizeof(void*)
+ };
+
+private:
+ enum {
+ /// The number of free lists we want to be sure to support
+ /// inline. This is just enough that availability attributes
+ /// don't surpass it. It's actually very unlikely we'll see an
+ /// attribute that needs more than that; on x86-64 you'd need 10
+ /// expression arguments, and on i386 you'd need 19.
+ InlineFreeListsCapacity =
+ 1 + (AvailabilityAllocSize - sizeof(AttributeList)) / sizeof(void*)
+ };
+
+ llvm::BumpPtrAllocator Alloc;
+
+ /// Free lists. The index is determined by the following formula:
+ /// (size - sizeof(AttributeList)) / sizeof(void*)
+ SmallVector<AttributeList*, InlineFreeListsCapacity> FreeLists;
+
+ // The following are the private interface used by AttributePool.
+ friend class AttributePool;
+
+ /// Allocate an attribute of the given size.
+ void *allocate(size_t size);
+
+ /// Reclaim all the attributes in the given pool chain, which is
+ /// non-empty. Note that the current implementation is safe
+ /// against reclaiming things which were not actually allocated
+ /// with the allocator, although of course it's important to make
+ /// sure that their allocator lives at least as long as this one.
+ void reclaimPool(AttributeList *head);
+
+public:
+ AttributeFactory();
+ ~AttributeFactory();
+};
+
+class AttributePool {
+ AttributeFactory &Factory;
+ AttributeList *Head;
+
+ void *allocate(size_t size) {
+ return Factory.allocate(size);
+ }
+
+ AttributeList *add(AttributeList *attr) {
+ // We don't care about the order of the pool.
+ attr->NextInPool = Head;
+ Head = attr;
+ return attr;
+ }
+
+ void takePool(AttributeList *pool);
+
+public:
+ /// Create a new pool for a factory.
+ AttributePool(AttributeFactory &factory) : Factory(factory), Head(nullptr) {}
+
+ AttributePool(const AttributePool &) = delete;
+
+ /// Move the given pool's allocations to this pool.
+ AttributePool(AttributePool &&pool) : Factory(pool.Factory), Head(pool.Head) {
+ pool.Head = nullptr;
+ }
+
+ AttributeFactory &getFactory() const { return Factory; }
+
+ void clear() {
+ if (Head) {
+ Factory.reclaimPool(Head);
+ Head = nullptr;
+ }
+ }
+
+ /// Take the given pool's allocations and add them to this pool.
+ void takeAllFrom(AttributePool &pool) {
+ if (pool.Head) {
+ takePool(pool.Head);
+ pool.Head = nullptr;
+ }
+ }
+
+ ~AttributePool() {
+ if (Head) Factory.reclaimPool(Head);
+ }
+
+ AttributeList *create(IdentifierInfo *attrName, SourceRange attrRange,
+ IdentifierInfo *scopeName, SourceLocation scopeLoc,
+ ArgsUnion *args, unsigned numArgs,
+ AttributeList::Syntax syntax,
+ SourceLocation ellipsisLoc = SourceLocation()) {
+ void *memory = allocate(sizeof(AttributeList)
+ + numArgs * sizeof(ArgsUnion));
+ return add(new (memory) AttributeList(attrName, attrRange,
+ scopeName, scopeLoc,
+ args, numArgs, syntax,
+ ellipsisLoc));
+ }
+
+ AttributeList *create(IdentifierInfo *attrName, SourceRange attrRange,
+ IdentifierInfo *scopeName, SourceLocation scopeLoc,
+ IdentifierLoc *Param,
+ const AvailabilityChange &introduced,
+ const AvailabilityChange &deprecated,
+ const AvailabilityChange &obsoleted,
+ SourceLocation unavailable,
+ const Expr *MessageExpr,
+ AttributeList::Syntax syntax) {
+ void *memory = allocate(AttributeFactory::AvailabilityAllocSize);
+ return add(new (memory) AttributeList(attrName, attrRange,
+ scopeName, scopeLoc,
+ Param, introduced, deprecated,
+ obsoleted, unavailable, MessageExpr,
+ syntax));
+ }
+
+ AttributeList *create(IdentifierInfo *attrName, SourceRange attrRange,
+ IdentifierInfo *scopeName, SourceLocation scopeLoc,
+ IdentifierLoc *Param1,
+ IdentifierLoc *Param2,
+ IdentifierLoc *Param3,
+ AttributeList::Syntax syntax) {
+ size_t size = sizeof(AttributeList) + 3 * sizeof(ArgsUnion);
+ void *memory = allocate(size);
+ return add(new (memory) AttributeList(attrName, attrRange,
+ scopeName, scopeLoc,
+ Param1, Param2, Param3,
+ syntax));
+ }
+
+ AttributeList *createTypeTagForDatatype(
+ IdentifierInfo *attrName, SourceRange attrRange,
+ IdentifierInfo *scopeName, SourceLocation scopeLoc,
+ IdentifierLoc *argumentKind, ParsedType matchingCType,
+ bool layoutCompatible, bool mustBeNull,
+ AttributeList::Syntax syntax) {
+ void *memory = allocate(AttributeFactory::TypeTagForDatatypeAllocSize);
+ return add(new (memory) AttributeList(attrName, attrRange,
+ scopeName, scopeLoc,
+ argumentKind, matchingCType,
+ layoutCompatible, mustBeNull,
+ syntax));
+ }
+
+ AttributeList *createTypeAttribute(
+ IdentifierInfo *attrName, SourceRange attrRange,
+ IdentifierInfo *scopeName, SourceLocation scopeLoc,
+ ParsedType typeArg, AttributeList::Syntax syntaxUsed) {
+ void *memory = allocate(sizeof(AttributeList) + sizeof(void *));
+ return add(new (memory) AttributeList(attrName, attrRange,
+ scopeName, scopeLoc,
+ typeArg, syntaxUsed));
+ }
+
+ AttributeList *createPropertyAttribute(
+ IdentifierInfo *attrName, SourceRange attrRange,
+ IdentifierInfo *scopeName, SourceLocation scopeLoc,
+ IdentifierInfo *getterId, IdentifierInfo *setterId,
+ AttributeList::Syntax syntaxUsed) {
+ void *memory = allocate(AttributeFactory::PropertyAllocSize);
+ return add(new (memory) AttributeList(attrName, attrRange,
+ scopeName, scopeLoc,
+ getterId, setterId,
+ syntaxUsed));
+ }
+};
+
+/// 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(AttributeFactory &factory)
+ : pool(factory), list(nullptr) {
+ }
+
+ ParsedAttributes(const ParsedAttributes &) = delete;
+
+ AttributePool &getPool() const { return pool; }
+
+ bool empty() const { return list == nullptr; }
+
+ void add(AttributeList *newAttr) {
+ assert(newAttr);
+ assert(newAttr->getNext() == nullptr);
+ newAttr->setNext(list);
+ list = newAttr;
+ }
+
+ void addAll(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 takeAllFrom(ParsedAttributes &attrs) {
+ addAll(attrs.list);
+ attrs.list = nullptr;
+ pool.takeAllFrom(attrs.pool);
+ }
+
+ void clear() { list = nullptr; pool.clear(); }
+ 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; }
+
+ /// Add attribute with expression arguments.
+ AttributeList *addNew(IdentifierInfo *attrName, SourceRange attrRange,
+ IdentifierInfo *scopeName, SourceLocation scopeLoc,
+ ArgsUnion *args, unsigned numArgs,
+ AttributeList::Syntax syntax,
+ SourceLocation ellipsisLoc = SourceLocation()) {
+ AttributeList *attr =
+ pool.create(attrName, attrRange, scopeName, scopeLoc, args, numArgs,
+ syntax, ellipsisLoc);
+ add(attr);
+ return attr;
+ }
+
+ /// Add availability attribute.
+ AttributeList *addNew(IdentifierInfo *attrName, SourceRange attrRange,
+ IdentifierInfo *scopeName, SourceLocation scopeLoc,
+ IdentifierLoc *Param,
+ const AvailabilityChange &introduced,
+ const AvailabilityChange &deprecated,
+ const AvailabilityChange &obsoleted,
+ SourceLocation unavailable,
+ const Expr *MessageExpr,
+ AttributeList::Syntax syntax) {
+ AttributeList *attr =
+ pool.create(attrName, attrRange, scopeName, scopeLoc, Param, introduced,
+ deprecated, obsoleted, unavailable, MessageExpr, syntax);
+ add(attr);
+ return attr;
+ }
+
+ /// Add objc_bridge_related attribute.
+ AttributeList *addNew(IdentifierInfo *attrName, SourceRange attrRange,
+ IdentifierInfo *scopeName, SourceLocation scopeLoc,
+ IdentifierLoc *Param1,
+ IdentifierLoc *Param2,
+ IdentifierLoc *Param3,
+ AttributeList::Syntax syntax) {
+ AttributeList *attr =
+ pool.create(attrName, attrRange, scopeName, scopeLoc,
+ Param1, Param2, Param3, syntax);
+ add(attr);
+ return attr;
+ }
+
+ /// Add type_tag_for_datatype attribute.
+ AttributeList *addNewTypeTagForDatatype(
+ IdentifierInfo *attrName, SourceRange attrRange,
+ IdentifierInfo *scopeName, SourceLocation scopeLoc,
+ IdentifierLoc *argumentKind, ParsedType matchingCType,
+ bool layoutCompatible, bool mustBeNull,
+ AttributeList::Syntax syntax) {
+ AttributeList *attr =
+ pool.createTypeTagForDatatype(attrName, attrRange,
+ scopeName, scopeLoc,
+ argumentKind, matchingCType,
+ layoutCompatible, mustBeNull, syntax);
+ add(attr);
+ return attr;
+ }
+
+ /// Add an attribute with a single type argument.
+ AttributeList *
+ addNewTypeAttr(IdentifierInfo *attrName, SourceRange attrRange,
+ IdentifierInfo *scopeName, SourceLocation scopeLoc,
+ ParsedType typeArg, AttributeList::Syntax syntaxUsed) {
+ AttributeList *attr =
+ pool.createTypeAttribute(attrName, attrRange, scopeName, scopeLoc,
+ typeArg, syntaxUsed);
+ add(attr);
+ return attr;
+ }
+
+ /// Add microsoft __delspec(property) attribute.
+ AttributeList *
+ addNewPropertyAttr(IdentifierInfo *attrName, SourceRange attrRange,
+ IdentifierInfo *scopeName, SourceLocation scopeLoc,
+ IdentifierInfo *getterId, IdentifierInfo *setterId,
+ AttributeList::Syntax syntaxUsed) {
+ AttributeList *attr =
+ pool.createPropertyAttribute(attrName, attrRange, scopeName, scopeLoc,
+ getterId, setterId, syntaxUsed);
+ add(attr);
+ return attr;
+ }
+
+private:
+ mutable AttributePool pool;
+ AttributeList *list;
+};
+
+/// These constants match the enumerated choices of
+/// err_attribute_argument_n_type and err_attribute_argument_type.
+enum AttributeArgumentNType {
+ AANT_ArgumentIntOrBool,
+ AANT_ArgumentIntegerConstant,
+ AANT_ArgumentString,
+ AANT_ArgumentIdentifier
+};
+
+/// These constants match the enumerated choices of
+/// warn_attribute_wrong_decl_type and err_attribute_wrong_decl_type.
+enum AttributeDeclKind {
+ ExpectedFunction,
+ ExpectedUnion,
+ ExpectedVariableOrFunction,
+ ExpectedFunctionOrMethod,
+ ExpectedParameter,
+ ExpectedFunctionMethodOrBlock,
+ ExpectedFunctionMethodOrClass,
+ ExpectedFunctionMethodOrParameter,
+ ExpectedClass,
+ ExpectedEnum,
+ ExpectedVariable,
+ ExpectedMethod,
+ ExpectedVariableFunctionOrLabel,
+ ExpectedFieldOrGlobalVar,
+ ExpectedStruct,
+ ExpectedVariableOrTypedef,
+ ExpectedTLSVar,
+ ExpectedVariableOrField,
+ ExpectedVariableFieldOrTag,
+ ExpectedTypeOrNamespace,
+ ExpectedObjectiveCInterface,
+ ExpectedMethodOrProperty,
+ ExpectedStructOrUnion,
+ ExpectedStructOrUnionOrClass,
+ ExpectedType,
+ ExpectedObjCInstanceMethod,
+ ExpectedObjCInterfaceDeclInitMethod,
+ ExpectedFunctionVariableOrClass,
+ ExpectedObjectiveCProtocol,
+ ExpectedFunctionGlobalVarMethodOrProperty,
+ ExpectedStructOrUnionOrTypedef,
+ ExpectedStructOrTypedef,
+ ExpectedObjectiveCInterfaceOrProtocol,
+ ExpectedKernelFunction,
+ ExpectedFunctionWithProtoType
+};
+
+} // 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..6685751
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Sema/CXXFieldCollector.h
@@ -0,0 +1,80 @@
+//===- 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 "clang/Basic/LLVM.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.
+ 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.
+ 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..9702273
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Sema/CodeCompleteConsumer.h
@@ -0,0 +1,976 @@
+//===---- 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-c/Index.h"
+#include "clang/AST/CanonicalType.h"
+#include "clang/AST/Type.h"
+#include "clang/Sema/CodeCompleteOptions.h"
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/Support/Allocator.h"
+#include <string>
+
+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 An Objective-C method being used as a property.
+ CCD_MethodAsProperty = 2
+};
+
+/// \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, const 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(StringRef MacroName,
+ const LangOptions &LangOpts,
+ bool PreferredTypeIsPointer = false);
+
+/// \brief Determine the libclang cursor kind associated with the given
+/// declaration.
+CXCursorKind getCursorKindForDecl(const 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 using the dot operator.
+ ///
+ /// The results of this completion are the members of the type being
+ /// accessed. The type itself is available via
+ /// \c CodeCompletionContext::getType().
+ CCC_DotMemberAccess,
+ /// \brief Code completion occurred on the right-hand side of a member
+ /// access expression using the arrow operator.
+ ///
+ /// The results of this completion are the members of the type being
+ /// accessed. The type itself is available via
+ /// \c CodeCompletionContext::getType().
+ CCC_ArrowMemberAccess,
+ /// \brief Code completion occurred on the right-hand side of an Objective-C
+ /// property 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_ObjCPropertyAccess,
+ /// \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 Code completion where an Objective-C instance message is
+ /// expected.
+ CCC_ObjCInstanceMessage,
+ /// \brief Code completion where an Objective-C class message is expected.
+ CCC_ObjCClassMessage,
+ /// \brief Code completion where the name of an Objective-C class is
+ /// expected.
+ CCC_ObjCInterfaceName,
+ /// \brief Code completion where an Objective-C category name is expected.
+ CCC_ObjCCategoryName,
+ /// \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;
+
+ /// \brief The identifiers for Objective-C selector parts.
+ ArrayRef<IdentifierInfo *> SelIdents;
+
+public:
+ /// \brief Construct a new code-completion context of the given kind.
+ CodeCompletionContext(enum Kind Kind) : Kind(Kind), SelIdents(None) { }
+
+ /// \brief Construct a new code-completion context of the given kind.
+ CodeCompletionContext(enum Kind Kind, QualType T,
+ ArrayRef<IdentifierInfo *> SelIdents = None)
+ : Kind(Kind),
+ SelIdents(SelIdents) {
+ if (Kind == CCC_DotMemberAccess || Kind == CCC_ArrowMemberAccess ||
+ Kind == CCC_ObjCPropertyAccess || Kind == CCC_ObjCClassMessage ||
+ Kind == CCC_ObjCInstanceMessage)
+ 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 Retrieve the Objective-C selector identifiers.
+ ArrayRef<IdentifierInfo *> getSelIdents() const { return SelIdents; }
+
+ /// \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 Vertical 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(nullptr) { }
+
+ explicit 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 : 16;
+
+ /// \brief The number of annotations for this code-completion result.
+ unsigned NumAnnotations : 16;
+
+ /// \brief The priority of this code-completion string.
+ unsigned Priority : 16;
+
+ /// \brief The availability of this code-completion result.
+ unsigned Availability : 2;
+
+ /// \brief The name of the parent context.
+ StringRef ParentName;
+
+ /// \brief A brief documentation comment attached to the declaration of
+ /// entity being completed by this result.
+ const char *BriefComment;
+
+ CodeCompletionString(const CodeCompletionString &) = delete;
+ void operator=(const CodeCompletionString &) = delete;
+
+ CodeCompletionString(const Chunk *Chunks, unsigned NumChunks,
+ unsigned Priority, CXAvailabilityKind Availability,
+ const char **Annotations, unsigned NumAnnotations,
+ StringRef ParentName,
+ const char *BriefComment);
+ ~CodeCompletionString() = default;
+
+ 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 Retrieve the availability of this code completion result.
+ unsigned getAvailability() const { return Availability; }
+
+ /// \brief Retrieve the number of annotations for this code completion result.
+ unsigned getAnnotationCount() const;
+
+ /// \brief Retrieve the annotation string specified by \c AnnotationNr.
+ const char *getAnnotation(unsigned AnnotationNr) const;
+
+ /// \brief Retrieve the name of the parent context.
+ StringRef getParentContextName() const {
+ return ParentName;
+ }
+
+ const char *getBriefComment() const {
+ return BriefComment;
+ }
+
+ /// \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(const Twine &String);
+};
+
+/// \brief Allocator for a cached set of global code completions.
+class GlobalCodeCompletionAllocator
+ : public CodeCompletionAllocator,
+ public RefCountedBase<GlobalCodeCompletionAllocator>
+{
+
+};
+
+class CodeCompletionTUInfo {
+ llvm::DenseMap<const DeclContext *, StringRef> ParentNames;
+ IntrusiveRefCntPtr<GlobalCodeCompletionAllocator> AllocatorRef;
+
+public:
+ explicit CodeCompletionTUInfo(
+ IntrusiveRefCntPtr<GlobalCodeCompletionAllocator> Allocator)
+ : AllocatorRef(Allocator) { }
+
+ IntrusiveRefCntPtr<GlobalCodeCompletionAllocator> getAllocatorRef() const {
+ return AllocatorRef;
+ }
+ CodeCompletionAllocator &getAllocator() const {
+ assert(AllocatorRef);
+ return *AllocatorRef;
+ }
+
+ StringRef getParentName(const DeclContext *DC);
+};
+
+} // end namespace clang
+
+namespace llvm {
+ template <> struct isPodLike<clang::CodeCompletionString::Chunk> {
+ static const bool value = true;
+ };
+}
+
+namespace clang {
+
+/// \brief A builder class used to construct new code-completion strings.
+class CodeCompletionBuilder {
+public:
+ typedef CodeCompletionString::Chunk Chunk;
+
+private:
+ CodeCompletionAllocator &Allocator;
+ CodeCompletionTUInfo &CCTUInfo;
+ unsigned Priority;
+ CXAvailabilityKind Availability;
+ StringRef ParentName;
+ const char *BriefComment;
+
+ /// \brief The chunks stored in this string.
+ SmallVector<Chunk, 4> Chunks;
+
+ SmallVector<const char *, 2> Annotations;
+
+public:
+ CodeCompletionBuilder(CodeCompletionAllocator &Allocator,
+ CodeCompletionTUInfo &CCTUInfo)
+ : Allocator(Allocator), CCTUInfo(CCTUInfo),
+ Priority(0), Availability(CXAvailability_Available),
+ BriefComment(nullptr) { }
+
+ CodeCompletionBuilder(CodeCompletionAllocator &Allocator,
+ CodeCompletionTUInfo &CCTUInfo,
+ unsigned Priority, CXAvailabilityKind Availability)
+ : Allocator(Allocator), CCTUInfo(CCTUInfo),
+ Priority(Priority), Availability(Availability),
+ BriefComment(nullptr) { }
+
+ /// \brief Retrieve the allocator into which the code completion
+ /// strings should be allocated.
+ CodeCompletionAllocator &getAllocator() const { return Allocator; }
+
+ CodeCompletionTUInfo &getCodeCompletionTUInfo() const { return CCTUInfo; }
+
+ /// \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);
+
+ /// \brief Add a new text chunk.
+ void AddTextChunk(const char *Text);
+
+ /// \brief Add a new optional chunk.
+ void AddOptionalChunk(CodeCompletionString *Optional);
+
+ /// \brief Add a new placeholder chunk.
+ void AddPlaceholderChunk(const char *Placeholder);
+
+ /// \brief Add a new informative chunk.
+ void AddInformativeChunk(const char *Text);
+
+ /// \brief Add a new result-type chunk.
+ void AddResultTypeChunk(const char *ResultType);
+
+ /// \brief Add a new current-parameter chunk.
+ void AddCurrentParameterChunk(const char *CurrentParameter);
+
+ /// \brief Add a new chunk.
+ void AddChunk(CodeCompletionString::ChunkKind CK, const char *Text = "");
+
+ void AddAnnotation(const char *A) { Annotations.push_back(A); }
+
+ /// \brief Add the parent context information to this code completion.
+ void addParentContext(const DeclContext *DC);
+
+ const char *getBriefComment() const { return BriefComment; }
+ void addBriefComment(StringRef Comment);
+
+ StringRef getParentName() const { return ParentName; }
+};
+
+/// \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 When Kind == RK_Declaration or RK_Pattern, the declaration we are
+ /// referring to. In the latter case, the declaration might be NULL.
+ const NamedDecl *Declaration;
+
+ union {
+ /// \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.
+ const IdentifierInfo *Macro;
+ };
+
+ /// \brief The priority of this particular code-completion result.
+ unsigned Priority;
+
+ /// \brief Specifies which parameter (of a function, Objective-C method,
+ /// macro, etc.) we should start with when formatting the result.
+ unsigned StartParameter;
+
+ /// \brief The kind of result stored here.
+ ResultKind Kind;
+
+ /// \brief The cursor kind that describes this result.
+ CXCursorKind CursorKind;
+
+ /// \brief The availability of this result.
+ CXAvailabilityKind Availability;
+
+ /// \brief Whether this result is hidden by another name.
+ bool Hidden : 1;
+
+ /// \brief 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(const NamedDecl *Declaration,
+ unsigned Priority,
+ NestedNameSpecifier *Qualifier = nullptr,
+ bool QualifierIsInformative = false,
+ bool Accessible = true)
+ : Declaration(Declaration), Priority(Priority),
+ StartParameter(0), Kind(RK_Declaration),
+ Availability(CXAvailability_Available), Hidden(false),
+ QualifierIsInformative(QualifierIsInformative),
+ StartsNestedNameSpecifier(false), AllParametersAreInformative(false),
+ DeclaringEntity(false), Qualifier(Qualifier) {
+ computeCursorKindAndAvailability(Accessible);
+ }
+
+ /// \brief Build a result that refers to a keyword or symbol.
+ CodeCompletionResult(const char *Keyword, unsigned Priority = CCP_Keyword)
+ : Declaration(nullptr), Keyword(Keyword), Priority(Priority),
+ StartParameter(0), Kind(RK_Keyword), CursorKind(CXCursor_NotImplemented),
+ Availability(CXAvailability_Available), Hidden(false),
+ QualifierIsInformative(0), StartsNestedNameSpecifier(false),
+ AllParametersAreInformative(false), DeclaringEntity(false),
+ Qualifier(nullptr) {}
+
+ /// \brief Build a result that refers to a macro.
+ CodeCompletionResult(const IdentifierInfo *Macro,
+ unsigned Priority = CCP_Macro)
+ : Declaration(nullptr), Macro(Macro), Priority(Priority), StartParameter(0),
+ Kind(RK_Macro), CursorKind(CXCursor_MacroDefinition),
+ Availability(CXAvailability_Available), Hidden(false),
+ QualifierIsInformative(0), StartsNestedNameSpecifier(false),
+ AllParametersAreInformative(false), DeclaringEntity(false),
+ Qualifier(nullptr) {}
+
+ /// \brief Build a result that refers to a pattern.
+ CodeCompletionResult(CodeCompletionString *Pattern,
+ unsigned Priority = CCP_CodePattern,
+ CXCursorKind CursorKind = CXCursor_NotImplemented,
+ CXAvailabilityKind Availability = CXAvailability_Available,
+ const NamedDecl *D = nullptr)
+ : Declaration(D), Pattern(Pattern), Priority(Priority), StartParameter(0),
+ Kind(RK_Pattern), CursorKind(CursorKind), Availability(Availability),
+ Hidden(false), QualifierIsInformative(0),
+ StartsNestedNameSpecifier(false), AllParametersAreInformative(false),
+ DeclaringEntity(false), Qualifier(nullptr)
+ {
+ }
+
+ /// \brief Build a result that refers to a pattern with an associated
+ /// declaration.
+ CodeCompletionResult(CodeCompletionString *Pattern, NamedDecl *D,
+ unsigned Priority)
+ : Declaration(D), Pattern(Pattern), Priority(Priority), StartParameter(0),
+ Kind(RK_Pattern), Availability(CXAvailability_Available), Hidden(false),
+ QualifierIsInformative(false), StartsNestedNameSpecifier(false),
+ AllParametersAreInformative(false), DeclaringEntity(false),
+ Qualifier(nullptr) {
+ computeCursorKindAndAvailability();
+ }
+
+ /// \brief Retrieve the declaration stored in this result.
+ const 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,
+ const CodeCompletionContext &CCContext,
+ CodeCompletionAllocator &Allocator,
+ CodeCompletionTUInfo &CCTUInfo,
+ bool IncludeBriefComments);
+ CodeCompletionString *CreateCodeCompletionString(ASTContext &Ctx,
+ Preprocessor &PP,
+ const CodeCompletionContext &CCContext,
+ CodeCompletionAllocator &Allocator,
+ CodeCompletionTUInfo &CCTUInfo,
+ bool IncludeBriefComments);
+
+private:
+ void computeCursorKindAndAvailability(bool Accessible = true);
+};
+
+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);
+}
+
+
+raw_ostream &operator<<(raw_ostream &OS,
+ const CodeCompletionString &CCS);
+
+/// \brief Abstract interface for a consumer of code-completion
+/// information.
+class CodeCompleteConsumer {
+protected:
+ const CodeCompleteOptions CodeCompleteOpts;
+
+ /// \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,
+ CodeCompletionTUInfo &CCTUInfo,
+ bool IncludeBriefComments) const;
+ };
+
+ CodeCompleteConsumer(const CodeCompleteOptions &CodeCompleteOpts,
+ bool OutputIsBinary)
+ : CodeCompleteOpts(CodeCompleteOpts), OutputIsBinary(OutputIsBinary)
+ { }
+
+ /// \brief Whether the code-completion consumer wants to see macros.
+ bool includeMacros() const {
+ return CodeCompleteOpts.IncludeMacros;
+ }
+
+ /// \brief Whether the code-completion consumer wants to see code patterns.
+ bool includeCodePatterns() const {
+ return CodeCompleteOpts.IncludeCodePatterns;
+ }
+
+ /// \brief Whether to include global (top-level) declaration results.
+ bool includeGlobals() const {
+ return CodeCompleteOpts.IncludeGlobals;
+ }
+
+ /// \brief Whether to include brief documentation comments within the set of
+ /// code completions returned.
+ bool includeBriefComments() const {
+ return CodeCompleteOpts.IncludeBriefComments;
+ }
+
+ /// \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;
+
+ virtual CodeCompletionTUInfo &getCodeCompletionTUInfo() = 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.
+ raw_ostream &OS;
+
+ CodeCompletionTUInfo CCTUInfo;
+
+public:
+ /// \brief Create a new printing code-completion consumer that prints its
+ /// results to the given raw output stream.
+ PrintingCodeCompleteConsumer(const CodeCompleteOptions &CodeCompleteOpts,
+ raw_ostream &OS)
+ : CodeCompleteConsumer(CodeCompleteOpts, false), OS(OS),
+ CCTUInfo(new GlobalCodeCompletionAllocator) {}
+
+ /// \brief Prints the finalized code-completion results.
+ void ProcessCodeCompleteResults(Sema &S, CodeCompletionContext Context,
+ CodeCompletionResult *Results,
+ unsigned NumResults) override;
+
+ void ProcessOverloadCandidates(Sema &S, unsigned CurrentArg,
+ OverloadCandidate *Candidates,
+ unsigned NumCandidates) override;
+
+ CodeCompletionAllocator &getAllocator() override {
+ return CCTUInfo.getAllocator();
+ }
+
+ CodeCompletionTUInfo &getCodeCompletionTUInfo() override { return CCTUInfo; }
+};
+
+} // end namespace clang
+
+#endif // LLVM_CLANG_SEMA_CODECOMPLETECONSUMER_H
diff --git a/contrib/llvm/tools/clang/include/clang/Sema/CodeCompleteOptions.h b/contrib/llvm/tools/clang/include/clang/Sema/CodeCompleteOptions.h
new file mode 100644
index 0000000..fc7713c
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Sema/CodeCompleteOptions.h
@@ -0,0 +1,41 @@
+//===---- CodeCompleteOptions.h - Code Completion Options -------*- 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_SEMA_CODECOMPLETEOPTIONS_H
+#define LLVM_CLANG_SEMA_CODECOMPLETEOPTIONS_H
+
+namespace clang {
+
+/// Options controlling the behavior of code completion.
+class CodeCompleteOptions {
+public:
+ /// Show macros in code completion results.
+ unsigned IncludeMacros : 1;
+
+ /// Show code patterns in code completion results.
+ unsigned IncludeCodePatterns : 1;
+
+ /// Show top-level decls in code completion results.
+ unsigned IncludeGlobals : 1;
+
+ /// Show brief documentation comments in code completion results.
+ unsigned IncludeBriefComments : 1;
+
+ CodeCompleteOptions() :
+ IncludeMacros(0),
+ IncludeCodePatterns(0),
+ IncludeGlobals(1),
+ IncludeBriefComments(0)
+ { }
+};
+
+} // namespace clang
+
+#endif
+
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..e9fdb70
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Sema/DeclSpec.h
@@ -0,0 +1,2313 @@
+//===--- 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.
+//
+//===----------------------------------------------------------------------===//
+///
+/// \file
+/// \brief This file defines the classes used to store parsed information about
+/// declaration-specifiers and declarators.
+///
+/// \verbatim
+/// static const int volatile x, *y, *(*(*z)[10])(const void *x);
+/// ------------------------- - -- ---------------------------
+/// declaration-specifiers \ | /
+/// declarators
+/// \endverbatim
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_SEMA_DECLSPEC_H
+#define LLVM_CLANG_SEMA_DECLSPEC_H
+
+#include "clang/AST/NestedNameSpecifier.h"
+#include "clang/Basic/ExceptionSpecificationType.h"
+#include "clang/Basic/Lambda.h"
+#include "clang/Basic/OperatorKinds.h"
+#include "clang/Basic/Specifiers.h"
+#include "clang/Lex/Token.h"
+#include "clang/Sema/AttributeList.h"
+#include "clang/Sema/Ownership.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/Support/Compiler.h"
+#include "llvm/Support/ErrorHandling.h"
+
+namespace clang {
+ class ASTContext;
+ class CXXRecordDecl;
+ class TypeLoc;
+ class LangOptions;
+ class IdentifierInfo;
+ class NamespaceAliasDecl;
+ class NamespaceDecl;
+ class ObjCDeclSpec;
+ class Sema;
+ class Declarator;
+ struct TemplateIdAnnotation;
+
+/// \brief 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, identified 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;
+ NestedNameSpecifierLocBuilder Builder;
+
+public:
+ SourceRange getRange() const { return Range; }
+ void setRange(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(); }
+
+ /// \brief Retrieve the representation of the nested-name-specifier.
+ NestedNameSpecifier *getScopeRep() const {
+ return Builder.getRepresentation();
+ }
+
+ /// \brief Extend the current nested-name-specifier by another
+ /// nested-name-specifier component of the form 'type::'.
+ ///
+ /// \param Context The AST context in which this nested-name-specifier
+ /// resides.
+ ///
+ /// \param TemplateKWLoc The location of the 'template' keyword, if present.
+ ///
+ /// \param TL The TypeLoc that describes the type preceding the '::'.
+ ///
+ /// \param ColonColonLoc The location of the trailing '::'.
+ void Extend(ASTContext &Context, SourceLocation TemplateKWLoc, TypeLoc TL,
+ SourceLocation ColonColonLoc);
+
+ /// \brief Extend the current nested-name-specifier by another
+ /// nested-name-specifier component of the form 'identifier::'.
+ ///
+ /// \param Context The AST context in which this nested-name-specifier
+ /// resides.
+ ///
+ /// \param Identifier The identifier.
+ ///
+ /// \param IdentifierLoc The location of the identifier.
+ ///
+ /// \param ColonColonLoc The location of the trailing '::'.
+ void Extend(ASTContext &Context, IdentifierInfo *Identifier,
+ SourceLocation IdentifierLoc, SourceLocation ColonColonLoc);
+
+ /// \brief Extend the current nested-name-specifier by another
+ /// nested-name-specifier component of the form 'namespace::'.
+ ///
+ /// \param Context The AST context in which this nested-name-specifier
+ /// resides.
+ ///
+ /// \param Namespace The namespace.
+ ///
+ /// \param NamespaceLoc The location of the namespace name.
+ ///
+ /// \param ColonColonLoc The location of the trailing '::'.
+ void Extend(ASTContext &Context, NamespaceDecl *Namespace,
+ SourceLocation NamespaceLoc, SourceLocation ColonColonLoc);
+
+ /// \brief Extend the current nested-name-specifier by another
+ /// nested-name-specifier component of the form 'namespace-alias::'.
+ ///
+ /// \param Context The AST context in which this nested-name-specifier
+ /// resides.
+ ///
+ /// \param Alias The namespace alias.
+ ///
+ /// \param AliasLoc The location of the namespace alias
+ /// name.
+ ///
+ /// \param ColonColonLoc The location of the trailing '::'.
+ void Extend(ASTContext &Context, NamespaceAliasDecl *Alias,
+ SourceLocation AliasLoc, SourceLocation ColonColonLoc);
+
+ /// \brief Turn this (empty) nested-name-specifier into the global
+ /// nested-name-specifier '::'.
+ void MakeGlobal(ASTContext &Context, SourceLocation ColonColonLoc);
+
+ /// \brief Turns this (empty) nested-name-specifier into '__super'
+ /// nested-name-specifier.
+ ///
+ /// \param Context The AST context in which this nested-name-specifier
+ /// resides.
+ ///
+ /// \param RD The declaration of the class in which nested-name-specifier
+ /// appeared.
+ ///
+ /// \param SuperLoc The location of the '__super' keyword.
+ /// name.
+ ///
+ /// \param ColonColonLoc The location of the trailing '::'.
+ void MakeSuper(ASTContext &Context, CXXRecordDecl *RD,
+ SourceLocation SuperLoc, SourceLocation ColonColonLoc);
+
+ /// \brief Make a new nested-name-specifier from incomplete source-location
+ /// information.
+ ///
+ /// FIXME: This routine should be used very, very rarely, in cases where we
+ /// need to synthesize a nested-name-specifier. Most code should instead use
+ /// \c Adopt() with a proper \c NestedNameSpecifierLoc.
+ void MakeTrivial(ASTContext &Context, NestedNameSpecifier *Qualifier,
+ SourceRange R);
+
+ /// \brief Adopt an existing nested-name-specifier (with source-range
+ /// information).
+ void Adopt(NestedNameSpecifierLoc Other);
+
+ /// \brief Retrieve a nested-name-specifier with location information, copied
+ /// into the given AST context.
+ ///
+ /// \param Context The context into which this nested-name-specifier will be
+ /// copied.
+ NestedNameSpecifierLoc getWithLocInContext(ASTContext &Context) const;
+
+ /// \brief Retrieve the location of the name in the last qualifier
+ /// in this nested name specifier.
+ ///
+ /// For example, the location of \c bar
+ /// in
+ /// \verbatim
+ /// \::foo::bar<0>::
+ /// ^~~
+ /// \endverbatim
+ SourceLocation getLastQualifierNameLoc() const;
+
+ /// 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 occurred during parsing of the scope specifier.
+ bool isInvalid() const { return isNotEmpty() && getScopeRep() == nullptr; }
+ /// A scope specifier is present, and it refers to a real scope.
+ bool isValid() const { return isNotEmpty() && getScopeRep() != nullptr; }
+
+ /// \brief Indicate that this nested-name-specifier is invalid.
+ void SetInvalid(SourceRange R) {
+ assert(R.isValid() && "Must have a valid source range");
+ if (Range.getBegin().isInvalid())
+ Range.setBegin(R.getBegin());
+ Range.setEnd(R.getEnd());
+ Builder.Clear();
+ }
+
+ /// Deprecated. Some call sites intend isNotEmpty() while others intend
+ /// isValid().
+ bool isSet() const { return getScopeRep() != nullptr; }
+
+ void clear() {
+ Range = SourceRange();
+ Builder.Clear();
+ }
+
+ /// \brief Retrieve the data associated with the source-location information.
+ char *location_data() const { return Builder.getBuffer().first; }
+
+ /// \brief Retrieve the size of the data associated with source-location
+ /// information.
+ unsigned location_size() const { return Builder.getBuffer().second; }
+};
+
+/// \brief Captures information about "declaration specifiers".
+///
+/// "Declaration specifiers" encompasses storage-class-specifiers,
+/// type-specifiers, type-qualifiers, and function-specifiers.
+class DeclSpec {
+public:
+ /// \brief 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 thread storage class specifier enumeration and constants.
+ // These can be combined with SCS_extern and SCS_static.
+ typedef ThreadStorageClassSpecifier TSCS;
+ static const TSCS TSCS_unspecified = clang::TSCS_unspecified;
+ static const TSCS TSCS___thread = clang::TSCS___thread;
+ static const TSCS TSCS_thread_local = clang::TSCS_thread_local;
+ static const TSCS TSCS__Thread_local = clang::TSCS__Thread_local;
+
+ // 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_int128 = clang::TST_int128;
+ static const TST TST_half = clang::TST_half;
+ 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_interface = clang::TST_interface;
+ 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_decltype_auto = clang::TST_decltype_auto;
+ static const TST TST_underlyingType = clang::TST_underlyingType;
+ static const TST TST_auto = clang::TST_auto;
+ static const TST TST_auto_type = clang::TST_auto_type;
+ static const TST TST_unknown_anytype = clang::TST_unknown_anytype;
+ static const TST TST_atomic = clang::TST_atomic;
+ 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,
+ // This has no corresponding Qualifiers::TQ value, because it's not treated
+ // as a qualifier in our type system.
+ TQ_atomic = 8
+ };
+
+ /// 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;
+ /*TSCS*/unsigned ThreadStorageClassSpec : 2;
+ unsigned SCS_extern_in_linkage_spec : 1;
+
+ // type-specifier
+ /*TSW*/unsigned TypeSpecWidth : 2;
+ /*TSC*/unsigned TypeSpecComplex : 2;
+ /*TSS*/unsigned TypeSpecSign : 2;
+ /*TST*/unsigned TypeSpecType : 6;
+ unsigned TypeAltiVecVector : 1;
+ unsigned TypeAltiVecPixel : 1;
+ unsigned TypeAltiVecBool : 1;
+ unsigned TypeSpecOwned : 1;
+
+ // type-qualifiers
+ unsigned TypeQualifiers : 4; // Bitwise OR of TQ.
+
+ // function-specifier
+ unsigned FS_inline_specified : 1;
+ unsigned FS_forceinline_specified: 1;
+ unsigned FS_virtual_specified : 1;
+ unsigned FS_explicit_specified : 1;
+ unsigned FS_noreturn_specified : 1;
+
+ // friend-specifier
+ unsigned Friend_specified : 1;
+
+ // constexpr-specifier
+ unsigned Constexpr_specified : 1;
+
+ // concept-specifier
+ unsigned Concept_specified : 1;
+
+ union {
+ UnionParsedType TypeRep;
+ Decl *DeclRep;
+ Expr *ExprRep;
+ };
+
+ // attributes.
+ ParsedAttributes Attrs;
+
+ // Scope specifier for the type spec, if applicable.
+ CXXScopeSpec TypeScope;
+
+ // SourceLocation info. These are null if the item wasn't specified or if
+ // the setting was synthesized.
+ SourceRange Range;
+
+ SourceLocation StorageClassSpecLoc, ThreadStorageClassSpecLoc;
+ SourceLocation TSWLoc, TSCLoc, TSSLoc, TSTLoc, AltiVecLoc;
+ /// TSTNameLoc - If TypeSpecType is any of class, enum, struct, union,
+ /// typename, then this is the location of the named type (if present);
+ /// otherwise, it is the same as TSTLoc. Hence, the pair TSTLoc and
+ /// TSTNameLoc provides source range info for tag types.
+ SourceLocation TSTNameLoc;
+ SourceRange TypeofParensRange;
+ SourceLocation TQ_constLoc, TQ_restrictLoc, TQ_volatileLoc, TQ_atomicLoc;
+ SourceLocation FS_inlineLoc, FS_virtualLoc, FS_explicitLoc, FS_noreturnLoc;
+ SourceLocation FS_forceinlineLoc;
+ SourceLocation FriendLoc, ModulePrivateLoc, ConstexprLoc, ConceptLoc;
+
+ WrittenBuiltinSpecs writtenBS;
+ void SaveWrittenBuiltinSpecs();
+
+ ObjCDeclSpec *ObjCQualifiers;
+
+ static bool isTypeRep(TST T) {
+ return (T == TST_typename || T == TST_typeofType ||
+ T == TST_underlyingType || T == TST_atomic);
+ }
+ static bool isExprRep(TST T) {
+ return (T == TST_typeofExpr || T == TST_decltype);
+ }
+
+ DeclSpec(const DeclSpec &) = delete;
+ void operator=(const DeclSpec &) = delete;
+public:
+ static bool isDeclRep(TST T) {
+ return (T == TST_enum || T == TST_struct ||
+ T == TST_interface || T == TST_union ||
+ T == TST_class);
+ }
+
+ DeclSpec(AttributeFactory &attrFactory)
+ : StorageClassSpec(SCS_unspecified),
+ ThreadStorageClassSpec(TSCS_unspecified),
+ 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(TQ_unspecified),
+ FS_inline_specified(false),
+ FS_forceinline_specified(false),
+ FS_virtual_specified(false),
+ FS_explicit_specified(false),
+ FS_noreturn_specified(false),
+ Friend_specified(false),
+ Constexpr_specified(false),
+ Concept_specified(false),
+ Attrs(attrFactory),
+ writtenBS(),
+ ObjCQualifiers(nullptr) {
+ }
+
+ // storage-class-specifier
+ SCS getStorageClassSpec() const { return (SCS)StorageClassSpec; }
+ TSCS getThreadStorageClassSpec() const {
+ return (TSCS)ThreadStorageClassSpec;
+ }
+ 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 getThreadStorageClassSpecLoc() const {
+ return ThreadStorageClassSpecLoc;
+ }
+
+ void ClearStorageClassSpecs() {
+ StorageClassSpec = DeclSpec::SCS_unspecified;
+ ThreadStorageClassSpec = DeclSpec::TSCS_unspecified;
+ SCS_extern_in_linkage_spec = false;
+ StorageClassSpecLoc = SourceLocation();
+ ThreadStorageClassSpecLoc = SourceLocation();
+ }
+
+ void ClearTypeSpecType() {
+ TypeSpecType = DeclSpec::TST_unspecified;
+ TypeSpecOwned = false;
+ TSTLoc = 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; }
+ bool isTypeRep() const { return isTypeRep((TST) TypeSpecType); }
+
+ 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; }
+
+ SourceRange getSourceRange() const LLVM_READONLY { return Range; }
+ SourceLocation getLocStart() const LLVM_READONLY { return Range.getBegin(); }
+ SourceLocation getLocEnd() const LLVM_READONLY { return Range.getEnd(); }
+
+ 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; }
+
+ SourceLocation getTypeSpecTypeNameLoc() const {
+ assert(isDeclRep((TST) TypeSpecType) || TypeSpecType == TST_typename);
+ return TSTNameLoc;
+ }
+
+ SourceRange getTypeofParensRange() const { return TypeofParensRange; }
+ void setTypeofParensRange(SourceRange range) { TypeofParensRange = range; }
+
+ bool containsPlaceholderType() const {
+ return (TypeSpecType == TST_auto || TypeSpecType == TST_auto_type ||
+ TypeSpecType == TST_decltype_auto);
+ }
+
+ bool hasTagDefinition() const;
+
+ /// \brief Turn a type-specifier-type into a string like "_Bool" or "union".
+ static const char *getSpecifierName(DeclSpec::TST T,
+ const PrintingPolicy &Policy);
+ 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);
+ static const char *getSpecifierName(DeclSpec::TSCS 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; }
+ SourceLocation getAtomicSpecLoc() const { return TQ_atomicLoc; }
+
+ /// \brief Clear out all of the type qualifiers.
+ void ClearTypeQualifiers() {
+ TypeQualifiers = 0;
+ TQ_constLoc = SourceLocation();
+ TQ_restrictLoc = SourceLocation();
+ TQ_volatileLoc = SourceLocation();
+ TQ_atomicLoc = SourceLocation();
+ }
+
+ // function-specifier
+ bool isInlineSpecified() const {
+ return FS_inline_specified | FS_forceinline_specified;
+ }
+ SourceLocation getInlineSpecLoc() const {
+ return FS_inline_specified ? FS_inlineLoc : FS_forceinlineLoc;
+ }
+
+ 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; }
+
+ bool isNoreturnSpecified() const { return FS_noreturn_specified; }
+ SourceLocation getNoreturnSpecLoc() const { return FS_noreturnLoc; }
+
+ void ClearFunctionSpecs() {
+ FS_inline_specified = false;
+ FS_inlineLoc = SourceLocation();
+ FS_forceinline_specified = false;
+ FS_forceinlineLoc = SourceLocation();
+ FS_virtual_specified = false;
+ FS_virtualLoc = SourceLocation();
+ FS_explicit_specified = false;
+ FS_explicitLoc = SourceLocation();
+ FS_noreturn_specified = false;
+ FS_noreturnLoc = SourceLocation();
+ }
+
+ /// \brief 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;
+ }
+
+ /// \brief Return a bitmask of which flavors of specifiers this
+ /// DeclSpec includes.
+ unsigned getParsedSpecifiers() const;
+
+ /// 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(Sema &S, SCS SC, SourceLocation Loc,
+ const char *&PrevSpec, unsigned &DiagID,
+ const PrintingPolicy &Policy);
+ bool SetStorageClassSpecThread(TSCS TSC, SourceLocation Loc,
+ const char *&PrevSpec, unsigned &DiagID);
+ bool SetTypeSpecWidth(TSW W, SourceLocation Loc, const char *&PrevSpec,
+ unsigned &DiagID, const PrintingPolicy &Policy);
+ 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, const PrintingPolicy &Policy);
+ bool SetTypeSpecType(TST T, SourceLocation Loc, const char *&PrevSpec,
+ unsigned &DiagID, ParsedType Rep,
+ const PrintingPolicy &Policy);
+ bool SetTypeSpecType(TST T, SourceLocation Loc, const char *&PrevSpec,
+ unsigned &DiagID, Decl *Rep, bool Owned,
+ const PrintingPolicy &Policy);
+ bool SetTypeSpecType(TST T, SourceLocation TagKwLoc,
+ SourceLocation TagNameLoc, const char *&PrevSpec,
+ unsigned &DiagID, ParsedType Rep,
+ const PrintingPolicy &Policy);
+ bool SetTypeSpecType(TST T, SourceLocation TagKwLoc,
+ SourceLocation TagNameLoc, const char *&PrevSpec,
+ unsigned &DiagID, Decl *Rep, bool Owned,
+ const PrintingPolicy &Policy);
+
+ bool SetTypeSpecType(TST T, SourceLocation Loc, const char *&PrevSpec,
+ unsigned &DiagID, Expr *Rep,
+ const PrintingPolicy &policy);
+ bool SetTypeAltiVecVector(bool isAltiVecVector, SourceLocation Loc,
+ const char *&PrevSpec, unsigned &DiagID,
+ const PrintingPolicy &Policy);
+ bool SetTypeAltiVecPixel(bool isAltiVecPixel, SourceLocation Loc,
+ const char *&PrevSpec, unsigned &DiagID,
+ const PrintingPolicy &Policy);
+ bool SetTypeAltiVecBool(bool isAltiVecBool, SourceLocation Loc,
+ const char *&PrevSpec, unsigned &DiagID,
+ const PrintingPolicy &Policy);
+ 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 setFunctionSpecForceInline(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 setFunctionSpecNoreturn(SourceLocation Loc, const char *&PrevSpec,
+ unsigned &DiagID);
+
+ bool SetFriendSpec(SourceLocation Loc, const char *&PrevSpec,
+ unsigned &DiagID);
+ bool setModulePrivateSpec(SourceLocation Loc, const char *&PrevSpec,
+ unsigned &DiagID);
+ bool SetConstexprSpec(SourceLocation Loc, const char *&PrevSpec,
+ unsigned &DiagID);
+ bool SetConceptSpec(SourceLocation Loc, const char *&PrevSpec,
+ unsigned &DiagID);
+
+ bool isFriendSpecified() const { return Friend_specified; }
+ SourceLocation getFriendSpecLoc() const { return FriendLoc; }
+
+ bool isModulePrivateSpecified() const { return ModulePrivateLoc.isValid(); }
+ SourceLocation getModulePrivateSpecLoc() const { return ModulePrivateLoc; }
+
+ bool isConstexprSpecified() const { return Constexpr_specified; }
+ SourceLocation getConstexprSpecLoc() const { return ConstexprLoc; }
+
+ bool isConceptSpecified() const { return Concept_specified; }
+ SourceLocation getConceptSpecLoc() const { return ConceptLoc; }
+
+ void ClearConstexprSpec() {
+ Constexpr_specified = false;
+ ConstexprLoc = SourceLocation();
+ }
+
+ void ClearConceptSpec() {
+ Concept_specified = false;
+ ConceptLoc = SourceLocation();
+ }
+
+ AttributePool &getAttributePool() const {
+ return Attrs.getPool();
+ }
+
+ /// \brief Concatenates two attribute lists.
+ ///
+ /// The GCC attribute syntax allows for the following:
+ ///
+ /// \code
+ /// short __attribute__(( unused, deprecated ))
+ /// int __attribute__(( may_alias, aligned(16) )) var;
+ /// \endcode
+ ///
+ /// This declares 4 attributes using 2 lists. The following syntax is
+ /// also allowed and equivalent to the previous declaration.
+ ///
+ /// \code
+ /// short __attribute__((unused)) __attribute__((deprecated))
+ /// int __attribute__((may_alias)) __attribute__((aligned(16))) var;
+ /// \endcode
+ ///
+ void addAttributes(AttributeList *AL) {
+ Attrs.addAll(AL);
+ }
+
+ bool hasAttributes() const { return !Attrs.empty(); }
+
+ ParsedAttributes &getAttributes() { return Attrs; }
+ const ParsedAttributes &getAttributes() const { return Attrs; }
+
+ void takeAttributesFrom(ParsedAttributes &attrs) {
+ Attrs.takeAllFrom(attrs);
+ }
+
+ /// 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(Sema &S, const PrintingPolicy &Policy);
+
+ const WrittenBuiltinSpecs& getWrittenBuiltinSpecs() const {
+ return writtenBS;
+ }
+
+ ObjCDeclSpec *getObjCQualifiers() const { return ObjCQualifiers; }
+ void setObjCQualifiers(ObjCDeclSpec *quals) { ObjCQualifiers = quals; }
+
+ /// \brief Checks if this DeclSpec can stand alone, without a Declarator.
+ ///
+ /// Only tag declspecs can stand alone.
+ bool isMissingDeclaratorOk();
+};
+
+/// \brief Captures information about "declaration specifiers" specific to
+/// Objective-C.
+class ObjCDeclSpec {
+public:
+ /// ObjCDeclQualifier - Qualifier used on types in method
+ /// declarations. Not all combinations are sensible. Parameters
+ /// can be one of { in, out, inout } with one of { bycopy, byref }.
+ /// Returns can either be { oneway } or not.
+ ///
+ /// This should be kept in sync with Decl::ObjCDeclQualifier.
+ enum ObjCDeclQualifier {
+ DQ_None = 0x0,
+ DQ_In = 0x1,
+ DQ_Inout = 0x2,
+ DQ_Out = 0x4,
+ DQ_Bycopy = 0x8,
+ DQ_Byref = 0x10,
+ DQ_Oneway = 0x20,
+ DQ_CSNullability = 0x40
+ };
+
+ /// 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,
+ DQ_PR_weak = 0x200,
+ DQ_PR_strong = 0x400,
+ DQ_PR_unsafe_unretained = 0x800,
+ DQ_PR_nullability = 0x1000,
+ DQ_PR_null_resettable = 0x2000
+ };
+
+ ObjCDeclSpec()
+ : objcDeclQualifier(DQ_None), PropertyAttributes(DQ_PR_noattr),
+ Nullability(0), GetterName(nullptr), SetterName(nullptr) { }
+
+ ObjCDeclQualifier getObjCDeclQualifier() const { return objcDeclQualifier; }
+ void setObjCDeclQualifier(ObjCDeclQualifier DQVal) {
+ objcDeclQualifier = (ObjCDeclQualifier) (objcDeclQualifier | DQVal);
+ }
+ void clearObjCDeclQualifier(ObjCDeclQualifier DQVal) {
+ objcDeclQualifier = (ObjCDeclQualifier) (objcDeclQualifier & ~DQVal);
+ }
+
+ ObjCPropertyAttributeKind getPropertyAttributes() const {
+ return ObjCPropertyAttributeKind(PropertyAttributes);
+ }
+ void setPropertyAttributes(ObjCPropertyAttributeKind PRVal) {
+ PropertyAttributes =
+ (ObjCPropertyAttributeKind)(PropertyAttributes | PRVal);
+ }
+
+ NullabilityKind getNullability() const {
+ assert(((getObjCDeclQualifier() & DQ_CSNullability) ||
+ (getPropertyAttributes() & DQ_PR_nullability)) &&
+ "Objective-C declspec doesn't have nullability");
+ return static_cast<NullabilityKind>(Nullability);
+ }
+
+ SourceLocation getNullabilityLoc() const {
+ assert(((getObjCDeclQualifier() & DQ_CSNullability) ||
+ (getPropertyAttributes() & DQ_PR_nullability)) &&
+ "Objective-C declspec doesn't have nullability");
+ return NullabilityLoc;
+ }
+
+ void setNullability(SourceLocation loc, NullabilityKind kind) {
+ assert(((getObjCDeclQualifier() & DQ_CSNullability) ||
+ (getPropertyAttributes() & DQ_PR_nullability)) &&
+ "Set the nullability declspec or property attribute first");
+ Nullability = static_cast<unsigned>(kind);
+ NullabilityLoc = loc;
+ }
+
+ 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 mutually exclusive. So perhaps
+ // we can put them in a union to reflect their mutual exclusivity
+ // (space saving is negligible).
+ ObjCDeclQualifier objcDeclQualifier : 7;
+
+ // NOTE: VC++ treats enums as signed, avoid using ObjCPropertyAttributeKind
+ unsigned PropertyAttributes : 14;
+
+ unsigned Nullability : 2;
+
+ SourceLocation NullabilityLoc;
+
+ IdentifierInfo *GetterName; // getter name or NULL if no getter
+ IdentifierInfo *SetterName; // setter name or NULL if no setter
+};
+
+/// \brief Represents a C++ unqualified-id that has been parsed.
+class UnqualifiedId {
+private:
+ UnqualifiedId(const UnqualifiedId &Other) = delete;
+ const UnqualifiedId &operator=(const UnqualifiedId &) = delete;
+
+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,
+ /// \brief An implicit 'self' parameter
+ IK_ImplicitSelfParam
+ } Kind;
+
+ struct OFI {
+ /// \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];
+ };
+
+ /// \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 OFI 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(nullptr) { }
+
+ /// \brief Clear out this unqualified-id, setting it to default (invalid)
+ /// state.
+ void clear() {
+ Kind = IK_Identifier;
+ Identifier = nullptr;
+ StartLocation = SourceLocation();
+ EndLocation = SourceLocation();
+ }
+
+ /// \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; }
+ void setKind(IdKind kind) { Kind = 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 LLVM_READONLY {
+ return SourceRange(StartLocation, EndLocation);
+ }
+ SourceLocation getLocStart() const LLVM_READONLY { return StartLocation; }
+ SourceLocation getLocEnd() const LLVM_READONLY { return EndLocation; }
+};
+
+/// \brief A set of tokens that has been cached for later parsing.
+typedef SmallVector<Token, 4> CachedTokens;
+
+/// \brief 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;
+
+ SourceRange getSourceRange() const {
+ if (EndLoc.isInvalid())
+ return SourceRange(Loc, Loc);
+ return SourceRange(Loc, EndLoc);
+ }
+
+ struct TypeInfoCommon {
+ AttributeList *AttrList;
+ };
+
+ struct PointerTypeInfo : TypeInfoCommon {
+ /// The type qualifiers: const/volatile/restrict/atomic.
+ unsigned TypeQuals : 4;
+
+ /// The location of the const-qualifier, if any.
+ unsigned ConstQualLoc;
+
+ /// The location of the volatile-qualifier, if any.
+ unsigned VolatileQualLoc;
+
+ /// The location of the restrict-qualifier, if any.
+ unsigned RestrictQualLoc;
+
+ /// The location of the _Atomic-qualifier, if any.
+ unsigned AtomicQualLoc;
+
+ 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/_Atomic.
+ unsigned TypeQuals : 4;
+
+ /// 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 parameters
+ /// 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 = nullptr)
+ : 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
+ /// parameter. 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;
+
+ /// Can this declaration be a constructor-style initializer?
+ unsigned isAmbiguous : 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;
+
+ /// ExceptionSpecType - An ExceptionSpecificationType value.
+ unsigned ExceptionSpecType : 4;
+
+ /// DeleteParams - If this is true, we need to delete[] Params.
+ unsigned DeleteParams : 1;
+
+ /// HasTrailingReturnType - If this is true, a trailing return type was
+ /// specified.
+ unsigned HasTrailingReturnType : 1;
+
+ /// The location of the left parenthesis in the source.
+ unsigned LParenLoc;
+
+ /// When isVariadic is true, the location of the ellipsis in the source.
+ unsigned EllipsisLoc;
+
+ /// The location of the right parenthesis in the source.
+ unsigned RParenLoc;
+
+ /// NumParams - This is the number of formal parameters specified by the
+ /// declarator.
+ unsigned NumParams;
+
+ /// NumExceptions - This is the number of types in the dynamic-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;
+
+ /// \brief The location of the const-qualifier, if any.
+ ///
+ /// If this is an invalid location, there is no const-qualifier.
+ unsigned ConstQualifierLoc;
+
+ /// \brief The location of the volatile-qualifier, if any.
+ ///
+ /// If this is an invalid location, there is no volatile-qualifier.
+ unsigned VolatileQualifierLoc;
+
+ /// \brief The location of the restrict-qualifier, if any.
+ ///
+ /// If this is an invalid location, there is no restrict-qualifier.
+ unsigned RestrictQualifierLoc;
+
+ /// \brief The location of the 'mutable' qualifer in a lambda-declarator, if
+ /// any.
+ unsigned MutableLoc;
+
+ /// \brief The beginning location of the exception specification, if any.
+ unsigned ExceptionSpecLocBeg;
+
+ /// \brief The end location of the exception specification, if any.
+ unsigned ExceptionSpecLocEnd;
+
+ /// Params - This is a pointer to a new[]'d array of ParamInfo objects that
+ /// describe the parameters specified by this function declarator. null if
+ /// there are no parameters specified.
+ ParamInfo *Params;
+
+ union {
+ /// \brief Pointer to a new[]'d array of TypeAndRange objects that
+ /// contain the types in the function's dynamic exception specification
+ /// and their locations, if there is one.
+ TypeAndRange *Exceptions;
+
+ /// \brief Pointer to the expression in the noexcept-specifier of this
+ /// function, if it has one.
+ Expr *NoexceptExpr;
+
+ /// \brief Pointer to the cached tokens for an exception-specification
+ /// that has not yet been parsed.
+ CachedTokens *ExceptionSpecTokens;
+ };
+
+ /// \brief If HasTrailingReturnType is true, this is the trailing return
+ /// type specified.
+ UnionParsedType TrailingReturnType;
+
+ /// \brief Reset the parameter list to having zero parameters.
+ ///
+ /// This is used in various places for error recovery.
+ void freeParams() {
+ for (unsigned I = 0; I < NumParams; ++I) {
+ delete Params[I].DefaultArgTokens;
+ Params[I].DefaultArgTokens = nullptr;
+ }
+ if (DeleteParams) {
+ delete[] Params;
+ DeleteParams = false;
+ }
+ NumParams = 0;
+ }
+
+ void destroy() {
+ if (DeleteParams)
+ delete[] Params;
+ if (getExceptionSpecType() == EST_Dynamic)
+ delete[] Exceptions;
+ else if (getExceptionSpecType() == EST_Unparsed)
+ delete ExceptionSpecTokens;
+ }
+
+ /// 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 parameter type definitions.
+ bool isKNRPrototype() const { return !hasPrototype && NumParams != 0; }
+
+ SourceLocation getLParenLoc() const {
+ return SourceLocation::getFromRawEncoding(LParenLoc);
+ }
+
+ SourceLocation getEllipsisLoc() const {
+ return SourceLocation::getFromRawEncoding(EllipsisLoc);
+ }
+
+ SourceLocation getRParenLoc() const {
+ return SourceLocation::getFromRawEncoding(RParenLoc);
+ }
+
+ SourceLocation getExceptionSpecLocBeg() const {
+ return SourceLocation::getFromRawEncoding(ExceptionSpecLocBeg);
+ }
+
+ SourceLocation getExceptionSpecLocEnd() const {
+ return SourceLocation::getFromRawEncoding(ExceptionSpecLocEnd);
+ }
+
+ SourceRange getExceptionSpecRange() const {
+ return SourceRange(getExceptionSpecLocBeg(), getExceptionSpecLocEnd());
+ }
+
+ /// \brief Retrieve the location of the ref-qualifier, if any.
+ SourceLocation getRefQualifierLoc() const {
+ return SourceLocation::getFromRawEncoding(RefQualifierLoc);
+ }
+
+ /// \brief Retrieve the location of the 'const' qualifier, if any.
+ SourceLocation getConstQualifierLoc() const {
+ return SourceLocation::getFromRawEncoding(ConstQualifierLoc);
+ }
+
+ /// \brief Retrieve the location of the 'volatile' qualifier, if any.
+ SourceLocation getVolatileQualifierLoc() const {
+ return SourceLocation::getFromRawEncoding(VolatileQualifierLoc);
+ }
+
+ /// \brief Retrieve the location of the 'restrict' qualifier, if any.
+ SourceLocation getRestrictQualifierLoc() const {
+ return SourceLocation::getFromRawEncoding(RestrictQualifierLoc);
+ }
+
+ /// \brief Retrieve the location of the 'mutable' qualifier, if any.
+ SourceLocation getMutableLoc() const {
+ return SourceLocation::getFromRawEncoding(MutableLoc);
+ }
+
+ /// \brief Determine whether this function declaration contains a
+ /// ref-qualifier.
+ bool hasRefQualifier() const { return getRefQualifierLoc().isValid(); }
+
+ /// \brief Determine whether this lambda-declarator contains a 'mutable'
+ /// qualifier.
+ bool hasMutableQualifier() const { return getMutableLoc().isValid(); }
+
+ /// \brief Get the type of exception specification this function has.
+ ExceptionSpecificationType getExceptionSpecType() const {
+ return static_cast<ExceptionSpecificationType>(ExceptionSpecType);
+ }
+
+ /// \brief Determine whether this function declarator had a
+ /// trailing-return-type.
+ bool hasTrailingReturnType() const { return HasTrailingReturnType; }
+
+ /// \brief Get the trailing-return-type for this function declarator.
+ ParsedType getTrailingReturnType() const { return TrailingReturnType; }
+ };
+
+ struct BlockPointerTypeInfo : TypeInfoCommon {
+ /// For now, sema will catch these as invalid.
+ /// The type qualifiers: const/volatile/restrict/_Atomic.
+ unsigned TypeQuals : 4;
+
+ void destroy() {
+ }
+ };
+
+ struct MemberPointerTypeInfo : TypeInfoCommon {
+ /// The type qualifiers: const/volatile/restrict/_Atomic.
+ unsigned TypeQuals : 4;
+ // 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) {
+ 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;
+ }
+ }
+
+ /// \brief If there are attributes applied to this declaratorchunk, return
+ /// them.
+ const AttributeList *getAttrs() const {
+ return Common.AttrList;
+ }
+
+ AttributeList *&getAttrListRef() {
+ return Common.AttrList;
+ }
+
+ /// \brief Return a DeclaratorChunk for a pointer.
+ static DeclaratorChunk getPointer(unsigned TypeQuals, SourceLocation Loc,
+ SourceLocation ConstQualLoc,
+ SourceLocation VolatileQualLoc,
+ SourceLocation RestrictQualLoc,
+ SourceLocation AtomicQualLoc) {
+ DeclaratorChunk I;
+ I.Kind = Pointer;
+ I.Loc = Loc;
+ I.Ptr.TypeQuals = TypeQuals;
+ I.Ptr.ConstQualLoc = ConstQualLoc.getRawEncoding();
+ I.Ptr.VolatileQualLoc = VolatileQualLoc.getRawEncoding();
+ I.Ptr.RestrictQualLoc = RestrictQualLoc.getRawEncoding();
+ I.Ptr.AtomicQualLoc = AtomicQualLoc.getRawEncoding();
+ I.Ptr.AttrList = nullptr;
+ return I;
+ }
+
+ /// \brief Return a DeclaratorChunk for a reference.
+ static DeclaratorChunk getReference(unsigned TypeQuals, SourceLocation Loc,
+ 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 = nullptr;
+ return I;
+ }
+
+ /// \brief Return a DeclaratorChunk for an array.
+ static DeclaratorChunk getArray(unsigned TypeQuals,
+ bool isStatic, bool isStar, Expr *NumElts,
+ SourceLocation LBLoc, SourceLocation RBLoc) {
+ DeclaratorChunk I;
+ I.Kind = Array;
+ I.Loc = LBLoc;
+ I.EndLoc = RBLoc;
+ I.Arr.AttrList = nullptr;
+ 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(bool HasProto,
+ bool IsAmbiguous,
+ SourceLocation LParenLoc,
+ ParamInfo *Params, unsigned NumParams,
+ SourceLocation EllipsisLoc,
+ SourceLocation RParenLoc,
+ unsigned TypeQuals,
+ bool RefQualifierIsLvalueRef,
+ SourceLocation RefQualifierLoc,
+ SourceLocation ConstQualifierLoc,
+ SourceLocation VolatileQualifierLoc,
+ SourceLocation RestrictQualifierLoc,
+ SourceLocation MutableLoc,
+ ExceptionSpecificationType ESpecType,
+ SourceRange ESpecRange,
+ ParsedType *Exceptions,
+ SourceRange *ExceptionRanges,
+ unsigned NumExceptions,
+ Expr *NoexceptExpr,
+ CachedTokens *ExceptionSpecTokens,
+ SourceLocation LocalRangeBegin,
+ SourceLocation LocalRangeEnd,
+ Declarator &TheDeclarator,
+ TypeResult TrailingReturnType =
+ TypeResult());
+
+ /// \brief Return a DeclaratorChunk for a block.
+ static DeclaratorChunk getBlockPointer(unsigned TypeQuals,
+ SourceLocation Loc) {
+ DeclaratorChunk I;
+ I.Kind = BlockPointer;
+ I.Loc = Loc;
+ I.Cls.TypeQuals = TypeQuals;
+ I.Cls.AttrList = nullptr;
+ return I;
+ }
+
+ static DeclaratorChunk getMemberPointer(const CXXScopeSpec &SS,
+ unsigned TypeQuals,
+ SourceLocation Loc) {
+ DeclaratorChunk I;
+ I.Kind = MemberPointer;
+ I.Loc = SS.getBeginLoc();
+ I.EndLoc = Loc;
+ I.Mem.TypeQuals = TypeQuals;
+ I.Mem.AttrList = nullptr;
+ new (I.Mem.ScopeMem.Mem) CXXScopeSpec(SS);
+ return I;
+ }
+
+ /// \brief 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 = nullptr;
+ return I;
+ }
+
+ bool isParen() const {
+ return Kind == Paren;
+ }
+};
+
+/// \brief Described the kind of function definition (if any) provided for
+/// a function.
+enum FunctionDefinitionKind {
+ FDK_Declaration,
+ FDK_Definition,
+ FDK_Defaulted,
+ FDK_Deleted
+};
+
+/// \brief 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.
+ ObjCResultContext, // An ObjC method result type.
+ ObjCParameterContext,// An ObjC method parameter type.
+ 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.
+ CXXNewContext, // C++ new-expression.
+ CXXCatchContext, // C++ catch exception-declaration
+ ObjCCatchContext, // Objective-C catch exception-declaration
+ BlockLiteralContext, // Block literal declarator.
+ LambdaExprContext, // Lambda-expression declarator.
+ LambdaExprParameterContext, // Lambda-expression parameter declarator.
+ ConversionIdContext, // C++ conversion-type-id.
+ TrailingReturnContext, // C++11 trailing-type-specifier.
+ TemplateTypeArgContext, // Template type argument.
+ AliasDeclContext, // C++11 alias-declaration.
+ AliasTemplateContext // C++11 alias-declaration template.
+ };
+
+private:
+ const DeclSpec &DS;
+ CXXScopeSpec SS;
+ UnqualifiedId Name;
+ SourceRange Range;
+
+ /// \brief 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.
+ SmallVector<DeclaratorChunk, 8> DeclTypeInfo;
+
+ /// InvalidType - Set by Sema::GetTypeForDeclarator().
+ bool InvalidType : 1;
+
+ /// GroupingParens - Set by Parser::ParseParenDeclarator().
+ bool GroupingParens : 1;
+
+ /// FunctionDefinition - Is this Declarator for a function or member
+ /// definition and, if so, what kind?
+ ///
+ /// Actually a FunctionDefinitionKind.
+ unsigned FunctionDefinition : 2;
+
+ /// \brief Is this Declarator a redeclaration?
+ bool Redeclaration : 1;
+
+ /// Attrs - Attributes.
+ ParsedAttributes Attrs;
+
+ /// \brief 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;
+
+ /// \brief true if the declaration is preceded by \c __extension__.
+ unsigned Extension : 1;
+
+ /// Indicates whether this is an Objective-C instance variable.
+ unsigned ObjCIvar : 1;
+
+ /// Indicates whether this is an Objective-C 'weak' property.
+ unsigned ObjCWeakProperty : 1;
+
+ /// \brief If this is the second or subsequent declarator in this declaration,
+ /// the location of the comma before this declarator.
+ SourceLocation CommaLoc;
+
+ /// \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), FunctionDefinition(FDK_Declaration),
+ Redeclaration(false),
+ Attrs(ds.getAttributePool().getFactory()), AsmLabel(nullptr),
+ InlineParamsUsed(false), Extension(false), ObjCIvar(false),
+ ObjCWeakProperty(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); }
+
+ AttributePool &getAttributePool() const {
+ return Attrs.getPool();
+ }
+
+ /// 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; }
+
+ bool isPrototypeContext() const {
+ return (Context == PrototypeContext ||
+ Context == ObjCParameterContext ||
+ Context == ObjCResultContext ||
+ Context == LambdaExprParameterContext);
+ }
+
+ /// \brief Get the source range that spans this declarator.
+ SourceRange getSourceRange() const LLVM_READONLY { return Range; }
+ SourceLocation getLocStart() const LLVM_READONLY { return Range.getBegin(); }
+ SourceLocation getLocEnd() const LLVM_READONLY { return Range.getEnd(); }
+
+ 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) {
+ SourceRange SR = DS.getSourceRange();
+ if (Range.getBegin().isInvalid())
+ Range.setBegin(SR.getBegin());
+ if (!SR.getEnd().isInvalid())
+ Range.setEnd(SR.getEnd());
+ }
+
+ /// \brief 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();
+ Attrs.clear();
+ AsmLabel = nullptr;
+ InlineParamsUsed = false;
+ ObjCIvar = false;
+ ObjCWeakProperty = false;
+ CommaLoc = SourceLocation();
+ EllipsisLoc = SourceLocation();
+ }
+
+ /// 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 {
+ switch (Context) {
+ case FileContext:
+ case KNRTypeListContext:
+ case MemberContext:
+ case BlockContext:
+ case ForContext:
+ case ConditionContext:
+ return false;
+
+ case TypeNameContext:
+ case AliasDeclContext:
+ case AliasTemplateContext:
+ case PrototypeContext:
+ case LambdaExprParameterContext:
+ case ObjCParameterContext:
+ case ObjCResultContext:
+ case TemplateParamContext:
+ case CXXNewContext:
+ case CXXCatchContext:
+ case ObjCCatchContext:
+ case BlockLiteralContext:
+ case LambdaExprContext:
+ case ConversionIdContext:
+ case TemplateTypeArgContext:
+ case TrailingReturnContext:
+ return true;
+ }
+ llvm_unreachable("unknown context kind!");
+ }
+
+ /// 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 {
+ switch (Context) {
+ case FileContext:
+ case KNRTypeListContext:
+ case MemberContext:
+ case BlockContext:
+ case ForContext:
+ case ConditionContext:
+ case PrototypeContext:
+ case LambdaExprParameterContext:
+ case TemplateParamContext:
+ case CXXCatchContext:
+ case ObjCCatchContext:
+ return true;
+
+ case TypeNameContext:
+ case CXXNewContext:
+ case AliasDeclContext:
+ case AliasTemplateContext:
+ case ObjCParameterContext:
+ case ObjCResultContext:
+ case BlockLiteralContext:
+ case LambdaExprContext:
+ case ConversionIdContext:
+ case TemplateTypeArgContext:
+ case TrailingReturnContext:
+ return false;
+ }
+ llvm_unreachable("unknown context kind!");
+ }
+
+ /// diagnoseIdentifier - Return true if the identifier is prohibited and
+ /// should be diagnosed (because it cannot be anything else).
+ bool diagnoseIdentifier() const {
+ switch (Context) {
+ case FileContext:
+ case KNRTypeListContext:
+ case MemberContext:
+ case BlockContext:
+ case ForContext:
+ case ConditionContext:
+ case PrototypeContext:
+ case LambdaExprParameterContext:
+ case TemplateParamContext:
+ case CXXCatchContext:
+ case ObjCCatchContext:
+ case TypeNameContext:
+ case ConversionIdContext:
+ case ObjCParameterContext:
+ case ObjCResultContext:
+ case BlockLiteralContext:
+ case CXXNewContext:
+ case LambdaExprContext:
+ return false;
+
+ case AliasDeclContext:
+ case AliasTemplateContext:
+ case TemplateTypeArgContext:
+ case TrailingReturnContext:
+ return true;
+ }
+ llvm_unreachable("unknown context kind!");
+ }
+
+ /// mayBeFollowedByCXXDirectInit - Return true if the declarator can be
+ /// followed by a C++ direct initializer, e.g. "int x(1);".
+ bool mayBeFollowedByCXXDirectInit() const {
+ if (hasGroupingParens()) return false;
+
+ if (getDeclSpec().getStorageClassSpec() == DeclSpec::SCS_typedef)
+ return false;
+
+ if (getDeclSpec().getStorageClassSpec() == DeclSpec::SCS_extern &&
+ Context != FileContext)
+ return false;
+
+ // Special names can't have direct initializers.
+ if (Name.getKind() != UnqualifiedId::IK_Identifier)
+ return false;
+
+ switch (Context) {
+ case FileContext:
+ case BlockContext:
+ case ForContext:
+ return true;
+
+ case ConditionContext:
+ // This may not be followed by a direct initializer, but it can't be a
+ // function declaration either, and we'd prefer to perform a tentative
+ // parse in order to produce the right diagnostic.
+ return true;
+
+ case KNRTypeListContext:
+ case MemberContext:
+ case PrototypeContext:
+ case LambdaExprParameterContext:
+ case ObjCParameterContext:
+ case ObjCResultContext:
+ case TemplateParamContext:
+ case CXXCatchContext:
+ case ObjCCatchContext:
+ case TypeNameContext:
+ case CXXNewContext:
+ case AliasDeclContext:
+ case AliasTemplateContext:
+ case BlockLiteralContext:
+ case LambdaExprContext:
+ case ConversionIdContext:
+ case TemplateTypeArgContext:
+ case TrailingReturnContext:
+ return false;
+ }
+ llvm_unreachable("unknown context kind!");
+ }
+
+ /// 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 nullptr;
+ }
+ 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,
+ ParsedAttributes &attrs,
+ SourceLocation EndLoc) {
+ DeclTypeInfo.push_back(TI);
+ DeclTypeInfo.back().getAttrListRef() = attrs.getList();
+ getAttributePool().takeAllFrom(attrs.getPool());
+
+ if (!EndLoc.isInvalid())
+ SetRangeEnd(EndLoc);
+ }
+
+ /// \brief Add a new innermost chunk to this declarator.
+ void AddInnermostTypeInfo(const DeclaratorChunk &TI) {
+ DeclTypeInfo.insert(DeclTypeInfo.begin(), TI);
+ }
+
+ /// \brief 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];
+ }
+
+ typedef SmallVectorImpl<DeclaratorChunk>::const_iterator type_object_iterator;
+ typedef llvm::iterator_range<type_object_iterator> type_object_range;
+
+ /// Returns the range of type objects, from the identifier outwards.
+ type_object_range type_objects() const {
+ return type_object_range(DeclTypeInfo.begin(), DeclTypeInfo.end());
+ }
+
+ void DropFirstTypeObject() {
+ assert(!DeclTypeInfo.empty() && "No type chunks to drop.");
+ DeclTypeInfo.front().destroy();
+ DeclTypeInfo.erase(DeclTypeInfo.begin());
+ }
+
+ /// Return the innermost (closest to the declarator) chunk of this
+ /// declarator that is not a parens chunk, or null if there are no
+ /// non-parens chunks.
+ const DeclaratorChunk *getInnermostNonParenChunk() const {
+ for (unsigned i = 0, i_end = DeclTypeInfo.size(); i < i_end; ++i) {
+ if (!DeclTypeInfo[i].isParen())
+ return &DeclTypeInfo[i];
+ }
+ return nullptr;
+ }
+
+ /// Return the outermost (furthest from the declarator) chunk of
+ /// this declarator that is not a parens chunk, or null if there are
+ /// no non-parens chunks.
+ const DeclaratorChunk *getOutermostNonParenChunk() const {
+ for (unsigned i = DeclTypeInfo.size(), i_end = 0; i != i_end; --i) {
+ if (!DeclTypeInfo[i-1].isParen())
+ return &DeclTypeInfo[i-1];
+ }
+ return nullptr;
+ }
+
+ /// isArrayOfUnknownBound - This method returns true if the declarator
+ /// is a declarator for an array of unknown bound (looking through
+ /// parentheses).
+ bool isArrayOfUnknownBound() const {
+ const DeclaratorChunk *chunk = getInnermostNonParenChunk();
+ return (chunk && chunk->Kind == DeclaratorChunk::Array &&
+ !chunk->Arr.NumElts);
+ }
+
+ /// 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;
+ }
+
+ /// 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();
+ }
+
+ /// \brief Determine whether the declaration that will be produced from
+ /// this declaration will be a function.
+ ///
+ /// A declaration can declare a function even if the declarator itself
+ /// isn't a function declarator, if the type specifier refers to a function
+ /// type. This routine checks for both cases.
+ bool isDeclarationOfFunction() const;
+
+ /// \brief Return true if this declaration appears in a context where a
+ /// function declarator would be a function declaration.
+ bool isFunctionDeclarationContext() const {
+ if (getDeclSpec().getStorageClassSpec() == DeclSpec::SCS_typedef)
+ return false;
+
+ switch (Context) {
+ case FileContext:
+ case MemberContext:
+ case BlockContext:
+ return true;
+
+ case ForContext:
+ case ConditionContext:
+ case KNRTypeListContext:
+ case TypeNameContext:
+ case AliasDeclContext:
+ case AliasTemplateContext:
+ case PrototypeContext:
+ case LambdaExprParameterContext:
+ case ObjCParameterContext:
+ case ObjCResultContext:
+ case TemplateParamContext:
+ case CXXNewContext:
+ case CXXCatchContext:
+ case ObjCCatchContext:
+ case BlockLiteralContext:
+ case LambdaExprContext:
+ case ConversionIdContext:
+ case TemplateTypeArgContext:
+ case TrailingReturnContext:
+ return false;
+ }
+ llvm_unreachable("unknown context kind!");
+ }
+
+ /// \brief Return true if a function declarator at this position would be a
+ /// function declaration.
+ bool isFunctionDeclaratorAFunctionDeclaration() const {
+ if (!isFunctionDeclarationContext())
+ return false;
+
+ for (unsigned I = 0, N = getNumTypeObjects(); I != N; ++I)
+ if (getTypeObject(I).Kind != DeclaratorChunk::Paren)
+ return false;
+
+ return true;
+ }
+
+ /// takeAttributes - Takes attributes from the given parsed-attributes
+ /// set and add them to this 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 takeAttributes(ParsedAttributes &attrs, SourceLocation lastLoc) {
+ Attrs.takeAllFrom(attrs);
+
+ if (!lastLoc.isInvalid())
+ SetRangeEnd(lastLoc);
+ }
+
+ const AttributeList *getAttributes() const { return Attrs.getList(); }
+ AttributeList *getAttributes() { return Attrs.getList(); }
+
+ AttributeList *&getAttrListRef() { return Attrs.getListRef(); }
+
+ /// 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;
+ }
+
+ /// \brief Return a source range list of C++11 attributes associated
+ /// with the declarator.
+ void getCXX11AttributeRanges(SmallVectorImpl<SourceRange> &Ranges) {
+ AttributeList *AttrList = Attrs.getList();
+ while (AttrList) {
+ if (AttrList->isCXX11Attribute())
+ Ranges.push_back(AttrList->getRange());
+ AttrList = AttrList->getNext();
+ }
+ }
+
+ void setAsmLabel(Expr *E) { AsmLabel = E; }
+ Expr *getAsmLabel() const { return AsmLabel; }
+
+ void setExtension(bool Val = true) { Extension = Val; }
+ bool getExtension() const { return Extension; }
+
+ void setObjCIvar(bool Val = true) { ObjCIvar = Val; }
+ bool isObjCIvar() const { return ObjCIvar; }
+
+ void setObjCWeakProperty(bool Val = true) { ObjCWeakProperty = Val; }
+ bool isObjCWeakProperty() const { return ObjCWeakProperty; }
+
+ 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 isFirstDeclarator() const { return !CommaLoc.isValid(); }
+ SourceLocation getCommaLoc() const { return CommaLoc; }
+ void setCommaLoc(SourceLocation CL) { CommaLoc = CL; }
+
+ bool hasEllipsis() const { return EllipsisLoc.isValid(); }
+ SourceLocation getEllipsisLoc() const { return EllipsisLoc; }
+ void setEllipsisLoc(SourceLocation EL) { EllipsisLoc = EL; }
+
+ void setFunctionDefinitionKind(FunctionDefinitionKind Val) {
+ FunctionDefinition = Val;
+ }
+
+ bool isFunctionDefinition() const {
+ return getFunctionDefinitionKind() != FDK_Declaration;
+ }
+
+ FunctionDefinitionKind getFunctionDefinitionKind() const {
+ return (FunctionDefinitionKind)FunctionDefinition;
+ }
+
+ /// Returns true if this declares a real member and not a friend.
+ bool isFirstDeclarationOfMember() {
+ return getContext() == MemberContext && !getDeclSpec().isFriendSpecified();
+ }
+
+ /// Returns true if this declares a static member. This cannot be called on a
+ /// declarator outside of a MemberContext because we won't know until
+ /// redeclaration time if the decl is static.
+ bool isStaticMember();
+
+ /// Returns true if this declares a constructor or a destructor.
+ bool isCtorOrDtor();
+
+ void setRedeclaration(bool Val) { Redeclaration = Val; }
+ bool isRedeclaration() const { return Redeclaration; }
+};
+
+/// \brief 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(const DeclSpec &DS)
+ : D(DS, Declarator::MemberContext), BitfieldSize(nullptr) { }
+};
+
+/// \brief Represents a C++11 virt-specifier-seq.
+class VirtSpecifiers {
+public:
+ enum Specifier {
+ VS_None = 0,
+ VS_Override = 1,
+ VS_Final = 2,
+ VS_Sealed = 4
+ };
+
+ VirtSpecifiers() : Specifiers(0), LastSpecifier(VS_None) { }
+
+ bool SetSpecifier(Specifier VS, SourceLocation Loc,
+ const char *&PrevSpec);
+
+ bool isUnset() const { return Specifiers == 0; }
+
+ bool isOverrideSpecified() const { return Specifiers & VS_Override; }
+ SourceLocation getOverrideLoc() const { return VS_overrideLoc; }
+
+ bool isFinalSpecified() const { return Specifiers & (VS_Final | VS_Sealed); }
+ bool isFinalSpelledSealed() const { return Specifiers & VS_Sealed; }
+ SourceLocation getFinalLoc() const { return VS_finalLoc; }
+
+ void clear() { Specifiers = 0; }
+
+ static const char *getSpecifierName(Specifier VS);
+
+ SourceLocation getFirstLocation() const { return FirstLocation; }
+ SourceLocation getLastLocation() const { return LastLocation; }
+ Specifier getLastSpecifier() const { return LastSpecifier; }
+
+private:
+ unsigned Specifiers;
+ Specifier LastSpecifier;
+
+ SourceLocation VS_overrideLoc, VS_finalLoc;
+ SourceLocation FirstLocation;
+ SourceLocation LastLocation;
+};
+
+enum class LambdaCaptureInitKind {
+ NoInit, //!< [a]
+ CopyInit, //!< [a = b], [a = {b}]
+ DirectInit, //!< [a(b)]
+ ListInit //!< [a{b}]
+};
+
+/// \brief Represents a complete lambda introducer.
+struct LambdaIntroducer {
+ /// \brief An individual capture in a lambda introducer.
+ struct LambdaCapture {
+ LambdaCaptureKind Kind;
+ SourceLocation Loc;
+ IdentifierInfo *Id;
+ SourceLocation EllipsisLoc;
+ LambdaCaptureInitKind InitKind;
+ ExprResult Init;
+ ParsedType InitCaptureType;
+ LambdaCapture(LambdaCaptureKind Kind, SourceLocation Loc,
+ IdentifierInfo *Id, SourceLocation EllipsisLoc,
+ LambdaCaptureInitKind InitKind, ExprResult Init,
+ ParsedType InitCaptureType)
+ : Kind(Kind), Loc(Loc), Id(Id), EllipsisLoc(EllipsisLoc),
+ InitKind(InitKind), Init(Init), InitCaptureType(InitCaptureType) {}
+ };
+
+ SourceRange Range;
+ SourceLocation DefaultLoc;
+ LambdaCaptureDefault Default;
+ SmallVector<LambdaCapture, 4> Captures;
+
+ LambdaIntroducer()
+ : Default(LCD_None) {}
+
+ /// \brief Append a capture in a lambda introducer.
+ void addCapture(LambdaCaptureKind Kind,
+ SourceLocation Loc,
+ IdentifierInfo* Id,
+ SourceLocation EllipsisLoc,
+ LambdaCaptureInitKind InitKind,
+ ExprResult Init,
+ ParsedType InitCaptureType) {
+ Captures.push_back(LambdaCapture(Kind, Loc, Id, EllipsisLoc, InitKind, Init,
+ InitCaptureType));
+ }
+};
+
+} // 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..155b3aa
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Sema/DelayedDiagnostic.h
@@ -0,0 +1,305 @@
+//===--- 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.
+//
+//===----------------------------------------------------------------------===//
+///
+/// \file
+/// \brief Defines the classes clang::DelayedDiagnostic and
+/// clang::AccessedEntity.
+///
+/// DelayedDiangostic 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.
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_SEMA_DELAYEDDIAGNOSTIC_H
+#define LLVM_CLANG_SEMA_DELAYEDDIAGNOSTIC_H
+
+#include "clang/Sema/Sema.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(PartialDiagnostic::StorageAllocator &Allocator,
+ MemberNonce _,
+ CXXRecordDecl *NamingClass,
+ DeclAccessPair FoundDecl,
+ QualType BaseObjectType)
+ : Access(FoundDecl.getAccess()), IsMember(true),
+ Target(FoundDecl.getDecl()), NamingClass(NamingClass),
+ BaseObjectType(BaseObjectType), Diag(0, Allocator) {
+ }
+
+ AccessedEntity(PartialDiagnostic::StorageAllocator &Allocator,
+ BaseNonce _,
+ CXXRecordDecl *BaseClass,
+ CXXRecordDecl *DerivedClass,
+ AccessSpecifier Access)
+ : Access(Access), IsMember(false),
+ Target(BaseClass),
+ NamingClass(DerivedClass),
+ Diag(0, Allocator) {
+ }
+
+ 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, Unavailable, Access, ForbiddenType };
+
+ unsigned char Kind; // actually a DDKind
+ bool Triggered;
+
+ SourceLocation Loc;
+
+ void Destroy();
+
+ static DelayedDiagnostic makeAvailability(Sema::AvailabilityDiagnostic AD,
+ SourceLocation Loc,
+ const NamedDecl *D,
+ const ObjCInterfaceDecl *UnknownObjCClass,
+ const ObjCPropertyDecl *ObjCProperty,
+ StringRef Msg,
+ bool ObjCPropertyAccess);
+
+
+ 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;
+ }
+
+ static DelayedDiagnostic makeForbiddenType(SourceLocation loc,
+ unsigned diagnostic,
+ QualType type,
+ unsigned argument) {
+ DelayedDiagnostic DD;
+ DD.Kind = ForbiddenType;
+ DD.Triggered = false;
+ DD.Loc = loc;
+ DD.ForbiddenTypeData.Diagnostic = diagnostic;
+ DD.ForbiddenTypeData.OperandType = type.getAsOpaquePtr();
+ DD.ForbiddenTypeData.Argument = argument;
+ 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 || Kind == Unavailable) &&
+ "Not a deprecation diagnostic.");
+ return DeprecationData.Decl;
+ }
+
+ StringRef getDeprecationMessage() const {
+ assert((Kind == Deprecation || Kind == Unavailable) &&
+ "Not a deprecation diagnostic.");
+ return StringRef(DeprecationData.Message,
+ DeprecationData.MessageLen);
+ }
+
+ /// The diagnostic ID to emit. Used like so:
+ /// Diag(diag.Loc, diag.getForbiddenTypeDiagnostic())
+ /// << diag.getForbiddenTypeOperand()
+ /// << diag.getForbiddenTypeArgument();
+ unsigned getForbiddenTypeDiagnostic() const {
+ assert(Kind == ForbiddenType && "not a forbidden-type diagnostic");
+ return ForbiddenTypeData.Diagnostic;
+ }
+
+ unsigned getForbiddenTypeArgument() const {
+ assert(Kind == ForbiddenType && "not a forbidden-type diagnostic");
+ return ForbiddenTypeData.Argument;
+ }
+
+ QualType getForbiddenTypeOperand() const {
+ assert(Kind == ForbiddenType && "not a forbidden-type diagnostic");
+ return QualType::getFromOpaquePtr(ForbiddenTypeData.OperandType);
+ }
+
+ const ObjCInterfaceDecl *getUnknownObjCClass() const {
+ return DeprecationData.UnknownObjCClass;
+ }
+
+ const ObjCPropertyDecl *getObjCProperty() const {
+ return DeprecationData.ObjCProperty;
+ }
+
+ bool getObjCPropertyAccess() const {
+ return DeprecationData.ObjCPropertyAccess;
+ }
+
+private:
+
+ struct DD {
+ const NamedDecl *Decl;
+ const ObjCInterfaceDecl *UnknownObjCClass;
+ const ObjCPropertyDecl *ObjCProperty;
+ const char *Message;
+ size_t MessageLen;
+ bool ObjCPropertyAccess;
+ };
+
+ struct FTD {
+ unsigned Diagnostic;
+ unsigned Argument;
+ void *OperandType;
+ };
+
+ union {
+ /// Deprecation
+ struct DD DeprecationData;
+ struct FTD ForbiddenTypeData;
+
+ /// Access control.
+ char AccessData[sizeof(AccessedEntity)];
+ };
+};
+
+/// \brief A collection of diagnostics which were delayed.
+class DelayedDiagnosticPool {
+ const DelayedDiagnosticPool *Parent;
+ SmallVector<DelayedDiagnostic, 4> Diagnostics;
+
+ DelayedDiagnosticPool(const DelayedDiagnosticPool &) = delete;
+ void operator=(const DelayedDiagnosticPool &) = delete;
+public:
+ DelayedDiagnosticPool(const DelayedDiagnosticPool *parent) : Parent(parent) {}
+ ~DelayedDiagnosticPool() {
+ for (SmallVectorImpl<DelayedDiagnostic>::iterator
+ i = Diagnostics.begin(), e = Diagnostics.end(); i != e; ++i)
+ i->Destroy();
+ }
+
+ DelayedDiagnosticPool(DelayedDiagnosticPool &&Other)
+ : Parent(Other.Parent), Diagnostics(std::move(Other.Diagnostics)) {
+ Other.Diagnostics.clear();
+ }
+ DelayedDiagnosticPool &operator=(DelayedDiagnosticPool &&Other) {
+ Parent = Other.Parent;
+ Diagnostics = std::move(Other.Diagnostics);
+ Other.Diagnostics.clear();
+ return *this;
+ }
+
+ const DelayedDiagnosticPool *getParent() const { return Parent; }
+
+ /// Does this pool, or any of its ancestors, contain any diagnostics?
+ bool empty() const {
+ return (Diagnostics.empty() && (!Parent || Parent->empty()));
+ }
+
+ /// Add a diagnostic to this pool.
+ void add(const DelayedDiagnostic &diag) {
+ Diagnostics.push_back(diag);
+ }
+
+ /// Steal the diagnostics from the given pool.
+ void steal(DelayedDiagnosticPool &pool) {
+ if (pool.Diagnostics.empty()) return;
+
+ if (Diagnostics.empty()) {
+ Diagnostics = std::move(pool.Diagnostics);
+ } else {
+ Diagnostics.append(pool.pool_begin(), pool.pool_end());
+ }
+ pool.Diagnostics.clear();
+ }
+
+ typedef SmallVectorImpl<DelayedDiagnostic>::const_iterator pool_iterator;
+ pool_iterator pool_begin() const { return Diagnostics.begin(); }
+ pool_iterator pool_end() const { return Diagnostics.end(); }
+ bool pool_empty() const { return Diagnostics.empty(); }
+};
+
+}
+
+/// Add a diagnostic to the current delay pool.
+inline void Sema::DelayedDiagnostics::add(const sema::DelayedDiagnostic &diag) {
+ assert(shouldDelayDiagnostics() && "trying to delay without pool");
+ CurPool->add(diag);
+}
+
+
+}
+
+#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..55603fe
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Sema/Designator.h
@@ -0,0 +1,210 @@
+//===--- 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 {
+ /// Designators - The actual designators for this initializer.
+ SmallVector<Designator, 2> Designators;
+
+public:
+ /// 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..97f78f4
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Sema/ExternalSemaSource.h
@@ -0,0 +1,229 @@
+//===--- 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_EXTERNALSEMASOURCE_H
+#define LLVM_CLANG_SEMA_EXTERNALSEMASOURCE_H
+
+#include "clang/AST/ExternalASTSource.h"
+#include "clang/AST/Type.h"
+#include "clang/Sema/TypoCorrection.h"
+#include "clang/Sema/Weak.h"
+#include "llvm/ADT/MapVector.h"
+#include <utility>
+
+namespace llvm {
+template <class T, unsigned n> class SmallSetVector;
+}
+
+namespace clang {
+
+class CXXConstructorDecl;
+class CXXDeleteExpr;
+class CXXRecordDecl;
+class DeclaratorDecl;
+class LookupResult;
+struct ObjCMethodList;
+class Scope;
+class Sema;
+class TypedefNameDecl;
+class ValueDecl;
+class VarDecl;
+struct LateParsedTemplate;
+
+/// \brief A simple structure that captures a vtable use for the purposes of
+/// the \c ExternalSemaSource.
+struct ExternalVTableUse {
+ CXXRecordDecl *Record;
+ SourceLocation Location;
+ bool DefinitionRequired;
+};
+
+/// \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() override;
+
+ /// \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.
+ virtual void ReadMethodPool(Selector Sel);
+
+ /// \brief Load the set of namespaces that are known to the external source,
+ /// which will be used during typo correction.
+ virtual void ReadKnownNamespaces(
+ SmallVectorImpl<NamespaceDecl *> &Namespaces);
+
+ /// \brief Load the set of used but not defined functions or variables with
+ /// internal linkage, or used but not defined internal functions.
+ virtual void ReadUndefinedButUsed(
+ llvm::DenseMap<NamedDecl*, SourceLocation> &Undefined);
+
+ virtual void ReadMismatchingDeleteExpressions(llvm::MapVector<
+ FieldDecl *, llvm::SmallVector<std::pair<SourceLocation, bool>, 4>> &);
+
+ /// \brief Do last resort, unqualified lookup on a LookupResult that
+ /// Sema cannot find.
+ ///
+ /// \param R a LookupResult that is being recovered.
+ ///
+ /// \param S the Scope of the identifier occurrence.
+ ///
+ /// \return true to tell Sema to recover using the LookupResult.
+ virtual bool LookupUnqualified(LookupResult &R, Scope *S) { return false; }
+
+ /// \brief Read the set of tentative definitions known to the external Sema
+ /// source.
+ ///
+ /// The external source should append its own tentative definitions to the
+ /// given vector of tentative definitions. Note that this routine may be
+ /// invoked multiple times; the external source should take care not to
+ /// introduce the same declarations repeatedly.
+ virtual void ReadTentativeDefinitions(
+ SmallVectorImpl<VarDecl *> &TentativeDefs) {}
+
+ /// \brief Read the set of unused file-scope declarations known to the
+ /// external Sema source.
+ ///
+ /// The external source should append its own unused, filed-scope to the
+ /// given vector of declarations. Note that this routine may be
+ /// invoked multiple times; the external source should take care not to
+ /// introduce the same declarations repeatedly.
+ virtual void ReadUnusedFileScopedDecls(
+ SmallVectorImpl<const DeclaratorDecl *> &Decls) {}
+
+ /// \brief Read the set of delegating constructors known to the
+ /// external Sema source.
+ ///
+ /// The external source should append its own delegating constructors to the
+ /// given vector of declarations. Note that this routine may be
+ /// invoked multiple times; the external source should take care not to
+ /// introduce the same declarations repeatedly.
+ virtual void ReadDelegatingConstructors(
+ SmallVectorImpl<CXXConstructorDecl *> &Decls) {}
+
+ /// \brief Read the set of ext_vector type declarations known to the
+ /// external Sema source.
+ ///
+ /// The external source should append its own ext_vector type declarations to
+ /// the given vector of declarations. Note that this routine may be
+ /// invoked multiple times; the external source should take care not to
+ /// introduce the same declarations repeatedly.
+ virtual void ReadExtVectorDecls(SmallVectorImpl<TypedefNameDecl *> &Decls) {}
+
+ /// \brief Read the set of potentially unused typedefs known to the source.
+ ///
+ /// The external source should append its own potentially unused local
+ /// typedefs to the given vector of declarations. Note that this routine may
+ /// be invoked multiple times; the external source should take care not to
+ /// introduce the same declarations repeatedly.
+ virtual void ReadUnusedLocalTypedefNameCandidates(
+ llvm::SmallSetVector<const TypedefNameDecl *, 4> &Decls) {}
+
+ /// \brief Read the set of referenced selectors known to the
+ /// external Sema source.
+ ///
+ /// The external source should append its own referenced selectors to the
+ /// given vector of selectors. Note that this routine
+ /// may be invoked multiple times; the external source should take care not
+ /// to introduce the same selectors repeatedly.
+ virtual void ReadReferencedSelectors(
+ SmallVectorImpl<std::pair<Selector, SourceLocation> > &Sels) {}
+
+ /// \brief Read the set of weak, undeclared identifiers known to the
+ /// external Sema source.
+ ///
+ /// The external source should append its own weak, undeclared identifiers to
+ /// the given vector. Note that this routine may be invoked multiple times;
+ /// the external source should take care not to introduce the same identifiers
+ /// repeatedly.
+ virtual void ReadWeakUndeclaredIdentifiers(
+ SmallVectorImpl<std::pair<IdentifierInfo *, WeakInfo> > &WI) {}
+
+ /// \brief Read the set of used vtables known to the external Sema source.
+ ///
+ /// The external source should append its own used vtables to the given
+ /// vector. Note that this routine may be invoked multiple times; the external
+ /// source should take care not to introduce the same vtables repeatedly.
+ virtual void ReadUsedVTables(SmallVectorImpl<ExternalVTableUse> &VTables) {}
+
+ /// \brief Read the set of pending instantiations known to the external
+ /// Sema source.
+ ///
+ /// The external source should append its own pending instantiations to the
+ /// given vector. Note that this routine may be invoked multiple times; the
+ /// external source should take care not to introduce the same instantiations
+ /// repeatedly.
+ virtual void ReadPendingInstantiations(
+ SmallVectorImpl<std::pair<ValueDecl *,
+ SourceLocation> > &Pending) {}
+
+ /// \brief Read the set of late parsed template functions for this source.
+ ///
+ /// The external source should insert its own late parsed template functions
+ /// into the map. Note that this routine may be invoked multiple times; the
+ /// external source should take care not to introduce the same map entries
+ /// repeatedly.
+ virtual void ReadLateParsedTemplates(
+ llvm::MapVector<const FunctionDecl *, LateParsedTemplate *> &LPTMap) {}
+
+ /// \copydoc Sema::CorrectTypo
+ /// \note LookupKind must correspond to a valid Sema::LookupNameKind
+ ///
+ /// ExternalSemaSource::CorrectTypo is always given the first chance to
+ /// correct a typo (really, to offer suggestions to repair a failed lookup).
+ /// It will even be called when SpellChecking is turned off or after a
+ /// fatal error has already been detected.
+ virtual TypoCorrection CorrectTypo(const DeclarationNameInfo &Typo,
+ int LookupKind, Scope *S, CXXScopeSpec *SS,
+ CorrectionCandidateCallback &CCC,
+ DeclContext *MemberContext,
+ bool EnteringContext,
+ const ObjCObjectPointerType *OPT) {
+ return TypoCorrection();
+ }
+
+ /// \brief Produces a diagnostic note if the external source contains a
+ /// complete definition for \p T.
+ ///
+ /// \param Loc the location at which a complete type was required but not
+ /// provided
+ ///
+ /// \param T the \c QualType that should have been complete at \p Loc
+ ///
+ /// \return true if a diagnostic was produced, false otherwise.
+ virtual bool MaybeDiagnoseMissingCompleteType(SourceLocation Loc,
+ QualType T) {
+ return false;
+ }
+
+ // isa/cast/dyn_cast support
+ static bool classof(const ExternalASTSource *Source) {
+ return Source->SemaSource;
+ }
+};
+
+} // 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..a07834f
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Sema/IdentifierResolver.h
@@ -0,0 +1,213 @@
+//===- 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_SEMA_IDENTIFIERRESOLVER_H
+#define LLVM_CLANG_SEMA_IDENTIFIERRESOLVER_H
+
+#include "clang/Basic/IdentifierTable.h"
+#include "llvm/ADT/SmallVector.h"
+
+namespace clang {
+
+class ASTContext;
+class Decl;
+class DeclContext;
+class DeclarationName;
+class ExternalPreprocessorSource;
+class NamedDecl;
+class Preprocessor;
+class Scope;
+
+/// IdentifierResolver - Keeps track of shadowed decls on enclosing
+/// scopes. It manages the shadowing chains of declaration names and
+/// implements efficient 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 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);
+
+ /// \brief Insert the given declaration at the given position in the list.
+ void InsertDecl(DeclsTy::iterator Pos, NamedDecl *D) {
+ Decls.insert(Pos, D);
+ }
+
+ 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'.
+ iterator begin(DeclarationName Name);
+
+ /// end - Returns an iterator that has 'finished'.
+ 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.
+ ///
+ /// \param AllowInlineNamespace If \c true, we are checking whether a prior
+ /// declaration is in scope in a declaration that requires a prior
+ /// declaration (because it is either explicitly qualified or is a
+ /// template instantiation or specialization). In this case, a
+ /// declaration is in scope if it's in the inline namespace set of the
+ /// context.
+ bool isDeclInScope(Decl *D, DeclContext *Ctx, Scope *S = nullptr,
+ bool AllowInlineNamespace = false) 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);
+
+ /// \brief Insert the given declaration after the given iterator
+ /// position.
+ void InsertDeclAfter(iterator Pos, NamedDecl *D);
+
+ /// \brief Try to add the given declaration to the top level scope, if it
+ /// (or a redeclaration of it) hasn't already been added.
+ ///
+ /// \param D The externally-produced declaration to add.
+ ///
+ /// \param Name The name of the externally-produced declaration.
+ ///
+ /// \returns true if the declaration was added, false otherwise.
+ bool tryAddTopLevelDecl(NamedDecl *D, DeclarationName Name);
+
+ explicit IdentifierResolver(Preprocessor &PP);
+ ~IdentifierResolver();
+
+private:
+ const LangOptions &LangOpt;
+ Preprocessor &PP;
+
+ class IdDeclInfoMap;
+ IdDeclInfoMap *IdDeclInfos;
+
+ void updatingIdentifier(IdentifierInfo &II);
+ void readingIdentifier(IdentifierInfo &II);
+
+ /// 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..d4f57b7
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Sema/Initialization.h
@@ -0,0 +1,1145 @@
+//===--- Initialization.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/AST/ASTContext.h"
+#include "clang/AST/Attr.h"
+#include "clang/AST/Type.h"
+#include "clang/AST/UnresolvedSet.h"
+#include "clang/Basic/SourceLocation.h"
+#include "clang/Sema/Overload.h"
+#include "clang/Sema/Ownership.h"
+#include "llvm/ADT/PointerIntPair.h"
+#include "llvm/ADT/SmallVector.h"
+#include <cassert>
+
+namespace clang {
+
+class CXXBaseSpecifier;
+class DeclaratorDecl;
+class DeclaratorInfo;
+class FieldDecl;
+class FunctionDecl;
+class ParmVarDecl;
+class Sema;
+class TypeLoc;
+class VarDecl;
+class ObjCMethodDecl;
+
+/// \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 initialization is being done by a delegating constructor.
+ EK_Delegating,
+ /// \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,
+ /// \brief The entity being initialized is the real or imaginary part of a
+ /// complex number.
+ EK_ComplexElement,
+ /// \brief The entity being initialized is the field that captures a
+ /// variable in a lambda.
+ EK_LambdaCapture,
+ /// \brief The entity being initialized is the initializer for a compound
+ /// literal.
+ EK_CompoundLiteralInit,
+ /// \brief The entity being implicitly initialized back to the formal
+ /// result type.
+ EK_RelatedResult,
+ /// \brief The entity being initialized is a function parameter; function
+ /// is member of group of audited CF APIs.
+ EK_Parameter_CF_Audited
+
+ // Note: err_init_conversion_failed in DiagnosticSemaKinds.td uses this
+ // enum as an index for its first %select. When modifying this list,
+ // that diagnostic text needs to be updated as well.
+ };
+
+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;
+
+ /// \brief The mangling number for the next reference temporary to be created.
+ mutable unsigned ManglingNumber;
+
+ struct LN {
+ /// \brief When Kind == EK_Result, EK_Exception, 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 entity being initialized may end up using the
+ /// named return value optimization (NRVO).
+ bool NRVO;
+ };
+
+ struct C {
+ /// \brief The name of the variable being captured by an EK_LambdaCapture.
+ IdentifierInfo *VarID;
+
+ /// \brief The source location at which the capture occurs.
+ unsigned Location;
+ };
+
+ union {
+ /// \brief When Kind == EK_Variable, or EK_Member, the VarDecl or
+ /// FieldDecl, respectively.
+ DeclaratorDecl *VariableOrMember;
+
+ /// \brief When Kind == EK_RelatedResult, the ObjectiveC method where
+ /// result type was implicitly changed to accommodate ARC semantics.
+ ObjCMethodDecl *MethodDecl;
+
+ /// \brief When Kind == EK_Parameter, the ParmVarDecl, with the
+ /// low bit indicating whether the parameter is "consumed".
+ uintptr_t Parameter;
+
+ /// \brief When Kind == EK_Temporary or EK_CompoundLiteralInit, the type
+ /// source information for the temporary.
+ TypeSourceInfo *TypeInfo;
+
+ struct LN 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, EK_VectorElement, or
+ /// EK_ComplexElement, the index of the array or vector element being
+ /// initialized.
+ unsigned Index;
+
+ struct C Capture;
+ };
+
+ InitializedEntity() : ManglingNumber(0) {}
+
+ /// \brief Create the initialization entity for a variable.
+ InitializedEntity(VarDecl *Var)
+ : Kind(EK_Variable), Parent(nullptr), Type(Var->getType()),
+ ManglingNumber(0), VariableOrMember(Var) { }
+
+ /// \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(nullptr), Type(Type), ManglingNumber(0)
+ {
+ 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()),
+ ManglingNumber(0), VariableOrMember(Member) { }
+
+ /// \brief Create the initialization entity for an array element.
+ InitializedEntity(ASTContext &Context, unsigned Index,
+ const InitializedEntity &Parent);
+
+ /// \brief Create the initialization entity for a lambda capture.
+ InitializedEntity(IdentifierInfo *VarID, QualType FieldType, SourceLocation Loc)
+ : Kind(EK_LambdaCapture), Parent(nullptr), Type(FieldType),
+ ManglingNumber(0)
+ {
+ Capture.VarID = VarID;
+ Capture.Location = Loc.getRawEncoding();
+ }
+
+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) {
+ return InitializeParameter(Context, Parm, Parm->getType());
+ }
+
+ /// \brief Create the initialization entity for a parameter, but use
+ /// another type.
+ static InitializedEntity InitializeParameter(ASTContext &Context,
+ ParmVarDecl *Parm,
+ QualType Type) {
+ bool Consumed = (Context.getLangOpts().ObjCAutoRefCount &&
+ Parm->hasAttr<NSConsumedAttr>());
+
+ InitializedEntity Entity;
+ Entity.Kind = EK_Parameter;
+ Entity.Type =
+ Context.getVariableArrayDecayedType(Type.getUnqualifiedType());
+ Entity.Parent = nullptr;
+ Entity.Parameter
+ = (static_cast<uintptr_t>(Consumed) | reinterpret_cast<uintptr_t>(Parm));
+ return Entity;
+ }
+
+ /// \brief Create the initialization entity for a parameter that is
+ /// only known by its type.
+ static InitializedEntity InitializeParameter(ASTContext &Context,
+ QualType Type,
+ bool Consumed) {
+ InitializedEntity Entity;
+ Entity.Kind = EK_Parameter;
+ Entity.Type = Context.getVariableArrayDecayedType(Type);
+ Entity.Parent = nullptr;
+ Entity.Parameter = (Consumed);
+ 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) {
+ InitializedEntity Result(EK_Temporary, SourceLocation(), Type);
+ Result.TypeInfo = nullptr;
+ return Result;
+ }
+
+ /// \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 related result.
+ static InitializedEntity InitializeRelatedResult(ObjCMethodDecl *MD,
+ QualType Type) {
+ InitializedEntity Result(EK_RelatedResult, SourceLocation(), Type);
+ Result.MethodDecl = MD;
+ return Result;
+ }
+
+
+ /// \brief Create the initialization entity for a base class subobject.
+ static InitializedEntity InitializeBase(ASTContext &Context,
+ const CXXBaseSpecifier *Base,
+ bool IsInheritedVirtualBase);
+
+ /// \brief Create the initialization entity for a delegated constructor.
+ static InitializedEntity InitializeDelegation(QualType Type) {
+ return InitializedEntity(EK_Delegating, SourceLocation(), Type);
+ }
+
+ /// \brief Create the initialization entity for a member subobject.
+ static InitializedEntity
+ InitializeMember(FieldDecl *Member,
+ const InitializedEntity *Parent = nullptr) {
+ return InitializedEntity(Member, Parent);
+ }
+
+ /// \brief Create the initialization entity for a member subobject.
+ static InitializedEntity
+ InitializeMember(IndirectFieldDecl *Member,
+ const InitializedEntity *Parent = nullptr) {
+ 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 Create the initialization entity for a lambda capture.
+ static InitializedEntity InitializeLambdaCapture(IdentifierInfo *VarID,
+ QualType FieldType,
+ SourceLocation Loc) {
+ return InitializedEntity(VarID, FieldType, Loc);
+ }
+
+ /// \brief Create the entity for a compound literal initializer.
+ static InitializedEntity InitializeCompoundLiteralInit(TypeSourceInfo *TSI) {
+ InitializedEntity Result(EK_CompoundLiteralInit, SourceLocation(),
+ TSI->getType());
+ Result.TypeInfo = TSI;
+ return Result;
+ }
+
+
+ /// \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 occurring 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 || Kind == EK_CompoundLiteralInit)
+ return TypeInfo;
+
+ return nullptr;
+ }
+
+ /// \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 Retrieve the ObjectiveC method being initialized.
+ ObjCMethodDecl *getMethodDecl() const { return MethodDecl; }
+
+ /// \brief Determine whether this initialization allows the named return
+ /// value optimization, which also applies to thrown objects.
+ bool allowsNRVO() const;
+
+ bool isParameterKind() const {
+ return (getKind() == EK_Parameter ||
+ getKind() == EK_Parameter_CF_Audited);
+ }
+ /// \brief Determine whether this initialization consumes the
+ /// parameter.
+ bool isParameterConsumed() const {
+ assert(isParameterKind() && "Not a parameter");
+ return (Parameter & 1);
+ }
+
+ /// \brief Retrieve the base specifier.
+ const CXXBaseSpecifier *getBaseSpecifier() const {
+ assert(getKind() == EK_Base && "Not a base specifier");
+ return reinterpret_cast<const 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 an array, vector, or complex number element, get the
+ /// element's index.
+ unsigned getElementIndex() const {
+ assert(getKind() == EK_ArrayElement || getKind() == EK_VectorElement ||
+ getKind() == EK_ComplexElement);
+ return Index;
+ }
+ /// \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 ||
+ getKind() == EK_ComplexElement);
+ this->Index = Index;
+ }
+ /// \brief For a lambda capture, return the capture's name.
+ StringRef getCapturedVarName() const {
+ assert(getKind() == EK_LambdaCapture && "Not a lambda capture!");
+ return Capture.VarID->getName();
+ }
+ /// \brief Determine the location of the capture when initializing
+ /// field from a captured variable in a lambda.
+ SourceLocation getCaptureLoc() const {
+ assert(getKind() == EK_LambdaCapture && "Not a lambda capture!");
+ return SourceLocation::getFromRawEncoding(Capture.Location);
+ }
+
+ void setParameterCFAudited() {
+ Kind = EK_Parameter_CF_Audited;
+ }
+
+ unsigned allocateManglingNumber() const { return ++ManglingNumber; }
+
+ /// Dump a representation of the initialized entity to standard error,
+ /// for debugging purposes.
+ void dump() const;
+
+private:
+ unsigned dumpImpl(raw_ostream &OS) const;
+};
+
+/// \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_DirectList, ///< Direct list-initialization
+ IK_Copy, ///< Copy initialization
+ IK_Default, ///< Default initialization
+ IK_Value ///< Value initialization
+ };
+
+private:
+ /// \brief The context of the initialization.
+ enum InitContext {
+ IC_Normal, ///< Normal context
+ IC_ExplicitConvs, ///< Normal context, but allows explicit conversion funcs
+ IC_Implicit, ///< Implicit context (value initialization)
+ IC_StaticCast, ///< Static cast context
+ IC_CStyleCast, ///< C-style cast context
+ IC_FunctionalCast ///< Functional cast context
+ };
+
+ /// \brief The kind of initialization being performed.
+ InitKind Kind : 8;
+
+ /// \brief The context of the initialization.
+ InitContext Context : 8;
+
+ /// \brief The source locations involved in the initialization.
+ SourceLocation Locations[3];
+
+ InitializationKind(InitKind Kind, InitContext Context, SourceLocation Loc1,
+ SourceLocation Loc2, SourceLocation Loc3)
+ : Kind(Kind), Context(Context)
+ {
+ 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(IK_Direct, IC_Normal,
+ InitLoc, LParenLoc, RParenLoc);
+ }
+
+ static InitializationKind CreateDirectList(SourceLocation InitLoc) {
+ return InitializationKind(IK_DirectList, IC_Normal,
+ InitLoc, InitLoc, InitLoc);
+ }
+
+ /// \brief Create a direct initialization due to a cast that isn't a C-style
+ /// or functional cast.
+ static InitializationKind CreateCast(SourceRange TypeRange) {
+ return InitializationKind(IK_Direct, IC_StaticCast, TypeRange.getBegin(),
+ TypeRange.getBegin(), TypeRange.getEnd());
+ }
+
+ /// \brief Create a direct initialization for a C-style cast.
+ static InitializationKind CreateCStyleCast(SourceLocation StartLoc,
+ SourceRange TypeRange,
+ bool InitList) {
+ // C++ cast syntax doesn't permit init lists, but C compound literals are
+ // exactly that.
+ return InitializationKind(InitList ? IK_DirectList : IK_Direct,
+ IC_CStyleCast, StartLoc, TypeRange.getBegin(),
+ TypeRange.getEnd());
+ }
+
+ /// \brief Create a direct initialization for a functional cast.
+ static InitializationKind CreateFunctionalCast(SourceRange TypeRange,
+ bool InitList) {
+ return InitializationKind(InitList ? IK_DirectList : IK_Direct,
+ IC_FunctionalCast, TypeRange.getBegin(),
+ TypeRange.getBegin(), TypeRange.getEnd());
+ }
+
+ /// \brief Create a copy initialization.
+ static InitializationKind CreateCopy(SourceLocation InitLoc,
+ SourceLocation EqualLoc,
+ bool AllowExplicitConvs = false) {
+ return InitializationKind(IK_Copy,
+ AllowExplicitConvs? IC_ExplicitConvs : IC_Normal,
+ InitLoc, EqualLoc, EqualLoc);
+ }
+
+ /// \brief Create a default initialization.
+ static InitializationKind CreateDefault(SourceLocation InitLoc) {
+ return InitializationKind(IK_Default, IC_Normal, InitLoc, InitLoc, InitLoc);
+ }
+
+ /// \brief Create a value initialization.
+ static InitializationKind CreateValue(SourceLocation InitLoc,
+ SourceLocation LParenLoc,
+ SourceLocation RParenLoc,
+ bool isImplicit = false) {
+ return InitializationKind(IK_Value, isImplicit ? IC_Implicit : IC_Normal,
+ InitLoc, LParenLoc, RParenLoc);
+ }
+
+ /// \brief Determine the initialization kind.
+ InitKind getKind() const {
+ return Kind;
+ }
+
+ /// \brief Determine whether this initialization is an explicit cast.
+ bool isExplicitCast() const {
+ return Context >= IC_StaticCast;
+ }
+
+ /// \brief Determine whether this initialization is a C-style cast.
+ bool isCStyleOrFunctionalCast() const {
+ return Context >= IC_CStyleCast;
+ }
+
+ /// \brief Determine whether this is a C-style cast.
+ bool isCStyleCast() const {
+ return Context == IC_CStyleCast;
+ }
+
+ /// \brief Determine whether this is a functional-style cast.
+ bool isFunctionalCast() const {
+ return Context == IC_FunctionalCast;
+ }
+
+ /// \brief Determine whether this initialization is an implicit
+ /// value-initialization, e.g., as occurs during aggregate
+ /// initialization.
+ bool isImplicitValueInit() const { return Context == IC_Implicit; }
+
+ /// \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 == IK_Copy && "Only copy initialization has an '='");
+ return Locations[1];
+ }
+
+ bool isCopyInit() const { return Kind == IK_Copy; }
+
+ /// \brief Retrieve whether this initialization allows the use of explicit
+ /// constructors.
+ bool AllowExplicit() const { return !isCopyInit(); }
+
+ /// \brief Retrieve whether this initialization allows the use of explicit
+ /// conversion functions when binding a reference. If the reference is the
+ /// first parameter in a copy or move constructor, such conversions are
+ /// permitted even though we are performing copy-initialization.
+ bool allowExplicitConversionFunctionsInRefBinding() const {
+ return !isCopyInit() || Context == IC_ExplicitConvs;
+ }
+
+ /// \brief Retrieve the source range containing the locations of the open
+ /// and closing parentheses for value and direct initializations.
+ SourceRange getParenRange() const {
+ assert((Kind == IK_Direct || Kind == IK_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.
+ 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-typed expressions.
+ DependentSequence,
+
+ /// \brief A normal sequence.
+ NormalSequence
+ };
+
+ /// \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 a conversion adding _Atomic to a type.
+ SK_AtomicConversion,
+ /// \brief Perform a load from a glvalue, producing an rvalue.
+ SK_LValueToRValue,
+ /// \brief Perform an implicit conversion sequence.
+ SK_ConversionSequence,
+ /// \brief Perform an implicit conversion sequence without narrowing.
+ SK_ConversionSequenceNoNarrowing,
+ /// \brief Perform list-initialization without a constructor.
+ SK_ListInitialization,
+ /// \brief Unwrap the single-element initializer list for a reference.
+ SK_UnwrapInitList,
+ /// \brief Rewrap the single-element initializer list for a reference.
+ SK_RewrapInitList,
+ /// \brief Perform initialization via a constructor.
+ SK_ConstructorInitialization,
+ /// \brief Perform initialization via a constructor, taking arguments from
+ /// a single InitListExpr.
+ SK_ConstructorInitializationFromList,
+ /// \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 Array initialization (from an array rvalue).
+ /// This is a GNU C extension.
+ SK_ArrayInit,
+ /// \brief Array initialization from a parenthesized initializer list.
+ /// This is a GNU C++ extension.
+ SK_ParenthesizedArrayInit,
+ /// \brief Pass an object by indirect copy-and-restore.
+ SK_PassByIndirectCopyRestore,
+ /// \brief Pass an object by indirect restore.
+ SK_PassByIndirectRestore,
+ /// \brief Produce an Objective-C object pointer.
+ SK_ProduceObjCObject,
+ /// \brief Construct a std::initializer_list from an initializer list.
+ SK_StdInitializerList,
+ /// \brief Perform initialization via a constructor taking a single
+ /// std::initializer_list argument.
+ SK_StdInitializerListConstructorCall,
+ /// \brief Initialize an OpenCL sampler from an integer.
+ SK_OCLSamplerInit,
+ /// \brief Passing zero to a function where OpenCL event_t is expected.
+ SK_OCLZeroEvent
+ };
+
+ /// \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;
+
+ struct F {
+ bool HadMultipleCandidates;
+ FunctionDecl *Function;
+ DeclAccessPair FoundDecl;
+ };
+
+ 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.
+ /// When Kind == SK_ConstructorInitialization or SK_ListConstruction,
+ /// the constructor to be called.
+ ///
+ /// Always a FunctionDecl, plus a Boolean flag telling if it was
+ /// selected from an overloaded set having size greater than 1.
+ /// For conversion decls, the naming class is the source type.
+ /// For construct decls, the naming class is the target type.
+ struct F Function;
+
+ /// \brief When Kind = SK_ConversionSequence, the implicit conversion
+ /// sequence.
+ ImplicitConversionSequence *ICS;
+
+ /// \brief When Kind = SK_RewrapInitList, the syntactic form of the
+ /// wrapping list.
+ InitListExpr *WrappingSyntacticList;
+ };
+
+ void Destroy();
+ };
+
+private:
+ /// \brief The kind of initialization sequence computed.
+ enum SequenceKind SequenceKind;
+
+ /// \brief Steps taken by this initialization.
+ 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 Array must be initialized with an initializer list or a
+ /// wide string literal.
+ FK_ArrayNeedsInitListOrWideStringLiteral,
+ /// \brief Initializing a wide char array with narrow string literal.
+ FK_NarrowStringIntoWideCharArray,
+ /// \brief Initializing char array with wide string literal.
+ FK_WideStringIntoCharArray,
+ /// \brief Initializing wide char array with incompatible wide string
+ /// literal.
+ FK_IncompatWideStringIntoWideChar,
+ /// \brief Array type mismatch.
+ FK_ArrayTypeMismatch,
+ /// \brief Non-constant array initializer
+ FK_NonConstantArrayInit,
+ /// \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 Implicit conversion failed.
+ FK_ConversionFromPropertyFailed,
+ /// \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 Overloading for initialization by constructor failed.
+ FK_ConstructorOverloadFailed,
+ /// \brief Overloading for list-initialization by constructor failed.
+ FK_ListConstructorOverloadFailed,
+ /// \brief Default-initialization of a 'const' object.
+ FK_DefaultInitOfConst,
+ /// \brief Initialization of an incomplete type.
+ FK_Incomplete,
+ /// \brief Variable-length array must not have an initializer.
+ FK_VariableLengthArrayHasInitializer,
+ /// \brief List initialization failed at some point.
+ FK_ListInitializationFailed,
+ /// \brief Initializer has a placeholder type which cannot be
+ /// resolved by initialization.
+ FK_PlaceholderType,
+ /// \brief Trying to take the address of a function that doesn't support
+ /// having its address taken.
+ FK_AddressOfUnaddressableFunction,
+ /// \brief List-copy-initialization chose an explicit constructor.
+ FK_ExplicitConstructor
+ };
+
+private:
+ /// \brief The reason why initialization failed.
+ FailureKind Failure;
+
+ /// \brief The failed result of overload resolution.
+ OverloadingResult FailedOverloadResult;
+
+ /// \brief The candidate set created when initialization failed.
+ OverloadCandidateSet FailedCandidateSet;
+
+ /// \brief The incomplete type that caused a failure.
+ QualType FailedIncompleteType;
+
+ /// \brief The fixit that needs to be applied to make this initialization
+ /// succeed.
+ std::string ZeroInitializationFixit;
+ SourceLocation ZeroInitializationFixitLoc;
+
+public:
+ /// \brief Call for initializations are invalid but that would be valid
+ /// zero initialzations if Fixit was applied.
+ void SetZeroInitializationFixit(const std::string& Fixit, SourceLocation L) {
+ ZeroInitializationFixit = Fixit;
+ ZeroInitializationFixitLoc = L;
+ }
+
+private:
+
+ /// \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 TopLevelOfInitList true if we are initializing from an expression
+ /// at the top level inside an initializer list. This disallows
+ /// narrowing conversions in C++11 onwards.
+ InitializationSequence(Sema &S,
+ const InitializedEntity &Entity,
+ const InitializationKind &Kind,
+ MultiExprArg Args,
+ bool TopLevelOfInitList = false);
+ void InitializeFrom(Sema &S, const InitializedEntity &Entity,
+ const InitializationKind &Kind, MultiExprArg Args,
+ bool TopLevelOfInitList);
+
+ ~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 transferred 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 = nullptr);
+
+ /// \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,
+ ArrayRef<Expr *> Args);
+
+ /// \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.
+ explicit operator bool() const { return !Failed(); }
+
+ /// \brief Determine whether the initialization sequence is invalid.
+ bool Failed() const { return SequenceKind == FailedSequence; }
+
+ typedef SmallVectorImpl<Step>::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 Returns whether the last step in this initialization sequence is a
+ /// narrowing conversion, defined by C++0x [dcl.init.list]p7.
+ ///
+ /// If this function returns true, *isInitializerConstant will be set to
+ /// describe whether *Initializer was a constant expression. If
+ /// *isInitializerConstant is set to true, *ConstantValue will be set to the
+ /// evaluated value of *Initializer.
+ bool endsWithNarrowing(ASTContext &Ctx, const Expr *Initializer,
+ bool *isInitializerConstant,
+ APValue *ConstantValue) 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,
+ bool HadMultipleCandidates);
+
+ /// \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 Category Indicates whether the result will be treated as an
+ /// rvalue, an xvalue, or 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.
+ 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,
+ bool HadMultipleCandidates);
+
+ /// \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 performs conversion from non-atomic to atomic
+ /// type.
+ void AddAtomicConversionStep(QualType Ty);
+
+ /// \brief Add a new step that performs a load of the given type.
+ ///
+ /// Although the term "LValueToRValue" is conventional, this applies to both
+ /// lvalues and xvalues.
+ void AddLValueToRValueStep(QualType Ty);
+
+ /// \brief Add a new step that applies an implicit conversion sequence.
+ void AddConversionSequenceStep(const ImplicitConversionSequence &ICS,
+ QualType T, bool TopLevelOfInitList = false);
+
+ /// \brief Add a list-initialization step.
+ void AddListInitializationStep(QualType T);
+
+ /// \brief Add a constructor-initialization step.
+ ///
+ /// \param FromInitList The constructor call is syntactically an initializer
+ /// list.
+ /// \param AsInitList The constructor is called as an init list constructor.
+ void AddConstructorInitializationStep(CXXConstructorDecl *Constructor,
+ AccessSpecifier Access,
+ QualType T,
+ bool HadMultipleCandidates,
+ bool FromInitList, bool AsInitList);
+
+ /// \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 Add an array initialization step.
+ void AddArrayInitStep(QualType T);
+
+ /// \brief Add a parenthesized array initialization step.
+ void AddParenthesizedArrayInitStep(QualType T);
+
+ /// \brief Add a step to pass an object by indirect copy-restore.
+ void AddPassByIndirectCopyRestoreStep(QualType T, bool shouldCopy);
+
+ /// \brief Add a step to "produce" an Objective-C object (by
+ /// retaining it).
+ void AddProduceObjCObjectStep(QualType T);
+
+ /// \brief Add a step to construct a std::initializer_list object from an
+ /// initializer list.
+ void AddStdInitializerListConstructionStep(QualType T);
+
+ /// \brief Add a step to initialize an OpenCL sampler from an integer
+ /// constant.
+ void AddOCLSamplerInitStep(QualType T);
+
+ /// \brief Add a step to initialize an OpenCL event_t from a NULL
+ /// constant.
+ void AddOCLZeroEventStep(QualType T);
+
+ /// \brief Add steps to unwrap a initializer list for a reference around a
+ /// single element and rewrap it at the end.
+ void RewrapReferenceInitList(QualType T, InitListExpr *Syntactic);
+
+ /// \brief Note that this initialization sequence failed.
+ void SetFailed(FailureKind Failure) {
+ SequenceKind = FailedSequence;
+ this->Failure = Failure;
+ assert((Failure != FK_Incomplete || !FailedIncompleteType.isNull()) &&
+ "Incomplete type failure requires a type!");
+ }
+
+ /// \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 Note that this initialization sequence failed due to an
+ /// incomplete type.
+ void setIncompleteTypeFailure(QualType IncompleteType) {
+ FailedIncompleteType = IncompleteType;
+ SetFailed(FK_Incomplete);
+ }
+
+ /// \brief Determine why initialization failed.
+ FailureKind getFailureKind() const {
+ assert(Failed() && "Not an initialization failure!");
+ return Failure;
+ }
+
+ /// \brief Dump a representation of this initialization sequence to
+ /// the given stream, for debugging purposes.
+ void dump(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/LocInfoType.h b/contrib/llvm/tools/clang/include/clang/Sema/LocInfoType.h
new file mode 100644
index 0000000..63dfa72
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Sema/LocInfoType.h
@@ -0,0 +1,62 @@
+//===--- LocInfoType.h - Parsed Type with Location 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 defines the LocInfoType class, which holds a type and its
+// source-location information.
+//
+//===----------------------------------------------------------------------===//
+#ifndef LLVM_CLANG_SEMA_LOCINFOTYPE_H
+#define LLVM_CLANG_SEMA_LOCINFOTYPE_H
+
+#include "clang/AST/Type.h"
+
+namespace clang {
+
+class TypeSourceInfo;
+
+/// \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->isInstantiationDependentType(),
+ 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;
+ }
+};
+
+} // end namespace clang
+
+#endif // LLVM_CLANG_SEMA_LOCINFOTYPE_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..87c40f0
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Sema/Lookup.h
@@ -0,0 +1,760 @@
+//===--- 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/AST/DeclCXX.h"
+#include "clang/Sema/Sema.h"
+
+namespace clang {
+
+/// @brief Represents the results of name lookup.
+///
+/// An instance of the LookupResult class captures the results of a
+/// single name lookup, which can return no result (nothing found),
+/// a single declaration, a set of overloaded functions, or an
+/// ambiguity. Use the getKind() method to determine which of these
+/// results occurred for a given lookup.
+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(nullptr),
+ NamingClass(nullptr),
+ SemaPtr(&SemaRef),
+ NameInfo(NameInfo),
+ LookupKind(LookupKind),
+ IDNS(0),
+ Redecl(Redecl != Sema::NotForRedeclaration),
+ HideTags(true),
+ Diagnose(Redecl == Sema::NotForRedeclaration),
+ AllowHidden(false),
+ Shadowed(false)
+ {
+ 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(nullptr),
+ NamingClass(nullptr),
+ SemaPtr(&SemaRef),
+ NameInfo(Name, NameLoc),
+ LookupKind(LookupKind),
+ IDNS(0),
+ Redecl(Redecl != Sema::NotForRedeclaration),
+ HideTags(true),
+ Diagnose(Redecl == Sema::NotForRedeclaration),
+ AllowHidden(false),
+ Shadowed(false)
+ {
+ 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(nullptr),
+ NamingClass(nullptr),
+ SemaPtr(Other.SemaPtr),
+ NameInfo(Other.NameInfo),
+ LookupKind(Other.LookupKind),
+ IDNS(Other.IDNS),
+ Redecl(Other.Redecl),
+ HideTags(Other.HideTags),
+ Diagnose(false),
+ AllowHidden(Other.AllowHidden),
+ Shadowed(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;
+ }
+
+ /// \brief Specify whether hidden declarations are visible, e.g.,
+ /// for recovery reasons.
+ void setAllowHidden(bool AH) {
+ AllowHidden = AH;
+ }
+
+ /// \brief Determine whether this lookup is permitted to see hidden
+ /// declarations, such as those in modules that have not yet been imported.
+ bool isHiddenDeclarationVisible(NamedDecl *ND) const {
+ return AllowHidden ||
+ (isForRedeclaration() && ND->isExternallyVisible());
+ }
+
+ /// 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 {
+ assert(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 Determine whether the given declaration is visible to the
+ /// program.
+ static bool isVisible(Sema &SemaRef, NamedDecl *D) {
+ // If this declaration is not hidden, it's visible.
+ if (!D->isHidden())
+ return true;
+
+ // During template instantiation, we can refer to hidden declarations, if
+ // they were visible in any module along the path of instantiation.
+ return isVisibleSlow(SemaRef, D);
+ }
+
+ /// \brief Retrieve the accepted (re)declaration of the given declaration,
+ /// if there is one.
+ NamedDecl *getAcceptableDecl(NamedDecl *D) const {
+ if (!D->isInIdentifierNamespace(IDNS))
+ return nullptr;
+
+ if (isVisible(getSema(), D) || isHiddenDeclarationVisible(D))
+ return D;
+
+ return getAcceptableDeclSlow(D);
+ }
+
+private:
+ static bool isVisibleSlow(Sema &SemaRef, NamedDecl *D);
+ NamedDecl *getAcceptableDeclSlow(NamedDecl *D) const;
+
+public:
+ /// \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 != nullptr;
+ }
+
+ /// \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 Determine whether the lookup result was shadowed by some other
+ /// declaration that lookup ignored.
+ bool isShadowed() const { return Shadowed; }
+
+ /// \brief Note that we found and ignored a declaration while performing
+ /// lookup.
+ void setShadowed() { Shadowed = true; }
+
+ /// \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 = nullptr;
+ }
+ } else {
+ AmbiguityKind SavedAK;
+ bool WasAmbiguous = false;
+ if (ResultKind == Ambiguous) {
+ SavedAK = Ambiguity;
+ WasAmbiguous = true;
+ }
+ ResultKind = Found;
+ resolveKind();
+
+ // If we didn't make the lookup unambiguous, restore the old
+ // ambiguity kind.
+ if (ResultKind == Ambiguous) {
+ (void)WasAmbiguous;
+ assert(WasAmbiguous);
+ Ambiguity = SavedAK;
+ } else if (Paths) {
+ deletePaths(Paths);
+ Paths = nullptr;
+ }
+ }
+ }
+
+ template <class DeclClass>
+ DeclClass *getAsSingle() const {
+ if (getResultKind() != Found) return nullptr;
+ 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 = nullptr;
+ NamingClass = nullptr;
+ Shadowed = false;
+ }
+
+ /// \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(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 *SemaPtr; }
+
+ /// 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(Filter &&F)
+ : Results(F.Results), I(F.I), Changed(F.Changed),
+ CalledDone(F.CalledDone) {
+ F.CalledDone = true;
+ }
+ ~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++;
+ }
+
+ /// Restart the iteration.
+ void restart() {
+ I = Results.begin();
+ }
+
+ /// 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);
+ }
+
+ void setFindLocalExtern(bool FindLocalExtern) {
+ if (FindLocalExtern)
+ IDNS |= Decl::IDNS_LocalExtern;
+ else
+ IDNS &= ~Decl::IDNS_LocalExtern;
+ }
+
+private:
+ void diagnose() {
+ if (isAmbiguous())
+ getSema().DiagnoseAmbiguousLookup(*this);
+ else if (isClassLookup() && getSema().getLangOpts().AccessControl)
+ getSema().CheckLookupAccess(*this);
+ }
+
+ void setAmbiguous(AmbiguityKind AK) {
+ ResultKind = Ambiguous;
+ Ambiguity = AK;
+ }
+
+ void addDeclsFromBasePaths(const CXXBasePaths &P);
+ void configure();
+
+ // Sanity checks.
+ bool sanity() const;
+
+ bool sanityCheckUnresolved() const {
+ for (iterator I = begin(), E = end(); I != E; ++I)
+ if (isa<UnresolvedUsingValueDecl>((*I)->getUnderlyingDecl()))
+ 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 *SemaPtr;
+ 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 True if we should allow hidden declarations to be 'visible'.
+ bool AllowHidden;
+
+ /// \brief True if the found declarations were shadowed by some other
+ /// declaration that we skipped. This only happens when \c LookupKind
+ /// is \c LookupRedeclarationWithLinkage.
+ bool Shadowed;
+};
+
+/// \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 Determine whether hidden declarations (from unimported
+ /// modules) should be given to this consumer. By default, they
+ /// are not included.
+ virtual bool includeHiddenDecls() const;
+
+ /// \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 Ctx the original context from which the lookup started.
+ ///
+ /// \param InBaseClass whether this declaration was found in base
+ /// class of the context we searched.
+ virtual void FoundDecl(NamedDecl *ND, NamedDecl *Hiding, DeclContext *Ctx,
+ 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
+ : public llvm::iterator_adaptor_base<
+ iterator, llvm::DenseMap<NamedDecl *, NamedDecl *>::iterator,
+ std::forward_iterator_tag, NamedDecl *> {
+ friend class ADLResult;
+
+ iterator(llvm::DenseMap<NamedDecl *, NamedDecl *>::iterator Iter)
+ : iterator_adaptor_base(std::move(Iter)) {}
+
+ public:
+ iterator() {}
+
+ value_type operator*() const { return I->second; }
+ };
+
+ iterator begin() { return iterator(Decls.begin()); }
+ iterator end() { return iterator(Decls.end()); }
+};
+
+}
+
+#endif
diff --git a/contrib/llvm/tools/clang/include/clang/Sema/LoopHint.h b/contrib/llvm/tools/clang/include/clang/Sema/LoopHint.h
new file mode 100644
index 0000000..c8b2ee8
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Sema/LoopHint.h
@@ -0,0 +1,45 @@
+//===--- LoopHint.h - Types for LoopHint ------------------------*- 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_SEMA_LOOPHINT_H
+#define LLVM_CLANG_SEMA_LOOPHINT_H
+
+#include "clang/Basic/IdentifierTable.h"
+#include "clang/Basic/SourceLocation.h"
+#include "clang/Sema/AttributeList.h"
+#include "clang/Sema/Ownership.h"
+
+namespace clang {
+
+/// \brief Loop optimization hint for loop and unroll pragmas.
+struct LoopHint {
+ // Source range of the directive.
+ SourceRange Range;
+ // Identifier corresponding to the name of the pragma. "loop" for
+ // "#pragma clang loop" directives and "unroll" for "#pragma unroll"
+ // hints.
+ IdentifierLoc *PragmaNameLoc;
+ // Name of the loop hint. Examples: "unroll", "vectorize". In the
+ // "#pragma unroll" and "#pragma nounroll" cases, this is identical to
+ // PragmaNameLoc.
+ IdentifierLoc *OptionLoc;
+ // Identifier for the hint state argument. If null, then the state is
+ // default value such as for "#pragma unroll".
+ IdentifierLoc *StateLoc;
+ // Expression for the hint argument if it exists, null otherwise.
+ Expr *ValueExpr;
+
+ LoopHint()
+ : PragmaNameLoc(nullptr), OptionLoc(nullptr), StateLoc(nullptr),
+ ValueExpr(nullptr) {}
+};
+
+} // end namespace clang
+
+#endif // LLVM_CLANG_SEMA_LOOPHINT_H
diff --git a/contrib/llvm/tools/clang/include/clang/Sema/MultiplexExternalSemaSource.h b/contrib/llvm/tools/clang/include/clang/Sema/MultiplexExternalSemaSource.h
new file mode 100644
index 0000000..d6daadc
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Sema/MultiplexExternalSemaSource.h
@@ -0,0 +1,353 @@
+//===--- MultiplexExternalSemaSource.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 ExternalSemaSource interface, dispatching to all clients
+//
+//===----------------------------------------------------------------------===//
+#ifndef LLVM_CLANG_SEMA_MULTIPLEXEXTERNALSEMASOURCE_H
+#define LLVM_CLANG_SEMA_MULTIPLEXEXTERNALSEMASOURCE_H
+
+#include "clang/Sema/ExternalSemaSource.h"
+#include "clang/Sema/Weak.h"
+#include "llvm/ADT/SmallVector.h"
+#include <utility>
+
+namespace clang {
+
+ class CXXConstructorDecl;
+ class CXXRecordDecl;
+ class DeclaratorDecl;
+ struct ExternalVTableUse;
+ class LookupResult;
+ class NamespaceDecl;
+ class Scope;
+ class Sema;
+ class TypedefNameDecl;
+ class ValueDecl;
+ class VarDecl;
+
+
+/// \brief An abstract interface that should be implemented by
+/// external AST sources that also provide information for semantic
+/// analysis.
+class MultiplexExternalSemaSource : public ExternalSemaSource {
+
+private:
+ SmallVector<ExternalSemaSource *, 2> Sources; // doesn't own them.
+
+public:
+
+ ///\brief Constructs a new multiplexing external sema source and appends the
+ /// given element to it.
+ ///
+ ///\param[in] s1 - A non-null (old) ExternalSemaSource.
+ ///\param[in] s2 - A non-null (new) ExternalSemaSource.
+ ///
+ MultiplexExternalSemaSource(ExternalSemaSource& s1, ExternalSemaSource& s2);
+
+ ~MultiplexExternalSemaSource() override;
+
+ ///\brief Appends new source to the source list.
+ ///
+ ///\param[in] source - An ExternalSemaSource.
+ ///
+ void addSource(ExternalSemaSource &source);
+
+ //===--------------------------------------------------------------------===//
+ // ExternalASTSource.
+ //===--------------------------------------------------------------------===//
+
+ /// \brief Resolve a declaration ID into a declaration, potentially
+ /// building a new declaration.
+ Decl *GetExternalDecl(uint32_t ID) override;
+
+ /// \brief Complete the redeclaration chain if it's been extended since the
+ /// previous generation of the AST source.
+ void CompleteRedeclChain(const Decl *D) override;
+
+ /// \brief Resolve a selector ID into a selector.
+ Selector GetExternalSelector(uint32_t ID) override;
+
+ /// \brief Returns the number of selectors known to the external AST
+ /// source.
+ uint32_t GetNumExternalSelectors() override;
+
+ /// \brief Resolve the offset of a statement in the decl stream into
+ /// a statement.
+ Stmt *GetExternalDeclStmt(uint64_t Offset) override;
+
+ /// \brief Resolve the offset of a set of C++ base specifiers in the decl
+ /// stream into an array of specifiers.
+ CXXBaseSpecifier *GetExternalCXXBaseSpecifiers(uint64_t Offset) override;
+
+ /// \brief Resolve a handle to a list of ctor initializers into the list of
+ /// initializers themselves.
+ CXXCtorInitializer **GetExternalCXXCtorInitializers(uint64_t Offset) override;
+
+ /// \brief Find all declarations with the given name in the
+ /// given context.
+ bool FindExternalVisibleDeclsByName(const DeclContext *DC,
+ DeclarationName Name) override;
+
+ /// \brief Ensures that the table of all visible declarations inside this
+ /// context is up to date.
+ void completeVisibleDeclsMap(const DeclContext *DC) override;
+
+ /// \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.
+ void
+ FindExternalLexicalDecls(const DeclContext *DC,
+ llvm::function_ref<bool(Decl::Kind)> IsKindWeWant,
+ SmallVectorImpl<Decl *> &Result) override;
+
+ /// \brief Get the decls that are contained in a file in the Offset/Length
+ /// range. \p Length can be 0 to indicate a point at \p Offset instead of
+ /// a range.
+ void FindFileRegionDecls(FileID File, unsigned Offset,unsigned Length,
+ SmallVectorImpl<Decl *> &Decls) override;
+
+ /// \brief Gives the external AST source an opportunity to complete
+ /// an incomplete type.
+ void CompleteType(TagDecl *Tag) override;
+
+ /// \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().
+ void CompleteType(ObjCInterfaceDecl *Class) override;
+
+ /// \brief Loads comment ranges.
+ void ReadComments() override;
+
+ /// \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.
+ void StartedDeserializing() override;
+
+ /// \brief Notify ExternalASTSource that we finished the deserialization of
+ /// a decl or type. Must be paired with StartedDeserializing.
+ void FinishedDeserializing() override;
+
+ /// \brief Function that will be invoked when we begin parsing a new
+ /// translation unit involving this external AST source.
+ void StartTranslationUnit(ASTConsumer *Consumer) override;
+
+ /// \brief Print any statistics that have been gathered regarding
+ /// the external AST source.
+ void PrintStats() override;
+
+
+ /// \brief Perform layout on the given record.
+ ///
+ /// This routine allows the external AST source to provide an specific
+ /// layout for a record, overriding the layout that would normally be
+ /// constructed. It is intended for clients who receive specific layout
+ /// details rather than source code (such as LLDB). The client is expected
+ /// to fill in the field offsets, base offsets, virtual base offsets, and
+ /// complete object size.
+ ///
+ /// \param Record The record whose layout is being requested.
+ ///
+ /// \param Size The final size of the record, in bits.
+ ///
+ /// \param Alignment The final alignment of the record, in bits.
+ ///
+ /// \param FieldOffsets The offset of each of the fields within the record,
+ /// expressed in bits. All of the fields must be provided with offsets.
+ ///
+ /// \param BaseOffsets The offset of each of the direct, non-virtual base
+ /// classes. If any bases are not given offsets, the bases will be laid
+ /// out according to the ABI.
+ ///
+ /// \param VirtualBaseOffsets The offset of each of the virtual base classes
+ /// (either direct or not). If any bases are not given offsets, the bases will
+ /// be laid out according to the ABI.
+ ///
+ /// \returns true if the record layout was provided, false otherwise.
+ bool
+ layoutRecordType(const RecordDecl *Record,
+ uint64_t &Size, uint64_t &Alignment,
+ llvm::DenseMap<const FieldDecl *, uint64_t> &FieldOffsets,
+ llvm::DenseMap<const CXXRecordDecl *, CharUnits> &BaseOffsets,
+ llvm::DenseMap<const CXXRecordDecl *,
+ CharUnits> &VirtualBaseOffsets) override;
+
+ /// Return the amount of memory used by memory buffers, breaking down
+ /// by heap-backed versus mmap'ed memory.
+ void getMemoryBufferSizes(MemoryBufferSizes &sizes) const override;
+
+ //===--------------------------------------------------------------------===//
+ // ExternalSemaSource.
+ //===--------------------------------------------------------------------===//
+
+ /// \brief Initialize the semantic source with the Sema instance
+ /// being used to perform semantic analysis on the abstract syntax
+ /// tree.
+ void InitializeSema(Sema &S) override;
+
+ /// \brief Inform the semantic consumer that Sema is no longer available.
+ void ForgetSema() override;
+
+ /// \brief Load the contents of the global method pool for a given
+ /// selector.
+ void ReadMethodPool(Selector Sel) override;
+
+ /// \brief Load the set of namespaces that are known to the external source,
+ /// which will be used during typo correction.
+ void
+ ReadKnownNamespaces(SmallVectorImpl<NamespaceDecl*> &Namespaces) override;
+
+ /// \brief Load the set of used but not defined functions or variables with
+ /// internal linkage, or used but not defined inline functions.
+ void ReadUndefinedButUsed(
+ llvm::DenseMap<NamedDecl*, SourceLocation> &Undefined) override;
+
+ void ReadMismatchingDeleteExpressions(llvm::MapVector<
+ FieldDecl *, llvm::SmallVector<std::pair<SourceLocation, bool>, 4>> &
+ Exprs) override;
+
+ /// \brief Do last resort, unqualified lookup on a LookupResult that
+ /// Sema cannot find.
+ ///
+ /// \param R a LookupResult that is being recovered.
+ ///
+ /// \param S the Scope of the identifier occurrence.
+ ///
+ /// \return true to tell Sema to recover using the LookupResult.
+ bool LookupUnqualified(LookupResult &R, Scope *S) override;
+
+ /// \brief Read the set of tentative definitions known to the external Sema
+ /// source.
+ ///
+ /// The external source should append its own tentative definitions to the
+ /// given vector of tentative definitions. Note that this routine may be
+ /// invoked multiple times; the external source should take care not to
+ /// introduce the same declarations repeatedly.
+ void ReadTentativeDefinitions(SmallVectorImpl<VarDecl*> &Defs) override;
+
+ /// \brief Read the set of unused file-scope declarations known to the
+ /// external Sema source.
+ ///
+ /// The external source should append its own unused, filed-scope to the
+ /// given vector of declarations. Note that this routine may be
+ /// invoked multiple times; the external source should take care not to
+ /// introduce the same declarations repeatedly.
+ void ReadUnusedFileScopedDecls(
+ SmallVectorImpl<const DeclaratorDecl*> &Decls) override;
+
+ /// \brief Read the set of delegating constructors known to the
+ /// external Sema source.
+ ///
+ /// The external source should append its own delegating constructors to the
+ /// given vector of declarations. Note that this routine may be
+ /// invoked multiple times; the external source should take care not to
+ /// introduce the same declarations repeatedly.
+ void ReadDelegatingConstructors(
+ SmallVectorImpl<CXXConstructorDecl*> &Decls) override;
+
+ /// \brief Read the set of ext_vector type declarations known to the
+ /// external Sema source.
+ ///
+ /// The external source should append its own ext_vector type declarations to
+ /// the given vector of declarations. Note that this routine may be
+ /// invoked multiple times; the external source should take care not to
+ /// introduce the same declarations repeatedly.
+ void ReadExtVectorDecls(SmallVectorImpl<TypedefNameDecl*> &Decls) override;
+
+ /// \brief Read the set of potentially unused typedefs known to the source.
+ ///
+ /// The external source should append its own potentially unused local
+ /// typedefs to the given vector of declarations. Note that this routine may
+ /// be invoked multiple times; the external source should take care not to
+ /// introduce the same declarations repeatedly.
+ void ReadUnusedLocalTypedefNameCandidates(
+ llvm::SmallSetVector<const TypedefNameDecl *, 4> &Decls) override;
+
+ /// \brief Read the set of referenced selectors known to the
+ /// external Sema source.
+ ///
+ /// The external source should append its own referenced selectors to the
+ /// given vector of selectors. Note that this routine
+ /// may be invoked multiple times; the external source should take care not
+ /// to introduce the same selectors repeatedly.
+ void ReadReferencedSelectors(SmallVectorImpl<std::pair<Selector,
+ SourceLocation> > &Sels) override;
+
+ /// \brief Read the set of weak, undeclared identifiers known to the
+ /// external Sema source.
+ ///
+ /// The external source should append its own weak, undeclared identifiers to
+ /// the given vector. Note that this routine may be invoked multiple times;
+ /// the external source should take care not to introduce the same identifiers
+ /// repeatedly.
+ void ReadWeakUndeclaredIdentifiers(
+ SmallVectorImpl<std::pair<IdentifierInfo*, WeakInfo> > &WI) override;
+
+ /// \brief Read the set of used vtables known to the external Sema source.
+ ///
+ /// The external source should append its own used vtables to the given
+ /// vector. Note that this routine may be invoked multiple times; the external
+ /// source should take care not to introduce the same vtables repeatedly.
+ void ReadUsedVTables(SmallVectorImpl<ExternalVTableUse> &VTables) override;
+
+ /// \brief Read the set of pending instantiations known to the external
+ /// Sema source.
+ ///
+ /// The external source should append its own pending instantiations to the
+ /// given vector. Note that this routine may be invoked multiple times; the
+ /// external source should take care not to introduce the same instantiations
+ /// repeatedly.
+ void ReadPendingInstantiations(
+ SmallVectorImpl<std::pair<ValueDecl*, SourceLocation> >& Pending) override;
+
+ /// \brief Read the set of late parsed template functions for this source.
+ ///
+ /// The external source should insert its own late parsed template functions
+ /// into the map. Note that this routine may be invoked multiple times; the
+ /// external source should take care not to introduce the same map entries
+ /// repeatedly.
+ void ReadLateParsedTemplates(
+ llvm::MapVector<const FunctionDecl *, LateParsedTemplate *> &LPTMap)
+ override;
+
+ /// \copydoc ExternalSemaSource::CorrectTypo
+ /// \note Returns the first nonempty correction.
+ TypoCorrection CorrectTypo(const DeclarationNameInfo &Typo,
+ int LookupKind, Scope *S, CXXScopeSpec *SS,
+ CorrectionCandidateCallback &CCC,
+ DeclContext *MemberContext,
+ bool EnteringContext,
+ const ObjCObjectPointerType *OPT) override;
+
+ /// \brief Produces a diagnostic note if one of the attached sources
+ /// contains a complete definition for \p T. Queries the sources in list
+ /// order until the first one claims that a diagnostic was produced.
+ ///
+ /// \param Loc the location at which a complete type was required but not
+ /// provided
+ ///
+ /// \param T the \c QualType that should have been complete at \p Loc
+ ///
+ /// \return true if a diagnostic was produced, false otherwise.
+ bool MaybeDiagnoseMissingCompleteType(SourceLocation Loc,
+ QualType T) override;
+
+ // isa/cast/dyn_cast support
+ static bool classof(const MultiplexExternalSemaSource*) { return true; }
+ //static bool classof(const ExternalSemaSource*) { return true; }
+};
+
+} // end namespace clang
+
+#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..b618e38
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Sema/ObjCMethodList.h
@@ -0,0 +1,58 @@
+//===--- 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_OBJCMETHODLIST_H
+#define LLVM_CLANG_SEMA_OBJCMETHODLIST_H
+
+#include "llvm/ADT/PointerIntPair.h"
+
+namespace clang {
+
+class ObjCMethodDecl;
+
+/// \brief a linked list of methods with the same selector name but different
+/// signatures.
+struct ObjCMethodList {
+ // NOTE: If you add any members to this struct, make sure to serialize them.
+ /// \brief If there is more than one decl with this signature.
+ llvm::PointerIntPair<ObjCMethodDecl *, 1> MethodAndHasMoreThanOneDecl;
+ /// \brief The next list object and 2 bits for extra info.
+ llvm::PointerIntPair<ObjCMethodList *, 2> NextAndExtraBits;
+
+ ObjCMethodList() { }
+ ObjCMethodList(ObjCMethodDecl *M)
+ : MethodAndHasMoreThanOneDecl(M, 0) {}
+
+ ObjCMethodList *getNext() const { return NextAndExtraBits.getPointer(); }
+ unsigned getBits() const { return NextAndExtraBits.getInt(); }
+ void setNext(ObjCMethodList *L) { NextAndExtraBits.setPointer(L); }
+ void setBits(unsigned B) { NextAndExtraBits.setInt(B); }
+
+ ObjCMethodDecl *getMethod() const {
+ return MethodAndHasMoreThanOneDecl.getPointer();
+ }
+ void setMethod(ObjCMethodDecl *M) {
+ return MethodAndHasMoreThanOneDecl.setPointer(M);
+ }
+
+ bool hasMoreThanOneDecl() const {
+ return MethodAndHasMoreThanOneDecl.getInt();
+ }
+ void setHasMoreThanOneDecl(bool B) {
+ return MethodAndHasMoreThanOneDecl.setInt(B);
+ }
+};
+
+}
+
+#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..20958b0
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Sema/Overload.h
@@ -0,0 +1,799 @@
+//===--- 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 "clang/Sema/SemaFixItUtils.h"
+#include "clang/Sema/TemplateDeduction.h"
+#include "llvm/ADT/SmallPtrSet.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/Support/AlignOf.h"
+#include "llvm/Support/Allocator.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_TransparentUnionConversion, ///< Transparent Union Conversions
+ ICK_Writeback_Conversion, ///< Objective-C ARC writeback conversion
+ ICK_Zero_Event_Conversion, ///< Zero constant to event (OpenCL1.2 6.12.10)
+ ICK_C_Only_Conversion, ///< Conversions allowed in C, but not C++
+ ICK_Num_Conversion_Kinds, ///< The number of conversion kinds
+ };
+
+ /// 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
+ ICR_Writeback_Conversion, ///< ObjC ARC writeback conversion
+ ICR_C_Conversion ///< Conversion only allowed in the C standard.
+ /// (e.g. void* to char*)
+ };
+
+ ImplicitConversionRank GetConversionRank(ImplicitConversionKind Kind);
+
+ /// NarrowingKind - The kind of narrowing conversion being performed by a
+ /// standard conversion sequence according to C++11 [dcl.init.list]p7.
+ enum NarrowingKind {
+ /// Not a narrowing conversion.
+ NK_Not_Narrowing,
+
+ /// A narrowing conversion by virtue of the source and destination types.
+ NK_Type_Narrowing,
+
+ /// A narrowing conversion, because a constant expression got narrowed.
+ NK_Constant_Narrowing,
+
+ /// A narrowing conversion, because a non-constant-expression variable might
+ /// have got narrowed.
+ NK_Variable_Narrowing
+ };
+
+ /// 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;
+
+ /// \brief Whether the qualification conversion involves a change in the
+ /// Objective-C lifetime (for automatic reference counting).
+ unsigned QualificationIncludesObjCLifetime : 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;
+
+ /// \brief Whether this binds a reference to an object with a different
+ /// Objective-C lifetime qualifier.
+ unsigned ObjCLifetimeConversionBinding : 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 Second == ICK_Identity && Third == ICK_Identity;
+ }
+
+ ImplicitConversionRank getRank() const;
+ NarrowingKind getNarrowingKind(ASTContext &Context, const Expr *Converted,
+ APValue &ConstantValue,
+ QualType &ConstantType) const;
+ bool isPointerConversionToBool() const;
+ bool isPointerConversionToVoidPointer(ASTContext& Context) const;
+ void dump() const;
+ };
+
+ /// UserDefinedConversionSequence - Represents a user-defined
+ /// conversion sequence (C++ 13.3.3.1.2).
+ struct UserDefinedConversionSequence {
+ /// \brief Represents the standard conversion that occurs before
+ /// the actual user-defined conversion.
+ ///
+ /// C++11 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 ... (ellipsis) 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;
+
+ /// HadMultipleCandidates - When this is true, it means that the
+ /// conversion function was resolved from an overloaded set having
+ /// size greater than 1.
+ bool HadMultipleCandidates : 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. Null if the conversion is an
+ /// aggregate initialization from an initializer list.
+ 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.
+ DeclAccessPair FoundConversionFunction;
+
+ void dump() const;
+ };
+
+ /// Represents an ambiguous user-defined conversion sequence.
+ struct AmbiguousConversionSequence {
+ typedef 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,
+ 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 = nullptr;
+ 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 : 30;
+
+ /// \brief Whether the target is really a std::initializer_list, and the
+ /// sequence only represents the worst element conversion.
+ bool StdInitializerListElement : 1;
+
+ 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), StdInitializerListElement(false)
+ {}
+ ~ImplicitConversionSequence() {
+ destruct();
+ }
+ ImplicitConversionSequence(const ImplicitConversionSequence &Other)
+ : ConversionKind(Other.ConversionKind),
+ StdInitializerListElement(Other.StdInitializerListElement)
+ {
+ 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;
+ }
+
+ llvm_unreachable("Invalid ImplicitConversionSequence::Kind!");
+ }
+
+ 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; }
+ bool isFailure() const { return isBad() || isAmbiguous(); }
+
+ /// 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();
+ }
+
+ /// \brief Whether the target is really a std::initializer_list, and the
+ /// sequence only represents the worst element conversion.
+ bool isStdInitializerListElement() const {
+ return StdInitializerListElement;
+ }
+
+ void setStdInitializerListElement(bool V = true) {
+ StdInitializerListElement = V;
+ }
+
+ // 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 dump() 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 was not considered because it is
+ /// an illegal instantiation of a constructor temploid: it is
+ /// callable with one argument, we only have one argument, and
+ /// its first parameter type is exactly the type of the class.
+ ///
+ /// Defining such a constructor directly is illegal, and
+ /// template-argument deduction is supposed to ignore such
+ /// instantiations, but we can still get one with the right
+ /// kind of implicit instantiation.
+ ovl_fail_illegal_constructor,
+
+ /// 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,
+
+ /// (CUDA) This candidate was not viable because the callee
+ /// was not accessible from the caller's target (i.e. host->device,
+ /// global->host, device->host).
+ ovl_fail_bad_target,
+
+ /// This candidate function was not viable because an enable_if
+ /// attribute disabled it.
+ ovl_fail_enable_if
+ };
+
+ /// 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, the pointer points to a
+ /// fixed size array with NumConversions elements. The memory is owned by
+ /// the OverloadCandidateSet.
+ ImplicitConversionSequence *Conversions;
+
+ /// The FixIt hints which can be used to fix the Bad candidate.
+ ConversionFixItGenerator Fix;
+
+ /// NumConversions - The number of elements in the Conversions array.
+ unsigned NumConversions;
+
+ /// 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;
+
+ 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 (unsigned i = 0, e = NumConversions; i != e; ++i) {
+ if (!Conversions[i].isInitialized()) return false;
+ if (Conversions[i].isAmbiguous()) return true;
+ }
+ return false;
+ }
+
+ bool TryToFixBadConversion(unsigned Idx, Sema &S) {
+ bool CanFix = Fix.tryToFixConversion(
+ Conversions[Idx].Bad.FromExpr,
+ Conversions[Idx].Bad.getFromType(),
+ Conversions[Idx].Bad.getToType(), S);
+
+ // If at least one conversion fails, the candidate cannot be fixed.
+ if (!CanFix)
+ Fix.clear();
+
+ return CanFix;
+ }
+
+ unsigned getNumParams() const {
+ if (IsSurrogate) {
+ auto STy = Surrogate->getConversionType();
+ while (STy->isPointerType() || STy->isReferenceType())
+ STy = STy->getPointeeType();
+ return STy->getAs<FunctionProtoType>()->getNumParams();
+ }
+ if (Function)
+ return Function->getNumParams();
+ return ExplicitCallArguments;
+ }
+ };
+
+ /// OverloadCandidateSet - A set of overload candidates, used in C++
+ /// overload resolution (C++ 13.3).
+ class OverloadCandidateSet {
+ public:
+ enum CandidateSetKind {
+ /// Normal lookup.
+ CSK_Normal,
+ /// Lookup for candidates for a call using operator syntax. Candidates
+ /// that have no parameters of class type will be skipped unless there
+ /// is a parameter of (reference to) enum type and the corresponding
+ /// argument is of the same enum type.
+ CSK_Operator
+ };
+
+ private:
+ SmallVector<OverloadCandidate, 16> Candidates;
+ llvm::SmallPtrSet<Decl *, 16> Functions;
+
+ // Allocator for OverloadCandidate::Conversions. We store the first few
+ // elements inline to avoid allocation for small sets.
+ llvm::BumpPtrAllocator ConversionSequenceAllocator;
+
+ SourceLocation Loc;
+ CandidateSetKind Kind;
+
+ unsigned NumInlineSequences;
+ llvm::AlignedCharArray<llvm::AlignOf<ImplicitConversionSequence>::Alignment,
+ 16 * sizeof(ImplicitConversionSequence)> InlineSpace;
+
+ OverloadCandidateSet(const OverloadCandidateSet &) = delete;
+ void operator=(const OverloadCandidateSet &) = delete;
+
+ void destroyCandidates();
+
+ public:
+ OverloadCandidateSet(SourceLocation Loc, CandidateSetKind CSK)
+ : Loc(Loc), Kind(CSK), NumInlineSequences(0) {}
+ ~OverloadCandidateSet() { destroyCandidates(); }
+
+ SourceLocation getLocation() const { return Loc; }
+ CandidateSetKind getKind() const { return Kind; }
+
+ /// \brief Determine when this overload candidate will be new to the
+ /// overload set.
+ bool isNewCandidate(Decl *F) {
+ return Functions.insert(F->getCanonicalDecl()).second;
+ }
+
+ /// \brief Clear out all of the candidates.
+ void clear();
+
+ typedef SmallVectorImpl<OverloadCandidate>::iterator iterator;
+ iterator begin() { return Candidates.begin(); }
+ iterator end() { return Candidates.end(); }
+
+ size_t size() const { return Candidates.size(); }
+ bool empty() const { return Candidates.empty(); }
+
+ /// \brief Add a new candidate with NumConversions conversion sequence slots
+ /// to the overload set.
+ OverloadCandidate &addCandidate(unsigned NumConversions = 0) {
+ Candidates.push_back(OverloadCandidate());
+ OverloadCandidate &C = Candidates.back();
+
+ // Assign space from the inline array if there are enough free slots
+ // available.
+ if (NumConversions + NumInlineSequences <= 16) {
+ ImplicitConversionSequence *I =
+ (ImplicitConversionSequence *)InlineSpace.buffer;
+ C.Conversions = &I[NumInlineSequences];
+ NumInlineSequences += NumConversions;
+ } else {
+ // Otherwise get memory from the allocator.
+ C.Conversions = ConversionSequenceAllocator
+ .Allocate<ImplicitConversionSequence>(NumConversions);
+ }
+
+ // Construct the new objects.
+ for (unsigned i = 0; i != NumConversions; ++i)
+ new (&C.Conversions[i]) ImplicitConversionSequence();
+
+ C.NumConversions = NumConversions;
+ return C;
+ }
+
+ /// 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,
+ ArrayRef<Expr *> Args,
+ StringRef Opc = "",
+ 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..8acf9e8
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Sema/Ownership.h
@@ -0,0 +1,287 @@
+//===--- 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 "clang/Basic/LLVM.h"
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/PointerIntPair.h"
+
+//===----------------------------------------------------------------------===//
+// OpaquePtr
+//===----------------------------------------------------------------------===//
+
+namespace clang {
+ class CXXCtorInitializer;
+ class CXXBaseSpecifier;
+ class Decl;
+ class Expr;
+ class ParsedTemplateArgument;
+ class QualType;
+ class Stmt;
+ class TemplateName;
+ class TemplateParameterList;
+
+ /// \brief Wrapper for void* pointer.
+ /// \tparam PtrTy Either a pointer type like 'T*' or a type that behaves like
+ /// a pointer.
+ ///
+ /// 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 PtrTy
+ /// 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(nullptr) {}
+
+ static OpaquePtr make(PtrTy P) { OpaquePtr OP; OP.set(P); return OP; }
+
+ /// \brief Returns plain pointer to the entity pointed by this wrapper.
+ /// \tparam PointeeT Type of pointed entity.
+ ///
+ /// It is identical to getPtrAs<PointeeT*>.
+ template <typename PointeeT> PointeeT* getPtrTo() const {
+ return get();
+ }
+
+ /// \brief Returns pointer converted to the specified type.
+ /// \tparam PtrT Result pointer type. There must be implicit conversion
+ /// from PtrTy to PtrT.
+ ///
+ /// In contrast to getPtrTo, this method allows the return type to be
+ /// a smart pointer.
+ template <typename PtrT> PtrT getPtrAs() const {
+ return get();
+ }
+
+ PtrTy get() const {
+ return Traits::getFromVoidPointer(Ptr);
+ }
+
+ void set(PtrTy P) {
+ Ptr = Traits::getAsVoidPointer(P);
+ }
+
+ explicit operator bool() const { return Ptr != nullptr; }
+
+ 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; };
+}
+
+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; }
+ bool isUnset() const { return !Invalid && !Val; }
+
+ PtrTy get() const { return Val; }
+ template <typename T> T *getAs() { 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; }
+ bool isUnset() const { return PtrWithInvalid == 0; }
+
+ PtrTy get() const {
+ void *VP = reinterpret_cast<void *>(PtrWithInvalid & ~0x01);
+ return PtrTraits::getFromVoidPointer(VP);
+ }
+ template <typename T> T *getAs() { 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;
+ }
+
+ // For types where we can fit a flag in with the pointer, provide
+ // conversions to/from pointer type.
+ static ActionResult getFromOpaquePointer(void *P) {
+ ActionResult Result;
+ Result.PtrWithInvalid = (uintptr_t)P;
+ return Result;
+ }
+ void *getAsOpaquePointer() const { return (void*)PtrWithInvalid; }
+ };
+
+ /// An opaque type for threading parsed type information through the
+ /// parser.
+ typedef OpaquePtr<QualType> ParsedType;
+ typedef UnionOpaquePtr<QualType> UnionParsedType;
+
+ // 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;
+ };
+
+ 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;
+
+ typedef MutableArrayRef<Expr*> MultiExprArg;
+ typedef MutableArrayRef<Stmt*> MultiStmtArg;
+ typedef MutableArrayRef<ParsedTemplateArgument> ASTTemplateArgsPtr;
+ typedef MutableArrayRef<ParsedType> MultiTypeArg;
+ typedef MutableArrayRef<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..b36425f
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Sema/ParsedTemplate.h
@@ -0,0 +1,214 @@
+//===--- 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(nullptr) { }
+
+ /// \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()),
+ SS(SS), Loc(TemplateLoc), EllipsisLoc() { }
+
+ /// \brief Determine whether the given template argument is invalid.
+ bool isInvalid() const { return Arg == nullptr; }
+
+ /// \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 Expr* (for an
+ /// expression), or an ActionBase::TemplateTy (for a template).
+ void *Arg;
+
+ /// \brief The nested-name-specifier that can accompany a template template
+ /// argument.
+ CXXScopeSpec SS;
+
+ /// \brief the location of the template argument.
+ SourceLocation Loc;
+
+ /// \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 {
+ /// \brief The nested-name-specifier that precedes the template name.
+ CXXScopeSpec SS;
+
+ /// TemplateKWLoc - The location of the template keyword within the
+ /// source.
+ SourceLocation TemplateKWLoc;
+
+ /// 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);
+ }
+
+ /// \brief Creates a new TemplateIdAnnotation with NumArgs arguments and
+ /// appends it to List.
+ static TemplateIdAnnotation *
+ Allocate(unsigned NumArgs, SmallVectorImpl<TemplateIdAnnotation*> &List) {
+ TemplateIdAnnotation *TemplateId
+ = (TemplateIdAnnotation *)std::malloc(sizeof(TemplateIdAnnotation) +
+ sizeof(ParsedTemplateArgument) * NumArgs);
+ TemplateId->NumArgs = NumArgs;
+
+ // Default-construct nested-name-specifier.
+ new (&TemplateId->SS) CXXScopeSpec();
+
+ // Default-construct parsed template arguments.
+ ParsedTemplateArgument *TemplateArgs = TemplateId->getTemplateArgs();
+ for (unsigned I = 0; I != NumArgs; ++I)
+ new (TemplateArgs + I) ParsedTemplateArgument();
+
+ List.push_back(TemplateId);
+ return TemplateId;
+ }
+
+ void Destroy() {
+ SS.~CXXScopeSpec();
+ free(this);
+ }
+ };
+
+ /// Retrieves the range of the given template parameter lists.
+ SourceRange getTemplateParamsRange(TemplateParameterList const *const *Params,
+ unsigned NumParams);
+}
+
+#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..ca22e64
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Sema/PrettyDeclStackTrace.h
@@ -0,0 +1,47 @@
+//===- 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_PRETTYDECLSTACKTRACE_H
+#define LLVM_CLANG_SEMA_PRETTYDECLSTACKTRACE_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) {}
+
+ void print(raw_ostream &OS) const override;
+};
+
+}
+
+#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..dfc6f9c
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Sema/Scope.h
@@ -0,0 +1,484 @@
+//===--- 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/PointerIntPair.h"
+#include "llvm/ADT/SmallPtrSet.h"
+#include "llvm/ADT/SmallVector.h"
+
+namespace llvm {
+
+class raw_ostream;
+
+}
+
+namespace clang {
+
+class Decl;
+class UsingDirectiveDecl;
+class VarDecl;
+
+/// 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 {
+ /// \brief This indicates that the scope corresponds to a function, which
+ /// means that labels are set here.
+ FnScope = 0x01,
+
+ /// \brief This is a while, do, switch, for, etc that can have break
+ /// statements embedded into it.
+ BreakScope = 0x02,
+
+ /// \brief This is a while, do, for, which can have continue statements
+ /// embedded into it.
+ ContinueScope = 0x04,
+
+ /// \brief This is a scope that can contain a declaration. Some scopes
+ /// just contain loop constructs but don't contain decls.
+ DeclScope = 0x08,
+
+ /// \brief The controlling scope in a if/switch/while/for statement.
+ ControlScope = 0x10,
+
+ /// \brief The scope of a struct/union/class definition.
+ ClassScope = 0x20,
+
+ /// \brief 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 and DeclScope flags set as well.
+ BlockScope = 0x40,
+
+ /// \brief 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,
+
+ /// \brief This is a scope that corresponds to the
+ /// parameters within a function prototype.
+ FunctionPrototypeScope = 0x100,
+
+ /// \brief This is a scope that corresponds to the parameters within
+ /// a function prototype for a function declaration (as opposed to any
+ /// other kind of function declarator). Always has FunctionPrototypeScope
+ /// set as well.
+ FunctionDeclarationScope = 0x200,
+
+ /// \brief This is a scope that corresponds to the Objective-C
+ /// \@catch statement.
+ AtCatchScope = 0x400,
+
+ /// \brief This scope corresponds to an Objective-C method body.
+ /// It always has FnScope and DeclScope set as well.
+ ObjCMethodScope = 0x800,
+
+ /// \brief This is a scope that corresponds to a switch statement.
+ SwitchScope = 0x1000,
+
+ /// \brief This is the scope of a C++ try statement.
+ TryScope = 0x2000,
+
+ /// \brief This is the scope for a function-level C++ try or catch scope.
+ FnTryCatchScope = 0x4000,
+
+ /// \brief This is the scope of OpenMP executable directive.
+ OpenMPDirectiveScope = 0x8000,
+
+ /// \brief This is the scope of some OpenMP loop directive.
+ OpenMPLoopDirectiveScope = 0x10000,
+
+ /// \brief This is the scope of some OpenMP simd directive.
+ /// For example, it is used for 'omp simd', 'omp for simd'.
+ /// This flag is propagated to children scopes.
+ OpenMPSimdDirectiveScope = 0x20000,
+
+ /// This scope corresponds to an enum.
+ EnumScope = 0x40000,
+
+ /// This scope corresponds to an SEH try.
+ SEHTryScope = 0x80000,
+
+ /// This scope corresponds to an SEH except.
+ SEHExceptScope = 0x100000,
+
+ /// We are currently in the filter expression of an SEH except block.
+ SEHFilterScope = 0x200000,
+ };
+private:
+ /// The parent scope for this scope. This is null for the translation-unit
+ /// scope.
+ Scope *AnyParent;
+
+ /// Flags - This contains a set of ScopeFlags, which indicates how the scope
+ /// interrelates with other control flow statements.
+ unsigned Flags;
+
+ /// Depth - This is the depth of this scope. The translation-unit scope has
+ /// depth 0.
+ unsigned short Depth;
+
+ /// \brief Declarations with static linkage are mangled with the number of
+ /// scopes seen as a component.
+ unsigned short MSLastManglingNumber;
+
+ unsigned short MSCurManglingNumber;
+
+ /// PrototypeDepth - This is the number of function prototype scopes
+ /// enclosing this scope, including this scope.
+ unsigned short PrototypeDepth;
+
+ /// PrototypeIndex - This is the number of parameters currently
+ /// declared in this scope.
+ unsigned short PrototypeIndex;
+
+ /// 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;
+ Scope *MSLastManglingParent;
+
+ /// BreakParent/ContinueParent - This is a direct link to the innermost
+ /// BreakScope/ContinueScope which contains the contents of this scope
+ /// for control flow purposes (and might be this scope itself), or null
+ /// if there is no such scope.
+ Scope *BreakParent, *ContinueParent;
+
+ /// 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;
+
+ /// The DeclContext 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.
+ DeclContext *Entity;
+
+ typedef SmallVector<UsingDirectiveDecl *, 2> UsingDirectivesTy;
+ UsingDirectivesTy UsingDirectives;
+
+ /// \brief Used to determine if errors occurred in this scope.
+ DiagnosticErrorTrap ErrorTrap;
+
+ /// A lattice consisting of undefined, a single NRVO candidate variable in
+ /// this scope, or over-defined. The bit is true when over-defined.
+ llvm::PointerIntPair<VarDecl *, 1, bool> NRVO;
+
+public:
+ Scope(Scope *Parent, unsigned ScopeFlags, DiagnosticsEngine &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; }
+
+ const Scope *getMSLastManglingParent() const {
+ return MSLastManglingParent;
+ }
+ Scope *getMSLastManglingParent() { return MSLastManglingParent; }
+
+ /// getContinueParent - Return the closest scope that a continue statement
+ /// would be affected by.
+ Scope *getContinueParent() {
+ return ContinueParent;
+ }
+
+ const Scope *getContinueParent() const {
+ return const_cast<Scope*>(this)->getContinueParent();
+ }
+
+ /// getBreakParent - Return the closest scope that a break statement
+ /// would be affected by.
+ Scope *getBreakParent() {
+ return BreakParent;
+ }
+ const Scope *getBreakParent() const {
+ return const_cast<Scope*>(this)->getBreakParent();
+ }
+
+ Scope *getBlockParent() { return BlockParent; }
+ const Scope *getBlockParent() const { return BlockParent; }
+
+ Scope *getTemplateParamParent() { return TemplateParamParent; }
+ const Scope *getTemplateParamParent() const { return TemplateParamParent; }
+
+ /// Returns the number of function prototype scopes in this scope
+ /// chain.
+ unsigned getFunctionPrototypeDepth() const {
+ return PrototypeDepth;
+ }
+
+ /// Return the number of parameters declared in this function
+ /// prototype, increasing it by one for the next call.
+ unsigned getNextFunctionPrototypeIndex() {
+ assert(isFunctionPrototypeScope());
+ return PrototypeIndex++;
+ }
+
+ typedef llvm::iterator_range<DeclSetTy::iterator> decl_range;
+ decl_range decls() const {
+ return decl_range(DeclsInScope.begin(), DeclsInScope.end());
+ }
+ bool decl_empty() const { return DeclsInScope.empty(); }
+
+ void AddDecl(Decl *D) {
+ DeclsInScope.insert(D);
+ }
+
+ void RemoveDecl(Decl *D) {
+ DeclsInScope.erase(D);
+ }
+
+ void incrementMSManglingNumber() {
+ if (Scope *MSLMP = getMSLastManglingParent()) {
+ MSLMP->MSLastManglingNumber += 1;
+ MSCurManglingNumber += 1;
+ }
+ }
+
+ void decrementMSManglingNumber() {
+ if (Scope *MSLMP = getMSLastManglingParent()) {
+ MSLMP->MSLastManglingNumber -= 1;
+ MSCurManglingNumber -= 1;
+ }
+ }
+
+ unsigned getMSLastManglingNumber() const {
+ if (const Scope *MSLMP = getMSLastManglingParent())
+ return MSLMP->MSLastManglingNumber;
+ return 1;
+ }
+
+ unsigned getMSCurManglingNumber() const {
+ return MSCurManglingNumber;
+ }
+
+ /// isDeclScope - Return true if this is the scope that the specified decl is
+ /// declared in.
+ bool isDeclScope(Decl *D) {
+ return DeclsInScope.count(D) != 0;
+ }
+
+ DeclContext *getEntity() const { return Entity; }
+ void setEntity(DeclContext *E) { Entity = E; }
+
+ bool hasErrorOccurred() const { return ErrorTrap.hasErrorOccurred(); }
+
+ bool hasUnrecoverableErrorOccurred() const {
+ return ErrorTrap.hasUnrecoverableErrorOccurred();
+ }
+
+ /// isFunctionScope() - Return true if this scope is a function scope.
+ bool isFunctionScope() const { return (getFlags() & Scope::FnScope); }
+
+ /// 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;
+ }
+
+ /// isInObjcMethodOuterScope - Return true if this scope is an
+ /// Objective-C method outer most body.
+ bool isInObjcMethodOuterScope() const {
+ if (const Scope *S = this) {
+ // 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;
+ }
+
+ /// isSwitchScope - Return true if this scope is a switch scope.
+ bool isSwitchScope() const {
+ for (const Scope *S = this; S; S = S->getParent()) {
+ if (S->getFlags() & Scope::SwitchScope)
+ return true;
+ else if (S->getFlags() & (Scope::FnScope | Scope::ClassScope |
+ Scope::BlockScope | Scope::TemplateParamScope |
+ Scope::FunctionPrototypeScope |
+ Scope::AtCatchScope | Scope::ObjCMethodScope))
+ return false;
+ }
+ return false;
+ }
+
+ /// \brief Determines whether this scope is the OpenMP directive scope
+ bool isOpenMPDirectiveScope() const {
+ return (getFlags() & Scope::OpenMPDirectiveScope);
+ }
+
+ /// \brief Determine whether this scope is some OpenMP loop directive scope
+ /// (for example, 'omp for', 'omp simd').
+ bool isOpenMPLoopDirectiveScope() const {
+ if (getFlags() & Scope::OpenMPLoopDirectiveScope) {
+ assert(isOpenMPDirectiveScope() &&
+ "OpenMP loop directive scope is not a directive scope");
+ return true;
+ }
+ return false;
+ }
+
+ /// \brief Determine whether this scope is (or is nested into) some OpenMP
+ /// loop simd directive scope (for example, 'omp simd', 'omp for simd').
+ bool isOpenMPSimdDirectiveScope() const {
+ return getFlags() & Scope::OpenMPSimdDirectiveScope;
+ }
+
+ /// \brief Determine whether this scope is a loop having OpenMP loop
+ /// directive attached.
+ bool isOpenMPLoopScope() const {
+ const Scope *P = getParent();
+ return P && P->isOpenMPLoopDirectiveScope();
+ }
+
+ /// \brief Determine whether this scope is a C++ 'try' block.
+ bool isTryScope() const { return getFlags() & Scope::TryScope; }
+
+ /// \brief Determine whether this scope is a SEH '__try' block.
+ bool isSEHTryScope() const { return getFlags() & Scope::SEHTryScope; }
+
+ /// \brief Determine whether this scope is a SEH '__except' block.
+ bool isSEHExceptScope() const { return getFlags() & Scope::SEHExceptScope; }
+
+ /// \brief Returns if rhs has a higher scope depth than this.
+ ///
+ /// The caller is responsible for calling this only if one of the two scopes
+ /// is an ancestor of the other.
+ bool Contains(const Scope& rhs) const { return Depth < rhs.Depth; }
+
+ /// containedInPrototypeScope - Return true if this or a parent scope
+ /// is a FunctionPrototypeScope.
+ bool containedInPrototypeScope() const;
+
+ void PushUsingDirective(UsingDirectiveDecl *UDir) {
+ UsingDirectives.push_back(UDir);
+ }
+
+ typedef llvm::iterator_range<UsingDirectivesTy::iterator>
+ using_directives_range;
+
+ using_directives_range using_directives() {
+ return using_directives_range(UsingDirectives.begin(),
+ UsingDirectives.end());
+ }
+
+ void addNRVOCandidate(VarDecl *VD) {
+ if (NRVO.getInt())
+ return;
+ if (NRVO.getPointer() == nullptr) {
+ NRVO.setPointer(VD);
+ return;
+ }
+ if (NRVO.getPointer() != VD)
+ setNoNRVO();
+ }
+
+ void setNoNRVO() {
+ NRVO.setInt(1);
+ NRVO.setPointer(nullptr);
+ }
+
+ void mergeNRVOIntoParent();
+
+ /// Init - This is used by the parser to implement scope caching.
+ ///
+ void Init(Scope *parent, unsigned flags);
+
+ /// \brief Sets up the specified scope flags and adjusts the scope state
+ /// variables accordingly.
+ ///
+ void AddFlags(unsigned Flags);
+
+ void dumpImpl(raw_ostream &OS) const;
+ void dump() const;
+};
+
+} // 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..d13667e
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Sema/ScopeInfo.h
@@ -0,0 +1,858 @@
+//===--- 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 its subclasses, which contain
+// information about a single function, block, lambda, or method body.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_SEMA_SCOPEINFO_H
+#define LLVM_CLANG_SEMA_SCOPEINFO_H
+
+#include "clang/AST/Expr.h"
+#include "clang/AST/Type.h"
+#include "clang/Basic/CapturedStmt.h"
+#include "clang/Basic/PartialDiagnostic.h"
+#include "clang/Sema/Ownership.h"
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/SmallSet.h"
+#include "llvm/ADT/SmallVector.h"
+#include <algorithm>
+
+namespace clang {
+
+class Decl;
+class BlockDecl;
+class CapturedDecl;
+class CXXMethodDecl;
+class FieldDecl;
+class ObjCPropertyDecl;
+class IdentifierInfo;
+class ImplicitParamDecl;
+class LabelDecl;
+class ReturnStmt;
+class Scope;
+class SwitchStmt;
+class TemplateTypeParmDecl;
+class TemplateParameterList;
+class VarDecl;
+class ObjCIvarRefExpr;
+class ObjCPropertyRefExpr;
+class ObjCMessageExpr;
+
+namespace sema {
+
+/// \brief Contains information about the compound statement currently being
+/// parsed.
+class CompoundScopeInfo {
+public:
+ CompoundScopeInfo()
+ : HasEmptyLoopBodies(false) { }
+
+ /// \brief Whether this compound stamement contains `for' or `while' loops
+ /// with empty bodies.
+ bool HasEmptyLoopBodies;
+
+ void setHasEmptyLoopBodies() {
+ HasEmptyLoopBodies = true;
+ }
+};
+
+class PossiblyUnreachableDiag {
+public:
+ PartialDiagnostic PD;
+ SourceLocation Loc;
+ const Stmt *stmt;
+
+ PossiblyUnreachableDiag(const PartialDiagnostic &PD, SourceLocation Loc,
+ const Stmt *stmt)
+ : PD(PD), Loc(Loc), stmt(stmt) {}
+};
+
+/// \brief Retains information about a function, method, or block that is
+/// currently being parsed.
+class FunctionScopeInfo {
+protected:
+ enum ScopeKind {
+ SK_Function,
+ SK_Block,
+ SK_Lambda,
+ SK_CapturedRegion
+ };
+
+public:
+ /// \brief What kind of scope we are describing.
+ ///
+ ScopeKind Kind : 3;
+
+ /// \brief Whether this function contains a VLA, \@try, try, C++
+ /// initializer, or anything else that can't be jumped past.
+ bool HasBranchProtectedScope : 1;
+
+ /// \brief Whether this function contains any switches or direct gotos.
+ bool HasBranchIntoScope : 1;
+
+ /// \brief Whether this function contains any indirect gotos.
+ bool HasIndirectGoto : 1;
+
+ /// \brief Whether a statement was dropped because it was invalid.
+ bool HasDroppedStmt : 1;
+
+ /// A flag that is set when parsing a method that must call super's
+ /// implementation, such as \c -dealloc, \c -finalize, or any method marked
+ /// with \c __attribute__((objc_requires_super)).
+ bool ObjCShouldCallSuper : 1;
+
+ /// True when this is a method marked as a designated initializer.
+ bool ObjCIsDesignatedInit : 1;
+ /// This starts true for a method marked as designated initializer and will
+ /// be set to false if there is an invocation to a designated initializer of
+ /// the super class.
+ bool ObjCWarnForNoDesignatedInitChain : 1;
+
+ /// True when this is an initializer method not marked as a designated
+ /// initializer within a class that has at least one initializer marked as a
+ /// designated initializer.
+ bool ObjCIsSecondaryInit : 1;
+ /// This starts true for a secondary initializer method and will be set to
+ /// false if there is an invocation of an initializer on 'self'.
+ bool ObjCWarnForNoInitDelegation : 1;
+
+ /// First 'return' statement in the current function.
+ SourceLocation FirstReturnLoc;
+
+ /// First C++ 'try' statement in the current function.
+ SourceLocation FirstCXXTryLoc;
+
+ /// First SEH '__try' statement in the current function.
+ SourceLocation FirstSEHTryLoc;
+
+ /// \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.
+ 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, or if we need to infer a return type.
+ SmallVector<ReturnStmt*, 4> Returns;
+
+ /// \brief The promise object for this coroutine, if any.
+ VarDecl *CoroutinePromise;
+
+ /// \brief The list of coroutine control flow constructs (co_await, co_yield,
+ /// co_return) that occur within the function or block. Empty if and only if
+ /// this function or block is not (yet known to be) a coroutine.
+ SmallVector<Stmt*, 4> CoroutineStmts;
+
+ /// \brief The stack of currently active compound stamement scopes in the
+ /// function.
+ SmallVector<CompoundScopeInfo, 4> CompoundScopes;
+
+ /// \brief A list of PartialDiagnostics created but delayed within the
+ /// current function scope. These diagnostics are vetted for reachability
+ /// prior to being emitted.
+ SmallVector<PossiblyUnreachableDiag, 4> PossiblyUnreachableDiags;
+
+ /// \brief A list of parameters which have the nonnull attribute and are
+ /// modified in the function.
+ llvm::SmallPtrSet<const ParmVarDecl*, 8> ModifiedNonNullParams;
+
+public:
+ /// Represents a simple identification of a weak object.
+ ///
+ /// Part of the implementation of -Wrepeated-use-of-weak.
+ ///
+ /// This is used to determine if two weak accesses refer to the same object.
+ /// Here are some examples of how various accesses are "profiled":
+ ///
+ /// Access Expression | "Base" Decl | "Property" Decl
+ /// :---------------: | :-----------------: | :------------------------------:
+ /// self.property | self (VarDecl) | property (ObjCPropertyDecl)
+ /// self.implicitProp | self (VarDecl) | -implicitProp (ObjCMethodDecl)
+ /// self->ivar.prop | ivar (ObjCIvarDecl) | prop (ObjCPropertyDecl)
+ /// cxxObj.obj.prop | obj (FieldDecl) | prop (ObjCPropertyDecl)
+ /// [self foo].prop | 0 (unknown) | prop (ObjCPropertyDecl)
+ /// self.prop1.prop2 | prop1 (ObjCPropertyDecl) | prop2 (ObjCPropertyDecl)
+ /// MyClass.prop | MyClass (ObjCInterfaceDecl) | -prop (ObjCMethodDecl)
+ /// weakVar | 0 (known) | weakVar (VarDecl)
+ /// self->weakIvar | self (VarDecl) | weakIvar (ObjCIvarDecl)
+ ///
+ /// Objects are identified with only two Decls to make it reasonably fast to
+ /// compare them.
+ class WeakObjectProfileTy {
+ /// The base object decl, as described in the class documentation.
+ ///
+ /// The extra flag is "true" if the Base and Property are enough to uniquely
+ /// identify the object in memory.
+ ///
+ /// \sa isExactProfile()
+ typedef llvm::PointerIntPair<const NamedDecl *, 1, bool> BaseInfoTy;
+ BaseInfoTy Base;
+
+ /// The "property" decl, as described in the class documentation.
+ ///
+ /// Note that this may not actually be an ObjCPropertyDecl, e.g. in the
+ /// case of "implicit" properties (regular methods accessed via dot syntax).
+ const NamedDecl *Property;
+
+ /// Used to find the proper base profile for a given base expression.
+ static BaseInfoTy getBaseInfo(const Expr *BaseE);
+
+ inline WeakObjectProfileTy();
+ static inline WeakObjectProfileTy getSentinel();
+
+ public:
+ WeakObjectProfileTy(const ObjCPropertyRefExpr *RE);
+ WeakObjectProfileTy(const Expr *Base, const ObjCPropertyDecl *Property);
+ WeakObjectProfileTy(const DeclRefExpr *RE);
+ WeakObjectProfileTy(const ObjCIvarRefExpr *RE);
+
+ const NamedDecl *getBase() const { return Base.getPointer(); }
+ const NamedDecl *getProperty() const { return Property; }
+
+ /// Returns true if the object base specifies a known object in memory,
+ /// rather than, say, an instance variable or property of another object.
+ ///
+ /// Note that this ignores the effects of aliasing; that is, \c foo.bar is
+ /// considered an exact profile if \c foo is a local variable, even if
+ /// another variable \c foo2 refers to the same object as \c foo.
+ ///
+ /// For increased precision, accesses with base variables that are
+ /// properties or ivars of 'self' (e.g. self.prop1.prop2) are considered to
+ /// be exact, though this is not true for arbitrary variables
+ /// (foo.prop1.prop2).
+ bool isExactProfile() const {
+ return Base.getInt();
+ }
+
+ bool operator==(const WeakObjectProfileTy &Other) const {
+ return Base == Other.Base && Property == Other.Property;
+ }
+
+ // For use in DenseMap.
+ // We can't specialize the usual llvm::DenseMapInfo at the end of the file
+ // because by that point the DenseMap in FunctionScopeInfo has already been
+ // instantiated.
+ class DenseMapInfo {
+ public:
+ static inline WeakObjectProfileTy getEmptyKey() {
+ return WeakObjectProfileTy();
+ }
+ static inline WeakObjectProfileTy getTombstoneKey() {
+ return WeakObjectProfileTy::getSentinel();
+ }
+
+ static unsigned getHashValue(const WeakObjectProfileTy &Val) {
+ typedef std::pair<BaseInfoTy, const NamedDecl *> Pair;
+ return llvm::DenseMapInfo<Pair>::getHashValue(Pair(Val.Base,
+ Val.Property));
+ }
+
+ static bool isEqual(const WeakObjectProfileTy &LHS,
+ const WeakObjectProfileTy &RHS) {
+ return LHS == RHS;
+ }
+ };
+ };
+
+ /// Represents a single use of a weak object.
+ ///
+ /// Stores both the expression and whether the access is potentially unsafe
+ /// (i.e. it could potentially be warned about).
+ ///
+ /// Part of the implementation of -Wrepeated-use-of-weak.
+ class WeakUseTy {
+ llvm::PointerIntPair<const Expr *, 1, bool> Rep;
+ public:
+ WeakUseTy(const Expr *Use, bool IsRead) : Rep(Use, IsRead) {}
+
+ const Expr *getUseExpr() const { return Rep.getPointer(); }
+ bool isUnsafe() const { return Rep.getInt(); }
+ void markSafe() { Rep.setInt(false); }
+
+ bool operator==(const WeakUseTy &Other) const {
+ return Rep == Other.Rep;
+ }
+ };
+
+ /// Used to collect uses of a particular weak object in a function body.
+ ///
+ /// Part of the implementation of -Wrepeated-use-of-weak.
+ typedef SmallVector<WeakUseTy, 4> WeakUseVector;
+
+ /// Used to collect all uses of weak objects in a function body.
+ ///
+ /// Part of the implementation of -Wrepeated-use-of-weak.
+ typedef llvm::SmallDenseMap<WeakObjectProfileTy, WeakUseVector, 8,
+ WeakObjectProfileTy::DenseMapInfo>
+ WeakObjectUseMap;
+
+private:
+ /// Used to collect all uses of weak objects in this function body.
+ ///
+ /// Part of the implementation of -Wrepeated-use-of-weak.
+ WeakObjectUseMap WeakObjectUses;
+
+protected:
+ FunctionScopeInfo(const FunctionScopeInfo&) = default;
+
+public:
+ /// Record that a weak object was accessed.
+ ///
+ /// Part of the implementation of -Wrepeated-use-of-weak.
+ template <typename ExprT>
+ inline void recordUseOfWeak(const ExprT *E, bool IsRead = true);
+
+ void recordUseOfWeak(const ObjCMessageExpr *Msg,
+ const ObjCPropertyDecl *Prop);
+
+ /// Record that a given expression is a "safe" access of a weak object (e.g.
+ /// assigning it to a strong variable.)
+ ///
+ /// Part of the implementation of -Wrepeated-use-of-weak.
+ void markSafeWeakUse(const Expr *E);
+
+ const WeakObjectUseMap &getWeakObjectUses() const {
+ return WeakObjectUses;
+ }
+
+ void setHasBranchIntoScope() {
+ HasBranchIntoScope = true;
+ }
+
+ void setHasBranchProtectedScope() {
+ HasBranchProtectedScope = true;
+ }
+
+ void setHasIndirectGoto() {
+ HasIndirectGoto = true;
+ }
+
+ void setHasDroppedStmt() {
+ HasDroppedStmt = true;
+ }
+
+ void setHasCXXTry(SourceLocation TryLoc) {
+ setHasBranchProtectedScope();
+ FirstCXXTryLoc = TryLoc;
+ }
+
+ void setHasSEHTry(SourceLocation TryLoc) {
+ setHasBranchProtectedScope();
+ FirstSEHTryLoc = TryLoc;
+ }
+
+ bool NeedsScopeChecking() const {
+ return !HasDroppedStmt &&
+ (HasIndirectGoto ||
+ (HasBranchProtectedScope && HasBranchIntoScope));
+ }
+
+ FunctionScopeInfo(DiagnosticsEngine &Diag)
+ : Kind(SK_Function),
+ HasBranchProtectedScope(false),
+ HasBranchIntoScope(false),
+ HasIndirectGoto(false),
+ HasDroppedStmt(false),
+ ObjCShouldCallSuper(false),
+ ObjCIsDesignatedInit(false),
+ ObjCWarnForNoDesignatedInitChain(false),
+ ObjCIsSecondaryInit(false),
+ ObjCWarnForNoInitDelegation(false),
+ ErrorTrap(Diag) { }
+
+ virtual ~FunctionScopeInfo();
+
+ /// \brief Clear out the information in this function scope, making it
+ /// suitable for reuse.
+ void Clear();
+};
+
+class CapturingScopeInfo : public FunctionScopeInfo {
+protected:
+ CapturingScopeInfo(const CapturingScopeInfo&) = default;
+
+public:
+ enum ImplicitCaptureStyle {
+ ImpCap_None, ImpCap_LambdaByval, ImpCap_LambdaByref, ImpCap_Block,
+ ImpCap_CapturedRegion
+ };
+
+ ImplicitCaptureStyle ImpCaptureStyle;
+
+ class Capture {
+ // There are three categories of capture: capturing 'this', capturing
+ // local variables, and C++1y initialized captures (which can have an
+ // arbitrary initializer, and don't really capture in the traditional
+ // sense at all).
+ //
+ // There are three ways to capture a local variable:
+ // - capture by copy in the C++11 sense,
+ // - capture by reference in the C++11 sense, and
+ // - __block capture.
+ // Lambdas explicitly specify capture by copy or capture by reference.
+ // For blocks, __block capture applies to variables with that annotation,
+ // variables of reference type are captured by reference, and other
+ // variables are captured by copy.
+ enum CaptureKind {
+ Cap_ByCopy, Cap_ByRef, Cap_Block, Cap_This
+ };
+
+ /// The variable being captured (if we are not capturing 'this') and whether
+ /// this is a nested capture.
+ llvm::PointerIntPair<VarDecl*, 1, bool> VarAndNested;
+
+ /// Expression to initialize a field of the given type, and the kind of
+ /// capture (if this is a capture and not an init-capture). The expression
+ /// is only required if we are capturing ByVal and the variable's type has
+ /// a non-trivial copy constructor.
+ llvm::PointerIntPair<void *, 2, CaptureKind> InitExprAndCaptureKind;
+
+ /// \brief The source location at which the first capture occurred.
+ SourceLocation Loc;
+
+ /// \brief The location of the ellipsis that expands a parameter pack.
+ SourceLocation EllipsisLoc;
+
+ /// \brief The type as it was captured, which is in effect the type of the
+ /// non-static data member that would hold the capture.
+ QualType CaptureType;
+
+ public:
+ Capture(VarDecl *Var, bool Block, bool ByRef, bool IsNested,
+ SourceLocation Loc, SourceLocation EllipsisLoc,
+ QualType CaptureType, Expr *Cpy)
+ : VarAndNested(Var, IsNested),
+ InitExprAndCaptureKind(Cpy, Block ? Cap_Block :
+ ByRef ? Cap_ByRef : Cap_ByCopy),
+ Loc(Loc), EllipsisLoc(EllipsisLoc), CaptureType(CaptureType) {}
+
+ enum IsThisCapture { ThisCapture };
+ Capture(IsThisCapture, bool IsNested, SourceLocation Loc,
+ QualType CaptureType, Expr *Cpy)
+ : VarAndNested(nullptr, IsNested),
+ InitExprAndCaptureKind(Cpy, Cap_This),
+ Loc(Loc), EllipsisLoc(), CaptureType(CaptureType) {}
+
+ bool isThisCapture() const {
+ return InitExprAndCaptureKind.getInt() == Cap_This;
+ }
+ bool isVariableCapture() const {
+ return InitExprAndCaptureKind.getInt() != Cap_This && !isVLATypeCapture();
+ }
+ bool isCopyCapture() const {
+ return InitExprAndCaptureKind.getInt() == Cap_ByCopy &&
+ !isVLATypeCapture();
+ }
+ bool isReferenceCapture() const {
+ return InitExprAndCaptureKind.getInt() == Cap_ByRef;
+ }
+ bool isBlockCapture() const {
+ return InitExprAndCaptureKind.getInt() == Cap_Block;
+ }
+ bool isVLATypeCapture() const {
+ return InitExprAndCaptureKind.getInt() == Cap_ByCopy &&
+ getVariable() == nullptr;
+ }
+ bool isNested() const { return VarAndNested.getInt(); }
+
+ VarDecl *getVariable() const {
+ return VarAndNested.getPointer();
+ }
+
+ /// \brief Retrieve the location at which this variable was captured.
+ SourceLocation getLocation() const { return Loc; }
+
+ /// \brief Retrieve the source location of the ellipsis, whose presence
+ /// indicates that the capture is a pack expansion.
+ SourceLocation getEllipsisLoc() const { return EllipsisLoc; }
+
+ /// \brief Retrieve the capture type for this capture, which is effectively
+ /// the type of the non-static data member in the lambda/block structure
+ /// that would store this capture.
+ QualType getCaptureType() const { return CaptureType; }
+
+ Expr *getInitExpr() const {
+ assert(!isVLATypeCapture() && "no init expression for type capture");
+ return static_cast<Expr *>(InitExprAndCaptureKind.getPointer());
+ }
+ };
+
+ CapturingScopeInfo(DiagnosticsEngine &Diag, ImplicitCaptureStyle Style)
+ : FunctionScopeInfo(Diag), ImpCaptureStyle(Style), CXXThisCaptureIndex(0),
+ HasImplicitReturnType(false)
+ {}
+
+ /// CaptureMap - A map of captured variables to (index+1) into Captures.
+ llvm::DenseMap<VarDecl*, unsigned> CaptureMap;
+
+ /// CXXThisCaptureIndex - The (index+1) of the capture of 'this';
+ /// zero if 'this' is not captured.
+ unsigned CXXThisCaptureIndex;
+
+ /// Captures - The captures.
+ SmallVector<Capture, 4> Captures;
+
+ /// \brief - Whether the target type of return statements in this context
+ /// is deduced (e.g. a lambda or block with omitted return type).
+ bool HasImplicitReturnType;
+
+ /// ReturnType - The target type of return statements in this context,
+ /// or null if unknown.
+ QualType ReturnType;
+
+ void addCapture(VarDecl *Var, bool isBlock, bool isByref, bool isNested,
+ SourceLocation Loc, SourceLocation EllipsisLoc,
+ QualType CaptureType, Expr *Cpy) {
+ Captures.push_back(Capture(Var, isBlock, isByref, isNested, Loc,
+ EllipsisLoc, CaptureType, Cpy));
+ CaptureMap[Var] = Captures.size();
+ }
+
+ void addVLATypeCapture(SourceLocation Loc, QualType CaptureType) {
+ Captures.push_back(Capture(/*Var*/ nullptr, /*isBlock*/ false,
+ /*isByref*/ false, /*isNested*/ false, Loc,
+ /*EllipsisLoc*/ SourceLocation(), CaptureType,
+ /*Cpy*/ nullptr));
+ }
+
+ void addThisCapture(bool isNested, SourceLocation Loc, QualType CaptureType,
+ Expr *Cpy);
+
+ /// \brief Determine whether the C++ 'this' is captured.
+ bool isCXXThisCaptured() const { return CXXThisCaptureIndex != 0; }
+
+ /// \brief Retrieve the capture of C++ 'this', if it has been captured.
+ Capture &getCXXThisCapture() {
+ assert(isCXXThisCaptured() && "this has not been captured");
+ return Captures[CXXThisCaptureIndex - 1];
+ }
+
+ /// \brief Determine whether the given variable has been captured.
+ bool isCaptured(VarDecl *Var) const {
+ return CaptureMap.count(Var);
+ }
+
+ /// \brief Determine whether the given variable-array type has been captured.
+ bool isVLATypeCaptured(const VariableArrayType *VAT) const;
+
+ /// \brief Retrieve the capture of the given variable, if it has been
+ /// captured already.
+ Capture &getCapture(VarDecl *Var) {
+ assert(isCaptured(Var) && "Variable has not been captured");
+ return Captures[CaptureMap[Var] - 1];
+ }
+
+ const Capture &getCapture(VarDecl *Var) const {
+ llvm::DenseMap<VarDecl*, unsigned>::const_iterator Known
+ = CaptureMap.find(Var);
+ assert(Known != CaptureMap.end() && "Variable has not been captured");
+ return Captures[Known->second - 1];
+ }
+
+ static bool classof(const FunctionScopeInfo *FSI) {
+ return FSI->Kind == SK_Block || FSI->Kind == SK_Lambda
+ || FSI->Kind == SK_CapturedRegion;
+ }
+};
+
+/// \brief Retains information about a block that is currently being parsed.
+class BlockScopeInfo final : public CapturingScopeInfo {
+public:
+ BlockDecl *TheDecl;
+
+ /// TheScope - This is the scope for the block itself, which contains
+ /// arguments etc.
+ Scope *TheScope;
+
+ /// BlockType - The function type of the block, if one was given.
+ /// Its return type may be BuiltinType::Dependent.
+ QualType FunctionType;
+
+ BlockScopeInfo(DiagnosticsEngine &Diag, Scope *BlockScope, BlockDecl *Block)
+ : CapturingScopeInfo(Diag, ImpCap_Block), TheDecl(Block),
+ TheScope(BlockScope)
+ {
+ Kind = SK_Block;
+ }
+
+ ~BlockScopeInfo() override;
+
+ static bool classof(const FunctionScopeInfo *FSI) {
+ return FSI->Kind == SK_Block;
+ }
+};
+
+/// \brief Retains information about a captured region.
+class CapturedRegionScopeInfo final : public CapturingScopeInfo {
+public:
+ /// \brief The CapturedDecl for this statement.
+ CapturedDecl *TheCapturedDecl;
+ /// \brief The captured record type.
+ RecordDecl *TheRecordDecl;
+ /// \brief This is the enclosing scope of the captured region.
+ Scope *TheScope;
+ /// \brief The implicit parameter for the captured variables.
+ ImplicitParamDecl *ContextParam;
+ /// \brief The kind of captured region.
+ CapturedRegionKind CapRegionKind;
+
+ CapturedRegionScopeInfo(DiagnosticsEngine &Diag, Scope *S, CapturedDecl *CD,
+ RecordDecl *RD, ImplicitParamDecl *Context,
+ CapturedRegionKind K)
+ : CapturingScopeInfo(Diag, ImpCap_CapturedRegion),
+ TheCapturedDecl(CD), TheRecordDecl(RD), TheScope(S),
+ ContextParam(Context), CapRegionKind(K)
+ {
+ Kind = SK_CapturedRegion;
+ }
+
+ ~CapturedRegionScopeInfo() override;
+
+ /// \brief A descriptive name for the kind of captured region this is.
+ StringRef getRegionName() const {
+ switch (CapRegionKind) {
+ case CR_Default:
+ return "default captured statement";
+ case CR_OpenMP:
+ return "OpenMP region";
+ }
+ llvm_unreachable("Invalid captured region kind!");
+ }
+
+ static bool classof(const FunctionScopeInfo *FSI) {
+ return FSI->Kind == SK_CapturedRegion;
+ }
+};
+
+class LambdaScopeInfo final : public CapturingScopeInfo {
+public:
+ /// \brief The class that describes the lambda.
+ CXXRecordDecl *Lambda;
+
+ /// \brief The lambda's compiler-generated \c operator().
+ CXXMethodDecl *CallOperator;
+
+ /// \brief Source range covering the lambda introducer [...].
+ SourceRange IntroducerRange;
+
+ /// \brief Source location of the '&' or '=' specifying the default capture
+ /// type, if any.
+ SourceLocation CaptureDefaultLoc;
+
+ /// \brief The number of captures in the \c Captures list that are
+ /// explicit captures.
+ unsigned NumExplicitCaptures;
+
+ /// \brief Whether this is a mutable lambda.
+ bool Mutable;
+
+ /// \brief Whether the (empty) parameter list is explicit.
+ bool ExplicitParams;
+
+ /// \brief Whether any of the capture expressions requires cleanups.
+ bool ExprNeedsCleanups;
+
+ /// \brief Whether the lambda contains an unexpanded parameter pack.
+ bool ContainsUnexpandedParameterPack;
+
+ /// \brief If this is a generic lambda, use this as the depth of
+ /// each 'auto' parameter, during initial AST construction.
+ unsigned AutoTemplateParameterDepth;
+
+ /// \brief Store the list of the auto parameters for a generic lambda.
+ /// If this is a generic lambda, store the list of the auto
+ /// parameters converted into TemplateTypeParmDecls into a vector
+ /// that can be used to construct the generic lambda's template
+ /// parameter list, during initial AST construction.
+ SmallVector<TemplateTypeParmDecl*, 4> AutoTemplateParams;
+
+ /// If this is a generic lambda, and the template parameter
+ /// list has been created (from the AutoTemplateParams) then
+ /// store a reference to it (cache it to avoid reconstructing it).
+ TemplateParameterList *GLTemplateParameterList;
+
+ /// \brief Contains all variable-referring-expressions (i.e. DeclRefExprs
+ /// or MemberExprs) that refer to local variables in a generic lambda
+ /// or a lambda in a potentially-evaluated-if-used context.
+ ///
+ /// Potentially capturable variables of a nested lambda that might need
+ /// to be captured by the lambda are housed here.
+ /// This is specifically useful for generic lambdas or
+ /// lambdas within a a potentially evaluated-if-used context.
+ /// If an enclosing variable is named in an expression of a lambda nested
+ /// within a generic lambda, we don't always know know whether the variable
+ /// will truly be odr-used (i.e. need to be captured) by that nested lambda,
+ /// until its instantiation. But we still need to capture it in the
+ /// enclosing lambda if all intervening lambdas can capture the variable.
+
+ llvm::SmallVector<Expr*, 4> PotentiallyCapturingExprs;
+
+ /// \brief Contains all variable-referring-expressions that refer
+ /// to local variables that are usable as constant expressions and
+ /// do not involve an odr-use (they may still need to be captured
+ /// if the enclosing full-expression is instantiation dependent).
+ llvm::SmallSet<Expr*, 8> NonODRUsedCapturingExprs;
+
+ SourceLocation PotentialThisCaptureLocation;
+
+ LambdaScopeInfo(DiagnosticsEngine &Diag)
+ : CapturingScopeInfo(Diag, ImpCap_None), Lambda(nullptr),
+ CallOperator(nullptr), NumExplicitCaptures(0), Mutable(false),
+ ExplicitParams(false), ExprNeedsCleanups(false),
+ ContainsUnexpandedParameterPack(false), AutoTemplateParameterDepth(0),
+ GLTemplateParameterList(nullptr) {
+ Kind = SK_Lambda;
+ }
+
+ /// \brief Note when all explicit captures have been added.
+ void finishedExplicitCaptures() {
+ NumExplicitCaptures = Captures.size();
+ }
+
+ static bool classof(const FunctionScopeInfo *FSI) {
+ return FSI->Kind == SK_Lambda;
+ }
+
+ ///
+ /// \brief Add a variable that might potentially be captured by the
+ /// lambda and therefore the enclosing lambdas.
+ ///
+ /// This is also used by enclosing lambda's to speculatively capture
+ /// variables that nested lambda's - depending on their enclosing
+ /// specialization - might need to capture.
+ /// Consider:
+ /// void f(int, int); <-- don't capture
+ /// void f(const int&, double); <-- capture
+ /// void foo() {
+ /// const int x = 10;
+ /// auto L = [=](auto a) { // capture 'x'
+ /// return [=](auto b) {
+ /// f(x, a); // we may or may not need to capture 'x'
+ /// };
+ /// };
+ /// }
+ void addPotentialCapture(Expr *VarExpr) {
+ assert(isa<DeclRefExpr>(VarExpr) || isa<MemberExpr>(VarExpr));
+ PotentiallyCapturingExprs.push_back(VarExpr);
+ }
+
+ void addPotentialThisCapture(SourceLocation Loc) {
+ PotentialThisCaptureLocation = Loc;
+ }
+ bool hasPotentialThisCapture() const {
+ return PotentialThisCaptureLocation.isValid();
+ }
+
+ /// \brief Mark a variable's reference in a lambda as non-odr using.
+ ///
+ /// For generic lambdas, if a variable is named in a potentially evaluated
+ /// expression, where the enclosing full expression is dependent then we
+ /// must capture the variable (given a default capture).
+ /// This is accomplished by recording all references to variables
+ /// (DeclRefExprs or MemberExprs) within said nested lambda in its array of
+ /// PotentialCaptures. All such variables have to be captured by that lambda,
+ /// except for as described below.
+ /// If that variable is usable as a constant expression and is named in a
+ /// manner that does not involve its odr-use (e.g. undergoes
+ /// lvalue-to-rvalue conversion, or discarded) record that it is so. Upon the
+ /// act of analyzing the enclosing full expression (ActOnFinishFullExpr)
+ /// if we can determine that the full expression is not instantiation-
+ /// dependent, then we can entirely avoid its capture.
+ ///
+ /// const int n = 0;
+ /// [&] (auto x) {
+ /// (void)+n + x;
+ /// };
+ /// Interestingly, this strategy would involve a capture of n, even though
+ /// it's obviously not odr-used here, because the full-expression is
+ /// instantiation-dependent. It could be useful to avoid capturing such
+ /// variables, even when they are referred to in an instantiation-dependent
+ /// expression, if we can unambiguously determine that they shall never be
+ /// odr-used. This would involve removal of the variable-referring-expression
+ /// from the array of PotentialCaptures during the lvalue-to-rvalue
+ /// conversions. But per the working draft N3797, (post-chicago 2013) we must
+ /// capture such variables.
+ /// Before anyone is tempted to implement a strategy for not-capturing 'n',
+ /// consider the insightful warning in:
+ /// /cfe-commits/Week-of-Mon-20131104/092596.html
+ /// "The problem is that the set of captures for a lambda is part of the ABI
+ /// (since lambda layout can be made visible through inline functions and the
+ /// like), and there are no guarantees as to which cases we'll manage to build
+ /// an lvalue-to-rvalue conversion in, when parsing a template -- some
+ /// seemingly harmless change elsewhere in Sema could cause us to start or stop
+ /// building such a node. So we need a rule that anyone can implement and get
+ /// exactly the same result".
+ ///
+ void markVariableExprAsNonODRUsed(Expr *CapturingVarExpr) {
+ assert(isa<DeclRefExpr>(CapturingVarExpr)
+ || isa<MemberExpr>(CapturingVarExpr));
+ NonODRUsedCapturingExprs.insert(CapturingVarExpr);
+ }
+ bool isVariableExprMarkedAsNonODRUsed(Expr *CapturingVarExpr) const {
+ assert(isa<DeclRefExpr>(CapturingVarExpr)
+ || isa<MemberExpr>(CapturingVarExpr));
+ return NonODRUsedCapturingExprs.count(CapturingVarExpr);
+ }
+ void removePotentialCapture(Expr *E) {
+ PotentiallyCapturingExprs.erase(
+ std::remove(PotentiallyCapturingExprs.begin(),
+ PotentiallyCapturingExprs.end(), E),
+ PotentiallyCapturingExprs.end());
+ }
+ void clearPotentialCaptures() {
+ PotentiallyCapturingExprs.clear();
+ PotentialThisCaptureLocation = SourceLocation();
+ }
+ unsigned getNumPotentialVariableCaptures() const {
+ return PotentiallyCapturingExprs.size();
+ }
+
+ bool hasPotentialCaptures() const {
+ return getNumPotentialVariableCaptures() ||
+ PotentialThisCaptureLocation.isValid();
+ }
+
+ // When passed the index, returns the VarDecl and Expr associated
+ // with the index.
+ void getPotentialVariableCapture(unsigned Idx, VarDecl *&VD, Expr *&E) const;
+};
+
+FunctionScopeInfo::WeakObjectProfileTy::WeakObjectProfileTy()
+ : Base(nullptr, false), Property(nullptr) {}
+
+FunctionScopeInfo::WeakObjectProfileTy
+FunctionScopeInfo::WeakObjectProfileTy::getSentinel() {
+ FunctionScopeInfo::WeakObjectProfileTy Result;
+ Result.Base.setInt(true);
+ return Result;
+}
+
+template <typename ExprT>
+void FunctionScopeInfo::recordUseOfWeak(const ExprT *E, bool IsRead) {
+ assert(E);
+ WeakUseVector &Uses = WeakObjectUses[WeakObjectProfileTy(E)];
+ Uses.push_back(WeakUseTy(E, IsRead));
+}
+
+inline void
+CapturingScopeInfo::addThisCapture(bool isNested, SourceLocation Loc,
+ QualType CaptureType, Expr *Cpy) {
+ Captures.push_back(Capture(Capture::ThisCapture, isNested, Loc, CaptureType,
+ Cpy));
+ CXXThisCaptureIndex = Captures.size();
+}
+
+} // end namespace sema
+} // end namespace clang
+
+#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..77d06f2
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Sema/Sema.h
@@ -0,0 +1,9265 @@
+//===--- 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/AST/Attr.h"
+#include "clang/AST/DeclarationName.h"
+#include "clang/AST/Expr.h"
+#include "clang/AST/ExprObjC.h"
+#include "clang/AST/ExternalASTSource.h"
+#include "clang/AST/MangleNumberingContext.h"
+#include "clang/AST/NSAPI.h"
+#include "clang/AST/PrettyPrinter.h"
+#include "clang/AST/TypeLoc.h"
+#include "clang/Basic/ExpressionTraits.h"
+#include "clang/Basic/LangOptions.h"
+#include "clang/Basic/Module.h"
+#include "clang/Basic/OpenMPKinds.h"
+#include "clang/Basic/Specifiers.h"
+#include "clang/Basic/TemplateKinds.h"
+#include "clang/Basic/TypeTraits.h"
+#include "clang/Sema/AnalysisBasedWarnings.h"
+#include "clang/Sema/DeclSpec.h"
+#include "clang/Sema/ExternalSemaSource.h"
+#include "clang/Sema/IdentifierResolver.h"
+#include "clang/Sema/LocInfoType.h"
+#include "clang/Sema/ObjCMethodList.h"
+#include "clang/Sema/Ownership.h"
+#include "clang/Sema/Scope.h"
+#include "clang/Sema/ScopeInfo.h"
+#include "clang/Sema/TypoCorrection.h"
+#include "clang/Sema/Weak.h"
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/Optional.h"
+#include "llvm/ADT/SetVector.h"
+#include "llvm/ADT/SmallPtrSet.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/TinyPtrVector.h"
+#include <deque>
+#include <memory>
+#include <string>
+#include <vector>
+
+namespace llvm {
+ class APSInt;
+ template <typename ValueT> struct DenseMapInfo;
+ template <typename ValueT, typename ValueInfoT> class DenseSet;
+ class SmallBitVector;
+ class InlineAsmIdentifierInfo;
+}
+
+namespace clang {
+ class ADLResult;
+ class ASTConsumer;
+ class ASTContext;
+ class ASTMutationListener;
+ class ASTReader;
+ class ASTWriter;
+ class ArrayType;
+ class AttributeList;
+ class BlockDecl;
+ class CapturedDecl;
+ class CXXBasePath;
+ class CXXBasePaths;
+ class CXXBindTemporaryExpr;
+ typedef SmallVector<CXXBaseSpecifier*, 4> CXXCastPath;
+ class CXXConstructorDecl;
+ class CXXConversionDecl;
+ class CXXDeleteExpr;
+ class CXXDestructorDecl;
+ class CXXFieldCollector;
+ class CXXMemberCallExpr;
+ class CXXMethodDecl;
+ class CXXScopeSpec;
+ class CXXTemporary;
+ class CXXTryStmt;
+ class CallExpr;
+ class ClassTemplateDecl;
+ class ClassTemplatePartialSpecializationDecl;
+ class ClassTemplateSpecializationDecl;
+ class VarTemplatePartialSpecializationDecl;
+ class CodeCompleteConsumer;
+ class CodeCompletionAllocator;
+ class CodeCompletionTUInfo;
+ class CodeCompletionResult;
+ class Decl;
+ class DeclAccessPair;
+ class DeclContext;
+ class DeclRefExpr;
+ class DeclaratorDecl;
+ class DeducedTemplateArgument;
+ class DependentDiagnostic;
+ class DesignatedInitExpr;
+ class Designation;
+ class EnableIfAttr;
+ 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 LambdaExpr;
+ class LangOptions;
+ class LocalInstantiationScope;
+ class LookupResult;
+ class MacroInfo;
+ typedef ArrayRef<std::pair<IdentifierInfo *, SourceLocation>> ModuleIdPath;
+ class ModuleLoader;
+ class MultiLevelTemplateArgumentList;
+ class NamedDecl;
+ class ObjCCategoryDecl;
+ class ObjCCategoryImplDecl;
+ class ObjCCompatibleAliasDecl;
+ class ObjCContainerDecl;
+ class ObjCImplDecl;
+ class ObjCImplementationDecl;
+ class ObjCInterfaceDecl;
+ class ObjCIvarDecl;
+ template <class T> class ObjCList;
+ class ObjCMessageExpr;
+ class ObjCMethodDecl;
+ class ObjCPropertyDecl;
+ class ObjCProtocolDecl;
+ class OMPThreadPrivateDecl;
+ class OMPClause;
+ struct OverloadCandidate;
+ class OverloadCandidateSet;
+ class OverloadExpr;
+ class ParenListExpr;
+ class ParmVarDecl;
+ class Preprocessor;
+ class PseudoDestructorTypeStorage;
+ class PseudoObjectExpr;
+ class QualType;
+ class StandardConversionSequence;
+ class Stmt;
+ class StringLiteral;
+ class SwitchStmt;
+ class TemplateArgument;
+ class TemplateArgumentList;
+ class TemplateArgumentLoc;
+ class TemplateDecl;
+ class TemplateParameterList;
+ class TemplatePartialOrderingContext;
+ class TemplateTemplateParmDecl;
+ class Token;
+ class TypeAliasDecl;
+ class TypedefDecl;
+ class TypedefNameDecl;
+ class TypeLoc;
+ class TypoCorrectionConsumer;
+ class UnqualifiedId;
+ class UnresolvedLookupExpr;
+ class UnresolvedMemberExpr;
+ class UnresolvedSetImpl;
+ class UnresolvedSetIterator;
+ class UsingDecl;
+ class UsingShadowDecl;
+ class ValueDecl;
+ class VarDecl;
+ class VarTemplateSpecializationDecl;
+ class VisibilityAttr;
+ class VisibleDeclConsumer;
+ class IndirectFieldDecl;
+ struct DeductionFailureInfo;
+ class TemplateSpecCandidateSet;
+
+namespace sema {
+ class AccessedEntity;
+ class BlockScopeInfo;
+ class CapturedRegionScopeInfo;
+ class CapturingScopeInfo;
+ class CompoundScopeInfo;
+ class DelayedDiagnostic;
+ class DelayedDiagnosticPool;
+ class FunctionScopeInfo;
+ class LambdaScopeInfo;
+ class PossiblyUnreachableDiag;
+ class TemplateDeductionInfo;
+}
+
+namespace threadSafety {
+ class BeforeSet;
+ void threadSafetyCleanup(BeforeSet* Cache);
+}
+
+// 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;
+
+/// Describes whether we've seen any nullability information for the given
+/// file.
+struct FileNullability {
+ /// The first pointer declarator (of any pointer kind) in the file that does
+ /// not have a corresponding nullability annotation.
+ SourceLocation PointerLoc;
+
+ /// Which kind of pointer declarator we saw.
+ uint8_t PointerKind;
+
+ /// Whether we saw any type nullability annotations in the given file.
+ bool SawTypeNullability = false;
+};
+
+/// A mapping from file IDs to a record of whether we've seen nullability
+/// information in that file.
+class FileNullabilityMap {
+ /// A mapping from file IDs to the nullability information for each file ID.
+ llvm::DenseMap<FileID, FileNullability> Map;
+
+ /// A single-element cache based on the file ID.
+ struct {
+ FileID File;
+ FileNullability Nullability;
+ } Cache;
+
+public:
+ FileNullability &operator[](FileID file) {
+ // Check the single-element cache.
+ if (file == Cache.File)
+ return Cache.Nullability;
+
+ // It's not in the single-element cache; flush the cache if we have one.
+ if (!Cache.File.isInvalid()) {
+ Map[Cache.File] = Cache.Nullability;
+ }
+
+ // Pull this entry into the cache.
+ Cache.File = file;
+ Cache.Nullability = Map[file];
+ return Cache.Nullability;
+ }
+};
+
+/// Sema - This implements semantic analysis and AST building for C.
+class Sema {
+ Sema(const Sema &) = delete;
+ void operator=(const Sema &) = delete;
+
+ ///\brief Source of additional semantic information.
+ ExternalSemaSource *ExternalSource;
+
+ ///\brief Whether Sema has generated a multiplexer and has to delete it.
+ bool isMultiplexExternalSource;
+
+ static bool mightHaveNonExternalLinkage(const DeclaratorDecl *FD);
+
+ bool isVisibleSlow(const NamedDecl *D);
+
+ bool shouldLinkPossiblyHiddenDecl(const NamedDecl *Old,
+ const NamedDecl *New) {
+ // We are about to link these. It is now safe to compute the linkage of
+ // the new decl. If the new decl has external linkage, we will
+ // link it with the hidden decl (which also has external linkage) and
+ // it will keep having external linkage. If it has internal linkage, we
+ // will not link it. Since it has no previous decls, it will remain
+ // with internal linkage.
+ return isVisible(Old) || New->isExternallyVisible();
+ }
+ bool shouldLinkPossiblyHiddenDecl(LookupResult &Old, const NamedDecl *New);
+
+public:
+ typedef OpaquePtr<DeclGroupRef> DeclGroupPtrTy;
+ typedef OpaquePtr<TemplateName> TemplateTy;
+ typedef OpaquePtr<QualType> TypeTy;
+
+ OpenCLOptions OpenCLFeatures;
+ FPOptions FPFeatures;
+
+ const LangOptions &LangOpts;
+ Preprocessor &PP;
+ ASTContext &Context;
+ ASTConsumer &Consumer;
+ DiagnosticsEngine &Diags;
+ SourceManager &SourceMgr;
+
+ /// \brief Flag indicating whether or not to collect detailed statistics.
+ bool CollectStats;
+
+ /// \brief Code-completion consumer.
+ CodeCompleteConsumer *CodeCompleter;
+
+ /// CurContext - This is the current declaration context of parsing.
+ DeclContext *CurContext;
+
+ /// \brief Generally null except when we temporarily switch decl contexts,
+ /// like in \see ActOnObjCTemporaryExitContainerContext.
+ DeclContext *OriginalLexicalContext;
+
+ /// 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*"
+
+ bool MSStructPragmaOn; // True when \#pragma ms_struct on
+
+ /// \brief Controls member pointer representation format under the MS ABI.
+ LangOptions::PragmaMSPointersToMembersKind
+ MSPointerToMemberRepresentationMethod;
+
+ enum PragmaVtorDispKind {
+ PVDK_Push, ///< #pragma vtordisp(push, mode)
+ PVDK_Set, ///< #pragma vtordisp(mode)
+ PVDK_Pop, ///< #pragma vtordisp(pop)
+ PVDK_Reset ///< #pragma vtordisp()
+ };
+
+ enum PragmaMsStackAction {
+ PSK_Reset, // #pragma ()
+ PSK_Set, // #pragma ("name")
+ PSK_Push, // #pragma (push[, id])
+ PSK_Push_Set, // #pragma (push[, id], "name")
+ PSK_Pop, // #pragma (pop[, id])
+ PSK_Pop_Set, // #pragma (pop[, id], "name")
+ };
+
+ /// \brief Whether to insert vtordisps prior to virtual bases in the Microsoft
+ /// C++ ABI. Possible values are 0, 1, and 2, which mean:
+ ///
+ /// 0: Suppress all vtordisps
+ /// 1: Insert vtordisps in the presence of vbase overrides and non-trivial
+ /// structors
+ /// 2: Always insert vtordisps to support RTTI on partially constructed
+ /// objects
+ ///
+ /// The stack always has at least one element in it.
+ SmallVector<MSVtorDispAttr::Mode, 2> VtorDispModeStack;
+
+ /// Stack of active SEH __finally scopes. Can be empty.
+ SmallVector<Scope*, 2> CurrentSEHFinally;
+
+ /// \brief Source location for newly created implicit MSInheritanceAttrs
+ SourceLocation ImplicitMSInheritanceAttrLoc;
+
+ template<typename ValueType>
+ struct PragmaStack {
+ struct Slot {
+ llvm::StringRef StackSlotLabel;
+ ValueType Value;
+ SourceLocation PragmaLocation;
+ Slot(llvm::StringRef StackSlotLabel,
+ ValueType Value,
+ SourceLocation PragmaLocation)
+ : StackSlotLabel(StackSlotLabel), Value(Value),
+ PragmaLocation(PragmaLocation) {}
+ };
+ void Act(SourceLocation PragmaLocation,
+ PragmaMsStackAction Action,
+ llvm::StringRef StackSlotLabel,
+ ValueType Value);
+ explicit PragmaStack(const ValueType &Value)
+ : CurrentValue(Value) {}
+ SmallVector<Slot, 2> Stack;
+ ValueType CurrentValue;
+ SourceLocation CurrentPragmaLocation;
+ };
+ // FIXME: We should serialize / deserialize these if they occur in a PCH (but
+ // we shouldn't do so if they're in a module).
+ PragmaStack<StringLiteral *> DataSegStack;
+ PragmaStack<StringLiteral *> BSSSegStack;
+ PragmaStack<StringLiteral *> ConstSegStack;
+ PragmaStack<StringLiteral *> CodeSegStack;
+
+ /// A mapping that describes the nullability we've seen in each header file.
+ FileNullabilityMap NullabilityMap;
+
+ /// Last section used with #pragma init_seg.
+ StringLiteral *CurInitSeg;
+ SourceLocation CurInitSegLoc;
+
+ /// VisContext - Manages the stack for \#pragma GCC visibility.
+ void *VisContext; // Really a "PragmaVisStack*"
+
+ /// \brief This represents the last location of a "#pragma clang optimize off"
+ /// directive if such a directive has not been closed by an "on" yet. If
+ /// optimizations are currently "on", this is set to an invalid location.
+ SourceLocation OptimizeOffPragmaLocation;
+
+ /// \brief Flag indicating if Sema is building a recovery call expression.
+ ///
+ /// This flag is used to avoid building recovery call expressions
+ /// if Sema is already doing so, which would cause infinite recursions.
+ bool IsBuildingRecoveryCallExpr;
+
+ /// ExprNeedsCleanups - True if the current evaluation context
+ /// requires cleanups to be run at its conclusion.
+ bool ExprNeedsCleanups;
+
+ /// ExprCleanupObjects - This is the stack of objects requiring
+ /// cleanup that are created by the current full expression. The
+ /// element type here is ExprWithCleanups::Object.
+ SmallVector<BlockDecl*, 8> ExprCleanupObjects;
+
+ /// \brief Store a list of either DeclRefExprs or MemberExprs
+ /// that contain a reference to a variable (constant) that may or may not
+ /// be odr-used in this Expr, and we won't know until all lvalue-to-rvalue
+ /// and discarded value conversions have been applied to all subexpressions
+ /// of the enclosing full expression. This is cleared at the end of each
+ /// full expression.
+ llvm::SmallPtrSet<Expr*, 2> MaybeODRUseExprs;
+
+ /// \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.
+ SmallVector<sema::FunctionScopeInfo *, 4> FunctionScopes;
+
+ typedef LazyVector<TypedefNameDecl *, ExternalSemaSource,
+ &ExternalSemaSource::ReadExtVectorDecls, 2, 2>
+ ExtVectorDeclsType;
+
+ /// 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.
+ ExtVectorDeclsType ExtVectorDecls;
+
+ /// FieldCollector - Collects CXXFieldDecls during parsing of C++ classes.
+ std::unique_ptr<CXXFieldCollector> FieldCollector;
+
+ typedef llvm::SmallSetVector<const NamedDecl*, 16> NamedDeclSetType;
+
+ /// \brief Set containing all declared private fields that are not used.
+ NamedDeclSetType UnusedPrivateFields;
+
+ /// \brief Set containing all typedefs that are likely unused.
+ llvm::SmallSetVector<const TypedefNameDecl *, 4>
+ UnusedLocalTypedefNameCandidates;
+
+ /// \brief Delete-expressions to be analyzed at the end of translation unit
+ ///
+ /// This list contains class members, and locations of delete-expressions
+ /// that could not be proven as to whether they mismatch with new-expression
+ /// used in initializer of the field.
+ typedef std::pair<SourceLocation, bool> DeleteExprLoc;
+ typedef llvm::SmallVector<DeleteExprLoc, 4> DeleteLocs;
+ llvm::MapVector<FieldDecl *, DeleteLocs> DeleteExprs;
+
+ 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.
+ std::unique_ptr<RecordDeclSetTy> PureVirtualClassDiagSet;
+
+ /// ParsingInitForAutoVars - a set of declarations with auto types for which
+ /// we are currently parsing the initializer.
+ llvm::SmallPtrSet<const Decl*, 4> ParsingInitForAutoVars;
+
+ /// \brief Look for a locally scoped extern "C" declaration by the given name.
+ NamedDecl *findLocallyScopedExternCDecl(DeclarationName Name);
+
+ typedef LazyVector<VarDecl *, ExternalSemaSource,
+ &ExternalSemaSource::ReadTentativeDefinitions, 2, 2>
+ TentativeDefinitionsType;
+
+ /// \brief All the tentative definitions encountered in the TU.
+ TentativeDefinitionsType TentativeDefinitions;
+
+ typedef LazyVector<const DeclaratorDecl *, ExternalSemaSource,
+ &ExternalSemaSource::ReadUnusedFileScopedDecls, 2, 2>
+ UnusedFileScopedDeclsType;
+
+ /// \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.
+ UnusedFileScopedDeclsType UnusedFileScopedDecls;
+
+ typedef LazyVector<CXXConstructorDecl *, ExternalSemaSource,
+ &ExternalSemaSource::ReadDelegatingConstructors, 2, 2>
+ DelegatingCtorDeclsType;
+
+ /// \brief All the delegating constructors seen so far in the file, used for
+ /// cycle detection at the end of the TU.
+ DelegatingCtorDeclsType DelegatingCtorDecls;
+
+ /// \brief All the overriding functions seen during a class definition
+ /// that had their exception spec checks delayed, plus the overridden
+ /// function.
+ SmallVector<std::pair<const CXXMethodDecl*, const CXXMethodDecl*>, 2>
+ DelayedExceptionSpecChecks;
+
+ /// \brief All the members seen during a class definition which were both
+ /// explicitly defaulted and had explicitly-specified exception
+ /// specifications, along with the function type containing their
+ /// user-specified exception specification. Those exception specifications
+ /// were overridden with the default specifications, but we still need to
+ /// check whether they are compatible with the default specification, and
+ /// we can't do that until the nesting set of class definitions is complete.
+ SmallVector<std::pair<CXXMethodDecl*, const FunctionProtoType*>, 2>
+ DelayedDefaultedMemberExceptionSpecs;
+
+ typedef llvm::MapVector<const FunctionDecl *, LateParsedTemplate *>
+ LateParsedTemplateMapT;
+ LateParsedTemplateMapT LateParsedTemplateMap;
+
+ /// \brief Callback to the parser to parse templated functions when needed.
+ typedef void LateTemplateParserCB(void *P, LateParsedTemplate &LPT);
+ typedef void LateTemplateParserCleanupCB(void *P);
+ LateTemplateParserCB *LateTemplateParser;
+ LateTemplateParserCleanupCB *LateTemplateParserCleanup;
+ void *OpaqueParser;
+
+ void SetLateTemplateParser(LateTemplateParserCB *LTP,
+ LateTemplateParserCleanupCB *LTPCleanup,
+ void *P) {
+ LateTemplateParser = LTP;
+ LateTemplateParserCleanup = LTPCleanup;
+ OpaqueParser = P;
+ }
+
+ class DelayedDiagnostics;
+
+ class DelayedDiagnosticsState {
+ sema::DelayedDiagnosticPool *SavedPool;
+ friend class Sema::DelayedDiagnostics;
+ };
+ typedef DelayedDiagnosticsState ParsingDeclState;
+ typedef DelayedDiagnosticsState ProcessingContextState;
+
+ /// A class which encapsulates the logic for delaying diagnostics
+ /// during parsing and other processing.
+ class DelayedDiagnostics {
+ /// \brief The current pool of diagnostics into which delayed
+ /// diagnostics should go.
+ sema::DelayedDiagnosticPool *CurPool;
+
+ public:
+ DelayedDiagnostics() : CurPool(nullptr) {}
+
+ /// Adds a delayed diagnostic.
+ void add(const sema::DelayedDiagnostic &diag); // in DelayedDiagnostic.h
+
+ /// Determines whether diagnostics should be delayed.
+ bool shouldDelayDiagnostics() { return CurPool != nullptr; }
+
+ /// Returns the current delayed-diagnostics pool.
+ sema::DelayedDiagnosticPool *getCurrentPool() const {
+ return CurPool;
+ }
+
+ /// Enter a new scope. Access and deprecation diagnostics will be
+ /// collected in this pool.
+ DelayedDiagnosticsState push(sema::DelayedDiagnosticPool &pool) {
+ DelayedDiagnosticsState state;
+ state.SavedPool = CurPool;
+ CurPool = &pool;
+ return state;
+ }
+
+ /// Leave a delayed-diagnostic state that was previously pushed.
+ /// Do not emit any of the diagnostics. This is performed as part
+ /// of the bookkeeping of popping a pool "properly".
+ void popWithoutEmitting(DelayedDiagnosticsState state) {
+ CurPool = state.SavedPool;
+ }
+
+ /// Enter a new scope where access and deprecation diagnostics are
+ /// not delayed.
+ DelayedDiagnosticsState pushUndelayed() {
+ DelayedDiagnosticsState state;
+ state.SavedPool = CurPool;
+ CurPool = nullptr;
+ return state;
+ }
+
+ /// Undo a previous pushUndelayed().
+ void popUndelayed(DelayedDiagnosticsState state) {
+ assert(CurPool == nullptr);
+ CurPool = state.SavedPool;
+ }
+ } DelayedDiagnostics;
+
+ /// A RAII object to temporarily push a declaration context.
+ class ContextRAII {
+ private:
+ Sema &S;
+ DeclContext *SavedContext;
+ ProcessingContextState SavedContextState;
+ QualType SavedCXXThisTypeOverride;
+
+ public:
+ ContextRAII(Sema &S, DeclContext *ContextToPush, bool NewThisContext = true)
+ : S(S), SavedContext(S.CurContext),
+ SavedContextState(S.DelayedDiagnostics.pushUndelayed()),
+ SavedCXXThisTypeOverride(S.CXXThisTypeOverride)
+ {
+ assert(ContextToPush && "pushing null context");
+ S.CurContext = ContextToPush;
+ if (NewThisContext)
+ S.CXXThisTypeOverride = QualType();
+ }
+
+ void pop() {
+ if (!SavedContext) return;
+ S.CurContext = SavedContext;
+ S.DelayedDiagnostics.popUndelayed(SavedContextState);
+ S.CXXThisTypeOverride = SavedCXXThisTypeOverride;
+ SavedContext = nullptr;
+ }
+
+ ~ContextRAII() {
+ pop();
+ }
+ };
+
+ /// \brief RAII object to handle the state changes required to synthesize
+ /// a function body.
+ class SynthesizedFunctionScope {
+ Sema &S;
+ Sema::ContextRAII SavedContext;
+
+ public:
+ SynthesizedFunctionScope(Sema &S, DeclContext *DC)
+ : S(S), SavedContext(S, DC)
+ {
+ S.PushFunctionScope();
+ S.PushExpressionEvaluationContext(Sema::PotentiallyEvaluated);
+ }
+
+ ~SynthesizedFunctionScope() {
+ S.PopExpressionEvaluationContext();
+ S.PopFunctionScopeInfo();
+ }
+ };
+
+ /// WeakUndeclaredIdentifiers - Identifiers contained in
+ /// \#pragma weak before declared. rare. may alias another
+ /// identifier, declared or undeclared
+ llvm::MapVector<IdentifierInfo *, WeakInfo> WeakUndeclaredIdentifiers;
+
+ /// ExtnameUndeclaredIdentifiers - Identifiers contained in
+ /// \#pragma redefine_extname before declared. Used in Solaris system headers
+ /// to define functions that occur in multiple standards to call the version
+ /// in the currently selected standard.
+ llvm::DenseMap<IdentifierInfo*,AsmLabelAttr*> ExtnameUndeclaredIdentifiers;
+
+
+ /// \brief Load weak undeclared identifiers from the external source.
+ void LoadExternalWeakUndeclaredIdentifiers();
+
+ /// 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.
+ 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++ "std::initializer_list" template, which is defined in
+ /// \<initializer_list>.
+ ClassTemplateDecl *StdInitializerList;
+
+ /// \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;
+
+ /// \brief Caches identifiers/selectors for NSFoundation APIs.
+ std::unique_ptr<NSAPI> NSAPIObj;
+
+ /// \brief The declaration of the Objective-C NSNumber class.
+ ObjCInterfaceDecl *NSNumberDecl;
+
+ /// \brief The declaration of the Objective-C NSValue class.
+ ObjCInterfaceDecl *NSValueDecl;
+
+ /// \brief Pointer to NSNumber type (NSNumber *).
+ QualType NSNumberPointer;
+
+ /// \brief Pointer to NSValue type (NSValue *).
+ QualType NSValuePointer;
+
+ /// \brief The Objective-C NSNumber methods used to create NSNumber literals.
+ ObjCMethodDecl *NSNumberLiteralMethods[NSAPI::NumNSNumberLiteralMethods];
+
+ /// \brief The declaration of the Objective-C NSString class.
+ ObjCInterfaceDecl *NSStringDecl;
+
+ /// \brief Pointer to NSString type (NSString *).
+ QualType NSStringPointer;
+
+ /// \brief The declaration of the stringWithUTF8String: method.
+ ObjCMethodDecl *StringWithUTF8StringMethod;
+
+ /// \brief The declaration of the valueWithBytes:objCType: method.
+ ObjCMethodDecl *ValueWithBytesObjCTypeMethod;
+
+ /// \brief The declaration of the Objective-C NSArray class.
+ ObjCInterfaceDecl *NSArrayDecl;
+
+ /// \brief The declaration of the arrayWithObjects:count: method.
+ ObjCMethodDecl *ArrayWithObjectsMethod;
+
+ /// \brief The declaration of the Objective-C NSDictionary class.
+ ObjCInterfaceDecl *NSDictionaryDecl;
+
+ /// \brief The declaration of the dictionaryWithObjects:forKeys:count: method.
+ ObjCMethodDecl *DictionaryWithObjectsMethod;
+
+ /// \brief id<NSCopying> type.
+ QualType QIDNSCopying;
+
+ /// \brief will hold 'respondsToSelector:'
+ Selector RespondsToSelectorSel;
+
+ /// \brief counter for internal MS Asm label names.
+ unsigned MSAsmLabelNameCounter;
+
+ /// A flag to remember whether the implicit forms of operator new and delete
+ /// have been declared.
+ bool GlobalNewDeleteDeclared;
+
+ /// A flag to indicate that we're in a context that permits abstract
+ /// references to fields. This is really a
+ bool AllowAbstractFieldReference;
+
+ /// \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++11 [expr]p7), such as the subexpression of
+ /// \c sizeof, where the type 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 occurs within an unevaluated
+ /// operand that unconditionally permits abstract references to
+ /// fields, such as a SIZE operator in MS-style inline assembly.
+ UnevaluatedAbstract,
+
+ /// \brief The current context is "potentially evaluated" in C++11 terms,
+ /// but the expression is evaluated at compile-time (like the values of
+ /// cases in a switch statement).
+ ConstantEvaluated,
+
+ /// \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 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 Whether the enclosing context needed a cleanup.
+ bool ParentNeedsCleanups;
+
+ /// \brief Whether we are in a decltype expression.
+ bool IsDecltype;
+
+ /// \brief The number of active cleanup objects when we entered
+ /// this expression evaluation context.
+ unsigned NumCleanupObjects;
+
+ /// \brief The number of typos encountered during this expression evaluation
+ /// context (i.e. the number of TypoExprs created).
+ unsigned NumTypos;
+
+ llvm::SmallPtrSet<Expr*, 2> SavedMaybeODRUseExprs;
+
+ /// \brief The lambdas that are present within this context, if it
+ /// is indeed an unevaluated context.
+ SmallVector<LambdaExpr *, 2> Lambdas;
+
+ /// \brief The declaration that provides context for lambda expressions
+ /// and block literals if the normal declaration context does not
+ /// suffice, e.g., in a default function argument.
+ Decl *ManglingContextDecl;
+
+ /// \brief The context information used to mangle lambda expressions
+ /// and block literals within this context.
+ ///
+ /// This mangling information is allocated lazily, since most contexts
+ /// do not have lambda expressions or block literals.
+ IntrusiveRefCntPtr<MangleNumberingContext> MangleNumbering;
+
+ /// \brief If we are processing a decltype type, a set of call expressions
+ /// for which we have deferred checking the completeness of the return type.
+ SmallVector<CallExpr *, 8> DelayedDecltypeCalls;
+
+ /// \brief If we are processing a decltype type, a set of temporary binding
+ /// expressions for which we have deferred checking the destructor.
+ SmallVector<CXXBindTemporaryExpr *, 8> DelayedDecltypeBinds;
+
+ ExpressionEvaluationContextRecord(ExpressionEvaluationContext Context,
+ unsigned NumCleanupObjects,
+ bool ParentNeedsCleanups,
+ Decl *ManglingContextDecl,
+ bool IsDecltype)
+ : Context(Context), ParentNeedsCleanups(ParentNeedsCleanups),
+ IsDecltype(IsDecltype), NumCleanupObjects(NumCleanupObjects),
+ NumTypos(0),
+ ManglingContextDecl(ManglingContextDecl), MangleNumbering() { }
+
+ /// \brief Retrieve the mangling numbering context, used to consistently
+ /// number constructs like lambdas for mangling.
+ MangleNumberingContext &getMangleNumberingContext(ASTContext &Ctx);
+
+ bool isUnevaluated() const {
+ return Context == Unevaluated || Context == UnevaluatedAbstract;
+ }
+ };
+
+ /// A stack of expression evaluation contexts.
+ SmallVector<ExpressionEvaluationContextRecord, 8> ExprEvalContexts;
+
+ /// \brief Compute the mangling number context for a lambda expression or
+ /// block literal.
+ ///
+ /// \param DC - The DeclContext containing the lambda expression or
+ /// block literal.
+ /// \param[out] ManglingContextDecl - Returns the ManglingContextDecl
+ /// associated with the context, if relevant.
+ MangleNumberingContext *getCurrentMangleNumberContext(
+ const DeclContext *DC,
+ Decl *&ManglingContextDecl);
+
+
+ /// SpecialMemberOverloadResult - The overloading result for a special member
+ /// function.
+ ///
+ /// This is basically a wrapper around PointerIntPair. The lowest bits of the
+ /// integer are used to determine whether overload resolution succeeded.
+ class SpecialMemberOverloadResult : public llvm::FastFoldingSetNode {
+ public:
+ enum Kind {
+ NoMemberOrDeleted,
+ Ambiguous,
+ Success
+ };
+
+ private:
+ llvm::PointerIntPair<CXXMethodDecl*, 2> Pair;
+
+ public:
+ SpecialMemberOverloadResult(const llvm::FoldingSetNodeID &ID)
+ : FastFoldingSetNode(ID)
+ {}
+
+ CXXMethodDecl *getMethod() const { return Pair.getPointer(); }
+ void setMethod(CXXMethodDecl *MD) { Pair.setPointer(MD); }
+
+ Kind getKind() const { return static_cast<Kind>(Pair.getInt()); }
+ void setKind(Kind K) { Pair.setInt(K); }
+ };
+
+ /// \brief A cache of special member function overload resolution results
+ /// for C++ records.
+ llvm::FoldingSet<SpecialMemberOverloadResult> SpecialMemberCache;
+
+ /// \brief A cache of the flags available in enumerations with the flag_bits
+ /// attribute.
+ mutable llvm::DenseMap<const EnumDecl*, llvm::APInt> FlagBitsCache;
+
+ /// \brief The kind of translation unit we are processing.
+ ///
+ /// When we're processing a complete translation unit, Sema will perform
+ /// end-of-translation-unit semantic tasks (such as creating
+ /// initializers for tentative definitions in C) once parsing has
+ /// completed. Modules and precompiled headers perform different kinds of
+ /// checks.
+ TranslationUnitKind TUKind;
+
+ llvm::BumpPtrAllocator BumpAlloc;
+
+ /// \brief The number of SFINAE diagnostics that have been trapped.
+ unsigned NumSFINAEErrors;
+
+ typedef llvm::DenseMap<ParmVarDecl *, llvm::TinyPtrVector<ParmVarDecl *>>
+ 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 which require a
+ /// definition in this translation unit.
+ llvm::DenseMap<NamedDecl *, SourceLocation> UndefinedButUsed;
+
+ /// Obtain a sorted list of functions that are undefined but ODR-used.
+ void getUndefinedButUsed(
+ SmallVectorImpl<std::pair<NamedDecl *, SourceLocation> > &Undefined);
+
+ /// Retrieves list of suspicious delete-expressions that will be checked at
+ /// the end of translation unit.
+ const llvm::MapVector<FieldDecl *, DeleteLocs> &
+ getMismatchingDeleteExpressions() const;
+
+ 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").
+ /// At the head of the list it is recorded whether there were 0, 1, or >= 2
+ /// methods inside categories with a particular selector.
+ GlobalMethodPool MethodPool;
+
+ /// Method selectors used in a \@selector expression. Used for implementation
+ /// of -Wselector.
+ llvm::MapVector<Selector, SourceLocation> ReferencedSelectors;
+
+ /// Kinds of C++ special members.
+ enum CXXSpecialMember {
+ CXXDefaultConstructor,
+ CXXCopyConstructor,
+ CXXMoveConstructor,
+ CXXCopyAssignment,
+ CXXMoveAssignment,
+ CXXDestructor,
+ CXXInvalid
+ };
+
+ typedef std::pair<CXXRecordDecl*, CXXSpecialMember> SpecialMemberDecl;
+
+ /// The C++ special members which we are currently in the process of
+ /// declaring. If this process recursively triggers the declaration of the
+ /// same special member, we should act as if it is not yet declared.
+ llvm::SmallSet<SpecialMemberDecl, 4> SpecialMembersBeingDeclared;
+
+ void ReadMethodPool(Selector Sel);
+
+ /// Private Helper predicate to check for 'self'.
+ bool isSelfExpr(Expr *RExpr);
+ bool isSelfExpr(Expr *RExpr, const ObjCMethodDecl *Method);
+
+ /// \brief Cause the active diagnostic on the DiagosticsEngine to be
+ /// emitted. This is closely coupled to the SemaDiagnosticBuilder class and
+ /// should not be used elsewhere.
+ void EmitCurrentDiagnostic(unsigned DiagID);
+
+ /// Records and restores the FP_CONTRACT state on entry/exit of compound
+ /// statements.
+ class FPContractStateRAII {
+ public:
+ FPContractStateRAII(Sema& S)
+ : S(S), OldFPContractState(S.FPFeatures.fp_contract) {}
+ ~FPContractStateRAII() {
+ S.FPFeatures.fp_contract = OldFPContractState;
+ }
+ private:
+ Sema& S;
+ bool OldFPContractState : 1;
+ };
+
+ /// Records and restores the vtordisp state on entry/exit of C++ method body.
+ class VtorDispStackRAII {
+ public:
+ VtorDispStackRAII(Sema &S, bool ShouldSaveAndRestore)
+ : S(S), ShouldSaveAndRestore(ShouldSaveAndRestore), OldVtorDispStack() {
+ if (ShouldSaveAndRestore)
+ OldVtorDispStack = S.VtorDispModeStack;
+ }
+ ~VtorDispStackRAII() {
+ if (ShouldSaveAndRestore)
+ S.VtorDispModeStack = OldVtorDispStack;
+ }
+ private:
+ Sema &S;
+ bool ShouldSaveAndRestore;
+ SmallVector<MSVtorDispAttr::Mode, 2> OldVtorDispStack;
+ };
+
+ void addImplicitTypedef(StringRef Name, QualType T);
+
+public:
+ Sema(Preprocessor &pp, ASTContext &ctxt, ASTConsumer &consumer,
+ TranslationUnitKind TUKind = TU_Complete,
+ CodeCompleteConsumer *CompletionConsumer = nullptr);
+ ~Sema();
+
+ /// \brief Perform initialization that occurs after the parser has been
+ /// initialized but before it parses anything.
+ void Initialize();
+
+ const LangOptions &getLangOpts() const { return LangOpts; }
+ OpenCLOptions &getOpenCLOptions() { return OpenCLFeatures; }
+ FPOptions &getFPOptions() { return FPFeatures; }
+
+ DiagnosticsEngine &getDiagnostics() const { return Diags; }
+ SourceManager &getSourceManager() const { return SourceMgr; }
+ Preprocessor &getPreprocessor() const { return PP; }
+ ASTContext &getASTContext() const { return Context; }
+ ASTConsumer &getASTConsumer() const { return Consumer; }
+ ASTMutationListener *getASTMutationListener() const;
+ ExternalSemaSource* getExternalSource() const { return ExternalSource; }
+
+ ///\brief Registers an external source. If an external source already exists,
+ /// creates a multiplex external source and appends to it.
+ ///
+ ///\param[in] E - A non-null external sema source.
+ ///
+ void addExternalSource(ExternalSemaSource *E);
+
+ void PrintStats() const;
+
+ /// \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) { }
+
+ // This is a cunning lie. DiagnosticBuilder actually performs move
+ // construction in its copy constructor (but due to varied uses, it's not
+ // possible to conveniently express this as actual move construction). So
+ // the default copy ctor here is fine, because the base class disables the
+ // source anyway, so the user-defined ~SemaDiagnosticBuilder is a safe no-op
+ // in that case anwyay.
+ SemaDiagnosticBuilder(const SemaDiagnosticBuilder&) = default;
+
+ ~SemaDiagnosticBuilder() {
+ // If we aren't active, there is nothing to do.
+ if (!isActive()) return;
+
+ // Otherwise, we need to emit the diagnostic. First flush the underlying
+ // DiagnosticBuilder data, and clear the diagnostic builder itself so it
+ // won't emit the diagnostic in its own destructor.
+ //
+ // This seems wasteful, in that as written the DiagnosticBuilder dtor will
+ // do its own needless checks to see if the diagnostic needs to be
+ // emitted. However, because we take care to ensure that the builder
+ // objects never escape, a sufficiently smart compiler will be able to
+ // eliminate that code.
+ FlushCounts();
+ Clear();
+
+ // Dispatch to Sema to emit the diagnostic.
+ SemaRef.EmitCurrentDiagnostic(DiagID);
+ }
+
+ /// Teach operator<< to produce an object of the correct type.
+ template<typename T>
+ friend const SemaDiagnosticBuilder &operator<<(
+ const SemaDiagnosticBuilder &Diag, const T &Value) {
+ const DiagnosticBuilder &BaseDiag = Diag;
+ BaseDiag << Value;
+ return Diag;
+ }
+ };
+
+ /// \brief Emit a diagnostic.
+ SemaDiagnosticBuilder Diag(SourceLocation Loc, unsigned DiagID) {
+ DiagnosticBuilder DB = Diags.Report(Loc, DiagID);
+ return SemaDiagnosticBuilder(DB, *this, 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
+
+ bool findMacroSpelling(SourceLocation &loc, StringRef name);
+
+ /// \brief Get a string to suggest for zero-initialization of a type.
+ std::string
+ getFixItZeroInitializerForType(QualType T, SourceLocation Loc) const;
+ std::string getFixItZeroLiteralForType(QualType T, SourceLocation Loc) const;
+
+ /// \brief Calls \c Lexer::getLocForEndOfToken()
+ SourceLocation getLocForEndOfToken(SourceLocation Loc, unsigned Offset = 0);
+
+ /// \brief Retrieve the module loader associated with the preprocessor.
+ ModuleLoader &getModuleLoader() const;
+
+ void emitAndClearUnusedLocalTypedefWarnings();
+
+ void ActOnEndOfTranslationUnit();
+
+ void CheckDelegatingCtorCycles();
+
+ Scope *getScopeForContext(DeclContext *Ctx);
+
+ void PushFunctionScope();
+ void PushBlockScope(Scope *BlockScope, BlockDecl *Block);
+ sema::LambdaScopeInfo *PushLambdaScope();
+
+ /// \brief This is used to inform Sema what the current TemplateParameterDepth
+ /// is during Parsing. Currently it is used to pass on the depth
+ /// when parsing generic lambda 'auto' parameters.
+ void RecordParsingTemplateParameterDepth(unsigned Depth);
+
+ void PushCapturedRegionScope(Scope *RegionScope, CapturedDecl *CD,
+ RecordDecl *RD,
+ CapturedRegionKind K);
+ void
+ PopFunctionScopeInfo(const sema::AnalysisBasedWarnings::Policy *WP = nullptr,
+ const Decl *D = nullptr,
+ const BlockExpr *blkExpr = nullptr);
+
+ sema::FunctionScopeInfo *getCurFunction() const {
+ return FunctionScopes.back();
+ }
+
+ sema::FunctionScopeInfo *getEnclosingFunction() const {
+ if (FunctionScopes.empty())
+ return nullptr;
+
+ for (int e = FunctionScopes.size()-1; e >= 0; --e) {
+ if (isa<sema::BlockScopeInfo>(FunctionScopes[e]))
+ continue;
+ return FunctionScopes[e];
+ }
+ return nullptr;
+ }
+
+ template <typename ExprT>
+ void recordUseOfEvaluatedWeak(const ExprT *E, bool IsRead=true) {
+ if (!isUnevaluatedContext())
+ getCurFunction()->recordUseOfWeak(E, IsRead);
+ }
+
+ void PushCompoundScope();
+ void PopCompoundScope();
+
+ sema::CompoundScopeInfo &getCurCompoundScope() const;
+
+ bool hasAnyUnrecoverableErrorsInThisFunction() const;
+
+ /// \brief Retrieve the current block, if any.
+ sema::BlockScopeInfo *getCurBlock();
+
+ /// \brief Retrieve the current lambda scope info, if any.
+ sema::LambdaScopeInfo *getCurLambda();
+
+ /// \brief Retrieve the current generic lambda info, if any.
+ sema::LambdaScopeInfo *getCurGenericLambda();
+
+ /// \brief Retrieve the current captured region, if any.
+ sema::CapturedRegionScopeInfo *getCurCapturedRegion();
+
+ /// WeakTopLevelDeclDecls - access to \#pragma weak-generated Decls
+ SmallVectorImpl<Decl *> &WeakTopLevelDecls() { return WeakTopLevelDecl; }
+
+ void ActOnComment(SourceRange Comment);
+
+ //===--------------------------------------------------------------------===//
+ // Type Analysis / Processing: SemaType.cpp.
+ //
+
+ QualType BuildQualifiedType(QualType T, SourceLocation Loc, Qualifiers Qs,
+ const DeclSpec *DS = nullptr);
+ QualType BuildQualifiedType(QualType T, SourceLocation Loc, unsigned CVRA,
+ const DeclSpec *DS = nullptr);
+ 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);
+
+ bool CheckFunctionReturnType(QualType T, SourceLocation Loc);
+
+ /// \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 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.
+ ///
+ /// \param EPI Extra information about the function type. Usually this will
+ /// be taken from an existing function with the same prototype.
+ ///
+ /// \returns A suitable function type, if there are no errors. The
+ /// unqualified type will always be a FunctionProtoType.
+ /// Otherwise, returns a NULL type.
+ QualType BuildFunctionType(QualType T,
+ MutableArrayRef<QualType> ParamTypes,
+ SourceLocation Loc, DeclarationName Entity,
+ const FunctionProtoType::ExtProtoInfo &EPI);
+
+ QualType BuildMemberPointerType(QualType T, QualType Class,
+ SourceLocation Loc,
+ DeclarationName Entity);
+ QualType BuildBlockPointerType(QualType T,
+ SourceLocation Loc, DeclarationName Entity);
+ QualType BuildParenType(QualType T);
+ QualType BuildAtomicType(QualType T, SourceLocation Loc);
+
+ TypeSourceInfo *GetTypeForDeclarator(Declarator &D, Scope *S);
+ TypeSourceInfo *GetTypeForDeclaratorCast(Declarator &D, QualType FromTy);
+ 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 = nullptr);
+ CanThrowResult canThrow(const Expr *E);
+ const FunctionProtoType *ResolveExceptionSpec(SourceLocation Loc,
+ const FunctionProtoType *FPT);
+ void UpdateExceptionSpec(FunctionDecl *FD,
+ const FunctionProtoType::ExceptionSpecInfo &ESI);
+ bool CheckSpecifiedExceptionType(QualType &T, 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 = nullptr,
+ bool *MissingEmptyExceptionSpecification = nullptr,
+ bool AllowNoexceptAllMatchWithNoSpec = false,
+ bool IsOperatorNew = false);
+ 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);
+
+ /// \brief The parser has parsed the context-sensitive type 'instancetype'
+ /// in an Objective-C message declaration. Return the appropriate type.
+ ParsedType ActOnObjCInstanceType(SourceLocation Loc);
+
+ /// \brief Abstract class used to diagnose incomplete types.
+ struct TypeDiagnoser {
+ TypeDiagnoser() {}
+
+ virtual void diagnose(Sema &S, SourceLocation Loc, QualType T) = 0;
+ virtual ~TypeDiagnoser() {}
+ };
+
+ static int getPrintable(int I) { return I; }
+ static unsigned getPrintable(unsigned I) { return I; }
+ static bool getPrintable(bool B) { return B; }
+ static const char * getPrintable(const char *S) { return S; }
+ static StringRef getPrintable(StringRef S) { return S; }
+ static const std::string &getPrintable(const std::string &S) { return S; }
+ static const IdentifierInfo *getPrintable(const IdentifierInfo *II) {
+ return II;
+ }
+ static DeclarationName getPrintable(DeclarationName N) { return N; }
+ static QualType getPrintable(QualType T) { return T; }
+ static SourceRange getPrintable(SourceRange R) { return R; }
+ static SourceRange getPrintable(SourceLocation L) { return L; }
+ static SourceRange getPrintable(const Expr *E) { return E->getSourceRange(); }
+ static SourceRange getPrintable(TypeLoc TL) { return TL.getSourceRange();}
+
+ template <typename... Ts> class BoundTypeDiagnoser : public TypeDiagnoser {
+ unsigned DiagID;
+ std::tuple<const Ts &...> Args;
+
+ template <std::size_t... Is>
+ void emit(const SemaDiagnosticBuilder &DB,
+ llvm::index_sequence<Is...>) const {
+ // Apply all tuple elements to the builder in order.
+ bool Dummy[] = {false, (DB << getPrintable(std::get<Is>(Args)))...};
+ (void)Dummy;
+ }
+
+ public:
+ BoundTypeDiagnoser(unsigned DiagID, const Ts &...Args)
+ : TypeDiagnoser(), DiagID(DiagID), Args(Args...) {
+ assert(DiagID != 0 && "no diagnostic for type diagnoser");
+ }
+
+ void diagnose(Sema &S, SourceLocation Loc, QualType T) override {
+ const SemaDiagnosticBuilder &DB = S.Diag(Loc, DiagID);
+ emit(DB, llvm::index_sequence_for<Ts...>());
+ DB << T;
+ }
+ };
+
+private:
+ bool RequireCompleteTypeImpl(SourceLocation Loc, QualType T,
+ TypeDiagnoser *Diagnoser);
+
+ VisibleModuleSet VisibleModules;
+ llvm::SmallVector<VisibleModuleSet, 16> VisibleModulesStack;
+
+ Module *CachedFakeTopLevelModule;
+
+public:
+ /// \brief Get the module owning an entity.
+ Module *getOwningModule(Decl *Entity);
+
+ /// \brief Make a merged definition of an existing hidden definition \p ND
+ /// visible at the specified location.
+ void makeMergedDefinitionVisible(NamedDecl *ND, SourceLocation Loc);
+
+ bool isModuleVisible(Module *M) { return VisibleModules.isVisible(M); }
+
+ /// Determine whether a declaration is visible to name lookup.
+ bool isVisible(const NamedDecl *D) {
+ return !D->isHidden() || isVisibleSlow(D);
+ }
+ bool hasVisibleMergedDefinition(NamedDecl *Def);
+
+ /// Determine if \p D has a visible definition. If not, suggest a declaration
+ /// that should be made visible to expose the definition.
+ bool hasVisibleDefinition(NamedDecl *D, NamedDecl **Suggested,
+ bool OnlyNeedComplete = false);
+ bool hasVisibleDefinition(const NamedDecl *D) {
+ NamedDecl *Hidden;
+ return hasVisibleDefinition(const_cast<NamedDecl*>(D), &Hidden);
+ }
+
+ /// Determine if the template parameter \p D has a visible default argument.
+ bool
+ hasVisibleDefaultArgument(const NamedDecl *D,
+ llvm::SmallVectorImpl<Module *> *Modules = nullptr);
+
+ /// Determine if \p A and \p B are equivalent internal linkage declarations
+ /// from different modules, and thus an ambiguity error can be downgraded to
+ /// an extension warning.
+ bool isEquivalentInternalLinkageDeclaration(const NamedDecl *A,
+ const NamedDecl *B);
+ void diagnoseEquivalentInternalLinkageDeclarations(
+ SourceLocation Loc, const NamedDecl *D,
+ ArrayRef<const NamedDecl *> Equiv);
+
+ bool isCompleteType(SourceLocation Loc, QualType T) {
+ return !RequireCompleteTypeImpl(Loc, T, nullptr);
+ }
+ bool RequireCompleteType(SourceLocation Loc, QualType T,
+ TypeDiagnoser &Diagnoser);
+ bool RequireCompleteType(SourceLocation Loc, QualType T,
+ unsigned DiagID);
+
+ template <typename... Ts>
+ bool RequireCompleteType(SourceLocation Loc, QualType T, unsigned DiagID,
+ const Ts &...Args) {
+ BoundTypeDiagnoser<Ts...> Diagnoser(DiagID, Args...);
+ return RequireCompleteType(Loc, T, Diagnoser);
+ }
+
+ void completeExprArrayBound(Expr *E);
+ bool RequireCompleteExprType(Expr *E, TypeDiagnoser &Diagnoser);
+ bool RequireCompleteExprType(Expr *E, unsigned DiagID);
+
+ template <typename... Ts>
+ bool RequireCompleteExprType(Expr *E, unsigned DiagID, const Ts &...Args) {
+ BoundTypeDiagnoser<Ts...> Diagnoser(DiagID, Args...);
+ return RequireCompleteExprType(E, Diagnoser);
+ }
+
+ bool RequireLiteralType(SourceLocation Loc, QualType T,
+ TypeDiagnoser &Diagnoser);
+ bool RequireLiteralType(SourceLocation Loc, QualType T, unsigned DiagID);
+
+ template <typename... Ts>
+ bool RequireLiteralType(SourceLocation Loc, QualType T, unsigned DiagID,
+ const Ts &...Args) {
+ BoundTypeDiagnoser<Ts...> Diagnoser(DiagID, Args...);
+ return RequireLiteralType(Loc, T, Diagnoser);
+ }
+
+ QualType getElaboratedType(ElaboratedTypeKeyword Keyword,
+ const CXXScopeSpec &SS, QualType T);
+
+ QualType BuildTypeofExprType(Expr *E, SourceLocation Loc);
+ /// If AsUnevaluated is false, E is treated as though it were an evaluated
+ /// context, such as when building a type for decltype(auto).
+ QualType BuildDecltypeType(Expr *E, SourceLocation Loc,
+ bool AsUnevaluated = true);
+ QualType BuildUnaryTransformType(QualType BaseType,
+ UnaryTransformType::UTTKind UKind,
+ SourceLocation Loc);
+
+ //===--------------------------------------------------------------------===//
+ // Symbol table / Decl tracking callbacks: SemaDecl.cpp.
+ //
+
+ struct SkipBodyInfo {
+ SkipBodyInfo() : ShouldSkip(false), Previous(nullptr) {}
+ bool ShouldSkip;
+ NamedDecl *Previous;
+ };
+
+ /// List of decls defined in a function prototype. This contains EnumConstants
+ /// that incorrectly end up in translation unit scope because there is no
+ /// function to pin them on. ActOnFunctionDeclarator reads this list and patches
+ /// them into the FunctionDecl.
+ std::vector<NamedDecl*> DeclsInPrototypeScope;
+
+ DeclGroupPtrTy ConvertDeclToDeclGroup(Decl *Ptr, Decl *OwnedType = nullptr);
+
+ void DiagnoseUseOfUnimplementedSelectors();
+
+ bool isSimpleTypeSpecifier(tok::TokenKind Kind) const;
+
+ ParsedType getTypeName(const IdentifierInfo &II, SourceLocation NameLoc,
+ Scope *S, CXXScopeSpec *SS = nullptr,
+ bool isClassName = false,
+ bool HasTrailingDot = false,
+ ParsedType ObjectType = ParsedType(),
+ bool IsCtorOrDtorName = false,
+ bool WantNontrivialTypeSourceInfo = false,
+ IdentifierInfo **CorrectedII = nullptr);
+ TypeSpecifierType isTagName(IdentifierInfo &II, Scope *S);
+ bool isMicrosoftMissingTypename(const CXXScopeSpec *SS, Scope *S);
+ void DiagnoseUnknownTypeName(IdentifierInfo *&II,
+ SourceLocation IILoc,
+ Scope *S,
+ CXXScopeSpec *SS,
+ ParsedType &SuggestedType,
+ bool AllowClassTemplates = false);
+
+ /// \brief For compatibility with MSVC, we delay parsing of some default
+ /// template type arguments until instantiation time. Emits a warning and
+ /// returns a synthesized DependentNameType that isn't really dependent on any
+ /// other template arguments.
+ ParsedType ActOnDelayedDefaultTemplateArg(const IdentifierInfo &II,
+ SourceLocation NameLoc);
+
+ /// \brief Describes the result of the name lookup and resolution performed
+ /// by \c ClassifyName().
+ enum NameClassificationKind {
+ NC_Unknown,
+ NC_Error,
+ NC_Keyword,
+ NC_Type,
+ NC_Expression,
+ NC_NestedNameSpecifier,
+ NC_TypeTemplate,
+ NC_VarTemplate,
+ NC_FunctionTemplate
+ };
+
+ class NameClassification {
+ NameClassificationKind Kind;
+ ExprResult Expr;
+ TemplateName Template;
+ ParsedType Type;
+ const IdentifierInfo *Keyword;
+
+ explicit NameClassification(NameClassificationKind Kind) : Kind(Kind) {}
+
+ public:
+ NameClassification(ExprResult Expr) : Kind(NC_Expression), Expr(Expr) {}
+
+ NameClassification(ParsedType Type) : Kind(NC_Type), Type(Type) {}
+
+ NameClassification(const IdentifierInfo *Keyword)
+ : Kind(NC_Keyword), Keyword(Keyword) { }
+
+ static NameClassification Error() {
+ return NameClassification(NC_Error);
+ }
+
+ static NameClassification Unknown() {
+ return NameClassification(NC_Unknown);
+ }
+
+ static NameClassification NestedNameSpecifier() {
+ return NameClassification(NC_NestedNameSpecifier);
+ }
+
+ static NameClassification TypeTemplate(TemplateName Name) {
+ NameClassification Result(NC_TypeTemplate);
+ Result.Template = Name;
+ return Result;
+ }
+
+ static NameClassification VarTemplate(TemplateName Name) {
+ NameClassification Result(NC_VarTemplate);
+ Result.Template = Name;
+ return Result;
+ }
+
+ static NameClassification FunctionTemplate(TemplateName Name) {
+ NameClassification Result(NC_FunctionTemplate);
+ Result.Template = Name;
+ return Result;
+ }
+
+ NameClassificationKind getKind() const { return Kind; }
+
+ ParsedType getType() const {
+ assert(Kind == NC_Type);
+ return Type;
+ }
+
+ ExprResult getExpression() const {
+ assert(Kind == NC_Expression);
+ return Expr;
+ }
+
+ TemplateName getTemplateName() const {
+ assert(Kind == NC_TypeTemplate || Kind == NC_FunctionTemplate ||
+ Kind == NC_VarTemplate);
+ return Template;
+ }
+
+ TemplateNameKind getTemplateNameKind() const {
+ switch (Kind) {
+ case NC_TypeTemplate:
+ return TNK_Type_template;
+ case NC_FunctionTemplate:
+ return TNK_Function_template;
+ case NC_VarTemplate:
+ return TNK_Var_template;
+ default:
+ llvm_unreachable("unsupported name classification.");
+ }
+ }
+ };
+
+ /// \brief Perform name lookup on the given name, classifying it based on
+ /// the results of name lookup and the following token.
+ ///
+ /// This routine is used by the parser to resolve identifiers and help direct
+ /// parsing. When the identifier cannot be found, this routine will attempt
+ /// to correct the typo and classify based on the resulting name.
+ ///
+ /// \param S The scope in which we're performing name lookup.
+ ///
+ /// \param SS The nested-name-specifier that precedes the name.
+ ///
+ /// \param Name The identifier. If typo correction finds an alternative name,
+ /// this pointer parameter will be updated accordingly.
+ ///
+ /// \param NameLoc The location of the identifier.
+ ///
+ /// \param NextToken The token following the identifier. Used to help
+ /// disambiguate the name.
+ ///
+ /// \param IsAddressOfOperand True if this name is the operand of a unary
+ /// address of ('&') expression, assuming it is classified as an
+ /// expression.
+ ///
+ /// \param CCC The correction callback, if typo correction is desired.
+ NameClassification
+ ClassifyName(Scope *S, CXXScopeSpec &SS, IdentifierInfo *&Name,
+ SourceLocation NameLoc, const Token &NextToken,
+ bool IsAddressOfOperand,
+ std::unique_ptr<CorrectionCandidateCallback> CCC = nullptr);
+
+ Decl *ActOnDeclarator(Scope *S, Declarator &D);
+
+ NamedDecl *HandleDeclarator(Scope *S, Declarator &D,
+ MultiTemplateParamsArg TemplateParameterLists);
+ void RegisterLocallyScopedExternCDecl(NamedDecl *ND, Scope *S);
+ bool DiagnoseClassNameShadow(DeclContext *DC, DeclarationNameInfo Info);
+ bool diagnoseQualifiedDeclaration(CXXScopeSpec &SS, DeclContext *DC,
+ DeclarationName Name,
+ SourceLocation Loc);
+ void
+ diagnoseIgnoredQualifiers(unsigned DiagID, unsigned Quals,
+ SourceLocation FallbackLoc,
+ SourceLocation ConstQualLoc = SourceLocation(),
+ SourceLocation VolatileQualLoc = SourceLocation(),
+ SourceLocation RestrictQualLoc = SourceLocation(),
+ SourceLocation AtomicQualLoc = SourceLocation());
+
+ static bool adjustContextForLocalExternDecl(DeclContext *&DC);
+ void DiagnoseFunctionSpecifiers(const DeclSpec &DS);
+ void CheckShadow(Scope *S, VarDecl *D, const LookupResult& R);
+ void CheckShadow(Scope *S, VarDecl *D);
+ void CheckCastAlign(Expr *Op, QualType T, SourceRange TRange);
+ void handleTagNumbering(const TagDecl *Tag, Scope *TagScope);
+ void setTagNameForLinkagePurposes(TagDecl *TagFromDeclSpec,
+ TypedefNameDecl *NewTD);
+ void CheckTypedefForVariablyModifiedType(Scope *S, TypedefNameDecl *D);
+ NamedDecl* ActOnTypedefDeclarator(Scope* S, Declarator& D, DeclContext* DC,
+ TypeSourceInfo *TInfo,
+ LookupResult &Previous);
+ NamedDecl* ActOnTypedefNameDecl(Scope* S, DeclContext* DC, TypedefNameDecl *D,
+ LookupResult &Previous, bool &Redeclaration);
+ NamedDecl *ActOnVariableDeclarator(Scope *S, Declarator &D, DeclContext *DC,
+ TypeSourceInfo *TInfo,
+ LookupResult &Previous,
+ MultiTemplateParamsArg TemplateParamLists,
+ bool &AddToScope);
+ // Returns true if the variable declaration is a redeclaration
+ bool CheckVariableDeclaration(VarDecl *NewVD, LookupResult &Previous);
+ void CheckVariableDeclarationType(VarDecl *NewVD);
+ void CheckCompleteVariableDeclaration(VarDecl *var);
+ void MaybeSuggestAddingStaticToDecl(const FunctionDecl *D);
+
+ NamedDecl* ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC,
+ TypeSourceInfo *TInfo,
+ LookupResult &Previous,
+ MultiTemplateParamsArg TemplateParamLists,
+ bool &AddToScope);
+ bool AddOverriddenMethods(CXXRecordDecl *DC, CXXMethodDecl *MD);
+
+ bool CheckConstexprFunctionDecl(const FunctionDecl *FD);
+ bool CheckConstexprFunctionBody(const FunctionDecl *FD, Stmt *Body);
+
+ void DiagnoseHiddenVirtualMethods(CXXMethodDecl *MD);
+ void FindHiddenVirtualMethods(CXXMethodDecl *MD,
+ SmallVectorImpl<CXXMethodDecl*> &OverloadedMethods);
+ void NoteHiddenVirtualMethods(CXXMethodDecl *MD,
+ SmallVectorImpl<CXXMethodDecl*> &OverloadedMethods);
+ // Returns true if the function declaration is a redeclaration
+ bool CheckFunctionDeclaration(Scope *S,
+ FunctionDecl *NewFD, LookupResult &Previous,
+ bool IsExplicitSpecialization);
+ void CheckMain(FunctionDecl *FD, const DeclSpec &D);
+ void CheckMSVCRTEntryPoint(FunctionDecl *FD);
+ Decl *ActOnParamDeclarator(Scope *S, Declarator &D);
+ ParmVarDecl *BuildParmVarDeclForTypedef(DeclContext *DC,
+ SourceLocation Loc,
+ QualType T);
+ ParmVarDecl *CheckParameter(DeclContext *DC, SourceLocation StartLoc,
+ SourceLocation NameLoc, IdentifierInfo *Name,
+ QualType T, TypeSourceInfo *TSInfo,
+ StorageClass SC);
+ void ActOnParamDefaultArgument(Decl *param,
+ SourceLocation EqualLoc,
+ Expr *defarg);
+ void ActOnParamUnparsedDefaultArgument(Decl *param,
+ SourceLocation EqualLoc,
+ SourceLocation ArgLoc);
+ void ActOnParamDefaultArgumentError(Decl *param, SourceLocation EqualLoc);
+ 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 ActOnPureSpecifier(Decl *D, SourceLocation PureSpecLoc);
+ void ActOnCXXForRangeDecl(Decl *D);
+ StmtResult ActOnCXXForRangeIdentifier(Scope *S, SourceLocation IdentLoc,
+ IdentifierInfo *Ident,
+ ParsedAttributes &Attrs,
+ SourceLocation AttrEnd);
+ void SetDeclDeleted(Decl *dcl, SourceLocation DelLoc);
+ void SetDeclDefaulted(Decl *dcl, SourceLocation DefaultLoc);
+ void FinalizeDeclaration(Decl *D);
+ DeclGroupPtrTy FinalizeDeclaratorGroup(Scope *S, const DeclSpec &DS,
+ ArrayRef<Decl *> Group);
+ DeclGroupPtrTy BuildDeclaratorGroup(MutableArrayRef<Decl *> Group,
+ bool TypeMayContainAuto = true);
+
+ /// Should be called on all declarations that might have attached
+ /// documentation comments.
+ void ActOnDocumentableDecl(Decl *D);
+ void ActOnDocumentableDecls(ArrayRef<Decl *> Group);
+
+ void ActOnFinishKNRParamDeclarations(Scope *S, Declarator &D,
+ SourceLocation LocAfterDecls);
+ void CheckForFunctionRedefinition(
+ FunctionDecl *FD, const FunctionDecl *EffectiveDefinition = nullptr,
+ SkipBodyInfo *SkipBody = nullptr);
+ Decl *ActOnStartOfFunctionDef(Scope *S, Declarator &D,
+ MultiTemplateParamsArg TemplateParamLists,
+ SkipBodyInfo *SkipBody = nullptr);
+ Decl *ActOnStartOfFunctionDef(Scope *S, Decl *D,
+ SkipBodyInfo *SkipBody = nullptr);
+ void ActOnStartOfObjCMethodDef(Scope *S, Decl *D);
+ bool isObjCMethodDecl(Decl *D) {
+ return D && isa<ObjCMethodDecl>(D);
+ }
+
+ /// \brief Determine whether we can delay parsing the body of a function or
+ /// function template until it is used, assuming we don't care about emitting
+ /// code for that function.
+ ///
+ /// This will be \c false if we may need the body of the function in the
+ /// middle of parsing an expression (where it's impractical to switch to
+ /// parsing a different function), for instance, if it's constexpr in C++11
+ /// or has an 'auto' return type in C++14. These cases are essentially bugs.
+ bool canDelayFunctionBody(const Declarator &D);
+
+ /// \brief Determine whether we can skip parsing the body of a function
+ /// definition, assuming we don't care about analyzing its body or emitting
+ /// code for that function.
+ ///
+ /// This will be \c false only if we may need the body of the function in
+ /// order to parse the rest of the program (for instance, if it is
+ /// \c constexpr in C++11 or has an 'auto' return type in C++14).
+ bool canSkipFunctionBody(Decl *D);
+
+ void computeNRVO(Stmt *Body, sema::FunctionScopeInfo *Scope);
+ Decl *ActOnFinishFunctionBody(Decl *Decl, Stmt *Body);
+ Decl *ActOnFinishFunctionBody(Decl *Decl, Stmt *Body, bool IsInstantiation);
+ Decl *ActOnSkippedFunctionBody(Decl *Decl);
+ void ActOnFinishInlineMethodDef(CXXMethodDecl *D);
+
+ /// ActOnFinishDelayedAttribute - Invoked when we have finished parsing an
+ /// attribute for which parsing is delayed.
+ void ActOnFinishDelayedAttribute(Scope *S, Decl *D, ParsedAttributes &Attrs);
+
+ /// \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(Expr *expr,
+ SourceLocation AsmLoc,
+ SourceLocation RParenLoc);
+
+ /// \brief Handle a C++11 empty-declaration and attribute-declaration.
+ Decl *ActOnEmptyDeclaration(Scope *S,
+ AttributeList *AttrList,
+ SourceLocation SemiLoc);
+
+ /// \brief The parser has processed a module import declaration.
+ ///
+ /// \param AtLoc The location of the '@' symbol, if any.
+ ///
+ /// \param ImportLoc The location of the 'import' keyword.
+ ///
+ /// \param Path The module access path.
+ DeclResult ActOnModuleImport(SourceLocation AtLoc, SourceLocation ImportLoc,
+ ModuleIdPath Path);
+
+ /// \brief The parser has processed a module import translated from a
+ /// #include or similar preprocessing directive.
+ void ActOnModuleInclude(SourceLocation DirectiveLoc, Module *Mod);
+
+ /// \brief The parsed has entered a submodule.
+ void ActOnModuleBegin(SourceLocation DirectiveLoc, Module *Mod);
+ /// \brief The parser has left a submodule.
+ void ActOnModuleEnd(SourceLocation DirectiveLoc, Module *Mod);
+
+ /// \brief Check if module import may be found in the current context,
+ /// emit error if not.
+ void diagnoseMisplacedModuleImport(Module *M, SourceLocation ImportLoc);
+
+ /// \brief Create an implicit import of the given module at the given
+ /// source location, for error recovery, if possible.
+ ///
+ /// This routine is typically used when an entity found by name lookup
+ /// is actually hidden within a module that we know about but the user
+ /// has forgotten to import.
+ void createImplicitModuleImportForErrorRecovery(SourceLocation Loc,
+ Module *Mod);
+
+ /// Kinds of missing import. Note, the values of these enumerators correspond
+ /// to %select values in diagnostics.
+ enum class MissingImportKind {
+ Declaration,
+ Definition,
+ DefaultArgument
+ };
+
+ /// \brief Diagnose that the specified declaration needs to be visible but
+ /// isn't, and suggest a module import that would resolve the problem.
+ void diagnoseMissingImport(SourceLocation Loc, NamedDecl *Decl,
+ bool NeedDefinition, bool Recover = true);
+ void diagnoseMissingImport(SourceLocation Loc, NamedDecl *Decl,
+ SourceLocation DeclLoc, ArrayRef<Module *> Modules,
+ MissingImportKind MIK, bool Recover);
+
+ /// \brief Retrieve a suitable printing policy.
+ PrintingPolicy getPrintingPolicy() const {
+ return getPrintingPolicy(Context, PP);
+ }
+
+ /// \brief Retrieve a suitable printing policy.
+ static PrintingPolicy getPrintingPolicy(const ASTContext &Ctx,
+ const Preprocessor &PP);
+
+ /// Scope actions.
+ void ActOnPopScope(SourceLocation Loc, Scope *S);
+ void ActOnTranslationUnitScope(Scope *S);
+
+ Decl *ParsedFreeStandingDeclSpec(Scope *S, AccessSpecifier AS,
+ DeclSpec &DS);
+ Decl *ParsedFreeStandingDeclSpec(Scope *S, AccessSpecifier AS,
+ DeclSpec &DS,
+ MultiTemplateParamsArg TemplateParams,
+ bool IsExplicitInstantiation = false);
+
+ Decl *BuildAnonymousStructOrUnion(Scope *S, DeclSpec &DS,
+ AccessSpecifier AS,
+ RecordDecl *Record,
+ const PrintingPolicy &Policy);
+
+ Decl *BuildMicrosoftCAnonymousStruct(Scope *S, DeclSpec &DS,
+ RecordDecl *Record);
+
+ bool isAcceptableTagRedeclaration(const TagDecl *Previous,
+ TagTypeKind NewTag, bool isDefinition,
+ 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,
+ SourceLocation ModulePrivateLoc,
+ MultiTemplateParamsArg TemplateParameterLists,
+ bool &OwnedDecl, bool &IsDependent,
+ SourceLocation ScopedEnumKWLoc,
+ bool ScopedEnumUsesClassTag, TypeResult UnderlyingType,
+ bool IsTypeSpecifier, SkipBodyInfo *SkipBody = nullptr);
+
+ 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,
+ 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,
+ InClassInitStyle InitStyle,
+ AccessSpecifier AS);
+ MSPropertyDecl *HandleMSProperty(Scope *S, RecordDecl *TagD,
+ SourceLocation DeclStart,
+ Declarator &D, Expr *BitfieldWidth,
+ InClassInitStyle InitStyle,
+ AccessSpecifier AS,
+ AttributeList *MSPropertyAttr);
+
+ FieldDecl *CheckFieldDecl(DeclarationName Name, QualType T,
+ TypeSourceInfo *TInfo,
+ RecordDecl *Record, SourceLocation Loc,
+ bool Mutable, Expr *BitfieldWidth,
+ InClassInitStyle InitStyle,
+ SourceLocation TSSL,
+ AccessSpecifier AS, NamedDecl *PrevDecl,
+ Declarator *D = nullptr);
+
+ bool CheckNontrivialField(FieldDecl *FD);
+ void DiagnoseNontrivial(const CXXRecordDecl *Record, CXXSpecialMember CSM);
+ bool SpecialMemberIsTrivial(CXXMethodDecl *MD, CXXSpecialMember CSM,
+ bool Diagnose = false);
+ CXXSpecialMember getSpecialMember(const CXXMethodDecl *MD);
+ void ActOnLastBitfield(SourceLocation DeclStart,
+ SmallVectorImpl<Decl *> &AllIvarDecls);
+ Decl *ActOnIvar(Scope *S, SourceLocation DeclStart,
+ 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,
+ ArrayRef<Decl *> Fields,
+ 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);
+
+ typedef void *SkippedDefinitionContext;
+
+ /// \brief Invoked when we enter a tag definition that we're skipping.
+ SkippedDefinitionContext ActOnTagStartSkippedDefinition(Scope *S, Decl *TD);
+
+ Decl *ActOnObjCContainerStartDefinition(Decl *IDecl);
+
+ /// 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,
+ SourceLocation FinalLoc,
+ bool IsFinalSpelledSealed,
+ 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);
+
+ void ActOnTagFinishSkippedDefinition(SkippedDefinitionContext Context);
+
+ void ActOnObjCContainerFinishDefinition();
+
+ /// \brief Invoked when we must temporarily exit the objective-c container
+ /// scope for parsing/looking-up C constructs.
+ ///
+ /// Must be followed by a call to \see ActOnObjCReenterContainerContext
+ void ActOnObjCTemporaryExitContainerContext(DeclContext *DC);
+ void ActOnObjCReenterContainerContext(DeclContext *DC);
+
+ /// 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);
+ bool CheckEnumUnderlyingType(TypeSourceInfo *TI);
+ bool CheckEnumRedeclaration(SourceLocation EnumLoc, bool IsScoped,
+ QualType EnumUnderlyingTy,
+ bool EnumUnderlyingIsImplicit,
+ const EnumDecl *Prev);
+
+ /// Determine whether the body of an anonymous enumeration should be skipped.
+ /// \param II The name of the first enumerator.
+ SkipBodyInfo shouldSkipAnonEnumBody(Scope *S, IdentifierInfo *II,
+ SourceLocation IILoc);
+
+ 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,
+ ArrayRef<Decl *> Elements,
+ 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);
+
+ /// Push the parameters of D, which must be a function, into scope.
+ void ActOnReenterFunctionContext(Scope* S, Decl* D);
+ void ActOnExitFunctionContext();
+
+ 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);
+
+ /// \brief Make the given externally-produced declaration visible at the
+ /// top level scope.
+ ///
+ /// \param D The externally-produced declaration to push.
+ ///
+ /// \param Name The name of the externally-produced declaration.
+ void pushExternalDeclIntoScope(NamedDecl *D, DeclarationName Name);
+
+ /// 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.
+ ///
+ /// \param AllowInlineNamespace If \c true, allow the declaration to be in the
+ /// enclosing namespace set of the context, rather than contained
+ /// directly within it.
+ bool isDeclInScope(NamedDecl *D, DeclContext *Ctx, Scope *S = nullptr,
+ bool AllowInlineNamespace = false);
+
+ /// 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);
+ bool isIncompatibleTypedef(TypeDecl *Old, TypedefNameDecl *New);
+
+ /// \brief Describes the kind of merge to perform for availability
+ /// attributes (including "deprecated", "unavailable", and "availability").
+ enum AvailabilityMergeKind {
+ /// \brief Don't merge availability attributes at all.
+ AMK_None,
+ /// \brief Merge availability attributes for a redeclaration, which requires
+ /// an exact match.
+ AMK_Redeclaration,
+ /// \brief Merge availability attributes for an override, which requires
+ /// an exact match or a weakening of constraints.
+ AMK_Override,
+ /// \brief Merge availability attributes for an implementation of
+ /// a protocol requirement.
+ AMK_ProtocolImplementation,
+ };
+
+ /// Attribute merging methods. Return true if a new attribute was added.
+ AvailabilityAttr *mergeAvailabilityAttr(NamedDecl *D, SourceRange Range,
+ IdentifierInfo *Platform,
+ VersionTuple Introduced,
+ VersionTuple Deprecated,
+ VersionTuple Obsoleted,
+ bool IsUnavailable,
+ StringRef Message,
+ AvailabilityMergeKind AMK,
+ unsigned AttrSpellingListIndex);
+ TypeVisibilityAttr *mergeTypeVisibilityAttr(Decl *D, SourceRange Range,
+ TypeVisibilityAttr::VisibilityType Vis,
+ unsigned AttrSpellingListIndex);
+ VisibilityAttr *mergeVisibilityAttr(Decl *D, SourceRange Range,
+ VisibilityAttr::VisibilityType Vis,
+ unsigned AttrSpellingListIndex);
+ DLLImportAttr *mergeDLLImportAttr(Decl *D, SourceRange Range,
+ unsigned AttrSpellingListIndex);
+ DLLExportAttr *mergeDLLExportAttr(Decl *D, SourceRange Range,
+ unsigned AttrSpellingListIndex);
+ MSInheritanceAttr *
+ mergeMSInheritanceAttr(Decl *D, SourceRange Range, bool BestCase,
+ unsigned AttrSpellingListIndex,
+ MSInheritanceAttr::Spelling SemanticSpelling);
+ FormatAttr *mergeFormatAttr(Decl *D, SourceRange Range,
+ IdentifierInfo *Format, int FormatIdx,
+ int FirstArg, unsigned AttrSpellingListIndex);
+ SectionAttr *mergeSectionAttr(Decl *D, SourceRange Range, StringRef Name,
+ unsigned AttrSpellingListIndex);
+ AlwaysInlineAttr *mergeAlwaysInlineAttr(Decl *D, SourceRange Range,
+ IdentifierInfo *Ident,
+ unsigned AttrSpellingListIndex);
+ MinSizeAttr *mergeMinSizeAttr(Decl *D, SourceRange Range,
+ unsigned AttrSpellingListIndex);
+ OptimizeNoneAttr *mergeOptimizeNoneAttr(Decl *D, SourceRange Range,
+ unsigned AttrSpellingListIndex);
+ InternalLinkageAttr *mergeInternalLinkageAttr(Decl *D, SourceRange Range,
+ IdentifierInfo *Ident,
+ unsigned AttrSpellingListIndex);
+ CommonAttr *mergeCommonAttr(Decl *D, SourceRange Range, IdentifierInfo *Ident,
+ unsigned AttrSpellingListIndex);
+
+ void mergeDeclAttributes(NamedDecl *New, Decl *Old,
+ AvailabilityMergeKind AMK = AMK_Redeclaration);
+ void MergeTypedefNameDecl(Scope *S, TypedefNameDecl *New,
+ LookupResult &OldDecls);
+ bool MergeFunctionDecl(FunctionDecl *New, NamedDecl *&Old, Scope *S,
+ bool MergeTypeWithOld);
+ bool MergeCompatibleFunctionDecls(FunctionDecl *New, FunctionDecl *Old,
+ Scope *S, bool MergeTypeWithOld);
+ void mergeObjCMethodDecls(ObjCMethodDecl *New, ObjCMethodDecl *Old);
+ void MergeVarDecl(VarDecl *New, LookupResult &Previous);
+ void MergeVarDeclTypes(VarDecl *New, VarDecl *Old, bool MergeTypeWithOld);
+ void MergeVarDeclExceptionSpecs(VarDecl *New, VarDecl *Old);
+ bool MergeCXXFunctionDecl(FunctionDecl *New, FunctionDecl *Old, Scope *S);
+
+ // 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,
+ AA_Passing_CFAudited
+ };
+
+ /// 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);
+
+ /// \brief Checks availability of the function depending on the current
+ /// function context.Inside an unavailable function,unavailability is ignored.
+ ///
+ /// \returns true if \p FD is unavailable and current context is inside
+ /// an available function, false otherwise.
+ bool isFunctionConsideredUnavailable(FunctionDecl *FD);
+
+ ImplicitConversionSequence
+ TryImplicitConversion(Expr *From, QualType ToType,
+ bool SuppressUserConversions,
+ bool AllowExplicit,
+ bool InOverloadResolution,
+ bool CStyle,
+ bool AllowObjCWritebackConversion);
+
+ 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 isObjCWritebackConversion(QualType FromType, QualType ToType,
+ QualType &ConvertedType);
+ bool IsBlockPointerConversion(QualType FromType, QualType ToType,
+ QualType& ConvertedType);
+ bool FunctionParamTypesAreEqual(const FunctionProtoType *OldType,
+ const FunctionProtoType *NewType,
+ unsigned *ArgPos = nullptr);
+ void HandleFunctionTypeMismatch(PartialDiagnostic &PDiag,
+ QualType FromType, QualType ToType);
+
+ void maybeExtendBlockObject(ExprResult &E);
+ CastKind PrepareCastToObjCObjectPointer(ExprResult &E);
+ 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 &ObjCLifetimeConversion);
+ bool IsNoReturnConversion(QualType FromType, QualType ToType,
+ QualType &ResultTy);
+ bool DiagnoseMultipleUserDefinedConversion(Expr *From, QualType ToType);
+ bool isSameOrCompatibleFunctionType(CanQualType Param, CanQualType Arg);
+
+ ExprResult PerformMoveOrCopyInitialization(const InitializedEntity &Entity,
+ const VarDecl *NRVOCandidate,
+ QualType ResultType,
+ Expr *Value,
+ bool AllowNRVO = true);
+
+ bool CanPerformCopyInitialization(const InitializedEntity &Entity,
+ ExprResult Init);
+ ExprResult PerformCopyInitialization(const InitializedEntity &Entity,
+ SourceLocation EqualLoc,
+ ExprResult Init,
+ bool TopLevelOfInitList = false,
+ bool AllowExplicit = false);
+ ExprResult PerformObjectArgumentInitialization(Expr *From,
+ NestedNameSpecifier *Qualifier,
+ NamedDecl *FoundDecl,
+ CXXMethodDecl *Method);
+
+ ExprResult PerformContextuallyConvertToBool(Expr *From);
+ ExprResult PerformContextuallyConvertToObjCPointer(Expr *From);
+
+ /// Contexts in which a converted constant expression is required.
+ enum CCEKind {
+ CCEK_CaseValue, ///< Expression in a case label.
+ CCEK_Enumerator, ///< Enumerator value with fixed underlying type.
+ CCEK_TemplateArg, ///< Value of a non-type template parameter.
+ CCEK_NewExpr ///< Constant expression in a noptr-new-declarator.
+ };
+ ExprResult CheckConvertedConstantExpression(Expr *From, QualType T,
+ llvm::APSInt &Value, CCEKind CCE);
+ ExprResult CheckConvertedConstantExpression(Expr *From, QualType T,
+ APValue &Value, CCEKind CCE);
+
+ /// \brief Abstract base class used to perform a contextual implicit
+ /// conversion from an expression to any type passing a filter.
+ class ContextualImplicitConverter {
+ public:
+ bool Suppress;
+ bool SuppressConversion;
+
+ ContextualImplicitConverter(bool Suppress = false,
+ bool SuppressConversion = false)
+ : Suppress(Suppress), SuppressConversion(SuppressConversion) {}
+
+ /// \brief Determine whether the specified type is a valid destination type
+ /// for this conversion.
+ virtual bool match(QualType T) = 0;
+
+ /// \brief Emits a diagnostic complaining that the expression does not have
+ /// integral or enumeration type.
+ virtual SemaDiagnosticBuilder
+ diagnoseNoMatch(Sema &S, SourceLocation Loc, QualType T) = 0;
+
+ /// \brief Emits a diagnostic when the expression has incomplete class type.
+ virtual SemaDiagnosticBuilder
+ diagnoseIncomplete(Sema &S, SourceLocation Loc, QualType T) = 0;
+
+ /// \brief Emits a diagnostic when the only matching conversion function
+ /// is explicit.
+ virtual SemaDiagnosticBuilder diagnoseExplicitConv(
+ Sema &S, SourceLocation Loc, QualType T, QualType ConvTy) = 0;
+
+ /// \brief Emits a note for the explicit conversion function.
+ virtual SemaDiagnosticBuilder
+ noteExplicitConv(Sema &S, CXXConversionDecl *Conv, QualType ConvTy) = 0;
+
+ /// \brief Emits a diagnostic when there are multiple possible conversion
+ /// functions.
+ virtual SemaDiagnosticBuilder
+ diagnoseAmbiguous(Sema &S, SourceLocation Loc, QualType T) = 0;
+
+ /// \brief Emits a note for one of the candidate conversions.
+ virtual SemaDiagnosticBuilder
+ noteAmbiguous(Sema &S, CXXConversionDecl *Conv, QualType ConvTy) = 0;
+
+ /// \brief Emits a diagnostic when we picked a conversion function
+ /// (for cases when we are not allowed to pick a conversion function).
+ virtual SemaDiagnosticBuilder diagnoseConversion(
+ Sema &S, SourceLocation Loc, QualType T, QualType ConvTy) = 0;
+
+ virtual ~ContextualImplicitConverter() {}
+ };
+
+ class ICEConvertDiagnoser : public ContextualImplicitConverter {
+ bool AllowScopedEnumerations;
+
+ public:
+ ICEConvertDiagnoser(bool AllowScopedEnumerations,
+ bool Suppress, bool SuppressConversion)
+ : ContextualImplicitConverter(Suppress, SuppressConversion),
+ AllowScopedEnumerations(AllowScopedEnumerations) {}
+
+ /// Match an integral or (possibly scoped) enumeration type.
+ bool match(QualType T) override;
+
+ SemaDiagnosticBuilder
+ diagnoseNoMatch(Sema &S, SourceLocation Loc, QualType T) override {
+ return diagnoseNotInt(S, Loc, T);
+ }
+
+ /// \brief Emits a diagnostic complaining that the expression does not have
+ /// integral or enumeration type.
+ virtual SemaDiagnosticBuilder
+ diagnoseNotInt(Sema &S, SourceLocation Loc, QualType T) = 0;
+ };
+
+ /// Perform a contextual implicit conversion.
+ ExprResult PerformContextualImplicitConversion(
+ SourceLocation Loc, Expr *FromE, ContextualImplicitConverter &Converter);
+
+
+ enum ObjCSubscriptKind {
+ OS_Array,
+ OS_Dictionary,
+ OS_Error
+ };
+ ObjCSubscriptKind CheckSubscriptingKind(Expr *FromE);
+
+ // Note that LK_String is intentionally after the other literals, as
+ // this is used for diagnostics logic.
+ enum ObjCLiteralKind {
+ LK_Array,
+ LK_Dictionary,
+ LK_Numeric,
+ LK_Boxed,
+ LK_String,
+ LK_Block,
+ LK_None
+ };
+ ObjCLiteralKind CheckLiteralKind(Expr *FromE);
+
+ ExprResult 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(FunctionDecl *Function,
+ DeclAccessPair FoundDecl,
+ ArrayRef<Expr *> Args,
+ OverloadCandidateSet& CandidateSet,
+ bool SuppressUserConversions = false,
+ bool PartialOverloading = false,
+ bool AllowExplicit = false);
+ void AddFunctionCandidates(const UnresolvedSetImpl &Functions,
+ ArrayRef<Expr *> Args,
+ OverloadCandidateSet &CandidateSet,
+ TemplateArgumentListInfo *ExplicitTemplateArgs = nullptr,
+ bool SuppressUserConversions = false,
+ bool PartialOverloading = false);
+ void AddMethodCandidate(DeclAccessPair FoundDecl,
+ QualType ObjectType,
+ Expr::Classification ObjectClassification,
+ ArrayRef<Expr *> Args,
+ OverloadCandidateSet& CandidateSet,
+ bool SuppressUserConversion = false);
+ void AddMethodCandidate(CXXMethodDecl *Method,
+ DeclAccessPair FoundDecl,
+ CXXRecordDecl *ActingContext, QualType ObjectType,
+ Expr::Classification ObjectClassification,
+ ArrayRef<Expr *> Args,
+ OverloadCandidateSet& CandidateSet,
+ bool SuppressUserConversions = false,
+ bool PartialOverloading = false);
+ void AddMethodTemplateCandidate(FunctionTemplateDecl *MethodTmpl,
+ DeclAccessPair FoundDecl,
+ CXXRecordDecl *ActingContext,
+ TemplateArgumentListInfo *ExplicitTemplateArgs,
+ QualType ObjectType,
+ Expr::Classification ObjectClassification,
+ ArrayRef<Expr *> Args,
+ OverloadCandidateSet& CandidateSet,
+ bool SuppressUserConversions = false,
+ bool PartialOverloading = false);
+ void AddTemplateOverloadCandidate(FunctionTemplateDecl *FunctionTemplate,
+ DeclAccessPair FoundDecl,
+ TemplateArgumentListInfo *ExplicitTemplateArgs,
+ ArrayRef<Expr *> Args,
+ OverloadCandidateSet& CandidateSet,
+ bool SuppressUserConversions = false,
+ bool PartialOverloading = false);
+ void AddConversionCandidate(CXXConversionDecl *Conversion,
+ DeclAccessPair FoundDecl,
+ CXXRecordDecl *ActingContext,
+ Expr *From, QualType ToType,
+ OverloadCandidateSet& CandidateSet,
+ bool AllowObjCConversionOnExplicit);
+ void AddTemplateConversionCandidate(FunctionTemplateDecl *FunctionTemplate,
+ DeclAccessPair FoundDecl,
+ CXXRecordDecl *ActingContext,
+ Expr *From, QualType ToType,
+ OverloadCandidateSet &CandidateSet,
+ bool AllowObjCConversionOnExplicit);
+ void AddSurrogateCandidate(CXXConversionDecl *Conversion,
+ DeclAccessPair FoundDecl,
+ CXXRecordDecl *ActingContext,
+ const FunctionProtoType *Proto,
+ Expr *Object, ArrayRef<Expr *> Args,
+ OverloadCandidateSet& CandidateSet);
+ void AddMemberOperatorCandidates(OverloadedOperatorKind Op,
+ SourceLocation OpLoc, ArrayRef<Expr *> Args,
+ OverloadCandidateSet& CandidateSet,
+ SourceRange OpRange = SourceRange());
+ void AddBuiltinCandidate(QualType ResultTy, QualType *ParamTys,
+ ArrayRef<Expr *> Args,
+ OverloadCandidateSet& CandidateSet,
+ bool IsAssignmentOperator = false,
+ unsigned NumContextualBoolArguments = 0);
+ void AddBuiltinOperatorCandidates(OverloadedOperatorKind Op,
+ SourceLocation OpLoc, ArrayRef<Expr *> Args,
+ OverloadCandidateSet& CandidateSet);
+ void AddArgumentDependentLookupCandidates(DeclarationName Name,
+ SourceLocation Loc,
+ ArrayRef<Expr *> Args,
+ TemplateArgumentListInfo *ExplicitTemplateArgs,
+ OverloadCandidateSet& CandidateSet,
+ bool PartialOverloading = false);
+
+ // Emit as a 'note' the specific overload candidate
+ void NoteOverloadCandidate(FunctionDecl *Fn, QualType DestType = QualType(),
+ bool TakingAddress = false);
+
+ // Emit as a series of 'note's all template and non-templates identified by
+ // the expression Expr
+ void NoteAllOverloadCandidates(Expr *E, QualType DestType = QualType(),
+ bool TakingAddress = false);
+
+ /// Check the enable_if expressions on the given function. Returns the first
+ /// failing attribute, or NULL if they were all successful.
+ EnableIfAttr *CheckEnableIf(FunctionDecl *Function, ArrayRef<Expr *> Args,
+ bool MissingImplicitThis = false);
+
+ /// Returns whether the given function's address can be taken or not,
+ /// optionally emitting a diagnostic if the address can't be taken.
+ ///
+ /// Returns false if taking the address of the function is illegal.
+ bool checkAddressOfFunctionIsAvailable(const FunctionDecl *Function,
+ bool Complain = false,
+ SourceLocation Loc = SourceLocation());
+
+ // [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,
+ bool *pHadMultipleCandidates = nullptr);
+
+ FunctionDecl *
+ ResolveSingleFunctionTemplateSpecialization(OverloadExpr *ovl,
+ bool Complain = false,
+ DeclAccessPair *Found = nullptr);
+
+ bool ResolveAndFixSingleFunctionTemplateSpecialization(
+ ExprResult &SrcExpr,
+ bool DoFunctionPointerConverion = false,
+ bool Complain = false,
+ SourceRange OpRangeForComplaining = SourceRange(),
+ QualType DestTypeForComplaining = QualType(),
+ unsigned DiagIDForComplaining = 0);
+
+
+ Expr *FixOverloadedFunctionReference(Expr *E,
+ DeclAccessPair FoundDecl,
+ FunctionDecl *Fn);
+ ExprResult FixOverloadedFunctionReference(ExprResult,
+ DeclAccessPair FoundDecl,
+ FunctionDecl *Fn);
+
+ void AddOverloadedCallCandidates(UnresolvedLookupExpr *ULE,
+ ArrayRef<Expr *> Args,
+ OverloadCandidateSet &CandidateSet,
+ bool PartialOverloading = false);
+
+ // An enum used to represent the different possible results of building a
+ // range-based for loop.
+ enum ForRangeStatus {
+ FRS_Success,
+ FRS_NoViableFunction,
+ FRS_DiagnosticIssued
+ };
+
+ ForRangeStatus BuildForRangeBeginEndCall(SourceLocation Loc,
+ SourceLocation RangeLoc,
+ const DeclarationNameInfo &NameInfo,
+ LookupResult &MemberLookup,
+ OverloadCandidateSet *CandidateSet,
+ Expr *Range, ExprResult *CallExpr);
+
+ ExprResult BuildOverloadedCallExpr(Scope *S, Expr *Fn,
+ UnresolvedLookupExpr *ULE,
+ SourceLocation LParenLoc,
+ MultiExprArg Args,
+ SourceLocation RParenLoc,
+ Expr *ExecConfig,
+ bool AllowTypoCorrection=true);
+
+ bool buildOverloadedCallSet(Scope *S, Expr *Fn, UnresolvedLookupExpr *ULE,
+ MultiExprArg Args, SourceLocation RParenLoc,
+ OverloadCandidateSet *CandidateSet,
+ ExprResult *Result);
+
+ ExprResult CreateOverloadedUnaryOp(SourceLocation OpLoc,
+ UnaryOperatorKind Opc,
+ const UnresolvedSetImpl &Fns,
+ Expr *input);
+
+ ExprResult CreateOverloadedBinOp(SourceLocation OpLoc,
+ BinaryOperatorKind 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,
+ MultiExprArg Args,
+ SourceLocation RParenLoc);
+ ExprResult
+ BuildCallToObjectOfClassType(Scope *S, Expr *Object, SourceLocation LParenLoc,
+ MultiExprArg Args,
+ SourceLocation RParenLoc);
+
+ ExprResult BuildOverloadedArrowExpr(Scope *S, Expr *Base,
+ SourceLocation OpLoc,
+ bool *NoArrowOperatorFound = nullptr);
+
+ /// 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 *const *Param,
+ ParmVarDecl *const *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 a friend of a local class. This lookup does not look
+ /// outside the innermost non-class scope. See C++11 [class.friend]p11.
+ LookupLocalFriendName,
+ /// Look up the name of an Objective-C protocol.
+ LookupObjCProtocolName,
+ /// Look up implicit 'self' parameter of an objective-c method.
+ LookupObjCImplicitSelfParam,
+ /// \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
+ };
+
+ /// \brief The possible outcomes of name lookup for a literal operator.
+ enum LiteralOperatorLookupResult {
+ /// \brief The lookup resulted in an error.
+ LOLR_Error,
+ /// \brief The lookup found a single 'cooked' literal operator, which
+ /// expects a normal literal to be built and passed to it.
+ LOLR_Cooked,
+ /// \brief The lookup found a single 'raw' literal operator, which expects
+ /// a string literal containing the spelling of the literal token.
+ LOLR_Raw,
+ /// \brief The lookup found an overload set of literal operator templates,
+ /// which expect the characters of the spelling of the literal token to be
+ /// passed as a non-type template argument pack.
+ LOLR_Template,
+ /// \brief The lookup found an overload set of literal operator templates,
+ /// which expect the character type and characters of the spelling of the
+ /// string literal token to be passed as template arguments.
+ LOLR_StringTemplate
+ };
+
+ SpecialMemberOverloadResult *LookupSpecialMember(CXXRecordDecl *D,
+ CXXSpecialMember SM,
+ bool ConstArg,
+ bool VolatileArg,
+ bool RValueThis,
+ bool ConstThis,
+ bool VolatileThis);
+
+ typedef std::function<void(const TypoCorrection &)> TypoDiagnosticGenerator;
+ typedef std::function<ExprResult(Sema &, TypoExpr *, TypoCorrection)>
+ TypoRecoveryCallback;
+
+private:
+ bool CppLookupName(LookupResult &R, Scope *S);
+
+ struct TypoExprState {
+ std::unique_ptr<TypoCorrectionConsumer> Consumer;
+ TypoDiagnosticGenerator DiagHandler;
+ TypoRecoveryCallback RecoveryHandler;
+ TypoExprState();
+ TypoExprState(TypoExprState&& other) LLVM_NOEXCEPT;
+ TypoExprState& operator=(TypoExprState&& other) LLVM_NOEXCEPT;
+ };
+
+ /// \brief The set of unhandled TypoExprs and their associated state.
+ llvm::MapVector<TypoExpr *, TypoExprState> DelayedTypos;
+
+ /// \brief Creates a new TypoExpr AST node.
+ TypoExpr *createDelayedTypo(std::unique_ptr<TypoCorrectionConsumer> TCC,
+ TypoDiagnosticGenerator TDG,
+ TypoRecoveryCallback TRC);
+
+ // \brief The set of known/encountered (unique, canonicalized) NamespaceDecls.
+ //
+ // The boolean value will be true to indicate that the namespace was loaded
+ // from an AST/PCH file, or false otherwise.
+ llvm::MapVector<NamespaceDecl*, bool> KnownNamespaces;
+
+ /// \brief Whether we have already loaded known namespaces from an extenal
+ /// source.
+ bool LoadedExternalKnownNamespaces;
+
+ /// \brief Helper for CorrectTypo and CorrectTypoDelayed used to create and
+ /// populate a new TypoCorrectionConsumer. Returns nullptr if typo correction
+ /// should be skipped entirely.
+ std::unique_ptr<TypoCorrectionConsumer>
+ makeTypoCorrectionConsumer(const DeclarationNameInfo &Typo,
+ Sema::LookupNameKind LookupKind, Scope *S,
+ CXXScopeSpec *SS,
+ std::unique_ptr<CorrectionCandidateCallback> CCC,
+ DeclContext *MemberContext, bool EnteringContext,
+ const ObjCObjectPointerType *OPT,
+ bool ErrorRecovery);
+
+public:
+ const TypoExprState &getTypoExprState(TypoExpr *TE) const;
+
+ /// \brief Clears the state of the given TypoExpr.
+ void clearDelayedTypo(TypoExpr *TE);
+
+ /// \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 LookupQualifiedName(LookupResult &R, DeclContext *LookupCtx,
+ CXXScopeSpec &SS);
+ bool LookupParsedName(LookupResult &R, Scope *S, CXXScopeSpec *SS,
+ bool AllowBuiltinCreation = false,
+ bool EnteringContext = false);
+ ObjCProtocolDecl *LookupProtocol(IdentifierInfo *II, SourceLocation IdLoc,
+ RedeclarationKind Redecl
+ = NotForRedeclaration);
+ bool LookupInSuper(LookupResult &R, CXXRecordDecl *Class);
+
+ void LookupOverloadedOperatorName(OverloadedOperatorKind Op, Scope *S,
+ QualType T1, QualType T2,
+ UnresolvedSetImpl &Functions);
+ void addOverloadedOperatorToUnresolvedSet(UnresolvedSetImpl &Functions,
+ DeclAccessPair Operator,
+ QualType T1, QualType T2);
+
+ LabelDecl *LookupOrCreateLabel(IdentifierInfo *II, SourceLocation IdentLoc,
+ SourceLocation GnuLabelLoc = SourceLocation());
+
+ DeclContextLookupResult LookupConstructors(CXXRecordDecl *Class);
+ CXXConstructorDecl *LookupDefaultConstructor(CXXRecordDecl *Class);
+ CXXConstructorDecl *LookupCopyingConstructor(CXXRecordDecl *Class,
+ unsigned Quals);
+ CXXMethodDecl *LookupCopyingAssignment(CXXRecordDecl *Class, unsigned Quals,
+ bool RValueThis, unsigned ThisQuals);
+ CXXConstructorDecl *LookupMovingConstructor(CXXRecordDecl *Class,
+ unsigned Quals);
+ CXXMethodDecl *LookupMovingAssignment(CXXRecordDecl *Class, unsigned Quals,
+ bool RValueThis, unsigned ThisQuals);
+ CXXDestructorDecl *LookupDestructor(CXXRecordDecl *Class);
+
+ bool checkLiteralOperatorId(const CXXScopeSpec &SS, const UnqualifiedId &Id);
+ LiteralOperatorLookupResult LookupLiteralOperator(Scope *S, LookupResult &R,
+ ArrayRef<QualType> ArgTys,
+ bool AllowRaw,
+ bool AllowTemplate,
+ bool AllowStringTemplate);
+ bool isKnownName(StringRef name);
+
+ void ArgumentDependentLookup(DeclarationName Name, SourceLocation Loc,
+ ArrayRef<Expr *> Args, ADLResult &Functions);
+
+ void LookupVisibleDecls(Scope *S, LookupNameKind Kind,
+ VisibleDeclConsumer &Consumer,
+ bool IncludeGlobalScope = true);
+ void LookupVisibleDecls(DeclContext *Ctx, LookupNameKind Kind,
+ VisibleDeclConsumer &Consumer,
+ bool IncludeGlobalScope = true);
+
+ enum CorrectTypoKind {
+ CTK_NonError, // CorrectTypo used in a non error recovery situation.
+ CTK_ErrorRecovery // CorrectTypo used in normal error recovery.
+ };
+
+ TypoCorrection CorrectTypo(const DeclarationNameInfo &Typo,
+ Sema::LookupNameKind LookupKind,
+ Scope *S, CXXScopeSpec *SS,
+ std::unique_ptr<CorrectionCandidateCallback> CCC,
+ CorrectTypoKind Mode,
+ DeclContext *MemberContext = nullptr,
+ bool EnteringContext = false,
+ const ObjCObjectPointerType *OPT = nullptr,
+ bool RecordFailure = true);
+
+ TypoExpr *CorrectTypoDelayed(const DeclarationNameInfo &Typo,
+ Sema::LookupNameKind LookupKind, Scope *S,
+ CXXScopeSpec *SS,
+ std::unique_ptr<CorrectionCandidateCallback> CCC,
+ TypoDiagnosticGenerator TDG,
+ TypoRecoveryCallback TRC, CorrectTypoKind Mode,
+ DeclContext *MemberContext = nullptr,
+ bool EnteringContext = false,
+ const ObjCObjectPointerType *OPT = nullptr);
+
+ /// \brief Process any TypoExprs in the given Expr and its children,
+ /// generating diagnostics as appropriate and returning a new Expr if there
+ /// were typos that were all successfully corrected and ExprError if one or
+ /// more typos could not be corrected.
+ ///
+ /// \param E The Expr to check for TypoExprs.
+ ///
+ /// \param InitDecl A VarDecl to avoid because the Expr being corrected is its
+ /// initializer.
+ ///
+ /// \param Filter A function applied to a newly rebuilt Expr to determine if
+ /// it is an acceptable/usable result from a single combination of typo
+ /// corrections. As long as the filter returns ExprError, different
+ /// combinations of corrections will be tried until all are exhausted.
+ ExprResult
+ CorrectDelayedTyposInExpr(Expr *E, VarDecl *InitDecl = nullptr,
+ llvm::function_ref<ExprResult(Expr *)> Filter =
+ [](Expr *E) -> ExprResult { return E; });
+
+ ExprResult
+ CorrectDelayedTyposInExpr(Expr *E,
+ llvm::function_ref<ExprResult(Expr *)> Filter) {
+ return CorrectDelayedTyposInExpr(E, nullptr, Filter);
+ }
+
+ ExprResult
+ CorrectDelayedTyposInExpr(ExprResult ER, VarDecl *InitDecl = nullptr,
+ llvm::function_ref<ExprResult(Expr *)> Filter =
+ [](Expr *E) -> ExprResult { return E; }) {
+ return ER.isInvalid() ? ER : CorrectDelayedTyposInExpr(ER.get(), Filter);
+ }
+
+ ExprResult
+ CorrectDelayedTyposInExpr(ExprResult ER,
+ llvm::function_ref<ExprResult(Expr *)> Filter) {
+ return CorrectDelayedTyposInExpr(ER, nullptr, Filter);
+ }
+
+ void diagnoseTypo(const TypoCorrection &Correction,
+ const PartialDiagnostic &TypoDiag,
+ bool ErrorRecovery = true);
+
+ void diagnoseTypo(const TypoCorrection &Correction,
+ const PartialDiagnostic &TypoDiag,
+ const PartialDiagnostic &PrevNote,
+ bool ErrorRecovery = true);
+
+ void FindAssociatedClassesAndNamespaces(SourceLocation InstantiationLoc,
+ ArrayRef<Expr *> Args,
+ AssociatedNamespaceSet &AssociatedNamespaces,
+ AssociatedClassSet &AssociatedClasses);
+
+ void FilterLookupForScope(LookupResult &R, DeclContext *Ctx, Scope *S,
+ bool ConsiderLinkage, bool AllowInlineNamespace);
+
+ void 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.
+
+ void ProcessPragmaWeak(Scope *S, Decl *D);
+ // Decl attributes - this routine is the top level dispatcher.
+ void ProcessDeclAttributes(Scope *S, Decl *D, const Declarator &PD);
+ void ProcessDeclAttributeList(Scope *S, Decl *D, const AttributeList *AL,
+ bool IncludeCXX11Attributes = true);
+ bool ProcessAccessDeclAttributeList(AccessSpecDecl *ASDecl,
+ const AttributeList *AttrList);
+
+ void checkUnusedDeclAttributes(Declarator &D);
+
+ /// Determine if type T is a valid subject for a nonnull and similar
+ /// attributes. By default, we look through references (the behavior used by
+ /// nonnull), but if the second parameter is true, then we treat a reference
+ /// type as valid.
+ bool isValidPointerAttrType(QualType T, bool RefOkay = false);
+
+ bool CheckRegparmAttr(const AttributeList &attr, unsigned &value);
+ bool CheckCallingConvAttr(const AttributeList &attr, CallingConv &CC,
+ const FunctionDecl *FD = nullptr);
+ bool CheckNoReturnAttr(const AttributeList &attr);
+ bool checkStringLiteralArgumentAttr(const AttributeList &Attr,
+ unsigned ArgNum, StringRef &Str,
+ SourceLocation *ArgLocation = nullptr);
+ bool checkSectionName(SourceLocation LiteralLoc, StringRef Str);
+ void checkTargetAttr(SourceLocation LiteralLoc, StringRef Str);
+ bool checkMSInheritanceAttrOnDefinition(
+ CXXRecordDecl *RD, SourceRange Range, bool BestCase,
+ MSInheritanceAttr::Spelling SemanticSpelling);
+
+ void CheckAlignasUnderalignment(Decl *D);
+
+ /// Adjust the calling convention of a method to be the ABI default if it
+ /// wasn't specified explicitly. This handles method types formed from
+ /// function type typedefs and typename template arguments.
+ void adjustMemberFunctionCC(QualType &T, bool IsStatic, bool IsCtorOrDtor,
+ SourceLocation Loc);
+
+ // Check if there is an explicit attribute, but only look through parens.
+ // The intent is to look for an attribute on the current declarator, but not
+ // one that came from a typedef.
+ bool hasExplicitCallingConv(QualType &T);
+
+ /// Get the outermost AttributedType node that sets a calling convention.
+ /// Valid types should not have multiple attributes with different CCs.
+ const AttributedType *getCallingConvAttributedType(QualType T) const;
+
+ /// Check whether a nullability type specifier can be added to the given
+ /// type.
+ ///
+ /// \param type The type to which the nullability specifier will be
+ /// added. On success, this type will be updated appropriately.
+ ///
+ /// \param nullability The nullability specifier to add.
+ ///
+ /// \param nullabilityLoc The location of the nullability specifier.
+ ///
+ /// \param isContextSensitive Whether this nullability specifier was
+ /// written as a context-sensitive keyword (in an Objective-C
+ /// method) or an Objective-C property attribute, rather than as an
+ /// underscored type specifier.
+ ///
+ /// \returns true if nullability cannot be applied, false otherwise.
+ bool checkNullabilityTypeSpecifier(QualType &type, NullabilityKind nullability,
+ SourceLocation nullabilityLoc,
+ bool isContextSensitive);
+
+ /// \brief Stmt attributes - this routine is the top level dispatcher.
+ StmtResult ProcessStmtAttributes(Stmt *Stmt, AttributeList *Attrs,
+ SourceRange Range);
+
+ void WarnConflictingTypedMethods(ObjCMethodDecl *Method,
+ ObjCMethodDecl *MethodDecl,
+ bool IsProtocolMethodDecl);
+
+ void CheckConflictingOverridingMethod(ObjCMethodDecl *Method,
+ ObjCMethodDecl *Overridden,
+ bool IsProtocolMethodDecl);
+
+ /// WarnExactTypedMethods - This routine issues a warning if method
+ /// implementation declaration matches exactly that of its declaration.
+ void WarnExactTypedMethods(ObjCMethodDecl *Method,
+ ObjCMethodDecl *MethodDecl,
+ bool IsProtocolMethodDecl);
+
+ typedef llvm::SmallPtrSet<Selector, 8> SelectorSet;
+ typedef llvm::DenseMap<Selector, ObjCMethodDecl*> ProtocolsMethodsMap;
+
+ /// 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);
+
+ /// 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,
+ bool SynthesizeProperties);
+
+ /// Diagnose any null-resettable synthesized setters.
+ void diagnoseNullResettableSynthesizedSetters(const ObjCImplDecl *impDecl);
+
+ /// DefaultSynthesizeProperties - This routine default synthesizes all
+ /// properties which must be synthesized in the class's \@implementation.
+ void DefaultSynthesizeProperties (Scope *S, ObjCImplDecl* IMPDecl,
+ ObjCInterfaceDecl *IDecl);
+ void DefaultSynthesizeProperties(Scope *S, Decl *D);
+
+ /// IvarBacksCurrentMethodAccessor - This routine returns 'true' if 'IV' is
+ /// an ivar synthesized for 'Method' and 'Method' is a property accessor
+ /// declared in class 'IFace'.
+ bool IvarBacksCurrentMethodAccessor(ObjCInterfaceDecl *IFace,
+ ObjCMethodDecl *Method, ObjCIvarDecl *IV);
+
+ /// DiagnoseUnusedBackingIvarInAccessor - Issue an 'unused' warning if ivar which
+ /// backs the property is not used in the property's accessor.
+ void DiagnoseUnusedBackingIvarInAccessor(Scope *S,
+ const ObjCImplementationDecl *ImplD);
+
+ /// GetIvarBackingPropertyAccessor - If method is a property setter/getter and
+ /// it property has a backing ivar, returns this ivar; otherwise, returns NULL.
+ /// It also returns ivar's property on success.
+ ObjCIvarDecl *GetIvarBackingPropertyAccessor(const ObjCMethodDecl *Method,
+ const ObjCPropertyDecl *&PDecl) const;
+
+ /// Called by ActOnProperty to handle \@property declarations in
+ /// class extensions.
+ ObjCPropertyDecl *HandlePropertyInClassExtension(Scope *S,
+ SourceLocation AtLoc,
+ SourceLocation LParenLoc,
+ FieldDeclarator &FD,
+ Selector GetterSel,
+ Selector SetterSel,
+ const bool isReadWrite,
+ unsigned &Attributes,
+ const unsigned AttributesAsWritten,
+ QualType T,
+ TypeSourceInfo *TSI,
+ 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,
+ SourceLocation LParenLoc,
+ FieldDeclarator &FD,
+ Selector GetterSel,
+ Selector SetterSel,
+ const bool isReadWrite,
+ const unsigned Attributes,
+ const unsigned AttributesAsWritten,
+ QualType T,
+ TypeSourceInfo *TSI,
+ tok::ObjCKeywordKind MethodImplKind,
+ DeclContext *lexicalDC = nullptr);
+
+ /// 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,
+ ObjCInterfaceDecl* IDecl);
+
+ void DiagnoseOwningPropertyGetterSynthesis(const ObjCImplementationDecl *D);
+
+ void DiagnoseMissingDesignatedInitOverrides(
+ const ObjCImplementationDecl *ImplD,
+ const ObjCInterfaceDecl *IFD);
+
+ void DiagnoseDuplicateIvars(ObjCInterfaceDecl *ID, ObjCInterfaceDecl *SID);
+
+ enum MethodMatchStrategy {
+ MMS_loose,
+ MMS_strict
+ };
+
+ /// MatchTwoMethodDeclarations - Checks if two methods' type match and returns
+ /// true, or false, accordingly.
+ bool MatchTwoMethodDeclarations(const ObjCMethodDecl *Method,
+ const ObjCMethodDecl *PrevMethod,
+ MethodMatchStrategy strategy = MMS_strict);
+
+ /// 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,
+ bool WarnCategoryMethodImpl=false);
+
+ /// CheckCategoryVsClassMethodMatches - Checks that methods implemented in
+ /// category matches with those implemented in its primary class and
+ /// warns each time an exact match is found.
+ void CheckCategoryVsClassMethodMatches(ObjCCategoryImplDecl *CatIMP);
+
+ /// \brief Add the given method to the list of globally-known methods.
+ void addMethodToGlobalList(ObjCMethodList *List, ObjCMethodDecl *Method);
+
+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 instance);
+
+public:
+ /// \brief - Returns instance or factory methods in global method pool for
+ /// given selector. If no such method or only one method found, function returns
+ /// false; otherwise, it returns true
+ bool CollectMultipleMethodsInGlobalPool(Selector Sel,
+ SmallVectorImpl<ObjCMethodDecl*>& Methods,
+ bool instance);
+
+ bool AreMultipleMethodsInGlobalPool(Selector Sel, ObjCMethodDecl *BestMethod,
+ SourceRange R,
+ bool receiverIdOrClass);
+
+ void DiagnoseMultipleMethodInGlobalPool(SmallVectorImpl<ObjCMethodDecl*> &Methods,
+ Selector Sel, SourceRange R,
+ bool receiverIdOrClass);
+
+private:
+ /// \brief - Returns a selector which best matches given argument list or
+ /// nullptr if none could be found
+ ObjCMethodDecl *SelectBestMethod(Selector Sel, MultiExprArg Args,
+ bool IsInstance);
+
+
+ /// \brief Record the typo correction failure and return an empty correction.
+ TypoCorrection FailedCorrection(IdentifierInfo *Typo, SourceLocation TypoLoc,
+ bool RecordFailure = true) {
+ if (RecordFailure)
+ TypoCorrectionFailures[Typo].insert(TypoLoc);
+ return TypoCorrection();
+ }
+
+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);
+ }
+
+ /// AddAnyMethodToGlobalPool - Add any method, instance or factory to global
+ /// pool.
+ void AddAnyMethodToGlobalPool(Decl *D);
+
+ /// LookupInstanceMethodInGlobalPool - Returns the method and warns if
+ /// there are multiple signatures.
+ ObjCMethodDecl *LookupInstanceMethodInGlobalPool(Selector Sel, SourceRange R,
+ bool receiverIdOrClass=false) {
+ return LookupMethodInGlobalPool(Sel, R, receiverIdOrClass,
+ /*instance*/true);
+ }
+
+ /// LookupFactoryMethodInGlobalPool - Returns the method and warns if
+ /// there are multiple signatures.
+ ObjCMethodDecl *LookupFactoryMethodInGlobalPool(Selector Sel, SourceRange R,
+ bool receiverIdOrClass=false) {
+ return LookupMethodInGlobalPool(Sel, R, receiverIdOrClass,
+ /*instance*/false);
+ }
+
+ const ObjCMethodDecl *SelectorsForTypoCorrection(Selector Sel,
+ QualType ObjectType=QualType());
+ /// LookupImplementedMethodInGlobalPool - Returns the method which has an
+ /// implementation.
+ ObjCMethodDecl *LookupImplementedMethodInGlobalPool(Selector Sel);
+
+ /// CollectIvarsToConstructOrDestruct - Collect those ivars which require
+ /// initialization.
+ void CollectIvarsToConstructOrDestruct(ObjCInterfaceDecl *OI,
+ SmallVectorImpl<ObjCIvarDecl*> &Ivars);
+
+ //===--------------------------------------------------------------------===//
+ // Statement Parsing Callbacks: SemaStmt.cpp.
+public:
+ class FullExprArg {
+ public:
+ FullExprArg(Sema &actions) : E(nullptr) { }
+
+ ExprResult release() {
+ return 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 MakeFullExpr(Arg, Arg ? Arg->getExprLoc() : SourceLocation());
+ }
+ FullExprArg MakeFullExpr(Expr *Arg, SourceLocation CC) {
+ return FullExprArg(ActOnFinishFullExpr(Arg, CC).get());
+ }
+ FullExprArg MakeFullDiscardedValueExpr(Expr *Arg) {
+ ExprResult FE =
+ ActOnFinishFullExpr(Arg, Arg ? Arg->getExprLoc() : SourceLocation(),
+ /*DiscardedValue*/ true);
+ return FullExprArg(FE.get());
+ }
+
+ StmtResult ActOnExprStmt(ExprResult Arg);
+ StmtResult ActOnExprStmtError();
+
+ StmtResult ActOnNullStmt(SourceLocation SemiLoc,
+ bool HasLeadingEmptyMacro = false);
+
+ void ActOnStartOfCompoundStmt();
+ void ActOnFinishOfCompoundStmt();
+ StmtResult ActOnCompoundStmt(SourceLocation L, SourceLocation R,
+ ArrayRef<Stmt *> Elts, bool isStmtExpr);
+
+ /// \brief A RAII object to enter scope of a compound statement.
+ class CompoundScopeRAII {
+ public:
+ CompoundScopeRAII(Sema &S): S(S) {
+ S.ActOnStartOfCompoundStmt();
+ }
+
+ ~CompoundScopeRAII() {
+ S.ActOnFinishOfCompoundStmt();
+ }
+
+ private:
+ Sema &S;
+ };
+
+ /// An RAII helper that pops function a function scope on exit.
+ struct FunctionScopeRAII {
+ Sema &S;
+ bool Active;
+ FunctionScopeRAII(Sema &S) : S(S), Active(true) {}
+ ~FunctionScopeRAII() {
+ if (Active)
+ S.PopFunctionScopeInfo();
+ }
+ void disable() { Active = false; }
+ };
+
+ 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 ActOnAttributedStmt(SourceLocation AttrLoc,
+ ArrayRef<const Attr*> Attrs,
+ 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);
+ ExprResult CheckObjCForCollectionOperand(SourceLocation forLoc,
+ Expr *collection);
+ StmtResult ActOnObjCForCollectionStmt(SourceLocation ForColLoc,
+ Stmt *First, Expr *collection,
+ SourceLocation RParenLoc);
+ StmtResult FinishObjCForCollectionStmt(Stmt *ForCollection, Stmt *Body);
+
+ enum BuildForRangeKind {
+ /// Initial building of a for-range statement.
+ BFRK_Build,
+ /// Instantiation or recovery rebuild of a for-range statement. Don't
+ /// attempt any typo-correction.
+ BFRK_Rebuild,
+ /// Determining whether a for-range statement could be built. Avoid any
+ /// unnecessary or irreversible actions.
+ BFRK_Check
+ };
+
+ StmtResult ActOnCXXForRangeStmt(Scope *S, SourceLocation ForLoc,
+ SourceLocation CoawaitLoc,
+ Stmt *LoopVar,
+ SourceLocation ColonLoc, Expr *Collection,
+ SourceLocation RParenLoc,
+ BuildForRangeKind Kind);
+ StmtResult BuildCXXForRangeStmt(SourceLocation ForLoc,
+ SourceLocation CoawaitLoc,
+ SourceLocation ColonLoc,
+ Stmt *RangeDecl, Stmt *BeginEndDecl,
+ Expr *Cond, Expr *Inc,
+ Stmt *LoopVarDecl,
+ SourceLocation RParenLoc,
+ BuildForRangeKind Kind);
+ StmtResult FinishCXXForRangeStmt(Stmt *ForRange, 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 BreakLoc, Scope *CurScope);
+
+ void ActOnCapturedRegionStart(SourceLocation Loc, Scope *CurScope,
+ CapturedRegionKind Kind, unsigned NumParams);
+ typedef std::pair<StringRef, QualType> CapturedParamNameType;
+ void ActOnCapturedRegionStart(SourceLocation Loc, Scope *CurScope,
+ CapturedRegionKind Kind,
+ ArrayRef<CapturedParamNameType> Params);
+ StmtResult ActOnCapturedRegionEnd(Stmt *S);
+ void ActOnCapturedRegionError();
+ RecordDecl *CreateCapturedStmtRecordDecl(CapturedDecl *&CD,
+ SourceLocation Loc,
+ unsigned NumParams);
+ VarDecl *getCopyElisionCandidate(QualType ReturnType, Expr *E,
+ bool AllowFunctionParameters);
+ bool isCopyElisionCandidate(QualType ReturnType, const VarDecl *VD,
+ bool AllowFunctionParameters);
+
+ StmtResult ActOnReturnStmt(SourceLocation ReturnLoc, Expr *RetValExp,
+ Scope *CurScope);
+ StmtResult BuildReturnStmt(SourceLocation ReturnLoc, Expr *RetValExp);
+ StmtResult ActOnCapScopeReturnStmt(SourceLocation ReturnLoc, Expr *RetValExp);
+
+ StmtResult ActOnGCCAsmStmt(SourceLocation AsmLoc, bool IsSimple,
+ bool IsVolatile, unsigned NumOutputs,
+ unsigned NumInputs, IdentifierInfo **Names,
+ MultiExprArg Constraints, MultiExprArg Exprs,
+ Expr *AsmString, MultiExprArg Clobbers,
+ SourceLocation RParenLoc);
+
+ ExprResult LookupInlineAsmIdentifier(CXXScopeSpec &SS,
+ SourceLocation TemplateKWLoc,
+ UnqualifiedId &Id,
+ llvm::InlineAsmIdentifierInfo &Info,
+ bool IsUnevaluatedContext);
+ bool LookupInlineAsmField(StringRef Base, StringRef Member,
+ unsigned &Offset, SourceLocation AsmLoc);
+ ExprResult LookupInlineAsmVarDeclField(Expr *RefExpr, StringRef Member,
+ llvm::InlineAsmIdentifierInfo &Info,
+ SourceLocation AsmLoc);
+ StmtResult ActOnMSAsmStmt(SourceLocation AsmLoc, SourceLocation LBraceLoc,
+ ArrayRef<Token> AsmToks,
+ StringRef AsmString,
+ unsigned NumOutputs, unsigned NumInputs,
+ ArrayRef<StringRef> Constraints,
+ ArrayRef<StringRef> Clobbers,
+ ArrayRef<Expr*> Exprs,
+ SourceLocation EndLoc);
+ LabelDecl *GetOrCreateMSAsmLabel(StringRef ExternalLabelName,
+ SourceLocation Location,
+ bool AlwaysCreate);
+
+ VarDecl *BuildObjCExceptionDecl(TypeSourceInfo *TInfo, QualType ExceptionType,
+ SourceLocation StartLoc,
+ SourceLocation IdLoc, IdentifierInfo *Id,
+ 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);
+ ExprResult ActOnObjCAtSynchronizedOperand(SourceLocation atLoc,
+ Expr *operand);
+ StmtResult ActOnObjCAtSynchronizedStmt(SourceLocation AtLoc,
+ Expr *SynchExpr,
+ Stmt *SynchBody);
+
+ StmtResult ActOnObjCAutoreleasePoolStmt(SourceLocation AtLoc, Stmt *Body);
+
+ VarDecl *BuildExceptionDeclaration(Scope *S, TypeSourceInfo *TInfo,
+ SourceLocation StartLoc,
+ SourceLocation IdLoc,
+ IdentifierInfo *Id);
+
+ Decl *ActOnExceptionDeclarator(Scope *S, Declarator &D);
+
+ StmtResult ActOnCXXCatchBlock(SourceLocation CatchLoc,
+ Decl *ExDecl, Stmt *HandlerBlock);
+ StmtResult ActOnCXXTryBlock(SourceLocation TryLoc, Stmt *TryBlock,
+ ArrayRef<Stmt *> Handlers);
+
+ StmtResult ActOnSEHTryBlock(bool IsCXXTry, // try (true) or __try (false) ?
+ SourceLocation TryLoc, Stmt *TryBlock,
+ Stmt *Handler);
+ StmtResult ActOnSEHExceptBlock(SourceLocation Loc,
+ Expr *FilterExpr,
+ Stmt *Block);
+ void ActOnStartSEHFinallyBlock();
+ void ActOnAbortSEHFinallyBlock();
+ StmtResult ActOnFinishSEHFinallyBlock(SourceLocation Loc, Stmt *Block);
+ StmtResult ActOnSEHLeaveStmt(SourceLocation Loc, Scope *CurScope);
+
+ 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 DiagnoseUnusedNestedTypedefs(const RecordDecl *D);
+ void DiagnoseUnusedDecl(const NamedDecl *ND);
+
+ /// Emit \p DiagID if statement located on \p StmtLoc has a suspicious null
+ /// statement as a \p Body, and it is located on the same line.
+ ///
+ /// This helps prevent bugs due to typos, such as:
+ /// if (condition);
+ /// do_stuff();
+ void DiagnoseEmptyStmtBody(SourceLocation StmtLoc,
+ const Stmt *Body,
+ unsigned DiagID);
+
+ /// Warn if a for/while loop statement \p S, which is followed by
+ /// \p PossibleBody, has a suspicious null statement as a body.
+ void DiagnoseEmptyLoopBody(const Stmt *S,
+ const Stmt *PossibleBody);
+
+ /// Warn if a value is moved to itself.
+ void DiagnoseSelfMove(const Expr *LHSExpr, const Expr *RHSExpr,
+ SourceLocation OpLoc);
+
+ /// \brief Warn if we're implicitly casting from a _Nullable pointer type to a
+ /// _Nonnull one.
+ void diagnoseNullableToNonnullConversion(QualType DstType, QualType SrcType,
+ SourceLocation Loc);
+
+ ParsingDeclState PushParsingDeclaration(sema::DelayedDiagnosticPool &pool) {
+ return DelayedDiagnostics.push(pool);
+ }
+ void PopParsingDeclaration(ParsingDeclState state, Decl *decl);
+
+ typedef ProcessingContextState ParsingClassState;
+ ParsingClassState PushParsingClass() {
+ return DelayedDiagnostics.pushUndelayed();
+ }
+ void PopParsingClass(ParsingClassState state) {
+ DelayedDiagnostics.popUndelayed(state);
+ }
+
+ void redelayDiagnostics(sema::DelayedDiagnosticPool &pool);
+
+ enum AvailabilityDiagnostic { AD_Deprecation, AD_Unavailable, AD_Partial };
+
+ void EmitAvailabilityWarning(AvailabilityDiagnostic AD,
+ NamedDecl *D, StringRef Message,
+ SourceLocation Loc,
+ const ObjCInterfaceDecl *UnknownObjCClass,
+ const ObjCPropertyDecl *ObjCProperty,
+ bool ObjCPropertyAccess);
+
+ bool makeUnavailableInSystemHeader(SourceLocation loc,
+ UnavailableAttr::ImplicitReason reason);
+
+ //===--------------------------------------------------------------------===//
+ // Expression Parsing Callbacks: SemaExpr.cpp.
+
+ bool CanUseDecl(NamedDecl *D);
+ bool DiagnoseUseOfDecl(NamedDecl *D, SourceLocation Loc,
+ const ObjCInterfaceDecl *UnknownObjCClass=nullptr,
+ bool ObjCPropertyAccess=false);
+ void NoteDeletedFunction(FunctionDecl *FD);
+ std::string getDeletedOrUnavailableSuffix(const FunctionDecl *FD);
+ bool DiagnosePropertyAccessorMismatch(ObjCPropertyDecl *PD,
+ ObjCMethodDecl *Getter,
+ SourceLocation Loc);
+ void DiagnoseSentinelCalls(NamedDecl *D, SourceLocation Loc,
+ ArrayRef<Expr *> Args);
+
+ void PushExpressionEvaluationContext(ExpressionEvaluationContext NewContext,
+ Decl *LambdaContextDecl = nullptr,
+ bool IsDecltype = false);
+ enum ReuseLambdaContextDecl_t { ReuseLambdaContextDecl };
+ void PushExpressionEvaluationContext(ExpressionEvaluationContext NewContext,
+ ReuseLambdaContextDecl_t,
+ bool IsDecltype = false);
+ void PopExpressionEvaluationContext();
+
+ void DiscardCleanupsInEvaluationContext();
+
+ ExprResult TransformToPotentiallyEvaluated(Expr *E);
+ ExprResult HandleExprEvaluationContextForTypeof(Expr *E);
+
+ ExprResult ActOnConstantExpression(ExprResult Res);
+
+ // Functions for marking a declaration referenced. These functions also
+ // contain the relevant logic for marking if a reference to a function or
+ // variable is an odr-use (in the C++11 sense). There are separate variants
+ // for expressions referring to a decl; these exist because odr-use marking
+ // needs to be delayed for some constant variables when we build one of the
+ // named expressions.
+ void MarkAnyDeclReferenced(SourceLocation Loc, Decl *D, bool OdrUse);
+ void MarkFunctionReferenced(SourceLocation Loc, FunctionDecl *Func,
+ bool OdrUse = true);
+ void MarkVariableReferenced(SourceLocation Loc, VarDecl *Var);
+ void MarkDeclRefReferenced(DeclRefExpr *E);
+ void MarkMemberReferenced(MemberExpr *E);
+
+ void UpdateMarkingForLValueToRValue(Expr *E);
+ void CleanupVarDeclMarking();
+
+ enum TryCaptureKind {
+ TryCapture_Implicit, TryCapture_ExplicitByVal, TryCapture_ExplicitByRef
+ };
+
+ /// \brief Try to capture the given variable.
+ ///
+ /// \param Var The variable to capture.
+ ///
+ /// \param Loc The location at which the capture occurs.
+ ///
+ /// \param Kind The kind of capture, which may be implicit (for either a
+ /// block or a lambda), or explicit by-value or by-reference (for a lambda).
+ ///
+ /// \param EllipsisLoc The location of the ellipsis, if one is provided in
+ /// an explicit lambda capture.
+ ///
+ /// \param BuildAndDiagnose Whether we are actually supposed to add the
+ /// captures or diagnose errors. If false, this routine merely check whether
+ /// the capture can occur without performing the capture itself or complaining
+ /// if the variable cannot be captured.
+ ///
+ /// \param CaptureType Will be set to the type of the field used to capture
+ /// this variable in the innermost block or lambda. Only valid when the
+ /// variable can be captured.
+ ///
+ /// \param DeclRefType Will be set to the type of a reference to the capture
+ /// from within the current scope. Only valid when the variable can be
+ /// captured.
+ ///
+ /// \param FunctionScopeIndexToStopAt If non-null, it points to the index
+ /// of the FunctionScopeInfo stack beyond which we do not attempt to capture.
+ /// This is useful when enclosing lambdas must speculatively capture
+ /// variables that may or may not be used in certain specializations of
+ /// a nested generic lambda.
+ ///
+ /// \returns true if an error occurred (i.e., the variable cannot be
+ /// captured) and false if the capture succeeded.
+ bool tryCaptureVariable(VarDecl *Var, SourceLocation Loc, TryCaptureKind Kind,
+ SourceLocation EllipsisLoc, bool BuildAndDiagnose,
+ QualType &CaptureType,
+ QualType &DeclRefType,
+ const unsigned *const FunctionScopeIndexToStopAt);
+
+ /// \brief Try to capture the given variable.
+ bool tryCaptureVariable(VarDecl *Var, SourceLocation Loc,
+ TryCaptureKind Kind = TryCapture_Implicit,
+ SourceLocation EllipsisLoc = SourceLocation());
+
+ /// \brief Checks if the variable must be captured.
+ bool NeedToCaptureVariable(VarDecl *Var, SourceLocation Loc);
+
+ /// \brief Given a variable, determine the type that a reference to that
+ /// variable will have in the given scope.
+ QualType getCapturedDeclRefType(VarDecl *Var, SourceLocation Loc);
+
+ void MarkDeclarationsReferencedInType(SourceLocation Loc, QualType T);
+ void MarkDeclarationsReferencedInExpr(Expr *E,
+ bool SkipLocalVariables = false);
+
+ /// \brief Try to recover by turning the given expression into a
+ /// call. Returns true if recovery was attempted or an error was
+ /// emitted; this may also leave the ExprResult invalid.
+ bool tryToRecoverWithCall(ExprResult &E, const PartialDiagnostic &PD,
+ bool ForceComplain = false,
+ bool (*IsPlausibleResult)(QualType) = nullptr);
+
+ /// \brief Figure out if an expression could be turned into a call.
+ bool tryExprAsCall(Expr &E, QualType &ZeroArgCallReturnTy,
+ UnresolvedSetImpl &NonTemplateOverloads);
+
+ /// \brief Conditionally issue a diagnostic based on the current
+ /// evaluation context.
+ ///
+ /// \param Statement If Statement is non-null, delay reporting the
+ /// diagnostic until the function body is parsed, and then do a basic
+ /// reachability analysis to determine if the statement is reachable.
+ /// If it is unreachable, the diagnostic will not be emitted.
+ bool DiagRuntimeBehavior(SourceLocation Loc, const Stmt *Statement,
+ const PartialDiagnostic &PD);
+
+ // Primary Expressions.
+ SourceRange getExprRange(Expr *E) const;
+
+ ExprResult ActOnIdExpression(
+ Scope *S, CXXScopeSpec &SS, SourceLocation TemplateKWLoc,
+ UnqualifiedId &Id, bool HasTrailingLParen, bool IsAddressOfOperand,
+ std::unique_ptr<CorrectionCandidateCallback> CCC = nullptr,
+ bool IsInlineAsmIdentifier = false, Token *KeywordReplacement = nullptr);
+
+ void DecomposeUnqualifiedId(const UnqualifiedId &Id,
+ TemplateArgumentListInfo &Buffer,
+ DeclarationNameInfo &NameInfo,
+ const TemplateArgumentListInfo *&TemplateArgs);
+
+ bool
+ DiagnoseEmptyLookup(Scope *S, CXXScopeSpec &SS, LookupResult &R,
+ std::unique_ptr<CorrectionCandidateCallback> CCC,
+ TemplateArgumentListInfo *ExplicitTemplateArgs = nullptr,
+ ArrayRef<Expr *> Args = None, TypoExpr **Out = nullptr);
+
+ ExprResult LookupInObjCMethod(LookupResult &LookUp, Scope *S,
+ IdentifierInfo *II,
+ bool AllowBuiltinCreation=false);
+
+ ExprResult ActOnDependentIdExpression(const CXXScopeSpec &SS,
+ SourceLocation TemplateKWLoc,
+ const DeclarationNameInfo &NameInfo,
+ bool isAddressOfOperand,
+ const TemplateArgumentListInfo *TemplateArgs);
+
+ ExprResult BuildDeclRefExpr(ValueDecl *D, QualType Ty,
+ ExprValueKind VK,
+ SourceLocation Loc,
+ const CXXScopeSpec *SS = nullptr);
+ ExprResult
+ BuildDeclRefExpr(ValueDecl *D, QualType Ty, ExprValueKind VK,
+ const DeclarationNameInfo &NameInfo,
+ const CXXScopeSpec *SS = nullptr,
+ NamedDecl *FoundD = nullptr,
+ const TemplateArgumentListInfo *TemplateArgs = nullptr);
+ ExprResult
+ BuildAnonymousStructUnionMemberReference(
+ const CXXScopeSpec &SS,
+ SourceLocation nameLoc,
+ IndirectFieldDecl *indirectField,
+ DeclAccessPair FoundDecl = DeclAccessPair::make(nullptr, AS_none),
+ Expr *baseObjectExpr = nullptr,
+ SourceLocation opLoc = SourceLocation());
+
+ ExprResult BuildPossibleImplicitMemberExpr(const CXXScopeSpec &SS,
+ SourceLocation TemplateKWLoc,
+ LookupResult &R,
+ const TemplateArgumentListInfo *TemplateArgs,
+ const Scope *S);
+ ExprResult BuildImplicitMemberExpr(const CXXScopeSpec &SS,
+ SourceLocation TemplateKWLoc,
+ LookupResult &R,
+ const TemplateArgumentListInfo *TemplateArgs,
+ bool IsDefiniteInstance,
+ const Scope *S);
+ bool UseArgumentDependentLookup(const CXXScopeSpec &SS,
+ const LookupResult &R,
+ bool HasTrailingLParen);
+
+ ExprResult
+ BuildQualifiedDeclarationNameExpr(CXXScopeSpec &SS,
+ const DeclarationNameInfo &NameInfo,
+ bool IsAddressOfOperand, const Scope *S,
+ TypeSourceInfo **RecoveryTSI = nullptr);
+
+ ExprResult BuildDependentDeclRefExpr(const CXXScopeSpec &SS,
+ SourceLocation TemplateKWLoc,
+ const DeclarationNameInfo &NameInfo,
+ const TemplateArgumentListInfo *TemplateArgs);
+
+ ExprResult BuildDeclarationNameExpr(const CXXScopeSpec &SS,
+ LookupResult &R,
+ bool NeedsADL,
+ bool AcceptInvalidDecl = false);
+ ExprResult BuildDeclarationNameExpr(
+ const CXXScopeSpec &SS, const DeclarationNameInfo &NameInfo, NamedDecl *D,
+ NamedDecl *FoundD = nullptr,
+ const TemplateArgumentListInfo *TemplateArgs = nullptr,
+ bool AcceptInvalidDecl = false);
+
+ ExprResult BuildLiteralOperatorCall(LookupResult &R,
+ DeclarationNameInfo &SuffixInfo,
+ ArrayRef<Expr *> Args,
+ SourceLocation LitEndLoc,
+ TemplateArgumentListInfo *ExplicitTemplateArgs = nullptr);
+
+ ExprResult BuildPredefinedExpr(SourceLocation Loc,
+ PredefinedExpr::IdentType IT);
+ ExprResult ActOnPredefinedExpr(SourceLocation Loc, tok::TokenKind Kind);
+ ExprResult ActOnIntegerConstant(SourceLocation Loc, uint64_t Val);
+
+ bool CheckLoopHintExpr(Expr *E, SourceLocation Loc);
+
+ ExprResult ActOnNumericConstant(const Token &Tok, Scope *UDLScope = nullptr);
+ ExprResult ActOnCharacterConstant(const Token &Tok,
+ Scope *UDLScope = nullptr);
+ ExprResult ActOnParenExpr(SourceLocation L, SourceLocation R, Expr *E);
+ ExprResult ActOnParenListExpr(SourceLocation L,
+ SourceLocation R,
+ MultiExprArg Val);
+
+ /// ActOnStringLiteral - The specified tokens were lexed as pasted string
+ /// fragments (e.g. "foo" "bar" L"baz").
+ ExprResult ActOnStringLiteral(ArrayRef<Token> StringToks,
+ Scope *UDLScope = nullptr);
+
+ ExprResult ActOnGenericSelectionExpr(SourceLocation KeyLoc,
+ SourceLocation DefaultLoc,
+ SourceLocation RParenLoc,
+ Expr *ControllingExpr,
+ ArrayRef<ParsedType> ArgTypes,
+ ArrayRef<Expr *> ArgExprs);
+ ExprResult CreateGenericSelectionExpr(SourceLocation KeyLoc,
+ SourceLocation DefaultLoc,
+ SourceLocation RParenLoc,
+ Expr *ControllingExpr,
+ ArrayRef<TypeSourceInfo *> Types,
+ ArrayRef<Expr *> Exprs);
+
+ // Binary/Unary Operators. 'Tok' is the token for the operator.
+ ExprResult CreateBuiltinUnaryOp(SourceLocation OpLoc, UnaryOperatorKind Opc,
+ Expr *InputExpr);
+ ExprResult BuildUnaryOp(Scope *S, SourceLocation OpLoc,
+ UnaryOperatorKind Opc, Expr *Input);
+ ExprResult ActOnUnaryOp(Scope *S, SourceLocation OpLoc,
+ tok::TokenKind Op, Expr *Input);
+
+ QualType CheckAddressOfOperand(ExprResult &Operand, SourceLocation OpLoc);
+
+ ExprResult CreateUnaryExprOrTypeTraitExpr(TypeSourceInfo *TInfo,
+ SourceLocation OpLoc,
+ UnaryExprOrTypeTrait ExprKind,
+ SourceRange R);
+ ExprResult CreateUnaryExprOrTypeTraitExpr(Expr *E, SourceLocation OpLoc,
+ UnaryExprOrTypeTrait ExprKind);
+ ExprResult
+ ActOnUnaryExprOrTypeTraitExpr(SourceLocation OpLoc,
+ UnaryExprOrTypeTrait ExprKind,
+ bool IsType, void *TyOrEx,
+ SourceRange ArgRange);
+
+ ExprResult CheckPlaceholderExpr(Expr *E);
+ bool CheckVecStepExpr(Expr *E);
+
+ bool CheckUnaryExprOrTypeTraitOperand(Expr *E, UnaryExprOrTypeTrait ExprKind);
+ bool CheckUnaryExprOrTypeTraitOperand(QualType ExprType, SourceLocation OpLoc,
+ SourceRange ExprRange,
+ UnaryExprOrTypeTrait ExprKind);
+ 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 ActOnOMPArraySectionExpr(Expr *Base, SourceLocation LBLoc,
+ Expr *LowerBound, SourceLocation ColonLoc,
+ Expr *Length, SourceLocation RBLoc);
+
+ // This struct is for use by ActOnMemberAccess to allow
+ // BuildMemberReferenceExpr to be able to reinvoke ActOnMemberAccess after
+ // changing the access operator from a '.' to a '->' (to see if that is the
+ // change needed to fix an error about an unknown member, e.g. when the class
+ // defines a custom operator->).
+ struct ActOnMemberAccessExtraArgs {
+ Scope *S;
+ UnqualifiedId &Id;
+ Decl *ObjCImpDecl;
+ };
+
+ ExprResult BuildMemberReferenceExpr(
+ Expr *Base, QualType BaseType, SourceLocation OpLoc, bool IsArrow,
+ CXXScopeSpec &SS, SourceLocation TemplateKWLoc,
+ NamedDecl *FirstQualifierInScope, const DeclarationNameInfo &NameInfo,
+ const TemplateArgumentListInfo *TemplateArgs,
+ const Scope *S,
+ ActOnMemberAccessExtraArgs *ExtraArgs = nullptr);
+
+ ExprResult
+ BuildMemberReferenceExpr(Expr *Base, QualType BaseType, SourceLocation OpLoc,
+ bool IsArrow, const CXXScopeSpec &SS,
+ SourceLocation TemplateKWLoc,
+ NamedDecl *FirstQualifierInScope, LookupResult &R,
+ const TemplateArgumentListInfo *TemplateArgs,
+ const Scope *S,
+ bool SuppressQualifierCheck = false,
+ ActOnMemberAccessExtraArgs *ExtraArgs = nullptr);
+
+ ExprResult PerformMemberExprBaseConversion(Expr *Base, bool IsArrow);
+
+ 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,
+ SourceLocation TemplateKWLoc,
+ NamedDecl *FirstQualifierInScope,
+ const DeclarationNameInfo &NameInfo,
+ const TemplateArgumentListInfo *TemplateArgs);
+
+ ExprResult ActOnMemberAccessExpr(Scope *S, Expr *Base,
+ SourceLocation OpLoc,
+ tok::TokenKind OpKind,
+ CXXScopeSpec &SS,
+ SourceLocation TemplateKWLoc,
+ UnqualifiedId &Member,
+ Decl *ObjCImpDecl);
+
+ void ActOnDefaultCtorInitializers(Decl *CDtorDecl);
+ bool ConvertArgumentsForCall(CallExpr *Call, Expr *Fn,
+ FunctionDecl *FDecl,
+ const FunctionProtoType *Proto,
+ ArrayRef<Expr *> Args,
+ SourceLocation RParenLoc,
+ bool ExecConfig = false);
+ void CheckStaticArrayArgument(SourceLocation CallLoc,
+ ParmVarDecl *Param,
+ const Expr *ArgExpr);
+
+ /// 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 ArgExprs, SourceLocation RParenLoc,
+ Expr *ExecConfig = nullptr,
+ bool IsExecConfig = false);
+ ExprResult BuildResolvedCallExpr(Expr *Fn, NamedDecl *NDecl,
+ SourceLocation LParenLoc,
+ ArrayRef<Expr *> Arg,
+ SourceLocation RParenLoc,
+ Expr *Config = nullptr,
+ bool IsExecConfig = false);
+
+ ExprResult ActOnCUDAExecConfigExpr(Scope *S, SourceLocation LLLLoc,
+ MultiExprArg ExecConfig,
+ SourceLocation GGGLoc);
+
+ ExprResult ActOnCastExpr(Scope *S, SourceLocation LParenLoc,
+ Declarator &D, ParsedType &Ty,
+ SourceLocation RParenLoc, Expr *CastExpr);
+ ExprResult BuildCStyleCastExpr(SourceLocation LParenLoc,
+ TypeSourceInfo *Ty,
+ SourceLocation RParenLoc,
+ Expr *Op);
+ CastKind PrepareScalarCast(ExprResult &src, QualType destType);
+
+ /// \brief Build an altivec or OpenCL literal.
+ ExprResult BuildVectorLiteral(SourceLocation LParenLoc,
+ SourceLocation RParenLoc, Expr *E,
+ TypeSourceInfo *TInfo);
+
+ ExprResult MaybeConvertParenListExprToParenExpr(Scope *S, Expr *ME);
+
+ ExprResult ActOnCompoundLiteral(SourceLocation LParenLoc,
+ ParsedType Ty,
+ SourceLocation RParenLoc,
+ Expr *InitExpr);
+
+ ExprResult BuildCompoundLiteralExpr(SourceLocation LParenLoc,
+ TypeSourceInfo *TInfo,
+ SourceLocation RParenLoc,
+ Expr *LiteralExpr);
+
+ ExprResult ActOnInitList(SourceLocation LBraceLoc,
+ MultiExprArg InitArgList,
+ SourceLocation RBraceLoc);
+
+ ExprResult ActOnDesignatedInitializer(Designation &Desig,
+ SourceLocation Loc,
+ bool GNUSyntax,
+ ExprResult Init);
+
+private:
+ static BinaryOperatorKind ConvertTokenKindToBinaryOpcode(tok::TokenKind Kind);
+
+public:
+ ExprResult ActOnBinOp(Scope *S, SourceLocation TokLoc,
+ tok::TokenKind Kind, Expr *LHSExpr, Expr *RHSExpr);
+ ExprResult BuildBinOp(Scope *S, SourceLocation OpLoc,
+ BinaryOperatorKind Opc, Expr *LHSExpr, Expr *RHSExpr);
+ ExprResult CreateBuiltinBinOp(SourceLocation OpLoc, BinaryOperatorKind Opc,
+ Expr *LHSExpr, Expr *RHSExpr);
+
+ /// 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 *CondExpr, Expr *LHSExpr, Expr *RHSExpr);
+
+ /// ActOnAddrLabel - Parse the GNU address of label extension: "&&foo".
+ ExprResult ActOnAddrLabel(SourceLocation OpLoc, SourceLocation LabLoc,
+ LabelDecl *TheDecl);
+
+ void ActOnStartStmtExpr();
+ ExprResult ActOnStmtExpr(SourceLocation LPLoc, Stmt *SubStmt,
+ SourceLocation RPLoc); // "({..})"
+ void ActOnStmtExprError();
+
+ // __builtin_offsetof(type, identifier(.identifier|[expr])*)
+ struct OffsetOfComponent {
+ SourceLocation LocStart, LocEnd;
+ bool isBrackets; // true if [expr], false if .ident
+ union {
+ IdentifierInfo *IdentInfo;
+ Expr *E;
+ } U;
+ };
+
+ /// __builtin_offsetof(type, a.b[123][456].c)
+ ExprResult BuildBuiltinOffsetOf(SourceLocation BuiltinLoc,
+ TypeSourceInfo *TInfo,
+ ArrayRef<OffsetOfComponent> Components,
+ SourceLocation RParenLoc);
+ ExprResult ActOnBuiltinOffsetOf(Scope *S,
+ SourceLocation BuiltinLoc,
+ SourceLocation TypeLoc,
+ ParsedType ParsedArgTy,
+ ArrayRef<OffsetOfComponent> Components,
+ SourceLocation RParenLoc);
+
+ // __builtin_choose_expr(constExpr, expr1, expr2)
+ ExprResult ActOnChooseExpr(SourceLocation BuiltinLoc,
+ Expr *CondExpr, Expr *LHSExpr,
+ Expr *RHSExpr, SourceLocation RPLoc);
+
+ // __builtin_va_arg(expr, type)
+ ExprResult ActOnVAArg(SourceLocation BuiltinLoc, Expr *E, ParsedType Ty,
+ SourceLocation RPLoc);
+ ExprResult BuildVAArgExpr(SourceLocation BuiltinLoc, Expr *E,
+ TypeSourceInfo *TInfo, SourceLocation RPLoc);
+
+ // __null
+ ExprResult ActOnGNUNullExpr(SourceLocation TokenLoc);
+
+ bool CheckCaseExpression(Expr *E);
+
+ /// \brief Describes the result of an "if-exists" condition check.
+ enum IfExistsResult {
+ /// \brief The symbol exists.
+ IER_Exists,
+
+ /// \brief The symbol does not exist.
+ IER_DoesNotExist,
+
+ /// \brief The name is a dependent name, so the results will differ
+ /// from one instantiation to the next.
+ IER_Dependent,
+
+ /// \brief An error occurred.
+ IER_Error
+ };
+
+ IfExistsResult
+ CheckMicrosoftIfExistsSymbol(Scope *S, CXXScopeSpec &SS,
+ const DeclarationNameInfo &TargetNameInfo);
+
+ IfExistsResult
+ CheckMicrosoftIfExistsSymbol(Scope *S, SourceLocation KeywordLoc,
+ bool IsIfExists, CXXScopeSpec &SS,
+ UnqualifiedId &Name);
+
+ StmtResult BuildMSDependentExistsStmt(SourceLocation KeywordLoc,
+ bool IsIfExists,
+ NestedNameSpecifierLoc QualifierLoc,
+ DeclarationNameInfo NameInfo,
+ Stmt *Nested);
+ StmtResult ActOnMSDependentExistsStmt(SourceLocation KeywordLoc,
+ bool IsIfExists,
+ CXXScopeSpec &SS, UnqualifiedId &Name,
+ Stmt *Nested);
+
+ //===------------------------- "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(SourceLocation CaretLoc, 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);
+
+ //===---------------------------- Clang Extensions ----------------------===//
+
+ /// __builtin_convertvector(...)
+ ExprResult ActOnConvertVectorExpr(Expr *E, ParsedType ParsedDestTy,
+ SourceLocation BuiltinLoc,
+ SourceLocation RParenLoc);
+
+ //===---------------------------- OpenCL Features -----------------------===//
+
+ /// __builtin_astype(...)
+ ExprResult ActOnAsTypeExpr(Expr *E, ParsedType ParsedDestTy,
+ SourceLocation BuiltinLoc,
+ SourceLocation RParenLoc);
+
+ //===---------------------------- C++ Features --------------------------===//
+
+ // Act on C++ namespaces
+ Decl *ActOnStartNamespaceDef(Scope *S, SourceLocation InlineLoc,
+ SourceLocation NamespaceLoc,
+ SourceLocation IdentLoc,
+ IdentifierInfo *Ident,
+ SourceLocation LBrace,
+ AttributeList *AttrList,
+ UsingDirectiveDecl * &UsingDecl);
+ void ActOnFinishNamespaceDef(Decl *Dcl, SourceLocation RBrace);
+
+ NamespaceDecl *getStdNamespace() const;
+ NamespaceDecl *getOrCreateStdNamespace();
+
+ CXXRecordDecl *getStdBadAlloc() const;
+
+ /// \brief Tests whether Ty is an instance of std::initializer_list and, if
+ /// it is and Element is not NULL, assigns the element type to Element.
+ bool isStdInitializerList(QualType Ty, QualType *Element);
+
+ /// \brief Looks for the std::initializer_list template and instantiates it
+ /// with Element, or emits an error if it's not found.
+ ///
+ /// \returns The instantiated template, or null on error.
+ QualType BuildStdInitializerList(QualType Element, SourceLocation Loc);
+
+ /// \brief Determine whether Ctor is an initializer-list constructor, as
+ /// defined in [dcl.init.list]p2.
+ bool isInitListConstructor(const CXXConstructorDecl *Ctor);
+
+ 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 *&PrevShadow);
+ UsingShadowDecl *BuildUsingShadowDecl(Scope *S, UsingDecl *UD,
+ NamedDecl *Target,
+ UsingShadowDecl *PrevDecl);
+
+ bool CheckUsingDeclRedeclaration(SourceLocation UsingLoc,
+ bool HasTypenameKeyword,
+ const CXXScopeSpec &SS,
+ SourceLocation NameLoc,
+ const LookupResult &Previous);
+ bool CheckUsingDeclQualifier(SourceLocation UsingLoc,
+ const CXXScopeSpec &SS,
+ const DeclarationNameInfo &NameInfo,
+ SourceLocation NameLoc);
+
+ NamedDecl *BuildUsingDeclaration(Scope *S, AccessSpecifier AS,
+ SourceLocation UsingLoc,
+ CXXScopeSpec &SS,
+ DeclarationNameInfo NameInfo,
+ AttributeList *AttrList,
+ bool IsInstantiation,
+ bool HasTypenameKeyword,
+ SourceLocation TypenameLoc);
+
+ bool CheckInheritingConstructorUsingDecl(UsingDecl *UD);
+
+ Decl *ActOnUsingDeclaration(Scope *CurScope,
+ AccessSpecifier AS,
+ bool HasUsingKeyword,
+ SourceLocation UsingLoc,
+ CXXScopeSpec &SS,
+ UnqualifiedId &Name,
+ AttributeList *AttrList,
+ bool HasTypenameKeyword,
+ SourceLocation TypenameLoc);
+ Decl *ActOnAliasDeclaration(Scope *CurScope,
+ AccessSpecifier AS,
+ MultiTemplateParamsArg TemplateParams,
+ SourceLocation UsingLoc,
+ UnqualifiedId &Name,
+ AttributeList *AttrList,
+ TypeResult Type,
+ Decl *DeclFromDeclSpec);
+
+ /// 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 HadMultipleCandidates, bool IsListInitialization,
+ bool IsStdInitListInitialization,
+ bool RequiresZeroInit, unsigned ConstructKind,
+ SourceRange ParenRange);
+
+ // FIXME: Can we 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 HadMultipleCandidates,
+ bool IsListInitialization,
+ bool IsStdInitListInitialization, bool RequiresZeroInit,
+ unsigned ConstructKind, SourceRange ParenRange);
+
+ ExprResult BuildCXXDefaultInitExpr(SourceLocation Loc, FieldDecl *Field);
+
+ /// 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 Helper class that collects exception specifications for
+ /// implicitly-declared special member functions.
+ class ImplicitExceptionSpecification {
+ // Pointer to allow copying
+ Sema *Self;
+ // We order exception specifications thus:
+ // noexcept is the most restrictive, but is only used in C++11.
+ // throw() comes next.
+ // Then a throw(collected exceptions)
+ // Finally no specification, which is expressed as noexcept(false).
+ // throw(...) is used instead if any called function uses it.
+ ExceptionSpecificationType ComputedEST;
+ llvm::SmallPtrSet<CanQualType, 4> ExceptionsSeen;
+ SmallVector<QualType, 4> Exceptions;
+
+ void ClearExceptions() {
+ ExceptionsSeen.clear();
+ Exceptions.clear();
+ }
+
+ public:
+ explicit ImplicitExceptionSpecification(Sema &Self)
+ : Self(&Self), ComputedEST(EST_BasicNoexcept) {
+ if (!Self.getLangOpts().CPlusPlus11)
+ ComputedEST = EST_DynamicNone;
+ }
+
+ /// \brief Get the computed exception specification type.
+ ExceptionSpecificationType getExceptionSpecType() const {
+ assert(ComputedEST != EST_ComputedNoexcept &&
+ "noexcept(expr) should not be a possible result");
+ return ComputedEST;
+ }
+
+ /// \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 Integrate another called method into the collected data.
+ void CalledDecl(SourceLocation CallLoc, const CXXMethodDecl *Method);
+
+ /// \brief Integrate an invoked expression into the collected data.
+ void CalledExpr(Expr *E);
+
+ /// \brief Overwrite an EPI's exception specification with this
+ /// computed exception specification.
+ FunctionProtoType::ExceptionSpecInfo getExceptionSpec() const {
+ FunctionProtoType::ExceptionSpecInfo ESI;
+ ESI.Type = getExceptionSpecType();
+ if (ESI.Type == EST_Dynamic) {
+ ESI.Exceptions = Exceptions;
+ } else if (ESI.Type == EST_None) {
+ /// C++11 [except.spec]p14:
+ /// The exception-specification is noexcept(false) if the set of
+ /// potential exceptions of the special member function contains "any"
+ ESI.Type = EST_ComputedNoexcept;
+ ESI.NoexceptExpr = Self->ActOnCXXBoolLiteral(SourceLocation(),
+ tok::kw_false).get();
+ }
+ return ESI;
+ }
+ };
+
+ /// \brief Determine what sort of exception specification a defaulted
+ /// copy constructor of a class will have.
+ ImplicitExceptionSpecification
+ ComputeDefaultedDefaultCtorExceptionSpec(SourceLocation Loc,
+ CXXMethodDecl *MD);
+
+ /// \brief Determine what sort of exception specification a defaulted
+ /// default constructor of a class will have, and whether the parameter
+ /// will be const.
+ ImplicitExceptionSpecification
+ ComputeDefaultedCopyCtorExceptionSpec(CXXMethodDecl *MD);
+
+ /// \brief Determine what sort of exception specification a defautled
+ /// copy assignment operator of a class will have, and whether the
+ /// parameter will be const.
+ ImplicitExceptionSpecification
+ ComputeDefaultedCopyAssignmentExceptionSpec(CXXMethodDecl *MD);
+
+ /// \brief Determine what sort of exception specification a defaulted move
+ /// constructor of a class will have.
+ ImplicitExceptionSpecification
+ ComputeDefaultedMoveCtorExceptionSpec(CXXMethodDecl *MD);
+
+ /// \brief Determine what sort of exception specification a defaulted move
+ /// assignment operator of a class will have.
+ ImplicitExceptionSpecification
+ ComputeDefaultedMoveAssignmentExceptionSpec(CXXMethodDecl *MD);
+
+ /// \brief Determine what sort of exception specification a defaulted
+ /// destructor of a class will have.
+ ImplicitExceptionSpecification
+ ComputeDefaultedDtorExceptionSpec(CXXMethodDecl *MD);
+
+ /// \brief Determine what sort of exception specification an inheriting
+ /// constructor of a class will have.
+ ImplicitExceptionSpecification
+ ComputeInheritingCtorExceptionSpec(CXXConstructorDecl *CD);
+
+ /// \brief Evaluate the implicit exception specification for a defaulted
+ /// special member function.
+ void EvaluateImplicitExceptionSpec(SourceLocation Loc, CXXMethodDecl *MD);
+
+ /// \brief Check the given exception-specification and update the
+ /// exception specification information with the results.
+ void checkExceptionSpecification(bool IsTopLevel,
+ ExceptionSpecificationType EST,
+ ArrayRef<ParsedType> DynamicExceptions,
+ ArrayRef<SourceRange> DynamicExceptionRanges,
+ Expr *NoexceptExpr,
+ SmallVectorImpl<QualType> &Exceptions,
+ FunctionProtoType::ExceptionSpecInfo &ESI);
+
+ /// \brief Determine if we're in a case where we need to (incorrectly) eagerly
+ /// parse an exception specification to work around a libstdc++ bug.
+ bool isLibstdcxxEagerExceptionSpecHack(const Declarator &D);
+
+ /// \brief Add an exception-specification to the given member function
+ /// (or member function template). The exception-specification was parsed
+ /// after the method itself was declared.
+ void actOnDelayedExceptionSpecification(Decl *Method,
+ ExceptionSpecificationType EST,
+ SourceRange SpecificationRange,
+ ArrayRef<ParsedType> DynamicExceptions,
+ ArrayRef<SourceRange> DynamicExceptionRanges,
+ Expr *NoexceptExpr);
+
+ /// \brief Determine if a special member function should have a deleted
+ /// definition when it is defaulted.
+ bool ShouldDeleteSpecialMember(CXXMethodDecl *MD, CXXSpecialMember CSM,
+ bool Diagnose = false);
+
+ /// \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 Build an exception spec for destructors that don't have one.
+ ///
+ /// C++11 says that user-defined destructors with no exception spec get one
+ /// that looks as if the destructor was implicitly declared.
+ void AdjustDestructorExceptionSpec(CXXRecordDecl *ClassDecl,
+ CXXDestructorDecl *Destructor);
+
+ /// \brief Declare all inheriting constructors for the given class.
+ ///
+ /// \param ClassDecl The class declaration into which the inheriting
+ /// constructors will be added.
+ void DeclareInheritingConstructors(CXXRecordDecl *ClassDecl);
+
+ /// \brief Define the specified inheriting constructor.
+ void DefineInheritingConstructor(SourceLocation UseLoc,
+ CXXConstructorDecl *Constructor);
+
+ /// \brief Declare the implicit copy constructor for the given class.
+ ///
+ /// \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);
+
+ /// \brief Declare the implicit move constructor for the given class.
+ ///
+ /// \param ClassDecl The Class declaration into which the implicit
+ /// move constructor will be added.
+ ///
+ /// \returns The implicitly-declared move constructor, or NULL if it wasn't
+ /// declared.
+ CXXConstructorDecl *DeclareImplicitMoveConstructor(CXXRecordDecl *ClassDecl);
+
+ /// DefineImplicitMoveConstructor - Checks for feasibility of
+ /// defining this constructor as the move constructor.
+ void DefineImplicitMoveConstructor(SourceLocation CurrentLocation,
+ CXXConstructorDecl *Constructor);
+
+ /// \brief Declare the implicit copy assignment operator for the given class.
+ ///
+ /// \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 Defines an implicitly-declared copy assignment operator.
+ void DefineImplicitCopyAssignment(SourceLocation CurrentLocation,
+ CXXMethodDecl *MethodDecl);
+
+ /// \brief Declare the implicit move assignment operator for the given class.
+ ///
+ /// \param ClassDecl The Class declaration into which the implicit
+ /// move assignment operator will be added.
+ ///
+ /// \returns The implicitly-declared move assignment operator, or NULL if it
+ /// wasn't declared.
+ CXXMethodDecl *DeclareImplicitMoveAssignment(CXXRecordDecl *ClassDecl);
+
+ /// \brief Defines an implicitly-declared move assignment operator.
+ void DefineImplicitMoveAssignment(SourceLocation CurrentLocation,
+ CXXMethodDecl *MethodDecl);
+
+ /// \brief Force the declaration of any implicitly-declared members of this
+ /// class.
+ void ForceDeclarationOfImplicitMembers(CXXRecordDecl *Class);
+
+ /// \brief Determine whether the given function is an implicitly-deleted
+ /// special member function.
+ bool isImplicitlyDeleted(FunctionDecl *FD);
+
+ /// \brief Check whether 'this' shows up in the type of a static member
+ /// function after the (naturally empty) cv-qualifier-seq would be.
+ ///
+ /// \returns true if an error occurred.
+ bool checkThisInStaticMemberFunctionType(CXXMethodDecl *Method);
+
+ /// \brief Whether this' shows up in the exception specification of a static
+ /// member function.
+ bool checkThisInStaticMemberFunctionExceptionSpec(CXXMethodDecl *Method);
+
+ /// \brief Check whether 'this' shows up in the attributes of the given
+ /// static member function.
+ ///
+ /// \returns true if an error occurred.
+ bool checkThisInStaticMemberFunctionAttributes(CXXMethodDecl *Method);
+
+ /// 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,
+ SmallVectorImpl<Expr*> &ConvertedArgs,
+ bool AllowExplicit = false,
+ bool IsListInitialization = false);
+
+ ParsedType getInheritingConstructorName(CXXScopeSpec &SS,
+ SourceLocation NameLoc,
+ IdentifierInfo &Name);
+
+ ParsedType getDestructorName(SourceLocation TildeLoc,
+ IdentifierInfo &II, SourceLocation NameLoc,
+ Scope *S, CXXScopeSpec &SS,
+ ParsedType ObjectType,
+ bool EnteringContext);
+
+ ParsedType getDestructorType(const DeclSpec& DS, ParsedType ObjectType);
+
+ // Checks that reinterpret casts don't have undefined behavior.
+ void CheckCompatibleReinterpretCast(QualType SrcType, QualType DestType,
+ bool IsDereference, SourceRange Range);
+
+ /// ActOnCXXNamedCast - Parse {dynamic,static,reinterpret,const}_cast's.
+ ExprResult ActOnCXXNamedCast(SourceLocation OpLoc,
+ tok::TokenKind Kind,
+ SourceLocation LAngleBracketLoc,
+ Declarator &D,
+ 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);
+
+ /// \brief Handle a C++1z fold-expression: ( expr op ... op expr ).
+ ExprResult ActOnCXXFoldExpr(SourceLocation LParenLoc, Expr *LHS,
+ tok::TokenKind Operator,
+ SourceLocation EllipsisLoc, Expr *RHS,
+ SourceLocation RParenLoc);
+ ExprResult BuildCXXFoldExpr(SourceLocation LParenLoc, Expr *LHS,
+ BinaryOperatorKind Operator,
+ SourceLocation EllipsisLoc, Expr *RHS,
+ SourceLocation RParenLoc);
+ ExprResult BuildEmptyCXXFoldExpr(SourceLocation EllipsisLoc,
+ BinaryOperatorKind Operator);
+
+ //// ActOnCXXThis - Parse 'this' pointer.
+ ExprResult ActOnCXXThis(SourceLocation loc);
+
+ /// \brief Try to retrieve the type of the 'this' pointer.
+ ///
+ /// \returns The type of 'this', if possible. Otherwise, returns a NULL type.
+ QualType getCurrentThisType();
+
+ /// \brief When non-NULL, the C++ 'this' expression is allowed despite the
+ /// current context not being a non-static member function. In such cases,
+ /// this provides the type used for 'this'.
+ QualType CXXThisTypeOverride;
+
+ /// \brief RAII object used to temporarily allow the C++ 'this' expression
+ /// to be used, with the given qualifiers on the current class type.
+ class CXXThisScopeRAII {
+ Sema &S;
+ QualType OldCXXThisTypeOverride;
+ bool Enabled;
+
+ public:
+ /// \brief Introduce a new scope where 'this' may be allowed (when enabled),
+ /// using the given declaration (which is either a class template or a
+ /// class) along with the given qualifiers.
+ /// along with the qualifiers placed on '*this'.
+ CXXThisScopeRAII(Sema &S, Decl *ContextDecl, unsigned CXXThisTypeQuals,
+ bool Enabled = true);
+
+ ~CXXThisScopeRAII();
+ };
+
+ /// \brief Make sure the value of 'this' is actually available in the current
+ /// context, if it is a potentially evaluated context.
+ ///
+ /// \param Loc The location at which the capture of 'this' occurs.
+ ///
+ /// \param Explicit Whether 'this' is explicitly captured in a lambda
+ /// capture list.
+ ///
+ /// \param FunctionScopeIndexToStopAt If non-null, it points to the index
+ /// of the FunctionScopeInfo stack beyond which we do not attempt to capture.
+ /// This is useful when enclosing lambdas must speculatively capture
+ /// 'this' that may or may not be used in certain specializations of
+ /// a nested generic lambda (depending on whether the name resolves to
+ /// a non-static member function or a static function).
+ /// \return returns 'true' if failed, 'false' if success.
+ bool CheckCXXThisCapture(SourceLocation Loc, bool Explicit = false,
+ bool BuildAndDiagnose = true,
+ const unsigned *const FunctionScopeIndexToStopAt = nullptr);
+
+ /// \brief Determine whether the given type is the type of *this that is used
+ /// outside of the body of a member function for a type that is currently
+ /// being defined.
+ bool isThisOutsideMemberFunctionBody(QualType BaseType);
+
+ /// ActOnCXXBoolLiteral - Parse {true,false} literals.
+ ExprResult ActOnCXXBoolLiteral(SourceLocation OpLoc, tok::TokenKind Kind);
+
+
+ /// ActOnObjCBoolLiteral - Parse {__objc_yes,__objc_no} literals.
+ ExprResult ActOnObjCBoolLiteral(SourceLocation OpLoc, tok::TokenKind Kind);
+
+ /// ActOnCXXNullPtrLiteral - Parse 'nullptr'.
+ ExprResult ActOnCXXNullPtrLiteral(SourceLocation Loc);
+
+ //// ActOnCXXThrow - Parse throw expressions.
+ ExprResult ActOnCXXThrow(Scope *S, SourceLocation OpLoc, Expr *expr);
+ ExprResult BuildCXXThrow(SourceLocation OpLoc, Expr *Ex,
+ bool IsThrownVarInScope);
+ bool CheckCXXThrowOperand(SourceLocation ThrowLoc, QualType ThrowTy, 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,
+ Expr *Initializer);
+ ExprResult BuildCXXNew(SourceRange Range, bool UseGlobal,
+ SourceLocation PlacementLParen,
+ MultiExprArg PlacementArgs,
+ SourceLocation PlacementRParen,
+ SourceRange TypeIdParens,
+ QualType AllocType,
+ TypeSourceInfo *AllocTypeInfo,
+ Expr *ArraySize,
+ SourceRange DirectInitRange,
+ Expr *Initializer,
+ bool TypeMayContainAuto = true);
+
+ bool CheckAllocatedType(QualType AllocType, SourceLocation Loc,
+ SourceRange R);
+ bool FindAllocationFunctions(SourceLocation StartLoc, SourceRange Range,
+ bool UseGlobal, QualType AllocType, bool IsArray,
+ MultiExprArg PlaceArgs,
+ FunctionDecl *&OperatorNew,
+ FunctionDecl *&OperatorDelete);
+ bool FindAllocationOverload(SourceLocation StartLoc, SourceRange Range,
+ DeclarationName Name, MultiExprArg Args,
+ DeclContext *Ctx,
+ bool AllowMissing, FunctionDecl *&Operator,
+ bool Diagnose = true);
+ void DeclareGlobalNewDelete();
+ void DeclareGlobalAllocationFunction(DeclarationName Name, QualType Return,
+ QualType Param1,
+ QualType Param2 = QualType(),
+ bool addRestrictAttr = false);
+
+ bool FindDeallocationFunction(SourceLocation StartLoc, CXXRecordDecl *RD,
+ DeclarationName Name, FunctionDecl* &Operator,
+ bool Diagnose = true);
+ FunctionDecl *FindUsualDeallocationFunction(SourceLocation StartLoc,
+ bool CanProvideSize,
+ DeclarationName Name);
+
+ /// 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);
+
+ /// \brief Parsed one of the type trait support pseudo-functions.
+ ExprResult ActOnTypeTrait(TypeTrait Kind, SourceLocation KWLoc,
+ ArrayRef<ParsedType> Args,
+ SourceLocation RParenLoc);
+ ExprResult BuildTypeTrait(TypeTrait Kind, SourceLocation KWLoc,
+ ArrayRef<TypeSourceInfo *> Args,
+ SourceLocation RParenLoc);
+
+ /// ActOnArrayTypeTrait - Parsed one of the bianry type trait support
+ /// pseudo-functions.
+ ExprResult ActOnArrayTypeTrait(ArrayTypeTrait ATT,
+ SourceLocation KWLoc,
+ ParsedType LhsTy,
+ Expr *DimExpr,
+ SourceLocation RParen);
+
+ ExprResult BuildArrayTypeTrait(ArrayTypeTrait ATT,
+ SourceLocation KWLoc,
+ TypeSourceInfo *TSInfo,
+ Expr *DimExpr,
+ SourceLocation RParen);
+
+ /// ActOnExpressionTrait - Parsed one of the unary type trait support
+ /// pseudo-functions.
+ ExprResult ActOnExpressionTrait(ExpressionTrait OET,
+ SourceLocation KWLoc,
+ Expr *Queried,
+ SourceLocation RParen);
+
+ ExprResult BuildExpressionTrait(ExpressionTrait OET,
+ SourceLocation KWLoc,
+ Expr *Queried,
+ SourceLocation RParen);
+
+ ExprResult ActOnStartCXXMemberReference(Scope *S,
+ Expr *Base,
+ SourceLocation OpLoc,
+ tok::TokenKind OpKind,
+ ParsedType &ObjectType,
+ bool &MayBePseudoDestructor);
+
+ ExprResult BuildPseudoDestructorExpr(Expr *Base,
+ SourceLocation OpLoc,
+ tok::TokenKind OpKind,
+ const CXXScopeSpec &SS,
+ TypeSourceInfo *ScopeType,
+ SourceLocation CCLoc,
+ SourceLocation TildeLoc,
+ PseudoDestructorTypeStorage DestroyedType);
+
+ ExprResult ActOnPseudoDestructorExpr(Scope *S, Expr *Base,
+ SourceLocation OpLoc,
+ tok::TokenKind OpKind,
+ CXXScopeSpec &SS,
+ UnqualifiedId &FirstTypeName,
+ SourceLocation CCLoc,
+ SourceLocation TildeLoc,
+ UnqualifiedId &SecondTypeName);
+
+ ExprResult ActOnPseudoDestructorExpr(Scope *S, Expr *Base,
+ SourceLocation OpLoc,
+ tok::TokenKind OpKind,
+ SourceLocation TildeLoc,
+ const DeclSpec& DS);
+
+ /// 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) {
+ return ActOnFinishFullExpr(Expr, Expr ? Expr->getExprLoc()
+ : SourceLocation());
+ }
+ ExprResult ActOnFinishFullExpr(Expr *Expr, SourceLocation CC,
+ bool DiscardedValue = false,
+ bool IsConstexpr = false,
+ bool IsLambdaInitCaptureInitializer = false);
+ 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);
+
+ /// \brief The parser has parsed a global nested-name-specifier '::'.
+ ///
+ /// \param CCLoc The location of the '::'.
+ ///
+ /// \param SS The nested-name-specifier, which will be updated in-place
+ /// to reflect the parsed nested-name-specifier.
+ ///
+ /// \returns true if an error occurred, false otherwise.
+ bool ActOnCXXGlobalScopeSpecifier(SourceLocation CCLoc, CXXScopeSpec &SS);
+
+ /// \brief The parser has parsed a '__super' nested-name-specifier.
+ ///
+ /// \param SuperLoc The location of the '__super' keyword.
+ ///
+ /// \param ColonColonLoc The location of the '::'.
+ ///
+ /// \param SS The nested-name-specifier, which will be updated in-place
+ /// to reflect the parsed nested-name-specifier.
+ ///
+ /// \returns true if an error occurred, false otherwise.
+ bool ActOnSuperScopeSpecifier(SourceLocation SuperLoc,
+ SourceLocation ColonColonLoc, CXXScopeSpec &SS);
+
+ bool isAcceptableNestedNameSpecifier(const NamedDecl *SD,
+ bool *CanCorrect = nullptr);
+ NamedDecl *FindFirstQualifierInScope(Scope *S, NestedNameSpecifier *NNS);
+
+ bool isNonTypeNestedNameSpecifier(Scope *S, CXXScopeSpec &SS,
+ SourceLocation IdLoc,
+ IdentifierInfo &II,
+ ParsedType ObjectType);
+
+ bool BuildCXXNestedNameSpecifier(Scope *S,
+ IdentifierInfo &Identifier,
+ SourceLocation IdentifierLoc,
+ SourceLocation CCLoc,
+ QualType ObjectType,
+ bool EnteringContext,
+ CXXScopeSpec &SS,
+ NamedDecl *ScopeLookupResult,
+ bool ErrorRecoveryLookup,
+ bool *IsCorrectedToColon = nullptr);
+
+ /// \brief The parser has parsed a nested-name-specifier 'identifier::'.
+ ///
+ /// \param S The scope in which this nested-name-specifier occurs.
+ ///
+ /// \param Identifier The identifier preceding the '::'.
+ ///
+ /// \param IdentifierLoc The location of the identifier.
+ ///
+ /// \param CCLoc The location of the '::'.
+ ///
+ /// \param ObjectType The type of the object, if we're parsing
+ /// nested-name-specifier in a member access expression.
+ ///
+ /// \param EnteringContext Whether we're entering the context nominated by
+ /// this nested-name-specifier.
+ ///
+ /// \param SS The nested-name-specifier, which is both an input
+ /// parameter (the nested-name-specifier before this type) and an
+ /// output parameter (containing the full nested-name-specifier,
+ /// including this new type).
+ ///
+ /// \param ErrorRecoveryLookup If true, then this method is called to improve
+ /// error recovery. In this case do not emit error message.
+ ///
+ /// \param IsCorrectedToColon If not null, suggestions to replace '::' -> ':'
+ /// are allowed. The bool value pointed by this parameter is set to 'true'
+ /// if the identifier is treated as if it was followed by ':', not '::'.
+ ///
+ /// \returns true if an error occurred, false otherwise.
+ bool ActOnCXXNestedNameSpecifier(Scope *S,
+ IdentifierInfo &Identifier,
+ SourceLocation IdentifierLoc,
+ SourceLocation CCLoc,
+ ParsedType ObjectType,
+ bool EnteringContext,
+ CXXScopeSpec &SS,
+ bool ErrorRecoveryLookup = false,
+ bool *IsCorrectedToColon = nullptr);
+
+ ExprResult ActOnDecltypeExpression(Expr *E);
+
+ bool ActOnCXXNestedNameSpecifierDecltype(CXXScopeSpec &SS,
+ const DeclSpec &DS,
+ SourceLocation ColonColonLoc);
+
+ bool IsInvalidUnlessNestedName(Scope *S, CXXScopeSpec &SS,
+ IdentifierInfo &Identifier,
+ SourceLocation IdentifierLoc,
+ SourceLocation ColonLoc,
+ ParsedType ObjectType,
+ bool EnteringContext);
+
+ /// \brief The parser has parsed a nested-name-specifier
+ /// 'template[opt] template-name < template-args >::'.
+ ///
+ /// \param S The scope in which this nested-name-specifier occurs.
+ ///
+ /// \param SS The nested-name-specifier, which is both an input
+ /// parameter (the nested-name-specifier before this type) and an
+ /// output parameter (containing the full nested-name-specifier,
+ /// including this new type).
+ ///
+ /// \param TemplateKWLoc the location of the 'template' keyword, if any.
+ /// \param TemplateName the template name.
+ /// \param TemplateNameLoc The location of the template name.
+ /// \param LAngleLoc The location of the opening angle bracket ('<').
+ /// \param TemplateArgs The template arguments.
+ /// \param RAngleLoc The location of the closing angle bracket ('>').
+ /// \param CCLoc The location of the '::'.
+ ///
+ /// \param EnteringContext Whether we're entering the context of the
+ /// nested-name-specifier.
+ ///
+ ///
+ /// \returns true if an error occurred, false otherwise.
+ bool ActOnCXXNestedNameSpecifier(Scope *S,
+ CXXScopeSpec &SS,
+ SourceLocation TemplateKWLoc,
+ TemplateTy TemplateName,
+ SourceLocation TemplateNameLoc,
+ SourceLocation LAngleLoc,
+ ASTTemplateArgsPtr TemplateArgs,
+ SourceLocation RAngleLoc,
+ SourceLocation CCLoc,
+ bool EnteringContext);
+
+ /// \brief Given a C++ nested-name-specifier, produce an annotation value
+ /// that the parser can use later to reconstruct the given
+ /// nested-name-specifier.
+ ///
+ /// \param SS A nested-name-specifier.
+ ///
+ /// \returns A pointer containing all of the information in the
+ /// nested-name-specifier \p SS.
+ void *SaveNestedNameSpecifierAnnotation(CXXScopeSpec &SS);
+
+ /// \brief Given an annotation pointer for a nested-name-specifier, restore
+ /// the nested-name-specifier structure.
+ ///
+ /// \param Annotation The annotation pointer, produced by
+ /// \c SaveNestedNameSpecifierAnnotation().
+ ///
+ /// \param AnnotationRange The source range corresponding to the annotation.
+ ///
+ /// \param SS The nested-name-specifier that will be updated with the contents
+ /// of the annotation pointer.
+ void RestoreNestedNameSpecifierAnnotation(void *Annotation,
+ SourceRange AnnotationRange,
+ CXXScopeSpec &SS);
+
+ bool ShouldEnterDeclaratorScope(Scope *S, const CXXScopeSpec &SS);
+
+ /// ActOnCXXEnterDeclaratorScope - Called when a C++ scope specifier (global
+ /// scope or nested-name-specifier) is parsed, part of a declarator-id.
+ /// 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);
+
+ /// \brief Create a new lambda closure type.
+ CXXRecordDecl *createLambdaClosureType(SourceRange IntroducerRange,
+ TypeSourceInfo *Info,
+ bool KnownDependent,
+ LambdaCaptureDefault CaptureDefault);
+
+ /// \brief Start the definition of a lambda expression.
+ CXXMethodDecl *startLambdaDefinition(CXXRecordDecl *Class,
+ SourceRange IntroducerRange,
+ TypeSourceInfo *MethodType,
+ SourceLocation EndLoc,
+ ArrayRef<ParmVarDecl *> Params);
+
+ /// \brief Endow the lambda scope info with the relevant properties.
+ void buildLambdaScope(sema::LambdaScopeInfo *LSI,
+ CXXMethodDecl *CallOperator,
+ SourceRange IntroducerRange,
+ LambdaCaptureDefault CaptureDefault,
+ SourceLocation CaptureDefaultLoc,
+ bool ExplicitParams,
+ bool ExplicitResultType,
+ bool Mutable);
+
+ /// \brief Perform initialization analysis of the init-capture and perform
+ /// any implicit conversions such as an lvalue-to-rvalue conversion if
+ /// not being used to initialize a reference.
+ ParsedType actOnLambdaInitCaptureInitialization(
+ SourceLocation Loc, bool ByRef, IdentifierInfo *Id,
+ LambdaCaptureInitKind InitKind, Expr *&Init) {
+ return ParsedType::make(buildLambdaInitCaptureInitialization(
+ Loc, ByRef, Id, InitKind != LambdaCaptureInitKind::CopyInit, Init));
+ }
+ QualType buildLambdaInitCaptureInitialization(SourceLocation Loc, bool ByRef,
+ IdentifierInfo *Id,
+ bool DirectInit, Expr *&Init);
+
+ /// \brief Create a dummy variable within the declcontext of the lambda's
+ /// call operator, for name lookup purposes for a lambda init capture.
+ ///
+ /// CodeGen handles emission of lambda captures, ignoring these dummy
+ /// variables appropriately.
+ VarDecl *createLambdaInitCaptureVarDecl(SourceLocation Loc,
+ QualType InitCaptureType,
+ IdentifierInfo *Id,
+ unsigned InitStyle, Expr *Init);
+
+ /// \brief Build the implicit field for an init-capture.
+ FieldDecl *buildInitCaptureField(sema::LambdaScopeInfo *LSI, VarDecl *Var);
+
+ /// \brief Note that we have finished the explicit captures for the
+ /// given lambda.
+ void finishLambdaExplicitCaptures(sema::LambdaScopeInfo *LSI);
+
+ /// \brief Introduce the lambda parameters into scope.
+ void addLambdaParameters(CXXMethodDecl *CallOperator, Scope *CurScope);
+
+ /// \brief Deduce a block or lambda's return type based on the return
+ /// statements present in the body.
+ void deduceClosureReturnType(sema::CapturingScopeInfo &CSI);
+
+ /// ActOnStartOfLambdaDefinition - This is called just before we start
+ /// parsing the body of a lambda; it analyzes the explicit captures and
+ /// arguments, and sets up various data-structures for the body of the
+ /// lambda.
+ void ActOnStartOfLambdaDefinition(LambdaIntroducer &Intro,
+ Declarator &ParamInfo, Scope *CurScope);
+
+ /// ActOnLambdaError - If there is an error parsing a lambda, this callback
+ /// is invoked to pop the information about the lambda.
+ void ActOnLambdaError(SourceLocation StartLoc, Scope *CurScope,
+ bool IsInstantiation = false);
+
+ /// ActOnLambdaExpr - This is called when the body of a lambda expression
+ /// was successfully completed.
+ ExprResult ActOnLambdaExpr(SourceLocation StartLoc, Stmt *Body,
+ Scope *CurScope);
+
+ /// \brief Complete a lambda-expression having processed and attached the
+ /// lambda body.
+ ExprResult BuildLambdaExpr(SourceLocation StartLoc, SourceLocation EndLoc,
+ sema::LambdaScopeInfo *LSI);
+
+ /// \brief Define the "body" of the conversion from a lambda object to a
+ /// function pointer.
+ ///
+ /// This routine doesn't actually define a sensible body; rather, it fills
+ /// in the initialization expression needed to copy the lambda object into
+ /// the block, and IR generation actually generates the real body of the
+ /// block pointer conversion.
+ void DefineImplicitLambdaToFunctionPointerConversion(
+ SourceLocation CurrentLoc, CXXConversionDecl *Conv);
+
+ /// \brief Define the "body" of the conversion from a lambda object to a
+ /// block pointer.
+ ///
+ /// This routine doesn't actually define a sensible body; rather, it fills
+ /// in the initialization expression needed to copy the lambda object into
+ /// the block, and IR generation actually generates the real body of the
+ /// block pointer conversion.
+ void DefineImplicitLambdaToBlockPointerConversion(SourceLocation CurrentLoc,
+ CXXConversionDecl *Conv);
+
+ ExprResult BuildBlockForLambdaConversion(SourceLocation CurrentLocation,
+ SourceLocation ConvLocation,
+ CXXConversionDecl *Conv,
+ Expr *Src);
+
+ // ParseObjCStringLiteral - Parse Objective-C string literals.
+ ExprResult ParseObjCStringLiteral(SourceLocation *AtLocs,
+ ArrayRef<Expr *> Strings);
+
+ ExprResult BuildObjCStringLiteral(SourceLocation AtLoc, StringLiteral *S);
+
+ /// BuildObjCNumericLiteral - builds an ObjCBoxedExpr AST node for the
+ /// numeric literal expression. Type of the expression will be "NSNumber *"
+ /// or "id" if NSNumber is unavailable.
+ ExprResult BuildObjCNumericLiteral(SourceLocation AtLoc, Expr *Number);
+ ExprResult ActOnObjCBoolLiteral(SourceLocation AtLoc, SourceLocation ValueLoc,
+ bool Value);
+ ExprResult BuildObjCArrayLiteral(SourceRange SR, MultiExprArg Elements);
+
+ /// BuildObjCBoxedExpr - builds an ObjCBoxedExpr AST node for the
+ /// '@' prefixed parenthesized expression. The type of the expression will
+ /// either be "NSNumber *", "NSString *" or "NSValue *" depending on the type
+ /// of ValueType, which is allowed to be a built-in numeric type, "char *",
+ /// "const char *" or C structure with attribute 'objc_boxable'.
+ ExprResult BuildObjCBoxedExpr(SourceRange SR, Expr *ValueExpr);
+
+ ExprResult BuildObjCSubscriptExpression(SourceLocation RB, Expr *BaseExpr,
+ Expr *IndexExpr,
+ ObjCMethodDecl *getterMethod,
+ ObjCMethodDecl *setterMethod);
+
+ ExprResult BuildObjCDictionaryLiteral(SourceRange SR,
+ MutableArrayRef<ObjCDictionaryElement> Elements);
+
+ ExprResult BuildObjCEncodeExpression(SourceLocation AtLoc,
+ TypeSourceInfo *EncodedTypeInfo,
+ SourceLocation RParenLoc);
+ ExprResult BuildCXXMemberCallExpr(Expr *Exp, NamedDecl *FoundDecl,
+ CXXConversionDecl *Method,
+ bool HadMultipleCandidates);
+
+ 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,
+ bool WarnMultipleSelectors);
+
+ /// ParseObjCProtocolExpression - Build protocol expression for \@protocol
+ ExprResult ParseObjCProtocolExpression(IdentifierInfo * ProtocolName,
+ SourceLocation AtLoc,
+ SourceLocation ProtoLoc,
+ SourceLocation LParenLoc,
+ SourceLocation ProtoIdLoc,
+ SourceLocation RParenLoc);
+
+ //===--------------------------------------------------------------------===//
+ // C++ Declarations
+ //
+ Decl *ActOnStartLinkageSpecification(Scope *S,
+ SourceLocation ExternLoc,
+ Expr *LangStr,
+ SourceLocation LBraceLoc);
+ Decl *ActOnFinishLinkageSpecification(Scope *S,
+ Decl *LinkageSpec,
+ SourceLocation RBraceLoc);
+
+
+ //===--------------------------------------------------------------------===//
+ // C++ Classes
+ //
+ bool isCurrentClassName(const IdentifierInfo &II, Scope *S,
+ const CXXScopeSpec *SS = nullptr);
+ bool isCurrentClassNameTypo(IdentifierInfo *&II, const CXXScopeSpec *SS);
+
+ bool ActOnAccessSpecifier(AccessSpecifier Access,
+ SourceLocation ASLoc,
+ SourceLocation ColonLoc,
+ AttributeList *Attrs = nullptr);
+
+ NamedDecl *ActOnCXXMemberDeclarator(Scope *S, AccessSpecifier AS,
+ Declarator &D,
+ MultiTemplateParamsArg TemplateParameterLists,
+ Expr *BitfieldWidth, const VirtSpecifiers &VS,
+ InClassInitStyle InitStyle);
+
+ void ActOnStartCXXInClassMemberInitializer();
+ void ActOnFinishCXXInClassMemberInitializer(Decl *VarDecl,
+ SourceLocation EqualLoc,
+ Expr *Init);
+
+ MemInitResult ActOnMemInitializer(Decl *ConstructorD,
+ Scope *S,
+ CXXScopeSpec &SS,
+ IdentifierInfo *MemberOrBase,
+ ParsedType TemplateTypeTy,
+ const DeclSpec &DS,
+ SourceLocation IdLoc,
+ SourceLocation LParenLoc,
+ ArrayRef<Expr *> Args,
+ SourceLocation RParenLoc,
+ SourceLocation EllipsisLoc);
+
+ MemInitResult ActOnMemInitializer(Decl *ConstructorD,
+ Scope *S,
+ CXXScopeSpec &SS,
+ IdentifierInfo *MemberOrBase,
+ ParsedType TemplateTypeTy,
+ const DeclSpec &DS,
+ SourceLocation IdLoc,
+ Expr *InitList,
+ SourceLocation EllipsisLoc);
+
+ MemInitResult BuildMemInitializer(Decl *ConstructorD,
+ Scope *S,
+ CXXScopeSpec &SS,
+ IdentifierInfo *MemberOrBase,
+ ParsedType TemplateTypeTy,
+ const DeclSpec &DS,
+ SourceLocation IdLoc,
+ Expr *Init,
+ SourceLocation EllipsisLoc);
+
+ MemInitResult BuildMemberInitializer(ValueDecl *Member,
+ Expr *Init,
+ SourceLocation IdLoc);
+
+ MemInitResult BuildBaseInitializer(QualType BaseType,
+ TypeSourceInfo *BaseTInfo,
+ Expr *Init,
+ CXXRecordDecl *ClassDecl,
+ SourceLocation EllipsisLoc);
+
+ MemInitResult BuildDelegatingInitializer(TypeSourceInfo *TInfo,
+ Expr *Init,
+ CXXRecordDecl *ClassDecl);
+
+ bool SetDelegatingInitializer(CXXConstructorDecl *Constructor,
+ CXXCtorInitializer *Initializer);
+
+ bool SetCtorInitializers(CXXConstructorDecl *Constructor, bool AnyErrors,
+ ArrayRef<CXXCtorInitializer *> Initializers = None);
+
+ 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.
+ 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 Load any externally-stored vtable uses.
+ void LoadExternalVTableUses();
+
+ /// \brief Note that the vtable for the given class was used at the
+ /// given location.
+ void MarkVTableUsed(SourceLocation Loc, CXXRecordDecl *Class,
+ bool DefinitionRequired = false);
+
+ /// \brief Mark the exception specifications of all virtual member functions
+ /// in the given class as needed.
+ void MarkVirtualMemberExceptionSpecsNeeded(SourceLocation Loc,
+ const CXXRecordDecl *RD);
+
+ /// 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,
+ ArrayRef<CXXCtorInitializer*> MemInits,
+ bool AnyErrors);
+
+ void checkClassLevelDLLAttribute(CXXRecordDecl *Class);
+ void propagateDLLAttrToBaseClassTemplate(
+ CXXRecordDecl *Class, Attr *ClassAttr,
+ ClassTemplateSpecializationDecl *BaseTemplateSpec,
+ SourceLocation BaseLoc);
+ void CheckCompletedCXXClass(CXXRecordDecl *Record);
+ void ActOnFinishCXXMemberSpecification(Scope* S, SourceLocation RLoc,
+ Decl *TagDecl,
+ SourceLocation LBrac,
+ SourceLocation RBrac,
+ AttributeList *AttrList);
+ void ActOnFinishCXXMemberDecls();
+ void ActOnFinishCXXNonNestedClass(Decl *D);
+
+ void ActOnReenterCXXMethodParameter(Scope *S, ParmVarDecl *Param);
+ unsigned ActOnReenterTemplateScope(Scope *S, Decl *Template);
+ void ActOnStartDelayedMemberDeclarations(Scope *S, Decl *Record);
+ void ActOnStartDelayedCXXMethodDeclaration(Scope *S, Decl *Method);
+ void ActOnDelayedCXXMethodParameter(Scope *S, Decl *Param);
+ void ActOnFinishDelayedMemberDeclarations(Scope *S, Decl *Record);
+ void ActOnFinishDelayedCXXMethodDeclaration(Scope *S, Decl *Method);
+ void ActOnFinishDelayedMemberInitializers(Decl *Record);
+ void MarkAsLateParsedTemplate(FunctionDecl *FD, Decl *FnD,
+ CachedTokens &Toks);
+ void UnmarkAsLateParsedTemplate(FunctionDecl *FD);
+ bool IsInsideALocalClassWithinATemplateFunction();
+
+ Decl *ActOnStaticAssertDeclaration(SourceLocation StaticAssertLoc,
+ Expr *AssertExpr,
+ Expr *AssertMessageExpr,
+ SourceLocation RParenLoc);
+ Decl *BuildStaticAssertDeclaration(SourceLocation StaticAssertLoc,
+ Expr *AssertExpr,
+ StringLiteral *AssertMessageExpr,
+ SourceLocation RParenLoc,
+ bool Failed);
+
+ FriendDecl *CheckFriendTypeDecl(SourceLocation LocStart,
+ SourceLocation FriendLoc,
+ TypeSourceInfo *TSInfo);
+ Decl *ActOnFriendTypeDecl(Scope *S, const DeclSpec &DS,
+ MultiTemplateParamsArg TemplateParams);
+ NamedDecl *ActOnFriendFunctionDecl(Scope *S, Declarator &D,
+ 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);
+
+ void CheckExplicitlyDefaultedSpecialMember(CXXMethodDecl *MD);
+ void CheckExplicitlyDefaultedMemberExceptionSpec(CXXMethodDecl *MD,
+ const FunctionProtoType *T);
+ void CheckDelayedMemberExceptionSpecs();
+
+ //===--------------------------------------------------------------------===//
+ // 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,
+ ParsedAttributes &Attrs,
+ bool Virtual, AccessSpecifier Access,
+ ParsedType basetype,
+ SourceLocation BaseLoc,
+ SourceLocation EllipsisLoc);
+
+ bool AttachBaseSpecifiers(CXXRecordDecl *Class,
+ MutableArrayRef<CXXBaseSpecifier *> Bases);
+ void ActOnBaseSpecifiers(Decl *ClassDecl,
+ MutableArrayRef<CXXBaseSpecifier *> Bases);
+
+ bool IsDerivedFrom(SourceLocation Loc, QualType Derived, QualType Base);
+ bool IsDerivedFrom(SourceLocation Loc, QualType Derived, QualType Base,
+ CXXBasePaths &Paths);
+
+ // FIXME: I don't like this name.
+ void BuildBasePathArray(const CXXBasePaths &Paths, CXXCastPath &BasePath);
+
+ bool CheckDerivedToBaseConversion(QualType Derived, QualType Base,
+ SourceLocation Loc, SourceRange Range,
+ CXXCastPath *BasePath = nullptr,
+ 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);
+
+ bool CheckOverridingFunctionAttributes(const CXXMethodDecl *New,
+ const CXXMethodDecl *Old);
+
+ /// 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++11 override control semantics.
+ void CheckOverrideControl(NamedDecl *D);
+
+ /// DiagnoseAbsenceOfOverrideControl - Diagnose if 'override' keyword was
+ /// not used in the declaration of an overriding method.
+ void DiagnoseAbsenceOfOverrideControl(NamedDecl *D);
+
+ /// CheckForFunctionMarkedFinal - Checks whether a virtual member function
+ /// overrides a virtual member function marked 'final', according to
+ /// C++11 [class.virtual]p4.
+ 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,
+ bool Diagnose = true);
+ AccessResult CheckConstructorAccess(SourceLocation Loc,
+ CXXConstructorDecl *D,
+ const InitializedEntity &Entity,
+ AccessSpecifier Access,
+ bool IsCopyBindingRefToTemp = false);
+ AccessResult CheckConstructorAccess(SourceLocation Loc,
+ CXXConstructorDecl *D,
+ const InitializedEntity &Entity,
+ AccessSpecifier Access,
+ const PartialDiagnostic &PDiag);
+ AccessResult CheckDestructorAccess(SourceLocation Loc,
+ CXXDestructorDecl *Dtor,
+ const PartialDiagnostic &PDiag,
+ QualType objectType = QualType());
+ AccessResult CheckFriendAccess(NamedDecl *D);
+ AccessResult CheckMemberAccess(SourceLocation UseLoc,
+ CXXRecordDecl *NamingClass,
+ DeclAccessPair Found);
+ 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);
+ bool IsSimplyAccessible(NamedDecl *decl, DeclContext *Ctx);
+ bool isSpecialMemberAccessibleForDeletion(CXXMethodDecl *decl,
+ AccessSpecifier access,
+ QualType objectType);
+
+ void HandleDependentAccessCheck(const DependentDiagnostic &DD,
+ const MultiLevelTemplateArgumentList &TemplateArgs);
+ void PerformDependentDiagnostics(const DeclContext *Pattern,
+ const MultiLevelTemplateArgumentList &TemplateArgs);
+
+ void HandleDelayedAccessCheck(sema::DelayedDiagnostic &DD, Decl *Ctx);
+
+ /// \brief When true, access checking violations are treated as SFINAE
+ /// failures rather than hard errors.
+ bool AccessCheckingSFINAE;
+
+ enum AbstractDiagSelID {
+ AbstractNone = -1,
+ AbstractReturnType,
+ AbstractParamType,
+ AbstractVariableType,
+ AbstractFieldType,
+ AbstractIvarType,
+ AbstractSynthesizedIvarType,
+ AbstractArrayType
+ };
+
+ bool isAbstractType(SourceLocation Loc, QualType T);
+ bool RequireNonAbstractType(SourceLocation Loc, QualType T,
+ TypeDiagnoser &Diagnoser);
+ template <typename... Ts>
+ bool RequireNonAbstractType(SourceLocation Loc, QualType T, unsigned DiagID,
+ const Ts &...Args) {
+ BoundTypeDiagnoser<Ts...> Diagnoser(DiagID, Args...);
+ return RequireNonAbstractType(Loc, T, Diagnoser);
+ }
+
+ void DiagnoseAbstractType(const CXXRecordDecl *RD);
+
+ //===--------------------------------------------------------------------===//
+ // C++ Overloaded Operators [C++ 13.5]
+ //
+
+ bool CheckOverloadedOperatorDeclaration(FunctionDecl *FnDecl);
+
+ bool CheckLiteralOperatorDeclaration(FunctionDecl *FnDecl);
+
+ //===--------------------------------------------------------------------===//
+ // C++ Templates [C++ 14]
+ //
+ void FilterAcceptableTemplateNames(LookupResult &R,
+ bool AllowFunctionTemplates = true);
+ bool hasAnyAcceptableTemplateNames(LookupResult &R,
+ bool AllowFunctionTemplates = true);
+
+ 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);
+
+ void DiagnoseTemplateParameterShadow(SourceLocation Loc, Decl *PrevDecl);
+ TemplateDecl *AdjustDeclIfTemplate(Decl *&Decl);
+
+ Decl *ActOnTypeParameter(Scope *S, bool Typename,
+ 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,
+ TemplateParameterList *Params,
+ SourceLocation EllipsisLoc,
+ IdentifierInfo *ParamName,
+ SourceLocation ParamNameLoc,
+ unsigned Depth,
+ unsigned Position,
+ SourceLocation EqualLoc,
+ ParsedTemplateArgument DefaultArg);
+
+ TemplateParameterList *
+ ActOnTemplateParameterList(unsigned Depth,
+ SourceLocation ExportLoc,
+ SourceLocation TemplateLoc,
+ SourceLocation LAngleLoc,
+ ArrayRef<Decl *> Params,
+ SourceLocation RAngleLoc);
+
+ /// \brief The context in which we are checking a template parameter list.
+ enum TemplateParamListContext {
+ TPC_ClassTemplate,
+ TPC_VarTemplate,
+ TPC_FunctionTemplate,
+ TPC_ClassTemplateMember,
+ TPC_FriendClassTemplate,
+ TPC_FriendFunctionTemplate,
+ TPC_FriendFunctionTemplateDefinition,
+ TPC_TypeAliasTemplate
+ };
+
+ bool CheckTemplateParameterList(TemplateParameterList *NewParams,
+ TemplateParameterList *OldParams,
+ TemplateParamListContext TPC);
+ TemplateParameterList *MatchTemplateParametersToScopeSpecifier(
+ SourceLocation DeclStartLoc, SourceLocation DeclLoc,
+ const CXXScopeSpec &SS, TemplateIdAnnotation *TemplateId,
+ ArrayRef<TemplateParameterList *> ParamLists,
+ 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,
+ SourceLocation ModulePrivateLoc,
+ SourceLocation FriendLoc,
+ unsigned NumOuterTemplateParamLists,
+ TemplateParameterList **OuterTemplateParamLists,
+ SkipBodyInfo *SkipBody = nullptr);
+
+ void translateTemplateArguments(const ASTTemplateArgsPtr &In,
+ TemplateArgumentListInfo &Out);
+
+ void NoteAllFoundTemplates(TemplateName Name);
+
+ QualType CheckTemplateIdType(TemplateName Template,
+ SourceLocation TemplateLoc,
+ TemplateArgumentListInfo &TemplateArgs);
+
+ TypeResult
+ ActOnTemplateIdType(CXXScopeSpec &SS, SourceLocation TemplateKWLoc,
+ TemplateTy Template, SourceLocation TemplateLoc,
+ SourceLocation LAngleLoc,
+ ASTTemplateArgsPtr TemplateArgs,
+ SourceLocation RAngleLoc,
+ bool IsCtorOrDtorName = false);
+
+ /// \brief Parsed an elaborated-type-specifier that refers to a template-id,
+ /// such as \c class T::template apply<U>.
+ TypeResult ActOnTagTemplateIdType(TagUseKind TUK,
+ TypeSpecifierType TagSpec,
+ SourceLocation TagLoc,
+ CXXScopeSpec &SS,
+ SourceLocation TemplateKWLoc,
+ TemplateTy TemplateD,
+ SourceLocation TemplateLoc,
+ SourceLocation LAngleLoc,
+ ASTTemplateArgsPtr TemplateArgsIn,
+ SourceLocation RAngleLoc);
+
+ DeclResult ActOnVarTemplateSpecialization(
+ Scope *S, Declarator &D, TypeSourceInfo *DI,
+ SourceLocation TemplateKWLoc, TemplateParameterList *TemplateParams,
+ StorageClass SC, bool IsPartialSpecialization);
+
+ DeclResult CheckVarTemplateId(VarTemplateDecl *Template,
+ SourceLocation TemplateLoc,
+ SourceLocation TemplateNameLoc,
+ const TemplateArgumentListInfo &TemplateArgs);
+
+ ExprResult CheckVarTemplateId(const CXXScopeSpec &SS,
+ const DeclarationNameInfo &NameInfo,
+ VarTemplateDecl *Template,
+ SourceLocation TemplateLoc,
+ const TemplateArgumentListInfo *TemplateArgs);
+
+ ExprResult BuildTemplateIdExpr(const CXXScopeSpec &SS,
+ SourceLocation TemplateKWLoc,
+ LookupResult &R,
+ bool RequiresADL,
+ const TemplateArgumentListInfo *TemplateArgs);
+
+ ExprResult BuildQualifiedTemplateIdExpr(CXXScopeSpec &SS,
+ SourceLocation TemplateKWLoc,
+ const DeclarationNameInfo &NameInfo,
+ const TemplateArgumentListInfo *TemplateArgs);
+
+ TemplateNameKind ActOnDependentTemplateName(Scope *S,
+ CXXScopeSpec &SS,
+ SourceLocation TemplateKWLoc,
+ UnqualifiedId &Name,
+ ParsedType ObjectType,
+ bool EnteringContext,
+ TemplateTy &Template);
+
+ DeclResult
+ ActOnClassTemplateSpecialization(Scope *S, unsigned TagSpec, TagUseKind TUK,
+ SourceLocation KWLoc,
+ SourceLocation ModulePrivateLoc,
+ TemplateIdAnnotation &TemplateId,
+ AttributeList *Attr,
+ MultiTemplateParamsArg TemplateParameterLists,
+ SkipBodyInfo *SkipBody = nullptr);
+
+ Decl *ActOnTemplateDeclarator(Scope *S,
+ 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,
+ 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,
+ SmallVectorImpl<TemplateArgument>
+ &Converted,
+ bool &HasDefaultArg);
+
+ /// \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,
+ TemplateArgumentLoc &Arg,
+ NamedDecl *Template,
+ SourceLocation TemplateLoc,
+ SourceLocation RAngleLoc,
+ unsigned ArgumentPackIndex,
+ SmallVectorImpl<TemplateArgument> &Converted,
+ CheckTemplateArgumentKind CTAK = CTAK_Specified);
+
+ /// \brief Check that the given template arguments can be be provided to
+ /// the given template, converting the arguments along the way.
+ ///
+ /// \param Template The template to which the template arguments are being
+ /// provided.
+ ///
+ /// \param TemplateLoc The location of the template name in the source.
+ ///
+ /// \param TemplateArgs The list of template arguments. If the template is
+ /// a template template parameter, this function may extend the set of
+ /// template arguments to also include substituted, defaulted template
+ /// arguments.
+ ///
+ /// \param PartialTemplateArgs True if the list of template arguments is
+ /// intentionally partial, e.g., because we're checking just the initial
+ /// set of template arguments.
+ ///
+ /// \param Converted Will receive the converted, canonicalized template
+ /// arguments.
+ ///
+ /// \returns true if an error occurred, false otherwise.
+ bool CheckTemplateArgumentList(TemplateDecl *Template,
+ SourceLocation TemplateLoc,
+ TemplateArgumentListInfo &TemplateArgs,
+ bool PartialTemplateArgs,
+ SmallVectorImpl<TemplateArgument> &Converted);
+
+ bool CheckTemplateTypeArgument(TemplateTypeParmDecl *Param,
+ TemplateArgumentLoc &Arg,
+ SmallVectorImpl<TemplateArgument> &Converted);
+
+ bool CheckTemplateArgument(TemplateTypeParmDecl *Param,
+ TypeSourceInfo *Arg);
+ ExprResult CheckTemplateArgument(NonTypeTemplateParmDecl *Param,
+ QualType InstantiatedParamType, Expr *Arg,
+ TemplateArgument &Converted,
+ CheckTemplateArgumentKind CTAK = CTAK_Specified);
+ bool CheckTemplateArgument(TemplateTemplateParmDecl *Param,
+ TemplateArgumentLoc &Arg,
+ unsigned ArgumentPackIndex);
+
+ 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 TemplateName The template name.
+ /// \param TemplateNameLoc The location of the template name.
+ /// \param LAngleLoc The location of the opening angle bracket ('<').
+ /// \param TemplateArgs The template arguments.
+ /// \param RAngleLoc The location of the closing angle bracket ('>').
+ TypeResult
+ ActOnTypenameType(Scope *S, SourceLocation TypenameLoc,
+ const CXXScopeSpec &SS,
+ SourceLocation TemplateLoc,
+ TemplateTy TemplateName,
+ SourceLocation TemplateNameLoc,
+ SourceLocation LAngleLoc,
+ ASTTemplateArgsPtr TemplateArgs,
+ SourceLocation RAngleLoc);
+
+ QualType CheckTypenameType(ElaboratedTypeKeyword Keyword,
+ SourceLocation KeywordLoc,
+ NestedNameSpecifierLoc QualifierLoc,
+ const IdentifierInfo &II,
+ SourceLocation IILoc);
+
+ TypeSourceInfo *RebuildTypeInCurrentInstantiation(TypeSourceInfo *T,
+ SourceLocation Loc,
+ DeclarationName Name);
+ bool RebuildNestedNameSpecifierInCurrentInstantiation(CXXScopeSpec &SS);
+
+ ExprResult RebuildExprInCurrentInstantiation(Expr *E);
+ bool RebuildTemplateParamsInCurrentInstantiation(
+ TemplateParameterList *Params);
+
+ 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])
+ //===--------------------------------------------------------------------===//
+
+ /// Determine whether an unexpanded parameter pack might be permitted in this
+ /// location. Useful for error recovery.
+ bool isUnexpandedParameterPackPermitted();
+
+ /// \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 Microsoft __if_exists.
+ UPPC_IfExists,
+
+ /// \brief Microsoft __if_not_exists.
+ UPPC_IfNotExists,
+
+ /// \brief Lambda expression.
+ UPPC_Lambda,
+
+ /// \brief Block expression,
+ UPPC_Block
+ };
+
+ /// \brief Diagnose unexpanded parameter packs.
+ ///
+ /// \param Loc The location at which we should emit the diagnostic.
+ ///
+ /// \param UPPC The context in which we are diagnosing unexpanded
+ /// parameter packs.
+ ///
+ /// \param Unexpanded the set of unexpanded parameter packs.
+ ///
+ /// \returns true if an error occurred, false otherwise.
+ bool DiagnoseUnexpandedParameterPacks(SourceLocation Loc,
+ UnexpandedParameterPackContext UPPC,
+ ArrayRef<UnexpandedParameterPack> Unexpanded);
+
+ /// \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 occurred, 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 occurred, 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 occurred, 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 occurred, 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 occurred, 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 occurred, 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,
+ 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,
+ 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,
+ 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,
+ SmallVectorImpl<UnexpandedParameterPack> &Unexpanded);
+
+ /// \brief Collect the set of unexpanded parameter packs within the given
+ /// nested-name-specifier.
+ ///
+ /// \param SS The nested-name-specifier that will be traversed to find
+ /// unexpanded parameter packs.
+ void collectUnexpandedParameterPacks(CXXScopeSpec &SS,
+ SmallVectorImpl<UnexpandedParameterPack> &Unexpanded);
+
+ /// \brief Collect the set of unexpanded parameter packs within the given
+ /// name.
+ ///
+ /// \param NameInfo The name that will be traversed to find
+ /// unexpanded parameter packs.
+ void collectUnexpandedParameterPacks(const DeclarationNameInfo &NameInfo,
+ 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,
+ Optional<unsigned> NumExpansions);
+
+ /// \brief Construct a pack expansion type from the pattern of the pack
+ /// expansion.
+ QualType CheckPackExpansion(QualType Pattern,
+ SourceRange PatternRange,
+ SourceLocation EllipsisLoc,
+ 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,
+ 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 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,
+ ArrayRef<UnexpandedParameterPack> Unexpanded,
+ const MultiLevelTemplateArgumentList &TemplateArgs,
+ bool &ShouldExpand,
+ bool &RetainExpansion,
+ Optional<unsigned> &NumExpansions);
+
+ /// \brief Determine the number of arguments in the given pack expansion
+ /// type.
+ ///
+ /// This routine assumes that the number of arguments in the expansion is
+ /// consistent across all of the unexpanded parameter packs in its pattern.
+ ///
+ /// Returns an empty Optional if the type can't be expanded.
+ Optional<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);
+
+ /// \brief Returns the pattern of the pack expansion for a template argument.
+ ///
+ /// \param OrigLoc The template argument to expand.
+ ///
+ /// \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 getTemplateArgumentPackExpansionPattern(
+ TemplateArgumentLoc OrigLoc,
+ SourceLocation &Ellipsis,
+ Optional<unsigned> &NumExpansions) const;
+
+ //===--------------------------------------------------------------------===//
+ // C++ Template Argument Deduction (C++ [temp.deduct])
+ //===--------------------------------------------------------------------===//
+
+ QualType adjustCCAndNoReturn(QualType ArgFunctionType, QualType FunctionType);
+
+ /// \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 The declaration was invalid; do nothing.
+ TDK_Invalid,
+ /// \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 After substituting deduced template arguments, a dependent
+ /// parameter type did not match the corresponding argument.
+ TDK_DeducedMismatch,
+ /// \brief A non-depnedent component of the parameter did not match the
+ /// corresponding component of the argument.
+ 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,
+ /// \brief Deduction failed; that's all we know.
+ TDK_MiscellaneousDeductionFailure
+ };
+
+ TemplateDeductionResult
+ DeduceTemplateArguments(ClassTemplatePartialSpecializationDecl *Partial,
+ const TemplateArgumentList &TemplateArgs,
+ sema::TemplateDeductionInfo &Info);
+
+ TemplateDeductionResult
+ DeduceTemplateArguments(VarTemplatePartialSpecializationDecl *Partial,
+ const TemplateArgumentList &TemplateArgs,
+ sema::TemplateDeductionInfo &Info);
+
+ TemplateDeductionResult SubstituteExplicitTemplateArguments(
+ FunctionTemplateDecl *FunctionTemplate,
+ TemplateArgumentListInfo &ExplicitTemplateArgs,
+ SmallVectorImpl<DeducedTemplateArgument> &Deduced,
+ SmallVectorImpl<QualType> &ParamTypes, QualType *FunctionType,
+ sema::TemplateDeductionInfo &Info);
+
+ /// brief A function argument from which we performed template argument
+ // deduction for a call.
+ struct OriginalCallArg {
+ OriginalCallArg(QualType OriginalParamType,
+ unsigned ArgIdx,
+ QualType OriginalArgType)
+ : OriginalParamType(OriginalParamType), ArgIdx(ArgIdx),
+ OriginalArgType(OriginalArgType) { }
+
+ QualType OriginalParamType;
+ unsigned ArgIdx;
+ QualType OriginalArgType;
+ };
+
+ TemplateDeductionResult
+ FinishTemplateArgumentDeduction(FunctionTemplateDecl *FunctionTemplate,
+ SmallVectorImpl<DeducedTemplateArgument> &Deduced,
+ unsigned NumExplicitlySpecified,
+ FunctionDecl *&Specialization,
+ sema::TemplateDeductionInfo &Info,
+ SmallVectorImpl<OriginalCallArg> const *OriginalCallArgs = nullptr,
+ bool PartialOverloading = false);
+
+ TemplateDeductionResult
+ DeduceTemplateArguments(FunctionTemplateDecl *FunctionTemplate,
+ TemplateArgumentListInfo *ExplicitTemplateArgs,
+ ArrayRef<Expr *> Args,
+ FunctionDecl *&Specialization,
+ sema::TemplateDeductionInfo &Info,
+ bool PartialOverloading = false);
+
+ TemplateDeductionResult
+ DeduceTemplateArguments(FunctionTemplateDecl *FunctionTemplate,
+ TemplateArgumentListInfo *ExplicitTemplateArgs,
+ QualType ArgFunctionType,
+ FunctionDecl *&Specialization,
+ sema::TemplateDeductionInfo &Info,
+ bool InOverloadResolution = false);
+
+ TemplateDeductionResult
+ DeduceTemplateArguments(FunctionTemplateDecl *FunctionTemplate,
+ QualType ToType,
+ CXXConversionDecl *&Specialization,
+ sema::TemplateDeductionInfo &Info);
+
+ TemplateDeductionResult
+ DeduceTemplateArguments(FunctionTemplateDecl *FunctionTemplate,
+ TemplateArgumentListInfo *ExplicitTemplateArgs,
+ FunctionDecl *&Specialization,
+ sema::TemplateDeductionInfo &Info,
+ bool InOverloadResolution = false);
+
+ /// \brief Substitute Replacement for \p auto in \p TypeWithAuto
+ QualType SubstAutoType(QualType TypeWithAuto, QualType Replacement);
+ /// \brief Substitute Replacement for auto in TypeWithAuto
+ TypeSourceInfo* SubstAutoTypeSourceInfo(TypeSourceInfo *TypeWithAuto,
+ QualType Replacement);
+
+ /// \brief Result type of DeduceAutoType.
+ enum DeduceAutoResult {
+ DAR_Succeeded,
+ DAR_Failed,
+ DAR_FailedAlreadyDiagnosed
+ };
+
+ DeduceAutoResult DeduceAutoType(TypeSourceInfo *AutoType, Expr *&Initializer,
+ QualType &Result);
+ DeduceAutoResult DeduceAutoType(TypeLoc AutoTypeLoc, Expr *&Initializer,
+ QualType &Result);
+ void DiagnoseAutoDeductionFailure(VarDecl *VDecl, Expr *Init);
+ bool DeduceReturnType(FunctionDecl *FD, SourceLocation Loc,
+ bool Diagnose = true);
+
+ QualType deduceVarTypeFromInitializer(VarDecl *VDecl, DeclarationName Name,
+ QualType Type, TypeSourceInfo *TSI,
+ SourceRange Range, bool DirectInit,
+ Expr *Init);
+
+ TypeLoc getReturnTypeLoc(FunctionDecl *FD) const;
+
+ bool DeduceFunctionTypeFromReturnExpr(FunctionDecl *FD,
+ SourceLocation ReturnLoc,
+ Expr *&RetExpr, AutoType *AT);
+
+ FunctionTemplateDecl *getMoreSpecializedTemplate(FunctionTemplateDecl *FT1,
+ FunctionTemplateDecl *FT2,
+ SourceLocation Loc,
+ TemplatePartialOrderingContext TPOC,
+ unsigned NumCallArguments1,
+ unsigned NumCallArguments2);
+ UnresolvedSetIterator
+ getMostSpecialized(UnresolvedSetIterator SBegin, UnresolvedSetIterator SEnd,
+ TemplateSpecCandidateSet &FailedCandidates,
+ SourceLocation Loc,
+ const PartialDiagnostic &NoneDiag,
+ const PartialDiagnostic &AmbigDiag,
+ const PartialDiagnostic &CandidateDiag,
+ bool Complain = true, QualType TargetType = QualType());
+
+ ClassTemplatePartialSpecializationDecl *
+ getMoreSpecializedPartialSpecialization(
+ ClassTemplatePartialSpecializationDecl *PS1,
+ ClassTemplatePartialSpecializationDecl *PS2,
+ SourceLocation Loc);
+
+ VarTemplatePartialSpecializationDecl *getMoreSpecializedPartialSpecialization(
+ VarTemplatePartialSpecializationDecl *PS1,
+ VarTemplatePartialSpecializationDecl *PS2, SourceLocation Loc);
+
+ void MarkUsedTemplateParameters(const TemplateArgumentList &TemplateArgs,
+ bool OnlyDeduced,
+ unsigned Depth,
+ llvm::SmallBitVector &Used);
+ void MarkDeducedTemplateParameters(
+ const FunctionTemplateDecl *FunctionTemplate,
+ llvm::SmallBitVector &Deduced) {
+ return MarkDeducedTemplateParameters(Context, FunctionTemplate, Deduced);
+ }
+ static void MarkDeducedTemplateParameters(ASTContext &Ctx,
+ const FunctionTemplateDecl *FunctionTemplate,
+ llvm::SmallBitVector &Deduced);
+
+ //===--------------------------------------------------------------------===//
+ // C++ Template Instantiation
+ //
+
+ MultiLevelTemplateArgumentList
+ getTemplateInstantiationArgs(NamedDecl *D,
+ const TemplateArgumentList *Innermost = nullptr,
+ bool RelativeToPrimary = false,
+ const FunctionDecl *Pattern = nullptr);
+
+ /// \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,
+
+ /// We are instantiating the exception specification for a function
+ /// template which was deferred until it was needed.
+ ExceptionSpecInstantiation
+ } 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.
+ Decl *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(nullptr), Entity(nullptr),
+ TemplateArgs(nullptr), NumTemplateArgs(0), DeductionInfo(nullptr) {}
+
+ /// \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:
+ case ExceptionSpecInstantiation:
+ return true;
+
+ case PriorTemplateArgumentSubstitution:
+ case DefaultTemplateArgumentChecking:
+ return X.Template == Y.Template && X.TemplateArgs == Y.TemplateArgs;
+
+ case DefaultTemplateArgumentInstantiation:
+ case ExplicitTemplateArgumentSubstitution:
+ case DeducedTemplateArgumentSubstitution:
+ case DefaultFunctionArgumentInstantiation:
+ return X.TemplateArgs == Y.TemplateArgs;
+
+ }
+
+ llvm_unreachable("Invalid InstantiationKind!");
+ }
+
+ 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.
+ SmallVector<ActiveTemplateInstantiation, 16>
+ ActiveTemplateInstantiations;
+
+ /// \brief Extra modules inspected when performing a lookup during a template
+ /// instantiation. Computed lazily.
+ SmallVector<Module*, 16> ActiveTemplateInstantiationLookupModules;
+
+ /// \brief Cache of additional modules that should be used for name lookup
+ /// within the current template instantiation. Computed lazily; use
+ /// getLookupModules() to get a complete set.
+ llvm::DenseSet<Module*> LookupModulesCache;
+
+ /// \brief Get the set of additional modules that should be checked during
+ /// name lookup. A module and its imports become visible when instanting a
+ /// template defined within it.
+ llvm::DenseSet<Module*> &getLookupModules();
+
+ /// \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 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.
+ typedef llvm::DenseMap<Decl *, SmallVector<PartialDiagnosticAt, 1> >
+ SuppressedDiagnosticsMap;
+ SuppressedDiagnosticsMap 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, variable template, alias template,
+ /// or a member thereof.
+ InstantiatingTemplate(Sema &SemaRef, SourceLocation PointOfInstantiation,
+ Decl *Entity,
+ SourceRange InstantiationRange = SourceRange());
+
+ struct ExceptionSpecification {};
+ /// \brief Note that we are instantiating an exception specification
+ /// of a function template.
+ InstantiatingTemplate(Sema &SemaRef, SourceLocation PointOfInstantiation,
+ FunctionDecl *Entity, ExceptionSpecification,
+ SourceRange InstantiationRange = SourceRange());
+
+ /// \brief Note that we are instantiating a default argument in a
+ /// template-id.
+ InstantiatingTemplate(Sema &SemaRef, SourceLocation PointOfInstantiation,
+ TemplateDecl *Template,
+ ArrayRef<TemplateArgument> TemplateArgs,
+ SourceRange InstantiationRange = SourceRange());
+
+ /// \brief Note that we are instantiating a default argument in a
+ /// template-id.
+ InstantiatingTemplate(Sema &SemaRef, SourceLocation PointOfInstantiation,
+ FunctionTemplateDecl *FunctionTemplate,
+ ArrayRef<TemplateArgument> TemplateArgs,
+ 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,
+ ArrayRef<TemplateArgument> TemplateArgs,
+ sema::TemplateDeductionInfo &DeductionInfo,
+ SourceRange InstantiationRange = SourceRange());
+
+ /// \brief Note that we are instantiating as part of template
+ /// argument deduction for a variable template partial
+ /// specialization.
+ InstantiatingTemplate(Sema &SemaRef, SourceLocation PointOfInstantiation,
+ VarTemplatePartialSpecializationDecl *PartialSpec,
+ ArrayRef<TemplateArgument> TemplateArgs,
+ sema::TemplateDeductionInfo &DeductionInfo,
+ SourceRange InstantiationRange = SourceRange());
+
+ /// \brief Note that we are instantiating a default argument for a function
+ /// parameter.
+ InstantiatingTemplate(Sema &SemaRef, SourceLocation PointOfInstantiation,
+ ParmVarDecl *Param,
+ ArrayRef<TemplateArgument> TemplateArgs,
+ SourceRange InstantiationRange = SourceRange());
+
+ /// \brief Note that we are substituting prior template arguments into a
+ /// non-type parameter.
+ InstantiatingTemplate(Sema &SemaRef, SourceLocation PointOfInstantiation,
+ NamedDecl *Template,
+ NonTypeTemplateParmDecl *Param,
+ ArrayRef<TemplateArgument> TemplateArgs,
+ SourceRange InstantiationRange);
+
+ /// \brief Note that we are substituting prior template arguments into a
+ /// template template parameter.
+ InstantiatingTemplate(Sema &SemaRef, SourceLocation PointOfInstantiation,
+ NamedDecl *Template,
+ TemplateTemplateParmDecl *Param,
+ ArrayRef<TemplateArgument> TemplateArgs,
+ 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,
+ ArrayRef<TemplateArgument> TemplateArgs,
+ 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.
+ bool isInvalid() const { return Invalid; }
+
+ private:
+ Sema &SemaRef;
+ bool Invalid;
+ bool SavedInNonInstantiationSFINAEContext;
+ bool CheckInstantiationDepth(SourceLocation PointOfInstantiation,
+ SourceRange InstantiationRange);
+
+ InstantiatingTemplate(
+ Sema &SemaRef, ActiveTemplateInstantiation::InstantiationKind Kind,
+ SourceLocation PointOfInstantiation, SourceRange InstantiationRange,
+ Decl *Entity, NamedDecl *Template = nullptr,
+ ArrayRef<TemplateArgument> TemplateArgs = None,
+ sema::TemplateDeductionInfo *DeductionInfo = nullptr);
+
+ InstantiatingTemplate(const InstantiatingTemplate&) = delete;
+
+ InstantiatingTemplate&
+ operator=(const InstantiatingTemplate&) = delete;
+ };
+
+ void PrintInstantiationStack();
+
+ /// \brief Determines whether we are currently in a context where
+ /// template argument substitution failures are not considered
+ /// errors.
+ ///
+ /// \returns An empty \c 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.
+ Optional<sema::TemplateDeductionInfo *> isSFINAEContext() const;
+
+ /// \brief Determines whether we are currently in a context that
+ /// is not evaluated as per C++ [expr] p5.
+ bool isUnevaluatedContext() const {
+ assert(!ExprEvalContexts.empty() &&
+ "Must be in an expression evaluation context");
+ return ExprEvalContexts.back().isUnevaluated();
+ }
+
+ /// \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 RAII class used to indicate that we are performing provisional
+ /// semantic analysis to determine the validity of a construct, so
+ /// typo-correction and diagnostics in the immediate context (not within
+ /// implicitly-instantiated templates) should be suppressed.
+ class TentativeAnalysisScope {
+ Sema &SemaRef;
+ // FIXME: Using a SFINAETrap for this is a hack.
+ SFINAETrap Trap;
+ bool PrevDisableTypoCorrection;
+ public:
+ explicit TentativeAnalysisScope(Sema &SemaRef)
+ : SemaRef(SemaRef), Trap(SemaRef, true),
+ PrevDisableTypoCorrection(SemaRef.DisableTypoCorrection) {
+ SemaRef.DisableTypoCorrection = true;
+ }
+ ~TentativeAnalysisScope() {
+ SemaRef.DisableTypoCorrection = PrevDisableTypoCorrection;
+ }
+ };
+
+ /// \brief The current instantiation scope used to store local
+ /// variables.
+ LocalInstantiationScope *CurrentInstantiationScope;
+
+ /// \brief Tracks whether we are in a context where typo correction is
+ /// disabled.
+ bool DisableTypoCorrection;
+
+ /// \brief The number of typos corrected by CorrectTypo.
+ unsigned TyposCorrected;
+
+ typedef llvm::SmallSet<SourceLocation, 2> SrcLocSet;
+ typedef llvm::DenseMap<IdentifierInfo *, SrcLocSet> IdentifierSourceLocations;
+
+ /// \brief A cache containing identifiers for which typo correction failed and
+ /// their locations, so that repeated attempts to correct an identifier in a
+ /// given location are ignored if typo correction already failed for it.
+ IdentifierSourceLocations TypoCorrectionFailures;
+
+ /// \brief Worker object for performing CFG-based warnings.
+ sema::AnalysisBasedWarnings AnalysisWarnings;
+ threadSafety::BeforeSet *ThreadSafetyDeclCache;
+
+ /// \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;
+
+ class SavePendingInstantiationsAndVTableUsesRAII {
+ public:
+ SavePendingInstantiationsAndVTableUsesRAII(Sema &S, bool Enabled)
+ : S(S), Enabled(Enabled) {
+ if (!Enabled) return;
+
+ SavedPendingInstantiations.swap(S.PendingInstantiations);
+ SavedVTableUses.swap(S.VTableUses);
+ }
+
+ ~SavePendingInstantiationsAndVTableUsesRAII() {
+ if (!Enabled) return;
+
+ // Restore the set of pending vtables.
+ assert(S.VTableUses.empty() &&
+ "VTableUses should be empty before it is discarded.");
+ S.VTableUses.swap(SavedVTableUses);
+
+ // Restore the set of pending implicit instantiations.
+ assert(S.PendingInstantiations.empty() &&
+ "PendingInstantiations should be empty before it is discarded.");
+ S.PendingInstantiations.swap(SavedPendingInstantiations);
+ }
+
+ private:
+ Sema &S;
+ SmallVector<VTableUse, 16> SavedVTableUses;
+ std::deque<PendingImplicitInstantiation> SavedPendingInstantiations;
+ bool Enabled;
+ };
+
+ /// \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;
+
+ class SavePendingLocalImplicitInstantiationsRAII {
+ public:
+ SavePendingLocalImplicitInstantiationsRAII(Sema &S): S(S) {
+ SavedPendingLocalImplicitInstantiations.swap(
+ S.PendingLocalImplicitInstantiations);
+ }
+
+ ~SavePendingLocalImplicitInstantiationsRAII() {
+ assert(S.PendingLocalImplicitInstantiations.empty() &&
+ "there shouldn't be any pending local implicit instantiations");
+ SavedPendingLocalImplicitInstantiations.swap(
+ S.PendingLocalImplicitInstantiations);
+ }
+
+ private:
+ Sema &S;
+ std::deque<PendingImplicitInstantiation>
+ SavedPendingLocalImplicitInstantiations;
+ };
+
+ 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,
+ CXXRecordDecl *ThisContext,
+ unsigned ThisTypeQuals);
+ void SubstExceptionSpec(FunctionDecl *New, const FunctionProtoType *Proto,
+ const MultiLevelTemplateArgumentList &Args);
+ ParmVarDecl *SubstParmVarDecl(ParmVarDecl *D,
+ const MultiLevelTemplateArgumentList &TemplateArgs,
+ int indexAdjustment,
+ Optional<unsigned> NumExpansions,
+ bool ExpectParameterPack);
+ bool SubstParmTypes(SourceLocation Loc,
+ ParmVarDecl **Params, unsigned NumParams,
+ const MultiLevelTemplateArgumentList &TemplateArgs,
+ SmallVectorImpl<QualType> &ParamTypes,
+ SmallVectorImpl<ParmVarDecl *> *OutParams = nullptr);
+ 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 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(ArrayRef<Expr *> Exprs, bool IsCall,
+ const MultiLevelTemplateArgumentList &TemplateArgs,
+ SmallVectorImpl<Expr *> &Outputs);
+
+ StmtResult SubstStmt(Stmt *S,
+ const MultiLevelTemplateArgumentList &TemplateArgs);
+
+ Decl *SubstDecl(Decl *D, DeclContext *Owner,
+ const MultiLevelTemplateArgumentList &TemplateArgs);
+
+ ExprResult SubstInitializer(Expr *E,
+ const MultiLevelTemplateArgumentList &TemplateArgs,
+ bool CXXDirectInit);
+
+ 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);
+
+ bool InstantiateEnum(SourceLocation PointOfInstantiation,
+ EnumDecl *Instantiation, EnumDecl *Pattern,
+ const MultiLevelTemplateArgumentList &TemplateArgs,
+ TemplateSpecializationKind TSK);
+
+ bool InstantiateInClassInitializer(
+ SourceLocation PointOfInstantiation, FieldDecl *Instantiation,
+ FieldDecl *Pattern, const MultiLevelTemplateArgumentList &TemplateArgs);
+
+ struct LateInstantiatedAttribute {
+ const Attr *TmplAttr;
+ LocalInstantiationScope *Scope;
+ Decl *NewDecl;
+
+ LateInstantiatedAttribute(const Attr *A, LocalInstantiationScope *S,
+ Decl *D)
+ : TmplAttr(A), Scope(S), NewDecl(D)
+ { }
+ };
+ typedef SmallVector<LateInstantiatedAttribute, 16> LateInstantiatedAttrVec;
+
+ void InstantiateAttrs(const MultiLevelTemplateArgumentList &TemplateArgs,
+ const Decl *Pattern, Decl *Inst,
+ LateInstantiatedAttrVec *LateAttrs = nullptr,
+ LocalInstantiationScope *OuterMostScope = nullptr);
+
+ 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);
+
+ NestedNameSpecifierLoc
+ SubstNestedNameSpecifierLoc(NestedNameSpecifierLoc NNS,
+ const MultiLevelTemplateArgumentList &TemplateArgs);
+
+ DeclarationNameInfo
+ SubstDeclarationNameInfo(const DeclarationNameInfo &NameInfo,
+ const MultiLevelTemplateArgumentList &TemplateArgs);
+ TemplateName
+ SubstTemplateName(NestedNameSpecifierLoc QualifierLoc, TemplateName Name,
+ SourceLocation Loc,
+ const MultiLevelTemplateArgumentList &TemplateArgs);
+ bool Subst(const TemplateArgumentLoc *Args, unsigned NumArgs,
+ TemplateArgumentListInfo &Result,
+ const MultiLevelTemplateArgumentList &TemplateArgs);
+
+ void InstantiateExceptionSpec(SourceLocation PointOfInstantiation,
+ FunctionDecl *Function);
+ void InstantiateFunctionDefinition(SourceLocation PointOfInstantiation,
+ FunctionDecl *Function,
+ bool Recursive = false,
+ bool DefinitionRequired = false);
+ VarTemplateSpecializationDecl *BuildVarTemplateInstantiation(
+ VarTemplateDecl *VarTemplate, VarDecl *FromVar,
+ const TemplateArgumentList &TemplateArgList,
+ const TemplateArgumentListInfo &TemplateArgsInfo,
+ SmallVectorImpl<TemplateArgument> &Converted,
+ SourceLocation PointOfInstantiation, void *InsertPos,
+ LateInstantiatedAttrVec *LateAttrs = nullptr,
+ LocalInstantiationScope *StartingScope = nullptr);
+ VarTemplateSpecializationDecl *CompleteVarTemplateSpecializationDecl(
+ VarTemplateSpecializationDecl *VarSpec, VarDecl *PatternDecl,
+ const MultiLevelTemplateArgumentList &TemplateArgs);
+ void
+ BuildVariableInstantiation(VarDecl *NewVar, VarDecl *OldVar,
+ const MultiLevelTemplateArgumentList &TemplateArgs,
+ LateInstantiatedAttrVec *LateAttrs,
+ DeclContext *Owner,
+ LocalInstantiationScope *StartingScope,
+ bool InstantiatingVarTemplate = false);
+ void InstantiateVariableInitializer(
+ VarDecl *Var, VarDecl *OldVar,
+ const MultiLevelTemplateArgumentList &TemplateArgs);
+ void InstantiateVariableDefinition(SourceLocation PointOfInstantiation,
+ VarDecl *Var, 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.
+ enum ObjCContainerKind {
+ OCK_None = -1,
+ OCK_Interface = 0,
+ OCK_Protocol,
+ OCK_Category,
+ OCK_ClassExtension,
+ OCK_Implementation,
+ OCK_CategoryImplementation
+ };
+ ObjCContainerKind getObjCContainerKind() const;
+
+ DeclResult actOnObjCTypeParam(Scope *S,
+ ObjCTypeParamVariance variance,
+ SourceLocation varianceLoc,
+ unsigned index,
+ IdentifierInfo *paramName,
+ SourceLocation paramLoc,
+ SourceLocation colonLoc,
+ ParsedType typeBound);
+
+ ObjCTypeParamList *actOnObjCTypeParamList(Scope *S, SourceLocation lAngleLoc,
+ ArrayRef<Decl *> typeParams,
+ SourceLocation rAngleLoc);
+ void popObjCTypeParamList(Scope *S, ObjCTypeParamList *typeParamList);
+
+ Decl *ActOnStartClassInterface(Scope *S,
+ SourceLocation AtInterfaceLoc,
+ IdentifierInfo *ClassName,
+ SourceLocation ClassLoc,
+ ObjCTypeParamList *typeParamList,
+ IdentifierInfo *SuperName,
+ SourceLocation SuperLoc,
+ ArrayRef<ParsedType> SuperTypeArgs,
+ SourceRange SuperTypeArgsRange,
+ Decl * const *ProtoRefs,
+ unsigned NumProtoRefs,
+ const SourceLocation *ProtoLocs,
+ SourceLocation EndProtoLoc,
+ AttributeList *AttrList);
+
+ void ActOnSuperClassOfClassInterface(Scope *S,
+ SourceLocation AtInterfaceLoc,
+ ObjCInterfaceDecl *IDecl,
+ IdentifierInfo *ClassName,
+ SourceLocation ClassLoc,
+ IdentifierInfo *SuperName,
+ SourceLocation SuperLoc,
+ ArrayRef<ParsedType> SuperTypeArgs,
+ SourceRange SuperTypeArgsRange);
+
+ void ActOnTypedefedProtocols(SmallVectorImpl<Decl *> &ProtocolRefs,
+ IdentifierInfo *SuperName,
+ SourceLocation SuperLoc);
+
+ Decl *ActOnCompatibilityAlias(
+ SourceLocation AtCompatibilityAliasLoc,
+ IdentifierInfo *AliasName, SourceLocation AliasLocation,
+ IdentifierInfo *ClassName, SourceLocation ClassLocation);
+
+ bool 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,
+ ObjCTypeParamList *typeParamList,
+ 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);
+
+ DeclGroupPtrTy ActOnFinishObjCImplementation(Decl *ObjCImpDecl,
+ ArrayRef<Decl *> Decls);
+
+ DeclGroupPtrTy ActOnForwardClassDeclaration(SourceLocation Loc,
+ IdentifierInfo **IdentList,
+ SourceLocation *IdentLocs,
+ ArrayRef<ObjCTypeParamList *> TypeParamLists,
+ unsigned NumElts);
+
+ DeclGroupPtrTy ActOnForwardProtocolDeclaration(SourceLocation AtProtoclLoc,
+ ArrayRef<IdentifierLocPair> IdentList,
+ AttributeList *attrList);
+
+ void FindProtocolDeclaration(bool WarnOnDeclarations, bool ForObjCContainer,
+ ArrayRef<IdentifierLocPair> ProtocolId,
+ SmallVectorImpl<Decl *> &Protocols);
+
+ /// Given a list of identifiers (and their locations), resolve the
+ /// names to either Objective-C protocol qualifiers or type
+ /// arguments, as appropriate.
+ void actOnObjCTypeArgsOrProtocolQualifiers(
+ Scope *S,
+ ParsedType baseType,
+ SourceLocation lAngleLoc,
+ ArrayRef<IdentifierInfo *> identifiers,
+ ArrayRef<SourceLocation> identifierLocs,
+ SourceLocation rAngleLoc,
+ SourceLocation &typeArgsLAngleLoc,
+ SmallVectorImpl<ParsedType> &typeArgs,
+ SourceLocation &typeArgsRAngleLoc,
+ SourceLocation &protocolLAngleLoc,
+ SmallVectorImpl<Decl *> &protocols,
+ SourceLocation &protocolRAngleLoc,
+ bool warnOnIncompleteProtocols);
+
+ /// Build a an Objective-C protocol-qualified 'id' type where no
+ /// base type was specified.
+ TypeResult actOnObjCProtocolQualifierType(
+ SourceLocation lAngleLoc,
+ ArrayRef<Decl *> protocols,
+ ArrayRef<SourceLocation> protocolLocs,
+ SourceLocation rAngleLoc);
+
+ /// Build a specialized and/or protocol-qualified Objective-C type.
+ TypeResult actOnObjCTypeArgsAndProtocolQualifiers(
+ Scope *S,
+ SourceLocation Loc,
+ ParsedType BaseType,
+ SourceLocation TypeArgsLAngleLoc,
+ ArrayRef<ParsedType> TypeArgs,
+ SourceLocation TypeArgsRAngleLoc,
+ SourceLocation ProtocolLAngleLoc,
+ ArrayRef<Decl *> Protocols,
+ ArrayRef<SourceLocation> ProtocolLocs,
+ SourceLocation ProtocolRAngleLoc);
+
+ /// Build an Objective-C object pointer type.
+ QualType BuildObjCObjectType(QualType BaseType,
+ SourceLocation Loc,
+ SourceLocation TypeArgsLAngleLoc,
+ ArrayRef<TypeSourceInfo *> TypeArgs,
+ SourceLocation TypeArgsRAngleLoc,
+ SourceLocation ProtocolLAngleLoc,
+ ArrayRef<ObjCProtocolDecl *> Protocols,
+ ArrayRef<SourceLocation> ProtocolLocs,
+ SourceLocation ProtocolRAngleLoc,
+ bool FailOnError = false);
+
+ /// Check the application of the Objective-C '__kindof' qualifier to
+ /// the given type.
+ bool checkObjCKindOfType(QualType &type, SourceLocation loc);
+
+ /// Ensure attributes are consistent with type.
+ /// \param [in, out] Attributes The attributes to check; they will
+ /// be modified to be consistent with \p PropertyTy.
+ void CheckObjCPropertyAttributes(Decl *PropertyPtrTy,
+ SourceLocation Loc,
+ unsigned &Attributes,
+ bool propertyInPrimaryClass);
+
+ /// Process the specified property declaration and create decls for the
+ /// setters and getters as needed.
+ /// \param property The property declaration being processed
+ void ProcessPropertyDecl(ObjCPropertyDecl *property);
+
+
+ void DiagnosePropertyMismatch(ObjCPropertyDecl *Property,
+ ObjCPropertyDecl *SuperProperty,
+ const IdentifierInfo *Name,
+ bool OverridingProtocolProperty);
+
+ void DiagnoseClassExtensionDupMethods(ObjCCategoryDecl *CAT,
+ ObjCInterfaceDecl *ID);
+
+ Decl *ActOnAtEnd(Scope *S, SourceRange AtEnd,
+ ArrayRef<Decl *> allMethods = None,
+ ArrayRef<DeclGroupPtrTy> allTUVars = None);
+
+ Decl *ActOnProperty(Scope *S, SourceLocation AtLoc,
+ SourceLocation LParenLoc,
+ FieldDeclarator &FD, ObjCDeclSpec &ODS,
+ Selector GetterSel, Selector SetterSel,
+ tok::ObjCKeywordKind MethodImplKind,
+ DeclContext *lexicalDC = nullptr);
+
+ Decl *ActOnPropertyImplDecl(Scope *S,
+ SourceLocation AtLoc,
+ SourceLocation PropertyLoc,
+ bool ImplKind,
+ IdentifierInfo *PropertyId,
+ IdentifierInfo *PropertyIvar,
+ SourceLocation PropertyIvarLoc);
+
+ enum ObjCSpecialMethodKind {
+ OSMK_None,
+ OSMK_Alloc,
+ OSMK_New,
+ OSMK_Copy,
+ OSMK_RetainingInit,
+ OSMK_NonRetainingInit
+ };
+
+ 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,
+ ObjCDeclSpec &ReturnQT, ParsedType ReturnType,
+ ArrayRef<SourceLocation> SelectorLocs, 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, bool MethodDefinition);
+
+ ObjCMethodDecl *LookupMethodInQualifiedType(Selector Sel,
+ const ObjCObjectPointerType *OPT,
+ bool IsInstance);
+ ObjCMethodDecl *LookupMethodInObjectType(Selector Sel, QualType Ty,
+ bool IsInstance);
+
+ bool CheckARCMethodDecl(ObjCMethodDecl *method);
+ bool inferObjCARCLifetime(ValueDecl *decl);
+
+ ExprResult
+ HandleExprPropertyRefExpr(const ObjCObjectPointerType *OPT,
+ Expr *BaseExpr,
+ SourceLocation OpLoc,
+ DeclarationName MemberName,
+ SourceLocation MemberLoc,
+ SourceLocation SuperLoc, QualType SuperType,
+ bool Super);
+
+ ExprResult
+ ActOnClassPropertyRefExpr(IdentifierInfo &receiverName,
+ IdentifierInfo &propertyName,
+ SourceLocation receiverNameLoc,
+ SourceLocation propertyNameLoc);
+
+ ObjCMethodDecl *tryCaptureObjCSelf(SourceLocation Loc);
+
+ /// \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,
+ ArrayRef<SourceLocation> SelectorLocs,
+ SourceLocation RBracLoc,
+ MultiExprArg Args);
+
+ ExprResult BuildClassMessage(TypeSourceInfo *ReceiverTypeInfo,
+ QualType ReceiverType,
+ SourceLocation SuperLoc,
+ Selector Sel,
+ ObjCMethodDecl *Method,
+ SourceLocation LBracLoc,
+ ArrayRef<SourceLocation> SelectorLocs,
+ SourceLocation RBracLoc,
+ MultiExprArg Args,
+ bool isImplicit = false);
+
+ ExprResult BuildClassMessageImplicit(QualType ReceiverType,
+ bool isSuperReceiver,
+ SourceLocation Loc,
+ Selector Sel,
+ ObjCMethodDecl *Method,
+ MultiExprArg Args);
+
+ ExprResult ActOnClassMessage(Scope *S,
+ ParsedType Receiver,
+ Selector Sel,
+ SourceLocation LBracLoc,
+ ArrayRef<SourceLocation> SelectorLocs,
+ SourceLocation RBracLoc,
+ MultiExprArg Args);
+
+ ExprResult BuildInstanceMessage(Expr *Receiver,
+ QualType ReceiverType,
+ SourceLocation SuperLoc,
+ Selector Sel,
+ ObjCMethodDecl *Method,
+ SourceLocation LBracLoc,
+ ArrayRef<SourceLocation> SelectorLocs,
+ SourceLocation RBracLoc,
+ MultiExprArg Args,
+ bool isImplicit = false);
+
+ ExprResult BuildInstanceMessageImplicit(Expr *Receiver,
+ QualType ReceiverType,
+ SourceLocation Loc,
+ Selector Sel,
+ ObjCMethodDecl *Method,
+ MultiExprArg Args);
+
+ ExprResult ActOnInstanceMessage(Scope *S,
+ Expr *Receiver,
+ Selector Sel,
+ SourceLocation LBracLoc,
+ ArrayRef<SourceLocation> SelectorLocs,
+ SourceLocation RBracLoc,
+ MultiExprArg Args);
+
+ ExprResult BuildObjCBridgedCast(SourceLocation LParenLoc,
+ ObjCBridgeCastKind Kind,
+ SourceLocation BridgeKeywordLoc,
+ TypeSourceInfo *TSInfo,
+ Expr *SubExpr);
+
+ ExprResult ActOnObjCBridgedCast(Scope *S,
+ SourceLocation LParenLoc,
+ ObjCBridgeCastKind Kind,
+ SourceLocation BridgeKeywordLoc,
+ ParsedType Type,
+ SourceLocation RParenLoc,
+ Expr *SubExpr);
+
+ void CheckTollFreeBridgeCast(QualType castType, Expr *castExpr);
+
+ void CheckObjCBridgeRelatedCast(QualType castType, Expr *castExpr);
+
+ bool CheckTollFreeBridgeStaticCast(QualType castType, Expr *castExpr,
+ CastKind &Kind);
+
+ bool checkObjCBridgeRelatedComponents(SourceLocation Loc,
+ QualType DestType, QualType SrcType,
+ ObjCInterfaceDecl *&RelatedClass,
+ ObjCMethodDecl *&ClassMethod,
+ ObjCMethodDecl *&InstanceMethod,
+ TypedefNameDecl *&TDNDecl,
+ bool CfToNs);
+
+ bool CheckObjCBridgeRelatedConversions(SourceLocation Loc,
+ QualType DestType, QualType SrcType,
+ Expr *&SrcExpr);
+
+ bool ConversionToObjCStringLiteralCheck(QualType DstType, Expr *&SrcExpr);
+
+ bool checkInitMethod(ObjCMethodDecl *method, QualType receiverTypeIfCall);
+
+ /// \brief Check whether the given new method is a valid override of the
+ /// given overridden method, and set any properties that should be inherited.
+ void CheckObjCMethodOverride(ObjCMethodDecl *NewMethod,
+ const ObjCMethodDecl *Overridden);
+
+ /// \brief Describes the compatibility of a result type with its method.
+ enum ResultTypeCompatibilityKind {
+ RTC_Compatible,
+ RTC_Incompatible,
+ RTC_Unknown
+ };
+
+ void CheckObjCMethodOverrides(ObjCMethodDecl *ObjCMethod,
+ ObjCInterfaceDecl *CurrentClass,
+ ResultTypeCompatibilityKind RTC);
+
+ 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);
+
+ 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])
+ };
+
+ enum PragmaMSStructKind {
+ PMSST_OFF, // #pragms ms_struct off
+ PMSST_ON // #pragms ms_struct on
+ };
+
+ enum PragmaMSCommentKind {
+ PCK_Unknown,
+ PCK_Linker, // #pragma comment(linker, ...)
+ PCK_Lib, // #pragma comment(lib, ...)
+ PCK_Compiler, // #pragma comment(compiler, ...)
+ PCK_ExeStr, // #pragma comment(exestr, ...)
+ PCK_User // #pragma comment(user, ...)
+ };
+
+ /// ActOnPragmaPack - Called on well formed \#pragma pack(...).
+ void ActOnPragmaPack(PragmaPackKind Kind,
+ IdentifierInfo *Name,
+ Expr *Alignment,
+ SourceLocation PragmaLoc,
+ SourceLocation LParenLoc,
+ SourceLocation RParenLoc);
+
+ /// ActOnPragmaMSStruct - Called on well formed \#pragma ms_struct [on|off].
+ void ActOnPragmaMSStruct(PragmaMSStructKind Kind);
+
+ /// ActOnPragmaMSComment - Called on well formed
+ /// \#pragma comment(kind, "arg").
+ void ActOnPragmaMSComment(PragmaMSCommentKind Kind, StringRef Arg);
+
+ /// ActOnPragmaMSPointersToMembers - called on well formed \#pragma
+ /// pointers_to_members(representation method[, general purpose
+ /// representation]).
+ void ActOnPragmaMSPointersToMembers(
+ LangOptions::PragmaMSPointersToMembersKind Kind,
+ SourceLocation PragmaLoc);
+
+ /// \brief Called on well formed \#pragma vtordisp().
+ void ActOnPragmaMSVtorDisp(PragmaVtorDispKind Kind, SourceLocation PragmaLoc,
+ MSVtorDispAttr::Mode Value);
+
+ enum PragmaSectionKind {
+ PSK_DataSeg,
+ PSK_BSSSeg,
+ PSK_ConstSeg,
+ PSK_CodeSeg,
+ };
+
+ bool UnifySection(StringRef SectionName,
+ int SectionFlags,
+ DeclaratorDecl *TheDecl);
+ bool UnifySection(StringRef SectionName,
+ int SectionFlags,
+ SourceLocation PragmaSectionLocation);
+
+ /// \brief Called on well formed \#pragma bss_seg/data_seg/const_seg/code_seg.
+ void ActOnPragmaMSSeg(SourceLocation PragmaLocation,
+ PragmaMsStackAction Action,
+ llvm::StringRef StackSlotLabel,
+ StringLiteral *SegmentName,
+ llvm::StringRef PragmaName);
+
+ /// \brief Called on well formed \#pragma section().
+ void ActOnPragmaMSSection(SourceLocation PragmaLocation,
+ int SectionFlags, StringLiteral *SegmentName);
+
+ /// \brief Called on well-formed \#pragma init_seg().
+ void ActOnPragmaMSInitSeg(SourceLocation PragmaLocation,
+ StringLiteral *SegmentName);
+
+ /// ActOnPragmaDetectMismatch - Call on well-formed \#pragma detect_mismatch
+ void ActOnPragmaDetectMismatch(StringRef Name, StringRef Value);
+
+ /// 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(const IdentifierInfo* VisType,
+ SourceLocation PragmaLoc);
+
+ NamedDecl *DeclClonePragmaWeak(NamedDecl *ND, IdentifierInfo *II,
+ SourceLocation Loc);
+ void DeclApplyPragmaWeak(Scope *S, NamedDecl *ND, WeakInfo &W);
+
+ /// ActOnPragmaWeakID - Called on well formed \#pragma weak ident.
+ void ActOnPragmaWeakID(IdentifierInfo* WeakName,
+ SourceLocation PragmaLoc,
+ SourceLocation WeakNameLoc);
+
+ /// ActOnPragmaRedefineExtname - Called on well formed
+ /// \#pragma redefine_extname oldname newname.
+ void ActOnPragmaRedefineExtname(IdentifierInfo* WeakName,
+ IdentifierInfo* AliasName,
+ SourceLocation PragmaLoc,
+ SourceLocation WeakNameLoc,
+ SourceLocation AliasNameLoc);
+
+ /// 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);
+
+ /// AddMsStructLayoutForRecord - Adds ms_struct layout attribute to record.
+ void AddMsStructLayoutForRecord(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,
+ SourceLocation Loc);
+
+ /// 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(bool IsNamespaceEnd, SourceLocation EndLoc);
+
+ /// FreeVisContext - Deallocate and null out VisContext.
+ void FreeVisContext();
+
+ /// AddCFAuditedAttribute - Check whether we're currently within
+ /// '\#pragma clang arc_cf_code_audited' and, if so, consider adding
+ /// the appropriate attribute.
+ void AddCFAuditedAttribute(Decl *D);
+
+ /// \brief Called on well formed \#pragma clang optimize.
+ void ActOnPragmaOptimize(bool On, SourceLocation PragmaLoc);
+
+ /// \brief Get the location for the currently active "\#pragma clang optimize
+ /// off". If this location is invalid, then the state of the pragma is "on".
+ SourceLocation getOptimizeOffPragmaLocation() const {
+ return OptimizeOffPragmaLocation;
+ }
+
+ /// \brief Only called on function definitions; if there is a pragma in scope
+ /// with the effect of a range-based optnone, consider marking the function
+ /// with attribute optnone.
+ void AddRangeBasedOptnone(FunctionDecl *FD);
+
+ /// \brief Adds the 'optnone' attribute to the function declaration if there
+ /// are no conflicts; Loc represents the location causing the 'optnone'
+ /// attribute to be added (usually because of a pragma).
+ void AddOptnoneAttributeIfNoConflicts(FunctionDecl *FD, SourceLocation Loc);
+
+ /// AddAlignedAttr - Adds an aligned attribute to a particular declaration.
+ void AddAlignedAttr(SourceRange AttrRange, Decl *D, Expr *E,
+ unsigned SpellingListIndex, bool IsPackExpansion);
+ void AddAlignedAttr(SourceRange AttrRange, Decl *D, TypeSourceInfo *T,
+ unsigned SpellingListIndex, bool IsPackExpansion);
+
+ /// AddAssumeAlignedAttr - Adds an assume_aligned attribute to a particular
+ /// declaration.
+ void AddAssumeAlignedAttr(SourceRange AttrRange, Decl *D, Expr *E, Expr *OE,
+ unsigned SpellingListIndex);
+
+ /// AddAlignValueAttr - Adds an align_value attribute to a particular
+ /// declaration.
+ void AddAlignValueAttr(SourceRange AttrRange, Decl *D, Expr *E,
+ unsigned SpellingListIndex);
+
+ /// AddLaunchBoundsAttr - Adds a launch_bounds attribute to a particular
+ /// declaration.
+ void AddLaunchBoundsAttr(SourceRange AttrRange, Decl *D, Expr *MaxThreads,
+ Expr *MinBlocks, unsigned SpellingListIndex);
+
+ //===--------------------------------------------------------------------===//
+ // C++ Coroutines TS
+ //
+ ExprResult ActOnCoawaitExpr(Scope *S, SourceLocation KwLoc, Expr *E);
+ ExprResult ActOnCoyieldExpr(Scope *S, SourceLocation KwLoc, Expr *E);
+ StmtResult ActOnCoreturnStmt(SourceLocation KwLoc, Expr *E);
+
+ ExprResult BuildCoawaitExpr(SourceLocation KwLoc, Expr *E);
+ ExprResult BuildCoyieldExpr(SourceLocation KwLoc, Expr *E);
+ StmtResult BuildCoreturnStmt(SourceLocation KwLoc, Expr *E);
+
+ void CheckCompletedCoroutineBody(FunctionDecl *FD, Stmt *&Body);
+
+ //===--------------------------------------------------------------------===//
+ // OpenMP directives and clauses.
+ //
+private:
+ void *VarDataSharingAttributesStack;
+ /// \brief Initialization of data-sharing attributes stack.
+ void InitDataSharingAttributesStack();
+ void DestroyDataSharingAttributesStack();
+ ExprResult
+ VerifyPositiveIntegerConstantInClause(Expr *Op, OpenMPClauseKind CKind,
+ bool StrictlyPositive = true);
+
+public:
+ /// \brief Return true if the provided declaration \a VD should be captured by
+ /// reference in the provided scope \a RSI. This will take into account the
+ /// semantics of the directive and associated clauses.
+ bool IsOpenMPCapturedByRef(VarDecl *VD,
+ const sema::CapturedRegionScopeInfo *RSI);
+
+ /// \brief Check if the specified variable is used in one of the private
+ /// clauses (private, firstprivate, lastprivate, reduction etc.) in OpenMP
+ /// constructs.
+ bool IsOpenMPCapturedVar(VarDecl *VD);
+
+ /// \brief Check if the specified variable is used in 'private' clause.
+ /// \param Level Relative level of nested OpenMP construct for that the check
+ /// is performed.
+ bool isOpenMPPrivateVar(VarDecl *VD, unsigned Level);
+
+ /// \brief Check if the specified variable is captured by 'target' directive.
+ /// \param Level Relative level of nested OpenMP construct for that the check
+ /// is performed.
+ bool isOpenMPTargetCapturedVar(VarDecl *VD, unsigned Level);
+
+ ExprResult PerformOpenMPImplicitIntegerConversion(SourceLocation OpLoc,
+ Expr *Op);
+ /// \brief Called on start of new data sharing attribute block.
+ void StartOpenMPDSABlock(OpenMPDirectiveKind K,
+ const DeclarationNameInfo &DirName, Scope *CurScope,
+ SourceLocation Loc);
+ /// \brief Start analysis of clauses.
+ void StartOpenMPClause(OpenMPClauseKind K);
+ /// \brief End analysis of clauses.
+ void EndOpenMPClause();
+ /// \brief Called on end of data sharing attribute block.
+ void EndOpenMPDSABlock(Stmt *CurDirective);
+
+ /// \brief Check if the current region is an OpenMP loop region and if it is,
+ /// mark loop control variable, used in \p Init for loop initialization, as
+ /// private by default.
+ /// \param Init First part of the for loop.
+ void ActOnOpenMPLoopInitialization(SourceLocation ForLoc, Stmt *Init);
+
+ // OpenMP directives and clauses.
+ /// \brief Called on correct id-expression from the '#pragma omp
+ /// threadprivate'.
+ ExprResult ActOnOpenMPIdExpression(Scope *CurScope,
+ CXXScopeSpec &ScopeSpec,
+ const DeclarationNameInfo &Id);
+ /// \brief Called on well-formed '#pragma omp threadprivate'.
+ DeclGroupPtrTy ActOnOpenMPThreadprivateDirective(
+ SourceLocation Loc,
+ ArrayRef<Expr *> VarList);
+ /// \brief Builds a new OpenMPThreadPrivateDecl and checks its correctness.
+ OMPThreadPrivateDecl *CheckOMPThreadPrivateDecl(
+ SourceLocation Loc,
+ ArrayRef<Expr *> VarList);
+
+ /// \brief Initialization of captured region for OpenMP region.
+ void ActOnOpenMPRegionStart(OpenMPDirectiveKind DKind, Scope *CurScope);
+ /// \brief End of OpenMP region.
+ ///
+ /// \param S Statement associated with the current OpenMP region.
+ /// \param Clauses List of clauses for the current OpenMP region.
+ ///
+ /// \returns Statement for finished OpenMP region.
+ StmtResult ActOnOpenMPRegionEnd(StmtResult S, ArrayRef<OMPClause *> Clauses);
+ StmtResult ActOnOpenMPExecutableDirective(
+ OpenMPDirectiveKind Kind, const DeclarationNameInfo &DirName,
+ OpenMPDirectiveKind CancelRegion, ArrayRef<OMPClause *> Clauses,
+ Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc);
+ /// \brief Called on well-formed '\#pragma omp parallel' after parsing
+ /// of the associated statement.
+ StmtResult ActOnOpenMPParallelDirective(ArrayRef<OMPClause *> Clauses,
+ Stmt *AStmt,
+ SourceLocation StartLoc,
+ SourceLocation EndLoc);
+ /// \brief Called on well-formed '\#pragma omp simd' after parsing
+ /// of the associated statement.
+ StmtResult ActOnOpenMPSimdDirective(
+ ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
+ SourceLocation EndLoc,
+ llvm::DenseMap<VarDecl *, Expr *> &VarsWithImplicitDSA);
+ /// \brief Called on well-formed '\#pragma omp for' after parsing
+ /// of the associated statement.
+ StmtResult ActOnOpenMPForDirective(
+ ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
+ SourceLocation EndLoc,
+ llvm::DenseMap<VarDecl *, Expr *> &VarsWithImplicitDSA);
+ /// \brief Called on well-formed '\#pragma omp for simd' after parsing
+ /// of the associated statement.
+ StmtResult ActOnOpenMPForSimdDirective(
+ ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
+ SourceLocation EndLoc,
+ llvm::DenseMap<VarDecl *, Expr *> &VarsWithImplicitDSA);
+ /// \brief Called on well-formed '\#pragma omp sections' after parsing
+ /// of the associated statement.
+ StmtResult ActOnOpenMPSectionsDirective(ArrayRef<OMPClause *> Clauses,
+ Stmt *AStmt, SourceLocation StartLoc,
+ SourceLocation EndLoc);
+ /// \brief Called on well-formed '\#pragma omp section' after parsing of the
+ /// associated statement.
+ StmtResult ActOnOpenMPSectionDirective(Stmt *AStmt, SourceLocation StartLoc,
+ SourceLocation EndLoc);
+ /// \brief Called on well-formed '\#pragma omp single' after parsing of the
+ /// associated statement.
+ StmtResult ActOnOpenMPSingleDirective(ArrayRef<OMPClause *> Clauses,
+ Stmt *AStmt, SourceLocation StartLoc,
+ SourceLocation EndLoc);
+ /// \brief Called on well-formed '\#pragma omp master' after parsing of the
+ /// associated statement.
+ StmtResult ActOnOpenMPMasterDirective(Stmt *AStmt, SourceLocation StartLoc,
+ SourceLocation EndLoc);
+ /// \brief Called on well-formed '\#pragma omp critical' after parsing of the
+ /// associated statement.
+ StmtResult ActOnOpenMPCriticalDirective(const DeclarationNameInfo &DirName,
+ ArrayRef<OMPClause *> Clauses,
+ Stmt *AStmt, SourceLocation StartLoc,
+ SourceLocation EndLoc);
+ /// \brief Called on well-formed '\#pragma omp parallel for' after parsing
+ /// of the associated statement.
+ StmtResult ActOnOpenMPParallelForDirective(
+ ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
+ SourceLocation EndLoc,
+ llvm::DenseMap<VarDecl *, Expr *> &VarsWithImplicitDSA);
+ /// \brief Called on well-formed '\#pragma omp parallel for simd' after
+ /// parsing of the associated statement.
+ StmtResult ActOnOpenMPParallelForSimdDirective(
+ ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
+ SourceLocation EndLoc,
+ llvm::DenseMap<VarDecl *, Expr *> &VarsWithImplicitDSA);
+ /// \brief Called on well-formed '\#pragma omp parallel sections' after
+ /// parsing of the associated statement.
+ StmtResult ActOnOpenMPParallelSectionsDirective(ArrayRef<OMPClause *> Clauses,
+ Stmt *AStmt,
+ SourceLocation StartLoc,
+ SourceLocation EndLoc);
+ /// \brief Called on well-formed '\#pragma omp task' after parsing of the
+ /// associated statement.
+ StmtResult ActOnOpenMPTaskDirective(ArrayRef<OMPClause *> Clauses,
+ Stmt *AStmt, SourceLocation StartLoc,
+ SourceLocation EndLoc);
+ /// \brief Called on well-formed '\#pragma omp taskyield'.
+ StmtResult ActOnOpenMPTaskyieldDirective(SourceLocation StartLoc,
+ SourceLocation EndLoc);
+ /// \brief Called on well-formed '\#pragma omp barrier'.
+ StmtResult ActOnOpenMPBarrierDirective(SourceLocation StartLoc,
+ SourceLocation EndLoc);
+ /// \brief Called on well-formed '\#pragma omp taskwait'.
+ StmtResult ActOnOpenMPTaskwaitDirective(SourceLocation StartLoc,
+ SourceLocation EndLoc);
+ /// \brief Called on well-formed '\#pragma omp taskgroup'.
+ StmtResult ActOnOpenMPTaskgroupDirective(Stmt *AStmt, SourceLocation StartLoc,
+ SourceLocation EndLoc);
+ /// \brief Called on well-formed '\#pragma omp flush'.
+ StmtResult ActOnOpenMPFlushDirective(ArrayRef<OMPClause *> Clauses,
+ SourceLocation StartLoc,
+ SourceLocation EndLoc);
+ /// \brief Called on well-formed '\#pragma omp ordered' after parsing of the
+ /// associated statement.
+ StmtResult ActOnOpenMPOrderedDirective(ArrayRef<OMPClause *> Clauses,
+ Stmt *AStmt, SourceLocation StartLoc,
+ SourceLocation EndLoc);
+ /// \brief Called on well-formed '\#pragma omp atomic' after parsing of the
+ /// associated statement.
+ StmtResult ActOnOpenMPAtomicDirective(ArrayRef<OMPClause *> Clauses,
+ Stmt *AStmt, SourceLocation StartLoc,
+ SourceLocation EndLoc);
+ /// \brief Called on well-formed '\#pragma omp target' after parsing of the
+ /// associated statement.
+ StmtResult ActOnOpenMPTargetDirective(ArrayRef<OMPClause *> Clauses,
+ Stmt *AStmt, SourceLocation StartLoc,
+ SourceLocation EndLoc);
+ /// \brief Called on well-formed '\#pragma omp target data' after parsing of
+ /// the associated statement.
+ StmtResult ActOnOpenMPTargetDataDirective(ArrayRef<OMPClause *> Clauses,
+ Stmt *AStmt, SourceLocation StartLoc,
+ SourceLocation EndLoc);
+ /// \brief Called on well-formed '\#pragma omp teams' after parsing of the
+ /// associated statement.
+ StmtResult ActOnOpenMPTeamsDirective(ArrayRef<OMPClause *> Clauses,
+ Stmt *AStmt, SourceLocation StartLoc,
+ SourceLocation EndLoc);
+ /// \brief Called on well-formed '\#pragma omp cancellation point'.
+ StmtResult
+ ActOnOpenMPCancellationPointDirective(SourceLocation StartLoc,
+ SourceLocation EndLoc,
+ OpenMPDirectiveKind CancelRegion);
+ /// \brief Called on well-formed '\#pragma omp cancel'.
+ StmtResult ActOnOpenMPCancelDirective(ArrayRef<OMPClause *> Clauses,
+ SourceLocation StartLoc,
+ SourceLocation EndLoc,
+ OpenMPDirectiveKind CancelRegion);
+ /// \brief Called on well-formed '\#pragma omp taskloop' after parsing of the
+ /// associated statement.
+ StmtResult ActOnOpenMPTaskLoopDirective(
+ ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
+ SourceLocation EndLoc,
+ llvm::DenseMap<VarDecl *, Expr *> &VarsWithImplicitDSA);
+ /// \brief Called on well-formed '\#pragma omp taskloop simd' after parsing of
+ /// the associated statement.
+ StmtResult ActOnOpenMPTaskLoopSimdDirective(
+ ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
+ SourceLocation EndLoc,
+ llvm::DenseMap<VarDecl *, Expr *> &VarsWithImplicitDSA);
+ /// \brief Called on well-formed '\#pragma omp distribute' after parsing
+ /// of the associated statement.
+ StmtResult ActOnOpenMPDistributeDirective(
+ ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
+ SourceLocation EndLoc,
+ llvm::DenseMap<VarDecl *, Expr *> &VarsWithImplicitDSA);
+
+ OMPClause *ActOnOpenMPSingleExprClause(OpenMPClauseKind Kind,
+ Expr *Expr,
+ SourceLocation StartLoc,
+ SourceLocation LParenLoc,
+ SourceLocation EndLoc);
+ /// \brief Called on well-formed 'if' clause.
+ OMPClause *ActOnOpenMPIfClause(OpenMPDirectiveKind NameModifier,
+ Expr *Condition, SourceLocation StartLoc,
+ SourceLocation LParenLoc,
+ SourceLocation NameModifierLoc,
+ SourceLocation ColonLoc,
+ SourceLocation EndLoc);
+ /// \brief Called on well-formed 'final' clause.
+ OMPClause *ActOnOpenMPFinalClause(Expr *Condition, SourceLocation StartLoc,
+ SourceLocation LParenLoc,
+ SourceLocation EndLoc);
+ /// \brief Called on well-formed 'num_threads' clause.
+ OMPClause *ActOnOpenMPNumThreadsClause(Expr *NumThreads,
+ SourceLocation StartLoc,
+ SourceLocation LParenLoc,
+ SourceLocation EndLoc);
+ /// \brief Called on well-formed 'safelen' clause.
+ OMPClause *ActOnOpenMPSafelenClause(Expr *Length,
+ SourceLocation StartLoc,
+ SourceLocation LParenLoc,
+ SourceLocation EndLoc);
+ /// \brief Called on well-formed 'simdlen' clause.
+ OMPClause *ActOnOpenMPSimdlenClause(Expr *Length, SourceLocation StartLoc,
+ SourceLocation LParenLoc,
+ SourceLocation EndLoc);
+ /// \brief Called on well-formed 'collapse' clause.
+ OMPClause *ActOnOpenMPCollapseClause(Expr *NumForLoops,
+ SourceLocation StartLoc,
+ SourceLocation LParenLoc,
+ SourceLocation EndLoc);
+ /// \brief Called on well-formed 'ordered' clause.
+ OMPClause *
+ ActOnOpenMPOrderedClause(SourceLocation StartLoc, SourceLocation EndLoc,
+ SourceLocation LParenLoc = SourceLocation(),
+ Expr *NumForLoops = nullptr);
+ /// \brief Called on well-formed 'grainsize' clause.
+ OMPClause *ActOnOpenMPGrainsizeClause(Expr *Size, SourceLocation StartLoc,
+ SourceLocation LParenLoc,
+ SourceLocation EndLoc);
+ /// \brief Called on well-formed 'num_tasks' clause.
+ OMPClause *ActOnOpenMPNumTasksClause(Expr *NumTasks, SourceLocation StartLoc,
+ SourceLocation LParenLoc,
+ SourceLocation EndLoc);
+ /// \brief Called on well-formed 'hint' clause.
+ OMPClause *ActOnOpenMPHintClause(Expr *Hint, SourceLocation StartLoc,
+ SourceLocation LParenLoc,
+ SourceLocation EndLoc);
+
+ OMPClause *ActOnOpenMPSimpleClause(OpenMPClauseKind Kind,
+ unsigned Argument,
+ SourceLocation ArgumentLoc,
+ SourceLocation StartLoc,
+ SourceLocation LParenLoc,
+ SourceLocation EndLoc);
+ /// \brief Called on well-formed 'default' clause.
+ OMPClause *ActOnOpenMPDefaultClause(OpenMPDefaultClauseKind Kind,
+ SourceLocation KindLoc,
+ SourceLocation StartLoc,
+ SourceLocation LParenLoc,
+ SourceLocation EndLoc);
+ /// \brief Called on well-formed 'proc_bind' clause.
+ OMPClause *ActOnOpenMPProcBindClause(OpenMPProcBindClauseKind Kind,
+ SourceLocation KindLoc,
+ SourceLocation StartLoc,
+ SourceLocation LParenLoc,
+ SourceLocation EndLoc);
+
+ OMPClause *ActOnOpenMPSingleExprWithArgClause(
+ OpenMPClauseKind Kind, ArrayRef<unsigned> Arguments, Expr *Expr,
+ SourceLocation StartLoc, SourceLocation LParenLoc,
+ ArrayRef<SourceLocation> ArgumentsLoc, SourceLocation DelimLoc,
+ SourceLocation EndLoc);
+ /// \brief Called on well-formed 'schedule' clause.
+ OMPClause *ActOnOpenMPScheduleClause(
+ OpenMPScheduleClauseModifier M1, OpenMPScheduleClauseModifier M2,
+ OpenMPScheduleClauseKind Kind, Expr *ChunkSize, SourceLocation StartLoc,
+ SourceLocation LParenLoc, SourceLocation M1Loc, SourceLocation M2Loc,
+ SourceLocation KindLoc, SourceLocation CommaLoc, SourceLocation EndLoc);
+
+ OMPClause *ActOnOpenMPClause(OpenMPClauseKind Kind, SourceLocation StartLoc,
+ SourceLocation EndLoc);
+ /// \brief Called on well-formed 'nowait' clause.
+ OMPClause *ActOnOpenMPNowaitClause(SourceLocation StartLoc,
+ SourceLocation EndLoc);
+ /// \brief Called on well-formed 'untied' clause.
+ OMPClause *ActOnOpenMPUntiedClause(SourceLocation StartLoc,
+ SourceLocation EndLoc);
+ /// \brief Called on well-formed 'mergeable' clause.
+ OMPClause *ActOnOpenMPMergeableClause(SourceLocation StartLoc,
+ SourceLocation EndLoc);
+ /// \brief Called on well-formed 'read' clause.
+ OMPClause *ActOnOpenMPReadClause(SourceLocation StartLoc,
+ SourceLocation EndLoc);
+ /// \brief Called on well-formed 'write' clause.
+ OMPClause *ActOnOpenMPWriteClause(SourceLocation StartLoc,
+ SourceLocation EndLoc);
+ /// \brief Called on well-formed 'update' clause.
+ OMPClause *ActOnOpenMPUpdateClause(SourceLocation StartLoc,
+ SourceLocation EndLoc);
+ /// \brief Called on well-formed 'capture' clause.
+ OMPClause *ActOnOpenMPCaptureClause(SourceLocation StartLoc,
+ SourceLocation EndLoc);
+ /// \brief Called on well-formed 'seq_cst' clause.
+ OMPClause *ActOnOpenMPSeqCstClause(SourceLocation StartLoc,
+ SourceLocation EndLoc);
+ /// \brief Called on well-formed 'threads' clause.
+ OMPClause *ActOnOpenMPThreadsClause(SourceLocation StartLoc,
+ SourceLocation EndLoc);
+ /// \brief Called on well-formed 'simd' clause.
+ OMPClause *ActOnOpenMPSIMDClause(SourceLocation StartLoc,
+ SourceLocation EndLoc);
+ /// \brief Called on well-formed 'nogroup' clause.
+ OMPClause *ActOnOpenMPNogroupClause(SourceLocation StartLoc,
+ SourceLocation EndLoc);
+
+ OMPClause *ActOnOpenMPVarListClause(
+ OpenMPClauseKind Kind, ArrayRef<Expr *> Vars, Expr *TailExpr,
+ SourceLocation StartLoc, SourceLocation LParenLoc,
+ SourceLocation ColonLoc, SourceLocation EndLoc,
+ CXXScopeSpec &ReductionIdScopeSpec,
+ const DeclarationNameInfo &ReductionId, OpenMPDependClauseKind DepKind,
+ OpenMPLinearClauseKind LinKind, OpenMPMapClauseKind MapTypeModifier,
+ OpenMPMapClauseKind MapType, SourceLocation DepLinMapLoc);
+ /// \brief Called on well-formed 'private' clause.
+ OMPClause *ActOnOpenMPPrivateClause(ArrayRef<Expr *> VarList,
+ SourceLocation StartLoc,
+ SourceLocation LParenLoc,
+ SourceLocation EndLoc);
+ /// \brief Called on well-formed 'firstprivate' clause.
+ OMPClause *ActOnOpenMPFirstprivateClause(ArrayRef<Expr *> VarList,
+ SourceLocation StartLoc,
+ SourceLocation LParenLoc,
+ SourceLocation EndLoc);
+ /// \brief Called on well-formed 'lastprivate' clause.
+ OMPClause *ActOnOpenMPLastprivateClause(ArrayRef<Expr *> VarList,
+ SourceLocation StartLoc,
+ SourceLocation LParenLoc,
+ SourceLocation EndLoc);
+ /// \brief Called on well-formed 'shared' clause.
+ OMPClause *ActOnOpenMPSharedClause(ArrayRef<Expr *> VarList,
+ SourceLocation StartLoc,
+ SourceLocation LParenLoc,
+ SourceLocation EndLoc);
+ /// \brief Called on well-formed 'reduction' clause.
+ OMPClause *
+ ActOnOpenMPReductionClause(ArrayRef<Expr *> VarList, SourceLocation StartLoc,
+ SourceLocation LParenLoc, SourceLocation ColonLoc,
+ SourceLocation EndLoc,
+ CXXScopeSpec &ReductionIdScopeSpec,
+ const DeclarationNameInfo &ReductionId);
+ /// \brief Called on well-formed 'linear' clause.
+ OMPClause *
+ ActOnOpenMPLinearClause(ArrayRef<Expr *> VarList, Expr *Step,
+ SourceLocation StartLoc, SourceLocation LParenLoc,
+ OpenMPLinearClauseKind LinKind, SourceLocation LinLoc,
+ SourceLocation ColonLoc, SourceLocation EndLoc);
+ /// \brief Called on well-formed 'aligned' clause.
+ OMPClause *ActOnOpenMPAlignedClause(ArrayRef<Expr *> VarList,
+ Expr *Alignment,
+ SourceLocation StartLoc,
+ SourceLocation LParenLoc,
+ SourceLocation ColonLoc,
+ SourceLocation EndLoc);
+ /// \brief Called on well-formed 'copyin' clause.
+ OMPClause *ActOnOpenMPCopyinClause(ArrayRef<Expr *> VarList,
+ SourceLocation StartLoc,
+ SourceLocation LParenLoc,
+ SourceLocation EndLoc);
+ /// \brief Called on well-formed 'copyprivate' clause.
+ OMPClause *ActOnOpenMPCopyprivateClause(ArrayRef<Expr *> VarList,
+ SourceLocation StartLoc,
+ SourceLocation LParenLoc,
+ SourceLocation EndLoc);
+ /// \brief Called on well-formed 'flush' pseudo clause.
+ OMPClause *ActOnOpenMPFlushClause(ArrayRef<Expr *> VarList,
+ SourceLocation StartLoc,
+ SourceLocation LParenLoc,
+ SourceLocation EndLoc);
+ /// \brief Called on well-formed 'depend' clause.
+ OMPClause *
+ ActOnOpenMPDependClause(OpenMPDependClauseKind DepKind, SourceLocation DepLoc,
+ SourceLocation ColonLoc, ArrayRef<Expr *> VarList,
+ SourceLocation StartLoc, SourceLocation LParenLoc,
+ SourceLocation EndLoc);
+ /// \brief Called on well-formed 'device' clause.
+ OMPClause *ActOnOpenMPDeviceClause(Expr *Device, SourceLocation StartLoc,
+ SourceLocation LParenLoc,
+ SourceLocation EndLoc);
+ /// \brief Called on well-formed 'map' clause.
+ OMPClause *ActOnOpenMPMapClause(
+ OpenMPMapClauseKind MapTypeModifier, OpenMPMapClauseKind MapType,
+ SourceLocation MapLoc, SourceLocation ColonLoc, ArrayRef<Expr *> VarList,
+ SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc);
+ /// \brief Called on well-formed 'num_teams' clause.
+ OMPClause *ActOnOpenMPNumTeamsClause(Expr *NumTeams, SourceLocation StartLoc,
+ SourceLocation LParenLoc,
+ SourceLocation EndLoc);
+ /// \brief Called on well-formed 'thread_limit' clause.
+ OMPClause *ActOnOpenMPThreadLimitClause(Expr *ThreadLimit,
+ SourceLocation StartLoc,
+ SourceLocation LParenLoc,
+ SourceLocation EndLoc);
+ /// \brief Called on well-formed 'priority' clause.
+ OMPClause *ActOnOpenMPPriorityClause(Expr *Priority, SourceLocation StartLoc,
+ SourceLocation LParenLoc,
+ SourceLocation EndLoc);
+
+ /// \brief The kind of conversion being performed.
+ enum CheckedConversionKind {
+ /// \brief An implicit conversion.
+ CCK_ImplicitConversion,
+ /// \brief A C-style cast.
+ CCK_CStyleCast,
+ /// \brief A functional-style cast.
+ CCK_FunctionalCast,
+ /// \brief A cast other than a C-style cast.
+ CCK_OtherCast
+ };
+
+ /// 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.
+ ExprResult ImpCastExprToType(Expr *E, QualType Type, CastKind CK,
+ ExprValueKind VK = VK_RValue,
+ const CXXCastPath *BasePath = nullptr,
+ CheckedConversionKind CCK
+ = CCK_ImplicitConversion);
+
+ /// ScalarTypeToBooleanCastKind - Returns the cast kind corresponding
+ /// to the conversion from scalar type ScalarTy to the Boolean type.
+ static CastKind ScalarTypeToBooleanCastKind(QualType ScalarTy);
+
+ /// IgnoredValueConversions - Given that an expression's result is
+ /// syntactically ignored, perform any conversions that are
+ /// required.
+ ExprResult IgnoredValueConversions(Expr *E);
+
+ // UsualUnaryConversions - promotes integers (C99 6.3.1.1p2) and converts
+ // functions and arrays to their respective pointers (C99 6.3.2.1).
+ ExprResult UsualUnaryConversions(Expr *E);
+
+ /// CallExprUnaryConversions - a special case of an unary conversion
+ /// performed on a function designator of a call expression.
+ ExprResult CallExprUnaryConversions(Expr *E);
+
+ // DefaultFunctionArrayConversion - converts functions and arrays
+ // to their respective pointers (C99 6.3.2.1).
+ ExprResult DefaultFunctionArrayConversion(Expr *E, bool Diagnose = true);
+
+ // DefaultFunctionArrayLvalueConversion - converts functions and
+ // arrays to their respective pointers and performs the
+ // lvalue-to-rvalue conversion.
+ ExprResult DefaultFunctionArrayLvalueConversion(Expr *E,
+ bool Diagnose = true);
+
+ // 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.
+ ExprResult DefaultLvalueConversion(Expr *E);
+
+ // 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.
+ ExprResult DefaultArgumentPromotion(Expr *E);
+
+ // Used for emitting the right warning by DefaultVariadicArgumentPromotion
+ enum VariadicCallType {
+ VariadicFunction,
+ VariadicBlock,
+ VariadicMethod,
+ VariadicConstructor,
+ VariadicDoesNotApply
+ };
+
+ VariadicCallType getVariadicCallType(FunctionDecl *FDecl,
+ const FunctionProtoType *Proto,
+ Expr *Fn);
+
+ // Used for determining in which context a type is allowed to be passed to a
+ // vararg function.
+ enum VarArgKind {
+ VAK_Valid,
+ VAK_ValidInCXX11,
+ VAK_Undefined,
+ VAK_MSVCUndefined,
+ VAK_Invalid
+ };
+
+ // Determines which VarArgKind fits an expression.
+ VarArgKind isValidVarArgType(const QualType &Ty);
+
+ /// Check to see if the given expression is a valid argument to a variadic
+ /// function, issuing a diagnostic if not.
+ void checkVariadicArgument(const Expr *E, VariadicCallType CT);
+
+ /// Check to see if a given expression could have '.c_str()' called on it.
+ bool hasCStrMethod(const Expr *E);
+
+ /// GatherArgumentsForCall - Collector argument expressions for various
+ /// form of call prototypes.
+ bool GatherArgumentsForCall(SourceLocation CallLoc, FunctionDecl *FDecl,
+ const FunctionProtoType *Proto,
+ unsigned FirstParam, ArrayRef<Expr *> Args,
+ SmallVectorImpl<Expr *> &AllArgs,
+ VariadicCallType CallType = VariadicDoesNotApply,
+ bool AllowExplicit = false,
+ bool IsListInitialization = false);
+
+ // DefaultVariadicArgumentPromotion - Like DefaultArgumentPromotion, but
+ // will create a runtime trap if the resulting type is not a POD type.
+ ExprResult DefaultVariadicArgumentPromotion(Expr *E, 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(ExprResult &LHS, ExprResult &RHS,
+ 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,
+
+ /// IncompatibleObjCWeakRef - Assigning a weak-unavailable object to an
+ /// object with __weak qualifier.
+ IncompatibleObjCWeakRef,
+
+ /// 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 = nullptr);
+
+ /// IsValueInFlagEnum - Determine if a value is allowed as part of a flag
+ /// enum. If AllowMask is true, then we also allow the complement of a valid
+ /// value, to be used as a mask.
+ bool IsValueInFlagEnum(const EnumDecl *ED, const llvm::APInt &Val,
+ bool AllowMask) const;
+
+ /// DiagnoseAssignmentEnum - Warn if assignment to enum is a constant
+ /// integer not in the range of enum values.
+ void DiagnoseAssignmentEnum(QualType DstType, QualType SrcType,
+ Expr *SrcExpr);
+
+ /// CheckAssignmentConstraints - Perform type checking for assignment,
+ /// argument passing, variable initialization, and function return values.
+ /// C99 6.5.16.
+ AssignConvertType CheckAssignmentConstraints(SourceLocation Loc,
+ QualType LHSType,
+ QualType RHSType);
+
+ /// Check assignment constraints and optionally prepare for a conversion of
+ /// the RHS to the LHS type. The conversion is prepared for if ConvertRHS
+ /// is true.
+ AssignConvertType CheckAssignmentConstraints(QualType LHSType,
+ ExprResult &RHS,
+ CastKind &Kind,
+ bool ConvertRHS = true);
+
+ // CheckSingleAssignmentConstraints - Currently used by
+ // CheckAssignmentOperands, and ActOnReturnStmt. Prior to type checking,
+ // this routine performs the default function/array converions, if ConvertRHS
+ // is true.
+ AssignConvertType CheckSingleAssignmentConstraints(QualType LHSType,
+ ExprResult &RHS,
+ bool Diagnose = true,
+ bool DiagnoseCFAudited = false,
+ bool ConvertRHS = true);
+
+ // \brief If the lhs type is a transparent union, check whether we
+ // can initialize the transparent union with the given expression.
+ AssignConvertType CheckTransparentUnionArgumentConstraints(QualType ArgType,
+ ExprResult &RHS);
+
+ bool IsStringLiteralToNonConstPointerConversion(Expr *From, QualType ToType);
+
+ bool CheckExceptionSpecCompatibility(Expr *From, QualType ToType);
+
+ ExprResult PerformImplicitConversion(Expr *From, QualType ToType,
+ AssignmentAction Action,
+ bool AllowExplicit = false);
+ ExprResult PerformImplicitConversion(Expr *From, QualType ToType,
+ AssignmentAction Action,
+ bool AllowExplicit,
+ ImplicitConversionSequence& ICS);
+ ExprResult PerformImplicitConversion(Expr *From, QualType ToType,
+ const ImplicitConversionSequence& ICS,
+ AssignmentAction Action,
+ CheckedConversionKind CCK
+ = CCK_ImplicitConversion);
+ ExprResult PerformImplicitConversion(Expr *From, QualType ToType,
+ const StandardConversionSequence& SCS,
+ AssignmentAction Action,
+ CheckedConversionKind CCK);
+
+ /// 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 Loc, ExprResult &LHS,
+ ExprResult &RHS);
+ QualType CheckPointerToMemberOperands( // C++ 5.5
+ ExprResult &LHS, ExprResult &RHS, ExprValueKind &VK,
+ SourceLocation OpLoc, bool isIndirect);
+ QualType CheckMultiplyDivideOperands( // C99 6.5.5
+ ExprResult &LHS, ExprResult &RHS, SourceLocation Loc, bool IsCompAssign,
+ bool IsDivide);
+ QualType CheckRemainderOperands( // C99 6.5.5
+ ExprResult &LHS, ExprResult &RHS, SourceLocation Loc,
+ bool IsCompAssign = false);
+ QualType CheckAdditionOperands( // C99 6.5.6
+ ExprResult &LHS, ExprResult &RHS, SourceLocation Loc,
+ BinaryOperatorKind Opc, QualType* CompLHSTy = nullptr);
+ QualType CheckSubtractionOperands( // C99 6.5.6
+ ExprResult &LHS, ExprResult &RHS, SourceLocation Loc,
+ QualType* CompLHSTy = nullptr);
+ QualType CheckShiftOperands( // C99 6.5.7
+ ExprResult &LHS, ExprResult &RHS, SourceLocation Loc,
+ BinaryOperatorKind Opc, bool IsCompAssign = false);
+ QualType CheckCompareOperands( // C99 6.5.8/9
+ ExprResult &LHS, ExprResult &RHS, SourceLocation Loc,
+ BinaryOperatorKind Opc, bool isRelational);
+ QualType CheckBitwiseOperands( // C99 6.5.[10...12]
+ ExprResult &LHS, ExprResult &RHS, SourceLocation Loc,
+ bool IsCompAssign = false);
+ QualType CheckLogicalOperands( // C99 6.5.[13,14]
+ ExprResult &LHS, ExprResult &RHS, SourceLocation Loc,
+ BinaryOperatorKind 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 *LHSExpr, ExprResult &RHS, SourceLocation Loc, QualType CompoundType);
+
+ ExprResult checkPseudoObjectIncDec(Scope *S, SourceLocation OpLoc,
+ UnaryOperatorKind Opcode, Expr *Op);
+ ExprResult checkPseudoObjectAssignment(Scope *S, SourceLocation OpLoc,
+ BinaryOperatorKind Opcode,
+ Expr *LHS, Expr *RHS);
+ ExprResult checkPseudoObjectRValue(Expr *E);
+ Expr *recreateSyntacticForm(PseudoObjectExpr *E);
+
+ QualType CheckConditionalOperands( // C99 6.5.15
+ ExprResult &Cond, ExprResult &LHS, ExprResult &RHS,
+ ExprValueKind &VK, ExprObjectKind &OK, SourceLocation QuestionLoc);
+ QualType CXXCheckConditionalOperands( // C++ 5.16
+ ExprResult &cond, ExprResult &lhs, ExprResult &rhs,
+ ExprValueKind &VK, ExprObjectKind &OK, SourceLocation questionLoc);
+ QualType FindCompositePointerType(SourceLocation Loc, Expr *&E1, Expr *&E2,
+ bool *NonStandardCompositeType = nullptr);
+ QualType FindCompositePointerType(SourceLocation Loc,
+ ExprResult &E1, ExprResult &E2,
+ bool *NonStandardCompositeType = nullptr) {
+ Expr *E1Tmp = E1.get(), *E2Tmp = E2.get();
+ QualType Composite = FindCompositePointerType(Loc, E1Tmp, E2Tmp,
+ NonStandardCompositeType);
+ E1 = E1Tmp;
+ E2 = E2Tmp;
+ return Composite;
+ }
+
+ QualType FindCompositeObjCPointerType(ExprResult &LHS, ExprResult &RHS,
+ SourceLocation QuestionLoc);
+
+ bool DiagnoseConditionalForNull(Expr *LHSExpr, Expr *RHSExpr,
+ SourceLocation QuestionLoc);
+
+ void DiagnoseAlwaysNonNullPointer(Expr *E,
+ Expr::NullPointerConstantKind NullType,
+ bool IsEqual, SourceRange Range);
+
+ /// type checking for vector binary operators.
+ QualType CheckVectorOperands(ExprResult &LHS, ExprResult &RHS,
+ SourceLocation Loc, bool IsCompAssign,
+ bool AllowBothBool, bool AllowBoolConversion);
+ QualType GetSignedVectorType(QualType V);
+ QualType CheckVectorCompareOperands(ExprResult &LHS, ExprResult &RHS,
+ SourceLocation Loc, bool isRelational);
+ QualType CheckVectorLogicalOperands(ExprResult &LHS, ExprResult &RHS,
+ SourceLocation Loc);
+
+ bool areLaxCompatibleVectorTypes(QualType srcType, QualType destType);
+ bool isLaxVectorConversion(QualType srcType, QualType destType);
+
+ /// type checking declaration initializers (C99 6.7.8)
+ 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,
+ bool &ObjCLifetimeConversion);
+
+ ExprResult checkUnknownAnyCast(SourceRange TypeRange, QualType CastType,
+ Expr *CastExpr, CastKind &CastKind,
+ ExprValueKind &VK, CXXCastPath &Path);
+
+ /// \brief Force an expression with unknown-type to an expression of the
+ /// given type.
+ ExprResult forceUnknownAnyToType(Expr *E, QualType ToType);
+
+ /// \brief Type-check an expression that's being passed to an
+ /// __unknown_anytype parameter.
+ ExprResult checkUnknownAnyArg(SourceLocation callLoc,
+ Expr *result, QualType &paramType);
+
+ // 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 the cast expr
+ ExprResult CheckExtVectorCast(SourceRange R, QualType DestTy, Expr *CastExpr,
+ CastKind &Kind);
+
+ ExprResult BuildCXXFunctionalCastExpr(TypeSourceInfo *TInfo,
+ SourceLocation LParenLoc,
+ Expr *CastExpr,
+ SourceLocation RParenLoc);
+
+ enum ARCConversionResult { ACR_okay, ACR_unbridged };
+
+ /// \brief Checks for invalid conversions and casts between
+ /// retainable pointers and other pointer kinds.
+ ARCConversionResult CheckObjCARCConversion(SourceRange castRange,
+ QualType castType, Expr *&op,
+ CheckedConversionKind CCK,
+ bool DiagnoseCFAudited = false,
+ BinaryOperatorKind Opc = BO_PtrMemD
+ );
+
+ Expr *stripARCUnbridgedCast(Expr *e);
+ void diagnoseARCUnbridgedCast(Expr *e);
+
+ bool CheckObjCARCUnavailableWeakConversion(QualType castType,
+ QualType ExprType);
+
+ /// checkRetainCycles - Check whether an Objective-C message send
+ /// might create an obvious retain cycle.
+ void checkRetainCycles(ObjCMessageExpr *msg);
+ void checkRetainCycles(Expr *receiver, Expr *argument);
+ void checkRetainCycles(VarDecl *Var, Expr *Init);
+
+ /// checkUnsafeAssigns - Check whether +1 expr is being assigned
+ /// to weak/__unsafe_unretained type.
+ bool checkUnsafeAssigns(SourceLocation Loc, QualType LHS, Expr *RHS);
+
+ /// checkUnsafeExprAssigns - Check whether +1 expr is being assigned
+ /// to weak/__unsafe_unretained expression.
+ void checkUnsafeExprAssigns(SourceLocation Loc, Expr *LHS, Expr *RHS);
+
+ /// 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(QualType ReceiverType,
+ MultiExprArg Args, Selector Sel,
+ ArrayRef<SourceLocation> SelectorLocs,
+ ObjCMethodDecl *Method, bool isClassMessage,
+ bool isSuperMessage,
+ SourceLocation lbrac, SourceLocation rbrac,
+ SourceRange RecRange,
+ QualType &ReturnType, ExprValueKind &VK);
+
+ /// \brief Determine the result of a message send expression based on
+ /// the type of the receiver, the method expected to receive the message,
+ /// and the form of the message send.
+ QualType getMessageSendResultType(QualType ReceiverType,
+ ObjCMethodDecl *Method,
+ bool isClassMessage, bool isSuperMessage);
+
+ /// \brief If the given expression involves a message send to a method
+ /// with a related result type, emit a note describing what happened.
+ void EmitRelatedResultTypeNote(const Expr *E);
+
+ /// \brief Given that we had incompatible pointer types in a return
+ /// statement, check whether we're in a method with a related result
+ /// type, and if so, emit a note describing what happened.
+ void EmitRelatedResultTypeNoteForReturn(QualType destType);
+
+ /// 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
+ ExprResult CheckBooleanCondition(Expr *E, 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.
+ ExprResult 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);
+
+ /// \brief Abstract base class used for diagnosing integer constant
+ /// expression violations.
+ class VerifyICEDiagnoser {
+ public:
+ bool Suppress;
+
+ VerifyICEDiagnoser(bool Suppress = false) : Suppress(Suppress) { }
+
+ virtual void diagnoseNotICE(Sema &S, SourceLocation Loc, SourceRange SR) =0;
+ virtual void diagnoseFold(Sema &S, SourceLocation Loc, SourceRange SR);
+ virtual ~VerifyICEDiagnoser() { }
+ };
+
+ /// 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.
+ ExprResult VerifyIntegerConstantExpression(Expr *E, llvm::APSInt *Result,
+ VerifyICEDiagnoser &Diagnoser,
+ bool AllowFold = true);
+ ExprResult VerifyIntegerConstantExpression(Expr *E, llvm::APSInt *Result,
+ unsigned DiagID,
+ bool AllowFold = true);
+ ExprResult VerifyIntegerConstantExpression(Expr *E,
+ llvm::APSInt *Result = nullptr);
+
+ /// 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
+ ExprResult VerifyBitField(SourceLocation FieldLoc, IdentifierInfo *FieldName,
+ QualType FieldTy, bool IsMsStruct,
+ Expr *BitWidth, bool *ZeroWidth = nullptr);
+
+ enum CUDAFunctionTarget {
+ CFT_Device,
+ CFT_Global,
+ CFT_Host,
+ CFT_HostDevice,
+ CFT_InvalidTarget
+ };
+
+ CUDAFunctionTarget IdentifyCUDATarget(const FunctionDecl *D);
+
+ enum CUDAFunctionPreference {
+ CFP_Never, // Invalid caller/callee combination.
+ CFP_LastResort, // Lowest priority. Only in effect if
+ // LangOpts.CUDADisableTargetCallChecks is true.
+ CFP_Fallback, // Low priority caller/callee combination
+ CFP_Best, // Preferred caller/callee combination
+ };
+
+ /// Identifies relative preference of a given Caller/Callee
+ /// combination, based on their host/device attributes.
+ /// \param Caller function which needs address of \p Callee.
+ /// nullptr in case of global context.
+ /// \param Callee target function
+ ///
+ /// \returns preference value for particular Caller/Callee combination.
+ CUDAFunctionPreference IdentifyCUDAPreference(const FunctionDecl *Caller,
+ const FunctionDecl *Callee);
+
+ bool CheckCUDATarget(const FunctionDecl *Caller, const FunctionDecl *Callee);
+
+ /// Finds a function in \p Matches with highest calling priority
+ /// from \p Caller context and erases all functions with lower
+ /// calling priority.
+ void EraseUnwantedCUDAMatches(const FunctionDecl *Caller,
+ SmallVectorImpl<FunctionDecl *> &Matches);
+ void EraseUnwantedCUDAMatches(const FunctionDecl *Caller,
+ SmallVectorImpl<DeclAccessPair> &Matches);
+ void EraseUnwantedCUDAMatches(
+ const FunctionDecl *Caller,
+ SmallVectorImpl<std::pair<DeclAccessPair, FunctionDecl *>> &Matches);
+
+ /// Given a implicit special member, infer its CUDA target from the
+ /// calls it needs to make to underlying base/field special members.
+ /// \param ClassDecl the class for which the member is being created.
+ /// \param CSM the kind of special member.
+ /// \param MemberDecl the special member itself.
+ /// \param ConstRHS true if this is a copy operation with a const object on
+ /// its RHS.
+ /// \param Diagnose true if this call should emit diagnostics.
+ /// \return true if there was an error inferring.
+ /// The result of this call is implicit CUDA target attribute(s) attached to
+ /// the member declaration.
+ bool inferCUDATargetForImplicitSpecialMember(CXXRecordDecl *ClassDecl,
+ CXXSpecialMember CSM,
+ CXXMethodDecl *MemberDecl,
+ bool ConstRHS,
+ bool Diagnose);
+
+ /// \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 CodeCompleteModuleImport(SourceLocation ImportLoc, ModuleIdPath Path);
+ 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, ArrayRef<Expr *> Args);
+ void CodeCompleteConstructor(Scope *S, QualType Type, SourceLocation Loc,
+ ArrayRef<Expr *> Args);
+ void CodeCompleteInitializer(Scope *S, Decl *D);
+ void CodeCompleteReturn(Scope *S);
+ void CodeCompleteAfterIf(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,
+ ArrayRef<CXXCtorInitializer *> Initializers);
+
+ void CodeCompleteLambdaIntroducer(Scope *S, LambdaIntroducer &Intro,
+ bool AfterAmpersand);
+
+ void CodeCompleteObjCAtDirective(Scope *S);
+ void CodeCompleteObjCAtVisibility(Scope *S);
+ void CodeCompleteObjCAtStatement(Scope *S);
+ void CodeCompleteObjCAtExpression(Scope *S);
+ void CodeCompleteObjCPropertyFlags(Scope *S, ObjCDeclSpec &ODS);
+ void CodeCompleteObjCPropertyGetter(Scope *S);
+ void CodeCompleteObjCPropertySetter(Scope *S);
+ void CodeCompleteObjCPassingType(Scope *S, ObjCDeclSpec &DS,
+ bool IsParameter);
+ void CodeCompleteObjCMessageReceiver(Scope *S);
+ void CodeCompleteObjCSuperMessage(Scope *S, SourceLocation SuperLoc,
+ ArrayRef<IdentifierInfo *> SelIdents,
+ bool AtArgumentExpression);
+ void CodeCompleteObjCClassMessage(Scope *S, ParsedType Receiver,
+ ArrayRef<IdentifierInfo *> SelIdents,
+ bool AtArgumentExpression,
+ bool IsSuper = false);
+ void CodeCompleteObjCInstanceMessage(Scope *S, Expr *Receiver,
+ ArrayRef<IdentifierInfo *> SelIdents,
+ bool AtArgumentExpression,
+ ObjCInterfaceDecl *Super = nullptr);
+ void CodeCompleteObjCForCollection(Scope *S,
+ DeclGroupPtrTy IterationVar);
+ void CodeCompleteObjCSelector(Scope *S,
+ ArrayRef<IdentifierInfo *> SelIdents);
+ void CodeCompleteObjCProtocolReferences(
+ ArrayRef<IdentifierLocPair> Protocols);
+ 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);
+ void CodeCompleteObjCPropertySynthesizeIvar(Scope *S,
+ IdentifierInfo *PropertyName);
+ void CodeCompleteObjCMethodDecl(Scope *S,
+ bool IsInstanceMethod,
+ ParsedType ReturnType);
+ void CodeCompleteObjCMethodDeclSelector(Scope *S,
+ bool IsInstanceMethod,
+ bool AtParameterName,
+ ParsedType ReturnType,
+ ArrayRef<IdentifierInfo *> SelIdents);
+ 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,
+ CodeCompletionTUInfo &CCTUInfo,
+ SmallVectorImpl<CodeCompletionResult> &Results);
+ //@}
+
+ //===--------------------------------------------------------------------===//
+ // Extra semantic analysis beyond the C type system
+
+public:
+ SourceLocation getLocationOfStringLiteralByte(const StringLiteral *SL,
+ unsigned ByteNo) const;
+
+private:
+ void CheckArrayAccess(const Expr *BaseExpr, const Expr *IndexExpr,
+ const ArraySubscriptExpr *ASE=nullptr,
+ bool AllowOnePastEnd=true, bool IndexNegated=false);
+ void CheckArrayAccess(const Expr *E);
+ // Used to grab the relevant information from a FormatAttr and a
+ // FunctionDeclaration.
+ struct FormatStringInfo {
+ unsigned FormatIdx;
+ unsigned FirstDataArg;
+ bool HasVAListArg;
+ };
+
+ static bool getFormatStringInfo(const FormatAttr *Format, bool IsCXXMember,
+ FormatStringInfo *FSI);
+ bool CheckFunctionCall(FunctionDecl *FDecl, CallExpr *TheCall,
+ const FunctionProtoType *Proto);
+ bool CheckObjCMethodCall(ObjCMethodDecl *Method, SourceLocation loc,
+ ArrayRef<const Expr *> Args);
+ bool CheckPointerCall(NamedDecl *NDecl, CallExpr *TheCall,
+ const FunctionProtoType *Proto);
+ bool CheckOtherCall(CallExpr *TheCall, const FunctionProtoType *Proto);
+ void CheckConstructorCall(FunctionDecl *FDecl,
+ ArrayRef<const Expr *> Args,
+ const FunctionProtoType *Proto,
+ SourceLocation Loc);
+
+ void checkCall(NamedDecl *FDecl, const FunctionProtoType *Proto,
+ ArrayRef<const Expr *> Args, bool IsMemberFunction,
+ SourceLocation Loc, SourceRange Range,
+ VariadicCallType CallType);
+
+ bool CheckObjCString(Expr *Arg);
+
+ ExprResult CheckBuiltinFunctionCall(FunctionDecl *FDecl,
+ unsigned BuiltinID, CallExpr *TheCall);
+
+ bool CheckARMBuiltinExclusiveCall(unsigned BuiltinID, CallExpr *TheCall,
+ unsigned MaxWidth);
+ bool CheckNeonBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall);
+ bool CheckARMBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall);
+
+ bool CheckAArch64BuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall);
+ bool CheckMipsBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall);
+ bool CheckSystemZBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall);
+ bool CheckX86BuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall);
+ bool CheckPPCBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall);
+
+ bool SemaBuiltinVAStartImpl(CallExpr *TheCall);
+ bool SemaBuiltinVAStart(CallExpr *TheCall);
+ bool SemaBuiltinMSVAStart(CallExpr *TheCall);
+ bool SemaBuiltinVAStartARM(CallExpr *Call);
+ bool SemaBuiltinUnorderedCompare(CallExpr *TheCall);
+ bool SemaBuiltinFPClassification(CallExpr *TheCall, unsigned NumArgs);
+
+public:
+ // Used by C++ template instantiation.
+ ExprResult SemaBuiltinShuffleVector(CallExpr *TheCall);
+ ExprResult SemaConvertVectorExpr(Expr *E, TypeSourceInfo *TInfo,
+ SourceLocation BuiltinLoc,
+ SourceLocation RParenLoc);
+
+private:
+ bool SemaBuiltinPrefetch(CallExpr *TheCall);
+ bool SemaBuiltinAssume(CallExpr *TheCall);
+ bool SemaBuiltinAssumeAligned(CallExpr *TheCall);
+ bool SemaBuiltinLongjmp(CallExpr *TheCall);
+ bool SemaBuiltinSetjmp(CallExpr *TheCall);
+ ExprResult SemaBuiltinAtomicOverloaded(ExprResult TheCallResult);
+ ExprResult SemaBuiltinNontemporalOverloaded(ExprResult TheCallResult);
+ ExprResult SemaAtomicOpsOverloaded(ExprResult TheCallResult,
+ AtomicExpr::AtomicOp Op);
+ bool SemaBuiltinConstantArg(CallExpr *TheCall, int ArgNum,
+ llvm::APSInt &Result);
+ bool SemaBuiltinConstantArgRange(CallExpr *TheCall, int ArgNum,
+ int Low, int High);
+ bool SemaBuiltinARMSpecialReg(unsigned BuiltinID, CallExpr *TheCall,
+ int ArgNum, unsigned ExpectedFieldNum,
+ bool AllowName);
+public:
+ enum FormatStringType {
+ FST_Scanf,
+ FST_Printf,
+ FST_NSString,
+ FST_Strftime,
+ FST_Strfmon,
+ FST_Kprintf,
+ FST_FreeBSDKPrintf,
+ FST_OSTrace,
+ FST_Unknown
+ };
+ static FormatStringType GetFormatStringType(const FormatAttr *Format);
+
+ void CheckFormatString(const StringLiteral *FExpr, const Expr *OrigFormatExpr,
+ ArrayRef<const Expr *> Args, bool HasVAListArg,
+ unsigned format_idx, unsigned firstDataArg,
+ FormatStringType Type, bool inFunctionCall,
+ VariadicCallType CallType,
+ llvm::SmallBitVector &CheckedVarArgs);
+
+ bool FormatStringHasSArg(const StringLiteral *FExpr);
+
+ static bool GetFormatNSStringIdx(const FormatAttr *Format, unsigned &Idx);
+
+private:
+ bool CheckFormatArguments(const FormatAttr *Format,
+ ArrayRef<const Expr *> Args,
+ bool IsCXXMember,
+ VariadicCallType CallType,
+ SourceLocation Loc, SourceRange Range,
+ llvm::SmallBitVector &CheckedVarArgs);
+ bool CheckFormatArguments(ArrayRef<const Expr *> Args,
+ bool HasVAListArg, unsigned format_idx,
+ unsigned firstDataArg, FormatStringType Type,
+ VariadicCallType CallType,
+ SourceLocation Loc, SourceRange range,
+ llvm::SmallBitVector &CheckedVarArgs);
+
+ void CheckAbsoluteValueFunction(const CallExpr *Call,
+ const FunctionDecl *FDecl,
+ IdentifierInfo *FnInfo);
+
+ void CheckMemaccessArguments(const CallExpr *Call,
+ unsigned BId,
+ IdentifierInfo *FnName);
+
+ void CheckStrlcpycatArguments(const CallExpr *Call,
+ IdentifierInfo *FnName);
+
+ void CheckStrncatArguments(const CallExpr *Call,
+ IdentifierInfo *FnName);
+
+ void CheckReturnValExpr(Expr *RetValExp, QualType lhsType,
+ SourceLocation ReturnLoc,
+ bool isObjCMethod = false,
+ const AttrVec *Attrs = nullptr,
+ const FunctionDecl *FD = nullptr);
+
+ void CheckFloatComparison(SourceLocation Loc, Expr* LHS, Expr* RHS);
+ void CheckImplicitConversions(Expr *E, SourceLocation CC = SourceLocation());
+ void CheckBoolLikeConversion(Expr *E, SourceLocation CC);
+ void CheckForIntOverflow(Expr *E);
+ void CheckUnsequencedOperations(Expr *E);
+
+ /// \brief Perform semantic checks on a completed expression. This will either
+ /// be a full-expression or a default argument expression.
+ void CheckCompletedExpr(Expr *E, SourceLocation CheckLoc = SourceLocation(),
+ bool IsConstexpr = false);
+
+ void CheckBitFieldInitialization(SourceLocation InitLoc, FieldDecl *Field,
+ Expr *Init);
+
+ /// \brief Check if the given expression contains 'break' or 'continue'
+ /// statement that produces control flow different from GCC.
+ void CheckBreakContinueBinding(Expr *E);
+
+ /// \brief Check whether receiver is mutable ObjC container which
+ /// attempts to add itself into the container
+ void CheckObjCCircularContainer(ObjCMessageExpr *Message);
+
+ void AnalyzeDeleteExprMismatch(const CXXDeleteExpr *DE);
+ void AnalyzeDeleteExprMismatch(FieldDecl *Field, SourceLocation DeleteLoc,
+ bool DeleteWasArrayForm);
+public:
+ /// \brief Register a magic integral constant to be used as a type tag.
+ void RegisterTypeTagForDatatype(const IdentifierInfo *ArgumentKind,
+ uint64_t MagicValue, QualType Type,
+ bool LayoutCompatible, bool MustBeNull);
+
+ struct TypeTagData {
+ TypeTagData() {}
+
+ TypeTagData(QualType Type, bool LayoutCompatible, bool MustBeNull) :
+ Type(Type), LayoutCompatible(LayoutCompatible),
+ MustBeNull(MustBeNull)
+ {}
+
+ QualType Type;
+
+ /// If true, \c Type should be compared with other expression's types for
+ /// layout-compatibility.
+ unsigned LayoutCompatible : 1;
+ unsigned MustBeNull : 1;
+ };
+
+ /// A pair of ArgumentKind identifier and magic value. This uniquely
+ /// identifies the magic value.
+ typedef std::pair<const IdentifierInfo *, uint64_t> TypeTagMagicValue;
+
+private:
+ /// \brief A map from magic value to type information.
+ std::unique_ptr<llvm::DenseMap<TypeTagMagicValue, TypeTagData>>
+ TypeTagForDatatypeMagicValues;
+
+ /// \brief Peform checks on a call of a function with argument_with_type_tag
+ /// or pointer_with_type_tag attributes.
+ void CheckArgumentWithTypeTag(const ArgumentWithTypeTagAttr *Attr,
+ const Expr * const *ExprArgs);
+
+ /// \brief The parser's current scope.
+ ///
+ /// The parser maintains this state here.
+ Scope *CurScope;
+
+ mutable IdentifierInfo *Ident_super;
+ mutable IdentifierInfo *Ident___float128;
+
+ /// Nullability type specifiers.
+ IdentifierInfo *Ident__Nonnull = nullptr;
+ IdentifierInfo *Ident__Nullable = nullptr;
+ IdentifierInfo *Ident__Null_unspecified = nullptr;
+
+ IdentifierInfo *Ident_NSError = nullptr;
+
+protected:
+ friend class Parser;
+ friend class InitializationSequence;
+ friend class ASTReader;
+ friend class ASTDeclReader;
+ friend class ASTWriter;
+
+public:
+ /// Retrieve the keyword associated
+ IdentifierInfo *getNullabilityKeyword(NullabilityKind nullability);
+
+ /// The struct behind the CFErrorRef pointer.
+ RecordDecl *CFError = nullptr;
+
+ /// Retrieve the identifier "NSError".
+ IdentifierInfo *getNSErrorIdent();
+
+ /// \brief Retrieve the parser's current scope.
+ ///
+ /// This routine must only be used when it is certain that semantic analysis
+ /// and the parser are in precisely the same context, which is not the case
+ /// when, e.g., we are performing any kind of template instantiation.
+ /// Therefore, the only safe places to use this scope are in the parser
+ /// itself and in routines directly invoked from the parser and *never* from
+ /// template substitution or instantiation.
+ Scope *getCurScope() const { return CurScope; }
+
+ void incrementMSManglingNumber() const {
+ return CurScope->incrementMSManglingNumber();
+ }
+
+ IdentifierInfo *getSuperIdentifier() const;
+ IdentifierInfo *getFloat128Identifier() const;
+
+ Decl *getObjCDeclContext() const;
+
+ DeclContext *getCurLexicalContext() const {
+ return OriginalLexicalContext ? OriginalLexicalContext : CurContext;
+ }
+
+ AvailabilityResult getCurContextAvailability() const;
+
+ const DeclContext *getCurObjCLexicalContext() const {
+ const DeclContext *DC = getCurLexicalContext();
+ // A category implicitly has the attribute of the interface.
+ if (const ObjCCategoryDecl *CatD = dyn_cast<ObjCCategoryDecl>(DC))
+ DC = CatD->getClassInterface();
+ return DC;
+ }
+
+ /// \brief To be used for checking whether the arguments being passed to
+ /// function exceeds the number of parameters expected for it.
+ static bool TooManyArguments(size_t NumParams, size_t NumArgs,
+ bool PartialOverloading = false) {
+ // We check whether we're just after a comma in code-completion.
+ if (NumArgs > 0 && PartialOverloading)
+ return NumArgs + 1 > NumParams; // If so, we view as an extra argument.
+ return NumArgs > NumParams;
+ }
+
+ // Emitting members of dllexported classes is delayed until the class
+ // (including field initializers) is fully parsed.
+ SmallVector<CXXRecordDecl*, 4> DelayedDllExportClasses;
+};
+
+/// \brief RAII object that enters a new expression evaluation context.
+class EnterExpressionEvaluationContext {
+ Sema &Actions;
+
+public:
+ EnterExpressionEvaluationContext(Sema &Actions,
+ Sema::ExpressionEvaluationContext NewContext,
+ Decl *LambdaContextDecl = nullptr,
+ bool IsDecltype = false)
+ : Actions(Actions) {
+ Actions.PushExpressionEvaluationContext(NewContext, LambdaContextDecl,
+ IsDecltype);
+ }
+ EnterExpressionEvaluationContext(Sema &Actions,
+ Sema::ExpressionEvaluationContext NewContext,
+ Sema::ReuseLambdaContextDecl_t,
+ bool IsDecltype = false)
+ : Actions(Actions) {
+ Actions.PushExpressionEvaluationContext(NewContext,
+ Sema::ReuseLambdaContextDecl,
+ IsDecltype);
+ }
+
+ ~EnterExpressionEvaluationContext() {
+ Actions.PopExpressionEvaluationContext();
+ }
+};
+
+DeductionFailureInfo
+MakeDeductionFailureInfo(ASTContext &Context, Sema::TemplateDeductionResult TDK,
+ sema::TemplateDeductionInfo &Info);
+
+/// \brief Contains a late templated function.
+/// Will be parsed at the end of the translation unit, used by Sema & Parser.
+struct LateParsedTemplate {
+ CachedTokens Toks;
+ /// \brief The template function declaration to be late parsed.
+ Decl *D;
+};
+
+} // 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..676646a
--- /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 {
+ virtual void anchor();
+ 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;
+ }
+ };
+}
+
+#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..7740d5e
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Sema/SemaDiagnostic.h
@@ -0,0 +1,28 @@
+//===--- 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_SEMA_SEMADIAGNOSTIC_H
+#define LLVM_CLANG_SEMA_SEMADIAGNOSTIC_H
+
+#include "clang/Basic/Diagnostic.h"
+
+namespace clang {
+ namespace diag {
+ enum {
+#define DIAG(ENUM,FLAGS,DEFAULT_MAPPING,DESC,GROUP,\
+ SFINAE,NOWERROR,SHOWINSYSHEADER,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/SemaFixItUtils.h b/contrib/llvm/tools/clang/include/clang/Sema/SemaFixItUtils.h
new file mode 100644
index 0000000..343ccfb
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Sema/SemaFixItUtils.h
@@ -0,0 +1,91 @@
+//===--- SemaFixItUtils.h - Sema FixIts -----------------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines helper classes for generation of Sema FixItHints.
+//
+//===----------------------------------------------------------------------===//
+#ifndef LLVM_CLANG_SEMA_SEMAFIXITUTILS_H
+#define LLVM_CLANG_SEMA_SEMAFIXITUTILS_H
+
+#include "clang/AST/Expr.h"
+
+namespace clang {
+
+enum OverloadFixItKind {
+ OFIK_Undefined = 0,
+ OFIK_Dereference,
+ OFIK_TakeAddress,
+ OFIK_RemoveDereference,
+ OFIK_RemoveTakeAddress
+};
+
+class Sema;
+
+/// The class facilities generation and storage of conversion FixIts. Hints for
+/// new conversions are added using TryToFixConversion method. The default type
+/// conversion checker can be reset.
+struct ConversionFixItGenerator {
+ /// Performs a simple check to see if From type can be converted to To type.
+ static bool compareTypesSimple(CanQualType From,
+ CanQualType To,
+ Sema &S,
+ SourceLocation Loc,
+ ExprValueKind FromVK);
+
+ /// The list of Hints generated so far.
+ std::vector<FixItHint> Hints;
+
+ /// The number of Conversions fixed. This can be different from the size
+ /// of the Hints vector since we allow multiple FixIts per conversion.
+ unsigned NumConversionsFixed;
+
+ /// The type of fix applied. If multiple conversions are fixed, corresponds
+ /// to the kid of the very first conversion.
+ OverloadFixItKind Kind;
+
+ typedef bool (*TypeComparisonFuncTy) (const CanQualType FromTy,
+ const CanQualType ToTy,
+ Sema &S,
+ SourceLocation Loc,
+ ExprValueKind FromVK);
+ /// The type comparison function used to decide if expression FromExpr of
+ /// type FromTy can be converted to ToTy. For example, one could check if
+ /// an implicit conversion exists. Returns true if comparison exists.
+ TypeComparisonFuncTy CompareTypes;
+
+ ConversionFixItGenerator(TypeComparisonFuncTy Foo): NumConversionsFixed(0),
+ Kind(OFIK_Undefined),
+ CompareTypes(Foo) {}
+
+ ConversionFixItGenerator(): NumConversionsFixed(0),
+ Kind(OFIK_Undefined),
+ CompareTypes(compareTypesSimple) {}
+
+ /// Resets the default conversion checker method.
+ void setConversionChecker(TypeComparisonFuncTy Foo) {
+ CompareTypes = Foo;
+ }
+
+ /// If possible, generates and stores a fix for the given conversion.
+ bool tryToFixConversion(const Expr *FromExpr,
+ const QualType FromQTy, const QualType ToQTy,
+ Sema &S);
+
+ void clear() {
+ Hints.clear();
+ NumConversionsFixed = 0;
+ }
+
+ bool isNull() {
+ return (NumConversionsFixed == 0);
+ }
+};
+
+} // endof 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..60c6598
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Sema/SemaInternal.h
@@ -0,0 +1,346 @@
+//===--- 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_SEMAINTERNAL_H
+#define LLVM_CLANG_SEMA_SEMAINTERNAL_H
+
+#include "clang/AST/ASTContext.h"
+#include "clang/Sema/Lookup.h"
+#include "clang/Sema/Sema.h"
+#include "clang/Sema/SemaDiagnostic.h"
+
+namespace clang {
+
+inline PartialDiagnostic Sema::PDiag(unsigned DiagID) {
+ return PartialDiagnostic(DiagID, Context.getDiagAllocator());
+}
+
+inline bool
+FTIHasSingleVoidParameter(const DeclaratorChunk::FunctionTypeInfo &FTI) {
+ return FTI.NumParams == 1 && !FTI.isVariadic &&
+ FTI.Params[0].Ident == nullptr && FTI.Params[0].Param &&
+ cast<ParmVarDecl>(FTI.Params[0].Param)->getType()->isVoidType();
+}
+
+inline bool
+FTIHasNonVoidParameters(const DeclaratorChunk::FunctionTypeInfo &FTI) {
+ // Assume FTI is well-formed.
+ return FTI.NumParams && !FTIHasSingleVoidParameter(FTI);
+}
+
+// This requires the variable to be non-dependent and the initializer
+// to not be value dependent.
+inline bool IsVariableAConstantExpression(VarDecl *Var, ASTContext &Context) {
+ const VarDecl *DefVD = nullptr;
+ return !isa<ParmVarDecl>(Var) &&
+ Var->isUsableInConstantExpressions(Context) &&
+ Var->getAnyInitializer(DefVD) && DefVD->checkInitIsICE();
+}
+
+// Helper function to check whether D's attributes match current CUDA mode.
+// Decls with mismatched attributes and related diagnostics may have to be
+// ignored during this CUDA compilation pass.
+inline bool DeclAttrsMatchCUDAMode(const LangOptions &LangOpts, Decl *D) {
+ if (!LangOpts.CUDA || !D)
+ return true;
+ bool isDeviceSideDecl = D->hasAttr<CUDADeviceAttr>() ||
+ D->hasAttr<CUDASharedAttr>() ||
+ D->hasAttr<CUDAGlobalAttr>();
+ return isDeviceSideDecl == LangOpts.CUDAIsDevice;
+}
+
+// Directly mark a variable odr-used. Given a choice, prefer to use
+// MarkVariableReferenced since it does additional checks and then
+// calls MarkVarDeclODRUsed.
+// If the variable must be captured:
+// - if FunctionScopeIndexToStopAt is null, capture it in the CurContext
+// - else capture it in the DeclContext that maps to the
+// *FunctionScopeIndexToStopAt on the FunctionScopeInfo stack.
+inline void MarkVarDeclODRUsed(VarDecl *Var,
+ SourceLocation Loc, Sema &SemaRef,
+ const unsigned *const FunctionScopeIndexToStopAt) {
+ // Keep track of used but undefined variables.
+ // FIXME: We shouldn't suppress this warning for static data members.
+ if (Var->hasDefinition(SemaRef.Context) == VarDecl::DeclarationOnly &&
+ !Var->isExternallyVisible() &&
+ !(Var->isStaticDataMember() && Var->hasInit())) {
+ SourceLocation &old = SemaRef.UndefinedButUsed[Var->getCanonicalDecl()];
+ if (old.isInvalid()) old = Loc;
+ }
+ QualType CaptureType, DeclRefType;
+ SemaRef.tryCaptureVariable(Var, Loc, Sema::TryCapture_Implicit,
+ /*EllipsisLoc*/ SourceLocation(),
+ /*BuildAndDiagnose*/ true,
+ CaptureType, DeclRefType,
+ FunctionScopeIndexToStopAt);
+
+ Var->markUsed(SemaRef.Context);
+}
+
+/// Return a DLL attribute from the declaration.
+inline InheritableAttr *getDLLAttr(Decl *D) {
+ assert(!(D->hasAttr<DLLImportAttr>() && D->hasAttr<DLLExportAttr>()) &&
+ "A declaration cannot be both dllimport and dllexport.");
+ if (auto *Import = D->getAttr<DLLImportAttr>())
+ return Import;
+ if (auto *Export = D->getAttr<DLLExportAttr>())
+ return Export;
+ return nullptr;
+}
+
+class TypoCorrectionConsumer : public VisibleDeclConsumer {
+ typedef SmallVector<TypoCorrection, 1> TypoResultList;
+ typedef llvm::StringMap<TypoResultList> TypoResultsMap;
+ typedef std::map<unsigned, TypoResultsMap> TypoEditDistanceMap;
+
+public:
+ TypoCorrectionConsumer(Sema &SemaRef,
+ const DeclarationNameInfo &TypoName,
+ Sema::LookupNameKind LookupKind,
+ Scope *S, CXXScopeSpec *SS,
+ std::unique_ptr<CorrectionCandidateCallback> CCC,
+ DeclContext *MemberContext,
+ bool EnteringContext)
+ : Typo(TypoName.getName().getAsIdentifierInfo()), CurrentTCIndex(0),
+ SavedTCIndex(0), SemaRef(SemaRef), S(S),
+ SS(SS ? llvm::make_unique<CXXScopeSpec>(*SS) : nullptr),
+ CorrectionValidator(std::move(CCC)), MemberContext(MemberContext),
+ Result(SemaRef, TypoName, LookupKind),
+ Namespaces(SemaRef.Context, SemaRef.CurContext, SS),
+ EnteringContext(EnteringContext), SearchNamespaces(false) {
+ Result.suppressDiagnostics();
+ // Arrange for ValidatedCorrections[0] to always be an empty correction.
+ ValidatedCorrections.push_back(TypoCorrection());
+ }
+
+ bool includeHiddenDecls() const override { return true; }
+
+ // Methods for adding potential corrections to the consumer.
+ void FoundDecl(NamedDecl *ND, NamedDecl *Hiding, DeclContext *Ctx,
+ bool InBaseClass) override;
+ void FoundName(StringRef Name);
+ void addKeywordResult(StringRef Keyword);
+ void addCorrection(TypoCorrection Correction);
+
+ bool empty() const {
+ return CorrectionResults.empty() && ValidatedCorrections.size() == 1;
+ }
+
+ /// \brief Return the list of TypoCorrections for the given identifier from
+ /// the set of corrections that have the closest edit distance, if any.
+ TypoResultList &operator[](StringRef Name) {
+ return CorrectionResults.begin()->second[Name];
+ }
+
+ /// \brief Return the edit distance of the corrections that have the
+ /// closest/best edit distance from the original typop.
+ unsigned getBestEditDistance(bool Normalized) {
+ if (CorrectionResults.empty())
+ return (std::numeric_limits<unsigned>::max)();
+
+ unsigned BestED = CorrectionResults.begin()->first;
+ return Normalized ? TypoCorrection::NormalizeEditDistance(BestED) : BestED;
+ }
+
+ /// \brief Set-up method to add to the consumer the set of namespaces to use
+ /// in performing corrections to nested name specifiers. This method also
+ /// implicitly adds all of the known classes in the current AST context to the
+ /// to the consumer for correcting nested name specifiers.
+ void
+ addNamespaces(const llvm::MapVector<NamespaceDecl *, bool> &KnownNamespaces);
+
+ /// \brief Return the next typo correction that passes all internal filters
+ /// and is deemed valid by the consumer's CorrectionCandidateCallback,
+ /// starting with the corrections that have the closest edit distance. An
+ /// empty TypoCorrection is returned once no more viable corrections remain
+ /// in the consumer.
+ const TypoCorrection &getNextCorrection();
+
+ /// \brief Get the last correction returned by getNextCorrection().
+ const TypoCorrection &getCurrentCorrection() {
+ return CurrentTCIndex < ValidatedCorrections.size()
+ ? ValidatedCorrections[CurrentTCIndex]
+ : ValidatedCorrections[0]; // The empty correction.
+ }
+
+ /// \brief Return the next typo correction like getNextCorrection, but keep
+ /// the internal state pointed to the current correction (i.e. the next time
+ /// getNextCorrection is called, it will return the same correction returned
+ /// by peekNextcorrection).
+ const TypoCorrection &peekNextCorrection() {
+ auto Current = CurrentTCIndex;
+ const TypoCorrection &TC = getNextCorrection();
+ CurrentTCIndex = Current;
+ return TC;
+ }
+
+ /// \brief Reset the consumer's position in the stream of viable corrections
+ /// (i.e. getNextCorrection() will return each of the previously returned
+ /// corrections in order before returning any new corrections).
+ void resetCorrectionStream() {
+ CurrentTCIndex = 0;
+ }
+
+ /// \brief Return whether the end of the stream of corrections has been
+ /// reached.
+ bool finished() {
+ return CorrectionResults.empty() &&
+ CurrentTCIndex >= ValidatedCorrections.size();
+ }
+
+ /// \brief Save the current position in the correction stream (overwriting any
+ /// previously saved position).
+ void saveCurrentPosition() {
+ SavedTCIndex = CurrentTCIndex;
+ }
+
+ /// \brief Restore the saved position in the correction stream.
+ void restoreSavedPosition() {
+ CurrentTCIndex = SavedTCIndex;
+ }
+
+ ASTContext &getContext() const { return SemaRef.Context; }
+ const LookupResult &getLookupResult() const { return Result; }
+
+ bool isAddressOfOperand() const { return CorrectionValidator->IsAddressOfOperand; }
+ const CXXScopeSpec *getSS() const { return SS.get(); }
+ Scope *getScope() const { return S; }
+
+private:
+ class NamespaceSpecifierSet {
+ struct SpecifierInfo {
+ DeclContext* DeclCtx;
+ NestedNameSpecifier* NameSpecifier;
+ unsigned EditDistance;
+ };
+
+ typedef SmallVector<DeclContext*, 4> DeclContextList;
+ typedef SmallVector<SpecifierInfo, 16> SpecifierInfoList;
+
+ ASTContext &Context;
+ DeclContextList CurContextChain;
+ std::string CurNameSpecifier;
+ SmallVector<const IdentifierInfo*, 4> CurContextIdentifiers;
+ SmallVector<const IdentifierInfo*, 4> CurNameSpecifierIdentifiers;
+
+ std::map<unsigned, SpecifierInfoList> DistanceMap;
+
+ /// \brief Helper for building the list of DeclContexts between the current
+ /// context and the top of the translation unit
+ static DeclContextList buildContextChain(DeclContext *Start);
+
+ unsigned buildNestedNameSpecifier(DeclContextList &DeclChain,
+ NestedNameSpecifier *&NNS);
+
+ public:
+ NamespaceSpecifierSet(ASTContext &Context, DeclContext *CurContext,
+ CXXScopeSpec *CurScopeSpec);
+
+ /// \brief Add the DeclContext (a namespace or record) to the set, computing
+ /// the corresponding NestedNameSpecifier and its distance in the process.
+ void addNameSpecifier(DeclContext *Ctx);
+
+ /// \brief Provides flat iteration over specifiers, sorted by distance.
+ class iterator
+ : public llvm::iterator_facade_base<iterator, std::forward_iterator_tag,
+ SpecifierInfo> {
+ /// Always points to the last element in the distance map.
+ const std::map<unsigned, SpecifierInfoList>::iterator OuterBack;
+ /// Iterator on the distance map.
+ std::map<unsigned, SpecifierInfoList>::iterator Outer;
+ /// Iterator on an element in the distance map.
+ SpecifierInfoList::iterator Inner;
+
+ public:
+ iterator(NamespaceSpecifierSet &Set, bool IsAtEnd)
+ : OuterBack(std::prev(Set.DistanceMap.end())),
+ Outer(Set.DistanceMap.begin()),
+ Inner(!IsAtEnd ? Outer->second.begin() : OuterBack->second.end()) {
+ assert(!Set.DistanceMap.empty());
+ }
+
+ iterator &operator++() {
+ ++Inner;
+ if (Inner == Outer->second.end() && Outer != OuterBack) {
+ ++Outer;
+ Inner = Outer->second.begin();
+ }
+ return *this;
+ }
+
+ SpecifierInfo &operator*() { return *Inner; }
+ bool operator==(const iterator &RHS) const { return Inner == RHS.Inner; }
+ };
+
+ iterator begin() { return iterator(*this, /*IsAtEnd=*/false); }
+ iterator end() { return iterator(*this, /*IsAtEnd=*/true); }
+ };
+
+ void addName(StringRef Name, NamedDecl *ND,
+ NestedNameSpecifier *NNS = nullptr, bool isKeyword = false);
+
+ /// \brief Find any visible decls for the given typo correction candidate.
+ /// If none are found, it to the set of candidates for which qualified lookups
+ /// will be performed to find possible nested name specifier changes.
+ bool resolveCorrection(TypoCorrection &Candidate);
+
+ /// \brief Perform qualified lookups on the queued set of typo correction
+ /// candidates and add the nested name specifier changes to each candidate if
+ /// a lookup succeeds (at which point the candidate will be returned to the
+ /// main pool of potential corrections).
+ void performQualifiedLookups();
+
+ /// \brief The name written that is a typo in the source.
+ IdentifierInfo *Typo;
+
+ /// \brief The results found that have the smallest edit distance
+ /// found (so far) with the typo name.
+ ///
+ /// The pointer value being set to the current DeclContext indicates
+ /// whether there is a keyword with this name.
+ TypoEditDistanceMap CorrectionResults;
+
+ SmallVector<TypoCorrection, 4> ValidatedCorrections;
+ size_t CurrentTCIndex;
+ size_t SavedTCIndex;
+
+ Sema &SemaRef;
+ Scope *S;
+ std::unique_ptr<CXXScopeSpec> SS;
+ std::unique_ptr<CorrectionCandidateCallback> CorrectionValidator;
+ DeclContext *MemberContext;
+ LookupResult Result;
+ NamespaceSpecifierSet Namespaces;
+ SmallVector<TypoCorrection, 2> QualifiedResults;
+ bool EnteringContext;
+ bool SearchNamespaces;
+};
+
+inline Sema::TypoExprState::TypoExprState() {}
+
+inline Sema::TypoExprState::TypoExprState(TypoExprState &&other) LLVM_NOEXCEPT {
+ *this = std::move(other);
+}
+
+inline Sema::TypoExprState &Sema::TypoExprState::operator=(
+ Sema::TypoExprState &&other) LLVM_NOEXCEPT {
+ Consumer = std::move(other.Consumer);
+ DiagHandler = std::move(other.DiagHandler);
+ RecoveryHandler = std::move(other.RecoveryHandler);
+ return *this;
+}
+
+} // end namespace clang
+
+#endif
diff --git a/contrib/llvm/tools/clang/include/clang/Sema/SemaLambda.h b/contrib/llvm/tools/clang/include/clang/Sema/SemaLambda.h
new file mode 100644
index 0000000..d043e2c
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Sema/SemaLambda.h
@@ -0,0 +1,36 @@
+//===--- SemaLambda.h - Lambda Helper Functions --------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+///
+/// \file
+/// \brief This file provides some common utility functions for processing
+/// Lambdas.
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_SEMA_SEMALAMBDA_H
+#define LLVM_CLANG_SEMA_SEMALAMBDA_H
+#include "clang/AST/ASTLambda.h"
+#include "clang/Sema/ScopeInfo.h"
+namespace clang {
+
+
+/// \brief Examines the FunctionScopeInfo stack to determine the nearest
+/// enclosing lambda (to the current lambda) that is 'capture-capable' for
+/// the variable referenced in the current lambda (i.e. \p VarToCapture).
+/// If successful, returns the index into Sema's FunctionScopeInfo stack
+/// of the capture-capable lambda's LambdaScopeInfo.
+/// See Implementation for more detailed comments.
+
+Optional<unsigned> getStackIndexOfNearestEnclosingCaptureCapableLambda(
+ ArrayRef<const sema::FunctionScopeInfo *> FunctionScopes,
+ VarDecl *VarToCapture, Sema &S);
+
+} // clang
+
+#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..c092630
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Sema/Template.h
@@ -0,0 +1,519 @@
+//===------- 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 "clang/Sema/Sema.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 {
+ /// \brief The template argument list at a certain template depth
+ typedef ArrayRef<TemplateArgument> ArgList;
+
+ /// \brief The template argument lists, stored from the innermost template
+ /// argument list (first) to the outermost template argument list (last).
+ 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].size());
+ return TemplateArgumentLists[getNumLevels() - Depth - 1][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].size())
+ 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].size());
+ const_cast<TemplateArgument&>(
+ TemplateArgumentLists[getNumLevels() - Depth - 1][Index])
+ = Arg;
+ }
+
+ /// \brief Add a new outermost level to the multi-level template argument
+ /// list.
+ void addOuterTemplateArguments(const TemplateArgumentList *TemplateArgs) {
+ addOuterTemplateArguments(ArgList(TemplateArgs->data(),
+ TemplateArgs->size()));
+ }
+
+ /// \brief Add a new outmost level to the multi-level template argument
+ /// list.
+ void addOuterTemplateArguments(ArgList Args) {
+ TemplateArgumentLists.push_back(Args);
+ }
+
+ /// \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(ASTContext &Ctx,
+ const llvm::APSInt &Value,
+ QualType ValueType,
+ bool DeducedFromArrayBound)
+ : TemplateArgument(Ctx, 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 SmallVector<ParmVarDecl *, 4> DeclArgumentPack;
+
+ private:
+ /// \brief Reference to the semantic analysis that is performing
+ /// this template instantiation.
+ Sema &SemaRef;
+
+ typedef llvm::SmallDenseMap<
+ const Decl *, llvm::PointerUnion<Decl *, DeclArgumentPack *>, 4>
+ 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.
+ 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 &) = delete;
+ void operator=(const LocalInstantiationScope &) = delete;
+
+ public:
+ LocalInstantiationScope(Sema &SemaRef, bool CombineWithOuterScope = false)
+ : SemaRef(SemaRef), Outer(SemaRef.CurrentInstantiationScope),
+ Exited(false), CombineWithOuterScope(CombineWithOuterScope),
+ PartiallySubstitutedPack(nullptr)
+ {
+ 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 Clone this scope, and all outer scopes, down to the given
+ /// outermost scope.
+ LocalInstantiationScope *cloneScopes(LocalInstantiationScope *Outermost) {
+ if (this == Outermost) return this;
+
+ // Save the current scope from SemaRef since the LocalInstantiationScope
+ // will overwrite it on construction
+ LocalInstantiationScope *oldScope = SemaRef.CurrentInstantiationScope;
+
+ LocalInstantiationScope *newScope =
+ new LocalInstantiationScope(SemaRef, CombineWithOuterScope);
+
+ newScope->Outer = nullptr;
+ if (Outer)
+ newScope->Outer = Outer->cloneScopes(Outermost);
+
+ newScope->PartiallySubstitutedPack = PartiallySubstitutedPack;
+ newScope->ArgsInPartiallySubstitutedPack = ArgsInPartiallySubstitutedPack;
+ newScope->NumArgsInPartiallySubstitutedPack =
+ NumArgsInPartiallySubstitutedPack;
+
+ for (LocalDeclsMap::iterator I = LocalDecls.begin(), E = LocalDecls.end();
+ I != E; ++I) {
+ const Decl *D = I->first;
+ llvm::PointerUnion<Decl *, DeclArgumentPack *> &Stored =
+ newScope->LocalDecls[D];
+ if (I->second.is<Decl *>()) {
+ Stored = I->second.get<Decl *>();
+ } else {
+ DeclArgumentPack *OldPack = I->second.get<DeclArgumentPack *>();
+ DeclArgumentPack *NewPack = new DeclArgumentPack(*OldPack);
+ Stored = NewPack;
+ newScope->ArgumentPacks.push_back(NewPack);
+ }
+ }
+ // Restore the saved scope to SemaRef
+ SemaRef.CurrentInstantiationScope = oldScope;
+ return newScope;
+ }
+
+ /// \brief deletes the given scope, and all otuer scopes, down to the
+ /// given outermost scope.
+ static void deleteScopes(LocalInstantiationScope *Scope,
+ LocalInstantiationScope *Outermost) {
+ while (Scope && Scope != Outermost) {
+ LocalInstantiationScope *Out = Scope->Outer;
+ delete Scope;
+ Scope = Out;
+ }
+ }
+
+ /// \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 instantiated, 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, ParmVarDecl *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 Reset the partially-substituted pack when it is no longer of
+ /// interest.
+ void ResetPartiallySubstitutedPack() {
+ assert(PartiallySubstitutedPack && "No partially-substituted pack");
+ PartiallySubstitutedPack = nullptr;
+ ArgsInPartiallySubstitutedPack = nullptr;
+ NumArgsInPartiallySubstitutedPack = 0;
+ }
+
+ /// \brief Retrieve the partially-substitued template parameter pack.
+ ///
+ /// If there is no partially-substituted parameter pack, returns NULL.
+ NamedDecl *
+ getPartiallySubstitutedPack(const TemplateArgument **ExplicitArgs = nullptr,
+ unsigned *NumExplicitArgs = nullptr) const;
+ };
+
+ class TemplateDeclInstantiator
+ : public DeclVisitor<TemplateDeclInstantiator, Decl *>
+ {
+ Sema &SemaRef;
+ Sema::ArgumentPackSubstitutionIndexRAII SubstIndex;
+ DeclContext *Owner;
+ const MultiLevelTemplateArgumentList &TemplateArgs;
+ Sema::LateInstantiatedAttrVec* LateAttrs;
+ LocalInstantiationScope *StartingScope;
+
+ /// \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.
+ SmallVector<std::pair<ClassTemplateDecl *,
+ ClassTemplatePartialSpecializationDecl *>, 4>
+ OutOfLinePartialSpecs;
+
+ /// \brief A list of out-of-line variable template partial
+ /// specializations that will need to be instantiated after the
+ /// enclosing variable's instantiation is complete.
+ /// FIXME: Verify that this is needed.
+ SmallVector<
+ std::pair<VarTemplateDecl *, VarTemplatePartialSpecializationDecl *>, 4>
+ OutOfLineVarPartialSpecs;
+
+ public:
+ TemplateDeclInstantiator(Sema &SemaRef, DeclContext *Owner,
+ const MultiLevelTemplateArgumentList &TemplateArgs)
+ : SemaRef(SemaRef),
+ SubstIndex(SemaRef, SemaRef.ArgumentPackSubstitutionIndex),
+ Owner(Owner), TemplateArgs(TemplateArgs), LateAttrs(nullptr),
+ StartingScope(nullptr) {}
+
+// Define all the decl visitors using DeclNodes.inc
+#define DECL(DERIVED, BASE) \
+ Decl *Visit ## DERIVED ## Decl(DERIVED ## Decl *D);
+#define ABSTRACT_DECL(DECL)
+
+// Decls which never appear inside a class or function.
+#define OBJCCONTAINER(DERIVED, BASE)
+#define FILESCOPEASM(DERIVED, BASE)
+#define IMPORT(DERIVED, BASE)
+#define LINKAGESPEC(DERIVED, BASE)
+#define OBJCCOMPATIBLEALIAS(DERIVED, BASE)
+#define OBJCMETHOD(DERIVED, BASE)
+#define OBJCTYPEPARAM(DERIVED, BASE)
+#define OBJCIVAR(DERIVED, BASE)
+#define OBJCPROPERTY(DERIVED, BASE)
+#define OBJCPROPERTYIMPL(DERIVED, BASE)
+#define EMPTY(DERIVED, BASE)
+
+// Decls which use special-case instantiation code.
+#define BLOCK(DERIVED, BASE)
+#define CAPTURED(DERIVED, BASE)
+#define IMPLICITPARAM(DERIVED, BASE)
+
+#include "clang/AST/DeclNodes.inc"
+
+ // A few supplemental visitor functions.
+ Decl *VisitCXXMethodDecl(CXXMethodDecl *D,
+ TemplateParameterList *TemplateParams,
+ bool IsClassScopeSpecialization = false);
+ Decl *VisitFunctionDecl(FunctionDecl *D,
+ TemplateParameterList *TemplateParams);
+ Decl *VisitDecl(Decl *D);
+ Decl *VisitVarDecl(VarDecl *D, bool InstantiatingVarTemplate);
+
+ // Enable late instantiation of attributes. Late instantiated attributes
+ // will be stored in LA.
+ void enableLateAttributeInstantiation(Sema::LateInstantiatedAttrVec *LA) {
+ LateAttrs = LA;
+ StartingScope = SemaRef.CurrentInstantiationScope;
+ }
+
+ // Disable late instantiation of attributes.
+ void disableLateAttributeInstantiation() {
+ LateAttrs = nullptr;
+ StartingScope = nullptr;
+ }
+
+ LocalInstantiationScope *getStartingScope() const { return StartingScope; }
+
+ typedef
+ SmallVectorImpl<std::pair<ClassTemplateDecl *,
+ ClassTemplatePartialSpecializationDecl *> >
+ ::iterator
+ delayed_partial_spec_iterator;
+
+ typedef SmallVectorImpl<std::pair<
+ VarTemplateDecl *, VarTemplatePartialSpecializationDecl *> >::iterator
+ delayed_var_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();
+ }
+
+ delayed_var_partial_spec_iterator delayed_var_partial_spec_begin() {
+ return OutOfLineVarPartialSpecs.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();
+ }
+
+ delayed_var_partial_spec_iterator delayed_var_partial_spec_end() {
+ return OutOfLineVarPartialSpecs.end();
+ }
+
+ // Helper functions for instantiating methods.
+ TypeSourceInfo *SubstFunctionType(FunctionDecl *D,
+ 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);
+
+ Decl *VisitVarTemplateSpecializationDecl(
+ VarTemplateDecl *VarTemplate, VarDecl *FromVar, void *InsertPos,
+ const TemplateArgumentListInfo &TemplateArgsInfo,
+ ArrayRef<TemplateArgument> Converted);
+
+ Decl *InstantiateTypedefNameDecl(TypedefNameDecl *D, bool IsTypeAlias);
+ ClassTemplatePartialSpecializationDecl *
+ InstantiateClassTemplatePartialSpecialization(
+ ClassTemplateDecl *ClassTemplate,
+ ClassTemplatePartialSpecializationDecl *PartialSpec);
+ VarTemplatePartialSpecializationDecl *
+ InstantiateVarTemplatePartialSpecialization(
+ VarTemplateDecl *VarTemplate,
+ VarTemplatePartialSpecializationDecl *PartialSpec);
+ void InstantiateEnumDefinition(EnumDecl *Enum, EnumDecl *Pattern);
+ };
+}
+
+#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..c22c703
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Sema/TemplateDeduction.h
@@ -0,0 +1,315 @@
+//===- 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_TEMPLATEDEDUCTION_H
+#define LLVM_CLANG_SEMA_TEMPLATEDEDUCTION_H
+
+#include "clang/AST/DeclTemplate.h"
+#include "clang/Basic/PartialDiagnostic.h"
+#include "llvm/ADT/SmallVector.h"
+
+namespace clang {
+
+struct DeducedPack;
+class TemplateArgumentList;
+class Sema;
+
+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 deduced template argument list.
+ ///
+ TemplateArgumentList *Deduced;
+
+ /// \brief The source location at which template argument
+ /// deduction is occurring.
+ SourceLocation Loc;
+
+ /// \brief Have we suppressed an error during deduction?
+ bool HasSFINAEDiagnostic;
+
+ /// \brief Warnings (and follow-on notes) that were suppressed due to
+ /// SFINAE while performing template argument deduction.
+ SmallVector<PartialDiagnosticAt, 4> SuppressedDiagnostics;
+
+ TemplateDeductionInfo(const TemplateDeductionInfo &) = delete;
+ void operator=(const TemplateDeductionInfo &) = delete;
+
+public:
+ TemplateDeductionInfo(SourceLocation Loc)
+ : Deduced(nullptr), Loc(Loc), HasSFINAEDiagnostic(false),
+ Expression(nullptr) {}
+
+ /// \brief Returns the location at which template argument is
+ /// occurring.
+ SourceLocation getLocation() const {
+ return Loc;
+ }
+
+ /// \brief Take ownership of the deduced template argument list.
+ TemplateArgumentList *take() {
+ TemplateArgumentList *Result = Deduced;
+ Deduced = nullptr;
+ return Result;
+ }
+
+ /// \brief Take ownership of the SFINAE diagnostic.
+ void takeSFINAEDiagnostic(PartialDiagnosticAt &PD) {
+ assert(HasSFINAEDiagnostic);
+ PD.first = SuppressedDiagnostics.front().first;
+ PD.second.swap(SuppressedDiagnostics.front().second);
+ SuppressedDiagnostics.clear();
+ HasSFINAEDiagnostic = false;
+ }
+
+ /// \brief Provide a new template argument list that contains the
+ /// results of template argument deduction.
+ void reset(TemplateArgumentList *NewDeduced) {
+ Deduced = NewDeduced;
+ }
+
+ /// \brief Is a SFINAE diagnostic available?
+ bool hasSFINAEDiagnostic() const {
+ return HasSFINAEDiagnostic;
+ }
+
+ /// \brief Set the diagnostic which caused the SFINAE failure.
+ void addSFINAEDiagnostic(SourceLocation Loc, PartialDiagnostic PD) {
+ // Only collect the first diagnostic.
+ if (HasSFINAEDiagnostic)
+ return;
+ SuppressedDiagnostics.clear();
+ SuppressedDiagnostics.emplace_back(Loc, std::move(PD));
+ HasSFINAEDiagnostic = true;
+ }
+
+ /// \brief Add a new diagnostic to the set of diagnostics
+ void addSuppressedDiagnostic(SourceLocation Loc,
+ PartialDiagnostic PD) {
+ if (HasSFINAEDiagnostic)
+ return;
+ SuppressedDiagnostics.emplace_back(Loc, std::move(PD));
+ }
+
+ /// \brief Iterator over the set of suppressed diagnostics.
+ typedef 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_DeducedMismatch: this is the parameter type, after substituting
+ /// deduced arguments.
+ ///
+ /// TDK_NonDeducedMismatch: this is the component of the 'parameter'
+ /// of the deduction, directly provided in the source code.
+ TemplateArgument FirstArg;
+
+ /// \brief The second template argument to which the template
+ /// argument deduction failure refers.
+ ///
+ /// TDK_Inconsistent: this argument is the second value deduced
+ /// for the corresponding template parameter.
+ ///
+ /// TDK_DeducedMismatch: this is the (adjusted) call argument type.
+ ///
+ /// TDK_NonDeducedMismatch: this is the mismatching component of the
+ /// 'argument' of the deduction, from which we are deducing arguments.
+ ///
+ /// FIXME: Finish documenting this.
+ TemplateArgument SecondArg;
+
+ union {
+ /// \brief The expression which caused a deduction failure.
+ ///
+ /// TDK_FailedOverloadResolution: this argument is the reference to
+ /// an overloaded function which could not be resolved to a specific
+ /// function.
+ Expr *Expression;
+
+ /// \brief The index of the function argument that caused a deduction
+ /// failure.
+ ///
+ /// TDK_DeducedMismatch: this is the index of the argument that had a
+ /// different argument type from its substituted parameter type.
+ unsigned CallArgIndex;
+ };
+
+ /// \brief Information on packs that we're currently expanding.
+ ///
+ /// FIXME: This should be kept internal to SemaTemplateDeduction.
+ SmallVector<DeducedPack *, 8> PendingDeducedPacks;
+};
+
+} // end namespace sema
+
+/// A structure used to record information about a failed
+/// template argument deduction, for diagnosis.
+struct DeductionFailureInfo {
+ /// A Sema::TemplateDeductionResult.
+ unsigned Result : 8;
+
+ /// \brief Indicates whether a diagnostic is stored in Diagnostic.
+ unsigned HasDiagnostic : 1;
+
+ /// \brief Opaque pointer containing additional data about
+ /// this deduction failure.
+ void *Data;
+
+ /// \brief A diagnostic indicating why deduction failed.
+ union {
+ void *Align;
+ char Diagnostic[sizeof(PartialDiagnosticAt)];
+ };
+
+ /// \brief Retrieve the diagnostic which caused this deduction failure,
+ /// if any.
+ PartialDiagnosticAt *getSFINAEDiagnostic();
+
+ /// \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 Return the expression this deduction failure refers to,
+ /// if any.
+ Expr *getExpr();
+
+ /// \brief Return the index of the call argument that this deduction
+ /// failure refers to, if any.
+ llvm::Optional<unsigned> getCallArgIndex();
+
+ /// \brief Free any memory associated with this deduction failure.
+ void Destroy();
+};
+
+/// TemplateSpecCandidate - This is a generalization of OverloadCandidate
+/// which keeps track of template argument deduction failure info, when
+/// handling explicit specializations (and instantiations) of templates
+/// beyond function overloading.
+/// For now, assume that the candidates are non-matching specializations.
+/// TODO: In the future, we may need to unify/generalize this with
+/// OverloadCandidate.
+struct TemplateSpecCandidate {
+ /// Specialization - The actual specialization that this candidate
+ /// represents. When NULL, this may be a built-in candidate.
+ Decl *Specialization;
+
+ /// Template argument deduction info
+ DeductionFailureInfo DeductionFailure;
+
+ void set(Decl *Spec, DeductionFailureInfo Info) {
+ Specialization = Spec;
+ DeductionFailure = Info;
+ }
+
+ /// Diagnose a template argument deduction failure.
+ void NoteDeductionFailure(Sema &S, bool ForTakingAddress);
+};
+
+/// TemplateSpecCandidateSet - A set of generalized overload candidates,
+/// used in template specializations.
+/// TODO: In the future, we may need to unify/generalize this with
+/// OverloadCandidateSet.
+class TemplateSpecCandidateSet {
+ SmallVector<TemplateSpecCandidate, 16> Candidates;
+ SourceLocation Loc;
+ // Stores whether we're taking the address of these candidates. This helps us
+ // produce better error messages when dealing with the pass_object_size
+ // attribute on parameters.
+ bool ForTakingAddress;
+
+ TemplateSpecCandidateSet(
+ const TemplateSpecCandidateSet &) = delete;
+ void operator=(const TemplateSpecCandidateSet &) = delete;
+
+ void destroyCandidates();
+
+public:
+ TemplateSpecCandidateSet(SourceLocation Loc, bool ForTakingAddress = false)
+ : Loc(Loc), ForTakingAddress(ForTakingAddress) {}
+ ~TemplateSpecCandidateSet() { destroyCandidates(); }
+
+ SourceLocation getLocation() const { return Loc; }
+
+ /// \brief Clear out all of the candidates.
+ /// TODO: This may be unnecessary.
+ void clear();
+
+ typedef SmallVector<TemplateSpecCandidate, 16>::iterator iterator;
+ iterator begin() { return Candidates.begin(); }
+ iterator end() { return Candidates.end(); }
+
+ size_t size() const { return Candidates.size(); }
+ bool empty() const { return Candidates.empty(); }
+
+ /// \brief Add a new candidate with NumConversions conversion sequence slots
+ /// to the overload set.
+ TemplateSpecCandidate &addCandidate() {
+ Candidates.emplace_back();
+ return Candidates.back();
+ }
+
+ void NoteCandidates(Sema &S, SourceLocation Loc);
+
+ void NoteCandidates(Sema &S, SourceLocation Loc) const {
+ const_cast<TemplateSpecCandidateSet *>(this)->NoteCandidates(S, Loc);
+ }
+};
+
+} // end namespace clang
+
+#endif
diff --git a/contrib/llvm/tools/clang/include/clang/Sema/TypoCorrection.h b/contrib/llvm/tools/clang/include/clang/Sema/TypoCorrection.h
new file mode 100644
index 0000000..3b0385e
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Sema/TypoCorrection.h
@@ -0,0 +1,366 @@
+//===--- TypoCorrection.h - Class for typo correction results ---*- C++ -*-===//
+//
+// 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 TypoCorrection class, which stores the results of
+// Sema's typo correction (Sema::CorrectTypo).
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_SEMA_TYPOCORRECTION_H
+#define LLVM_CLANG_SEMA_TYPOCORRECTION_H
+
+#include "clang/AST/DeclCXX.h"
+#include "clang/Sema/DeclSpec.h"
+#include "clang/Sema/Ownership.h"
+#include "llvm/ADT/SmallVector.h"
+
+namespace clang {
+
+/// @brief Simple class containing the result of Sema::CorrectTypo
+class TypoCorrection {
+public:
+ // "Distance" for unusable corrections
+ static const unsigned InvalidDistance = ~0U;
+ // The largest distance still considered valid (larger edit distances are
+ // mapped to InvalidDistance by getEditDistance).
+ static const unsigned MaximumDistance = 10000U;
+
+ // Relative weightings of the "edit distance" components. The higher the
+ // weight, the more of a penalty to fitness the component will give (higher
+ // weights mean greater contribution to the total edit distance, with the
+ // best correction candidates having the lowest edit distance).
+ static const unsigned CharDistanceWeight = 100U;
+ static const unsigned QualifierDistanceWeight = 110U;
+ static const unsigned CallbackDistanceWeight = 150U;
+
+ TypoCorrection(const DeclarationName &Name, NamedDecl *NameDecl,
+ NestedNameSpecifier *NNS = nullptr, unsigned CharDistance = 0,
+ unsigned QualifierDistance = 0)
+ : CorrectionName(Name), CorrectionNameSpec(NNS),
+ CharDistance(CharDistance), QualifierDistance(QualifierDistance),
+ CallbackDistance(0), ForceSpecifierReplacement(false),
+ RequiresImport(false) {
+ if (NameDecl)
+ CorrectionDecls.push_back(NameDecl);
+ }
+
+ TypoCorrection(NamedDecl *Name, NestedNameSpecifier *NNS = nullptr,
+ unsigned CharDistance = 0)
+ : CorrectionName(Name->getDeclName()), CorrectionNameSpec(NNS),
+ CharDistance(CharDistance), QualifierDistance(0), CallbackDistance(0),
+ ForceSpecifierReplacement(false), RequiresImport(false) {
+ if (Name)
+ CorrectionDecls.push_back(Name);
+ }
+
+ TypoCorrection(DeclarationName Name, NestedNameSpecifier *NNS = nullptr,
+ unsigned CharDistance = 0)
+ : CorrectionName(Name), CorrectionNameSpec(NNS),
+ CharDistance(CharDistance), QualifierDistance(0), CallbackDistance(0),
+ ForceSpecifierReplacement(false), RequiresImport(false) {}
+
+ TypoCorrection()
+ : CorrectionNameSpec(nullptr), CharDistance(0), QualifierDistance(0),
+ CallbackDistance(0), ForceSpecifierReplacement(false),
+ RequiresImport(false) {}
+
+ /// \brief Gets the DeclarationName of the typo correction
+ DeclarationName getCorrection() const { return CorrectionName; }
+ IdentifierInfo *getCorrectionAsIdentifierInfo() const {
+ return CorrectionName.getAsIdentifierInfo();
+ }
+
+ /// \brief Gets the NestedNameSpecifier needed to use the typo correction
+ NestedNameSpecifier *getCorrectionSpecifier() const {
+ return CorrectionNameSpec;
+ }
+ void setCorrectionSpecifier(NestedNameSpecifier *NNS) {
+ CorrectionNameSpec = NNS;
+ ForceSpecifierReplacement = (NNS != nullptr);
+ }
+
+ void WillReplaceSpecifier(bool ForceReplacement) {
+ ForceSpecifierReplacement = ForceReplacement;
+ }
+
+ bool WillReplaceSpecifier() const {
+ return ForceSpecifierReplacement;
+ }
+
+ void setQualifierDistance(unsigned ED) {
+ QualifierDistance = ED;
+ }
+
+ void setCallbackDistance(unsigned ED) {
+ CallbackDistance = ED;
+ }
+
+ // Convert the given weighted edit distance to a roughly equivalent number of
+ // single-character edits (typically for comparison to the length of the
+ // string being edited).
+ static unsigned NormalizeEditDistance(unsigned ED) {
+ if (ED > MaximumDistance)
+ return InvalidDistance;
+ return (ED + CharDistanceWeight / 2) / CharDistanceWeight;
+ }
+
+ /// \brief Gets the "edit distance" of the typo correction from the typo.
+ /// If Normalized is true, scale the distance down by the CharDistanceWeight
+ /// to return the edit distance in terms of single-character edits.
+ unsigned getEditDistance(bool Normalized = true) const {
+ if (CharDistance > MaximumDistance || QualifierDistance > MaximumDistance ||
+ CallbackDistance > MaximumDistance)
+ return InvalidDistance;
+ unsigned ED =
+ CharDistance * CharDistanceWeight +
+ QualifierDistance * QualifierDistanceWeight +
+ CallbackDistance * CallbackDistanceWeight;
+ if (ED > MaximumDistance)
+ return InvalidDistance;
+ // Half the CharDistanceWeight is added to ED to simulate rounding since
+ // integer division truncates the value (i.e. round-to-nearest-int instead
+ // of round-to-zero).
+ return Normalized ? NormalizeEditDistance(ED) : ED;
+ }
+
+ /// \brief Get the correction declaration found by name lookup (before we
+ /// looked through using shadow declarations and the like).
+ NamedDecl *getFoundDecl() const {
+ return hasCorrectionDecl() ? *(CorrectionDecls.begin()) : nullptr;
+ }
+
+ /// \brief Gets the pointer to the declaration of the typo correction
+ NamedDecl *getCorrectionDecl() const {
+ auto *D = getFoundDecl();
+ return D ? D->getUnderlyingDecl() : nullptr;
+ }
+ template <class DeclClass>
+ DeclClass *getCorrectionDeclAs() const {
+ return dyn_cast_or_null<DeclClass>(getCorrectionDecl());
+ }
+
+ /// \brief Clears the list of NamedDecls.
+ void ClearCorrectionDecls() {
+ CorrectionDecls.clear();
+ }
+
+ /// \brief Clears the list of NamedDecls before adding the new one.
+ void setCorrectionDecl(NamedDecl *CDecl) {
+ CorrectionDecls.clear();
+ addCorrectionDecl(CDecl);
+ }
+
+ /// \brief Clears the list of NamedDecls and adds the given set.
+ void setCorrectionDecls(ArrayRef<NamedDecl*> Decls) {
+ CorrectionDecls.clear();
+ CorrectionDecls.insert(CorrectionDecls.begin(), Decls.begin(), Decls.end());
+ }
+
+ /// \brief Add the given NamedDecl to the list of NamedDecls that are the
+ /// declarations associated with the DeclarationName of this TypoCorrection
+ void addCorrectionDecl(NamedDecl *CDecl);
+
+ std::string getAsString(const LangOptions &LO) const;
+ std::string getQuoted(const LangOptions &LO) const {
+ return "'" + getAsString(LO) + "'";
+ }
+
+ /// \brief Returns whether this TypoCorrection has a non-empty DeclarationName
+ explicit operator bool() const { return bool(CorrectionName); }
+
+ /// \brief Mark this TypoCorrection as being a keyword.
+ /// Since addCorrectionDeclsand setCorrectionDecl don't allow NULL to be
+ /// added to the list of the correction's NamedDecl pointers, NULL is added
+ /// as the only element in the list to mark this TypoCorrection as a keyword.
+ void makeKeyword() {
+ CorrectionDecls.clear();
+ CorrectionDecls.push_back(nullptr);
+ ForceSpecifierReplacement = true;
+ }
+
+ // Check if this TypoCorrection is a keyword by checking if the first
+ // item in CorrectionDecls is NULL.
+ bool isKeyword() const {
+ return !CorrectionDecls.empty() && CorrectionDecls.front() == nullptr;
+ }
+
+ // Check if this TypoCorrection is the given keyword.
+ template<std::size_t StrLen>
+ bool isKeyword(const char (&Str)[StrLen]) const {
+ return isKeyword() && getCorrectionAsIdentifierInfo()->isStr(Str);
+ }
+
+ // Returns true if the correction either is a keyword or has a known decl.
+ bool isResolved() const { return !CorrectionDecls.empty(); }
+
+ bool isOverloaded() const {
+ return CorrectionDecls.size() > 1;
+ }
+
+ void setCorrectionRange(CXXScopeSpec *SS,
+ const DeclarationNameInfo &TypoName) {
+ CorrectionRange = TypoName.getSourceRange();
+ if (ForceSpecifierReplacement && SS && !SS->isEmpty())
+ CorrectionRange.setBegin(SS->getBeginLoc());
+ }
+
+ SourceRange getCorrectionRange() const {
+ return CorrectionRange;
+ }
+
+ typedef SmallVectorImpl<NamedDecl *>::iterator decl_iterator;
+ decl_iterator begin() {
+ return isKeyword() ? CorrectionDecls.end() : CorrectionDecls.begin();
+ }
+ decl_iterator end() { return CorrectionDecls.end(); }
+ typedef SmallVectorImpl<NamedDecl *>::const_iterator const_decl_iterator;
+ const_decl_iterator begin() const {
+ return isKeyword() ? CorrectionDecls.end() : CorrectionDecls.begin();
+ }
+ const_decl_iterator end() const { return CorrectionDecls.end(); }
+
+ /// \brief Returns whether this typo correction is correcting to a
+ /// declaration that was declared in a module that has not been imported.
+ bool requiresImport() const { return RequiresImport; }
+ void setRequiresImport(bool Req) { RequiresImport = Req; }
+
+private:
+ bool hasCorrectionDecl() const {
+ return (!isKeyword() && !CorrectionDecls.empty());
+ }
+
+ // Results.
+ DeclarationName CorrectionName;
+ NestedNameSpecifier *CorrectionNameSpec;
+ SmallVector<NamedDecl *, 1> CorrectionDecls;
+ unsigned CharDistance;
+ unsigned QualifierDistance;
+ unsigned CallbackDistance;
+ SourceRange CorrectionRange;
+ bool ForceSpecifierReplacement;
+ bool RequiresImport;
+};
+
+/// @brief Base class for callback objects used by Sema::CorrectTypo to check
+/// the validity of a potential typo correction.
+class CorrectionCandidateCallback {
+public:
+ static const unsigned InvalidDistance = TypoCorrection::InvalidDistance;
+
+ explicit CorrectionCandidateCallback(IdentifierInfo *Typo = nullptr,
+ NestedNameSpecifier *TypoNNS = nullptr)
+ : WantTypeSpecifiers(true), WantExpressionKeywords(true),
+ WantCXXNamedCasts(true), WantFunctionLikeCasts(true),
+ WantRemainingKeywords(true), WantObjCSuper(false),
+ IsObjCIvarLookup(false), IsAddressOfOperand(false), Typo(Typo),
+ TypoNNS(TypoNNS) {}
+
+ virtual ~CorrectionCandidateCallback() {}
+
+ /// \brief Simple predicate used by the default RankCandidate to
+ /// determine whether to return an edit distance of 0 or InvalidDistance.
+ /// This can be overrided by validators that only need to determine if a
+ /// candidate is viable, without ranking potentially viable candidates.
+ /// Only ValidateCandidate or RankCandidate need to be overriden by a
+ /// callback wishing to check the viability of correction candidates.
+ /// The default predicate always returns true if the candidate is not a type
+ /// name or keyword, true for types if WantTypeSpecifiers is true, and true
+ /// for keywords if WantTypeSpecifiers, WantExpressionKeywords,
+ /// WantCXXNamedCasts, WantRemainingKeywords, or WantObjCSuper is true.
+ virtual bool ValidateCandidate(const TypoCorrection &candidate);
+
+ /// \brief Method used by Sema::CorrectTypo to assign an "edit distance" rank
+ /// to a candidate (where a lower value represents a better candidate), or
+ /// returning InvalidDistance if the candidate is not at all viable. For
+ /// validation callbacks that only need to determine if a candidate is viable,
+ /// the default RankCandidate returns either 0 or InvalidDistance depending
+ /// whether ValidateCandidate returns true or false.
+ virtual unsigned RankCandidate(const TypoCorrection &candidate) {
+ return (!MatchesTypo(candidate) && ValidateCandidate(candidate))
+ ? 0
+ : InvalidDistance;
+ }
+
+ void setTypoName(IdentifierInfo *II) { Typo = II; }
+ void setTypoNNS(NestedNameSpecifier *NNS) { TypoNNS = NNS; }
+
+ // Flags for context-dependent keywords. WantFunctionLikeCasts is only
+ // used/meaningful when WantCXXNamedCasts is false.
+ // TODO: Expand these to apply to non-keywords or possibly remove them.
+ bool WantTypeSpecifiers;
+ bool WantExpressionKeywords;
+ bool WantCXXNamedCasts;
+ bool WantFunctionLikeCasts;
+ bool WantRemainingKeywords;
+ bool WantObjCSuper;
+ // Temporary hack for the one case where a CorrectTypoContext enum is used
+ // when looking up results.
+ bool IsObjCIvarLookup;
+ bool IsAddressOfOperand;
+
+protected:
+ bool MatchesTypo(const TypoCorrection &candidate) {
+ return Typo && candidate.isResolved() && !candidate.requiresImport() &&
+ candidate.getCorrectionAsIdentifierInfo() == Typo &&
+ // FIXME: This probably does not return true when both
+ // NestedNameSpecifiers have the same textual representation.
+ candidate.getCorrectionSpecifier() == TypoNNS;
+ }
+
+ IdentifierInfo *Typo;
+ NestedNameSpecifier *TypoNNS;
+};
+
+/// @brief Simple template class for restricting typo correction candidates
+/// to ones having a single Decl* of the given type.
+template <class C>
+class DeclFilterCCC : public CorrectionCandidateCallback {
+public:
+ bool ValidateCandidate(const TypoCorrection &candidate) override {
+ return candidate.getCorrectionDeclAs<C>();
+ }
+};
+
+// @brief Callback class to limit the allowed keywords and to only accept typo
+// corrections that are keywords or whose decls refer to functions (or template
+// functions) that accept the given number of arguments.
+class FunctionCallFilterCCC : public CorrectionCandidateCallback {
+public:
+ FunctionCallFilterCCC(Sema &SemaRef, unsigned NumArgs,
+ bool HasExplicitTemplateArgs,
+ MemberExpr *ME = nullptr);
+
+ bool ValidateCandidate(const TypoCorrection &candidate) override;
+
+ private:
+ unsigned NumArgs;
+ bool HasExplicitTemplateArgs;
+ DeclContext *CurContext;
+ MemberExpr *MemberFn;
+};
+
+// @brief Callback class that effectively disabled typo correction
+class NoTypoCorrectionCCC : public CorrectionCandidateCallback {
+public:
+ NoTypoCorrectionCCC() {
+ WantTypeSpecifiers = false;
+ WantExpressionKeywords = false;
+ WantCXXNamedCasts = false;
+ WantFunctionLikeCasts = false;
+ WantRemainingKeywords = false;
+ }
+
+ bool ValidateCandidate(const TypoCorrection &candidate) override {
+ return false;
+ }
+};
+
+}
+
+#endif
diff --git a/contrib/llvm/tools/clang/include/clang/Sema/Weak.h b/contrib/llvm/tools/clang/include/clang/Sema/Weak.h
new file mode 100644
index 0000000..9c7212e
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Sema/Weak.h
@@ -0,0 +1,46 @@
+//===-- 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 WeakInfo class, which is used to store
+// information about the target of a #pragma weak directive.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_SEMA_WEAK_H
+#define LLVM_CLANG_SEMA_WEAK_H
+
+#include "clang/Basic/SourceLocation.h"
+
+namespace clang {
+
+class IdentifierInfo;
+
+/// \brief Captures information about a \#pragma weak directive.
+class WeakInfo {
+ IdentifierInfo *alias; // alias (optional)
+ SourceLocation loc; // for diagnostics
+ bool used; // identifier later declared?
+public:
+ WeakInfo()
+ : alias(nullptr), 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); }
+};
+
+} // end namespace clang
+
+#endif // LLVM_CLANG_SEMA_WEAK_H
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..16bda6e
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Serialization/ASTBitCodes.h
@@ -0,0 +1,1605 @@
+//===- 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_SERIALIZATION_ASTBITCODES_H
+#define LLVM_CLANG_SERIALIZATION_ASTBITCODES_H
+
+#include "clang/AST/DeclarationName.h"
+#include "clang/AST/Type.h"
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/Bitcode/BitCodes.h"
+#include "llvm/Support/DataTypes.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 = 6;
+
+ /// \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 an identifier in an AST file.
+ ///
+ /// The ID numbers of identifiers are consecutive (in order of discovery)
+ /// and start at 1. 0 is reserved for NULL.
+ typedef uint32_t IdentifierID;
+
+ /// \brief An ID number that refers to a declaration in an AST file.
+ ///
+ /// The ID numbers of declarations are consecutive (in order of
+ /// discovery), with values below NUM_PREDEF_DECL_IDS being reserved.
+ /// At the start of a chain of precompiled headers, declaration ID 1 is
+ /// used for the translation unit declaration.
+ typedef uint32_t DeclID;
+
+ // FIXME: Turn these into classes so we can have some type safety when
+ // we go from local ID to global and vice-versa.
+ typedef DeclID LocalDeclID;
+ typedef DeclID GlobalDeclID;
+
+ /// \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 {
+ if (Idx == uint32_t(-1))
+ return TypeID(-1);
+
+ return (Idx << Qualifiers::FastWidth) | FastQuals;
+ }
+ static TypeIdx fromTypeID(TypeID ID) {
+ if (ID == TypeID(-1))
+ return TypeIdx(-1);
+
+ 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 An ID number that refers to an identifier in an AST file.
+ typedef uint32_t IdentID;
+
+ /// \brief The number of predefined identifier IDs.
+ const unsigned int NUM_PREDEF_IDENT_IDS = 1;
+
+ /// \brief An ID number that refers to a macro in an AST file.
+ typedef uint32_t MacroID;
+
+ /// \brief A global ID number that refers to a macro in an AST file.
+ typedef uint32_t GlobalMacroID;
+
+ /// \brief A local to a module ID number that refers to a macro in an
+ /// AST file.
+ typedef uint32_t LocalMacroID;
+
+ /// \brief The number of predefined macro IDs.
+ const unsigned int NUM_PREDEF_MACRO_IDS = 1;
+
+ /// \brief An ID number that refers to an ObjC selector in an AST file.
+ typedef uint32_t SelectorID;
+
+ /// \brief The number of predefined selector IDs.
+ const unsigned int NUM_PREDEF_SELECTOR_IDS = 1;
+
+ /// \brief An ID number that refers to a set of CXXBaseSpecifiers in an
+ /// AST file.
+ typedef uint32_t CXXBaseSpecifiersID;
+
+ /// \brief An ID number that refers to a list of CXXCtorInitializers in an
+ /// AST file.
+ typedef uint32_t CXXCtorInitializersID;
+
+ /// \brief An ID number that refers to an entity in the detailed
+ /// preprocessing record.
+ typedef uint32_t PreprocessedEntityID;
+
+ /// \brief An ID number that refers to a submodule in a module file.
+ typedef uint32_t SubmoduleID;
+
+ /// \brief The number of predefined submodule IDs.
+ const unsigned int NUM_PREDEF_SUBMODULE_IDS = 1;
+
+ /// \brief Source range/offset of a preprocessed entity.
+ struct PPEntityOffset {
+ /// \brief Raw source location of beginning of range.
+ unsigned Begin;
+ /// \brief Raw source location of end of range.
+ unsigned End;
+ /// \brief Offset in the AST file.
+ uint32_t BitOffset;
+
+ PPEntityOffset(SourceRange R, uint32_t BitOffset)
+ : Begin(R.getBegin().getRawEncoding()),
+ End(R.getEnd().getRawEncoding()),
+ BitOffset(BitOffset) { }
+ };
+
+ /// \brief Source range/offset of a preprocessed entity.
+ struct DeclOffset {
+ /// \brief Raw source location.
+ unsigned Loc;
+ /// \brief Offset in the AST file.
+ uint32_t BitOffset;
+
+ DeclOffset() : Loc(0), BitOffset(0) { }
+ DeclOffset(SourceLocation Loc, uint32_t BitOffset)
+ : Loc(Loc.getRawEncoding()),
+ BitOffset(BitOffset) { }
+ void setLocation(SourceLocation L) {
+ Loc = L.getRawEncoding();
+ }
+ };
+
+ /// \brief The number of predefined preprocessed entity IDs.
+ const unsigned int NUM_PREDEF_PP_ENTITY_IDS = 1;
+
+ /// \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 the detailed preprocessing record.
+ PREPROCESSOR_DETAIL_BLOCK_ID,
+
+ /// \brief The block containing the submodule structure.
+ SUBMODULE_BLOCK_ID,
+
+ /// \brief The block containing comments.
+ COMMENTS_BLOCK_ID,
+
+ /// \brief The control block, which contains all of the
+ /// information that needs to be validated prior to committing
+ /// to loading the AST file.
+ CONTROL_BLOCK_ID,
+
+ /// \brief The block of input files, which were used as inputs
+ /// to create this AST file.
+ ///
+ /// This block is part of the control block.
+ INPUT_FILES_BLOCK_ID,
+
+ /// \brief The block of configuration options, used to check that
+ /// a module is being used in a configuration compatible with the
+ /// configuration in which it was built.
+ ///
+ /// This block is part of the control block.
+ OPTIONS_BLOCK_ID,
+
+ /// \brief A block containing a module file extension.
+ EXTENSION_BLOCK_ID,
+ };
+
+ /// \brief Record types that occur within the control block.
+ enum ControlRecordTypes {
+ /// \brief AST file metadata, including the AST file version number
+ /// and information about the compiler used to build this AST file.
+ METADATA = 1,
+
+ /// \brief Record code for the list of other AST files imported by
+ /// this AST file.
+ IMPORTS,
+
+ /// \brief Record code for the original file that was used to
+ /// generate the AST file, including both its file ID and its
+ /// name.
+ ORIGINAL_FILE,
+
+ /// \brief The directory that the PCH was originally created in.
+ ORIGINAL_PCH_DIR,
+
+ /// \brief Record code for file ID of the file or buffer that was used to
+ /// generate the AST file.
+ ORIGINAL_FILE_ID,
+
+ /// \brief Offsets into the input-files block where input files
+ /// reside.
+ INPUT_FILE_OFFSETS,
+
+ /// \brief Record code for the module name.
+ MODULE_NAME,
+
+ /// \brief Record code for the module map file that was used to build this
+ /// AST file.
+ MODULE_MAP_FILE,
+
+ /// \brief Record code for the signature that identifiers this AST file.
+ SIGNATURE,
+
+ /// \brief Record code for the module build directory.
+ MODULE_DIRECTORY,
+ };
+
+ /// \brief Record types that occur within the options block inside
+ /// the control block.
+ enum OptionsRecordTypes {
+ /// \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 = 1,
+
+ /// \brief Record code for the target options table.
+ TARGET_OPTIONS,
+
+ /// \brief Record code for the diagnostic options table.
+ DIAGNOSTIC_OPTIONS,
+
+ /// \brief Record code for the filesystem options table.
+ FILE_SYSTEM_OPTIONS,
+
+ /// \brief Record code for the headers search options table.
+ HEADER_SEARCH_OPTIONS,
+
+ /// \brief Record code for the preprocessor options table.
+ PREPROCESSOR_OPTIONS,
+ };
+
+ /// \brief Record code for extension blocks.
+ enum ExtensionBlockRecordTypes {
+ /// Metadata describing this particular extension.
+ EXTENSION_METADATA = 1,
+
+ /// The first record ID allocated to the extensions themselves.
+ FIRST_EXTENSION_RECORD_ID = 4
+ };
+
+ /// \brief Record types that occur within the input-files block
+ /// inside the control block.
+ enum InputFileRecordTypes {
+ /// \brief An input file.
+ INPUT_FILE = 1
+ };
+
+ /// \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 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 = 3,
+
+ /// \brief This is so that older clang versions, before the introduction
+ /// of the control block, can read and reject the newer PCH format.
+ /// *DON'T CHANGE THIS NUMBER*.
+ METADATA_OLD_FORMAT = 4,
+
+ /// \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 = 5,
+
+ /// \brief Record code for the array of eagerly deserialized decls.
+ ///
+ /// The AST file contains a list of all of the declarations that should be
+ /// eagerly deserialized present within the parsed headers, stored as an
+ /// array of declaration IDs. These declarations 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).
+ EAGERLY_DESERIALIZED_DECLS = 6,
+
+ /// \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 = 7,
+
+ /// \brief Record code for the extra statistics we gather while
+ /// generating an AST file.
+ STATISTICS = 8,
+
+ /// \brief Record code for the array of tentative definitions.
+ TENTATIVE_DEFINITIONS = 9,
+
+ // ID 10 used to be for a list of extern "C" declarations.
+
+ /// \brief Record code for the table of offsets into the
+ /// Objective-C method pool.
+ SELECTOR_OFFSETS = 11,
+
+ /// \brief Record code for the Objective-C method pool,
+ METHOD_POOL = 12,
+
+ /// \brief The value of the next __COUNTER__ to dispense.
+ /// [PP_COUNTER_VALUE, Val]
+ PP_COUNTER_VALUE = 13,
+
+ /// \brief Record code for the table of offsets into the block
+ /// of source-location information.
+ SOURCE_LOCATION_OFFSETS = 14,
+
+ /// \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 = 15,
+
+ /// \brief Record code for the set of ext_vector type names.
+ EXT_VECTOR_DECLS = 16,
+
+ /// \brief Record code for the array of unused file scoped decls.
+ UNUSED_FILESCOPED_DECLS = 17,
+
+ /// \brief Record code for the table of offsets to entries in the
+ /// preprocessing record.
+ PPD_ENTITIES_OFFSETS = 18,
+
+ /// \brief Record code for the array of VTable uses.
+ VTABLE_USES = 19,
+
+ // ID 20 used to be for a list of dynamic classes.
+
+ /// \brief Record code for referenced selector pool.
+ REFERENCED_SELECTOR_POOL = 21,
+
+ /// \brief Record code for an update to the TU's lexically contained
+ /// declarations.
+ TU_UPDATE_LEXICAL = 22,
+
+ // ID 23 used to be for a list of local redeclarations.
+
+ /// \brief Record code for declarations that Sema keeps references of.
+ SEMA_DECL_REFS = 24,
+
+ /// \brief Record code for weak undeclared identifiers.
+ WEAK_UNDECLARED_IDENTIFIERS = 25,
+
+ /// \brief Record code for pending implicit instantiations.
+ PENDING_IMPLICIT_INSTANTIATIONS = 26,
+
+ /// \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 = 27,
+
+ /// \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 = 28,
+
+ /// \brief Record for offsets of DECL_UPDATES records for declarations
+ /// that were modified after being deserialized and need updates.
+ DECL_UPDATE_OFFSETS = 29,
+
+ /// \brief Record of updates for a declaration that was modified after
+ /// being deserialized.
+ DECL_UPDATES = 30,
+
+ /// \brief Record code for the table of offsets to CXXBaseSpecifier
+ /// sets.
+ CXX_BASE_SPECIFIER_OFFSETS = 31,
+
+ /// \brief Record code for \#pragma diagnostic mappings.
+ DIAG_PRAGMA_MAPPINGS = 32,
+
+ /// \brief Record code for special CUDA declarations.
+ CUDA_SPECIAL_DECL_REFS = 33,
+
+ /// \brief Record code for header search information.
+ HEADER_SEARCH_TABLE = 34,
+
+ /// \brief Record code for floating point \#pragma options.
+ FP_PRAGMA_OPTIONS = 35,
+
+ /// \brief Record code for enabled OpenCL extensions.
+ OPENCL_EXTENSIONS = 36,
+
+ /// \brief The list of delegating constructor declarations.
+ DELEGATING_CTORS = 37,
+
+ /// \brief Record code for the set of known namespaces, which are used
+ /// for typo correction.
+ KNOWN_NAMESPACES = 38,
+
+ /// \brief Record code for the remapping information used to relate
+ /// loaded modules to the various offsets and IDs(e.g., source location
+ /// offests, declaration and type IDs) that are used in that module to
+ /// refer to other modules.
+ MODULE_OFFSET_MAP = 39,
+
+ /// \brief Record code for the source manager line table information,
+ /// which stores information about \#line directives.
+ SOURCE_MANAGER_LINE_TABLE = 40,
+
+ /// \brief Record code for map of Objective-C class definition IDs to the
+ /// ObjC categories in a module that are attached to that class.
+ OBJC_CATEGORIES_MAP = 41,
+
+ /// \brief Record code for a file sorted array of DeclIDs in a module.
+ FILE_SORTED_DECLS = 42,
+
+ /// \brief Record code for an array of all of the (sub)modules that were
+ /// imported by the AST file.
+ IMPORTED_MODULES = 43,
+
+ // ID 44 used to be a table of merged canonical declarations.
+ // ID 45 used to be a list of declaration IDs of local redeclarations.
+
+ /// \brief Record code for the array of Objective-C categories (including
+ /// extensions).
+ ///
+ /// This array can only be interpreted properly using the Objective-C
+ /// categories map.
+ OBJC_CATEGORIES = 46,
+
+ /// \brief Record code for the table of offsets of each macro ID.
+ ///
+ /// The offset table contains offsets into the blob stored in
+ /// the preprocessor block. Each offset points to the corresponding
+ /// macro definition.
+ MACRO_OFFSET = 47,
+
+ /// \brief A list of "interesting" identifiers. Only used in C++ (where we
+ /// don't normally do lookups into the serialized identifier table). These
+ /// are eagerly deserialized.
+ INTERESTING_IDENTIFIERS = 48,
+
+ /// \brief Record code for undefined but used functions and variables that
+ /// need a definition in this TU.
+ UNDEFINED_BUT_USED = 49,
+
+ /// \brief Record code for late parsed template functions.
+ LATE_PARSED_TEMPLATE = 50,
+
+ /// \brief Record code for \#pragma optimize options.
+ OPTIMIZE_PRAGMA_OPTIONS = 51,
+
+ /// \brief Record code for potentially unused local typedef names.
+ UNUSED_LOCAL_TYPEDEF_NAME_CANDIDATES = 52,
+
+ /// \brief Record code for the table of offsets to CXXCtorInitializers
+ /// lists.
+ CXX_CTOR_INITIALIZERS_OFFSETS = 53,
+
+ /// \brief Delete expressions that will be analyzed later.
+ DELETE_EXPRS_TO_ANALYZE = 54
+ };
+
+ /// \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 or a SM_SLOC_FILE_ENTRY with an
+ /// overridden buffer.
+ SM_SLOC_BUFFER_BLOB = 3,
+ /// \brief Describes a source location entry (SLocEntry) for a
+ /// macro expansion.
+ SM_SLOC_EXPANSION_ENTRY = 4
+ };
+
+ /// \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 The macro directives history for a particular identifier.
+ PP_MACRO_DIRECTIVE_HISTORY = 4,
+
+ /// \brief A macro directive exported by a module.
+ /// [PP_MODULE_MACRO, SubmoduleID, MacroID, (Overridden SubmoduleID)*]
+ PP_MODULE_MACRO = 5,
+ };
+
+ /// \brief Record types used within a preprocessor detail block.
+ enum PreprocessorDetailRecordTypes {
+ /// \brief Describes a macro expansion within the preprocessing record.
+ PPD_MACRO_EXPANSION = 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
+ };
+
+ /// \brief Record types used within a submodule description block.
+ enum SubmoduleRecordTypes {
+ /// \brief Metadata for submodules as a whole.
+ SUBMODULE_METADATA = 0,
+ /// \brief Defines the major attributes of a submodule, including its
+ /// name and parent.
+ SUBMODULE_DEFINITION = 1,
+ /// \brief Specifies the umbrella header used to create this module,
+ /// if any.
+ SUBMODULE_UMBRELLA_HEADER = 2,
+ /// \brief Specifies a header that falls into this (sub)module.
+ SUBMODULE_HEADER = 3,
+ /// \brief Specifies a top-level header that falls into this (sub)module.
+ SUBMODULE_TOPHEADER = 4,
+ /// \brief Specifies an umbrella directory.
+ SUBMODULE_UMBRELLA_DIR = 5,
+ /// \brief Specifies the submodules that are imported by this
+ /// submodule.
+ SUBMODULE_IMPORTS = 6,
+ /// \brief Specifies the submodules that are re-exported from this
+ /// submodule.
+ SUBMODULE_EXPORTS = 7,
+ /// \brief Specifies a required feature.
+ SUBMODULE_REQUIRES = 8,
+ /// \brief Specifies a header that has been explicitly excluded
+ /// from this submodule.
+ SUBMODULE_EXCLUDED_HEADER = 9,
+ /// \brief Specifies a library or framework to link against.
+ SUBMODULE_LINK_LIBRARY = 10,
+ /// \brief Specifies a configuration macro for this module.
+ SUBMODULE_CONFIG_MACRO = 11,
+ /// \brief Specifies a conflict with another module.
+ SUBMODULE_CONFLICT = 12,
+ /// \brief Specifies a header that is private to this submodule.
+ SUBMODULE_PRIVATE_HEADER = 13,
+ /// \brief Specifies a header that is part of the module but must be
+ /// textually included.
+ SUBMODULE_TEXTUAL_HEADER = 14,
+ /// \brief Specifies a header that is private to this submodule but
+ /// must be textually included.
+ SUBMODULE_PRIVATE_TEXTUAL_HEADER = 15,
+ };
+
+ /// \brief Record types used within a comments block.
+ enum CommentRecordTypes {
+ COMMENTS_RAW_COMMENT = 0
+ };
+
+ /// \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 'unknown any' placeholder type.
+ PREDEF_TYPE_UNKNOWN_ANY = 29,
+ /// \brief The placeholder type for bound member functions.
+ PREDEF_TYPE_BOUND_MEMBER = 30,
+ /// \brief The "auto" deduction type.
+ PREDEF_TYPE_AUTO_DEDUCT = 31,
+ /// \brief The "auto &&" deduction type.
+ PREDEF_TYPE_AUTO_RREF_DEDUCT = 32,
+ /// \brief The OpenCL 'half' / ARM NEON __fp16 type.
+ PREDEF_TYPE_HALF_ID = 33,
+ /// \brief ARC's unbridged-cast placeholder type.
+ PREDEF_TYPE_ARC_UNBRIDGED_CAST = 34,
+ /// \brief The pseudo-object placeholder type.
+ PREDEF_TYPE_PSEUDO_OBJECT = 35,
+ /// \brief The placeholder type for builtin functions.
+ PREDEF_TYPE_BUILTIN_FN = 36,
+ /// \brief OpenCL 1d image type.
+ PREDEF_TYPE_IMAGE1D_ID = 37,
+ /// \brief OpenCL 1d image array type.
+ PREDEF_TYPE_IMAGE1D_ARR_ID = 38,
+ /// \brief OpenCL 1d image buffer type.
+ PREDEF_TYPE_IMAGE1D_BUFF_ID = 39,
+ /// \brief OpenCL 2d image type.
+ PREDEF_TYPE_IMAGE2D_ID = 40,
+ /// \brief OpenCL 2d image array type.
+ PREDEF_TYPE_IMAGE2D_ARR_ID = 41,
+ /// \brief OpenCL 2d image depth type.
+ PREDEF_TYPE_IMAGE2D_DEP_ID = 42,
+ /// \brief OpenCL 2d image array depth type.
+ PREDEF_TYPE_IMAGE2D_ARR_DEP_ID = 43,
+ /// \brief OpenCL 2d image MSAA type.
+ PREDEF_TYPE_IMAGE2D_MSAA_ID = 44,
+ /// \brief OpenCL 2d image array MSAA type.
+ PREDEF_TYPE_IMAGE2D_ARR_MSAA_ID = 45,
+ /// \brief OpenCL 2d image MSAA depth type.
+ PREDEF_TYPE_IMAGE2D_MSAA_DEP_ID = 46,
+ /// \brief OpenCL 2d image array MSAA depth type.
+ PREDEF_TYPE_IMAGE2D_ARR_MSAA_DEPTH_ID = 47,
+ /// \brief OpenCL 3d image type.
+ PREDEF_TYPE_IMAGE3D_ID = 48,
+ /// \brief OpenCL event type.
+ PREDEF_TYPE_EVENT_ID = 49,
+ /// \brief OpenCL clk event type.
+ PREDEF_TYPE_CLK_EVENT_ID = 50,
+ /// \brief OpenCL sampler type.
+ PREDEF_TYPE_SAMPLER_ID = 51,
+ /// \brief OpenCL queue type.
+ PREDEF_TYPE_QUEUE_ID = 52,
+ /// \brief OpenCL ndrange type.
+ PREDEF_TYPE_NDRANGE_ID = 53,
+ /// \brief OpenCL reserve_id type.
+ PREDEF_TYPE_RESERVE_ID_ID = 54,
+ /// \brief The placeholder type for OpenMP array section.
+ PREDEF_TYPE_OMP_ARRAY_SECTION = 55
+ };
+
+ /// \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 A UnaryTransformType record.
+ TYPE_UNARY_TRANSFORM = 39,
+ /// \brief An AtomicType record.
+ TYPE_ATOMIC = 40,
+ /// \brief A DecayedType record.
+ TYPE_DECAYED = 41,
+ /// \brief An AdjustedType record.
+ TYPE_ADJUSTED = 42
+ };
+
+ /// \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 CFConstantString type
+ SPECIAL_TYPE_CF_CONSTANT_STRING = 0,
+ /// \brief C FILE typedef type
+ SPECIAL_TYPE_FILE = 1,
+ /// \brief C jmp_buf typedef type
+ SPECIAL_TYPE_JMP_BUF = 2,
+ /// \brief C sigjmp_buf typedef type
+ SPECIAL_TYPE_SIGJMP_BUF = 3,
+ /// \brief Objective-C "id" redefinition type
+ SPECIAL_TYPE_OBJC_ID_REDEFINITION = 4,
+ /// \brief Objective-C "Class" redefinition type
+ SPECIAL_TYPE_OBJC_CLASS_REDEFINITION = 5,
+ /// \brief Objective-C "SEL" redefinition type
+ SPECIAL_TYPE_OBJC_SEL_REDEFINITION = 6,
+ /// \brief C ucontext_t typedef type
+ SPECIAL_TYPE_UCONTEXT_T = 7
+ };
+
+ /// \brief The number of special type IDs.
+ const unsigned NumSpecialTypeIDs = 8;
+
+ /// \brief Predefined declaration IDs.
+ ///
+ /// These declaration IDs correspond to predefined declarations in the AST
+ /// context, such as the NULL declaration ID. Such declarations are never
+ /// actually serialized, since they will be built by the AST context when
+ /// it is created.
+ enum PredefinedDeclIDs {
+ /// \brief The NULL declaration.
+ PREDEF_DECL_NULL_ID = 0,
+
+ /// \brief The translation unit.
+ PREDEF_DECL_TRANSLATION_UNIT_ID = 1,
+
+ /// \brief The Objective-C 'id' type.
+ PREDEF_DECL_OBJC_ID_ID = 2,
+
+ /// \brief The Objective-C 'SEL' type.
+ PREDEF_DECL_OBJC_SEL_ID = 3,
+
+ /// \brief The Objective-C 'Class' type.
+ PREDEF_DECL_OBJC_CLASS_ID = 4,
+
+ /// \brief The Objective-C 'Protocol' type.
+ PREDEF_DECL_OBJC_PROTOCOL_ID = 5,
+
+ /// \brief The signed 128-bit integer type.
+ PREDEF_DECL_INT_128_ID = 6,
+
+ /// \brief The unsigned 128-bit integer type.
+ PREDEF_DECL_UNSIGNED_INT_128_ID = 7,
+
+ /// \brief The internal 'instancetype' typedef.
+ PREDEF_DECL_OBJC_INSTANCETYPE_ID = 8,
+
+ /// \brief The internal '__builtin_va_list' typedef.
+ PREDEF_DECL_BUILTIN_VA_LIST_ID = 9,
+
+ /// \brief The internal '__va_list_tag' struct, if any.
+ PREDEF_DECL_VA_LIST_TAG = 10,
+
+ /// \brief The internal '__builtin_ms_va_list' typedef.
+ PREDEF_DECL_BUILTIN_MS_VA_LIST_ID = 11,
+
+ /// \brief The extern "C" context.
+ PREDEF_DECL_EXTERN_C_CONTEXT_ID = 12,
+
+ /// \brief The internal '__make_integer_seq' template.
+ PREDEF_DECL_MAKE_INTEGER_SEQ_ID = 13,
+ };
+
+ /// \brief The number of declaration IDs that are predefined.
+ ///
+ /// For more information about predefined declarations, see the
+ /// \c PredefinedDeclIDs type and the PREDEF_DECL_*_ID constants.
+ const unsigned int NUM_PREDEF_DECL_IDS = 14;
+
+ /// \brief Record code for a list of local redeclarations of a declaration.
+ const unsigned int LOCAL_REDECLARATIONS = 50;
+
+ /// \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 TypedefDecl record.
+ DECL_TYPEDEF = 51,
+ /// \brief A TypeAliasDecl record.
+ DECL_TYPEALIAS,
+ /// \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 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 MSPropertyDecl record.
+ DECL_MS_PROPERTY,
+ /// \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 CapturedDecl record.
+ DECL_CAPTURED,
+ /// \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() and 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 VarTemplateDecl record.
+ DECL_VAR_TEMPLATE,
+ /// \brief A VarTemplateSpecializationDecl record.
+ DECL_VAR_TEMPLATE_SPECIALIZATION,
+ /// \brief A VarTemplatePartialSpecializationDecl record.
+ DECL_VAR_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 TypeAliasTemplateDecl record.
+ DECL_TYPE_ALIAS_TEMPLATE,
+ /// \brief A StaticAssertDecl record.
+ DECL_STATIC_ASSERT,
+ /// \brief A record containing CXXBaseSpecifiers.
+ DECL_CXX_BASE_SPECIFIERS,
+ /// \brief A record containing CXXCtorInitializers.
+ DECL_CXX_CTOR_INITIALIZERS,
+ /// \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 A TemplateTemplateParmDecl record that stores an expanded
+ /// template template parameter pack.
+ DECL_EXPANDED_TEMPLATE_TEMPLATE_PARM_PACK,
+ /// \brief A ClassScopeFunctionSpecializationDecl record a class scope
+ /// function specialization. (Microsoft extension).
+ DECL_CLASS_SCOPE_FUNCTION_SPECIALIZATION,
+ /// \brief An ImportDecl recording a module import.
+ DECL_IMPORT,
+ /// \brief An OMPThreadPrivateDecl record.
+ DECL_OMP_THREADPRIVATE,
+ /// \brief An EmptyDecl record.
+ DECL_EMPTY,
+ /// \brief An ObjCTypeParamDecl record.
+ DECL_OBJC_TYPE_PARAM,
+ };
+
+ /// \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 128. 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 = 128,
+ /// \brief A NULL expression.
+ STMT_NULL_PTR,
+ /// \brief A reference to a previously [de]serialized Stmt record.
+ STMT_REF_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 AttributedStmt record.
+ STMT_ATTRIBUTED,
+ /// \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 A CapturedStmt record.
+ STMT_CAPTURED,
+ /// \brief A GCC-style AsmStmt record.
+ STMT_GCCASM,
+ /// \brief A MS-style AsmStmt record.
+ STMT_MSASM,
+ /// \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 A DesignatedInitUpdateExpr record.
+ EXPR_DESIGNATED_INIT_UPDATE,
+ /// \brief An ImplicitValueInitExpr record.
+ EXPR_IMPLICIT_VALUE_INIT,
+ /// \brief An NoInitExpr record.
+ EXPR_NO_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 A ConvertVectorExpr record.
+ EXPR_CONVERT_VECTOR,
+ /// \brief BlockExpr
+ EXPR_BLOCK,
+ /// \brief A GenericSelectionExpr record.
+ EXPR_GENERIC_SELECTION,
+ /// \brief A PseudoObjectExpr record.
+ EXPR_PSEUDO_OBJECT,
+ /// \brief An AtomicExpr record.
+ EXPR_ATOMIC,
+
+ // Objective-C
+
+ /// \brief An ObjCStringLiteral record.
+ EXPR_OBJC_STRING_LITERAL,
+
+ EXPR_OBJC_BOXED_EXPRESSION,
+ EXPR_OBJC_ARRAY_LITERAL,
+ EXPR_OBJC_DICTIONARY_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 An ObjCSubscriptRefExpr record.
+ EXPR_OBJC_SUBSCRIPT_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 ObjCIndirectCopyRestoreExpr record.
+ EXPR_OBJC_INDIRECT_COPY_RESTORE,
+
+ /// \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,
+ /// \brief An ObjCAutoreleasePoolStmt record.
+ STMT_OBJC_AUTORELEASE_POOL,
+ /// \brief A ObjCBoolLiteralExpr record.
+ EXPR_OBJC_BOOL_LITERAL,
+
+ // C++
+
+ /// \brief A CXXCatchStmt record.
+ STMT_CXX_CATCH,
+ /// \brief A CXXTryStmt record.
+ STMT_CXX_TRY,
+ /// \brief A CXXForRangeStmt record.
+ STMT_CXX_FOR_RANGE,
+
+ /// \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 UserDefinedLiteral record.
+ EXPR_USER_DEFINED_LITERAL,
+ /// \brief A CXXStdInitializerListExpr record.
+ EXPR_CXX_STD_INITIALIZER_LIST,
+ /// \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_THIS, // CXXThisExpr
+ EXPR_CXX_THROW, // CXXThrowExpr
+ EXPR_CXX_DEFAULT_ARG, // CXXDefaultArgExpr
+ EXPR_CXX_DEFAULT_INIT, // CXXDefaultInitExpr
+ 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_EXPRESSION_TRAIT, // ExpressionTraitExpr
+ EXPR_CXX_NOEXCEPT, // CXXNoexceptExpr
+
+ EXPR_OPAQUE_VALUE, // OpaqueValueExpr
+ EXPR_BINARY_CONDITIONAL_OPERATOR, // BinaryConditionalOperator
+ EXPR_TYPE_TRAIT, // TypeTraitExpr
+ EXPR_ARRAY_TYPE_TRAIT, // ArrayTypeTraitIntExpr
+
+ EXPR_PACK_EXPANSION, // PackExpansionExpr
+ EXPR_SIZEOF_PACK, // SizeOfPackExpr
+ EXPR_SUBST_NON_TYPE_TEMPLATE_PARM, // SubstNonTypeTemplateParmExpr
+ EXPR_SUBST_NON_TYPE_TEMPLATE_PARM_PACK,// SubstNonTypeTemplateParmPackExpr
+ EXPR_FUNCTION_PARM_PACK, // FunctionParmPackExpr
+ EXPR_MATERIALIZE_TEMPORARY, // MaterializeTemporaryExpr
+ EXPR_CXX_FOLD, // CXXFoldExpr
+
+ // CUDA
+ EXPR_CUDA_KERNEL_CALL, // CUDAKernelCallExpr
+
+ // OpenCL
+ EXPR_ASTYPE, // AsTypeExpr
+
+ // Microsoft
+ EXPR_CXX_PROPERTY_REF_EXPR, // MSPropertyRefExpr
+ EXPR_CXX_PROPERTY_SUBSCRIPT_EXPR, // MSPropertySubscriptExpr
+ EXPR_CXX_UUIDOF_EXPR, // CXXUuidofExpr (of expr).
+ EXPR_CXX_UUIDOF_TYPE, // CXXUuidofExpr (of type).
+ STMT_SEH_LEAVE, // SEHLeaveStmt
+ STMT_SEH_EXCEPT, // SEHExceptStmt
+ STMT_SEH_FINALLY, // SEHFinallyStmt
+ STMT_SEH_TRY, // SEHTryStmt
+
+ // OpenMP directives
+ STMT_OMP_PARALLEL_DIRECTIVE,
+ STMT_OMP_SIMD_DIRECTIVE,
+ STMT_OMP_FOR_DIRECTIVE,
+ STMT_OMP_FOR_SIMD_DIRECTIVE,
+ STMT_OMP_SECTIONS_DIRECTIVE,
+ STMT_OMP_SECTION_DIRECTIVE,
+ STMT_OMP_SINGLE_DIRECTIVE,
+ STMT_OMP_MASTER_DIRECTIVE,
+ STMT_OMP_CRITICAL_DIRECTIVE,
+ STMT_OMP_PARALLEL_FOR_DIRECTIVE,
+ STMT_OMP_PARALLEL_FOR_SIMD_DIRECTIVE,
+ STMT_OMP_PARALLEL_SECTIONS_DIRECTIVE,
+ STMT_OMP_TASK_DIRECTIVE,
+ STMT_OMP_TASKYIELD_DIRECTIVE,
+ STMT_OMP_BARRIER_DIRECTIVE,
+ STMT_OMP_TASKWAIT_DIRECTIVE,
+ STMT_OMP_FLUSH_DIRECTIVE,
+ STMT_OMP_ORDERED_DIRECTIVE,
+ STMT_OMP_ATOMIC_DIRECTIVE,
+ STMT_OMP_TARGET_DIRECTIVE,
+ STMT_OMP_TARGET_DATA_DIRECTIVE,
+ STMT_OMP_TEAMS_DIRECTIVE,
+ STMT_OMP_TASKGROUP_DIRECTIVE,
+ STMT_OMP_CANCELLATION_POINT_DIRECTIVE,
+ STMT_OMP_CANCEL_DIRECTIVE,
+ STMT_OMP_TASKLOOP_DIRECTIVE,
+ STMT_OMP_TASKLOOP_SIMD_DIRECTIVE,
+ STMT_OMP_DISTRIBUTE_DIRECTIVE,
+ EXPR_OMP_ARRAY_SECTION,
+
+ // ARC
+ EXPR_OBJC_BRIDGED_CAST, // ObjCBridgedCastExpr
+
+ STMT_MS_DEPENDENT_EXISTS, // MSDependentExistsStmt
+ EXPR_LAMBDA // LambdaExpr
+ };
+
+ /// \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
+ };
+
+ /// \brief The different kinds of data that can occur in a
+ /// CtorInitializer.
+ enum CtorInitializerType {
+ CTOR_INITIALIZER_BASE,
+ CTOR_INITIALIZER_DELEGATING,
+ CTOR_INITIALIZER_MEMBER,
+ CTOR_INITIALIZER_INDIRECT_MEMBER
+ };
+
+ /// \brief Describes the redeclarations of a declaration.
+ struct LocalRedeclarationsInfo {
+ DeclID FirstID; // The ID of the first declaration
+ unsigned Offset; // Offset into the array of redeclaration chains.
+
+ friend bool operator<(const LocalRedeclarationsInfo &X,
+ const LocalRedeclarationsInfo &Y) {
+ return X.FirstID < Y.FirstID;
+ }
+
+ friend bool operator>(const LocalRedeclarationsInfo &X,
+ const LocalRedeclarationsInfo &Y) {
+ return X.FirstID > Y.FirstID;
+ }
+
+ friend bool operator<=(const LocalRedeclarationsInfo &X,
+ const LocalRedeclarationsInfo &Y) {
+ return X.FirstID <= Y.FirstID;
+ }
+
+ friend bool operator>=(const LocalRedeclarationsInfo &X,
+ const LocalRedeclarationsInfo &Y) {
+ return X.FirstID >= Y.FirstID;
+ }
+ };
+
+ /// \brief Describes the categories of an Objective-C class.
+ struct ObjCCategoriesInfo {
+ DeclID DefinitionID; // The ID of the definition
+ unsigned Offset; // Offset into the array of category lists.
+
+ friend bool operator<(const ObjCCategoriesInfo &X,
+ const ObjCCategoriesInfo &Y) {
+ return X.DefinitionID < Y.DefinitionID;
+ }
+
+ friend bool operator>(const ObjCCategoriesInfo &X,
+ const ObjCCategoriesInfo &Y) {
+ return X.DefinitionID > Y.DefinitionID;
+ }
+
+ friend bool operator<=(const ObjCCategoriesInfo &X,
+ const ObjCCategoriesInfo &Y) {
+ return X.DefinitionID <= Y.DefinitionID;
+ }
+
+ friend bool operator>=(const ObjCCategoriesInfo &X,
+ const ObjCCategoriesInfo &Y) {
+ return X.DefinitionID >= Y.DefinitionID;
+ }
+ };
+
+ /// \brief A key used when looking up entities by \ref DeclarationName.
+ ///
+ /// Different \ref DeclarationNames are mapped to different keys, but the
+ /// same key can occasionally represent multiple names (for names that
+ /// contain types, in particular).
+ class DeclarationNameKey {
+ typedef unsigned NameKind;
+
+ NameKind Kind;
+ uint64_t Data;
+
+ public:
+ DeclarationNameKey() : Kind(), Data() {}
+ DeclarationNameKey(DeclarationName Name);
+
+ DeclarationNameKey(NameKind Kind, uint64_t Data)
+ : Kind(Kind), Data(Data) {}
+
+ NameKind getKind() const { return Kind; }
+
+ IdentifierInfo *getIdentifier() const {
+ assert(Kind == DeclarationName::Identifier ||
+ Kind == DeclarationName::CXXLiteralOperatorName);
+ return (IdentifierInfo *)Data;
+ }
+ Selector getSelector() const {
+ assert(Kind == DeclarationName::ObjCZeroArgSelector ||
+ Kind == DeclarationName::ObjCOneArgSelector ||
+ Kind == DeclarationName::ObjCMultiArgSelector);
+ return Selector(Data);
+ }
+ OverloadedOperatorKind getOperatorKind() const {
+ assert(Kind == DeclarationName::CXXOperatorName);
+ return (OverloadedOperatorKind)Data;
+ }
+
+ /// Compute a fingerprint of this key for use in on-disk hash table.
+ unsigned getHash() const;
+
+ friend bool operator==(const DeclarationNameKey &A,
+ const DeclarationNameKey &B) {
+ return A.Kind == B.Kind && A.Data == B.Data;
+ }
+ };
+
+ /// @}
+ }
+} // end namespace clang
+
+namespace llvm {
+ template <> struct DenseMapInfo<clang::serialization::DeclarationNameKey> {
+ static clang::serialization::DeclarationNameKey getEmptyKey() {
+ return clang::serialization::DeclarationNameKey(-1, 1);
+ }
+ static clang::serialization::DeclarationNameKey getTombstoneKey() {
+ return clang::serialization::DeclarationNameKey(-1, 2);
+ }
+ static unsigned
+ getHashValue(const clang::serialization::DeclarationNameKey &Key) {
+ return Key.getHash();
+ }
+ static bool isEqual(const clang::serialization::DeclarationNameKey &L,
+ const clang::serialization::DeclarationNameKey &R) {
+ return L == R;
+ }
+ };
+}
+
+#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..4b10c39
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Serialization/ASTDeserializationListener.h
@@ -0,0 +1,58 @@
+//===- 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_SERIALIZATION_ASTDESERIALIZATIONLISTENER_H
+#define LLVM_CLANG_SERIALIZATION_ASTDESERIALIZATIONLISTENER_H
+
+#include "clang/Basic/IdentifierTable.h"
+#include "clang/Serialization/ASTBitCodes.h"
+
+namespace clang {
+
+class Decl;
+class ASTReader;
+class QualType;
+class MacroDefinitionRecord;
+class MacroInfo;
+class Module;
+
+class ASTDeserializationListener {
+public:
+ virtual ~ASTDeserializationListener();
+
+ /// \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 macro was read from the AST file.
+ virtual void MacroRead(serialization::MacroID ID, MacroInfo *MI) { }
+ /// \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::PreprocessedEntityID,
+ MacroDefinitionRecord *MD) {}
+ /// \brief A module definition was read from the AST file.
+ virtual void ModuleRead(serialization::SubmoduleID ID, Module *Mod) {}
+};
+}
+
+#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..588a6a9
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Serialization/ASTReader.h
@@ -0,0 +1,2141 @@
+//===--- 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_SERIALIZATION_ASTREADER_H
+#define LLVM_CLANG_SERIALIZATION_ASTREADER_H
+
+#include "clang/AST/DeclObjC.h"
+#include "clang/AST/DeclarationName.h"
+#include "clang/AST/TemplateBase.h"
+#include "clang/Basic/Diagnostic.h"
+#include "clang/Basic/FileManager.h"
+#include "clang/Basic/FileSystemOptions.h"
+#include "clang/Basic/IdentifierTable.h"
+#include "clang/Basic/SourceManager.h"
+#include "clang/Basic/Version.h"
+#include "clang/Lex/ExternalPreprocessorSource.h"
+#include "clang/Lex/HeaderSearch.h"
+#include "clang/Lex/PreprocessingRecord.h"
+#include "clang/Sema/ExternalSemaSource.h"
+#include "clang/Serialization/ASTBitCodes.h"
+#include "clang/Serialization/ContinuousRangeMap.h"
+#include "clang/Serialization/Module.h"
+#include "clang/Serialization/ModuleFileExtension.h"
+#include "clang/Serialization/ModuleManager.h"
+#include "llvm/ADT/APFloat.h"
+#include "llvm/ADT/APInt.h"
+#include "llvm/ADT/APSInt.h"
+#include "llvm/ADT/MapVector.h"
+#include "llvm/ADT/SmallPtrSet.h"
+#include "llvm/ADT/SmallSet.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/StringMap.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/ADT/TinyPtrVector.h"
+#include "llvm/Bitcode/BitstreamReader.h"
+#include "llvm/Support/DataTypes.h"
+#include "llvm/Support/Timer.h"
+#include <deque>
+#include <map>
+#include <memory>
+#include <string>
+#include <utility>
+#include <vector>
+
+namespace llvm {
+ class MemoryBuffer;
+}
+
+namespace clang {
+
+class AddrLabelExpr;
+class ASTConsumer;
+class ASTContext;
+class ASTIdentifierIterator;
+class ASTUnit; // FIXME: Layering violation and egregious hack.
+class Attr;
+class Decl;
+class DeclContext;
+class DefMacroDirective;
+class DiagnosticOptions;
+class NestedNameSpecifier;
+class CXXBaseSpecifier;
+class CXXConstructorDecl;
+class CXXCtorInitializer;
+class GlobalModuleIndex;
+class GotoStmt;
+class MacroDefinition;
+class MacroDirective;
+class ModuleMacro;
+class NamedDecl;
+class OpaqueValueExpr;
+class Preprocessor;
+class PreprocessorOptions;
+class Sema;
+class SwitchCase;
+class ASTDeserializationListener;
+class ASTWriter;
+class ASTReader;
+class ASTDeclReader;
+class ASTStmtReader;
+class TypeLocReader;
+struct HeaderFileInfo;
+class VersionTuple;
+class TargetOptions;
+class LazyASTUnresolvedSet;
+
+/// \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 full Clang version information.
+ ///
+ /// \returns true to indicate that the version is invalid. Subclasses should
+ /// generally defer to this implementation.
+ virtual bool ReadFullVersionInformation(StringRef FullVersion) {
+ return FullVersion != getClangFullRepositoryVersion();
+ }
+
+ virtual void ReadModuleName(StringRef ModuleName) {}
+ virtual void ReadModuleMapFile(StringRef ModuleMapPath) {}
+
+ /// \brief Receives the language options.
+ ///
+ /// \returns true to indicate the options are invalid or false otherwise.
+ virtual bool ReadLanguageOptions(const LangOptions &LangOpts,
+ bool Complain,
+ bool AllowCompatibleDifferences) {
+ return false;
+ }
+
+ /// \brief Receives the target options.
+ ///
+ /// \returns true to indicate the target options are invalid, or false
+ /// otherwise.
+ virtual bool ReadTargetOptions(const TargetOptions &TargetOpts, bool Complain,
+ bool AllowCompatibleDifferences) {
+ return false;
+ }
+
+ /// \brief Receives the diagnostic options.
+ ///
+ /// \returns true to indicate the diagnostic options are invalid, or false
+ /// otherwise.
+ virtual bool
+ ReadDiagnosticOptions(IntrusiveRefCntPtr<DiagnosticOptions> DiagOpts,
+ bool Complain) {
+ return false;
+ }
+
+ /// \brief Receives the file system options.
+ ///
+ /// \returns true to indicate the file system options are invalid, or false
+ /// otherwise.
+ virtual bool ReadFileSystemOptions(const FileSystemOptions &FSOpts,
+ bool Complain) {
+ return false;
+ }
+
+ /// \brief Receives the header search options.
+ ///
+ /// \returns true to indicate the header search options are invalid, or false
+ /// otherwise.
+ virtual bool ReadHeaderSearchOptions(const HeaderSearchOptions &HSOpts,
+ StringRef SpecificModuleCachePath,
+ bool Complain) {
+ return false;
+ }
+
+ /// \brief Receives the preprocessor options.
+ ///
+ /// \param SuggestedPredefines Can be filled in with the set of predefines
+ /// that are suggested by the preprocessor options. Typically only used when
+ /// loading a precompiled header.
+ ///
+ /// \returns true to indicate the preprocessor options are invalid, or false
+ /// otherwise.
+ virtual bool ReadPreprocessorOptions(const PreprocessorOptions &PPOpts,
+ bool Complain,
+ std::string &SuggestedPredefines) {
+ return false;
+ }
+
+ /// \brief Receives __COUNTER__ value.
+ virtual void ReadCounter(const serialization::ModuleFile &M,
+ unsigned Value) {}
+
+ /// This is called for each AST file loaded.
+ virtual void visitModuleFile(StringRef Filename,
+ serialization::ModuleKind Kind) {}
+
+ /// \brief Returns true if this \c ASTReaderListener wants to receive the
+ /// input files of the AST file via \c visitInputFile, false otherwise.
+ virtual bool needsInputFileVisitation() { return false; }
+ /// \brief Returns true if this \c ASTReaderListener wants to receive the
+ /// system input files of the AST file via \c visitInputFile, false otherwise.
+ virtual bool needsSystemInputFileVisitation() { return false; }
+ /// \brief if \c needsInputFileVisitation returns true, this is called for
+ /// each non-system input file of the AST File. If
+ /// \c needsSystemInputFileVisitation is true, then it is called for all
+ /// system input files as well.
+ ///
+ /// \returns true to continue receiving the next input file, false to stop.
+ virtual bool visitInputFile(StringRef Filename, bool isSystem,
+ bool isOverridden, bool isExplicitModule) {
+ return true;
+ }
+
+ /// \brief Returns true if this \c ASTReaderListener wants to receive the
+ /// imports of the AST file via \c visitImport, false otherwise.
+ virtual bool needsImportVisitation() const { return false; }
+ /// \brief If needsImportVisitation returns \c true, this is called for each
+ /// AST file imported by this AST file.
+ virtual void visitImport(StringRef Filename) {}
+
+ /// Indicates that a particular module file extension has been read.
+ virtual void readModuleFileExtension(
+ const ModuleFileExtensionMetadata &Metadata) {}
+};
+
+/// \brief Simple wrapper class for chaining listeners.
+class ChainedASTReaderListener : public ASTReaderListener {
+ std::unique_ptr<ASTReaderListener> First;
+ std::unique_ptr<ASTReaderListener> Second;
+
+public:
+ /// Takes ownership of \p First and \p Second.
+ ChainedASTReaderListener(std::unique_ptr<ASTReaderListener> First,
+ std::unique_ptr<ASTReaderListener> Second)
+ : First(std::move(First)), Second(std::move(Second)) {}
+
+ std::unique_ptr<ASTReaderListener> takeFirst() { return std::move(First); }
+ std::unique_ptr<ASTReaderListener> takeSecond() { return std::move(Second); }
+
+ bool ReadFullVersionInformation(StringRef FullVersion) override;
+ void ReadModuleName(StringRef ModuleName) override;
+ void ReadModuleMapFile(StringRef ModuleMapPath) override;
+ bool ReadLanguageOptions(const LangOptions &LangOpts, bool Complain,
+ bool AllowCompatibleDifferences) override;
+ bool ReadTargetOptions(const TargetOptions &TargetOpts, bool Complain,
+ bool AllowCompatibleDifferences) override;
+ bool ReadDiagnosticOptions(IntrusiveRefCntPtr<DiagnosticOptions> DiagOpts,
+ bool Complain) override;
+ bool ReadFileSystemOptions(const FileSystemOptions &FSOpts,
+ bool Complain) override;
+
+ bool ReadHeaderSearchOptions(const HeaderSearchOptions &HSOpts,
+ StringRef SpecificModuleCachePath,
+ bool Complain) override;
+ bool ReadPreprocessorOptions(const PreprocessorOptions &PPOpts,
+ bool Complain,
+ std::string &SuggestedPredefines) override;
+
+ void ReadCounter(const serialization::ModuleFile &M, unsigned Value) override;
+ bool needsInputFileVisitation() override;
+ bool needsSystemInputFileVisitation() override;
+ void visitModuleFile(StringRef Filename,
+ serialization::ModuleKind Kind) override;
+ bool visitInputFile(StringRef Filename, bool isSystem,
+ bool isOverridden, bool isExplicitModule) override;
+ void readModuleFileExtension(
+ const ModuleFileExtensionMetadata &Metadata) override;
+};
+
+/// \brief ASTReaderListener implementation to validate the information of
+/// the PCH file against an initialized Preprocessor.
+class PCHValidator : public ASTReaderListener {
+ Preprocessor &PP;
+ ASTReader &Reader;
+
+public:
+ PCHValidator(Preprocessor &PP, ASTReader &Reader)
+ : PP(PP), Reader(Reader) {}
+
+ bool ReadLanguageOptions(const LangOptions &LangOpts, bool Complain,
+ bool AllowCompatibleDifferences) override;
+ bool ReadTargetOptions(const TargetOptions &TargetOpts, bool Complain,
+ bool AllowCompatibleDifferences) override;
+ bool ReadDiagnosticOptions(IntrusiveRefCntPtr<DiagnosticOptions> DiagOpts,
+ bool Complain) override;
+ bool ReadPreprocessorOptions(const PreprocessorOptions &PPOpts, bool Complain,
+ std::string &SuggestedPredefines) override;
+ bool ReadHeaderSearchOptions(const HeaderSearchOptions &HSOpts,
+ StringRef SpecificModuleCachePath,
+ bool Complain) override;
+ void ReadCounter(const serialization::ModuleFile &M, unsigned Value) override;
+
+private:
+ void Error(const char *Msg);
+};
+
+namespace serialization {
+
+class ReadMethodPoolVisitor;
+
+namespace reader {
+ class ASTIdentifierLookupTrait;
+ /// \brief The on-disk hash table(s) used for DeclContext name lookup.
+ struct DeclContextLookupTable;
+}
+
+} // end namespace serialization
+
+/// \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 ExternalSLocEntrySource
+{
+public:
+ typedef SmallVector<uint64_t, 64> RecordData;
+ typedef SmallVectorImpl<uint64_t> RecordDataImpl;
+
+ /// \brief The result of reading the control block of an AST file, which
+ /// can fail for various reasons.
+ enum ASTReadResult {
+ /// \brief The control block was read successfully. Aside from failures,
+ /// the AST file is safe to read into the current context.
+ Success,
+ /// \brief The AST file itself appears corrupted.
+ Failure,
+ /// \brief The AST file was missing.
+ Missing,
+ /// \brief The AST file is out-of-date relative to its input files,
+ /// and needs to be regenerated.
+ OutOfDate,
+ /// \brief The AST file was written by a different version of Clang.
+ VersionMismatch,
+ /// \brief The AST file was writtten with a different language/target
+ /// configuration.
+ ConfigurationMismatch,
+ /// \brief The AST file has errors.
+ HadErrors
+ };
+
+ /// \brief Types of AST files.
+ friend class PCHValidator;
+ friend class ASTDeclReader;
+ friend class ASTStmtReader;
+ friend class ASTIdentifierIterator;
+ friend class serialization::reader::ASTIdentifierLookupTrait;
+ friend class TypeLocReader;
+ friend class ASTWriter;
+ friend class ASTUnit; // ASTUnit needs to remap source locations.
+ friend class serialization::ReadMethodPoolVisitor;
+
+ typedef serialization::ModuleFile ModuleFile;
+ typedef serialization::ModuleKind ModuleKind;
+ typedef serialization::ModuleManager ModuleManager;
+
+ typedef ModuleManager::ModuleIterator ModuleIterator;
+ typedef ModuleManager::ModuleConstIterator ModuleConstIterator;
+ typedef ModuleManager::ModuleReverseIterator ModuleReverseIterator;
+
+private:
+ /// \brief The receiver of some callbacks invoked by ASTReader.
+ std::unique_ptr<ASTReaderListener> Listener;
+
+ /// \brief The receiver of deserialization events.
+ ASTDeserializationListener *DeserializationListener;
+ bool OwnsDeserializationListener;
+
+ SourceManager &SourceMgr;
+ FileManager &FileMgr;
+ const PCHContainerReader &PCHContainerRdr;
+ DiagnosticsEngine &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 The module manager which manages modules and their dependencies
+ ModuleManager ModuleMgr;
+
+ /// A mapping from extension block names to module file extensions.
+ llvm::StringMap<IntrusiveRefCntPtr<ModuleFileExtension>> ModuleFileExtensions;
+
+ /// \brief A timer used to track the time spent deserializing.
+ std::unique_ptr<llvm::Timer> ReadTimer;
+
+ /// \brief The location where the module file will be considered as
+ /// imported from. For non-module AST types it should be invalid.
+ SourceLocation CurrentImportLoc;
+
+ /// \brief The global module index, if loaded.
+ std::unique_ptr<GlobalModuleIndex> GlobalIndex;
+
+ /// \brief A map of global bit offsets to the module that stores entities
+ /// at those bit offsets.
+ ContinuousRangeMap<uint64_t, ModuleFile*, 4> GlobalBitOffsetsMap;
+
+ /// \brief A map of negated SLocEntryIDs to the modules containing them.
+ ContinuousRangeMap<unsigned, ModuleFile*, 64> GlobalSLocEntryMap;
+
+ typedef ContinuousRangeMap<unsigned, ModuleFile*, 64> GlobalSLocOffsetMapType;
+
+ /// \brief A map of reversed (SourceManager::MaxLoadedOffset - SLocOffset)
+ /// SourceLocation offsets to the modules containing them.
+ GlobalSLocOffsetMapType GlobalSLocOffsetMap;
+
+ /// \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;
+
+ typedef ContinuousRangeMap<serialization::TypeID, ModuleFile *, 4>
+ GlobalTypeMapType;
+
+ /// \brief Mapping from global type IDs to the module in which the
+ /// type resides along with the offset that should be added to the
+ /// global type ID to produce a local ID.
+ GlobalTypeMapType GlobalTypeMap;
+
+ /// \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 ContinuousRangeMap<serialization::DeclID, ModuleFile *, 4>
+ GlobalDeclMapType;
+
+ /// \brief Mapping from global declaration IDs to the module in which the
+ /// declaration resides.
+ GlobalDeclMapType GlobalDeclMap;
+
+ typedef std::pair<ModuleFile *, uint64_t> FileOffset;
+ typedef 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;
+
+ /// \brief Declaration updates for already-loaded declarations that we need
+ /// to apply once we finish processing an import.
+ llvm::SmallVector<std::pair<serialization::GlobalDeclID, Decl*>, 16>
+ PendingUpdateRecords;
+
+ enum class PendingFakeDefinitionKind { NotFake, Fake, FakeLoaded };
+
+ /// \brief The DefinitionData pointers that we faked up for class definitions
+ /// that we needed but hadn't loaded yet.
+ llvm::DenseMap<void *, PendingFakeDefinitionKind> PendingFakeDefinitionData;
+
+ /// \brief Exception specification updates that have been loaded but not yet
+ /// propagated across the relevant redeclaration chain. The map key is the
+ /// canonical declaration (used only for deduplication) and the value is a
+ /// declaration that has an exception specification.
+ llvm::SmallMapVector<Decl *, FunctionDecl *, 4> PendingExceptionSpecUpdates;
+
+ struct ReplacedDeclInfo {
+ ModuleFile *Mod;
+ uint64_t Offset;
+ unsigned RawLoc;
+
+ ReplacedDeclInfo() : Mod(nullptr), Offset(0), RawLoc(0) {}
+ ReplacedDeclInfo(ModuleFile *Mod, uint64_t Offset, unsigned RawLoc)
+ : Mod(Mod), Offset(Offset), RawLoc(RawLoc) {}
+ };
+
+ typedef llvm::DenseMap<serialization::DeclID, ReplacedDeclInfo>
+ DeclReplacementMap;
+ /// \brief Declarations that have been replaced in a later file in the chain.
+ DeclReplacementMap ReplacedDecls;
+
+ /// \brief Declarations that have been imported and have typedef names for
+ /// linkage purposes.
+ llvm::DenseMap<std::pair<DeclContext*, IdentifierInfo*>, NamedDecl*>
+ ImportedTypedefNamesForLinkage;
+
+ /// \brief Mergeable declaration contexts that have anonymous declarations
+ /// within them, and those anonymous declarations.
+ llvm::DenseMap<DeclContext*, llvm::SmallVector<NamedDecl*, 2>>
+ AnonymousDeclarationsForMerging;
+
+ struct FileDeclsInfo {
+ ModuleFile *Mod;
+ ArrayRef<serialization::LocalDeclID> Decls;
+
+ FileDeclsInfo() : Mod(nullptr) {}
+ FileDeclsInfo(ModuleFile *Mod, ArrayRef<serialization::LocalDeclID> Decls)
+ : Mod(Mod), Decls(Decls) {}
+ };
+
+ /// \brief Map from a FileID to the file-level declarations that it contains.
+ llvm::DenseMap<FileID, FileDeclsInfo> FileDeclIDs;
+
+ /// \brief An array of lexical contents of a declaration context, as a sequence of
+ /// Decl::Kind, DeclID pairs.
+ typedef ArrayRef<llvm::support::unaligned_uint32_t> LexicalContents;
+
+ /// \brief Map from a DeclContext to its lexical contents.
+ llvm::DenseMap<const DeclContext*, std::pair<ModuleFile*, LexicalContents>>
+ LexicalDecls;
+
+ /// \brief Map from the TU to its lexical contents from each module file.
+ std::vector<std::pair<ModuleFile*, LexicalContents>> TULexicalDecls;
+
+ /// \brief Map from a DeclContext to its lookup tables.
+ llvm::DenseMap<const DeclContext *,
+ serialization::reader::DeclContextLookupTable> Lookups;
+
+ // Updates for visible decls can occur for other contexts than just the
+ // TU, and when we read those update records, the actual context may not
+ // be available yet, so have this pending map using the ID as a key. It
+ // will be realized when the context is actually loaded.
+ struct PendingVisibleUpdate {
+ ModuleFile *Mod;
+ const unsigned char *Data;
+ };
+ typedef SmallVector<PendingVisibleUpdate, 1> DeclContextVisibleUpdates;
+
+ /// \brief Updates to the visible declarations of declaration contexts that
+ /// haven't been loaded yet.
+ llvm::DenseMap<serialization::DeclID, DeclContextVisibleUpdates>
+ PendingVisibleUpdates;
+
+ /// \brief The set of C++ or Objective-C classes that have forward
+ /// declarations that have not yet been linked to their definitions.
+ llvm::SmallPtrSet<Decl *, 4> PendingDefinitions;
+
+ typedef llvm::MapVector<Decl *, uint64_t,
+ llvm::SmallDenseMap<Decl *, unsigned, 4>,
+ SmallVector<std::pair<Decl *, uint64_t>, 4> >
+ PendingBodiesMap;
+
+ /// \brief Functions or methods that have bodies that will be attached.
+ PendingBodiesMap PendingBodies;
+
+ /// \brief Definitions for which we have added merged definitions but not yet
+ /// performed deduplication.
+ llvm::SetVector<NamedDecl*> PendingMergedDefinitionsToDeduplicate;
+
+ /// \brief Read the record that describes the lexical contents of a DC.
+ bool ReadLexicalDeclContextStorage(ModuleFile &M,
+ llvm::BitstreamCursor &Cursor,
+ uint64_t Offset, DeclContext *DC);
+ /// \brief Read the record that describes the visible contents of a DC.
+ bool ReadVisibleDeclContextStorage(ModuleFile &M,
+ llvm::BitstreamCursor &Cursor,
+ uint64_t Offset, serialization::DeclID ID);
+
+ /// \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;
+
+ typedef ContinuousRangeMap<serialization::IdentID, ModuleFile *, 4>
+ GlobalIdentifierMapType;
+
+ /// \brief Mapping from global identifier IDs to the module in which the
+ /// identifier resides along with the offset that should be added to the
+ /// global identifier ID to produce a local ID.
+ GlobalIdentifierMapType GlobalIdentifierMap;
+
+ /// \brief A vector containing macros that have already been
+ /// loaded.
+ ///
+ /// If the pointer at index I is non-NULL, then it refers to the
+ /// MacroInfo for the identifier with ID=I+1 that has already
+ /// been loaded.
+ std::vector<MacroInfo *> MacrosLoaded;
+
+ typedef std::pair<IdentifierInfo *, serialization::SubmoduleID>
+ LoadedMacroInfo;
+
+ /// \brief A set of #undef directives that we have loaded; used to
+ /// deduplicate the same #undef information coming from multiple module
+ /// files.
+ llvm::DenseSet<LoadedMacroInfo> LoadedUndefs;
+
+ typedef ContinuousRangeMap<serialization::MacroID, ModuleFile *, 4>
+ GlobalMacroMapType;
+
+ /// \brief Mapping from global macro IDs to the module in which the
+ /// macro resides along with the offset that should be added to the
+ /// global macro ID to produce a local ID.
+ GlobalMacroMapType GlobalMacroMap;
+
+ /// \brief A vector containing submodules that have already been loaded.
+ ///
+ /// This vector is indexed by the Submodule ID (-1). NULL submodule entries
+ /// indicate that the particular submodule ID has not yet been loaded.
+ SmallVector<Module *, 2> SubmodulesLoaded;
+
+ typedef ContinuousRangeMap<serialization::SubmoduleID, ModuleFile *, 4>
+ GlobalSubmoduleMapType;
+
+ /// \brief Mapping from global submodule IDs to the module file in which the
+ /// submodule resides along with the offset that should be added to the
+ /// global submodule ID to produce a local ID.
+ GlobalSubmoduleMapType GlobalSubmoduleMap;
+
+ /// \brief A set of hidden declarations.
+ typedef SmallVector<Decl*, 2> HiddenNames;
+ typedef llvm::DenseMap<Module *, HiddenNames> HiddenNamesMapType;
+
+ /// \brief A mapping from each of the hidden submodules to the deserialized
+ /// declarations in that submodule that could be made visible.
+ HiddenNamesMapType HiddenNamesMap;
+
+
+ /// \brief A module import, export, or conflict that hasn't yet been resolved.
+ struct UnresolvedModuleRef {
+ /// \brief The file in which this module resides.
+ ModuleFile *File;
+
+ /// \brief The module that is importing or exporting.
+ Module *Mod;
+
+ /// \brief The kind of module reference.
+ enum { Import, Export, Conflict } Kind;
+
+ /// \brief The local ID of the module that is being exported.
+ unsigned ID;
+
+ /// \brief Whether this is a wildcard export.
+ unsigned IsWildcard : 1;
+
+ /// \brief String data.
+ StringRef String;
+ };
+
+ /// \brief The set of module imports and exports that still need to be
+ /// resolved.
+ SmallVector<UnresolvedModuleRef, 2> UnresolvedModuleRefs;
+
+ /// \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.
+ SmallVector<Selector, 16> SelectorsLoaded;
+
+ typedef ContinuousRangeMap<serialization::SelectorID, ModuleFile *, 4>
+ GlobalSelectorMapType;
+
+ /// \brief Mapping from global selector IDs to the module in which the
+
+ /// global selector ID to produce a local ID.
+ GlobalSelectorMapType GlobalSelectorMap;
+
+ /// \brief The generation number of the last time we loaded data from the
+ /// global method pool for this selector.
+ llvm::DenseMap<Selector, unsigned> SelectorGeneration;
+
+ struct PendingMacroInfo {
+ ModuleFile *M;
+ uint64_t MacroDirectivesOffset;
+
+ PendingMacroInfo(ModuleFile *M, uint64_t MacroDirectivesOffset)
+ : M(M), MacroDirectivesOffset(MacroDirectivesOffset) {}
+ };
+
+ typedef llvm::MapVector<IdentifierInfo *, SmallVector<PendingMacroInfo, 2> >
+ PendingMacroIDsMap;
+
+ /// \brief Mapping from identifiers that have a macro history to the global
+ /// IDs have not yet been deserialized to the global IDs of those macros.
+ PendingMacroIDsMap PendingMacroIDs;
+
+ typedef ContinuousRangeMap<unsigned, ModuleFile *, 4>
+ GlobalPreprocessedEntityMapType;
+
+ /// \brief Mapping from global preprocessing entity IDs to the module in
+ /// which the preprocessed entity resides along with the offset that should be
+ /// added to the global preprocessing entitiy ID to produce a local ID.
+ GlobalPreprocessedEntityMapType GlobalPreprocessedEntityMap;
+
+ /// \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 EAGERLY_DESERIALIZED_DECLS blocks
+ /// in the chain. The referenced declarations are deserialized and passed to
+ /// the consumer eagerly.
+ SmallVector<uint64_t, 16> EagerlyDeserializedDecls;
+
+ /// \brief The IDs of all tentative definitions stored in 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.
+ 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.
+ SmallVector<uint64_t, 64> VTableUses;
+
+ /// \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.
+ SmallVector<uint64_t, 64> PendingInstantiations;
+
+ //@}
+
+ /// \name DiagnosticsEngine-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.
+ SmallVector<uint64_t, 16> UnusedFileScopedDecls;
+
+ /// \brief A list of all the delegating constructors we've seen, to diagnose
+ /// cycles.
+ SmallVector<uint64_t, 4> DelegatingCtorDecls;
+
+ /// \brief Method selectors used in a @selector expression. Used for
+ /// implementation of -Wselector.
+ SmallVector<uint64_t, 64> ReferencedSelectorsData;
+
+ /// \brief A snapshot of Sema's weak undeclared identifier tracking, for
+ /// generating warnings.
+ 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.
+ 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 potentially unused typedef names in the chain.
+ ///
+ /// Sema tracks these to emit warnings.
+ SmallVector<uint64_t, 16> UnusedLocalTypedefNameCandidates;
+
+ /// \brief The IDs of the declarations Sema stores directly.
+ ///
+ /// Sema tracks a few important decls, such as namespace std, directly.
+ 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.
+ 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.
+ SmallVector<uint64_t, 2> CUDASpecialDeclRefs;
+
+ /// \brief The floating point pragma option settings.
+ SmallVector<uint64_t, 1> FPPragmaOptions;
+
+ /// \brief The pragma clang optimize location (if the pragma state is "off").
+ SourceLocation OptimizeOffPragmaLocation;
+
+ /// \brief The OpenCL extension settings.
+ SmallVector<uint64_t, 1> OpenCLExtensions;
+
+ /// \brief A list of the namespaces we've seen.
+ SmallVector<uint64_t, 4> KnownNamespaces;
+
+ /// \brief A list of undefined decls with internal linkage followed by the
+ /// SourceLocation of a matching ODR-use.
+ SmallVector<uint64_t, 8> UndefinedButUsed;
+
+ /// \brief Delete expressions to analyze at the end of translation unit.
+ SmallVector<uint64_t, 8> DelayedDeleteExprs;
+
+ // \brief A list of late parsed template function data.
+ SmallVector<uint64_t, 1> LateParsedTemplates;
+
+ struct ImportedSubmodule {
+ serialization::SubmoduleID ID;
+ SourceLocation ImportLoc;
+
+ ImportedSubmodule(serialization::SubmoduleID ID, SourceLocation ImportLoc)
+ : ID(ID), ImportLoc(ImportLoc) {}
+ };
+
+ /// \brief A list of modules that were imported by precompiled headers or
+ /// any other non-module AST file.
+ SmallVector<ImportedSubmodule, 2> ImportedModules;
+ //@}
+
+ /// \brief The directory that the PCH we are reading is stored in.
+ std::string CurrentDir;
+
+ /// \brief The system include root to be used when loading the
+ /// precompiled header.
+ std::string isysroot;
+
+ /// \brief Whether to disable the normal validation performed on precompiled
+ /// headers when they are loaded.
+ bool DisableValidation;
+
+ /// \brief Whether to accept an AST file with compiler errors.
+ bool AllowASTWithCompilerErrors;
+
+ /// \brief Whether to accept an AST file that has a different configuration
+ /// from the current compiler instance.
+ bool AllowConfigurationMismatch;
+
+ /// \brief Whether validate system input files.
+ bool ValidateSystemInputs;
+
+ /// \brief Whether we are allowed to use the global module index.
+ bool UseGlobalIndex;
+
+ /// \brief Whether we have tried loading the global module index yet.
+ bool TriedLoadingGlobalIndex;
+
+ typedef llvm::DenseMap<unsigned, SwitchCase *> SwitchCaseMapTy;
+ /// \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.
+ SwitchCaseMapTy SwitchCaseStmts;
+
+ SwitchCaseMapTy *CurrSwitchCaseStmts;
+
+ /// \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 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 lookups into identifier tables.
+ unsigned NumIdentifierLookups;
+
+ /// \brief The number of lookups into identifier tables that succeed.
+ unsigned NumIdentifierLookupHits;
+
+ /// \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.
+ unsigned NumMethodPoolLookups;
+
+ /// \brief The number of times we have looked up a selector in the method
+ /// pool and found something.
+ unsigned NumMethodPoolHits;
+
+ /// \brief The number of times we have looked up a selector in the method
+ /// pool within a specific module.
+ unsigned NumMethodPoolTableLookups;
+
+ /// \brief The number of times we have looked up a selector in the method
+ /// pool within a specific module and found something.
+ unsigned NumMethodPoolTableHits;
+
+ /// \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;
+
+ /// Total size of modules, in bits, currently loaded
+ uint64_t TotalModulesSizeInBits;
+
+ /// \brief Number of Decl/types that are currently deserializing.
+ unsigned NumCurrentElementsDeserializing;
+
+ /// \brief Set true while we are in the process of passing deserialized
+ /// "interesting" decls to consumer inside FinishedDeserializing().
+ /// This is used as a guard to avoid recursively repeating the process of
+ /// passing decls to consumer.
+ bool PassingDeclsToConsumer;
+
+ /// \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.
+ llvm::MapVector<IdentifierInfo *, SmallVector<uint32_t, 4> >
+ PendingIdentifierInfos;
+
+ /// \brief The set of lookup results that we have faked in order to support
+ /// merging of partially deserialized decls but that we have not yet removed.
+ llvm::SmallMapVector<IdentifierInfo *, SmallVector<NamedDecl*, 2>, 16>
+ PendingFakeLookupResults;
+
+ /// \brief The generation number of each identifier, which keeps track of
+ /// the last time we loaded information about this identifier.
+ llvm::DenseMap<IdentifierInfo *, unsigned> IdentifierGeneration;
+
+ /// \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 The list of redeclaration chains that still need to be
+ /// reconstructed, and the local offset to the corresponding list
+ /// of redeclarations.
+ SmallVector<std::pair<Decl *, uint64_t>, 16> PendingDeclChains;
+
+ /// \brief The list of canonical declarations whose redeclaration chains
+ /// need to be marked as incomplete once we're done deserializing things.
+ SmallVector<Decl *, 16> PendingIncompleteDeclChains;
+
+ /// \brief The Decl IDs for the Sema/Lexical DeclContext of a Decl that has
+ /// been loaded but its DeclContext was not set yet.
+ struct PendingDeclContextInfo {
+ Decl *D;
+ serialization::GlobalDeclID SemaDC;
+ serialization::GlobalDeclID LexicalDC;
+ };
+
+ /// \brief The set of Decls that have been loaded but their DeclContexts are
+ /// not set yet.
+ ///
+ /// The DeclContexts for these Decls will be set once recursive loading has
+ /// been completed.
+ std::deque<PendingDeclContextInfo> PendingDeclContextInfos;
+
+ /// \brief The set of NamedDecls that have been loaded, but are members of a
+ /// context that has been merged into another context where the corresponding
+ /// declaration is either missing or has not yet been loaded.
+ ///
+ /// We will check whether the corresponding declaration is in fact missing
+ /// once recursing loading has been completed.
+ llvm::SmallVector<NamedDecl *, 16> PendingOdrMergeChecks;
+
+ /// \brief Record definitions in which we found an ODR violation.
+ llvm::SmallDenseMap<CXXRecordDecl *, llvm::TinyPtrVector<CXXRecordDecl *>, 2>
+ PendingOdrMergeFailures;
+
+ /// \brief DeclContexts in which we have diagnosed an ODR violation.
+ llvm::SmallPtrSet<DeclContext*, 2> DiagnosedOdrMergeFailures;
+
+ /// \brief The set of Objective-C categories that have been deserialized
+ /// since the last time the declaration chains were linked.
+ llvm::SmallPtrSet<ObjCCategoryDecl *, 16> CategoriesDeserialized;
+
+ /// \brief The set of Objective-C class definitions that have already been
+ /// loaded, for which we will need to check for categories whenever a new
+ /// module is loaded.
+ SmallVector<ObjCInterfaceDecl *, 16> ObjCClassesLoaded;
+
+ typedef llvm::DenseMap<Decl *, SmallVector<serialization::DeclID, 2> >
+ KeyDeclsMap;
+
+ /// \brief A mapping from canonical declarations to the set of global
+ /// declaration IDs for key declaration that have been merged with that
+ /// canonical declaration. A key declaration is a formerly-canonical
+ /// declaration whose module did not import any other key declaration for that
+ /// entity. These are the IDs that we use as keys when finding redecl chains.
+ KeyDeclsMap KeyDecls;
+
+ /// \brief A mapping from DeclContexts to the semantic DeclContext that we
+ /// are treating as the definition of the entity. This is used, for instance,
+ /// when merging implicit instantiations of class templates across modules.
+ llvm::DenseMap<DeclContext *, DeclContext *> MergedDeclContexts;
+
+ /// \brief A mapping from canonical declarations of enums to their canonical
+ /// definitions. Only populated when using modules in C++.
+ llvm::DenseMap<EnumDecl *, EnumDecl *> EnumDefinitions;
+
+ /// \brief When reading a Stmt tree, Stmt operands are placed in this stack.
+ SmallVector<Stmt *, 16> StmtStack;
+
+ /// \brief What kind of records we are reading.
+ enum ReadingKind {
+ Read_None, 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 &) = delete;
+ void operator=(const ReadingKindTracker &) = delete;
+
+ public:
+ ReadingKindTracker(enum ReadingKind newKind, ASTReader &reader)
+ : Reader(reader), PrevKind(Reader.ReadingKind) {
+ Reader.ReadingKind = newKind;
+ }
+
+ ~ReadingKindTracker() { Reader.ReadingKind = PrevKind; }
+ };
+
+ /// \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(ModuleFile &F);
+
+ struct InputFileInfo {
+ std::string Filename;
+ off_t StoredSize;
+ time_t StoredTime;
+ bool Overridden;
+ bool Transient;
+ };
+
+ /// \brief Reads the stored information about an input file.
+ InputFileInfo readInputFileInfo(ModuleFile &F, unsigned ID);
+
+ /// \brief Retrieve the file entry and 'overridden' bit for an input
+ /// file in the given module file.
+ serialization::InputFile getInputFile(ModuleFile &F, unsigned ID,
+ bool Complain = true);
+
+public:
+ void ResolveImportedPath(ModuleFile &M, std::string &Filename);
+ static void ResolveImportedPath(std::string &Filename, StringRef Prefix);
+
+ /// \brief Returns the first key declaration for the given declaration. This
+ /// is one that is formerly-canonical (or still canonical) and whose module
+ /// did not import any other key declaration of the entity.
+ Decl *getKeyDeclaration(Decl *D) {
+ D = D->getCanonicalDecl();
+ if (D->isFromASTFile())
+ return D;
+
+ auto I = KeyDecls.find(D);
+ if (I == KeyDecls.end() || I->second.empty())
+ return D;
+ return GetExistingDecl(I->second[0]);
+ }
+ const Decl *getKeyDeclaration(const Decl *D) {
+ return getKeyDeclaration(const_cast<Decl*>(D));
+ }
+
+ /// \brief Run a callback on each imported key declaration of \p D.
+ template <typename Fn>
+ void forEachImportedKeyDecl(const Decl *D, Fn Visit) {
+ D = D->getCanonicalDecl();
+ if (D->isFromASTFile())
+ Visit(D);
+
+ auto It = KeyDecls.find(const_cast<Decl*>(D));
+ if (It != KeyDecls.end())
+ for (auto ID : It->second)
+ Visit(GetExistingDecl(ID));
+ }
+
+ /// \brief Get the loaded lookup tables for \p Primary, if any.
+ const serialization::reader::DeclContextLookupTable *
+ getLoadedLookupTables(DeclContext *Primary) const;
+
+private:
+ struct ImportedModule {
+ ModuleFile *Mod;
+ ModuleFile *ImportedBy;
+ SourceLocation ImportLoc;
+
+ ImportedModule(ModuleFile *Mod,
+ ModuleFile *ImportedBy,
+ SourceLocation ImportLoc)
+ : Mod(Mod), ImportedBy(ImportedBy), ImportLoc(ImportLoc) { }
+ };
+
+ ASTReadResult ReadASTCore(StringRef FileName, ModuleKind Type,
+ SourceLocation ImportLoc, ModuleFile *ImportedBy,
+ SmallVectorImpl<ImportedModule> &Loaded,
+ off_t ExpectedSize, time_t ExpectedModTime,
+ serialization::ASTFileSignature ExpectedSignature,
+ unsigned ClientLoadCapabilities);
+ ASTReadResult ReadControlBlock(ModuleFile &F,
+ SmallVectorImpl<ImportedModule> &Loaded,
+ const ModuleFile *ImportedBy,
+ unsigned ClientLoadCapabilities);
+ static ASTReadResult ReadOptionsBlock(
+ llvm::BitstreamCursor &Stream, unsigned ClientLoadCapabilities,
+ bool AllowCompatibleConfigurationMismatch, ASTReaderListener &Listener,
+ std::string &SuggestedPredefines);
+ ASTReadResult ReadASTBlock(ModuleFile &F, unsigned ClientLoadCapabilities);
+ ASTReadResult ReadExtensionBlock(ModuleFile &F);
+ bool ParseLineTable(ModuleFile &F, const RecordData &Record);
+ bool ReadSourceManagerBlock(ModuleFile &F);
+ llvm::BitstreamCursor &SLocCursorForID(int ID);
+ SourceLocation getImportLocation(ModuleFile *F);
+ ASTReadResult ReadModuleMapFileBlock(RecordData &Record, ModuleFile &F,
+ const ModuleFile *ImportedBy,
+ unsigned ClientLoadCapabilities);
+ ASTReadResult ReadSubmoduleBlock(ModuleFile &F,
+ unsigned ClientLoadCapabilities);
+ static bool ParseLanguageOptions(const RecordData &Record, bool Complain,
+ ASTReaderListener &Listener,
+ bool AllowCompatibleDifferences);
+ static bool ParseTargetOptions(const RecordData &Record, bool Complain,
+ ASTReaderListener &Listener,
+ bool AllowCompatibleDifferences);
+ static bool ParseDiagnosticOptions(const RecordData &Record, bool Complain,
+ ASTReaderListener &Listener);
+ static bool ParseFileSystemOptions(const RecordData &Record, bool Complain,
+ ASTReaderListener &Listener);
+ static bool ParseHeaderSearchOptions(const RecordData &Record, bool Complain,
+ ASTReaderListener &Listener);
+ static bool ParsePreprocessorOptions(const RecordData &Record, bool Complain,
+ ASTReaderListener &Listener,
+ std::string &SuggestedPredefines);
+
+ struct RecordLocation {
+ RecordLocation(ModuleFile *M, uint64_t O)
+ : F(M), Offset(O) {}
+ ModuleFile *F;
+ uint64_t Offset;
+ };
+
+ QualType readTypeRecord(unsigned Index);
+ void readExceptionSpec(ModuleFile &ModuleFile,
+ SmallVectorImpl<QualType> &ExceptionStorage,
+ FunctionProtoType::ExceptionSpecInfo &ESI,
+ const RecordData &Record, unsigned &Index);
+ RecordLocation TypeCursorForIndex(unsigned Index);
+ void LoadedDecl(unsigned Index, Decl *D);
+ Decl *ReadDeclRecord(serialization::DeclID ID);
+ void markIncompleteDeclChain(Decl *Canon);
+
+ /// \brief Returns the most recent declaration of a declaration (which must be
+ /// of a redeclarable kind) that is either local or has already been loaded
+ /// merged into its redecl chain.
+ Decl *getMostRecentExistingDecl(Decl *D);
+
+ RecordLocation DeclCursorForID(serialization::DeclID ID,
+ unsigned &RawLocation);
+ void loadDeclUpdateRecords(serialization::DeclID ID, Decl *D);
+ void loadPendingDeclChain(Decl *D, uint64_t LocalOffset);
+ void loadObjCCategories(serialization::GlobalDeclID ID, ObjCInterfaceDecl *D,
+ unsigned PreviousGeneration = 0);
+
+ RecordLocation getLocalBitOffset(uint64_t GlobalOffset);
+ uint64_t getGlobalBitOffset(ModuleFile &M, uint32_t LocalOffset);
+
+ /// \brief Returns the first preprocessed entity ID that begins or ends after
+ /// \arg Loc.
+ serialization::PreprocessedEntityID
+ findPreprocessedEntity(SourceLocation Loc, bool EndsAfter) const;
+
+ /// \brief Find the next module that contains entities and return the ID
+ /// of the first entry.
+ ///
+ /// \param SLocMapI points at a chunk of a module that contains no
+ /// preprocessed entities or the entities it contains are not the
+ /// ones we are looking for.
+ serialization::PreprocessedEntityID
+ findNextPreprocessedEntity(
+ GlobalSLocOffsetMapType::const_iterator SLocMapI) const;
+
+ /// \brief Returns (ModuleFile, Local index) pair for \p GlobalIndex of a
+ /// preprocessed entity.
+ std::pair<ModuleFile *, unsigned>
+ getModulePreprocessedEntity(unsigned GlobalIndex);
+
+ /// \brief Returns (begin, end) pair for the preprocessed entities of a
+ /// particular module.
+ llvm::iterator_range<PreprocessingRecord::iterator>
+ getModulePreprocessedEntities(ModuleFile &Mod) const;
+
+ class ModuleDeclIterator
+ : public llvm::iterator_adaptor_base<
+ ModuleDeclIterator, const serialization::LocalDeclID *,
+ std::random_access_iterator_tag, const Decl *, ptrdiff_t,
+ const Decl *, const Decl *> {
+ ASTReader *Reader;
+ ModuleFile *Mod;
+
+ public:
+ ModuleDeclIterator()
+ : iterator_adaptor_base(nullptr), Reader(nullptr), Mod(nullptr) {}
+
+ ModuleDeclIterator(ASTReader *Reader, ModuleFile *Mod,
+ const serialization::LocalDeclID *Pos)
+ : iterator_adaptor_base(Pos), Reader(Reader), Mod(Mod) {}
+
+ value_type operator*() const {
+ return Reader->GetDecl(Reader->getGlobalDeclID(*Mod, *I));
+ }
+ value_type operator->() const { return **this; }
+
+ bool operator==(const ModuleDeclIterator &RHS) const {
+ assert(Reader == RHS.Reader && Mod == RHS.Mod);
+ return I == RHS.I;
+ }
+ };
+
+ llvm::iterator_range<ModuleDeclIterator>
+ getModuleFileLevelDecls(ModuleFile &Mod);
+
+ void PassInterestingDeclsToConsumer();
+ void PassInterestingDeclToConsumer(Decl *D);
+
+ void finishPendingActions();
+ void diagnoseOdrViolations();
+
+ void pushExternalDeclIntoScope(NamedDecl *D, DeclarationName Name);
+
+ void addPendingDeclContextInfo(Decl *D,
+ serialization::GlobalDeclID SemaDC,
+ serialization::GlobalDeclID LexicalDC) {
+ assert(D);
+ PendingDeclContextInfo Info = { D, SemaDC, LexicalDC };
+ PendingDeclContextInfos.push_back(Info);
+ }
+
+ /// \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(StringRef Msg);
+ void Error(unsigned DiagID, StringRef Arg1 = StringRef(),
+ StringRef Arg2 = StringRef());
+
+ ASTReader(const ASTReader &) = delete;
+ void operator=(const ASTReader &) = delete;
+public:
+ /// \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 PCHContainerRdr the PCHContainerOperations to use for loading and
+ /// creating modules.
+ ///
+ /// \param Extensions the list of module file extensions that can be loaded
+ /// from the AST files.
+ ///
+ /// \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 AllowASTWithCompilerErrors If true, the AST reader will accept an
+ /// AST file the was created out of an AST with compiler errors,
+ /// otherwise it will reject it.
+ ///
+ /// \param AllowConfigurationMismatch If true, the AST reader will not check
+ /// for configuration differences between the AST file and the invocation.
+ ///
+ /// \param ValidateSystemInputs If true, the AST reader will validate
+ /// system input files in addition to user input files. This is only
+ /// meaningful if \p DisableValidation is false.
+ ///
+ /// \param UseGlobalIndex If true, the AST reader will try to load and use
+ /// the global module index.
+ ///
+ /// \param ReadTimer If non-null, a timer used to track the time spent
+ /// deserializing.
+ ASTReader(Preprocessor &PP, ASTContext &Context,
+ const PCHContainerReader &PCHContainerRdr,
+ ArrayRef<IntrusiveRefCntPtr<ModuleFileExtension>> Extensions,
+ StringRef isysroot = "", bool DisableValidation = false,
+ bool AllowASTWithCompilerErrors = false,
+ bool AllowConfigurationMismatch = false,
+ bool ValidateSystemInputs = false, bool UseGlobalIndex = true,
+ std::unique_ptr<llvm::Timer> ReadTimer = {});
+
+ ~ASTReader() override;
+
+ SourceManager &getSourceManager() const { return SourceMgr; }
+ FileManager &getFileManager() const { return FileMgr; }
+ DiagnosticsEngine &getDiags() const { return Diags; }
+
+ /// \brief Flags that indicate what kind of AST loading failures the client
+ /// of the AST reader can directly handle.
+ ///
+ /// When a client states that it can handle a particular kind of failure,
+ /// the AST reader will not emit errors when producing that kind of failure.
+ enum LoadFailureCapabilities {
+ /// \brief The client can't handle any AST loading failures.
+ ARR_None = 0,
+ /// \brief The client can handle an AST file that cannot load because it
+ /// is missing.
+ ARR_Missing = 0x1,
+ /// \brief The client can handle an AST file that cannot load because it
+ /// is out-of-date relative to its input files.
+ ARR_OutOfDate = 0x2,
+ /// \brief The client can handle an AST file that cannot load because it
+ /// was built with a different version of Clang.
+ ARR_VersionMismatch = 0x4,
+ /// \brief The client can handle an AST file that cannot load because it's
+ /// compiled configuration doesn't match that of the context it was
+ /// loaded into.
+ ARR_ConfigurationMismatch = 0x8
+ };
+
+ /// \brief Load the AST file designated by the given file name.
+ ///
+ /// \param FileName The name of the AST file to load.
+ ///
+ /// \param Type The kind of AST being loaded, e.g., PCH, module, main file,
+ /// or preamble.
+ ///
+ /// \param ImportLoc the location where the module file will be considered as
+ /// imported from. For non-module AST types it should be invalid.
+ ///
+ /// \param ClientLoadCapabilities The set of client load-failure
+ /// capabilities, represented as a bitset of the enumerators of
+ /// LoadFailureCapabilities.
+ ASTReadResult ReadAST(const std::string &FileName, ModuleKind Type,
+ SourceLocation ImportLoc,
+ unsigned ClientLoadCapabilities);
+
+ /// \brief Make the entities in the given module and any of its (non-explicit)
+ /// submodules visible to name lookup.
+ ///
+ /// \param Mod The module whose names should be made visible.
+ ///
+ /// \param NameVisibility The level of visibility to give the names in the
+ /// module. Visibility can only be increased over time.
+ ///
+ /// \param ImportLoc The location at which the import occurs.
+ void makeModuleVisible(Module *Mod,
+ Module::NameVisibilityKind NameVisibility,
+ SourceLocation ImportLoc);
+
+ /// \brief Make the names within this set of hidden names visible.
+ void makeNamesVisible(const HiddenNames &Names, Module *Owner);
+
+ /// \brief Take the AST callbacks listener.
+ std::unique_ptr<ASTReaderListener> takeListener() {
+ return std::move(Listener);
+ }
+
+ /// \brief Set the AST callbacks listener.
+ void setListener(std::unique_ptr<ASTReaderListener> Listener) {
+ this->Listener = std::move(Listener);
+ }
+
+ /// \brief Add an AST callback listener.
+ ///
+ /// Takes ownership of \p L.
+ void addListener(std::unique_ptr<ASTReaderListener> L) {
+ if (Listener)
+ L = llvm::make_unique<ChainedASTReaderListener>(std::move(L),
+ std::move(Listener));
+ Listener = std::move(L);
+ }
+
+ /// RAII object to temporarily add an AST callback listener.
+ class ListenerScope {
+ ASTReader &Reader;
+ bool Chained;
+
+ public:
+ ListenerScope(ASTReader &Reader, std::unique_ptr<ASTReaderListener> L)
+ : Reader(Reader), Chained(false) {
+ auto Old = Reader.takeListener();
+ if (Old) {
+ Chained = true;
+ L = llvm::make_unique<ChainedASTReaderListener>(std::move(L),
+ std::move(Old));
+ }
+ Reader.setListener(std::move(L));
+ }
+ ~ListenerScope() {
+ auto New = Reader.takeListener();
+ if (Chained)
+ Reader.setListener(static_cast<ChainedASTReaderListener *>(New.get())
+ ->takeSecond());
+ }
+ };
+
+ /// \brief Set the AST deserialization listener.
+ void setDeserializationListener(ASTDeserializationListener *Listener,
+ bool TakeOwnership = false);
+
+ /// \brief Determine whether this AST reader has a global index.
+ bool hasGlobalIndex() const { return (bool)GlobalIndex; }
+
+ /// \brief Return global module index.
+ GlobalModuleIndex *getGlobalIndex() { return GlobalIndex.get(); }
+
+ /// \brief Reset reader for a reload try.
+ void resetForReload() { TriedLoadingGlobalIndex = false; }
+
+ /// \brief Attempts to load the global index.
+ ///
+ /// \returns true if loading the global index has failed for any reason.
+ bool loadGlobalIndex();
+
+ /// \brief Determine whether we tried to load the global index, but failed,
+ /// e.g., because it is out-of-date or does not exist.
+ bool isGlobalIndexUnavailable() const;
+
+ /// \brief Initializes the ASTContext
+ void InitializeContext();
+
+ /// \brief Update the state of Sema after loading some additional modules.
+ void UpdateSema();
+
+ /// \brief Add in-memory (virtual file) buffer.
+ void addInMemoryBuffer(StringRef &FileName,
+ std::unique_ptr<llvm::MemoryBuffer> Buffer) {
+ ModuleMgr.addInMemoryBuffer(FileName, std::move(Buffer));
+ }
+
+ /// \brief Finalizes the AST reader's state before writing an AST file to
+ /// disk.
+ ///
+ /// This operation may undo temporary state in the AST that should not be
+ /// emitted.
+ void finalizeForWriting();
+
+ /// \brief Retrieve the module manager.
+ ModuleManager &getModuleManager() { return ModuleMgr; }
+
+ /// \brief Retrieve the preprocessor.
+ Preprocessor &getPreprocessor() const { return PP; }
+
+ /// \brief Retrieve the name of the original source file name for the primary
+ /// module file.
+ StringRef getOriginalSourceFile() {
+ return ModuleMgr.getPrimaryModule().OriginalSourceFileName;
+ }
+
+ /// \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,
+ const PCHContainerReader &PCHContainerRdr,
+ DiagnosticsEngine &Diags);
+
+ /// \brief Read the control block for the named AST file.
+ ///
+ /// \returns true if an error occurred, false otherwise.
+ static bool
+ readASTFileControlBlock(StringRef Filename, FileManager &FileMgr,
+ const PCHContainerReader &PCHContainerRdr,
+ bool FindModuleFileExtensions,
+ ASTReaderListener &Listener);
+
+ /// \brief Determine whether the given AST file is acceptable to load into a
+ /// translation unit with the given language and target options.
+ static bool isAcceptableASTFile(StringRef Filename, FileManager &FileMgr,
+ const PCHContainerReader &PCHContainerRdr,
+ const LangOptions &LangOpts,
+ const TargetOptions &TargetOpts,
+ const PreprocessorOptions &PPOpts,
+ std::string ExistingModuleCachePath);
+
+ /// \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 a preallocated preprocessed entity from the external source.
+ ///
+ /// \returns null if an error occurred that prevented the preprocessed
+ /// entity from being loaded.
+ PreprocessedEntity *ReadPreprocessedEntity(unsigned Index) override;
+
+ /// \brief Returns a pair of [Begin, End) indices of preallocated
+ /// preprocessed entities that \p Range encompasses.
+ std::pair<unsigned, unsigned>
+ findPreprocessedEntitiesInRange(SourceRange Range) override;
+
+ /// \brief Optionally returns true or false if the preallocated preprocessed
+ /// entity with index \p Index came from file \p FID.
+ Optional<bool> isPreprocessedEntityInFileID(unsigned Index,
+ FileID FID) override;
+
+ /// \brief Read the header file information for the given file entry.
+ HeaderFileInfo GetHeaderFileInfo(const FileEntry *FE) override;
+
+ void ReadPragmaDiagnosticMappings(DiagnosticsEngine &Diag);
+
+ /// \brief Returns the number of source locations found in the chain.
+ unsigned getTotalNumSLocs() const {
+ return TotalNumSLocEntries;
+ }
+
+ /// \brief Returns the number of identifiers found in the chain.
+ unsigned getTotalNumIdentifiers() const {
+ return static_cast<unsigned>(IdentifiersLoaded.size());
+ }
+
+ /// \brief Returns the number of macros found in the chain.
+ unsigned getTotalNumMacros() const {
+ return static_cast<unsigned>(MacrosLoaded.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 submodules known.
+ unsigned getTotalNumSubmodules() const {
+ return static_cast<unsigned>(SubmodulesLoaded.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 preprocessed entities known to the AST
+ /// reader.
+ unsigned getTotalNumPreprocessedEntities() const {
+ unsigned Result = 0;
+ for (ModuleConstIterator I = ModuleMgr.begin(),
+ E = ModuleMgr.end(); I != E; ++I) {
+ Result += (*I)->NumPreprocessedEntities;
+ }
+
+ return Result;
+ }
+
+ /// \brief Reads a TemplateArgumentLocInfo appropriate for the
+ /// given TemplateArgument kind.
+ TemplateArgumentLocInfo
+ GetTemplateArgumentLocInfo(ModuleFile &F, TemplateArgument::ArgKind Kind,
+ const RecordData &Record, unsigned &Idx);
+
+ /// \brief Reads a TemplateArgumentLoc.
+ TemplateArgumentLoc
+ ReadTemplateArgumentLoc(ModuleFile &F,
+ const RecordData &Record, unsigned &Idx);
+
+ const ASTTemplateArgumentListInfo*
+ ReadASTTemplateArgumentListInfo(ModuleFile &F,
+ const RecordData &Record, unsigned &Index);
+
+ /// \brief Reads a declarator info from the given record.
+ TypeSourceInfo *GetTypeSourceInfo(ModuleFile &F,
+ const RecordData &Record, unsigned &Idx);
+
+ /// \brief Resolve a type ID into a type, potentially building a new
+ /// type.
+ QualType GetType(serialization::TypeID ID);
+
+ /// \brief Resolve a local type ID within a given AST file into a type.
+ QualType getLocalType(ModuleFile &F, unsigned LocalID);
+
+ /// \brief Map a local type ID within a given AST file into a global type ID.
+ serialization::TypeID getGlobalTypeID(ModuleFile &F, unsigned LocalID) const;
+
+ /// \brief Read a type from the current position in the given record, which
+ /// was read from the given AST file.
+ QualType readType(ModuleFile &F, const RecordData &Record, unsigned &Idx) {
+ if (Idx >= Record.size())
+ return QualType();
+
+ return getLocalType(F, Record[Idx++]);
+ }
+
+ /// \brief Map from a local declaration ID within a given module to a
+ /// global declaration ID.
+ serialization::DeclID getGlobalDeclID(ModuleFile &F,
+ serialization::LocalDeclID LocalID) const;
+
+ /// \brief Returns true if global DeclID \p ID originated from module \p M.
+ bool isDeclIDFromModule(serialization::GlobalDeclID ID, ModuleFile &M) const;
+
+ /// \brief Retrieve the module file that owns the given declaration, or NULL
+ /// if the declaration is not from a module file.
+ ModuleFile *getOwningModuleFile(const Decl *D);
+
+ /// \brief Get the best name we know for the module that owns the given
+ /// declaration, or an empty string if the declaration is not from a module.
+ std::string getOwningModuleNameForDiagnostic(const Decl *D);
+
+ /// \brief Returns the source location for the decl \p ID.
+ SourceLocation getSourceLocationForDeclID(serialization::GlobalDeclID ID);
+
+ /// \brief Resolve a declaration ID into a declaration, potentially
+ /// building a new declaration.
+ Decl *GetDecl(serialization::DeclID ID);
+ Decl *GetExternalDecl(uint32_t ID) override;
+
+ /// \brief Resolve a declaration ID into a declaration. Return 0 if it's not
+ /// been loaded yet.
+ Decl *GetExistingDecl(serialization::DeclID ID);
+
+ /// \brief Reads a declaration with the given local ID in the given module.
+ Decl *GetLocalDecl(ModuleFile &F, uint32_t LocalID) {
+ return GetDecl(getGlobalDeclID(F, LocalID));
+ }
+
+ /// \brief Reads a declaration with the given local ID in the given module.
+ ///
+ /// \returns The requested declaration, casted to the given return type.
+ template<typename T>
+ T *GetLocalDeclAs(ModuleFile &F, uint32_t LocalID) {
+ return cast_or_null<T>(GetLocalDecl(F, LocalID));
+ }
+
+ /// \brief Map a global declaration ID into the declaration ID used to
+ /// refer to this declaration within the given module fule.
+ ///
+ /// \returns the global ID of the given declaration as known in the given
+ /// module file.
+ serialization::DeclID
+ mapGlobalIDToModuleFileGlobalID(ModuleFile &M,
+ serialization::DeclID GlobalID);
+
+ /// \brief Reads a declaration ID from the given position in a record in the
+ /// given module.
+ ///
+ /// \returns The declaration ID read from the record, adjusted to a global ID.
+ serialization::DeclID ReadDeclID(ModuleFile &F, const RecordData &Record,
+ unsigned &Idx);
+
+ /// \brief Reads a declaration from the given position in a record in the
+ /// given module.
+ Decl *ReadDecl(ModuleFile &F, const RecordData &R, unsigned &I) {
+ return GetDecl(ReadDeclID(F, R, I));
+ }
+
+ /// \brief Reads a declaration from the given position in a record in the
+ /// given module.
+ ///
+ /// \returns The declaration read from this location, casted to the given
+ /// result type.
+ template<typename T>
+ T *ReadDeclAs(ModuleFile &F, const RecordData &R, unsigned &I) {
+ return cast_or_null<T>(GetDecl(ReadDeclID(F, R, I)));
+ }
+
+ /// \brief If any redeclarations of \p D have been imported since it was
+ /// last checked, this digs out those redeclarations and adds them to the
+ /// redeclaration chain for \p D.
+ void CompleteRedeclChain(const Decl *D) override;
+
+ /// \brief Read a CXXBaseSpecifiers ID form the given record and
+ /// return its global bit offset.
+ uint64_t readCXXBaseSpecifiers(ModuleFile &M, const RecordData &Record,
+ unsigned &Idx);
+
+ CXXBaseSpecifier *GetExternalCXXBaseSpecifiers(uint64_t Offset) override;
+
+ /// \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 *GetExternalDeclStmt(uint64_t Offset) override;
+
+ /// 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.
+ static 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.
+ bool FindExternalVisibleDeclsByName(const DeclContext *DC,
+ DeclarationName Name) override;
+
+ /// \brief Read all of the declarations lexically stored in a
+ /// declaration context.
+ ///
+ /// \param DC The declaration context whose declarations will be
+ /// read.
+ ///
+ /// \param IsKindWeWant A predicate indicating which declaration kinds
+ /// we are interested in.
+ ///
+ /// \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.
+ void
+ FindExternalLexicalDecls(const DeclContext *DC,
+ llvm::function_ref<bool(Decl::Kind)> IsKindWeWant,
+ SmallVectorImpl<Decl *> &Decls) override;
+
+ /// \brief Get the decls that are contained in a file in the Offset/Length
+ /// range. \p Length can be 0 to indicate a point at \p Offset instead of
+ /// a range.
+ void FindFileRegionDecls(FileID File, unsigned Offset, unsigned Length,
+ SmallVectorImpl<Decl *> &Decls) override;
+
+ /// \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.
+ void StartedDeserializing() override;
+
+ /// \brief Notify ASTReader that we finished the deserialization of
+ /// a decl or type. Must be paired with StartedDeserializing.
+ void FinishedDeserializing() override;
+
+ /// \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.
+ void StartTranslationUnit(ASTConsumer *Consumer) override;
+
+ /// \brief Print some statistics about AST usage.
+ void PrintStats() override;
+
+ /// \brief Dump information about the AST reader to standard error.
+ void dump();
+
+ /// Return the amount of memory used by memory buffers, breaking down
+ /// by heap-backed versus mmap'ed memory.
+ void getMemoryBufferSizes(MemoryBufferSizes &sizes) const override;
+
+ /// \brief Initialize the semantic source with the Sema instance
+ /// being used to perform semantic analysis on the abstract syntax
+ /// tree.
+ void InitializeSema(Sema &S) override;
+
+ /// \brief Inform the semantic consumer that Sema is no longer available.
+ void ForgetSema() override { SemaObj = nullptr; }
+
+ /// \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.
+ IdentifierInfo *get(StringRef Name) override;
+
+ /// \brief Retrieve an iterator into the set of all identifiers
+ /// in all loaded AST files.
+ IdentifierIterator *getIdentifiers() override;
+
+ /// \brief Load the contents of the global method pool for a given
+ /// selector.
+ void ReadMethodPool(Selector Sel) override;
+
+ /// \brief Load the set of namespaces that are known to the external source,
+ /// which will be used during typo correction.
+ void ReadKnownNamespaces(
+ SmallVectorImpl<NamespaceDecl *> &Namespaces) override;
+
+ void ReadUndefinedButUsed(
+ llvm::DenseMap<NamedDecl *, SourceLocation> &Undefined) override;
+
+ void ReadMismatchingDeleteExpressions(llvm::MapVector<
+ FieldDecl *, llvm::SmallVector<std::pair<SourceLocation, bool>, 4>> &
+ Exprs) override;
+
+ void ReadTentativeDefinitions(
+ SmallVectorImpl<VarDecl *> &TentativeDefs) override;
+
+ void ReadUnusedFileScopedDecls(
+ SmallVectorImpl<const DeclaratorDecl *> &Decls) override;
+
+ void ReadDelegatingConstructors(
+ SmallVectorImpl<CXXConstructorDecl *> &Decls) override;
+
+ void ReadExtVectorDecls(SmallVectorImpl<TypedefNameDecl *> &Decls) override;
+
+ void ReadUnusedLocalTypedefNameCandidates(
+ llvm::SmallSetVector<const TypedefNameDecl *, 4> &Decls) override;
+
+ void ReadReferencedSelectors(
+ SmallVectorImpl<std::pair<Selector, SourceLocation> > &Sels) override;
+
+ void ReadWeakUndeclaredIdentifiers(
+ SmallVectorImpl<std::pair<IdentifierInfo *, WeakInfo> > &WI) override;
+
+ void ReadUsedVTables(SmallVectorImpl<ExternalVTableUse> &VTables) override;
+
+ void ReadPendingInstantiations(
+ SmallVectorImpl<std::pair<ValueDecl *,
+ SourceLocation> > &Pending) override;
+
+ void ReadLateParsedTemplates(
+ llvm::MapVector<const FunctionDecl *, LateParsedTemplate *> &LPTMap)
+ override;
+
+ /// \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 SmallVectorImpl<uint32_t> &DeclIDs,
+ SmallVectorImpl<Decl *> *Decls = nullptr);
+
+ /// \brief Report a diagnostic.
+ DiagnosticBuilder Diag(unsigned DiagID);
+
+ /// \brief Report a diagnostic.
+ DiagnosticBuilder Diag(SourceLocation Loc, unsigned DiagID);
+
+ IdentifierInfo *DecodeIdentifierInfo(serialization::IdentifierID ID);
+
+ IdentifierInfo *GetIdentifierInfo(ModuleFile &M, const RecordData &Record,
+ unsigned &Idx) {
+ return DecodeIdentifierInfo(getGlobalIdentifierID(M, Record[Idx++]));
+ }
+
+ IdentifierInfo *GetIdentifier(serialization::IdentifierID ID) override {
+ // Note that we are loading an identifier.
+ Deserializing AnIdentifier(this);
+
+ return DecodeIdentifierInfo(ID);
+ }
+
+ IdentifierInfo *getLocalIdentifier(ModuleFile &M, unsigned LocalID);
+
+ serialization::IdentifierID getGlobalIdentifierID(ModuleFile &M,
+ unsigned LocalID);
+
+ void resolvePendingMacro(IdentifierInfo *II, const PendingMacroInfo &PMInfo);
+
+ /// \brief Retrieve the macro with the given ID.
+ MacroInfo *getMacro(serialization::MacroID ID);
+
+ /// \brief Retrieve the global macro ID corresponding to the given local
+ /// ID within the given module file.
+ serialization::MacroID getGlobalMacroID(ModuleFile &M, unsigned LocalID);
+
+ /// \brief Read the source location entry with index ID.
+ bool ReadSLocEntry(int ID) override;
+
+ /// \brief Retrieve the module import location and module name for the
+ /// given source manager entry ID.
+ std::pair<SourceLocation, StringRef> getModuleImportLoc(int ID) override;
+
+ /// \brief Retrieve the global submodule ID given a module and its local ID
+ /// number.
+ serialization::SubmoduleID
+ getGlobalSubmoduleID(ModuleFile &M, unsigned LocalID);
+
+ /// \brief Retrieve the submodule that corresponds to a global submodule ID.
+ ///
+ Module *getSubmodule(serialization::SubmoduleID GlobalID);
+
+ /// \brief Retrieve the module that corresponds to the given module ID.
+ ///
+ /// Note: overrides method in ExternalASTSource
+ Module *getModule(unsigned ID) override;
+
+ /// \brief Retrieve the module file with a given local ID within the specified
+ /// ModuleFile.
+ ModuleFile *getLocalModuleFile(ModuleFile &M, unsigned ID);
+
+ /// \brief Get an ID for the given module file.
+ unsigned getModuleFileID(ModuleFile *M);
+
+ /// \brief Return a descriptor for the corresponding module.
+ llvm::Optional<ASTSourceDescriptor> getSourceDescriptor(unsigned ID) override;
+
+ /// \brief Retrieve a selector from the given module with its local ID
+ /// number.
+ Selector getLocalSelector(ModuleFile &M, unsigned LocalID);
+
+ Selector DecodeSelector(serialization::SelectorID Idx);
+
+ Selector GetExternalSelector(serialization::SelectorID ID) override;
+ uint32_t GetNumExternalSelectors() override;
+
+ Selector ReadSelector(ModuleFile &M, const RecordData &Record, unsigned &Idx) {
+ return getLocalSelector(M, Record[Idx++]);
+ }
+
+ /// \brief Retrieve the global selector ID that corresponds to this
+ /// the local selector ID in a given module.
+ serialization::SelectorID getGlobalSelectorID(ModuleFile &F,
+ unsigned LocalID) const;
+
+ /// \brief Read a declaration name.
+ DeclarationName ReadDeclarationName(ModuleFile &F,
+ const RecordData &Record, unsigned &Idx);
+ void ReadDeclarationNameLoc(ModuleFile &F,
+ DeclarationNameLoc &DNLoc, DeclarationName Name,
+ const RecordData &Record, unsigned &Idx);
+ void ReadDeclarationNameInfo(ModuleFile &F, DeclarationNameInfo &NameInfo,
+ const RecordData &Record, unsigned &Idx);
+
+ void ReadQualifierInfo(ModuleFile &F, QualifierInfo &Info,
+ const RecordData &Record, unsigned &Idx);
+
+ NestedNameSpecifier *ReadNestedNameSpecifier(ModuleFile &F,
+ const RecordData &Record,
+ unsigned &Idx);
+
+ NestedNameSpecifierLoc ReadNestedNameSpecifierLoc(ModuleFile &F,
+ const RecordData &Record,
+ unsigned &Idx);
+
+ /// \brief Read a template name.
+ TemplateName ReadTemplateName(ModuleFile &F, const RecordData &Record,
+ unsigned &Idx);
+
+ /// \brief Read a template argument.
+ TemplateArgument ReadTemplateArgument(ModuleFile &F, const RecordData &Record,
+ unsigned &Idx,
+ bool Canonicalize = false);
+
+ /// \brief Read a template parameter list.
+ TemplateParameterList *ReadTemplateParameterList(ModuleFile &F,
+ const RecordData &Record,
+ unsigned &Idx);
+
+ /// \brief Read a template argument array.
+ void ReadTemplateArgumentList(SmallVectorImpl<TemplateArgument> &TemplArgs,
+ ModuleFile &F, const RecordData &Record,
+ unsigned &Idx, bool Canonicalize = false);
+
+ /// \brief Read a UnresolvedSet structure.
+ void ReadUnresolvedSet(ModuleFile &F, LazyASTUnresolvedSet &Set,
+ const RecordData &Record, unsigned &Idx);
+
+ /// \brief Read a C++ base specifier.
+ CXXBaseSpecifier ReadCXXBaseSpecifier(ModuleFile &F,
+ const RecordData &Record,unsigned &Idx);
+
+ /// \brief Read a CXXCtorInitializer array.
+ CXXCtorInitializer **
+ ReadCXXCtorInitializers(ModuleFile &F, const RecordData &Record,
+ unsigned &Idx);
+
+ /// \brief Read a CXXCtorInitializers ID from the given record and
+ /// return its global bit offset.
+ uint64_t ReadCXXCtorInitializersRef(ModuleFile &M, const RecordData &Record,
+ unsigned &Idx);
+
+ /// \brief Read the contents of a CXXCtorInitializer array.
+ CXXCtorInitializer **GetExternalCXXCtorInitializers(uint64_t Offset) override;
+
+ /// \brief Read a source location from raw form.
+ SourceLocation ReadSourceLocation(ModuleFile &ModuleFile, unsigned Raw) const {
+ SourceLocation Loc = SourceLocation::getFromRawEncoding(Raw);
+ assert(ModuleFile.SLocRemap.find(Loc.getOffset()) != ModuleFile.SLocRemap.end() &&
+ "Cannot find offset to remap.");
+ int Remap = ModuleFile.SLocRemap.find(Loc.getOffset())->second;
+ return Loc.getLocWithOffset(Remap);
+ }
+
+ /// \brief Read a source location.
+ SourceLocation ReadSourceLocation(ModuleFile &ModuleFile,
+ const RecordDataImpl &Record,
+ unsigned &Idx) {
+ return ReadSourceLocation(ModuleFile, Record[Idx++]);
+ }
+
+ /// \brief Read a source range.
+ SourceRange ReadSourceRange(ModuleFile &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,
+ const llvm::fltSemantics &Sem, unsigned &Idx);
+
+ // \brief Read a string
+ static std::string ReadString(const RecordData &Record, unsigned &Idx);
+
+ // \brief Read a path
+ std::string ReadPath(ModuleFile &F, const RecordData &Record, unsigned &Idx);
+
+ /// \brief Read a version tuple.
+ static VersionTuple ReadVersionTuple(const RecordData &Record, unsigned &Idx);
+
+ CXXTemporary *ReadCXXTemporary(ModuleFile &F, const RecordData &Record,
+ unsigned &Idx);
+
+ /// \brief Reads attributes from the current stream position.
+ void ReadAttributes(ModuleFile &F, AttrVec &Attrs,
+ const RecordData &Record, unsigned &Idx);
+
+ /// \brief Reads a statement.
+ Stmt *ReadStmt(ModuleFile &F);
+
+ /// \brief Reads an expression.
+ Expr *ReadExpr(ModuleFile &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 a token out of a record.
+ Token ReadToken(ModuleFile &M, const RecordDataImpl &Record, unsigned &Idx);
+
+ /// \brief Reads the macro record located at the given offset.
+ MacroInfo *ReadMacroRecord(ModuleFile &F, uint64_t Offset);
+
+ /// \brief Determine the global preprocessed entity ID that corresponds to
+ /// the given local ID within the given module.
+ serialization::PreprocessedEntityID
+ getGlobalPreprocessedEntityID(ModuleFile &M, unsigned LocalID) const;
+
+ /// \brief Add a macro to deserialize its macro directive history.
+ ///
+ /// \param II The name of the macro.
+ /// \param M The module file.
+ /// \param MacroDirectivesOffset Offset of the serialized macro directive
+ /// history.
+ void addPendingMacro(IdentifierInfo *II, ModuleFile *M,
+ uint64_t MacroDirectivesOffset);
+
+ /// \brief Read the set of macros defined by this external macro source.
+ void ReadDefinedMacros() override;
+
+ /// \brief Update an out-of-date identifier.
+ void updateOutOfDateIdentifier(IdentifierInfo &II) override;
+
+ /// \brief Note that this identifier is up-to-date.
+ void markIdentifierUpToDate(IdentifierInfo *II);
+
+ /// \brief Load all external visible decls in the given DeclContext.
+ void completeVisibleDeclsMap(const DeclContext *DC) override;
+
+ /// \brief Retrieve the AST context that this AST reader supplements.
+ ASTContext &getContext() { return Context; }
+
+ // \brief Contains the IDs for declarations that were requested before we have
+ // access to a Sema object.
+ SmallVector<uint64_t, 16> PreloadedDeclIDs;
+
+ /// \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 Cursors for comments blocks.
+ SmallVector<std::pair<llvm::BitstreamCursor,
+ serialization::ModuleFile *>, 8> CommentsCursors;
+
+ /// \brief Loads comments ranges.
+ void ReadComments() override;
+};
+
+/// \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/ASTWriter.h b/contrib/llvm/tools/clang/include/clang/Serialization/ASTWriter.h
new file mode 100644
index 0000000..ed34547
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Serialization/ASTWriter.h
@@ -0,0 +1,920 @@
+//===--- 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_SERIALIZATION_ASTWRITER_H
+#define LLVM_CLANG_SERIALIZATION_ASTWRITER_H
+
+#include "clang/AST/ASTMutationListener.h"
+#include "clang/AST/Decl.h"
+#include "clang/AST/DeclarationName.h"
+#include "clang/Frontend/PCHContainerOperations.h"
+#include "clang/AST/TemplateBase.h"
+#include "clang/Sema/SemaConsumer.h"
+#include "clang/Serialization/ASTBitCodes.h"
+#include "clang/Serialization/ASTDeserializationListener.h"
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/DenseSet.h"
+#include "llvm/ADT/MapVector.h"
+#include "llvm/ADT/SetVector.h"
+#include "llvm/ADT/SmallPtrSet.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/Bitcode/BitstreamWriter.h"
+#include <map>
+#include <queue>
+#include <vector>
+
+namespace llvm {
+ class APFloat;
+ class APInt;
+ class BitstreamWriter;
+}
+
+namespace clang {
+
+class ASTContext;
+class Attr;
+class NestedNameSpecifier;
+class CXXBaseSpecifier;
+class CXXCtorInitializer;
+class FileEntry;
+class FPOptions;
+class HeaderSearch;
+class HeaderSearchOptions;
+class IdentifierResolver;
+class MacroDefinitionRecord;
+class MacroDirective;
+class MacroInfo;
+class OpaqueValueExpr;
+class OpenCLOptions;
+class ASTReader;
+class Module;
+class ModuleFileExtension;
+class ModuleFileExtensionWriter;
+class PreprocessedEntity;
+class PreprocessingRecord;
+class Preprocessor;
+class RecordDecl;
+class Sema;
+class SourceManager;
+struct StoredDeclsList;
+class SwitchCase;
+class TargetInfo;
+class Token;
+class VersionTuple;
+class ASTUnresolvedSet;
+
+namespace SrcMgr { class SLocEntry; }
+
+/// \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 SmallVector<uint64_t, 64> RecordData;
+ typedef SmallVectorImpl<uint64_t> RecordDataImpl;
+ typedef ArrayRef<uint64_t> RecordDataRef;
+
+ friend class ASTDeclWriter;
+ friend class ASTStmtWriter;
+private:
+ /// \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, serialization::TypeIdx,
+ serialization::UnsafeQualTypeDenseMapInfo>
+ TypeIdxMap;
+
+ /// \brief The bitstream writer used to emit this precompiled header.
+ llvm::BitstreamWriter &Stream;
+
+ /// \brief The ASTContext we're writing.
+ ASTContext *Context;
+
+ /// \brief The preprocessor we're writing.
+ Preprocessor *PP;
+
+ /// \brief The reader of existing AST files, if we're chaining.
+ ASTReader *Chain;
+
+ /// \brief The module we're currently writing, if any.
+ Module *WritingModule;
+
+ /// \brief The base directory for any relative paths we emit.
+ std::string BaseDirectory;
+
+ /// \brief Indicates whether timestamps should be written to the produced
+ /// module file. This is the case for files implicitly written to the
+ /// module cache, where we need the timestamps to determine if the module
+ /// file is up to date, but not otherwise.
+ bool IncludeTimestamps;
+
+ /// \brief Indicates when the AST writing is actively performing
+ /// serialization, rather than just queueing updates.
+ bool WritingAST;
+
+ /// \brief Indicates that we are done serializing the collection of decls
+ /// and types to emit.
+ bool DoneWritingDeclsAndTypes;
+
+ /// \brief Indicates that the AST contained compiler errors.
+ bool ASTHasCompilerErrors;
+
+ /// \brief Mapping from input file entries to the index into the
+ /// offset table where information about that input file is stored.
+ llvm::DenseMap<const FileEntry *, uint32_t> InputFileIDs;
+
+ /// \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<serialization::DeclOffset> DeclOffsets;
+
+ /// \brief Sorted (by file offset) vector of pairs of file offset/DeclID.
+ typedef SmallVector<std::pair<unsigned, serialization::DeclID>, 64>
+ LocDeclIDsTy;
+ struct DeclIDInFileInfo {
+ LocDeclIDsTy DeclIDs;
+ /// \brief Set when the DeclIDs vectors from all files are joined, this
+ /// indicates the index that this particular vector has in the global one.
+ unsigned FirstDeclIndex;
+ };
+ typedef llvm::DenseMap<FileID, DeclIDInFileInfo *> FileDeclIDsTy;
+
+ /// \brief Map from file SLocEntries to info about the file-level declarations
+ /// that it contains.
+ FileDeclIDsTy FileDeclIDs;
+
+ void associateDeclWithFile(const Decl *D, serialization::DeclID);
+
+ /// \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.
+ 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::MapVector<const IdentifierInfo *, serialization::IdentID> IdentifierIDs;
+
+ /// \brief The first ID number we can use for our own macros.
+ serialization::MacroID FirstMacroID;
+
+ /// \brief The identifier ID that will be assigned to the next new identifier.
+ serialization::MacroID NextMacroID;
+
+ /// \brief Map that provides the ID numbers of each macro.
+ llvm::DenseMap<MacroInfo *, serialization::MacroID> MacroIDs;
+
+ struct MacroInfoToEmitData {
+ const IdentifierInfo *Name;
+ MacroInfo *MI;
+ serialization::MacroID ID;
+ };
+ /// \brief The macro infos to emit.
+ std::vector<MacroInfoToEmitData> MacroInfosToEmit;
+
+ llvm::DenseMap<const IdentifierInfo *, uint64_t> IdentMacroDirectivesOffsetMap;
+
+ /// @name FlushStmt Caches
+ /// @{
+
+ /// \brief Set of parent Stmts for the currently serializing sub-stmt.
+ llvm::DenseSet<Stmt *> ParentStmts;
+
+ /// \brief Offsets of sub-stmts already serialized. The offset points
+ /// just after the stmt record.
+ llvm::DenseMap<Stmt *, uint64_t> SubStmtEntries;
+
+ /// @}
+
+ /// \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 submodules.
+ serialization::SubmoduleID FirstSubmoduleID;
+
+ /// \brief The submodule ID that will be assigned to the next new submodule.
+ serialization::SubmoduleID NextSubmoduleID;
+
+ /// \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 selector.
+ serialization::SelectorID NextSelectorID;
+
+ /// \brief Map that provides the ID numbers of each Selector.
+ llvm::MapVector<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 Mapping from macro definitions (as they occur in the preprocessing
+ /// record) to the macro IDs.
+ llvm::DenseMap<const MacroDefinitionRecord *,
+ serialization::PreprocessedEntityID> MacroDefinitions;
+
+ /// \brief Cache of indices of anonymous declarations within their lexical
+ /// contexts.
+ llvm::DenseMap<const Decl *, unsigned> AnonymousDeclarationNumbers;
+
+ /// An update to a Decl.
+ class DeclUpdate {
+ /// A DeclUpdateKind.
+ unsigned Kind;
+ union {
+ const Decl *Dcl;
+ void *Type;
+ unsigned Loc;
+ unsigned Val;
+ Module *Mod;
+ const Attr *Attribute;
+ };
+
+ public:
+ DeclUpdate(unsigned Kind) : Kind(Kind), Dcl(nullptr) {}
+ DeclUpdate(unsigned Kind, const Decl *Dcl) : Kind(Kind), Dcl(Dcl) {}
+ DeclUpdate(unsigned Kind, QualType Type)
+ : Kind(Kind), Type(Type.getAsOpaquePtr()) {}
+ DeclUpdate(unsigned Kind, SourceLocation Loc)
+ : Kind(Kind), Loc(Loc.getRawEncoding()) {}
+ DeclUpdate(unsigned Kind, unsigned Val)
+ : Kind(Kind), Val(Val) {}
+ DeclUpdate(unsigned Kind, Module *M)
+ : Kind(Kind), Mod(M) {}
+ DeclUpdate(unsigned Kind, const Attr *Attribute)
+ : Kind(Kind), Attribute(Attribute) {}
+
+ unsigned getKind() const { return Kind; }
+ const Decl *getDecl() const { return Dcl; }
+ QualType getType() const { return QualType::getFromOpaquePtr(Type); }
+ SourceLocation getLoc() const {
+ return SourceLocation::getFromRawEncoding(Loc);
+ }
+ unsigned getNumber() const { return Val; }
+ Module *getModule() const { return Mod; }
+ const Attr *getAttr() const { return Attribute; }
+ };
+
+ typedef SmallVector<DeclUpdate, 1> UpdateRecord;
+ typedef llvm::MapVector<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 and other 'interesting' declarations
+ /// as we are emitting declarations to the AST file. The AST file contains a
+ /// separate record for these declarations, 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 EAGERLY_DESERIALIZED_DECLS
+ /// record.
+ SmallVector<uint64_t, 16> EagerlyDeserializedDecls;
+
+ /// \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::SmallSetVector<const DeclContext *, 16> UpdatedDeclContexts;
+
+ /// \brief Keeps track of visible decls that were added in DeclContexts
+ /// coming from another AST file.
+ SmallVector<const Decl *, 16> UpdatingVisibleDecls;
+
+ /// \brief The set of Objective-C class that have categories we
+ /// should serialize.
+ llvm::SetVector<ObjCInterfaceDecl *> ObjCClassesWithCategories;
+
+ struct ReplacedDeclInfo {
+ serialization::DeclID ID;
+ uint64_t Offset;
+ unsigned Loc;
+
+ ReplacedDeclInfo() : ID(0), Offset(0), Loc(0) {}
+ ReplacedDeclInfo(serialization::DeclID ID, uint64_t Offset,
+ SourceLocation Loc)
+ : ID(ID), Offset(Offset), Loc(Loc.getRawEncoding()) {}
+ };
+
+ /// \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.
+ SmallVector<ReplacedDeclInfo, 16> ReplacedDecls;
+
+ /// \brief The set of declarations that may have redeclaration chains that
+ /// need to be serialized.
+ llvm::SmallVector<const Decl *, 16> Redeclarations;
+
+ /// \brief A cache of the first local declaration for "interesting"
+ /// redeclaration chains.
+ llvm::DenseMap<const Decl *, const Decl *> FirstLocalDeclCache;
+
+ /// \brief Statements that we've encountered while serializing a
+ /// declaration or type.
+ SmallVector<Stmt *, 16> StmtsToEmit;
+
+ /// \brief Statements collection to use for ASTWriter::AddStmt().
+ /// It will point to StmtsToEmit unless it is overriden.
+ SmallVector<Stmt *, 16> *CollectedStmts;
+
+ /// \brief Mapping from SwitchCase statements to IDs.
+ llvm::DenseMap<SwitchCase *, unsigned> SwitchCaseIDs;
+
+ /// \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.
+ SmallVector<uint32_t, 16> 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.
+ SmallVector<QueuedCXXBaseSpecifiers, 2> CXXBaseSpecifiersToWrite;
+
+ /// \brief The offset of each CXXCtorInitializer list within the AST.
+ SmallVector<uint32_t, 16> CXXCtorInitializersOffsets;
+
+ /// \brief The first ID number we can use for our own ctor initializers.
+ serialization::CXXCtorInitializersID FirstCXXCtorInitializersID;
+
+ /// \brief The ctor initializers ID that will be assigned to the next new
+ /// list of C++ ctor initializers.
+ serialization::CXXCtorInitializersID NextCXXCtorInitializersID;
+
+ /// \brief A set of C++ ctor initializers that is queued to be written
+ /// into the AST file.
+ struct QueuedCXXCtorInitializers {
+ QueuedCXXCtorInitializers() : ID() {}
+
+ QueuedCXXCtorInitializers(serialization::CXXCtorInitializersID ID,
+ ArrayRef<CXXCtorInitializer*> Inits)
+ : ID(ID), Inits(Inits) {}
+
+ serialization::CXXCtorInitializersID ID;
+ ArrayRef<CXXCtorInitializer*> Inits;
+ };
+
+ /// \brief Queue of C++ ctor initializers to be written to the AST file,
+ /// in the order they should be written.
+ SmallVector<QueuedCXXCtorInitializers, 2> CXXCtorInitializersToWrite;
+
+ /// \brief A mapping from each known submodule to its ID number, which will
+ /// be a positive integer.
+ llvm::DenseMap<Module *, unsigned> SubmoduleIDs;
+
+ /// \brief A list of the module file extension writers.
+ std::vector<std::unique_ptr<ModuleFileExtensionWriter>>
+ ModuleFileExtensionWriters;
+
+ /// \brief Retrieve or create a submodule ID for this module.
+ unsigned getSubmoduleID(Module *Mod);
+
+ /// \brief Write the given subexpression to the bitstream.
+ void WriteSubStmt(Stmt *S,
+ llvm::DenseMap<Stmt *, uint64_t> &SubStmtEntries,
+ llvm::DenseSet<Stmt *> &ParentStmts);
+
+ void WriteBlockInfoBlock();
+ uint64_t WriteControlBlock(Preprocessor &PP, ASTContext &Context,
+ StringRef isysroot, const std::string &OutputFile);
+ void WriteInputFiles(SourceManager &SourceMgr, HeaderSearchOptions &HSOpts,
+ bool Modules);
+ void WriteSourceManagerBlock(SourceManager &SourceMgr,
+ const Preprocessor &PP);
+ void WritePreprocessor(const Preprocessor &PP, bool IsModule);
+ void WriteHeaderSearch(const HeaderSearch &HS);
+ void WritePreprocessorDetail(PreprocessingRecord &PPRec);
+ void WriteSubmodules(Module *WritingModule);
+
+ void WritePragmaDiagnosticMappings(const DiagnosticsEngine &Diag,
+ bool isModule);
+ void WriteCXXBaseSpecifiersOffsets();
+ void WriteCXXCtorInitializersOffsets();
+
+ unsigned TypeExtQualAbbrev;
+ unsigned TypeFunctionProtoAbbrev;
+ void WriteTypeAbbrevs();
+ void WriteType(QualType T);
+
+ bool isLookupResultExternal(StoredDeclsList &Result, DeclContext *DC);
+ bool isLookupResultEntirelyExternal(StoredDeclsList &Result, DeclContext *DC);
+
+ void GenerateNameLookupTable(const DeclContext *DC,
+ llvm::SmallVectorImpl<char> &LookupTable);
+ uint64_t WriteDeclContextLexicalBlock(ASTContext &Context, DeclContext *DC);
+ uint64_t WriteDeclContextVisibleBlock(ASTContext &Context, DeclContext *DC);
+ void WriteTypeDeclOffsets();
+ void WriteFileDeclIDsMap();
+ void WriteComments();
+ void WriteSelectors(Sema &SemaRef);
+ void WriteReferencedSelectorsPool(Sema &SemaRef);
+ void WriteIdentifierTable(Preprocessor &PP, IdentifierResolver &IdResolver,
+ bool IsModule);
+ void WriteAttributes(ArrayRef<const Attr*> Attrs, RecordDataImpl &Record);
+ void WriteDeclUpdatesBlocks(RecordDataImpl &OffsetsRecord);
+ void WriteDeclReplacementsBlock();
+ void WriteDeclContextVisibleUpdate(const DeclContext *DC);
+ void WriteFPPragmaOptions(const FPOptions &Opts);
+ void WriteOpenCLExtensions(Sema &SemaRef);
+ void WriteObjCCategories();
+ void WriteLateParsedTemplates(Sema &SemaRef);
+ void WriteOptimizePragmaOptions(Sema &SemaRef);
+ void WriteModuleFileExtension(Sema &SemaRef,
+ ModuleFileExtensionWriter &Writer);
+
+ unsigned DeclParmVarAbbrev;
+ unsigned DeclContextLexicalAbbrev;
+ unsigned DeclContextVisibleLookupAbbrev;
+ unsigned UpdateVisibleAbbrev;
+ unsigned DeclRecordAbbrev;
+ unsigned DeclTypedefAbbrev;
+ unsigned DeclVarAbbrev;
+ unsigned DeclFieldAbbrev;
+ unsigned DeclEnumAbbrev;
+ unsigned DeclObjCIvarAbbrev;
+ unsigned DeclCXXMethodAbbrev;
+
+ unsigned DeclRefExprAbbrev;
+ unsigned CharacterLiteralAbbrev;
+ unsigned IntegerLiteralAbbrev;
+ unsigned ExprImplicitCastAbbrev;
+
+ void WriteDeclAbbrevs();
+ void WriteDecl(ASTContext &Context, Decl *D);
+ void AddFunctionDefinition(const FunctionDecl *FD, RecordData &Record);
+
+ uint64_t WriteASTCore(Sema &SemaRef,
+ StringRef isysroot, const std::string &OutputFile,
+ Module *WritingModule);
+
+public:
+ /// \brief Create a new precompiled header writer that outputs to
+ /// the given bitstream.
+ ASTWriter(llvm::BitstreamWriter &Stream,
+ ArrayRef<llvm::IntrusiveRefCntPtr<ModuleFileExtension>> Extensions,
+ bool IncludeTimestamps = true);
+ ~ASTWriter() override;
+
+ const LangOptions &getLangOpts() const;
+
+ /// \brief Get a timestamp for output into the AST file. The actual timestamp
+ /// of the specified file may be ignored if we have been instructed to not
+ /// include timestamps in the output file.
+ time_t getTimestampForOutput(const FileEntry *E) const;
+
+ /// \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 WritingModule The module that we are writing. If null, we are
+ /// writing a precompiled header.
+ ///
+ /// \param isysroot if non-empty, write a relocatable file whose headers
+ /// are relative to the given system root. If we're writing a module, its
+ /// build directory will be used in preference to this if both are available.
+ ///
+ /// \return the module signature, which eventually will be a hash of
+ /// the module but currently is merely a random 32-bit number.
+ uint64_t WriteAST(Sema &SemaRef, const std::string &OutputFile,
+ Module *WritingModule, StringRef isysroot,
+ bool hasErrors = false);
+
+ /// \brief Emit a token.
+ void AddToken(const Token &Tok, RecordDataImpl &Record);
+
+ /// \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 Get the unique number used to refer to the given macro.
+ serialization::MacroID getMacroRef(MacroInfo *MI, const IdentifierInfo *Name);
+
+ /// \brief Determine the ID of an already-emitted macro.
+ serialization::MacroID getMacroID(MacroInfo *MI);
+
+ uint64_t getMacroDirectivesOffset(const IdentifierInfo *Name);
+
+ /// \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 Emits a reference to a declarator info.
+ void AddTypeSourceInfo(TypeSourceInfo *TInfo, RecordDataImpl &Record);
+
+ /// \brief Emits a type with source-location information.
+ void AddTypeLoc(TypeLoc TL, 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 Emits an AST template argument list info.
+ void AddASTTemplateArgumentListInfo(
+ const ASTTemplateArgumentListInfo *ASTTemplArgList,
+ RecordDataImpl &Record);
+
+ /// \brief Find the first local declaration of a given local redeclarable
+ /// decl.
+ const Decl *getFirstLocalDecl(const Decl *D);
+
+ /// \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);
+ unsigned getAnonymousDeclarationNumber(const NamedDecl *D);
+
+ void AddQualifierInfo(const QualifierInfo &Info, RecordDataImpl &Record);
+
+ /// \brief Emit a nested name specifier.
+ void AddNestedNameSpecifier(NestedNameSpecifier *NNS, RecordDataImpl &Record);
+
+ /// \brief Emit a nested name specifier with source-location information.
+ void AddNestedNameSpecifierLoc(NestedNameSpecifierLoc 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 ASTUnresolvedSet &Set, RecordDataImpl &Record);
+
+ /// \brief Emit a C++ base specifier.
+ void AddCXXBaseSpecifier(const CXXBaseSpecifier &Base,
+ RecordDataImpl &Record);
+
+ /// \brief Emit the ID for a CXXCtorInitializer array and register the array
+ /// for later serialization.
+ void AddCXXCtorInitializersRef(ArrayRef<CXXCtorInitializer *> Inits,
+ 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(StringRef Str, RecordDataImpl &Record);
+
+ /// \brief Convert a path from this build process into one that is appropriate
+ /// for emission in the module file.
+ bool PreparePathForOutput(SmallVectorImpl<char> &Path);
+
+ /// \brief Add a path to the given record.
+ void AddPath(StringRef Path, RecordDataImpl &Record);
+
+ /// \brief Emit the current record with the given path as a blob.
+ void EmitRecordWithPath(unsigned Abbrev, RecordDataRef Record,
+ StringRef Path);
+
+ /// \brief Add a version tuple to the given record
+ void AddVersionTuple(const VersionTuple &Version, RecordDataImpl &Record);
+
+ /// \brief Infer the submodule ID that contains an entity at the given
+ /// source location.
+ serialization::SubmoduleID inferSubmoduleIDFromLocation(SourceLocation Loc);
+
+ /// \brief Retrieve or create a submodule ID for this module, or return 0 if
+ /// the submodule is neither local (a submodle of the currently-written module)
+ /// nor from an imported module.
+ unsigned getLocalOrImportedSubmoduleID(Module *Mod);
+
+ /// \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 Flush all of the C++ constructor initializer lists that have been
+ /// added via \c AddCXXCtorInitializersRef().
+ void FlushCXXCtorInitializers();
+
+ /// \brief Flush all pending records that are tacked onto the end of
+ /// decl and decl update records.
+ void FlushPendingAfterDecl() {
+ FlushStmts();
+ FlushCXXBaseSpecifiers();
+ FlushCXXCtorInitializers();
+ }
+
+ /// \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();
+
+ unsigned getTypeExtQualAbbrev() const {
+ return TypeExtQualAbbrev;
+ }
+ unsigned getTypeFunctionProtoAbbrev() const {
+ return TypeFunctionProtoAbbrev;
+ }
+
+ unsigned getDeclParmVarAbbrev() const { return DeclParmVarAbbrev; }
+ unsigned getDeclRecordAbbrev() const { return DeclRecordAbbrev; }
+ unsigned getDeclTypedefAbbrev() const { return DeclTypedefAbbrev; }
+ unsigned getDeclVarAbbrev() const { return DeclVarAbbrev; }
+ unsigned getDeclFieldAbbrev() const { return DeclFieldAbbrev; }
+ unsigned getDeclEnumAbbrev() const { return DeclEnumAbbrev; }
+ unsigned getDeclObjCIvarAbbrev() const { return DeclObjCIvarAbbrev; }
+ unsigned getDeclCXXMethodAbbrev() const { return DeclCXXMethodAbbrev; }
+
+ unsigned getDeclRefExprAbbrev() const { return DeclRefExprAbbrev; }
+ unsigned getCharacterLiteralAbbrev() const { return CharacterLiteralAbbrev; }
+ unsigned getIntegerLiteralAbbrev() const { return IntegerLiteralAbbrev; }
+ unsigned getExprImplicitCastAbbrev() const { return ExprImplicitCastAbbrev; }
+
+ bool hasChain() const { return Chain; }
+ ASTReader *getChain() const { return Chain; }
+
+ // ASTDeserializationListener implementation
+ void ReaderInitialized(ASTReader *Reader) override;
+ void IdentifierRead(serialization::IdentID ID, IdentifierInfo *II) override;
+ void MacroRead(serialization::MacroID ID, MacroInfo *MI) override;
+ void TypeRead(serialization::TypeIdx Idx, QualType T) override;
+ void SelectorRead(serialization::SelectorID ID, Selector Sel) override;
+ void MacroDefinitionRead(serialization::PreprocessedEntityID ID,
+ MacroDefinitionRecord *MD) override;
+ void ModuleRead(serialization::SubmoduleID ID, Module *Mod) override;
+
+ // ASTMutationListener implementation.
+ void CompletedTagDefinition(const TagDecl *D) override;
+ void AddedVisibleDecl(const DeclContext *DC, const Decl *D) override;
+ void AddedCXXImplicitMember(const CXXRecordDecl *RD, const Decl *D) override;
+ void ResolvedExceptionSpec(const FunctionDecl *FD) override;
+ void DeducedReturnType(const FunctionDecl *FD, QualType ReturnType) override;
+ void ResolvedOperatorDelete(const CXXDestructorDecl *DD,
+ const FunctionDecl *Delete) override;
+ void CompletedImplicitDefinition(const FunctionDecl *D) override;
+ void StaticDataMemberInstantiated(const VarDecl *D) override;
+ void FunctionDefinitionInstantiated(const FunctionDecl *D) override;
+ void AddedObjCCategoryToInterface(const ObjCCategoryDecl *CatD,
+ const ObjCInterfaceDecl *IFD) override;
+ void DeclarationMarkedUsed(const Decl *D) override;
+ void DeclarationMarkedOpenMPThreadPrivate(const Decl *D) override;
+ void RedefinedHiddenDefinition(const NamedDecl *D, Module *M) override;
+ void AddedAttributeToRecord(const Attr *Attr,
+ const RecordDecl *Record) override;
+};
+
+/// \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;
+ clang::Module *Module;
+ std::string isysroot;
+ Sema *SemaPtr;
+ std::shared_ptr<PCHBuffer> Buffer;
+ llvm::BitstreamWriter Stream;
+ ASTWriter Writer;
+ bool AllowASTWithErrors;
+
+protected:
+ ASTWriter &getWriter() { return Writer; }
+ const ASTWriter &getWriter() const { return Writer; }
+ SmallVectorImpl<char> &getPCH() const { return Buffer->Data; }
+
+public:
+ PCHGenerator(
+ const Preprocessor &PP, StringRef OutputFile,
+ clang::Module *Module, StringRef isysroot,
+ std::shared_ptr<PCHBuffer> Buffer,
+ ArrayRef<llvm::IntrusiveRefCntPtr<ModuleFileExtension>> Extensions,
+ bool AllowASTWithErrors = false,
+ bool IncludeTimestamps = true);
+ ~PCHGenerator() override;
+ void InitializeSema(Sema &S) override { SemaPtr = &S; }
+ void HandleTranslationUnit(ASTContext &Ctx) override;
+ ASTMutationListener *GetASTMutationListener() override;
+ ASTDeserializationListener *GetASTDeserializationListener() override;
+ bool hasEmittedPCH() const { return Buffer->IsComplete; }
+};
+
+} // end namespace clang
+
+#endif
diff --git a/contrib/llvm/tools/clang/include/clang/Serialization/ContinuousRangeMap.h b/contrib/llvm/tools/clang/include/clang/Serialization/ContinuousRangeMap.h
new file mode 100644
index 0000000..244b01b
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Serialization/ContinuousRangeMap.h
@@ -0,0 +1,139 @@
+//===--- ContinuousRangeMap.h - Map with int range as key -------*- C++ -*-===//
+//
+// 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 ContinuousRangeMap class, which is a highly
+// specialized container used by serialization.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_SERIALIZATION_CONTINUOUSRANGEMAP_H
+#define LLVM_CLANG_SERIALIZATION_CONTINUOUSRANGEMAP_H
+
+#include "clang/Basic/LLVM.h"
+#include "llvm/ADT/SmallVector.h"
+#include <algorithm>
+#include <utility>
+
+namespace clang {
+
+/// \brief A map from continuous integer ranges to some value, with a very
+/// specialized interface.
+///
+/// CRM maps from integer ranges to values. The ranges are continuous, i.e.
+/// where one ends, the next one begins. So if the map contains the stops I0-3,
+/// the first range is from I0 to I1, the second from I1 to I2, the third from
+/// I2 to I3 and the last from I3 to infinity.
+///
+/// Ranges must be inserted in order. Inserting a new stop I4 into the map will
+/// shrink the fourth range to I3 to I4 and add the new range I4 to inf.
+template <typename Int, typename V, unsigned InitialCapacity>
+class ContinuousRangeMap {
+public:
+ typedef std::pair<Int, V> value_type;
+ typedef value_type &reference;
+ typedef const value_type &const_reference;
+ typedef value_type *pointer;
+ typedef const value_type *const_pointer;
+
+private:
+ typedef SmallVector<value_type, InitialCapacity> Representation;
+ Representation Rep;
+
+ struct Compare {
+ bool operator ()(const_reference L, Int R) const {
+ return L.first < R;
+ }
+ bool operator ()(Int L, const_reference R) const {
+ return L < R.first;
+ }
+ bool operator ()(Int L, Int R) const {
+ return L < R;
+ }
+ bool operator ()(const_reference L, const_reference R) const {
+ return L.first < R.first;
+ }
+ };
+
+public:
+ void insert(const value_type &Val) {
+ if (!Rep.empty() && Rep.back() == Val)
+ return;
+
+ assert((Rep.empty() || Rep.back().first < Val.first) &&
+ "Must insert keys in order.");
+ Rep.push_back(Val);
+ }
+
+ void insertOrReplace(const value_type &Val) {
+ iterator I = std::lower_bound(Rep.begin(), Rep.end(), Val, Compare());
+ if (I != Rep.end() && I->first == Val.first) {
+ I->second = Val.second;
+ return;
+ }
+
+ Rep.insert(I, Val);
+ }
+
+ typedef typename Representation::iterator iterator;
+ typedef typename Representation::const_iterator const_iterator;
+
+ iterator begin() { return Rep.begin(); }
+ iterator end() { return Rep.end(); }
+ const_iterator begin() const { return Rep.begin(); }
+ const_iterator end() const { return Rep.end(); }
+
+ iterator find(Int K) {
+ iterator I = std::upper_bound(Rep.begin(), Rep.end(), K, Compare());
+ // I points to the first entry with a key > K, which is the range that
+ // follows the one containing K.
+ if (I == Rep.begin())
+ return Rep.end();
+ --I;
+ return I;
+ }
+ const_iterator find(Int K) const {
+ return const_cast<ContinuousRangeMap*>(this)->find(K);
+ }
+
+ reference back() { return Rep.back(); }
+ const_reference back() const { return Rep.back(); }
+
+ /// \brief An object that helps properly build a continuous range map
+ /// from a set of values.
+ class Builder {
+ ContinuousRangeMap &Self;
+
+ Builder(const Builder&) = delete;
+ Builder &operator=(const Builder&) = delete;
+
+ public:
+ explicit Builder(ContinuousRangeMap &Self) : Self(Self) { }
+
+ ~Builder() {
+ std::sort(Self.Rep.begin(), Self.Rep.end(), Compare());
+ std::unique(Self.Rep.begin(), Self.Rep.end(),
+ [](const_reference A, const_reference B) {
+ // FIXME: we should not allow any duplicate keys, but there are a lot of
+ // duplicate 0 -> 0 mappings to remove first.
+ assert((A == B || A.first != B.first) &&
+ "ContinuousRangeMap::Builder given non-unique keys");
+ return A == B;
+ });
+ }
+
+ void insert(const value_type &Val) {
+ Self.Rep.push_back(Val);
+ }
+ };
+ friend class Builder;
+};
+
+}
+
+#endif
diff --git a/contrib/llvm/tools/clang/include/clang/Serialization/GlobalModuleIndex.h b/contrib/llvm/tools/clang/include/clang/Serialization/GlobalModuleIndex.h
new file mode 100644
index 0000000..0f14eca
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Serialization/GlobalModuleIndex.h
@@ -0,0 +1,207 @@
+//===--- GlobalModuleIndex.h - Global Module Index --------------*- C++ -*-===//
+//
+// 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 GlobalModuleIndex class, which manages a global index
+// containing all of the identifiers known to the various modules within a given
+// subdirectory of the module cache. It is used to improve the performance of
+// queries such as "do any modules know about this identifier?"
+//
+//===----------------------------------------------------------------------===//
+#ifndef LLVM_CLANG_SERIALIZATION_GLOBALMODULEINDEX_H
+#define LLVM_CLANG_SERIALIZATION_GLOBALMODULEINDEX_H
+
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/SmallPtrSet.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/StringMap.h"
+#include "llvm/ADT/StringRef.h"
+#include <memory>
+#include <utility>
+
+namespace llvm {
+class BitstreamCursor;
+class MemoryBuffer;
+}
+
+namespace clang {
+
+class DirectoryEntry;
+class FileEntry;
+class FileManager;
+class IdentifierIterator;
+class PCHContainerOperations;
+class PCHContainerReader;
+
+namespace serialization {
+ class ModuleFile;
+}
+
+using llvm::SmallVector;
+using llvm::SmallVectorImpl;
+using llvm::StringRef;
+using serialization::ModuleFile;
+
+/// \brief A global index for a set of module files, providing information about
+/// the identifiers within those module files.
+///
+/// The global index is an aid for name lookup into modules, offering a central
+/// place where one can look for identifiers determine which
+/// module files contain any information about that identifier. This
+/// allows the client to restrict the search to only those module files known
+/// to have a information about that identifier, improving performance. Moreover,
+/// the global module index may know about module files that have not been
+/// imported, and can be queried to determine which modules the current
+/// translation could or should load to fix a problem.
+class GlobalModuleIndex {
+ /// \brief Buffer containing the index file, which is lazily accessed so long
+ /// as the global module index is live.
+ std::unique_ptr<llvm::MemoryBuffer> Buffer;
+
+ /// \brief The hash table.
+ ///
+ /// This pointer actually points to a IdentifierIndexTable object,
+ /// but that type is only accessible within the implementation of
+ /// GlobalModuleIndex.
+ void *IdentifierIndex;
+
+ /// \brief Information about a given module file.
+ struct ModuleInfo {
+ ModuleInfo() : File(), Size(), ModTime() { }
+
+ /// \brief The module file, once it has been resolved.
+ ModuleFile *File;
+
+ /// \brief The module file name.
+ std::string FileName;
+
+ /// \brief Size of the module file at the time the global index was built.
+ off_t Size;
+
+ /// \brief Modification time of the module file at the time the global
+ /// index was built.
+ time_t ModTime;
+
+ /// \brief The module IDs on which this module directly depends.
+ /// FIXME: We don't really need a vector here.
+ llvm::SmallVector<unsigned, 4> Dependencies;
+ };
+
+ /// \brief A mapping from module IDs to information about each module.
+ ///
+ /// This vector may have gaps, if module files have been removed or have
+ /// been updated since the index was built. A gap is indicated by an empty
+ /// file name.
+ llvm::SmallVector<ModuleInfo, 16> Modules;
+
+ /// \brief Lazily-populated mapping from module files to their
+ /// corresponding index into the \c Modules vector.
+ llvm::DenseMap<ModuleFile *, unsigned> ModulesByFile;
+
+ /// \brief The set of modules that have not yet been resolved.
+ ///
+ /// The string is just the name of the module itself, which maps to the
+ /// module ID.
+ llvm::StringMap<unsigned> UnresolvedModules;
+
+ /// \brief The number of identifier lookups we performed.
+ unsigned NumIdentifierLookups;
+
+ /// \brief The number of identifier lookup hits, where we recognize the
+ /// identifier.
+ unsigned NumIdentifierLookupHits;
+
+ /// \brief Internal constructor. Use \c readIndex() to read an index.
+ explicit GlobalModuleIndex(std::unique_ptr<llvm::MemoryBuffer> Buffer,
+ llvm::BitstreamCursor Cursor);
+
+ GlobalModuleIndex(const GlobalModuleIndex &) = delete;
+ GlobalModuleIndex &operator=(const GlobalModuleIndex &) = delete;
+
+public:
+ ~GlobalModuleIndex();
+
+ /// \brief An error code returned when trying to read an index.
+ enum ErrorCode {
+ /// \brief No error occurred.
+ EC_None,
+ /// \brief No index was found.
+ EC_NotFound,
+ /// \brief Some other process is currently building the index; it is not
+ /// available yet.
+ EC_Building,
+ /// \brief There was an unspecified I/O error reading or writing the index.
+ EC_IOError
+ };
+
+ /// \brief Read a global index file for the given directory.
+ ///
+ /// \param Path The path to the specific module cache where the module files
+ /// for the intended configuration reside.
+ ///
+ /// \returns A pair containing the global module index (if it exists) and
+ /// the error code.
+ static std::pair<GlobalModuleIndex *, ErrorCode>
+ readIndex(StringRef Path);
+
+ /// \brief Returns an iterator for identifiers stored in the index table.
+ ///
+ /// The caller accepts ownership of the returned object.
+ IdentifierIterator *createIdentifierIterator() const;
+
+ /// \brief Retrieve the set of modules that have up-to-date indexes.
+ ///
+ /// \param ModuleFiles Will be populated with the set of module files that
+ /// have been indexed.
+ void getKnownModules(SmallVectorImpl<ModuleFile *> &ModuleFiles);
+
+ /// \brief Retrieve the set of module files on which the given module file
+ /// directly depends.
+ void getModuleDependencies(ModuleFile *File,
+ SmallVectorImpl<ModuleFile *> &Dependencies);
+
+ /// \brief A set of module files in which we found a result.
+ typedef llvm::SmallPtrSet<ModuleFile *, 4> HitSet;
+
+ /// \brief Look for all of the module files with information about the given
+ /// identifier, e.g., a global function, variable, or type with that name.
+ ///
+ /// \param Name The identifier to look for.
+ ///
+ /// \param Hits Will be populated with the set of module files that have
+ /// information about this name.
+ ///
+ /// \returns true if the identifier is known to the index, false otherwise.
+ bool lookupIdentifier(StringRef Name, HitSet &Hits);
+
+ /// \brief Note that the given module file has been loaded.
+ ///
+ /// \returns false if the global module index has information about this
+ /// module file, and true otherwise.
+ bool loadedModuleFile(ModuleFile *File);
+
+ /// \brief Print statistics to standard error.
+ void printStats();
+
+ /// \brief Print debugging view to standard error.
+ void dump();
+
+ /// \brief Write a global index into the given
+ ///
+ /// \param FileMgr The file manager to use to load module files.
+ /// \param PCHContainerRdr - The PCHContainerOperations to use for loading and
+ /// creating modules.
+ /// \param Path The path to the directory containing module files, into
+ /// which the global index will be written.
+ static ErrorCode writeIndex(FileManager &FileMgr,
+ const PCHContainerReader &PCHContainerRdr,
+ StringRef Path);
+};
+}
+
+#endif
diff --git a/contrib/llvm/tools/clang/include/clang/Serialization/Module.h b/contrib/llvm/tools/clang/include/clang/Serialization/Module.h
new file mode 100644
index 0000000..d6d16a0
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Serialization/Module.h
@@ -0,0 +1,475 @@
+//===--- Module.h - Module description --------------------------*- C++ -*-===//
+//
+// 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 Module class, which describes a module that has
+// been loaded from an AST file.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_SERIALIZATION_MODULE_H
+#define LLVM_CLANG_SERIALIZATION_MODULE_H
+
+#include "clang/Basic/FileManager.h"
+#include "clang/Basic/SourceLocation.h"
+#include "clang/Serialization/ASTBitCodes.h"
+#include "clang/Serialization/ContinuousRangeMap.h"
+#include "clang/Serialization/ModuleFileExtension.h"
+#include "llvm/ADT/SetVector.h"
+#include "llvm/Bitcode/BitstreamReader.h"
+#include "llvm/Support/Endian.h"
+#include <memory>
+#include <string>
+
+namespace llvm {
+template <typename Info> class OnDiskChainedHashTable;
+template <typename Info> class OnDiskIterableChainedHashTable;
+}
+
+namespace clang {
+
+class DeclContext;
+class Module;
+
+namespace serialization {
+
+namespace reader {
+ class ASTDeclContextNameLookupTrait;
+}
+
+/// \brief Specifies the kind of module that has been loaded.
+enum ModuleKind {
+ MK_ImplicitModule, ///< File is an implicitly-loaded module.
+ MK_ExplicitModule, ///< File is an explicitly-loaded module.
+ MK_PCH, ///< File is a PCH file treated as such.
+ MK_Preamble, ///< File is a PCH file treated as the preamble.
+ MK_MainFile ///< File is a PCH file treated as the actual main file.
+};
+
+/// \brief The input file that has been loaded from this AST file, along with
+/// bools indicating whether this was an overridden buffer or if it was
+/// out-of-date or not-found.
+class InputFile {
+ enum {
+ Overridden = 1,
+ OutOfDate = 2,
+ NotFound = 3
+ };
+ llvm::PointerIntPair<const FileEntry *, 2, unsigned> Val;
+
+public:
+ InputFile() {}
+ InputFile(const FileEntry *File,
+ bool isOverridden = false, bool isOutOfDate = false) {
+ assert(!(isOverridden && isOutOfDate) &&
+ "an overridden cannot be out-of-date");
+ unsigned intVal = 0;
+ if (isOverridden)
+ intVal = Overridden;
+ else if (isOutOfDate)
+ intVal = OutOfDate;
+ Val.setPointerAndInt(File, intVal);
+ }
+
+ static InputFile getNotFound() {
+ InputFile File;
+ File.Val.setInt(NotFound);
+ return File;
+ }
+
+ const FileEntry *getFile() const { return Val.getPointer(); }
+ bool isOverridden() const { return Val.getInt() == Overridden; }
+ bool isOutOfDate() const { return Val.getInt() == OutOfDate; }
+ bool isNotFound() const { return Val.getInt() == NotFound; }
+};
+
+typedef unsigned ASTFileSignature;
+
+/// \brief Information about a module that has been loaded by the ASTReader.
+///
+/// Each instance of the Module class corresponds to a single AST file, which
+/// may be a precompiled header, precompiled preamble, a module, or an AST file
+/// of some sort loaded as the main file, all of which are specific formulations
+/// of the general notion of a "module". A module may depend on any number of
+/// other modules.
+class ModuleFile {
+public:
+ ModuleFile(ModuleKind Kind, unsigned Generation);
+ ~ModuleFile();
+
+ // === General information ===
+
+ /// \brief The index of this module in the list of modules.
+ unsigned Index;
+
+ /// \brief The type of this module.
+ ModuleKind Kind;
+
+ /// \brief The file name of the module file.
+ std::string FileName;
+
+ /// \brief The name of the module.
+ std::string ModuleName;
+
+ /// \brief The base directory of the module.
+ std::string BaseDirectory;
+
+ std::string getTimestampFilename() const {
+ return FileName + ".timestamp";
+ }
+
+ /// \brief The original source file name that was used to build the
+ /// primary AST file, which may have been modified for
+ /// relocatable-pch support.
+ std::string OriginalSourceFileName;
+
+ /// \brief The actual original source file name that was used to
+ /// build this AST file.
+ std::string ActualOriginalSourceFileName;
+
+ /// \brief The file ID for the original source file that was used to
+ /// build this AST file.
+ FileID OriginalSourceFileID;
+
+ /// \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;
+
+ std::string ModuleMapPath;
+
+ /// \brief Whether this precompiled header is a relocatable PCH file.
+ bool RelocatablePCH;
+
+ /// \brief Whether timestamps are included in this module file.
+ bool HasTimestamps;
+
+ /// \brief The file entry for the module file.
+ const FileEntry *File;
+
+ /// \brief The signature of the module file, which may be used along with size
+ /// and modification time to identify this particular file.
+ ASTFileSignature Signature;
+
+ /// \brief Whether this module has been directly imported by the
+ /// user.
+ bool DirectlyImported;
+
+ /// \brief The generation of which this module file is a part.
+ unsigned Generation;
+
+ /// \brief The memory buffer that stores the data associated with
+ /// this AST file.
+ std::unique_ptr<llvm::MemoryBuffer> Buffer;
+
+ /// \brief The size of this file, in bits.
+ uint64_t SizeInBits;
+
+ /// \brief The global bit offset (or base) of this module
+ uint64_t GlobalBitOffset;
+
+ /// \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;
+
+ /// \brief The source location where the module was explicitly or implicitly
+ /// imported in the local translation unit.
+ ///
+ /// If module A depends on and imports module B, both modules will have the
+ /// same DirectImportLoc, but different ImportLoc (B's ImportLoc will be a
+ /// source location inside module A).
+ ///
+ /// WARNING: This is largely useless. It doesn't tell you when a module was
+ /// made visible, just when the first submodule of that module was imported.
+ SourceLocation DirectImportLoc;
+
+ /// \brief The source location where this module was first imported.
+ SourceLocation ImportLoc;
+
+ /// \brief The first source location in this module.
+ SourceLocation FirstLoc;
+
+ /// The list of extension readers that are attached to this module
+ /// file.
+ std::vector<std::unique_ptr<ModuleFileExtensionReader>> ExtensionReaders;
+
+ // === Input Files ===
+ /// \brief The cursor to the start of the input-files block.
+ llvm::BitstreamCursor InputFilesCursor;
+
+ /// \brief Offsets for all of the input file entries in the AST file.
+ const llvm::support::unaligned_uint64_t *InputFileOffsets;
+
+ /// \brief The input files that have been loaded from this AST file.
+ std::vector<InputFile> InputFilesLoaded;
+
+ /// \brief If non-zero, specifies the time when we last validated input
+ /// files. Zero means we never validated them.
+ ///
+ /// The time is specified in seconds since the start of the Epoch.
+ uint64_t InputFilesValidationTimestamp;
+
+ // === 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 The base ID in the source manager's view of this module.
+ int SLocEntryBaseID;
+
+ /// \brief The base offset in the source manager's view of this module.
+ unsigned SLocEntryBaseOffset;
+
+ /// \brief Offsets for all of the source location entries in the
+ /// AST file.
+ const uint32_t *SLocEntryOffsets;
+
+ /// \brief SLocEntries that we're going to preload.
+ SmallVector<uint64_t, 4> PreloadSLocEntries;
+
+ /// \brief Remapping table for source locations in this module.
+ ContinuousRangeMap<uint32_t, int, 2> SLocRemap;
+
+ // === 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 Base identifier ID for identifiers local to this module.
+ serialization::IdentID BaseIdentifierID;
+
+ /// \brief Remapping table for identifier IDs in this module.
+ ContinuousRangeMap<uint32_t, int, 2> IdentifierRemap;
+
+ /// \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;
+
+ /// \brief Offsets of identifiers that we're going to preload within
+ /// IdentifierTableData.
+ std::vector<unsigned> PreloadIdentifierOffsets;
+
+ // === Macros ===
+
+ /// \brief The cursor to the start of the preprocessor block, which stores
+ /// all of the macro definitions.
+ llvm::BitstreamCursor MacroCursor;
+
+ /// \brief The number of macros in this AST file.
+ unsigned LocalNumMacros;
+
+ /// \brief Offsets of macros in the preprocessor block.
+ ///
+ /// This array is indexed by the macro ID (-1), and provides
+ /// the offset into the preprocessor block where macro definitions are
+ /// stored.
+ const uint32_t *MacroOffsets;
+
+ /// \brief Base macro ID for macros local to this module.
+ serialization::MacroID BaseMacroID;
+
+ /// \brief Remapping table for macro IDs in this module.
+ ContinuousRangeMap<uint32_t, int, 2> MacroRemap;
+
+ /// \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 Base preprocessed entity ID for preprocessed entities local to
+ /// this module.
+ serialization::PreprocessedEntityID BasePreprocessedEntityID;
+
+ /// \brief Remapping table for preprocessed entity IDs in this module.
+ ContinuousRangeMap<uint32_t, int, 2> PreprocessedEntityRemap;
+
+ const PPEntityOffset *PreprocessedEntityOffsets;
+ unsigned NumPreprocessedEntities;
+
+ // === 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;
+
+ // === Submodule information ===
+ /// \brief The number of submodules in this module.
+ unsigned LocalNumSubmodules;
+
+ /// \brief Base submodule ID for submodules local to this module.
+ serialization::SubmoduleID BaseSubmoduleID;
+
+ /// \brief Remapping table for submodule IDs in this module.
+ ContinuousRangeMap<uint32_t, int, 2> SubmoduleRemap;
+
+ // === 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 Base selector ID for selectors local to this module.
+ serialization::SelectorID BaseSelectorID;
+
+ /// \brief Remapping table for selector IDs in this module.
+ ContinuousRangeMap<uint32_t, int, 2> SelectorRemap;
+
+ /// \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;
+
+ // === 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 DeclOffset *DeclOffsets;
+
+ /// \brief Base declaration ID for declarations local to this module.
+ serialization::DeclID BaseDeclID;
+
+ /// \brief Remapping table for declaration IDs in this module.
+ ContinuousRangeMap<uint32_t, int, 2> DeclRemap;
+
+ /// \brief Mapping from the module files that this module file depends on
+ /// to the base declaration ID for that module as it is understood within this
+ /// module.
+ ///
+ /// This is effectively a reverse global-to-local mapping for declaration
+ /// IDs, so that we can interpret a true global ID (for this translation unit)
+ /// as a local ID (for this module file).
+ llvm::DenseMap<ModuleFile *, serialization::DeclID> GlobalToLocalDeclIDs;
+
+ /// \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;
+
+ /// \brief The number of C++ ctor initializer lists in this AST file.
+ unsigned LocalNumCXXCtorInitializers;
+
+ /// \brief Offset of each C++ ctor initializer list within the bitstream,
+ /// indexed by the C++ ctor initializer list ID minus 1.
+ const uint32_t *CXXCtorInitializersOffsets;
+
+ /// \brief Array of file-level DeclIDs sorted by file.
+ const serialization::DeclID *FileSortedDecls;
+ unsigned NumFileSortedDecls;
+
+ /// \brief Array of category list location information within this
+ /// module file, sorted by the definition ID.
+ const serialization::ObjCCategoriesInfo *ObjCCategoriesMap;
+
+ /// \brief The number of redeclaration info entries in ObjCCategoriesMap.
+ unsigned LocalNumObjCCategoriesInMap;
+
+ /// \brief The Objective-C category lists for categories known to this
+ /// module.
+ SmallVector<uint64_t, 1> ObjCCategories;
+
+ // === 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;
+
+ /// \brief Base type ID for types local to this module as represented in
+ /// the global type ID space.
+ serialization::TypeID BaseTypeIndex;
+
+ /// \brief Remapping table for type IDs in this module.
+ ContinuousRangeMap<uint32_t, int, 2> TypeRemap;
+
+ // === Miscellaneous ===
+
+ /// \brief Diagnostic IDs and their mappings that the user changed.
+ SmallVector<uint64_t, 8> PragmaDiagMappings;
+
+ /// \brief List of modules which depend on this module
+ llvm::SetVector<ModuleFile *> ImportedBy;
+
+ /// \brief List of modules which this module depends on
+ llvm::SetVector<ModuleFile *> Imports;
+
+ /// \brief Determine whether this module was directly imported at
+ /// any point during translation.
+ bool isDirectlyImported() const { return DirectlyImported; }
+
+ /// \brief Is this a module file for a module (rather than a PCH or similar).
+ bool isModule() const {
+ return Kind == MK_ImplicitModule || Kind == MK_ExplicitModule;
+ }
+
+ /// \brief Dump debugging output for this module.
+ void dump();
+};
+
+} // end namespace serialization
+
+} // end namespace clang
+
+#endif
diff --git a/contrib/llvm/tools/clang/include/clang/Serialization/ModuleFileExtension.h b/contrib/llvm/tools/clang/include/clang/Serialization/ModuleFileExtension.h
new file mode 100644
index 0000000..ba2e2fd
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Serialization/ModuleFileExtension.h
@@ -0,0 +1,149 @@
+//===-- ModuleFileExtension.h - Module File Extensions ----------*- 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_SERIALIZATION_MODULEFILEEXTENSION_H
+#define LLVM_CLANG_SERIALIZATION_MODULEFILEEXTENSION_H
+
+#include "llvm/ADT/IntrusiveRefCntPtr.h"
+#include <memory>
+#include <string>
+
+namespace llvm {
+class BitstreamCursor;
+class BitstreamWriter;
+class hash_code;
+class raw_ostream;
+}
+
+namespace clang {
+
+class ASTReader;
+class ASTWriter;
+class Sema;
+
+namespace serialization {
+ class ModuleFile;
+} // end namespace serialization
+
+/// Metadata for a module file extension.
+struct ModuleFileExtensionMetadata {
+ /// The name used to identify this particular extension block within
+ /// the resulting module file. It should be unique to the particular
+ /// extension, because this name will be used to match the name of
+ /// an extension block to the appropriate reader.
+ std::string BlockName;
+
+ /// The major version of the extension data.
+ unsigned MajorVersion;
+
+ /// The minor version of the extension data.
+ unsigned MinorVersion;
+
+ /// A string containing additional user information that will be
+ /// stored with the metadata.
+ std::string UserInfo;
+};
+
+class ModuleFileExtensionReader;
+class ModuleFileExtensionWriter;
+
+/// An abstract superclass that describes a custom extension to the
+/// module/precompiled header file format.
+///
+/// A module file extension can introduce additional information into
+/// compiled module files (.pcm) and precompiled headers (.pch) via a
+/// custom writer that can then be accessed via a custom reader when
+/// the module file or precompiled header is loaded.
+class ModuleFileExtension : public llvm::RefCountedBase<ModuleFileExtension> {
+public:
+ virtual ~ModuleFileExtension();
+
+ /// Retrieves the metadata for this module file extension.
+ virtual ModuleFileExtensionMetadata getExtensionMetadata() const = 0;
+
+ /// Hash information about the presence of this extension into the
+ /// module hash code.
+ ///
+ /// The module hash code is used to distinguish different variants
+ /// of a module that are incompatible. If the presence, absence, or
+ /// version of the module file extension should force the creation
+ /// of a separate set of module files, override this method to
+ /// combine that distinguishing information into the module hash
+ /// code.
+ ///
+ /// The default implementation of this function simply returns the
+ /// hash code as given, so the presence/absence of this extension
+ /// does not distinguish module files.
+ virtual llvm::hash_code hashExtension(llvm::hash_code c) const;
+
+ /// Create a new module file extension writer, which will be
+ /// responsible for writing the extension contents into a particular
+ /// module file.
+ virtual std::unique_ptr<ModuleFileExtensionWriter>
+ createExtensionWriter(ASTWriter &Writer) = 0;
+
+ /// Create a new module file extension reader, given the
+ /// metadata read from the block and the cursor into the extension
+ /// block.
+ ///
+ /// May return null to indicate that an extension block with the
+ /// given metadata cannot be read.
+ virtual std::unique_ptr<ModuleFileExtensionReader>
+ createExtensionReader(const ModuleFileExtensionMetadata &Metadata,
+ ASTReader &Reader, serialization::ModuleFile &Mod,
+ const llvm::BitstreamCursor &Stream) = 0;
+};
+
+/// Abstract base class that writes a module file extension block into
+/// a module file.
+class ModuleFileExtensionWriter {
+ ModuleFileExtension *Extension;
+
+protected:
+ ModuleFileExtensionWriter(ModuleFileExtension *Extension)
+ : Extension(Extension) { }
+
+public:
+ virtual ~ModuleFileExtensionWriter();
+
+ /// Retrieve the module file extension with which this writer is
+ /// associated.
+ ModuleFileExtension *getExtension() const { return Extension; }
+
+ /// Write the contents of the extension block into the given bitstream.
+ ///
+ /// Responsible for writing the contents of the extension into the
+ /// given stream. All of the contents should be written into custom
+ /// records with IDs >= FIRST_EXTENSION_RECORD_ID.
+ virtual void writeExtensionContents(Sema &SemaRef,
+ llvm::BitstreamWriter &Stream) = 0;
+};
+
+/// Abstract base class that reads a module file extension block from
+/// a module file.
+///
+/// Subclasses
+class ModuleFileExtensionReader {
+ ModuleFileExtension *Extension;
+
+protected:
+ ModuleFileExtensionReader(ModuleFileExtension *Extension)
+ : Extension(Extension) { }
+
+public:
+ /// Retrieve the module file extension with which this reader is
+ /// associated.
+ ModuleFileExtension *getExtension() const { return Extension; }
+
+ virtual ~ModuleFileExtensionReader();
+};
+
+} // end namespace clang
+
+#endif // LLVM_CLANG_FRONTEND_MODULEFILEEXTENSION_H
diff --git a/contrib/llvm/tools/clang/include/clang/Serialization/ModuleManager.h b/contrib/llvm/tools/clang/include/clang/Serialization/ModuleManager.h
new file mode 100644
index 0000000..08e7d40
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Serialization/ModuleManager.h
@@ -0,0 +1,289 @@
+//===--- ModuleManager.cpp - Module 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 ModuleManager class, which manages a set of loaded
+// modules for the ASTReader.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_SERIALIZATION_MODULEMANAGER_H
+#define LLVM_CLANG_SERIALIZATION_MODULEMANAGER_H
+
+#include "clang/Basic/FileManager.h"
+#include "clang/Serialization/Module.h"
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/SmallPtrSet.h"
+
+namespace clang {
+
+class GlobalModuleIndex;
+class ModuleMap;
+class PCHContainerReader;
+
+namespace serialization {
+
+/// \brief Manages the set of modules loaded by an AST reader.
+class ModuleManager {
+ /// \brief The chain of AST files, in the order in which we started to load
+ /// them (this order isn't really useful for anything).
+ SmallVector<ModuleFile *, 2> Chain;
+
+ /// \brief The chain of non-module PCH files. The first entry is the one named
+ /// by the user, the last one is the one that doesn't depend on anything
+ /// further.
+ SmallVector<ModuleFile *, 2> PCHChain;
+
+ // \brief The roots of the dependency DAG of AST files. This is used
+ // to implement short-circuiting logic when running DFS over the dependencies.
+ SmallVector<ModuleFile *, 2> Roots;
+
+ /// \brief All loaded modules, indexed by name.
+ llvm::DenseMap<const FileEntry *, ModuleFile *> Modules;
+
+ /// \brief FileManager that handles translating between filenames and
+ /// FileEntry *.
+ FileManager &FileMgr;
+
+ /// \brief Knows how to unwrap module containers.
+ const PCHContainerReader &PCHContainerRdr;
+
+ /// \brief A lookup of in-memory (virtual file) buffers
+ llvm::DenseMap<const FileEntry *, std::unique_ptr<llvm::MemoryBuffer>>
+ InMemoryBuffers;
+
+ /// \brief The visitation order.
+ SmallVector<ModuleFile *, 4> VisitOrder;
+
+ /// \brief The list of module files that both we and the global module index
+ /// know about.
+ ///
+ /// Either the global index or the module manager may have modules that the
+ /// other does not know about, because the global index can be out-of-date
+ /// (in which case the module manager could have modules it does not) and
+ /// this particular translation unit might not have loaded all of the modules
+ /// known to the global index.
+ SmallVector<ModuleFile *, 4> ModulesInCommonWithGlobalIndex;
+
+ /// \brief The global module index, if one is attached.
+ ///
+ /// The global module index will actually be owned by the ASTReader; this is
+ /// just an non-owning pointer.
+ GlobalModuleIndex *GlobalIndex;
+
+ /// \brief State used by the "visit" operation to avoid malloc traffic in
+ /// calls to visit().
+ struct VisitState {
+ explicit VisitState(unsigned N)
+ : VisitNumber(N, 0), NextVisitNumber(1), NextState(nullptr)
+ {
+ Stack.reserve(N);
+ }
+
+ ~VisitState() {
+ delete NextState;
+ }
+
+ /// \brief The stack used when marking the imports of a particular module
+ /// as not-to-be-visited.
+ SmallVector<ModuleFile *, 4> Stack;
+
+ /// \brief The visit number of each module file, which indicates when
+ /// this module file was last visited.
+ SmallVector<unsigned, 4> VisitNumber;
+
+ /// \brief The next visit number to use to mark visited module files.
+ unsigned NextVisitNumber;
+
+ /// \brief The next visit state.
+ VisitState *NextState;
+ };
+
+ /// \brief The first visit() state in the chain.
+ VisitState *FirstVisitState;
+
+ VisitState *allocateVisitState();
+ void returnVisitState(VisitState *State);
+
+public:
+ typedef SmallVectorImpl<ModuleFile*>::iterator ModuleIterator;
+ typedef SmallVectorImpl<ModuleFile*>::const_iterator ModuleConstIterator;
+ typedef SmallVectorImpl<ModuleFile*>::reverse_iterator ModuleReverseIterator;
+ typedef std::pair<uint32_t, StringRef> ModuleOffset;
+
+ explicit ModuleManager(FileManager &FileMgr,
+ const PCHContainerReader &PCHContainerRdr);
+ ~ModuleManager();
+
+ /// \brief Forward iterator to traverse all loaded modules.
+ ModuleIterator begin() { return Chain.begin(); }
+ /// \brief Forward iterator end-point to traverse all loaded modules
+ ModuleIterator end() { return Chain.end(); }
+
+ /// \brief Const forward iterator to traverse all loaded modules.
+ ModuleConstIterator begin() const { return Chain.begin(); }
+ /// \brief Const forward iterator end-point to traverse all loaded modules
+ ModuleConstIterator end() const { return Chain.end(); }
+
+ /// \brief Reverse iterator to traverse all loaded modules.
+ ModuleReverseIterator rbegin() { return Chain.rbegin(); }
+ /// \brief Reverse iterator end-point to traverse all loaded modules.
+ ModuleReverseIterator rend() { return Chain.rend(); }
+
+ /// \brief A range covering the PCH and preamble module files loaded.
+ llvm::iterator_range<ModuleConstIterator> pch_modules() const {
+ return llvm::make_range(PCHChain.begin(), PCHChain.end());
+ }
+
+ /// \brief Returns the primary module associated with the manager, that is,
+ /// the first module loaded
+ ModuleFile &getPrimaryModule() { return *Chain[0]; }
+
+ /// \brief Returns the primary module associated with the manager, that is,
+ /// the first module loaded.
+ ModuleFile &getPrimaryModule() const { return *Chain[0]; }
+
+ /// \brief Returns the module associated with the given index
+ ModuleFile &operator[](unsigned Index) const { return *Chain[Index]; }
+
+ /// \brief Returns the module associated with the given name
+ ModuleFile *lookup(StringRef Name);
+
+ /// \brief Returns the module associated with the given module file.
+ ModuleFile *lookup(const FileEntry *File);
+
+ /// \brief Returns the in-memory (virtual file) buffer with the given name
+ std::unique_ptr<llvm::MemoryBuffer> lookupBuffer(StringRef Name);
+
+ /// \brief Number of modules loaded
+ unsigned size() const { return Chain.size(); }
+
+ /// \brief The result of attempting to add a new module.
+ enum AddModuleResult {
+ /// \brief The module file had already been loaded.
+ AlreadyLoaded,
+ /// \brief The module file was just loaded in response to this call.
+ NewlyLoaded,
+ /// \brief The module file is missing.
+ Missing,
+ /// \brief The module file is out-of-date.
+ OutOfDate
+ };
+
+ typedef ASTFileSignature(*ASTFileSignatureReader)(llvm::BitstreamReader &);
+
+ /// \brief Attempts to create a new module and add it to the list of known
+ /// modules.
+ ///
+ /// \param FileName The file name of the module to be loaded.
+ ///
+ /// \param Type The kind of module being loaded.
+ ///
+ /// \param ImportLoc The location at which the module is imported.
+ ///
+ /// \param ImportedBy The module that is importing this module, or NULL if
+ /// this module is imported directly by the user.
+ ///
+ /// \param Generation The generation in which this module was loaded.
+ ///
+ /// \param ExpectedSize The expected size of the module file, used for
+ /// validation. This will be zero if unknown.
+ ///
+ /// \param ExpectedModTime The expected modification time of the module
+ /// file, used for validation. This will be zero if unknown.
+ ///
+ /// \param ExpectedSignature The expected signature of the module file, used
+ /// for validation. This will be zero if unknown.
+ ///
+ /// \param ReadSignature Reads the signature from an AST file without actually
+ /// loading it.
+ ///
+ /// \param Module A pointer to the module file if the module was successfully
+ /// loaded.
+ ///
+ /// \param ErrorStr Will be set to a non-empty string if any errors occurred
+ /// while trying to load the module.
+ ///
+ /// \return A pointer to the module that corresponds to this file name,
+ /// and a value indicating whether the module was loaded.
+ AddModuleResult addModule(StringRef FileName, ModuleKind Type,
+ SourceLocation ImportLoc,
+ ModuleFile *ImportedBy, unsigned Generation,
+ off_t ExpectedSize, time_t ExpectedModTime,
+ ASTFileSignature ExpectedSignature,
+ ASTFileSignatureReader ReadSignature,
+ ModuleFile *&Module,
+ std::string &ErrorStr);
+
+ /// \brief Remove the given set of modules.
+ void removeModules(ModuleIterator first, ModuleIterator last,
+ llvm::SmallPtrSetImpl<ModuleFile *> &LoadedSuccessfully,
+ ModuleMap *modMap);
+
+ /// \brief Add an in-memory buffer the list of known buffers
+ void addInMemoryBuffer(StringRef FileName,
+ std::unique_ptr<llvm::MemoryBuffer> Buffer);
+
+ /// \brief Set the global module index.
+ void setGlobalIndex(GlobalModuleIndex *Index);
+
+ /// \brief Notification from the AST reader that the given module file
+ /// has been "accepted", and will not (can not) be unloaded.
+ void moduleFileAccepted(ModuleFile *MF);
+
+ /// \brief Visit each of the modules.
+ ///
+ /// This routine visits each of the modules, starting with the
+ /// "root" modules that no other loaded modules depend on, and
+ /// proceeding to the leaf modules, visiting each module only once
+ /// during the traversal.
+ ///
+ /// This traversal is intended to support various "lookup"
+ /// operations that can find data in any of the loaded modules.
+ ///
+ /// \param Visitor A visitor function that will be invoked with each
+ /// module. The return value must be convertible to bool; when false, the
+ /// visitation continues to modules that the current module depends on. When
+ /// true, the visitation skips any modules that the current module depends on.
+ ///
+ /// \param ModuleFilesHit If non-NULL, contains the set of module files
+ /// that we know we need to visit because the global module index told us to.
+ /// Any module that is known to both the global module index and the module
+ /// manager that is *not* in this set can be skipped.
+ void visit(llvm::function_ref<bool(ModuleFile &M)> Visitor,
+ llvm::SmallPtrSetImpl<ModuleFile *> *ModuleFilesHit = nullptr);
+
+ /// \brief Attempt to resolve the given module file name to a file entry.
+ ///
+ /// \param FileName The name of the module file.
+ ///
+ /// \param ExpectedSize The size that the module file is expected to have.
+ /// If the actual size differs, the resolver should return \c true.
+ ///
+ /// \param ExpectedModTime The modification time that the module file is
+ /// expected to have. If the actual modification time differs, the resolver
+ /// should return \c true.
+ ///
+ /// \param File Will be set to the file if there is one, or null
+ /// otherwise.
+ ///
+ /// \returns True if a file exists but does not meet the size/
+ /// modification time criteria, false if the file is either available and
+ /// suitable, or is missing.
+ bool lookupModuleFile(StringRef FileName,
+ off_t ExpectedSize,
+ time_t ExpectedModTime,
+ const FileEntry *&File);
+
+ /// \brief View the graphviz representation of the module graph.
+ void viewGraph();
+};
+
+} } // end namespace clang::serialization
+
+#endif
diff --git a/contrib/llvm/tools/clang/include/clang/Serialization/SerializationDiagnostic.h b/contrib/llvm/tools/clang/include/clang/Serialization/SerializationDiagnostic.h
new file mode 100644
index 0000000..d50422a
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Serialization/SerializationDiagnostic.h
@@ -0,0 +1,28 @@
+//===--- SerializationDiagnostic.h - Serialization Diagnostics -*- 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_SERIALIZATION_SERIALIZATIONDIAGNOSTIC_H
+#define LLVM_CLANG_SERIALIZATION_SERIALIZATIONDIAGNOSTIC_H
+
+#include "clang/Basic/Diagnostic.h"
+
+namespace clang {
+ namespace diag {
+ enum {
+#define DIAG(ENUM,FLAGS,DEFAULT_MAPPING,DESC,GROUP,\
+ SFINAE,NOWERROR,SHOWINSYSHEADER,CATEGORY) ENUM,
+#define SERIALIZATIONSTART
+#include "clang/Basic/DiagnosticSerializationKinds.inc"
+#undef DIAG
+ NUM_BUILTIN_SERIALIZATION_DIAGNOSTICS
+ };
+ } // end namespace diag
+} // 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..11f1e5d
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Checkers/CheckerBase.td
@@ -0,0 +1,39 @@
+//===--- 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 CheckerGroup<string name> {
+ string GroupName = name;
+}
+class InGroup<CheckerGroup G> { CheckerGroup Group = G; }
+
+class Package<string name> {
+ string PackageName = name;
+ bit Hidden = 0;
+ Package ParentPackage;
+ CheckerGroup Group;
+}
+class InPackage<Package P> { Package ParentPackage = P; }
+
+// 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/ClangCheckers.h b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Checkers/ClangCheckers.h
new file mode 100644
index 0000000..cf0a30a
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Checkers/ClangCheckers.h
@@ -0,0 +1,22 @@
+//===--- ClangCheckers.h - Provides builtin checkers ------------*- 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_STATICANALYZER_CHECKERS_CLANGCHECKERS_H
+#define LLVM_CLANG_STATICANALYZER_CHECKERS_CLANGCHECKERS_H
+
+namespace clang {
+namespace ento {
+class CheckerRegistry;
+
+void registerBuiltinCheckers(CheckerRegistry &registry);
+
+} // end namespace ento
+} // end namespace clang
+
+#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..463f04a
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Checkers/LocalCheckers.h
@@ -0,0 +1,28 @@
+//==- 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_STATICANALYZER_CHECKERS_LOCALCHECKERS_H
+#define LLVM_CLANG_STATICANALYZER_CHECKERS_LOCALCHECKERS_H
+
+namespace clang {
+namespace ento {
+
+class ExprEngine;
+
+void RegisterCallInliner(ExprEngine &Eng);
+
+} // end namespace ento
+} // end namespace clang
+
+#endif
diff --git a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Checkers/ObjCRetainCount.h b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Checkers/ObjCRetainCount.h
new file mode 100644
index 0000000..5850656
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Checkers/ObjCRetainCount.h
@@ -0,0 +1,234 @@
+//==-- ObjCRetainCount.h - Retain count summaries for Cocoa -------*- C++ -*--//
+//
+// 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 core data structures for retain count "summaries"
+// for Objective-C and Core Foundation APIs. These summaries are used
+// by the static analyzer to summarize the retain/release effects of
+// function and method calls. This drives a path-sensitive typestate
+// analysis in the static analyzer, but can also potentially be used by
+// other clients.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_STATICANALYZER_CHECKERS_OBJCRETAINCOUNT_H
+#define LLVM_CLANG_STATICANALYZER_CHECKERS_OBJCRETAINCOUNT_H
+
+#include "clang/Basic/LLVM.h"
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/SmallVector.h"
+
+namespace clang {
+class FunctionDecl;
+class ObjCMethodDecl;
+
+namespace ento { namespace objc_retain {
+
+/// An ArgEffect summarizes the retain count behavior on an argument or receiver
+/// to a function or method.
+enum ArgEffect {
+ /// There is no effect.
+ DoNothing,
+
+ /// The argument is treated as if an -autorelease message had been sent to
+ /// the referenced object.
+ Autorelease,
+
+ /// The argument is treated as if an -dealloc message had been sent to
+ /// the referenced object.
+ Dealloc,
+
+ /// The argument has its reference count decreased by 1. This is as
+ /// if CFRelease has been called on the argument.
+ DecRef,
+
+ /// The argument has its reference count decreased by 1. This is as
+ /// if a -release message has been sent to the argument. This differs
+ /// in behavior from DecRef when GC is enabled.
+ DecRefMsg,
+
+ /// The argument has its reference count decreased by 1 to model
+ /// a transferred bridge cast under ARC.
+ DecRefBridgedTransferred,
+
+ /// The argument has its reference count increased by 1. This is as
+ /// if a -retain message has been sent to the argument. This differs
+ /// in behavior from IncRef when GC is enabled.
+ IncRefMsg,
+
+ /// The argument has its reference count increased by 1. This is as
+ /// if CFRetain has been called on the argument.
+ IncRef,
+
+ /// The argument acts as if has been passed to CFMakeCollectable, which
+ /// transfers the object to the Garbage Collector under GC.
+ MakeCollectable,
+
+ /// The argument is a pointer to a retain-counted object; on exit, the new
+ /// value of the pointer is a +0 value or NULL.
+ UnretainedOutParameter,
+
+ /// The argument is a pointer to a retain-counted object; on exit, the new
+ /// value of the pointer is a +1 value or NULL.
+ RetainedOutParameter,
+
+ /// The argument is treated as potentially escaping, meaning that
+ /// even when its reference count hits 0 it should be treated as still
+ /// possibly being alive as someone else *may* be holding onto the object.
+ MayEscape,
+
+ /// All typestate tracking of the object ceases. This is usually employed
+ /// when the effect of the call is completely unknown.
+ StopTracking,
+
+ /// All typestate tracking of the object ceases. Unlike StopTracking,
+ /// this is also enforced when the method body is inlined.
+ ///
+ /// In some cases, we obtain a better summary for this checker
+ /// by looking at the call site than by inlining the function.
+ /// Signifies that we should stop tracking the symbol even if
+ /// the function is inlined.
+ StopTrackingHard,
+
+ /// Performs the combined functionality of DecRef and StopTrackingHard.
+ ///
+ /// The models the effect that the called function decrements the reference
+ /// count of the argument and all typestate tracking on that argument
+ /// should cease.
+ DecRefAndStopTrackingHard,
+
+ /// Performs the combined functionality of DecRefMsg and StopTrackingHard.
+ ///
+ /// The models the effect that the called function decrements the reference
+ /// count of the argument and all typestate tracking on that argument
+ /// should cease.
+ DecRefMsgAndStopTrackingHard
+};
+
+/// RetEffect summarizes a call's retain/release behavior with respect
+/// to its return value.
+class RetEffect {
+public:
+ enum Kind {
+ /// Indicates that no retain count information is tracked for
+ /// the return value.
+ NoRet,
+ /// Indicates that the returned value is an owned (+1) symbol.
+ OwnedSymbol,
+ /// Indicates that the returned value is an owned (+1) symbol and
+ /// that it should be treated as freshly allocated.
+ OwnedAllocatedSymbol,
+ /// Indicates that the returned value is an object with retain count
+ /// semantics but that it is not owned (+0). This is the default
+ /// for getters, etc.
+ NotOwnedSymbol,
+ /// Indicates that the object is not owned and controlled by the
+ /// Garbage collector.
+ GCNotOwnedSymbol,
+ /// Indicates that the return value is an owned object when the
+ /// receiver is also a tracked object.
+ OwnedWhenTrackedReceiver,
+ // Treat this function as returning a non-tracked symbol even if
+ // the function has been inlined. This is used where the call
+ // site summary is more presise than the summary indirectly produced
+ // by inlining the function
+ NoRetHard
+ };
+
+ /// Determines the object kind of a tracked object.
+ enum ObjKind {
+ /// Indicates that the tracked object is a CF object. This is
+ /// important between GC and non-GC code.
+ CF,
+ /// Indicates that the tracked object is an Objective-C object.
+ ObjC,
+ /// Indicates that the tracked object could be a CF or Objective-C object.
+ AnyObj
+ };
+
+private:
+ Kind K;
+ ObjKind O;
+
+ RetEffect(Kind k, ObjKind o = AnyObj) : K(k), O(o) {}
+
+public:
+ Kind getKind() const { return K; }
+
+ ObjKind getObjKind() const { return O; }
+
+ bool isOwned() const {
+ return K == OwnedSymbol || K == OwnedAllocatedSymbol ||
+ K == OwnedWhenTrackedReceiver;
+ }
+
+ bool notOwned() const {
+ return K == NotOwnedSymbol;
+ }
+
+ bool operator==(const RetEffect &Other) const {
+ return K == Other.K && O == Other.O;
+ }
+
+ static RetEffect MakeOwnedWhenTrackedReceiver() {
+ return RetEffect(OwnedWhenTrackedReceiver, ObjC);
+ }
+
+ 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);
+ }
+ static RetEffect MakeNoRetHard() {
+ return RetEffect(NoRetHard);
+ }
+};
+
+/// Encapsulates the retain count semantics on the arguments, return value,
+/// and receiver (if any) of a function/method call.
+///
+/// Note that construction of these objects is not highly efficient. That
+/// is okay for clients where creating these objects isn't really a bottleneck.
+/// The purpose of the API is to provide something simple. The actual
+/// static analyzer checker that implements retain/release typestate
+/// tracking uses something more efficient.
+class CallEffects {
+ llvm::SmallVector<ArgEffect, 10> Args;
+ RetEffect Ret;
+ ArgEffect Receiver;
+
+ CallEffects(const RetEffect &R) : Ret(R) {}
+
+public:
+ /// Returns the argument effects for a call.
+ ArrayRef<ArgEffect> getArgs() const { return Args; }
+
+ /// Returns the effects on the receiver.
+ ArgEffect getReceiver() const { return Receiver; }
+
+ /// Returns the effect on the return value.
+ RetEffect getReturnValue() const { return Ret; }
+
+ /// Return the CallEfect for a given Objective-C method.
+ static CallEffects getEffect(const ObjCMethodDecl *MD);
+
+ /// Return the CallEfect for a given C/C++ function.
+ static CallEffects getEffect(const FunctionDecl *FD);
+};
+
+}}}
+
+#endif
+
diff --git a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/Analyses.def b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/Analyses.def
new file mode 100644
index 0000000..3355f4b
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/Analyses.def
@@ -0,0 +1,57 @@
+//===-- 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_STORE
+#define ANALYSIS_STORE(NAME, CMDFLAG, DESC, CREATFN)
+#endif
+
+ANALYSIS_STORE(RegionStore, "region", "Use region-based analyzer store", CreateRegionStoreManager)
+
+#ifndef ANALYSIS_CONSTRAINTS
+#define ANALYSIS_CONSTRAINTS(NAME, CMDFLAG, DESC, CREATFN)
+#endif
+
+ANALYSIS_CONSTRAINTS(RangeConstraints, "range", "Use constraint tracking of concrete value ranges", CreateRangeConstraintManager)
+
+#ifndef ANALYSIS_DIAGNOSTICS
+#define ANALYSIS_DIAGNOSTICS(NAME, CMDFLAG, DESC, CREATEFN)
+#endif
+
+ANALYSIS_DIAGNOSTICS(HTML, "html", "Output analysis results using HTML", createHTMLDiagnosticConsumer)
+ANALYSIS_DIAGNOSTICS(PLIST, "plist", "Output analysis results using Plists", createPlistDiagnosticConsumer)
+ANALYSIS_DIAGNOSTICS(PLIST_MULTI_FILE, "plist-multi-file", "Output analysis results using Plists (allowing for mult-file bugs)", createPlistMultiFileDiagnosticConsumer)
+ANALYSIS_DIAGNOSTICS(PLIST_HTML, "plist-html", "Output analysis results using HTML wrapped with Plists", createPlistHTMLDiagnosticConsumer)
+ANALYSIS_DIAGNOSTICS(TEXT, "text", "Text output of analysis results", createTextPathDiagnosticConsumer)
+
+#ifndef ANALYSIS_PURGE
+#define ANALYSIS_PURGE(NAME, CMDFLAG, DESC)
+#endif
+
+ANALYSIS_PURGE(PurgeStmt, "statement", "Purge symbols, bindings, and constraints before every statement")
+ANALYSIS_PURGE(PurgeBlock, "block", "Purge symbols, bindings, and constraints before every basic block")
+ANALYSIS_PURGE(PurgeNone, "none", "Do not purge symbols, bindings, or constraints")
+
+#ifndef ANALYSIS_INLINING_MODE
+#define ANALYSIS_INLINING_MODE(NAME, CMDFLAG, DESC)
+#endif
+
+ANALYSIS_INLINING_MODE(All, "all", "Analyze all functions as top level")
+ANALYSIS_INLINING_MODE(NoRedundancy, "noredundancy", "Do not analyze a function which has been previously inlined")
+
+#undef ANALYSIS_STORE
+#undef ANALYSIS_CONSTRAINTS
+#undef ANALYSIS_DIAGNOSTICS
+#undef ANALYSIS_PURGE
+#undef ANALYSIS_INLINING_MODE
+#undef ANALYSIS_IPA
+
diff --git a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/AnalyzerOptions.h b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/AnalyzerOptions.h
new file mode 100644
index 0000000..3959de2
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/AnalyzerOptions.h
@@ -0,0 +1,567 @@
+//===--- 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 defines various options for the static analyzer that are set
+// by the frontend and are consulted throughout the analyzer.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_STATICANALYZER_CORE_ANALYZEROPTIONS_H
+#define LLVM_CLANG_STATICANALYZER_CORE_ANALYZEROPTIONS_H
+
+#include "clang/Basic/LLVM.h"
+#include "llvm/ADT/IntrusiveRefCntPtr.h"
+#include "llvm/ADT/Optional.h"
+#include "llvm/ADT/StringMap.h"
+#include <string>
+#include <vector>
+
+namespace clang {
+class ASTConsumer;
+class DiagnosticsEngine;
+class Preprocessor;
+class LangOptions;
+
+namespace ento {
+class CheckerBase;
+}
+
+/// Analysis - Set of available source code analyses.
+enum Analyses {
+#define ANALYSIS(NAME, CMDFLAG, DESC, SCOPE) NAME,
+#include "clang/StaticAnalyzer/Core/Analyses.def"
+NumAnalyses
+};
+
+/// AnalysisStores - Set of available analysis store models.
+enum AnalysisStores {
+#define ANALYSIS_STORE(NAME, CMDFLAG, DESC, CREATFN) NAME##Model,
+#include "clang/StaticAnalyzer/Core/Analyses.def"
+NumStores
+};
+
+/// AnalysisConstraints - Set of available constraint models.
+enum AnalysisConstraints {
+#define ANALYSIS_CONSTRAINTS(NAME, CMDFLAG, DESC, CREATFN) NAME##Model,
+#include "clang/StaticAnalyzer/Core/Analyses.def"
+NumConstraints
+};
+
+/// AnalysisDiagClients - Set of available diagnostic clients for rendering
+/// analysis results.
+enum AnalysisDiagClients {
+#define ANALYSIS_DIAGNOSTICS(NAME, CMDFLAG, DESC, CREATFN) PD_##NAME,
+#include "clang/StaticAnalyzer/Core/Analyses.def"
+PD_NONE,
+NUM_ANALYSIS_DIAG_CLIENTS
+};
+
+/// AnalysisPurgeModes - Set of available strategies for dead symbol removal.
+enum AnalysisPurgeMode {
+#define ANALYSIS_PURGE(NAME, CMDFLAG, DESC) NAME,
+#include "clang/StaticAnalyzer/Core/Analyses.def"
+NumPurgeModes
+};
+
+/// AnalysisInlineFunctionSelection - Set of inlining function selection heuristics.
+enum AnalysisInliningMode {
+#define ANALYSIS_INLINING_MODE(NAME, CMDFLAG, DESC) NAME,
+#include "clang/StaticAnalyzer/Core/Analyses.def"
+NumInliningModes
+};
+
+/// \brief Describes the different kinds of C++ member functions which can be
+/// considered for inlining by the analyzer.
+///
+/// These options are cumulative; enabling one kind of member function will
+/// enable all kinds with lower enum values.
+enum CXXInlineableMemberKind {
+ // Uninitialized = 0,
+
+ /// A dummy mode in which no C++ inlining is enabled.
+ CIMK_None = 1,
+
+ /// Refers to regular member function and operator calls.
+ CIMK_MemberFunctions,
+
+ /// Refers to constructors (implicit or explicit).
+ ///
+ /// Note that a constructor will not be inlined if the corresponding
+ /// destructor is non-trivial.
+ CIMK_Constructors,
+
+ /// Refers to destructors (implicit or explicit).
+ CIMK_Destructors
+};
+
+/// \brief Describes the different modes of inter-procedural analysis.
+enum IPAKind {
+ IPAK_NotSet = 0,
+
+ /// Perform only intra-procedural analysis.
+ IPAK_None = 1,
+
+ /// Inline C functions and blocks when their definitions are available.
+ IPAK_BasicInlining = 2,
+
+ /// Inline callees(C, C++, ObjC) when their definitions are available.
+ IPAK_Inlining = 3,
+
+ /// Enable inlining of dynamically dispatched methods.
+ IPAK_DynamicDispatch = 4,
+
+ /// Enable inlining of dynamically dispatched methods, bifurcate paths when
+ /// exact type info is unavailable.
+ IPAK_DynamicDispatchBifurcate = 5
+};
+
+class AnalyzerOptions : public RefCountedBase<AnalyzerOptions> {
+public:
+ typedef llvm::StringMap<std::string> ConfigTable;
+
+ /// \brief Pair of checker name and enable/disable.
+ std::vector<std::pair<std::string, bool> > CheckersControlList;
+
+ /// \brief A key-value table of use-specified configuration values.
+ ConfigTable Config;
+ AnalysisStores AnalysisStoreOpt;
+ AnalysisConstraints AnalysisConstraintsOpt;
+ AnalysisDiagClients AnalysisDiagOpt;
+ AnalysisPurgeMode AnalysisPurgeOpt;
+
+ std::string AnalyzeSpecificFunction;
+
+ /// \brief The maximum number of times the analyzer visits a block.
+ unsigned maxBlockVisitOnPath;
+
+
+ /// \brief Disable all analyzer checks.
+ ///
+ /// This flag allows one to disable analyzer checks on the code processed by
+ /// the given analysis consumer. Note, the code will get parsed and the
+ /// command-line options will get checked.
+ unsigned DisableAllChecks : 1;
+
+ unsigned ShowCheckerHelp : 1;
+ unsigned AnalyzeAll : 1;
+ unsigned AnalyzerDisplayProgress : 1;
+ unsigned AnalyzeNestedBlocks : 1;
+
+ /// \brief The flag regulates if we should eagerly assume evaluations of
+ /// conditionals, thus, bifurcating the path.
+ ///
+ /// This flag indicates 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.
+ unsigned eagerlyAssumeBinOpBifurcation : 1;
+
+ unsigned TrimGraph : 1;
+ unsigned visualizeExplodedGraphWithGraphViz : 1;
+ unsigned visualizeExplodedGraphWithUbiGraph : 1;
+ unsigned UnoptimizedCFG : 1;
+ unsigned PrintStats : 1;
+
+ /// \brief Do not re-analyze paths leading to exhausted nodes with a different
+ /// strategy. We get better code coverage when retry is enabled.
+ unsigned NoRetryExhausted : 1;
+
+ /// \brief The inlining stack depth limit.
+ unsigned InlineMaxStackDepth;
+
+ /// \brief The mode of function selection used during inlining.
+ AnalysisInliningMode InliningMode;
+
+private:
+ /// \brief Describes the kinds for high-level analyzer mode.
+ enum UserModeKind {
+ UMK_NotSet = 0,
+ /// Perform shallow but fast analyzes.
+ UMK_Shallow = 1,
+ /// Perform deep analyzes.
+ UMK_Deep = 2
+ };
+
+ /// Controls the high-level analyzer mode, which influences the default
+ /// settings for some of the lower-level config options (such as IPAMode).
+ /// \sa getUserMode
+ UserModeKind UserMode;
+
+ /// Controls the mode of inter-procedural analysis.
+ IPAKind IPAMode;
+
+ /// Controls which C++ member functions will be considered for inlining.
+ CXXInlineableMemberKind CXXMemberInliningMode;
+
+ /// \sa includeTemporaryDtorsInCFG
+ Optional<bool> IncludeTemporaryDtorsInCFG;
+
+ /// \sa mayInlineCXXStandardLibrary
+ Optional<bool> InlineCXXStandardLibrary;
+
+ /// \sa mayInlineTemplateFunctions
+ Optional<bool> InlineTemplateFunctions;
+
+ /// \sa mayInlineCXXAllocator
+ Optional<bool> InlineCXXAllocator;
+
+ /// \sa mayInlineCXXContainerMethods
+ Optional<bool> InlineCXXContainerMethods;
+
+ /// \sa mayInlineCXXSharedPtrDtor
+ Optional<bool> InlineCXXSharedPtrDtor;
+
+ /// \sa mayInlineObjCMethod
+ Optional<bool> ObjCInliningMode;
+
+ // Cache of the "ipa-always-inline-size" setting.
+ // \sa getAlwaysInlineSize
+ Optional<unsigned> AlwaysInlineSize;
+
+ /// \sa shouldSuppressNullReturnPaths
+ Optional<bool> SuppressNullReturnPaths;
+
+ // \sa getMaxInlinableSize
+ Optional<unsigned> MaxInlinableSize;
+
+ /// \sa shouldAvoidSuppressingNullArgumentPaths
+ Optional<bool> AvoidSuppressingNullArgumentPaths;
+
+ /// \sa shouldSuppressInlinedDefensiveChecks
+ Optional<bool> SuppressInlinedDefensiveChecks;
+
+ /// \sa shouldSuppressFromCXXStandardLibrary
+ Optional<bool> SuppressFromCXXStandardLibrary;
+
+ /// \sa reportIssuesInMainSourceFile
+ Optional<bool> ReportIssuesInMainSourceFile;
+
+ /// \sa StableReportFilename
+ Optional<bool> StableReportFilename;
+
+ /// \sa getGraphTrimInterval
+ Optional<unsigned> GraphTrimInterval;
+
+ /// \sa getMaxTimesInlineLarge
+ Optional<unsigned> MaxTimesInlineLarge;
+
+ /// \sa getMinCFGSizeTreatFunctionsAsLarge
+ Optional<unsigned> MinCFGSizeTreatFunctionsAsLarge;
+
+ /// \sa getMaxNodesPerTopLevelFunction
+ Optional<unsigned> MaxNodesPerTopLevelFunction;
+
+ /// \sa shouldInlineLambdas
+ Optional<bool> InlineLambdas;
+
+ /// \sa shouldWidenLoops
+ Optional<bool> WidenLoops;
+
+ /// A helper function that retrieves option for a given full-qualified
+ /// checker name.
+ /// Options for checkers can be specified via 'analyzer-config' command-line
+ /// option.
+ /// Example:
+ /// @code-analyzer-config unix.Malloc:OptionName=CheckerOptionValue @endcode
+ /// or @code-analyzer-config unix:OptionName=GroupOptionValue @endcode
+ /// for groups of checkers.
+ /// @param [in] CheckerName Full-qualified checker name, like
+ /// alpha.unix.StreamChecker.
+ /// @param [in] OptionName Name of the option to get.
+ /// @param [in] Default Default value if no option is specified.
+ /// @param [in] SearchInParents If set to true and the searched option was not
+ /// specified for the given checker the options for the parent packages will
+ /// be searched as well. The inner packages take precedence over the outer
+ /// ones.
+ /// @retval CheckerOptionValue An option for a checker if it was specified.
+ /// @retval GroupOptionValue An option for group if it was specified and no
+ /// checker-specific options were found. The closer group to checker,
+ /// the more priority it has. For example, @c coregroup.subgroup has more
+ /// priority than @c coregroup for @c coregroup.subgroup.CheckerName checker.
+ /// @retval Default If nor checker option, nor group option was found.
+ StringRef getCheckerOption(StringRef CheckerName, StringRef OptionName,
+ StringRef Default,
+ bool SearchInParents = false);
+
+public:
+ /// Interprets an option's string value as a boolean. The "true" string is
+ /// interpreted as true and the "false" string is interpreted as false.
+ ///
+ /// If an option value is not provided, returns the given \p DefaultVal.
+ /// @param [in] Name Name for option to retrieve.
+ /// @param [in] DefaultVal Default value returned if no such option was
+ /// specified.
+ /// @param [in] C The optional checker parameter that can be used to restrict
+ /// the search to the options of this particular checker (and its parents
+ /// dependening on search mode).
+ /// @param [in] SearchInParents If set to true and the searched option was not
+ /// specified for the given checker the options for the parent packages will
+ /// be searched as well. The inner packages take precedence over the outer
+ /// ones.
+ bool getBooleanOption(StringRef Name, bool DefaultVal,
+ const ento::CheckerBase *C = nullptr,
+ bool SearchInParents = false);
+
+ /// Variant that accepts a Optional value to cache the result.
+ ///
+ /// @param [in,out] V Return value storage, returned if parameter contains
+ /// an existing valid option, else it is used to store a return value
+ /// @param [in] Name Name for option to retrieve.
+ /// @param [in] DefaultVal Default value returned if no such option was
+ /// specified.
+ /// @param [in] C The optional checker parameter that can be used to restrict
+ /// the search to the options of this particular checker (and its parents
+ /// dependening on search mode).
+ /// @param [in] SearchInParents If set to true and the searched option was not
+ /// specified for the given checker the options for the parent packages will
+ /// be searched as well. The inner packages take precedence over the outer
+ /// ones.
+ bool getBooleanOption(Optional<bool> &V, StringRef Name, bool DefaultVal,
+ const ento::CheckerBase *C = nullptr,
+ bool SearchInParents = false);
+
+ /// Interprets an option's string value as an integer value.
+ ///
+ /// If an option value is not provided, returns the given \p DefaultVal.
+ /// @param [in] Name Name for option to retrieve.
+ /// @param [in] DefaultVal Default value returned if no such option was
+ /// specified.
+ /// @param [in] C The optional checker parameter that can be used to restrict
+ /// the search to the options of this particular checker (and its parents
+ /// dependening on search mode).
+ /// @param [in] SearchInParents If set to true and the searched option was not
+ /// specified for the given checker the options for the parent packages will
+ /// be searched as well. The inner packages take precedence over the outer
+ /// ones.
+ int getOptionAsInteger(StringRef Name, int DefaultVal,
+ const ento::CheckerBase *C = nullptr,
+ bool SearchInParents = false);
+
+ /// Query an option's string value.
+ ///
+ /// If an option value is not provided, returns the given \p DefaultVal.
+ /// @param [in] Name Name for option to retrieve.
+ /// @param [in] DefaultVal Default value returned if no such option was
+ /// specified.
+ /// @param [in] C The optional checker parameter that can be used to restrict
+ /// the search to the options of this particular checker (and its parents
+ /// dependening on search mode).
+ /// @param [in] SearchInParents If set to true and the searched option was not
+ /// specified for the given checker the options for the parent packages will
+ /// be searched as well. The inner packages take precedence over the outer
+ /// ones.
+ StringRef getOptionAsString(StringRef Name, StringRef DefaultVal,
+ const ento::CheckerBase *C = nullptr,
+ bool SearchInParents = false);
+
+ /// \brief Retrieves and sets the UserMode. This is a high-level option,
+ /// which is used to set other low-level options. It is not accessible
+ /// outside of AnalyzerOptions.
+ UserModeKind getUserMode();
+
+ /// \brief Returns the inter-procedural analysis mode.
+ IPAKind getIPAMode();
+
+ /// Returns the option controlling which C++ member functions will be
+ /// considered for inlining.
+ ///
+ /// This is controlled by the 'c++-inlining' config option.
+ ///
+ /// \sa CXXMemberInliningMode
+ bool mayInlineCXXMemberFunction(CXXInlineableMemberKind K);
+
+ /// Returns true if ObjectiveC inlining is enabled, false otherwise.
+ bool mayInlineObjCMethod();
+
+ /// Returns whether or not the destructors for C++ temporary objects should
+ /// be included in the CFG.
+ ///
+ /// This is controlled by the 'cfg-temporary-dtors' config option, which
+ /// accepts the values "true" and "false".
+ bool includeTemporaryDtorsInCFG();
+
+ /// Returns whether or not C++ standard library functions may be considered
+ /// for inlining.
+ ///
+ /// This is controlled by the 'c++-stdlib-inlining' config option, which
+ /// accepts the values "true" and "false".
+ bool mayInlineCXXStandardLibrary();
+
+ /// Returns whether or not templated functions may be considered for inlining.
+ ///
+ /// This is controlled by the 'c++-template-inlining' config option, which
+ /// accepts the values "true" and "false".
+ bool mayInlineTemplateFunctions();
+
+ /// Returns whether or not allocator call may be considered for inlining.
+ ///
+ /// This is controlled by the 'c++-allocator-inlining' config option, which
+ /// accepts the values "true" and "false".
+ bool mayInlineCXXAllocator();
+
+ /// Returns whether or not methods of C++ container objects may be considered
+ /// for inlining.
+ ///
+ /// This is controlled by the 'c++-container-inlining' config option, which
+ /// accepts the values "true" and "false".
+ bool mayInlineCXXContainerMethods();
+
+ /// Returns whether or not the destructor of C++ 'shared_ptr' may be
+ /// considered for inlining.
+ ///
+ /// This covers std::shared_ptr, std::tr1::shared_ptr, and boost::shared_ptr,
+ /// and indeed any destructor named "~shared_ptr".
+ ///
+ /// This is controlled by the 'c++-shared_ptr-inlining' config option, which
+ /// accepts the values "true" and "false".
+ bool mayInlineCXXSharedPtrDtor();
+
+ /// Returns whether or not paths that go through null returns should be
+ /// suppressed.
+ ///
+ /// This is a heuristic for avoiding bug reports with paths that go through
+ /// inlined functions that are more defensive than their callers.
+ ///
+ /// This is controlled by the 'suppress-null-return-paths' config option,
+ /// which accepts the values "true" and "false".
+ bool shouldSuppressNullReturnPaths();
+
+ /// Returns whether a bug report should \em not be suppressed if its path
+ /// includes a call with a null argument, even if that call has a null return.
+ ///
+ /// This option has no effect when #shouldSuppressNullReturnPaths() is false.
+ ///
+ /// This is a counter-heuristic to avoid false negatives.
+ ///
+ /// This is controlled by the 'avoid-suppressing-null-argument-paths' config
+ /// option, which accepts the values "true" and "false".
+ bool shouldAvoidSuppressingNullArgumentPaths();
+
+ /// Returns whether or not diagnostics containing inlined defensive NULL
+ /// checks should be suppressed.
+ ///
+ /// This is controlled by the 'suppress-inlined-defensive-checks' config
+ /// option, which accepts the values "true" and "false".
+ bool shouldSuppressInlinedDefensiveChecks();
+
+ /// Returns whether or not diagnostics reported within the C++ standard
+ /// library should be suppressed.
+ ///
+ /// This is controlled by the 'suppress-c++-stdlib' config option,
+ /// which accepts the values "true" and "false".
+ bool shouldSuppressFromCXXStandardLibrary();
+
+ /// Returns whether or not the diagnostic report should be always reported
+ /// in the main source file and not the headers.
+ ///
+ /// This is controlled by the 'report-in-main-source-file' config option,
+ /// which accepts the values "true" and "false".
+ bool shouldReportIssuesInMainSourceFile();
+
+ /// Returns whether or not the report filename should be random or not.
+ ///
+ /// This is controlled by the 'stable-report-filename' config option,
+ /// which accepts the values "true" and "false". Default = false
+ bool shouldWriteStableReportFilename();
+
+ /// Returns whether irrelevant parts of a bug report path should be pruned
+ /// out of the final output.
+ ///
+ /// This is controlled by the 'prune-paths' config option, which accepts the
+ /// values "true" and "false".
+ bool shouldPrunePaths();
+
+ /// Returns true if 'static' initializers should be in conditional logic
+ /// in the CFG.
+ bool shouldConditionalizeStaticInitializers();
+
+ // Returns the size of the functions (in basic blocks), which should be
+ // considered to be small enough to always inline.
+ //
+ // This is controlled by "ipa-always-inline-size" analyzer-config option.
+ unsigned getAlwaysInlineSize();
+
+ // Returns the bound on the number of basic blocks in an inlined function
+ // (50 by default).
+ //
+ // This is controlled by "-analyzer-config max-inlinable-size" option.
+ unsigned getMaxInlinableSize();
+
+ /// Returns true if the analyzer engine should synthesize fake bodies
+ /// for well-known functions.
+ bool shouldSynthesizeBodies();
+
+ /// Returns how often nodes in the ExplodedGraph should be recycled to save
+ /// memory.
+ ///
+ /// This is controlled by the 'graph-trim-interval' config option. To disable
+ /// node reclamation, set the option to "0".
+ unsigned getGraphTrimInterval();
+
+ /// Returns the maximum times a large function could be inlined.
+ ///
+ /// This is controlled by the 'max-times-inline-large' config option.
+ unsigned getMaxTimesInlineLarge();
+
+ /// Returns the number of basic blocks a function needs to have to be
+ /// considered large for the 'max-times-inline-large' config option.
+ ///
+ /// This is controlled by the 'min-cfg-size-treat-functions-as-large' config
+ /// option.
+ unsigned getMinCFGSizeTreatFunctionsAsLarge();
+
+ /// Returns the maximum number of nodes the analyzer can generate while
+ /// exploring a top level function (for each exploded graph).
+ /// 150000 is default; 0 means no limit.
+ ///
+ /// This is controlled by the 'max-nodes' config option.
+ unsigned getMaxNodesPerTopLevelFunction();
+
+ /// Returns true if lambdas should be inlined. Otherwise a sink node will be
+ /// generated each time a LambdaExpr is visited.
+ bool shouldInlineLambdas();
+
+ /// Returns true if the analysis should try to widen loops.
+ /// This is controlled by the 'widen-loops' config option.
+ bool shouldWidenLoops();
+
+public:
+ AnalyzerOptions() :
+ AnalysisStoreOpt(RegionStoreModel),
+ AnalysisConstraintsOpt(RangeConstraintsModel),
+ AnalysisDiagOpt(PD_HTML),
+ AnalysisPurgeOpt(PurgeStmt),
+ DisableAllChecks(0),
+ ShowCheckerHelp(0),
+ AnalyzeAll(0),
+ AnalyzerDisplayProgress(0),
+ AnalyzeNestedBlocks(0),
+ eagerlyAssumeBinOpBifurcation(0),
+ TrimGraph(0),
+ visualizeExplodedGraphWithGraphViz(0),
+ visualizeExplodedGraphWithUbiGraph(0),
+ UnoptimizedCFG(0),
+ PrintStats(0),
+ NoRetryExhausted(0),
+ // Cap the stack depth at 4 calls (5 stack frames, base + 4 calls).
+ InlineMaxStackDepth(5),
+ InliningMode(NoRedundancy),
+ UserMode(UMK_NotSet),
+ IPAMode(IPAK_NotSet),
+ CXXMemberInliningMode() {}
+
+};
+
+typedef IntrusiveRefCntPtr<AnalyzerOptions> AnalyzerOptionsRef;
+
+}
+
+#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..57c73fd
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/BugReporter/BugReporter.h
@@ -0,0 +1,561 @@
+//===--- 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 ProgramState.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_STATICANALYZER_CORE_BUGREPORTER_BUGREPORTER_H
+#define LLVM_CLANG_STATICANALYZER_CORE_BUGREPORTER_BUGREPORTER_H
+
+#include "clang/Basic/SourceLocation.h"
+#include "clang/StaticAnalyzer/Core/AnalyzerOptions.h"
+#include "clang/StaticAnalyzer/Core/BugReporter/BugReporterVisitor.h"
+#include "clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h"
+#include "clang/StaticAnalyzer/Core/CheckerManager.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h"
+#include "llvm/ADT/DenseSet.h"
+#include "llvm/ADT/FoldingSet.h"
+#include "llvm/ADT/ImmutableSet.h"
+#include "llvm/ADT/SmallSet.h"
+#include "llvm/ADT/ilist.h"
+#include "llvm/ADT/ilist_node.h"
+
+namespace clang {
+
+class ASTContext;
+class DiagnosticsEngine;
+class Stmt;
+class ParentMap;
+
+namespace ento {
+
+class PathDiagnostic;
+class ExplodedNode;
+class ExplodedGraph;
+class BugReport;
+class BugReporter;
+class BugReporterContext;
+class ExprEngine;
+class BugType;
+
+//===----------------------------------------------------------------------===//
+// Interface for individual bug reports.
+//===----------------------------------------------------------------------===//
+
+/// This class provides an interface through which checkers can create
+/// individual bug reports.
+class BugReport : public llvm::ilist_node<BugReport> {
+public:
+ class NodeResolver {
+ virtual void anchor();
+ public:
+ virtual ~NodeResolver() {}
+ virtual const ExplodedNode*
+ getOriginalNode(const ExplodedNode *N) = 0;
+ };
+
+ typedef const SourceRange *ranges_iterator;
+ typedef SmallVector<std::unique_ptr<BugReporterVisitor>, 8> VisitorList;
+ typedef VisitorList::iterator visitor_iterator;
+ typedef SmallVector<StringRef, 2> ExtraTextList;
+
+protected:
+ friend class BugReporter;
+ friend class BugReportEquivClass;
+
+ BugType& BT;
+ const Decl *DeclWithIssue;
+ std::string ShortDescription;
+ std::string Description;
+ PathDiagnosticLocation Location;
+ PathDiagnosticLocation UniqueingLocation;
+ const Decl *UniqueingDecl;
+
+ const ExplodedNode *ErrorNode;
+ SmallVector<SourceRange, 4> Ranges;
+ ExtraTextList ExtraText;
+
+ typedef llvm::DenseSet<SymbolRef> Symbols;
+ typedef llvm::DenseSet<const MemRegion *> Regions;
+
+ /// A (stack of) a set of symbols that are registered with this
+ /// report as being "interesting", and thus used to help decide which
+ /// diagnostics to include when constructing the final path diagnostic.
+ /// The stack is largely used by BugReporter when generating PathDiagnostics
+ /// for multiple PathDiagnosticConsumers.
+ SmallVector<Symbols *, 2> interestingSymbols;
+
+ /// A (stack of) set of regions that are registered with this report as being
+ /// "interesting", and thus used to help decide which diagnostics
+ /// to include when constructing the final path diagnostic.
+ /// The stack is largely used by BugReporter when generating PathDiagnostics
+ /// for multiple PathDiagnosticConsumers.
+ SmallVector<Regions *, 2> interestingRegions;
+
+ /// A set of location contexts that correspoind to call sites which should be
+ /// considered "interesting".
+ llvm::SmallSet<const LocationContext *, 2> InterestingLocationContexts;
+
+ /// A set of custom visitors which generate "event" diagnostics at
+ /// interesting points in the path.
+ VisitorList Callbacks;
+
+ /// Used for ensuring the visitors are only added once.
+ llvm::FoldingSet<BugReporterVisitor> CallbacksSet;
+
+ /// Used for clients to tell if the report's configuration has changed
+ /// since the last time they checked.
+ unsigned ConfigurationChangeToken;
+
+ /// When set, this flag disables all callstack pruning from a diagnostic
+ /// path. This is useful for some reports that want maximum fidelty
+ /// when reporting an issue.
+ bool DoNotPrunePath;
+
+ /// Used to track unique reasons why a bug report might be invalid.
+ ///
+ /// \sa markInvalid
+ /// \sa removeInvalidation
+ typedef std::pair<const void *, const void *> InvalidationRecord;
+
+ /// If non-empty, this bug report is likely a false positive and should not be
+ /// shown to the user.
+ ///
+ /// \sa markInvalid
+ /// \sa removeInvalidation
+ llvm::SmallSet<InvalidationRecord, 4> Invalidations;
+
+private:
+ // Used internally by BugReporter.
+ Symbols &getInterestingSymbols();
+ Regions &getInterestingRegions();
+
+ void lazyInitializeInterestingSets();
+ void pushInterestingSymbolsAndRegions();
+ void popInterestingSymbolsAndRegions();
+
+public:
+ BugReport(BugType& bt, StringRef desc, const ExplodedNode *errornode)
+ : BT(bt), DeclWithIssue(nullptr), Description(desc), ErrorNode(errornode),
+ ConfigurationChangeToken(0), DoNotPrunePath(false) {}
+
+ BugReport(BugType& bt, StringRef shortDesc, StringRef desc,
+ const ExplodedNode *errornode)
+ : BT(bt), DeclWithIssue(nullptr), ShortDescription(shortDesc),
+ Description(desc), ErrorNode(errornode), ConfigurationChangeToken(0),
+ DoNotPrunePath(false) {}
+
+ BugReport(BugType &bt, StringRef desc, PathDiagnosticLocation l)
+ : BT(bt), DeclWithIssue(nullptr), Description(desc), Location(l),
+ ErrorNode(nullptr), ConfigurationChangeToken(0), DoNotPrunePath(false) {}
+
+ /// \brief Create a BugReport with a custom uniqueing location.
+ ///
+ /// The reports that have the same report location, description, bug type, and
+ /// ranges are uniqued - only one of the equivalent reports will be presented
+ /// to the user. This method allows to rest the location which should be used
+ /// for uniquing reports. For example, memory leaks checker, could set this to
+ /// the allocation site, rather then the location where the bug is reported.
+ BugReport(BugType& bt, StringRef desc, const ExplodedNode *errornode,
+ PathDiagnosticLocation LocationToUnique, const Decl *DeclToUnique)
+ : BT(bt), DeclWithIssue(nullptr), Description(desc),
+ UniqueingLocation(LocationToUnique),
+ UniqueingDecl(DeclToUnique),
+ ErrorNode(errornode), ConfigurationChangeToken(0),
+ DoNotPrunePath(false) {}
+
+ virtual ~BugReport();
+
+ const BugType& getBugType() const { return BT; }
+ BugType& getBugType() { return BT; }
+
+ const ExplodedNode *getErrorNode() const { return ErrorNode; }
+
+ StringRef getDescription() const { return Description; }
+
+ StringRef getShortDescription(bool UseFallback = true) const {
+ if (ShortDescription.empty() && UseFallback)
+ return Description;
+ return ShortDescription;
+ }
+
+ /// Indicates whether or not any path pruning should take place
+ /// when generating a PathDiagnostic from this BugReport.
+ bool shouldPrunePath() const { return !DoNotPrunePath; }
+
+ /// Disable all path pruning when generating a PathDiagnostic.
+ void disablePathPruning() { DoNotPrunePath = true; }
+
+ void markInteresting(SymbolRef sym);
+ void markInteresting(const MemRegion *R);
+ void markInteresting(SVal V);
+ void markInteresting(const LocationContext *LC);
+
+ bool isInteresting(SymbolRef sym);
+ bool isInteresting(const MemRegion *R);
+ bool isInteresting(SVal V);
+ bool isInteresting(const LocationContext *LC);
+
+ unsigned getConfigurationChangeToken() const {
+ return ConfigurationChangeToken;
+ }
+
+ /// Returns whether or not this report should be considered valid.
+ ///
+ /// Invalid reports are those that have been classified as likely false
+ /// positives after the fact.
+ bool isValid() const {
+ return Invalidations.empty();
+ }
+
+ /// Marks the current report as invalid, meaning that it is probably a false
+ /// positive and should not be reported to the user.
+ ///
+ /// The \p Tag and \p Data arguments are intended to be opaque identifiers for
+ /// this particular invalidation, where \p Tag represents the visitor
+ /// responsible for invalidation, and \p Data represents the reason this
+ /// visitor decided to invalidate the bug report.
+ ///
+ /// \sa removeInvalidation
+ void markInvalid(const void *Tag, const void *Data) {
+ Invalidations.insert(std::make_pair(Tag, Data));
+ }
+
+ /// Reverses the effects of a previous invalidation.
+ ///
+ /// \sa markInvalid
+ void removeInvalidation(const void *Tag, const void *Data) {
+ Invalidations.erase(std::make_pair(Tag, Data));
+ }
+
+ /// Return the canonical declaration, be it a method or class, where
+ /// this issue semantically occurred.
+ const Decl *getDeclWithIssue() const;
+
+ /// Specifically set the Decl where an issue occurred. This isn't necessary
+ /// for BugReports that cover a path as it will be automatically inferred.
+ void setDeclWithIssue(const Decl *declWithIssue) {
+ DeclWithIssue = declWithIssue;
+ }
+
+ /// \brief This allows for addition of meta data to the diagnostic.
+ ///
+ /// Currently, only the HTMLDiagnosticClient knows how to display it.
+ void addExtraText(StringRef S) {
+ ExtraText.push_back(S);
+ }
+
+ virtual const ExtraTextList &getExtraText() {
+ return ExtraText;
+ }
+
+ /// \brief 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 occurred.
+ /// This location is used by clients rendering diagnostics.
+ virtual PathDiagnosticLocation getLocation(const SourceManager &SM) const;
+
+ /// \brief Get the location on which the report should be uniqued.
+ PathDiagnosticLocation getUniqueingLocation() const {
+ return UniqueingLocation;
+ }
+
+ /// \brief Get the declaration containing the uniqueing location.
+ const Decl *getUniqueingDecl() const {
+ return UniqueingDecl;
+ }
+
+ const Stmt *getStmt() const;
+
+ /// \brief Add a range to a bug report.
+ ///
+ /// Ranges are used to highlight regions of interest in the source code.
+ /// They should be at the same source code line as the BugReport location.
+ /// By default, the source range of the statement corresponding to the error
+ /// node will be used; add a single invalid range to specify absence of
+ /// ranges.
+ void addRange(SourceRange R) {
+ assert((R.isValid() || Ranges.empty()) && "Invalid range can only be used "
+ "to specify that the report does not have a range.");
+ Ranges.push_back(R);
+ }
+
+ /// \brief Get the SourceRanges associated with the report.
+ virtual llvm::iterator_range<ranges_iterator> getRanges();
+
+ /// \brief Add custom or predefined bug report visitors to this report.
+ ///
+ /// The visitors should be used when the default trace is not sufficient.
+ /// For example, they allow constructing a more elaborate trace.
+ /// \sa registerConditionVisitor(), registerTrackNullOrUndefValue(),
+ /// registerFindLastStore(), registerNilReceiverVisitor(), and
+ /// registerVarDeclsLastStore().
+ void addVisitor(std::unique_ptr<BugReporterVisitor> visitor);
+
+ /// Iterators through the custom diagnostic visitors.
+ visitor_iterator visitor_begin() { return Callbacks.begin(); }
+ visitor_iterator visitor_end() { return Callbacks.end(); }
+
+ /// Profile to identify equivalent bug reports for error report coalescing.
+ /// Reports are uniqued to ensure that we do not emit multiple diagnostics
+ /// for each bug.
+ virtual void Profile(llvm::FoldingSetNodeID& hash) const;
+};
+
+} // end ento namespace
+} // end clang namespace
+
+namespace llvm {
+ template<> struct ilist_traits<clang::ento::BugReport>
+ : public ilist_default_traits<clang::ento::BugReport> {
+ clang::ento::BugReport *createSentinel() const {
+ return static_cast<clang::ento::BugReport *>(&Sentinel);
+ }
+ void destroySentinel(clang::ento::BugReport *) const {}
+
+ clang::ento::BugReport *provideInitialHead() const {
+ return createSentinel();
+ }
+ clang::ento::BugReport *ensureHead(clang::ento::BugReport *) const {
+ return createSentinel();
+ }
+ private:
+ mutable ilist_half_node<clang::ento::BugReport> Sentinel;
+ };
+}
+
+namespace clang {
+namespace ento {
+
+//===----------------------------------------------------------------------===//
+// BugTypes (collections of related reports).
+//===----------------------------------------------------------------------===//
+
+class BugReportEquivClass : public llvm::FoldingSetNode {
+ /// List of *owned* BugReport objects.
+ llvm::ilist<BugReport> Reports;
+
+ friend class BugReporter;
+ void AddReport(std::unique_ptr<BugReport> R) {
+ Reports.push_back(R.release());
+ }
+
+public:
+ BugReportEquivClass(std::unique_ptr<BugReport> R) { AddReport(std::move(R)); }
+ ~BugReportEquivClass();
+
+ void Profile(llvm::FoldingSetNodeID& ID) const {
+ assert(!Reports.empty());
+ Reports.front().Profile(ID);
+ }
+
+ typedef llvm::ilist<BugReport>::iterator iterator;
+ typedef llvm::ilist<BugReport>::const_iterator const_iterator;
+
+ iterator begin() { return Reports.begin(); }
+ iterator end() { return Reports.end(); }
+
+ const_iterator begin() const { return Reports.begin(); }
+ const_iterator end() const { return Reports.end(); }
+};
+
+//===----------------------------------------------------------------------===//
+// BugReporter and friends.
+//===----------------------------------------------------------------------===//
+
+class BugReporterData {
+public:
+ virtual ~BugReporterData();
+ virtual DiagnosticsEngine& getDiagnostic() = 0;
+ virtual ArrayRef<PathDiagnosticConsumer*> getPathDiagnosticConsumers() = 0;
+ virtual ASTContext &getASTContext() = 0;
+ virtual SourceManager& getSourceManager() = 0;
+ virtual AnalyzerOptions& getAnalyzerOptions() = 0;
+};
+
+/// BugReporter is a utility class for generating PathDiagnostics for analysis.
+/// It collects the BugReports and BugTypes and knows how to generate
+/// and flush the corresponding diagnostics.
+class BugReporter {
+public:
+ enum Kind { BaseBRKind, GRBugReporterKind };
+
+private:
+ typedef llvm::ImmutableSet<BugType*> BugTypesTy;
+ BugTypesTy::Factory F;
+ BugTypesTy BugTypes;
+
+ const Kind kind;
+ BugReporterData& D;
+
+ /// Generate and flush the diagnostics for the given bug report.
+ void FlushReport(BugReportEquivClass& EQ);
+
+ /// Generate and flush the diagnostics for the given bug report
+ /// and PathDiagnosticConsumer.
+ void FlushReport(BugReport *exampleReport,
+ PathDiagnosticConsumer &PD,
+ ArrayRef<BugReport*> BugReports);
+
+ /// The set of bug reports tracked by the BugReporter.
+ llvm::FoldingSet<BugReportEquivClass> EQClasses;
+ /// A vector of BugReports for tracking the allocated pointers and cleanup.
+ std::vector<BugReportEquivClass *> EQClassesVector;
+
+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();
+
+ /// \brief Generate and flush diagnostics for all bug reports.
+ void FlushReports();
+
+ Kind getKind() const { return kind; }
+
+ DiagnosticsEngine& getDiagnostic() {
+ return D.getDiagnostic();
+ }
+
+ ArrayRef<PathDiagnosticConsumer*> getPathDiagnosticConsumers() {
+ return D.getPathDiagnosticConsumers();
+ }
+
+ /// \brief Iterator over the set of BugTypes tracked by the BugReporter.
+ typedef BugTypesTy::iterator iterator;
+ iterator begin() { return BugTypes.begin(); }
+ iterator end() { return BugTypes.end(); }
+
+ /// \brief Iterator over the set of BugReports tracked by the BugReporter.
+ typedef llvm::FoldingSet<BugReportEquivClass>::iterator EQClasses_iterator;
+ EQClasses_iterator EQClasses_begin() { return EQClasses.begin(); }
+ EQClasses_iterator EQClasses_end() { return EQClasses.end(); }
+
+ ASTContext &getContext() { return D.getASTContext(); }
+
+ SourceManager& getSourceManager() { return D.getSourceManager(); }
+
+ AnalyzerOptions& getAnalyzerOptions() { return D.getAnalyzerOptions(); }
+
+ virtual bool generatePathDiagnostic(PathDiagnostic& pathDiagnostic,
+ PathDiagnosticConsumer &PC,
+ ArrayRef<BugReport *> &bugReports) {
+ return true;
+ }
+
+ bool RemoveUnneededCalls(PathPieces &pieces, BugReport *R);
+
+ void Register(BugType *BT);
+
+ /// \brief Add the given report to the set of reports tracked by BugReporter.
+ ///
+ /// The reports are usually generated by the checkers. Further, they are
+ /// folded based on the profile value, which is done to coalesce similar
+ /// reports.
+ void emitReport(std::unique_ptr<BugReport> R);
+
+ void EmitBasicReport(const Decl *DeclWithIssue, const CheckerBase *Checker,
+ StringRef BugName, StringRef BugCategory,
+ StringRef BugStr, PathDiagnosticLocation Loc,
+ ArrayRef<SourceRange> Ranges = None);
+
+ void EmitBasicReport(const Decl *DeclWithIssue, CheckName CheckName,
+ StringRef BugName, StringRef BugCategory,
+ StringRef BugStr, PathDiagnosticLocation Loc,
+ ArrayRef<SourceRange> Ranges = None);
+
+private:
+ llvm::StringMap<BugType *> StrBugTypes;
+
+ /// \brief Returns a BugType that is associated with the given name and
+ /// category.
+ BugType *getBugTypeForName(CheckName CheckName, StringRef name,
+ StringRef category);
+};
+
+// FIXME: Get rid of GRBugReporter. It's the wrong abstraction.
+class GRBugReporter : public BugReporter {
+ ExprEngine& Eng;
+public:
+ GRBugReporter(BugReporterData& d, ExprEngine& eng)
+ : BugReporter(d, GRBugReporterKind), Eng(eng) {}
+
+ ~GRBugReporter() override;
+
+ /// 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.
+ ProgramStateManager &getStateManager();
+
+ /// Generates a path corresponding to one of the given bug reports.
+ ///
+ /// Which report is used for path generation is not specified. The
+ /// bug reporter will try to pick the shortest path, but this is not
+ /// guaranteed.
+ ///
+ /// \return True if the report was valid and a path was generated,
+ /// false if the reports should be considered invalid.
+ bool generatePathDiagnostic(PathDiagnostic &PD, PathDiagnosticConsumer &PC,
+ ArrayRef<BugReport*> &bugReports) override;
+
+ /// classof - Used by isa<>, cast<>, and dyn_cast<>.
+ static bool classof(const BugReporter* R) {
+ return R->getKind() == GRBugReporterKind;
+ }
+};
+
+class BugReporterContext {
+ virtual void anchor();
+ GRBugReporter &BR;
+public:
+ BugReporterContext(GRBugReporter& br) : BR(br) {}
+
+ virtual ~BugReporterContext() {}
+
+ GRBugReporter& getBugReporter() { return BR; }
+
+ ExplodedGraph &getGraph() { return BR.getGraph(); }
+
+ ProgramStateManager& getStateManager() {
+ return BR.getStateManager();
+ }
+
+ SValBuilder& getSValBuilder() {
+ return getStateManager().getSValBuilder();
+ }
+
+ ASTContext &getASTContext() {
+ return BR.getContext();
+ }
+
+ SourceManager& getSourceManager() {
+ return BR.getSourceManager();
+ }
+
+ virtual BugReport::NodeResolver& getNodeResolver() = 0;
+};
+
+} // end GR namespace
+
+} // end clang namespace
+
+#endif
diff --git a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/BugReporter/BugReporterVisitor.h b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/BugReporter/BugReporterVisitor.h
new file mode 100644
index 0000000..197d27a
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/BugReporter/BugReporterVisitor.h
@@ -0,0 +1,366 @@
+//===--- BugReporterVisitor.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 declares BugReporterVisitors, which are used to generate enhanced
+// diagnostic traces.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_STATICANALYZER_CORE_BUGREPORTER_BUGREPORTERVISITOR_H
+#define LLVM_CLANG_STATICANALYZER_CORE_BUGREPORTER_BUGREPORTERVISITOR_H
+
+#include "clang/StaticAnalyzer/Core/PathSensitive/SVals.h"
+#include "llvm/ADT/FoldingSet.h"
+
+namespace clang {
+
+namespace ento {
+
+class BugReport;
+class BugReporterContext;
+class ExplodedNode;
+class MemRegion;
+class PathDiagnosticPiece;
+
+/// \brief BugReporterVisitors are used to add custom diagnostics along a path.
+///
+/// Custom visitors should subclass the BugReporterVisitorImpl class for a
+/// default implementation of the clone() method.
+/// (Warning: if you have a deep subclass of BugReporterVisitorImpl, the
+/// default implementation of clone() will NOT do the right thing, and you
+/// will have to provide your own implementation.)
+class BugReporterVisitor : public llvm::FoldingSetNode {
+public:
+ BugReporterVisitor() = default;
+ BugReporterVisitor(const BugReporterVisitor &) = default;
+ BugReporterVisitor(BugReporterVisitor &&) {}
+ virtual ~BugReporterVisitor();
+
+ /// \brief Returns a copy of this BugReporter.
+ ///
+ /// Custom BugReporterVisitors should not override this method directly.
+ /// Instead, they should inherit from BugReporterVisitorImpl and provide
+ /// a protected or public copy constructor.
+ ///
+ /// (Warning: if you have a deep subclass of BugReporterVisitorImpl, the
+ /// default implementation of clone() will NOT do the right thing, and you
+ /// will have to provide your own implementation.)
+ virtual std::unique_ptr<BugReporterVisitor> clone() const = 0;
+
+ /// \brief Return a diagnostic piece which should be associated with the
+ /// given node.
+ ///
+ /// The last parameter can be used to register a new visitor with the given
+ /// BugReport while processing a node.
+ virtual PathDiagnosticPiece *VisitNode(const ExplodedNode *Succ,
+ const ExplodedNode *Pred,
+ BugReporterContext &BRC,
+ BugReport &BR) = 0;
+
+ /// \brief Provide custom definition for the final diagnostic piece on the
+ /// path - the piece, which is displayed before the path is expanded.
+ ///
+ /// If returns NULL the default implementation will be used.
+ /// Also note that at most one visitor of a BugReport should generate a
+ /// non-NULL end of path diagnostic piece.
+ virtual std::unique_ptr<PathDiagnosticPiece>
+ getEndPath(BugReporterContext &BRC, const ExplodedNode *N, BugReport &BR);
+
+ virtual void Profile(llvm::FoldingSetNodeID &ID) const = 0;
+
+ /// \brief Generates the default final diagnostic piece.
+ static std::unique_ptr<PathDiagnosticPiece>
+ getDefaultEndPath(BugReporterContext &BRC, const ExplodedNode *N,
+ BugReport &BR);
+};
+
+/// This class provides a convenience implementation for clone() using the
+/// Curiously-Recurring Template Pattern. If you are implementing a custom
+/// BugReporterVisitor, subclass BugReporterVisitorImpl and provide a public
+/// or protected copy constructor.
+///
+/// (Warning: if you have a deep subclass of BugReporterVisitorImpl, the
+/// default implementation of clone() will NOT do the right thing, and you
+/// will have to provide your own implementation.)
+template <class DERIVED>
+class BugReporterVisitorImpl : public BugReporterVisitor {
+ std::unique_ptr<BugReporterVisitor> clone() const override {
+ return llvm::make_unique<DERIVED>(*static_cast<const DERIVED *>(this));
+ }
+};
+
+class FindLastStoreBRVisitor final
+ : public BugReporterVisitorImpl<FindLastStoreBRVisitor> {
+ const MemRegion *R;
+ SVal V;
+ bool Satisfied;
+
+ /// If the visitor is tracking the value directly responsible for the
+ /// bug, we are going to employ false positive suppression.
+ bool EnableNullFPSuppression;
+
+public:
+ /// Creates a visitor for every VarDecl inside a Stmt and registers it with
+ /// the BugReport.
+ static void registerStatementVarDecls(BugReport &BR, const Stmt *S,
+ bool EnableNullFPSuppression);
+
+ FindLastStoreBRVisitor(KnownSVal V, const MemRegion *R,
+ bool InEnableNullFPSuppression)
+ : R(R),
+ V(V),
+ Satisfied(false),
+ EnableNullFPSuppression(InEnableNullFPSuppression) {}
+
+ void Profile(llvm::FoldingSetNodeID &ID) const override;
+
+ PathDiagnosticPiece *VisitNode(const ExplodedNode *N,
+ const ExplodedNode *PrevN,
+ BugReporterContext &BRC,
+ BugReport &BR) override;
+};
+
+class TrackConstraintBRVisitor final
+ : public BugReporterVisitorImpl<TrackConstraintBRVisitor> {
+ DefinedSVal Constraint;
+ bool Assumption;
+ bool IsSatisfied;
+ bool IsZeroCheck;
+
+ /// We should start tracking from the last node along the path in which the
+ /// value is constrained.
+ bool IsTrackingTurnedOn;
+
+public:
+ TrackConstraintBRVisitor(DefinedSVal constraint, bool assumption)
+ : Constraint(constraint), Assumption(assumption), IsSatisfied(false),
+ IsZeroCheck(!Assumption && Constraint.getAs<Loc>()),
+ IsTrackingTurnedOn(false) {}
+
+ void Profile(llvm::FoldingSetNodeID &ID) const override;
+
+ /// Return the tag associated with this visitor. This tag will be used
+ /// to make all PathDiagnosticPieces created by this visitor.
+ static const char *getTag();
+
+ PathDiagnosticPiece *VisitNode(const ExplodedNode *N,
+ const ExplodedNode *PrevN,
+ BugReporterContext &BRC,
+ BugReport &BR) override;
+
+private:
+ /// Checks if the constraint is valid in the current state.
+ bool isUnderconstrained(const ExplodedNode *N) const;
+
+};
+
+/// \class NilReceiverBRVisitor
+/// \brief Prints path notes when a message is sent to a nil receiver.
+class NilReceiverBRVisitor final
+ : public BugReporterVisitorImpl<NilReceiverBRVisitor> {
+public:
+
+ void Profile(llvm::FoldingSetNodeID &ID) const override {
+ static int x = 0;
+ ID.AddPointer(&x);
+ }
+
+ PathDiagnosticPiece *VisitNode(const ExplodedNode *N,
+ const ExplodedNode *PrevN,
+ BugReporterContext &BRC,
+ BugReport &BR) override;
+
+ /// If the statement is a message send expression with nil receiver, returns
+ /// the receiver expression. Returns NULL otherwise.
+ static const Expr *getNilReceiver(const Stmt *S, const ExplodedNode *N);
+};
+
+/// Visitor that tries to report interesting diagnostics from conditions.
+class ConditionBRVisitor final
+ : public BugReporterVisitorImpl<ConditionBRVisitor> {
+public:
+ void Profile(llvm::FoldingSetNodeID &ID) const override {
+ static int x = 0;
+ ID.AddPointer(&x);
+ }
+
+ /// Return the tag associated with this visitor. This tag will be used
+ /// to make all PathDiagnosticPieces created by this visitor.
+ static const char *getTag();
+
+ PathDiagnosticPiece *VisitNode(const ExplodedNode *N,
+ const ExplodedNode *Prev,
+ BugReporterContext &BRC,
+ BugReport &BR) override;
+
+ PathDiagnosticPiece *VisitNodeImpl(const ExplodedNode *N,
+ const ExplodedNode *Prev,
+ BugReporterContext &BRC,
+ BugReport &BR);
+
+ PathDiagnosticPiece *VisitTerminator(const Stmt *Term,
+ const ExplodedNode *N,
+ const CFGBlock *srcBlk,
+ const CFGBlock *dstBlk,
+ BugReport &R,
+ BugReporterContext &BRC);
+
+ PathDiagnosticPiece *VisitTrueTest(const Expr *Cond,
+ bool tookTrue,
+ BugReporterContext &BRC,
+ BugReport &R,
+ const ExplodedNode *N);
+
+ PathDiagnosticPiece *VisitTrueTest(const Expr *Cond,
+ const DeclRefExpr *DR,
+ const bool tookTrue,
+ BugReporterContext &BRC,
+ BugReport &R,
+ const ExplodedNode *N);
+
+ PathDiagnosticPiece *VisitTrueTest(const Expr *Cond,
+ const BinaryOperator *BExpr,
+ const bool tookTrue,
+ BugReporterContext &BRC,
+ BugReport &R,
+ const ExplodedNode *N);
+
+ PathDiagnosticPiece *VisitConditionVariable(StringRef LhsString,
+ const Expr *CondVarExpr,
+ const bool tookTrue,
+ BugReporterContext &BRC,
+ BugReport &R,
+ const ExplodedNode *N);
+
+ bool patternMatch(const Expr *Ex,
+ raw_ostream &Out,
+ BugReporterContext &BRC,
+ BugReport &R,
+ const ExplodedNode *N,
+ Optional<bool> &prunable);
+};
+
+/// \brief Suppress reports that might lead to known false positives.
+///
+/// Currently this suppresses reports based on locations of bugs.
+class LikelyFalsePositiveSuppressionBRVisitor final
+ : public BugReporterVisitorImpl<LikelyFalsePositiveSuppressionBRVisitor> {
+public:
+ static void *getTag() {
+ static int Tag = 0;
+ return static_cast<void *>(&Tag);
+ }
+
+ void Profile(llvm::FoldingSetNodeID &ID) const override {
+ ID.AddPointer(getTag());
+ }
+
+ PathDiagnosticPiece *VisitNode(const ExplodedNode *N,
+ const ExplodedNode *Prev,
+ BugReporterContext &BRC,
+ BugReport &BR) override {
+ return nullptr;
+ }
+
+ std::unique_ptr<PathDiagnosticPiece> getEndPath(BugReporterContext &BRC,
+ const ExplodedNode *N,
+ BugReport &BR) override;
+};
+
+/// \brief When a region containing undefined value or '0' value is passed
+/// as an argument in a call, marks the call as interesting.
+///
+/// As a result, BugReporter will not prune the path through the function even
+/// if the region's contents are not modified/accessed by the call.
+class UndefOrNullArgVisitor final
+ : public BugReporterVisitorImpl<UndefOrNullArgVisitor> {
+
+ /// The interesting memory region this visitor is tracking.
+ const MemRegion *R;
+
+public:
+ UndefOrNullArgVisitor(const MemRegion *InR) : R(InR) {}
+
+ void Profile(llvm::FoldingSetNodeID &ID) const override {
+ static int Tag = 0;
+ ID.AddPointer(&Tag);
+ ID.AddPointer(R);
+ }
+
+ PathDiagnosticPiece *VisitNode(const ExplodedNode *N,
+ const ExplodedNode *PrevN,
+ BugReporterContext &BRC,
+ BugReport &BR) override;
+};
+
+class SuppressInlineDefensiveChecksVisitor final
+ : public BugReporterVisitorImpl<SuppressInlineDefensiveChecksVisitor> {
+ /// The symbolic value for which we are tracking constraints.
+ /// This value is constrained to null in the end of path.
+ DefinedSVal V;
+
+ /// Track if we found the node where the constraint was first added.
+ bool IsSatisfied;
+
+ /// Since the visitors can be registered on nodes previous to the last
+ /// node in the BugReport, but the path traversal always starts with the last
+ /// node, the visitor invariant (that we start with a node in which V is null)
+ /// might not hold when node visitation starts. We are going to start tracking
+ /// from the last node in which the value is null.
+ bool IsTrackingTurnedOn;
+
+public:
+ SuppressInlineDefensiveChecksVisitor(DefinedSVal Val, const ExplodedNode *N);
+
+ void Profile(llvm::FoldingSetNodeID &ID) const override;
+
+ /// Return the tag associated with this visitor. This tag will be used
+ /// to make all PathDiagnosticPieces created by this visitor.
+ static const char *getTag();
+
+ PathDiagnosticPiece *VisitNode(const ExplodedNode *Succ,
+ const ExplodedNode *Pred,
+ BugReporterContext &BRC,
+ BugReport &BR) override;
+};
+
+namespace bugreporter {
+
+/// Attempts to add visitors to trace a null or undefined value back to its
+/// point of origin, whether it is a symbol constrained to null or an explicit
+/// assignment.
+///
+/// \param N A node "downstream" from the evaluation of the statement.
+/// \param S The statement whose value is null or undefined.
+/// \param R The bug report to which visitors should be attached.
+/// \param IsArg Whether the statement is an argument to an inlined function.
+/// If this is the case, \p N \em must be the CallEnter node for
+/// the function.
+/// \param EnableNullFPSuppression Whether we should employ false positive
+/// suppression (inlined defensive checks, returned null).
+///
+/// \return Whether or not the function was able to add visitors for this
+/// statement. Note that returning \c true does not actually imply
+/// that any visitors were added.
+bool trackNullOrUndefValue(const ExplodedNode *N, const Stmt *S, BugReport &R,
+ bool IsArg = false,
+ bool EnableNullFPSuppression = true);
+
+const Expr *getDerefExpr(const Stmt *S);
+const Stmt *GetDenomExpr(const ExplodedNode *N);
+const Stmt *GetRetValExpr(const ExplodedNode *N);
+bool isDeclRefExprToReference(const Expr *E);
+
+
+} // end namespace clang
+} // end namespace ento
+} // end namespace bugreporter
+
+
+#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..16226e9
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/BugReporter/BugType.h
@@ -0,0 +1,81 @@
+//===--- 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_STATICANALYZER_CORE_BUGREPORTER_BUGTYPE_H
+#define LLVM_CLANG_STATICANALYZER_CORE_BUGREPORTER_BUGTYPE_H
+
+#include "clang/Basic/LLVM.h"
+#include "clang/StaticAnalyzer/Core/BugReporter/CommonBugCategories.h"
+#include "clang/StaticAnalyzer/Core/Checker.h"
+#include "llvm/ADT/FoldingSet.h"
+#include <string>
+
+namespace clang {
+
+namespace ento {
+
+class BugReporter;
+class ExplodedNode;
+class ExprEngine;
+
+class BugType {
+private:
+ const CheckName Check;
+ const std::string Name;
+ const std::string Category;
+ bool SuppressonSink;
+
+ virtual void anchor();
+public:
+ BugType(class CheckName check, StringRef name, StringRef cat)
+ : Check(check), Name(name), Category(cat), SuppressonSink(false) {}
+ BugType(const CheckerBase *checker, StringRef name, StringRef cat)
+ : Check(checker->getCheckName()), Name(name), Category(cat),
+ SuppressonSink(false) {}
+ virtual ~BugType() {}
+
+ // FIXME: Should these be made strings as well?
+ StringRef getName() const { return Name; }
+ StringRef getCategory() const { return Category; }
+ StringRef getCheckName() const { return Check.getName(); }
+
+ /// 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);
+};
+
+class BuiltinBug : public BugType {
+ const std::string desc;
+ void anchor() override;
+public:
+ BuiltinBug(class CheckName check, const char *name, const char *description)
+ : BugType(check, name, categories::LogicError), desc(description) {}
+
+ BuiltinBug(const CheckerBase *checker, const char *name,
+ const char *description)
+ : BugType(checker, name, categories::LogicError), desc(description) {}
+
+ BuiltinBug(const CheckerBase *checker, const char *name)
+ : BugType(checker, name, categories::LogicError), desc(name) {}
+
+ StringRef getDescription() const { return desc; }
+};
+
+} // end GR namespace
+
+} // end clang namespace
+#endif
diff --git a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/BugReporter/CommonBugCategories.h b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/BugReporter/CommonBugCategories.h
new file mode 100644
index 0000000..8df2bc3
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/BugReporter/CommonBugCategories.h
@@ -0,0 +1,25 @@
+//=--- CommonBugCategories.h - Provides common issue categories -*- 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_STATICANALYZER_CORE_BUGREPORTER_COMMONBUGCATEGORIES_H
+#define LLVM_CLANG_STATICANALYZER_CORE_BUGREPORTER_COMMONBUGCATEGORIES_H
+
+// Common strings used for the "category" of many static analyzer issues.
+namespace clang {
+ namespace ento {
+ namespace categories {
+ extern const char * const CoreFoundationObjectiveC;
+ extern const char * const LogicError;
+ extern const char * const MemoryCoreFoundationObjectiveC;
+ extern const char * const UnixAPI;
+ }
+ }
+}
+#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..35421f9
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h
@@ -0,0 +1,848 @@
+//===--- 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_STATICANALYZER_CORE_BUGREPORTER_PATHDIAGNOSTIC_H
+#define LLVM_CLANG_STATICANALYZER_CORE_BUGREPORTER_PATHDIAGNOSTIC_H
+
+#include "clang/Analysis/ProgramPoint.h"
+#include "clang/Basic/SourceLocation.h"
+#include "llvm/ADT/FoldingSet.h"
+#include "llvm/ADT/IntrusiveRefCntPtr.h"
+#include "llvm/ADT/Optional.h"
+#include "llvm/ADT/PointerUnion.h"
+#include <deque>
+#include <iterator>
+#include <list>
+#include <string>
+#include <vector>
+
+namespace clang {
+class ConditionalOperator;
+class AnalysisDeclContext;
+class BinaryOperator;
+class CompoundStmt;
+class Decl;
+class LocationContext;
+class MemberExpr;
+class ParentMap;
+class ProgramPoint;
+class SourceManager;
+class Stmt;
+class CallExpr;
+
+namespace ento {
+
+class ExplodedNode;
+class SymExpr;
+typedef const SymExpr* SymbolRef;
+
+//===----------------------------------------------------------------------===//
+// High-level interface for handlers of path-sensitive diagnostics.
+//===----------------------------------------------------------------------===//
+
+class PathDiagnostic;
+
+class PathDiagnosticConsumer {
+public:
+ class PDFileEntry : public llvm::FoldingSetNode {
+ public:
+ PDFileEntry(llvm::FoldingSetNodeID &NodeID) : NodeID(NodeID) {}
+
+ typedef std::vector<std::pair<StringRef, StringRef> > ConsumerFiles;
+
+ /// \brief A vector of <consumer,file> pairs.
+ ConsumerFiles files;
+
+ /// \brief A precomputed hash tag used for uniquing PDFileEntry objects.
+ const llvm::FoldingSetNodeID NodeID;
+
+ /// \brief Used for profiling in the FoldingSet.
+ void Profile(llvm::FoldingSetNodeID &ID) { ID = NodeID; }
+ };
+
+ class FilesMade {
+ llvm::BumpPtrAllocator Alloc;
+ llvm::FoldingSet<PDFileEntry> Set;
+
+ public:
+ ~FilesMade();
+
+ bool empty() const { return Set.empty(); }
+
+ void addDiagnostic(const PathDiagnostic &PD,
+ StringRef ConsumerName,
+ StringRef fileName);
+
+ PDFileEntry::ConsumerFiles *getFiles(const PathDiagnostic &PD);
+ };
+
+private:
+ virtual void anchor();
+public:
+ PathDiagnosticConsumer() : flushed(false) {}
+ virtual ~PathDiagnosticConsumer();
+
+ void FlushDiagnostics(FilesMade *FilesMade);
+
+ virtual void FlushDiagnosticsImpl(std::vector<const PathDiagnostic *> &Diags,
+ FilesMade *filesMade) = 0;
+
+ virtual StringRef getName() const = 0;
+
+ void HandlePathDiagnostic(std::unique_ptr<PathDiagnostic> D);
+
+ enum PathGenerationScheme { None, Minimal, Extensive, AlternateExtensive };
+ virtual PathGenerationScheme getGenerationScheme() const { return Minimal; }
+ virtual bool supportsLogicalOpControlFlow() const { return false; }
+
+ /// Return true if the PathDiagnosticConsumer supports individual
+ /// PathDiagnostics that span multiple files.
+ virtual bool supportsCrossFileDiagnostics() const { return false; }
+
+protected:
+ bool flushed;
+ llvm::FoldingSet<PathDiagnostic> Diags;
+};
+
+//===----------------------------------------------------------------------===//
+// Path-sensitive diagnostics.
+//===----------------------------------------------------------------------===//
+
+class PathDiagnosticRange : public SourceRange {
+public:
+ bool isPoint;
+
+ PathDiagnosticRange(SourceRange R, bool isP = false)
+ : SourceRange(R), isPoint(isP) {}
+
+ PathDiagnosticRange() : isPoint(false) {}
+};
+
+typedef llvm::PointerUnion<const LocationContext*, AnalysisDeclContext*>
+ LocationOrAnalysisDeclContext;
+
+class PathDiagnosticLocation {
+private:
+ enum Kind { RangeK, SingleLocK, StmtK, DeclK } K;
+ const Stmt *S;
+ const Decl *D;
+ const SourceManager *SM;
+ FullSourceLoc Loc;
+ PathDiagnosticRange Range;
+
+ PathDiagnosticLocation(SourceLocation L, const SourceManager &sm,
+ Kind kind)
+ : K(kind), S(nullptr), D(nullptr), SM(&sm),
+ Loc(genLocation(L)), Range(genRange()) {
+ }
+
+ FullSourceLoc genLocation(
+ SourceLocation L = SourceLocation(),
+ LocationOrAnalysisDeclContext LAC = (AnalysisDeclContext *)nullptr) const;
+
+ PathDiagnosticRange genRange(
+ LocationOrAnalysisDeclContext LAC = (AnalysisDeclContext *)nullptr) const;
+
+public:
+ /// Create an invalid location.
+ PathDiagnosticLocation()
+ : K(SingleLocK), S(nullptr), D(nullptr), SM(nullptr) {}
+
+ /// Create a location corresponding to the given statement.
+ PathDiagnosticLocation(const Stmt *s,
+ const SourceManager &sm,
+ LocationOrAnalysisDeclContext lac)
+ : K(s->getLocStart().isValid() ? StmtK : SingleLocK),
+ S(K == StmtK ? s : nullptr),
+ D(nullptr), SM(&sm),
+ Loc(genLocation(SourceLocation(), lac)),
+ Range(genRange(lac)) {
+ assert(K == SingleLocK || S);
+ assert(K == SingleLocK || Loc.isValid());
+ assert(K == SingleLocK || Range.isValid());
+ }
+
+ /// Create a location corresponding to the given declaration.
+ PathDiagnosticLocation(const Decl *d, const SourceManager &sm)
+ : K(DeclK), S(nullptr), D(d), SM(&sm),
+ Loc(genLocation()), Range(genRange()) {
+ assert(D);
+ assert(Loc.isValid());
+ assert(Range.isValid());
+ }
+
+ /// Create a location at an explicit offset in the source.
+ ///
+ /// This should only be used if there are no more appropriate constructors.
+ PathDiagnosticLocation(SourceLocation loc, const SourceManager &sm)
+ : K(SingleLocK), S(nullptr), D(nullptr), SM(&sm), Loc(loc, sm),
+ Range(genRange()) {
+ assert(Loc.isValid());
+ assert(Range.isValid());
+ }
+
+ /// Create a location corresponding to the given declaration.
+ static PathDiagnosticLocation create(const Decl *D,
+ const SourceManager &SM) {
+ return PathDiagnosticLocation(D, SM);
+ }
+
+ /// Create a location for the beginning of the declaration.
+ static PathDiagnosticLocation createBegin(const Decl *D,
+ const SourceManager &SM);
+
+ /// Create a location for the beginning of the statement.
+ static PathDiagnosticLocation createBegin(const Stmt *S,
+ const SourceManager &SM,
+ const LocationOrAnalysisDeclContext LAC);
+
+ /// Create a location for the end of the statement.
+ ///
+ /// If the statement is a CompoundStatement, the location will point to the
+ /// closing brace instead of following it.
+ static PathDiagnosticLocation createEnd(const Stmt *S,
+ const SourceManager &SM,
+ const LocationOrAnalysisDeclContext LAC);
+
+ /// Create the location for the operator of the binary expression.
+ /// Assumes the statement has a valid location.
+ static PathDiagnosticLocation createOperatorLoc(const BinaryOperator *BO,
+ const SourceManager &SM);
+ static PathDiagnosticLocation createConditionalColonLoc(
+ const ConditionalOperator *CO,
+ const SourceManager &SM);
+
+ /// For member expressions, return the location of the '.' or '->'.
+ /// Assumes the statement has a valid location.
+ static PathDiagnosticLocation createMemberLoc(const MemberExpr *ME,
+ const SourceManager &SM);
+
+ /// Create a location for the beginning of the compound statement.
+ /// Assumes the statement has a valid location.
+ static PathDiagnosticLocation createBeginBrace(const CompoundStmt *CS,
+ const SourceManager &SM);
+
+ /// Create a location for the end of the compound statement.
+ /// Assumes the statement has a valid location.
+ static PathDiagnosticLocation createEndBrace(const CompoundStmt *CS,
+ const SourceManager &SM);
+
+ /// Create a location for the beginning of the enclosing declaration body.
+ /// Defaults to the beginning of the first statement in the declaration body.
+ static PathDiagnosticLocation createDeclBegin(const LocationContext *LC,
+ const SourceManager &SM);
+
+ /// Constructs a location for the end of the enclosing declaration body.
+ /// Defaults to the end of brace.
+ static PathDiagnosticLocation createDeclEnd(const LocationContext *LC,
+ const SourceManager &SM);
+
+ /// Create a location corresponding to the given valid ExplodedNode.
+ static PathDiagnosticLocation create(const ProgramPoint& P,
+ const SourceManager &SMng);
+
+ /// Create a location corresponding to the next valid ExplodedNode as end
+ /// of path location.
+ static PathDiagnosticLocation createEndOfPath(const ExplodedNode* N,
+ const SourceManager &SM);
+
+ /// Convert the given location into a single kind location.
+ static PathDiagnosticLocation createSingleLocation(
+ const PathDiagnosticLocation &PDL);
+
+ bool operator==(const PathDiagnosticLocation &X) const {
+ return K == X.K && Loc == X.Loc && Range == X.Range;
+ }
+
+ bool operator!=(const PathDiagnosticLocation &X) const {
+ return !(*this == X);
+ }
+
+ bool isValid() const {
+ return SM != nullptr;
+ }
+
+ FullSourceLoc asLocation() const {
+ return Loc;
+ }
+
+ PathDiagnosticRange asRange() const {
+ return Range;
+ }
+
+ 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;
+
+ void dump() const;
+
+ /// \brief Given an exploded node, retrieve the statement that should be used
+ /// for the diagnostic location.
+ static const Stmt *getStmt(const ExplodedNode *N);
+
+ /// \brief Retrieve the statement corresponding to the successor node.
+ static const Stmt *getNextStmt(const ExplodedNode *N);
+};
+
+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 setStart(const PathDiagnosticLocation &L) { Start = L; }
+ void setEnd(const PathDiagnosticLocation &L) { End = L; }
+
+ 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 RefCountedBaseVPTR {
+public:
+ enum Kind { ControlFlow, Event, Macro, Call };
+ enum DisplayHint { Above, Below };
+
+private:
+ const std::string str;
+ const Kind kind;
+ const DisplayHint Hint;
+
+ /// \brief In the containing bug report, this piece is the last piece from
+ /// the main source file.
+ bool LastInMainSourceFile;
+
+ /// A constant string that can be used to tag the PathDiagnosticPiece,
+ /// typically with the identification of the creator. The actual pointer
+ /// value is meant to be an identifier; the string itself is useful for
+ /// debugging.
+ StringRef Tag;
+
+ std::vector<SourceRange> ranges;
+
+ PathDiagnosticPiece() = delete;
+ PathDiagnosticPiece(const PathDiagnosticPiece &P) = delete;
+ void operator=(const PathDiagnosticPiece &P) = delete;
+
+protected:
+ PathDiagnosticPiece(StringRef s, Kind k, DisplayHint hint = Below);
+
+ PathDiagnosticPiece(Kind k, DisplayHint hint = Below);
+
+public:
+ ~PathDiagnosticPiece() override;
+
+ StringRef getString() const { return str; }
+
+ /// Tag this PathDiagnosticPiece with the given C-string.
+ void setTag(const char *tag) { Tag = tag; }
+
+ /// Return the opaque tag (if any) on the PathDiagnosticPiece.
+ const void *getTag() const { return Tag.data(); }
+
+ /// Return the string representation of the tag. This is useful
+ /// for debugging.
+ StringRef getTagStr() const { return Tag; }
+
+ /// getDisplayHint - Return a hint indicating where the diagnostic should
+ /// be displayed by the PathDiagnosticConsumer.
+ DisplayHint getDisplayHint() const { return Hint; }
+
+ virtual PathDiagnosticLocation getLocation() const = 0;
+ virtual void flattenLocations() = 0;
+
+ Kind getKind() const { return kind; }
+
+ void addRange(SourceRange R) {
+ if (!R.isValid())
+ return;
+ ranges.push_back(R);
+ }
+
+ void addRange(SourceLocation B, SourceLocation E) {
+ if (!B.isValid() || !E.isValid())
+ return;
+ ranges.push_back(SourceRange(B,E));
+ }
+
+ /// Return the SourceRanges associated with this PathDiagnosticPiece.
+ ArrayRef<SourceRange> getRanges() const { return ranges; }
+
+ virtual void Profile(llvm::FoldingSetNodeID &ID) const;
+
+ void setAsLastInMainSourceFile() {
+ LastInMainSourceFile = true;
+ }
+
+ bool isLastInMainSourceFile() const {
+ return LastInMainSourceFile;
+ }
+
+ virtual void dump() const = 0;
+};
+
+
+class PathPieces : public std::list<IntrusiveRefCntPtr<PathDiagnosticPiece> > {
+ void flattenTo(PathPieces &Primary, PathPieces &Current,
+ bool ShouldFlattenMacros) const;
+public:
+
+ PathPieces flatten(bool ShouldFlattenMacros) const {
+ PathPieces Result;
+ flattenTo(Result, Result, ShouldFlattenMacros);
+ return Result;
+ }
+
+ void dump() const;
+};
+
+class PathDiagnosticSpotPiece : public PathDiagnosticPiece {
+private:
+ PathDiagnosticLocation Pos;
+public:
+ PathDiagnosticSpotPiece(const PathDiagnosticLocation &pos,
+ StringRef s,
+ PathDiagnosticPiece::Kind k,
+ bool addPosRange = true)
+ : PathDiagnosticPiece(s, k), Pos(pos) {
+ assert(Pos.isValid() && Pos.asLocation().isValid() &&
+ "PathDiagnosticSpotPiece's must have a valid location.");
+ if (addPosRange && Pos.hasRange()) addRange(Pos.asRange());
+ }
+
+ PathDiagnosticLocation getLocation() const override { return Pos; }
+ void flattenLocations() override { Pos.flatten(); }
+
+ void Profile(llvm::FoldingSetNodeID &ID) const override;
+
+ static bool classof(const PathDiagnosticPiece *P) {
+ return P->getKind() == Event || P->getKind() == Macro;
+ }
+};
+
+/// \brief Interface for classes constructing Stack hints.
+///
+/// If a PathDiagnosticEvent occurs in a different frame than the final
+/// diagnostic the hints can be used to summarize the effect of the call.
+class StackHintGenerator {
+public:
+ virtual ~StackHintGenerator() = 0;
+
+ /// \brief Construct the Diagnostic message for the given ExplodedNode.
+ virtual std::string getMessage(const ExplodedNode *N) = 0;
+};
+
+/// \brief Constructs a Stack hint for the given symbol.
+///
+/// The class knows how to construct the stack hint message based on
+/// traversing the CallExpr associated with the call and checking if the given
+/// symbol is returned or is one of the arguments.
+/// The hint can be customized by redefining 'getMessageForX()' methods.
+class StackHintGeneratorForSymbol : public StackHintGenerator {
+private:
+ SymbolRef Sym;
+ std::string Msg;
+
+public:
+ StackHintGeneratorForSymbol(SymbolRef S, StringRef M) : Sym(S), Msg(M) {}
+ ~StackHintGeneratorForSymbol() override {}
+
+ /// \brief Search the call expression for the symbol Sym and dispatch the
+ /// 'getMessageForX()' methods to construct a specific message.
+ std::string getMessage(const ExplodedNode *N) override;
+
+ /// Produces the message of the following form:
+ /// 'Msg via Nth parameter'
+ virtual std::string getMessageForArg(const Expr *ArgE, unsigned ArgIndex);
+ virtual std::string getMessageForReturn(const CallExpr *CallExpr) {
+ return Msg;
+ }
+ virtual std::string getMessageForSymbolNotFound() {
+ return Msg;
+ }
+};
+
+class PathDiagnosticEventPiece : public PathDiagnosticSpotPiece {
+ Optional<bool> IsPrunable;
+
+ /// If the event occurs in a different frame than the final diagnostic,
+ /// supply a message that will be used to construct an extra hint on the
+ /// returns from all the calls on the stack from this event to the final
+ /// diagnostic.
+ std::unique_ptr<StackHintGenerator> CallStackHint;
+
+public:
+ PathDiagnosticEventPiece(const PathDiagnosticLocation &pos,
+ StringRef s, bool addPosRange = true,
+ StackHintGenerator *stackHint = nullptr)
+ : PathDiagnosticSpotPiece(pos, s, Event, addPosRange),
+ CallStackHint(stackHint) {}
+
+ ~PathDiagnosticEventPiece() override;
+
+ /// Mark the diagnostic piece as being potentially prunable. This
+ /// flag may have been previously set, at which point it will not
+ /// be reset unless one specifies to do so.
+ void setPrunable(bool isPrunable, bool override = false) {
+ if (IsPrunable.hasValue() && !override)
+ return;
+ IsPrunable = isPrunable;
+ }
+
+ /// Return true if the diagnostic piece is prunable.
+ bool isPrunable() const {
+ return IsPrunable.hasValue() ? IsPrunable.getValue() : false;
+ }
+
+ bool hasCallStackHint() { return (bool)CallStackHint; }
+
+ /// Produce the hint for the given node. The node contains
+ /// information about the call for which the diagnostic can be generated.
+ std::string getCallStackMessage(const ExplodedNode *N) {
+ if (CallStackHint)
+ return CallStackHint->getMessage(N);
+ return "";
+ }
+
+ void dump() const override;
+
+ static inline bool classof(const PathDiagnosticPiece *P) {
+ return P->getKind() == Event;
+ }
+};
+
+class PathDiagnosticCallPiece : public PathDiagnosticPiece {
+ PathDiagnosticCallPiece(const Decl *callerD,
+ const PathDiagnosticLocation &callReturnPos)
+ : PathDiagnosticPiece(Call), Caller(callerD), Callee(nullptr),
+ NoExit(false), callReturn(callReturnPos) {}
+
+ PathDiagnosticCallPiece(PathPieces &oldPath, const Decl *caller)
+ : PathDiagnosticPiece(Call), Caller(caller), Callee(nullptr),
+ NoExit(true), path(oldPath) {}
+
+ const Decl *Caller;
+ const Decl *Callee;
+
+ // Flag signifying that this diagnostic has only call enter and no matching
+ // call exit.
+ bool NoExit;
+
+ // The custom string, which should appear after the call Return Diagnostic.
+ // TODO: Should we allow multiple diagnostics?
+ std::string CallStackMessage;
+
+public:
+ PathDiagnosticLocation callEnter;
+ PathDiagnosticLocation callEnterWithin;
+ PathDiagnosticLocation callReturn;
+ PathPieces path;
+
+ ~PathDiagnosticCallPiece() override;
+
+ const Decl *getCaller() const { return Caller; }
+
+ const Decl *getCallee() const { return Callee; }
+ void setCallee(const CallEnter &CE, const SourceManager &SM);
+
+ bool hasCallStackMessage() { return !CallStackMessage.empty(); }
+ void setCallStackMessage(StringRef st) {
+ CallStackMessage = st;
+ }
+
+ PathDiagnosticLocation getLocation() const override {
+ return callEnter;
+ }
+
+ IntrusiveRefCntPtr<PathDiagnosticEventPiece> getCallEnterEvent() const;
+ IntrusiveRefCntPtr<PathDiagnosticEventPiece>
+ getCallEnterWithinCallerEvent() const;
+ IntrusiveRefCntPtr<PathDiagnosticEventPiece> getCallExitEvent() const;
+
+ void flattenLocations() override {
+ callEnter.flatten();
+ callReturn.flatten();
+ for (PathPieces::iterator I = path.begin(),
+ E = path.end(); I != E; ++I) (*I)->flattenLocations();
+ }
+
+ static PathDiagnosticCallPiece *construct(const ExplodedNode *N,
+ const CallExitEnd &CE,
+ const SourceManager &SM);
+
+ static PathDiagnosticCallPiece *construct(PathPieces &pieces,
+ const Decl *caller);
+
+ void dump() const override;
+
+ void Profile(llvm::FoldingSetNodeID &ID) const override;
+
+ static inline bool classof(const PathDiagnosticPiece *P) {
+ return P->getKind() == Call;
+ }
+};
+
+class PathDiagnosticControlFlowPiece : public PathDiagnosticPiece {
+ std::vector<PathDiagnosticLocationPair> LPairs;
+public:
+ PathDiagnosticControlFlowPiece(const PathDiagnosticLocation &startPos,
+ const PathDiagnosticLocation &endPos,
+ 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() override;
+
+ 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 setStartLocation(const PathDiagnosticLocation &L) {
+ LPairs[0].setStart(L);
+ }
+
+ void setEndLocation(const PathDiagnosticLocation &L) {
+ LPairs[0].setEnd(L);
+ }
+
+ void push_back(const PathDiagnosticLocationPair &X) { LPairs.push_back(X); }
+
+ PathDiagnosticLocation getLocation() const override {
+ return getStartLocation();
+ }
+
+ typedef std::vector<PathDiagnosticLocationPair>::iterator iterator;
+ iterator begin() { return LPairs.begin(); }
+ iterator end() { return LPairs.end(); }
+
+ void flattenLocations() override {
+ 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;
+ }
+
+ void dump() const override;
+
+ void Profile(llvm::FoldingSetNodeID &ID) const override;
+};
+
+class PathDiagnosticMacroPiece : public PathDiagnosticSpotPiece {
+public:
+ PathDiagnosticMacroPiece(const PathDiagnosticLocation &pos)
+ : PathDiagnosticSpotPiece(pos, "", Macro) {}
+
+ ~PathDiagnosticMacroPiece() override;
+
+ PathPieces subPieces;
+
+ bool containsEvent() const;
+
+ void flattenLocations() override {
+ PathDiagnosticSpotPiece::flattenLocations();
+ for (PathPieces::iterator I = subPieces.begin(),
+ E = subPieces.end(); I != E; ++I) (*I)->flattenLocations();
+ }
+
+ static inline bool classof(const PathDiagnosticPiece *P) {
+ return P->getKind() == Macro;
+ }
+
+ void dump() const override;
+
+ void Profile(llvm::FoldingSetNodeID &ID) const override;
+};
+
+/// 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::string CheckName;
+ const Decl *DeclWithIssue;
+ std::string BugType;
+ std::string VerboseDesc;
+ std::string ShortDesc;
+ std::string Category;
+ std::deque<std::string> OtherDesc;
+
+ /// \brief Loc The location of the path diagnostic report.
+ PathDiagnosticLocation Loc;
+
+ PathPieces pathImpl;
+ SmallVector<PathPieces *, 3> pathStack;
+
+ /// \brief Important bug uniqueing location.
+ /// The location info is useful to differentiate between bugs.
+ PathDiagnosticLocation UniqueingLoc;
+ const Decl *UniqueingDecl;
+
+ PathDiagnostic() = delete;
+public:
+ PathDiagnostic(StringRef CheckName, const Decl *DeclWithIssue,
+ StringRef bugtype, StringRef verboseDesc, StringRef shortDesc,
+ StringRef category, PathDiagnosticLocation LocationToUnique,
+ const Decl *DeclToUnique);
+
+ ~PathDiagnostic();
+
+ const PathPieces &path;
+
+ /// Return the path currently used by builders for constructing the
+ /// PathDiagnostic.
+ PathPieces &getActivePath() {
+ if (pathStack.empty())
+ return pathImpl;
+ return *pathStack.back();
+ }
+
+ /// Return a mutable version of 'path'.
+ PathPieces &getMutablePieces() {
+ return pathImpl;
+ }
+
+ /// Return the unrolled size of the path.
+ unsigned full_size();
+
+ void pushActivePath(PathPieces *p) { pathStack.push_back(p); }
+ void popActivePath() { if (!pathStack.empty()) pathStack.pop_back(); }
+
+ bool isWithinCall() const { return !pathStack.empty(); }
+
+ void setEndOfPath(std::unique_ptr<PathDiagnosticPiece> EndPiece) {
+ assert(!Loc.isValid() && "End location already set!");
+ Loc = EndPiece->getLocation();
+ assert(Loc.isValid() && "Invalid location for end-of-path piece");
+ getActivePath().push_back(EndPiece.release());
+ }
+
+ void appendToDesc(StringRef S) {
+ if (!ShortDesc.empty())
+ ShortDesc.append(S);
+ VerboseDesc.append(S);
+ }
+
+ void resetPath() {
+ pathStack.clear();
+ pathImpl.clear();
+ Loc = PathDiagnosticLocation();
+ }
+
+ /// \brief If the last piece of the report point to the header file, resets
+ /// the location of the report to be the last location in the main source
+ /// file.
+ void resetDiagnosticLocationToMainFile();
+
+ StringRef getVerboseDescription() const { return VerboseDesc; }
+ StringRef getShortDescription() const {
+ return ShortDesc.empty() ? VerboseDesc : ShortDesc;
+ }
+ StringRef getCheckName() const { return CheckName; }
+ StringRef getBugType() const { return BugType; }
+ StringRef getCategory() const { return Category; }
+
+ /// Return the semantic context where an issue occurred. If the
+ /// issue occurs along a path, this represents the "central" area
+ /// where the bug manifests.
+ const Decl *getDeclWithIssue() const { return DeclWithIssue; }
+
+ 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(StringRef s) { OtherDesc.push_back(s); }
+
+ PathDiagnosticLocation getLocation() const {
+ assert(Loc.isValid() && "No report location set yet!");
+ return Loc;
+ }
+
+ /// \brief Get the location on which the report should be uniqued.
+ PathDiagnosticLocation getUniqueingLoc() const {
+ return UniqueingLoc;
+ }
+
+ /// \brief Get the declaration containing the uniqueing location.
+ const Decl *getUniqueingDecl() const {
+ return UniqueingDecl;
+ }
+
+ void flattenLocations() {
+ Loc.flatten();
+ for (PathPieces::iterator I = pathImpl.begin(), E = pathImpl.end();
+ I != E; ++I) (*I)->flattenLocations();
+ }
+
+ /// Profiles the diagnostic, independent of the path it references.
+ ///
+ /// This can be used to merge diagnostics that refer to the same issue
+ /// along different paths.
+ void Profile(llvm::FoldingSetNodeID &ID) const;
+
+ /// Profiles the diagnostic, including its path.
+ ///
+ /// Two diagnostics with the same issue along different paths will generate
+ /// different profiles.
+ void FullProfile(llvm::FoldingSetNodeID &ID) const;
+};
+
+} // end GR namespace
+
+} //end clang namespace
+
+#endif
diff --git a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/Checker.h b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/Checker.h
new file mode 100644
index 0000000..1410af1
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/Checker.h
@@ -0,0 +1,554 @@
+//== Checker.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 Checker, used to create and register checkers.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_STATICANALYZER_CORE_CHECKER_H
+#define LLVM_CLANG_STATICANALYZER_CORE_CHECKER_H
+
+#include "clang/Analysis/ProgramPoint.h"
+#include "clang/StaticAnalyzer/Core/CheckerManager.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/SVals.h"
+#include "llvm/Support/Casting.h"
+
+namespace clang {
+namespace ento {
+ class BugReporter;
+
+namespace check {
+
+template <typename DECL>
+class ASTDecl {
+ template <typename CHECKER>
+ static void _checkDecl(void *checker, const Decl *D, AnalysisManager& mgr,
+ BugReporter &BR) {
+ ((const CHECKER *)checker)->checkASTDecl(cast<DECL>(D), mgr, BR);
+ }
+
+ static bool _handlesDecl(const Decl *D) {
+ return isa<DECL>(D);
+ }
+public:
+ template <typename CHECKER>
+ static void _register(CHECKER *checker, CheckerManager &mgr) {
+ mgr._registerForDecl(CheckerManager::CheckDeclFunc(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(CheckerManager::CheckDeclFunc(checker,
+ _checkBody<CHECKER>));
+ }
+};
+
+class EndOfTranslationUnit {
+ template <typename CHECKER>
+ static void _checkEndOfTranslationUnit(void *checker,
+ const TranslationUnitDecl *TU,
+ AnalysisManager& mgr,
+ BugReporter &BR) {
+ ((const CHECKER *)checker)->checkEndOfTranslationUnit(TU, mgr, BR);
+ }
+
+public:
+ template <typename CHECKER>
+ static void _register(CHECKER *checker, CheckerManager &mgr){
+ mgr._registerForEndOfTranslationUnit(
+ CheckerManager::CheckEndOfTranslationUnit(checker,
+ _checkEndOfTranslationUnit<CHECKER>));
+ }
+};
+
+template <typename STMT>
+class PreStmt {
+ template <typename CHECKER>
+ static void _checkStmt(void *checker, const Stmt *S, CheckerContext &C) {
+ ((const CHECKER *)checker)->checkPreStmt(cast<STMT>(S), C);
+ }
+
+ static bool _handlesStmt(const Stmt *S) {
+ return isa<STMT>(S);
+ }
+public:
+ template <typename CHECKER>
+ static void _register(CHECKER *checker, CheckerManager &mgr) {
+ mgr._registerForPreStmt(CheckerManager::CheckStmtFunc(checker,
+ _checkStmt<CHECKER>),
+ _handlesStmt);
+ }
+};
+
+template <typename STMT>
+class PostStmt {
+ template <typename CHECKER>
+ static void _checkStmt(void *checker, const Stmt *S, CheckerContext &C) {
+ ((const CHECKER *)checker)->checkPostStmt(cast<STMT>(S), C);
+ }
+
+ static bool _handlesStmt(const Stmt *S) {
+ return isa<STMT>(S);
+ }
+public:
+ template <typename CHECKER>
+ static void _register(CHECKER *checker, CheckerManager &mgr) {
+ mgr._registerForPostStmt(CheckerManager::CheckStmtFunc(checker,
+ _checkStmt<CHECKER>),
+ _handlesStmt);
+ }
+};
+
+class PreObjCMessage {
+ template <typename CHECKER>
+ static void _checkObjCMessage(void *checker, const ObjCMethodCall &msg,
+ CheckerContext &C) {
+ ((const CHECKER *)checker)->checkPreObjCMessage(msg, C);
+ }
+
+public:
+ template <typename CHECKER>
+ static void _register(CHECKER *checker, CheckerManager &mgr) {
+ mgr._registerForPreObjCMessage(
+ CheckerManager::CheckObjCMessageFunc(checker, _checkObjCMessage<CHECKER>));
+ }
+};
+
+class ObjCMessageNil {
+ template <typename CHECKER>
+ static void _checkObjCMessage(void *checker, const ObjCMethodCall &msg,
+ CheckerContext &C) {
+ ((const CHECKER *)checker)->checkObjCMessageNil(msg, C);
+ }
+
+public:
+ template <typename CHECKER>
+ static void _register(CHECKER *checker, CheckerManager &mgr) {
+ mgr._registerForObjCMessageNil(
+ CheckerManager::CheckObjCMessageFunc(checker, _checkObjCMessage<CHECKER>));
+ }
+};
+
+class PostObjCMessage {
+ template <typename CHECKER>
+ static void _checkObjCMessage(void *checker, const ObjCMethodCall &msg,
+ CheckerContext &C) {
+ ((const CHECKER *)checker)->checkPostObjCMessage(msg, C);
+ }
+
+public:
+ template <typename CHECKER>
+ static void _register(CHECKER *checker, CheckerManager &mgr) {
+ mgr._registerForPostObjCMessage(
+ CheckerManager::CheckObjCMessageFunc(checker, _checkObjCMessage<CHECKER>));
+ }
+};
+
+class PreCall {
+ template <typename CHECKER>
+ static void _checkCall(void *checker, const CallEvent &msg,
+ CheckerContext &C) {
+ ((const CHECKER *)checker)->checkPreCall(msg, C);
+ }
+
+public:
+ template <typename CHECKER>
+ static void _register(CHECKER *checker, CheckerManager &mgr) {
+ mgr._registerForPreCall(
+ CheckerManager::CheckCallFunc(checker, _checkCall<CHECKER>));
+ }
+};
+
+class PostCall {
+ template <typename CHECKER>
+ static void _checkCall(void *checker, const CallEvent &msg,
+ CheckerContext &C) {
+ ((const CHECKER *)checker)->checkPostCall(msg, C);
+ }
+
+public:
+ template <typename CHECKER>
+ static void _register(CHECKER *checker, CheckerManager &mgr) {
+ mgr._registerForPostCall(
+ CheckerManager::CheckCallFunc(checker, _checkCall<CHECKER>));
+ }
+};
+
+class Location {
+ template <typename CHECKER>
+ static void _checkLocation(void *checker,
+ const SVal &location, bool isLoad, const Stmt *S,
+ CheckerContext &C) {
+ ((const CHECKER *)checker)->checkLocation(location, isLoad, S, C);
+ }
+
+public:
+ template <typename CHECKER>
+ static void _register(CHECKER *checker, CheckerManager &mgr) {
+ mgr._registerForLocation(
+ CheckerManager::CheckLocationFunc(checker, _checkLocation<CHECKER>));
+ }
+};
+
+class Bind {
+ template <typename CHECKER>
+ static void _checkBind(void *checker,
+ const SVal &location, const SVal &val, const Stmt *S,
+ CheckerContext &C) {
+ ((const CHECKER *)checker)->checkBind(location, val, S, C);
+ }
+
+public:
+ template <typename CHECKER>
+ static void _register(CHECKER *checker, CheckerManager &mgr) {
+ mgr._registerForBind(
+ CheckerManager::CheckBindFunc(checker, _checkBind<CHECKER>));
+ }
+};
+
+class EndAnalysis {
+ template <typename CHECKER>
+ static void _checkEndAnalysis(void *checker, ExplodedGraph &G,
+ BugReporter &BR, ExprEngine &Eng) {
+ ((const CHECKER *)checker)->checkEndAnalysis(G, BR, Eng);
+ }
+
+public:
+ template <typename CHECKER>
+ static void _register(CHECKER *checker, CheckerManager &mgr) {
+ mgr._registerForEndAnalysis(
+ CheckerManager::CheckEndAnalysisFunc(checker, _checkEndAnalysis<CHECKER>));
+ }
+};
+
+class EndFunction {
+ template <typename CHECKER>
+ static void _checkEndFunction(void *checker,
+ CheckerContext &C) {
+ ((const CHECKER *)checker)->checkEndFunction(C);
+ }
+
+public:
+ template <typename CHECKER>
+ static void _register(CHECKER *checker, CheckerManager &mgr) {
+ mgr._registerForEndFunction(
+ CheckerManager::CheckEndFunctionFunc(checker, _checkEndFunction<CHECKER>));
+ }
+};
+
+class BranchCondition {
+ template <typename CHECKER>
+ static void _checkBranchCondition(void *checker, const Stmt *Condition,
+ CheckerContext & C) {
+ ((const CHECKER *)checker)->checkBranchCondition(Condition, C);
+ }
+
+public:
+ template <typename CHECKER>
+ static void _register(CHECKER *checker, CheckerManager &mgr) {
+ mgr._registerForBranchCondition(
+ CheckerManager::CheckBranchConditionFunc(checker,
+ _checkBranchCondition<CHECKER>));
+ }
+};
+
+class LiveSymbols {
+ template <typename CHECKER>
+ static void _checkLiveSymbols(void *checker, ProgramStateRef state,
+ SymbolReaper &SR) {
+ ((const CHECKER *)checker)->checkLiveSymbols(state, SR);
+ }
+
+public:
+ template <typename CHECKER>
+ static void _register(CHECKER *checker, CheckerManager &mgr) {
+ mgr._registerForLiveSymbols(
+ CheckerManager::CheckLiveSymbolsFunc(checker, _checkLiveSymbols<CHECKER>));
+ }
+};
+
+class DeadSymbols {
+ template <typename CHECKER>
+ static void _checkDeadSymbols(void *checker,
+ SymbolReaper &SR, CheckerContext &C) {
+ ((const CHECKER *)checker)->checkDeadSymbols(SR, C);
+ }
+
+public:
+ template <typename CHECKER>
+ static void _register(CHECKER *checker, CheckerManager &mgr) {
+ mgr._registerForDeadSymbols(
+ CheckerManager::CheckDeadSymbolsFunc(checker, _checkDeadSymbols<CHECKER>));
+ }
+};
+
+class RegionChanges {
+ template <typename CHECKER>
+ static ProgramStateRef
+ _checkRegionChanges(void *checker,
+ ProgramStateRef state,
+ const InvalidatedSymbols *invalidated,
+ ArrayRef<const MemRegion *> Explicits,
+ ArrayRef<const MemRegion *> Regions,
+ const CallEvent *Call) {
+ return ((const CHECKER *)checker)->checkRegionChanges(state, invalidated,
+ Explicits, Regions, Call);
+ }
+ template <typename CHECKER>
+ static bool _wantsRegionChangeUpdate(void *checker,
+ ProgramStateRef state) {
+ return ((const CHECKER *)checker)->wantsRegionChangeUpdate(state);
+ }
+
+public:
+ template <typename CHECKER>
+ static void _register(CHECKER *checker, CheckerManager &mgr) {
+ mgr._registerForRegionChanges(
+ CheckerManager::CheckRegionChangesFunc(checker,
+ _checkRegionChanges<CHECKER>),
+ CheckerManager::WantsRegionChangeUpdateFunc(checker,
+ _wantsRegionChangeUpdate<CHECKER>));
+ }
+};
+
+class PointerEscape {
+ template <typename CHECKER>
+ static ProgramStateRef
+ _checkPointerEscape(void *Checker,
+ ProgramStateRef State,
+ const InvalidatedSymbols &Escaped,
+ const CallEvent *Call,
+ PointerEscapeKind Kind,
+ RegionAndSymbolInvalidationTraits *ETraits) {
+
+ if (!ETraits)
+ return ((const CHECKER *)Checker)->checkPointerEscape(State,
+ Escaped,
+ Call,
+ Kind);
+
+ InvalidatedSymbols RegularEscape;
+ for (InvalidatedSymbols::const_iterator I = Escaped.begin(),
+ E = Escaped.end(); I != E; ++I)
+ if (!ETraits->hasTrait(*I,
+ RegionAndSymbolInvalidationTraits::TK_PreserveContents) &&
+ !ETraits->hasTrait(*I,
+ RegionAndSymbolInvalidationTraits::TK_SuppressEscape))
+ RegularEscape.insert(*I);
+
+ if (RegularEscape.empty())
+ return State;
+
+ return ((const CHECKER *)Checker)->checkPointerEscape(State,
+ RegularEscape,
+ Call,
+ Kind);
+ }
+
+public:
+ template <typename CHECKER>
+ static void _register(CHECKER *checker, CheckerManager &mgr) {
+ mgr._registerForPointerEscape(
+ CheckerManager::CheckPointerEscapeFunc(checker,
+ _checkPointerEscape<CHECKER>));
+ }
+};
+
+class ConstPointerEscape {
+ template <typename CHECKER>
+ static ProgramStateRef
+ _checkConstPointerEscape(void *Checker,
+ ProgramStateRef State,
+ const InvalidatedSymbols &Escaped,
+ const CallEvent *Call,
+ PointerEscapeKind Kind,
+ RegionAndSymbolInvalidationTraits *ETraits) {
+
+ if (!ETraits)
+ return State;
+
+ InvalidatedSymbols ConstEscape;
+ for (InvalidatedSymbols::const_iterator I = Escaped.begin(),
+ E = Escaped.end(); I != E; ++I)
+ if (ETraits->hasTrait(*I,
+ RegionAndSymbolInvalidationTraits::TK_PreserveContents) &&
+ !ETraits->hasTrait(*I,
+ RegionAndSymbolInvalidationTraits::TK_SuppressEscape))
+ ConstEscape.insert(*I);
+
+ if (ConstEscape.empty())
+ return State;
+
+ return ((const CHECKER *)Checker)->checkConstPointerEscape(State,
+ ConstEscape,
+ Call,
+ Kind);
+ }
+
+public:
+ template <typename CHECKER>
+ static void _register(CHECKER *checker, CheckerManager &mgr) {
+ mgr._registerForPointerEscape(
+ CheckerManager::CheckPointerEscapeFunc(checker,
+ _checkConstPointerEscape<CHECKER>));
+ }
+};
+
+
+template <typename EVENT>
+class Event {
+ template <typename CHECKER>
+ static void _checkEvent(void *checker, const void *event) {
+ ((const CHECKER *)checker)->checkEvent(*(const EVENT *)event);
+ }
+public:
+ template <typename CHECKER>
+ static void _register(CHECKER *checker, CheckerManager &mgr) {
+ mgr._registerListenerForEvent<EVENT>(
+ CheckerManager::CheckEventFunc(checker, _checkEvent<CHECKER>));
+ }
+};
+
+} // end check namespace
+
+namespace eval {
+
+class Assume {
+ template <typename CHECKER>
+ static ProgramStateRef _evalAssume(void *checker,
+ ProgramStateRef state,
+ const SVal &cond,
+ bool assumption) {
+ return ((const CHECKER *)checker)->evalAssume(state, cond, assumption);
+ }
+
+public:
+ template <typename CHECKER>
+ static void _register(CHECKER *checker, CheckerManager &mgr) {
+ mgr._registerForEvalAssume(
+ CheckerManager::EvalAssumeFunc(checker, _evalAssume<CHECKER>));
+ }
+};
+
+class Call {
+ template <typename CHECKER>
+ static bool _evalCall(void *checker, const CallExpr *CE, CheckerContext &C) {
+ return ((const CHECKER *)checker)->evalCall(CE, C);
+ }
+
+public:
+ template <typename CHECKER>
+ static void _register(CHECKER *checker, CheckerManager &mgr) {
+ mgr._registerForEvalCall(
+ CheckerManager::EvalCallFunc(checker, _evalCall<CHECKER>));
+ }
+};
+
+} // end eval namespace
+
+class CheckerBase : public ProgramPointTag {
+ CheckName Name;
+ friend class ::clang::ento::CheckerManager;
+
+public:
+ StringRef getTagDescription() const override;
+ CheckName getCheckName() const;
+
+ /// See CheckerManager::runCheckersForPrintState.
+ virtual void printState(raw_ostream &Out, ProgramStateRef State,
+ const char *NL, const char *Sep) const { }
+};
+
+/// Dump checker name to stream.
+raw_ostream& operator<<(raw_ostream &Out, const CheckerBase &Checker);
+
+/// Tag that can use a checker name as a message provider
+/// (see SimpleProgramPointTag).
+class CheckerProgramPointTag : public SimpleProgramPointTag {
+public:
+ CheckerProgramPointTag(StringRef CheckerName, StringRef Msg);
+ CheckerProgramPointTag(const CheckerBase *Checker, StringRef Msg);
+};
+
+template <typename CHECK1, typename... CHECKs>
+class Checker : public CHECK1, public CHECKs..., public CheckerBase {
+public:
+ template <typename CHECKER>
+ static void _register(CHECKER *checker, CheckerManager &mgr) {
+ CHECK1::_register(checker, mgr);
+ Checker<CHECKs...>::_register(checker, mgr);
+ }
+};
+
+template <typename CHECK1>
+class Checker<CHECK1> : public CHECK1, public CheckerBase {
+public:
+ template <typename CHECKER>
+ static void _register(CHECKER *checker, CheckerManager &mgr) {
+ CHECK1::_register(checker, mgr);
+ }
+};
+
+template <typename EVENT>
+class EventDispatcher {
+ CheckerManager *Mgr;
+public:
+ EventDispatcher() : Mgr(nullptr) { }
+
+ template <typename CHECKER>
+ static void _register(CHECKER *checker, CheckerManager &mgr) {
+ mgr._registerDispatcherForEvent<EVENT>();
+ static_cast<EventDispatcher<EVENT> *>(checker)->Mgr = &mgr;
+ }
+
+ void dispatchEvent(const EVENT &event) const {
+ Mgr->_dispatchEvent(event);
+ }
+};
+
+/// \brief We dereferenced a location that may be null.
+struct ImplicitNullDerefEvent {
+ SVal Location;
+ bool IsLoad;
+ ExplodedNode *SinkNode;
+ BugReporter *BR;
+ // When true, the dereference is in the source code directly. When false, the
+ // dereference might happen later (for example pointer passed to a parameter
+ // that is marked with nonnull attribute.)
+ bool IsDirectDereference;
+};
+
+/// \brief A helper class which wraps a boolean value set to false by default.
+///
+/// This class should behave exactly like 'bool' except that it doesn't need to
+/// be explicitly initialized.
+struct DefaultBool {
+ bool val;
+ DefaultBool() : val(false) {}
+ /*implicit*/ operator bool&() { return val; }
+ /*implicit*/ operator const bool&() const { return val; }
+ DefaultBool &operator=(bool b) { val = b; return *this; }
+};
+
+} // end ento 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..bc9af49
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/CheckerManager.h
@@ -0,0 +1,632 @@
+//===--- 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_STATICANALYZER_CORE_CHECKERMANAGER_H
+#define LLVM_CLANG_STATICANALYZER_CORE_CHECKERMANAGER_H
+
+#include "clang/Analysis/ProgramPoint.h"
+#include "clang/Basic/LangOptions.h"
+#include "clang/StaticAnalyzer/Core/AnalyzerOptions.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/Store.h"
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/SmallVector.h"
+#include <vector>
+
+namespace clang {
+ class Decl;
+ class Stmt;
+ class CallExpr;
+
+namespace ento {
+ class CheckerBase;
+ class CheckerRegistry;
+ class ExprEngine;
+ class AnalysisManager;
+ class BugReporter;
+ class CheckerContext;
+ class ObjCMethodCall;
+ class SVal;
+ class ExplodedNode;
+ class ExplodedNodeSet;
+ class ExplodedGraph;
+ class ProgramState;
+ class NodeBuilder;
+ struct NodeBuilderContext;
+ class MemRegion;
+ class SymbolReaper;
+
+template <typename T> class CheckerFn;
+
+template <typename RET, typename... Ps>
+class CheckerFn<RET(Ps...)> {
+ typedef RET (*Func)(void *, Ps...);
+ Func Fn;
+public:
+ CheckerBase *Checker;
+ CheckerFn(CheckerBase *checker, Func fn) : Fn(fn), Checker(checker) { }
+ RET operator()(Ps... ps) const {
+ return Fn(Checker, ps...);
+ }
+};
+
+/// \brief Describes the different reasons a pointer escapes
+/// during analysis.
+enum PointerEscapeKind {
+ /// A pointer escapes due to binding its value to a location
+ /// that the analyzer cannot track.
+ PSK_EscapeOnBind,
+
+ /// The pointer has been passed to a function call directly.
+ PSK_DirectEscapeOnCall,
+
+ /// The pointer has been passed to a function indirectly.
+ /// For example, the pointer is accessible through an
+ /// argument to a function.
+ PSK_IndirectEscapeOnCall,
+
+ /// The reason for pointer escape is unknown. For example,
+ /// a region containing this pointer is invalidated.
+ PSK_EscapeOther
+};
+
+// This wrapper is used to ensure that only StringRefs originating from the
+// CheckerRegistry are used as check names. We want to make sure all check
+// name strings have a lifetime that keeps them alive at least until the path
+// diagnostics have been processed.
+class CheckName {
+ StringRef Name;
+ friend class ::clang::ento::CheckerRegistry;
+ explicit CheckName(StringRef Name) : Name(Name) {}
+
+public:
+ CheckName() = default;
+ StringRef getName() const { return Name; }
+};
+
+enum class ObjCMessageVisitKind {
+ Pre,
+ Post,
+ MessageNil
+};
+
+class CheckerManager {
+ const LangOptions LangOpts;
+ AnalyzerOptionsRef AOptions;
+ CheckName CurrentCheckName;
+
+public:
+ CheckerManager(const LangOptions &langOpts,
+ AnalyzerOptionsRef AOptions)
+ : LangOpts(langOpts),
+ AOptions(AOptions) {}
+
+ ~CheckerManager();
+
+ void setCurrentCheckName(CheckName name) { CurrentCheckName = name; }
+ CheckName getCurrentCheckName() const { return CurrentCheckName; }
+
+ bool hasPathSensitiveCheckers() const;
+
+ void finishedCheckerRegistration();
+
+ const LangOptions &getLangOpts() const { return LangOpts; }
+ AnalyzerOptions &getAnalyzerOptions() { return *AOptions; }
+
+ typedef CheckerBase *CheckerRef;
+ typedef const void *CheckerTag;
+ typedef CheckerFn<void ()> CheckerDtor;
+
+//===----------------------------------------------------------------------===//
+// registerChecker
+//===----------------------------------------------------------------------===//
+
+ /// \brief Used to register checkers.
+ ///
+ /// \returns a pointer to the checker object.
+ template <typename CHECKER>
+ CHECKER *registerChecker() {
+ CheckerTag tag = getTag<CHECKER>();
+ CheckerRef &ref = CheckerTags[tag];
+ if (ref)
+ return static_cast<CHECKER *>(ref); // already registered.
+
+ CHECKER *checker = new CHECKER();
+ checker->Name = CurrentCheckName;
+ CheckerDtors.push_back(CheckerDtor(checker, destruct<CHECKER>));
+ CHECKER::_register(checker, *this);
+ ref = checker;
+ return checker;
+ }
+
+ template <typename CHECKER>
+ CHECKER *registerChecker(AnalyzerOptions &AOpts) {
+ CheckerTag tag = getTag<CHECKER>();
+ CheckerRef &ref = CheckerTags[tag];
+ if (ref)
+ return static_cast<CHECKER *>(ref); // already registered.
+
+ CHECKER *checker = new CHECKER(AOpts);
+ checker->Name = CurrentCheckName;
+ CheckerDtors.push_back(CheckerDtor(checker, destruct<CHECKER>));
+ CHECKER::_register(checker, *this);
+ ref = checker;
+ return checker;
+ }
+
+//===----------------------------------------------------------------------===//
+// Functions for running checkers for AST traversing..
+//===----------------------------------------------------------------------===//
+
+ /// \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);
+
+//===----------------------------------------------------------------------===//
+// Functions for running checkers for path-sensitive checking.
+//===----------------------------------------------------------------------===//
+
+ /// \brief Run checkers for pre-visiting Stmts.
+ ///
+ /// The notification is performed for every explored CFGElement, which does
+ /// not include the control flow statements such as IfStmt.
+ ///
+ /// \sa runCheckersForBranchCondition, runCheckersForPostStmt
+ void runCheckersForPreStmt(ExplodedNodeSet &Dst,
+ const ExplodedNodeSet &Src,
+ const Stmt *S,
+ ExprEngine &Eng) {
+ runCheckersForStmt(/*isPreVisit=*/true, Dst, Src, S, Eng);
+ }
+
+ /// \brief Run checkers for post-visiting Stmts.
+ ///
+ /// The notification is performed for every explored CFGElement, which does
+ /// not include the control flow statements such as IfStmt.
+ ///
+ /// \sa runCheckersForBranchCondition, runCheckersForPreStmt
+ void runCheckersForPostStmt(ExplodedNodeSet &Dst,
+ const ExplodedNodeSet &Src,
+ const Stmt *S,
+ ExprEngine &Eng,
+ bool wasInlined = false) {
+ runCheckersForStmt(/*isPreVisit=*/false, Dst, Src, S, Eng, wasInlined);
+ }
+
+ /// \brief Run checkers for visiting Stmts.
+ void runCheckersForStmt(bool isPreVisit,
+ ExplodedNodeSet &Dst, const ExplodedNodeSet &Src,
+ const Stmt *S, ExprEngine &Eng,
+ bool wasInlined = false);
+
+ /// \brief Run checkers for pre-visiting obj-c messages.
+ void runCheckersForPreObjCMessage(ExplodedNodeSet &Dst,
+ const ExplodedNodeSet &Src,
+ const ObjCMethodCall &msg,
+ ExprEngine &Eng) {
+ runCheckersForObjCMessage(ObjCMessageVisitKind::Pre, Dst, Src, msg, Eng);
+ }
+
+ /// \brief Run checkers for post-visiting obj-c messages.
+ void runCheckersForPostObjCMessage(ExplodedNodeSet &Dst,
+ const ExplodedNodeSet &Src,
+ const ObjCMethodCall &msg,
+ ExprEngine &Eng,
+ bool wasInlined = false) {
+ runCheckersForObjCMessage(ObjCMessageVisitKind::Post, Dst, Src, msg, Eng,
+ wasInlined);
+ }
+
+ /// \brief Run checkers for visiting an obj-c message to nil.
+ void runCheckersForObjCMessageNil(ExplodedNodeSet &Dst,
+ const ExplodedNodeSet &Src,
+ const ObjCMethodCall &msg,
+ ExprEngine &Eng) {
+ runCheckersForObjCMessage(ObjCMessageVisitKind::MessageNil, Dst, Src, msg,
+ Eng);
+ }
+
+
+ /// \brief Run checkers for visiting obj-c messages.
+ void runCheckersForObjCMessage(ObjCMessageVisitKind visitKind,
+ ExplodedNodeSet &Dst,
+ const ExplodedNodeSet &Src,
+ const ObjCMethodCall &msg, ExprEngine &Eng,
+ bool wasInlined = false);
+
+ /// \brief Run checkers for pre-visiting obj-c messages.
+ void runCheckersForPreCall(ExplodedNodeSet &Dst, const ExplodedNodeSet &Src,
+ const CallEvent &Call, ExprEngine &Eng) {
+ runCheckersForCallEvent(/*isPreVisit=*/true, Dst, Src, Call, Eng);
+ }
+
+ /// \brief Run checkers for post-visiting obj-c messages.
+ void runCheckersForPostCall(ExplodedNodeSet &Dst, const ExplodedNodeSet &Src,
+ const CallEvent &Call, ExprEngine &Eng,
+ bool wasInlined = false) {
+ runCheckersForCallEvent(/*isPreVisit=*/false, Dst, Src, Call, Eng,
+ wasInlined);
+ }
+
+ /// \brief Run checkers for visiting obj-c messages.
+ void runCheckersForCallEvent(bool isPreVisit, ExplodedNodeSet &Dst,
+ const ExplodedNodeSet &Src,
+ const CallEvent &Call, ExprEngine &Eng,
+ bool wasInlined = false);
+
+ /// \brief Run checkers for load/store of a location.
+ void runCheckersForLocation(ExplodedNodeSet &Dst,
+ const ExplodedNodeSet &Src,
+ SVal location,
+ bool isLoad,
+ const Stmt *NodeEx,
+ const Stmt *BoundEx,
+ ExprEngine &Eng);
+
+ /// \brief Run checkers for binding of a value to a location.
+ void runCheckersForBind(ExplodedNodeSet &Dst,
+ const ExplodedNodeSet &Src,
+ SVal location, SVal val,
+ const Stmt *S, ExprEngine &Eng,
+ const ProgramPoint &PP);
+
+ /// \brief Run checkers for end of analysis.
+ void runCheckersForEndAnalysis(ExplodedGraph &G, BugReporter &BR,
+ ExprEngine &Eng);
+
+ /// \brief Run checkers on end of function.
+ void runCheckersForEndFunction(NodeBuilderContext &BC,
+ ExplodedNodeSet &Dst,
+ ExplodedNode *Pred,
+ ExprEngine &Eng);
+
+ /// \brief Run checkers for branch condition.
+ void runCheckersForBranchCondition(const Stmt *condition,
+ ExplodedNodeSet &Dst, ExplodedNode *Pred,
+ ExprEngine &Eng);
+
+ /// \brief Run checkers for live symbols.
+ ///
+ /// Allows modifying SymbolReaper object. For example, checkers can explicitly
+ /// register symbols of interest as live. These symbols will not be marked
+ /// dead and removed.
+ void runCheckersForLiveSymbols(ProgramStateRef state,
+ SymbolReaper &SymReaper);
+
+ /// \brief Run checkers for dead symbols.
+ ///
+ /// Notifies checkers when symbols become dead. For example, this allows
+ /// checkers to aggressively clean up/reduce the checker state and produce
+ /// precise diagnostics.
+ void runCheckersForDeadSymbols(ExplodedNodeSet &Dst,
+ const ExplodedNodeSet &Src,
+ SymbolReaper &SymReaper, const Stmt *S,
+ ExprEngine &Eng,
+ ProgramPoint::Kind K);
+
+ /// \brief True if at least one checker wants to check region changes.
+ bool wantsRegionChangeUpdate(ProgramStateRef state);
+
+ /// \brief Run checkers for region changes.
+ ///
+ /// This corresponds to the check::RegionChanges callback.
+ /// \param state The current program state.
+ /// \param invalidated A set of all symbols potentially touched by the change.
+ /// \param ExplicitRegions The regions explicitly requested for invalidation.
+ /// For example, in the case of a function call, these would be arguments.
+ /// \param Regions The transitive closure of accessible regions,
+ /// i.e. all regions that may have been touched by this change.
+ /// \param Call The call expression wrapper if the regions are invalidated
+ /// by a call.
+ ProgramStateRef
+ runCheckersForRegionChanges(ProgramStateRef state,
+ const InvalidatedSymbols *invalidated,
+ ArrayRef<const MemRegion *> ExplicitRegions,
+ ArrayRef<const MemRegion *> Regions,
+ const CallEvent *Call);
+
+ /// \brief Run checkers when pointers escape.
+ ///
+ /// This notifies the checkers about pointer escape, which occurs whenever
+ /// the analyzer cannot track the symbol any more. For example, as a
+ /// result of assigning a pointer into a global or when it's passed to a
+ /// function call the analyzer cannot model.
+ ///
+ /// \param State The state at the point of escape.
+ /// \param Escaped The list of escaped symbols.
+ /// \param Call The corresponding CallEvent, if the symbols escape as
+ /// parameters to the given call.
+ /// \param Kind The reason of pointer escape.
+ /// \param ITraits Information about invalidation for a particular
+ /// region/symbol.
+ /// \returns Checkers can modify the state by returning a new one.
+ ProgramStateRef
+ runCheckersForPointerEscape(ProgramStateRef State,
+ const InvalidatedSymbols &Escaped,
+ const CallEvent *Call,
+ PointerEscapeKind Kind,
+ RegionAndSymbolInvalidationTraits *ITraits);
+
+ /// \brief Run checkers for handling assumptions on symbolic values.
+ ProgramStateRef runCheckersForEvalAssume(ProgramStateRef state,
+ SVal Cond, bool Assumption);
+
+ /// \brief Run checkers for evaluating a call.
+ ///
+ /// Warning: Currently, the CallEvent MUST come from a CallExpr!
+ void runCheckersForEvalCall(ExplodedNodeSet &Dst,
+ const ExplodedNodeSet &Src,
+ const CallEvent &CE, ExprEngine &Eng);
+
+ /// \brief Run checkers for the entire Translation Unit.
+ void runCheckersOnEndOfTranslationUnit(const TranslationUnitDecl *TU,
+ AnalysisManager &mgr,
+ BugReporter &BR);
+
+ /// \brief Run checkers for debug-printing a ProgramState.
+ ///
+ /// Unlike most other callbacks, any checker can simply implement the virtual
+ /// method CheckerBase::printState if it has custom data to print.
+ /// \param Out The output stream
+ /// \param State The state being printed
+ /// \param NL The preferred representation of a newline.
+ /// \param Sep The preferred separator between different kinds of data.
+ void runCheckersForPrintState(raw_ostream &Out, ProgramStateRef State,
+ const char *NL, const char *Sep);
+
+//===----------------------------------------------------------------------===//
+// Internal registration functions for AST traversing.
+//===----------------------------------------------------------------------===//
+
+ // Functions used by the registration mechanism, checkers should not touch
+ // these directly.
+
+ typedef CheckerFn<void (const Decl *, AnalysisManager&, BugReporter &)>
+ CheckDeclFunc;
+
+ typedef bool (*HandlesDeclFunc)(const Decl *D);
+ void _registerForDecl(CheckDeclFunc checkfn, HandlesDeclFunc isForDeclFn);
+
+ void _registerForBody(CheckDeclFunc checkfn);
+
+//===----------------------------------------------------------------------===//
+// Internal registration functions for path-sensitive checking.
+//===----------------------------------------------------------------------===//
+
+ typedef CheckerFn<void (const Stmt *, CheckerContext &)> CheckStmtFunc;
+
+ typedef CheckerFn<void (const ObjCMethodCall &, CheckerContext &)>
+ CheckObjCMessageFunc;
+
+ typedef CheckerFn<void (const CallEvent &, CheckerContext &)>
+ CheckCallFunc;
+
+ typedef CheckerFn<void (const SVal &location, bool isLoad,
+ const Stmt *S,
+ CheckerContext &)>
+ CheckLocationFunc;
+
+ typedef CheckerFn<void (const SVal &location, const SVal &val,
+ const Stmt *S, CheckerContext &)>
+ CheckBindFunc;
+
+ typedef CheckerFn<void (ExplodedGraph &, BugReporter &, ExprEngine &)>
+ CheckEndAnalysisFunc;
+
+ typedef CheckerFn<void (CheckerContext &)>
+ CheckEndFunctionFunc;
+
+ typedef CheckerFn<void (const Stmt *, CheckerContext &)>
+ CheckBranchConditionFunc;
+
+ typedef CheckerFn<void (SymbolReaper &, CheckerContext &)>
+ CheckDeadSymbolsFunc;
+
+ typedef CheckerFn<void (ProgramStateRef,SymbolReaper &)> CheckLiveSymbolsFunc;
+
+ typedef CheckerFn<ProgramStateRef (ProgramStateRef,
+ const InvalidatedSymbols *symbols,
+ ArrayRef<const MemRegion *> ExplicitRegions,
+ ArrayRef<const MemRegion *> Regions,
+ const CallEvent *Call)>
+ CheckRegionChangesFunc;
+
+ typedef CheckerFn<bool (ProgramStateRef)> WantsRegionChangeUpdateFunc;
+
+ typedef CheckerFn<ProgramStateRef (ProgramStateRef,
+ const InvalidatedSymbols &Escaped,
+ const CallEvent *Call,
+ PointerEscapeKind Kind,
+ RegionAndSymbolInvalidationTraits *ITraits)>
+ CheckPointerEscapeFunc;
+
+ typedef CheckerFn<ProgramStateRef (ProgramStateRef,
+ const SVal &cond, bool assumption)>
+ EvalAssumeFunc;
+
+ typedef CheckerFn<bool (const CallExpr *, CheckerContext &)>
+ EvalCallFunc;
+
+ typedef CheckerFn<void (const TranslationUnitDecl *,
+ AnalysisManager&, BugReporter &)>
+ CheckEndOfTranslationUnit;
+
+ typedef bool (*HandlesStmtFunc)(const Stmt *D);
+ void _registerForPreStmt(CheckStmtFunc checkfn,
+ HandlesStmtFunc isForStmtFn);
+ void _registerForPostStmt(CheckStmtFunc checkfn,
+ HandlesStmtFunc isForStmtFn);
+
+ void _registerForPreObjCMessage(CheckObjCMessageFunc checkfn);
+ void _registerForPostObjCMessage(CheckObjCMessageFunc checkfn);
+
+ void _registerForObjCMessageNil(CheckObjCMessageFunc checkfn);
+
+ void _registerForPreCall(CheckCallFunc checkfn);
+ void _registerForPostCall(CheckCallFunc checkfn);
+
+ void _registerForLocation(CheckLocationFunc checkfn);
+
+ void _registerForBind(CheckBindFunc checkfn);
+
+ void _registerForEndAnalysis(CheckEndAnalysisFunc checkfn);
+
+ void _registerForEndFunction(CheckEndFunctionFunc checkfn);
+
+ void _registerForBranchCondition(CheckBranchConditionFunc checkfn);
+
+ void _registerForLiveSymbols(CheckLiveSymbolsFunc checkfn);
+
+ void _registerForDeadSymbols(CheckDeadSymbolsFunc checkfn);
+
+ void _registerForRegionChanges(CheckRegionChangesFunc checkfn,
+ WantsRegionChangeUpdateFunc wantUpdateFn);
+
+ void _registerForPointerEscape(CheckPointerEscapeFunc checkfn);
+
+ void _registerForConstPointerEscape(CheckPointerEscapeFunc checkfn);
+
+ void _registerForEvalAssume(EvalAssumeFunc checkfn);
+
+ void _registerForEvalCall(EvalCallFunc checkfn);
+
+ void _registerForEndOfTranslationUnit(CheckEndOfTranslationUnit checkfn);
+
+//===----------------------------------------------------------------------===//
+// Internal registration functions for events.
+//===----------------------------------------------------------------------===//
+
+ typedef void *EventTag;
+ typedef CheckerFn<void (const void *event)> CheckEventFunc;
+
+ template <typename EVENT>
+ void _registerListenerForEvent(CheckEventFunc checkfn) {
+ EventInfo &info = Events[getTag<EVENT>()];
+ info.Checkers.push_back(checkfn);
+ }
+
+ template <typename EVENT>
+ void _registerDispatcherForEvent() {
+ EventInfo &info = Events[getTag<EVENT>()];
+ info.HasDispatcher = true;
+ }
+
+ template <typename EVENT>
+ void _dispatchEvent(const EVENT &event) const {
+ EventsTy::const_iterator I = Events.find(getTag<EVENT>());
+ if (I == Events.end())
+ return;
+ const EventInfo &info = I->second;
+ for (unsigned i = 0, e = info.Checkers.size(); i != e; ++i)
+ info.Checkers[i](&event);
+ }
+
+//===----------------------------------------------------------------------===//
+// Implementation details.
+//===----------------------------------------------------------------------===//
+
+private:
+ template <typename CHECKER>
+ static void destruct(void *obj) { delete static_cast<CHECKER *>(obj); }
+
+ template <typename T>
+ static void *getTag() { static int tag; return &tag; }
+
+ llvm::DenseMap<CheckerTag, CheckerRef> CheckerTags;
+
+ std::vector<CheckerDtor> CheckerDtors;
+
+ struct DeclCheckerInfo {
+ CheckDeclFunc CheckFn;
+ HandlesDeclFunc IsForDeclFn;
+ };
+ std::vector<DeclCheckerInfo> DeclCheckers;
+
+ std::vector<CheckDeclFunc> BodyCheckers;
+
+ typedef SmallVector<CheckDeclFunc, 4> CachedDeclCheckers;
+ typedef llvm::DenseMap<unsigned, CachedDeclCheckers> CachedDeclCheckersMapTy;
+ CachedDeclCheckersMapTy CachedDeclCheckersMap;
+
+ struct StmtCheckerInfo {
+ CheckStmtFunc CheckFn;
+ HandlesStmtFunc IsForStmtFn;
+ bool IsPreVisit;
+ };
+ std::vector<StmtCheckerInfo> StmtCheckers;
+
+ typedef SmallVector<CheckStmtFunc, 4> CachedStmtCheckers;
+ typedef llvm::DenseMap<unsigned, CachedStmtCheckers> CachedStmtCheckersMapTy;
+ CachedStmtCheckersMapTy CachedStmtCheckersMap;
+
+ const CachedStmtCheckers &getCachedStmtCheckersFor(const Stmt *S,
+ bool isPreVisit);
+
+ /// Returns the checkers that have registered for callbacks of the
+ /// given \p Kind.
+ const std::vector<CheckObjCMessageFunc> &
+ getObjCMessageCheckers(ObjCMessageVisitKind Kind);
+
+ std::vector<CheckObjCMessageFunc> PreObjCMessageCheckers;
+ std::vector<CheckObjCMessageFunc> PostObjCMessageCheckers;
+ std::vector<CheckObjCMessageFunc> ObjCMessageNilCheckers;
+
+ std::vector<CheckCallFunc> PreCallCheckers;
+ std::vector<CheckCallFunc> PostCallCheckers;
+
+ std::vector<CheckLocationFunc> LocationCheckers;
+
+ std::vector<CheckBindFunc> BindCheckers;
+
+ std::vector<CheckEndAnalysisFunc> EndAnalysisCheckers;
+
+ std::vector<CheckEndFunctionFunc> EndFunctionCheckers;
+
+ std::vector<CheckBranchConditionFunc> BranchConditionCheckers;
+
+ std::vector<CheckLiveSymbolsFunc> LiveSymbolsCheckers;
+
+ std::vector<CheckDeadSymbolsFunc> DeadSymbolsCheckers;
+
+ struct RegionChangesCheckerInfo {
+ CheckRegionChangesFunc CheckFn;
+ WantsRegionChangeUpdateFunc WantUpdateFn;
+ };
+ std::vector<RegionChangesCheckerInfo> RegionChangesCheckers;
+
+ std::vector<CheckPointerEscapeFunc> PointerEscapeCheckers;
+
+ std::vector<EvalAssumeFunc> EvalAssumeCheckers;
+
+ std::vector<EvalCallFunc> EvalCallCheckers;
+
+ std::vector<CheckEndOfTranslationUnit> EndOfTranslationUnitCheckers;
+
+ struct EventInfo {
+ SmallVector<CheckEventFunc, 4> Checkers;
+ bool HasDispatcher;
+ EventInfo() : HasDispatcher(false) { }
+ };
+
+ typedef llvm::DenseMap<EventTag, EventInfo> EventsTy;
+ EventsTy Events;
+};
+
+} // end ento namespace
+
+} // end clang namespace
+
+#endif
diff --git a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/CheckerOptInfo.h b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/CheckerOptInfo.h
new file mode 100644
index 0000000..e981871
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/CheckerOptInfo.h
@@ -0,0 +1,44 @@
+//===--- CheckerOptInfo.h - Specifies which checkers to use -----*- 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_STATICANALYZER_CORE_CHECKEROPTINFO_H
+#define LLVM_CLANG_STATICANALYZER_CORE_CHECKEROPTINFO_H
+
+#include "clang/Basic/LLVM.h"
+#include "llvm/ADT/StringRef.h"
+
+namespace clang {
+namespace ento {
+
+/// Represents a request to include or exclude a checker or package from a
+/// specific analysis run.
+///
+/// \sa CheckerRegistry::initializeManager
+class CheckerOptInfo {
+ StringRef Name;
+ bool Enable;
+ bool Claimed;
+
+public:
+ CheckerOptInfo(StringRef name, bool enable)
+ : Name(name), Enable(enable), Claimed(false) { }
+
+ StringRef 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; }
+};
+
+} // end namespace ento
+} // end namespace clang
+
+#endif
diff --git a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/CheckerRegistry.h b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/CheckerRegistry.h
new file mode 100644
index 0000000..c9724c0
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/CheckerRegistry.h
@@ -0,0 +1,140 @@
+//===--- CheckerRegistry.h - Maintains all available checkers ---*- 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_STATICANALYZER_CORE_CHECKERREGISTRY_H
+#define LLVM_CLANG_STATICANALYZER_CORE_CHECKERREGISTRY_H
+
+#include "clang/Basic/LLVM.h"
+#include "clang/StaticAnalyzer/Core/CheckerManager.h"
+#include <vector>
+
+// FIXME: move this information to an HTML file in docs/.
+// At the very least, a checker plugin is a dynamic library that exports
+// clang_analyzerAPIVersionString. This should be defined as follows:
+//
+// extern "C"
+// const char clang_analyzerAPIVersionString[] =
+// CLANG_ANALYZER_API_VERSION_STRING;
+//
+// This is used to check whether the current version of the analyzer is known to
+// be incompatible with a plugin. Plugins with incompatible version strings,
+// or without a version string at all, will not be loaded.
+//
+// To add a custom checker to the analyzer, the plugin must also define the
+// function clang_registerCheckers. For example:
+//
+// extern "C"
+// void clang_registerCheckers (CheckerRegistry &registry) {
+// registry.addChecker<MainCallChecker>("example.MainCallChecker",
+// "Disallows calls to functions called main");
+// }
+//
+// The first method argument is the full name of the checker, including its
+// enclosing package. By convention, the registered name of a checker is the
+// name of the associated class (the template argument).
+// The second method argument is a short human-readable description of the
+// checker.
+//
+// The clang_registerCheckers function may add any number of checkers to the
+// registry. If any checkers require additional initialization, use the three-
+// argument form of CheckerRegistry::addChecker.
+//
+// To load a checker plugin, specify the full path to the dynamic library as
+// the argument to the -load option in the cc1 frontend. You can then enable
+// your custom checker using the -analyzer-checker:
+//
+// clang -cc1 -load </path/to/plugin.dylib> -analyze
+// -analyzer-checker=<example.MainCallChecker>
+//
+// For a complete working example, see examples/analyzer-plugin.
+
+#ifndef CLANG_ANALYZER_API_VERSION_STRING
+// FIXME: The Clang version string is not particularly granular;
+// the analyzer infrastructure can change a lot between releases.
+// Unfortunately, this string has to be statically embedded in each plugin,
+// so we can't just use the functions defined in Version.h.
+#include "clang/Basic/Version.h"
+#define CLANG_ANALYZER_API_VERSION_STRING CLANG_VERSION_STRING
+#endif
+
+namespace clang {
+class DiagnosticsEngine;
+class AnalyzerOptions;
+
+namespace ento {
+
+class CheckerOptInfo;
+
+/// Manages a set of available checkers for running a static analysis.
+/// The checkers are organized into packages by full name, where including
+/// a package will recursively include all subpackages and checkers within it.
+/// For example, the checker "core.builtin.NoReturnFunctionChecker" will be
+/// included if initializeManager() is called with an option of "core",
+/// "core.builtin", or the full name "core.builtin.NoReturnFunctionChecker".
+class CheckerRegistry {
+public:
+ /// Initialization functions perform any necessary setup for a checker.
+ /// They should include a call to CheckerManager::registerChecker.
+ typedef void (*InitializationFunction)(CheckerManager &);
+ struct CheckerInfo {
+ InitializationFunction Initialize;
+ StringRef FullName;
+ StringRef Desc;
+
+ CheckerInfo(InitializationFunction fn, StringRef name, StringRef desc)
+ : Initialize(fn), FullName(name), Desc(desc) {}
+ };
+
+ typedef std::vector<CheckerInfo> CheckerInfoList;
+
+private:
+ template <typename T>
+ static void initializeManager(CheckerManager &mgr) {
+ mgr.registerChecker<T>();
+ }
+
+public:
+ /// Adds a checker to the registry. Use this non-templated overload when your
+ /// checker requires custom initialization.
+ void addChecker(InitializationFunction fn, StringRef fullName,
+ StringRef desc);
+
+ /// Adds a checker to the registry. Use this templated overload when your
+ /// checker does not require any custom initialization.
+ template <class T>
+ void addChecker(StringRef fullName, StringRef desc) {
+ // Avoid MSVC's Compiler Error C2276:
+ // http://msdn.microsoft.com/en-us/library/850cstw1(v=VS.80).aspx
+ addChecker(&CheckerRegistry::initializeManager<T>, fullName, desc);
+ }
+
+ /// Initializes a CheckerManager by calling the initialization functions for
+ /// all checkers specified by the given CheckerOptInfo list. The order of this
+ /// list is significant; later options can be used to reverse earlier ones.
+ /// This can be used to exclude certain checkers in an included package.
+ void initializeManager(CheckerManager &mgr,
+ SmallVectorImpl<CheckerOptInfo> &opts) const;
+
+ /// Check if every option corresponds to a specific checker or package.
+ void validateCheckerOptions(const AnalyzerOptions &opts,
+ DiagnosticsEngine &diags) const;
+
+ /// Prints the name and description of all checkers in this registry.
+ /// This output is not intended to be machine-parseable.
+ void printHelp(raw_ostream &out, size_t maxNameChars = 30) const ;
+
+private:
+ mutable CheckerInfoList Checkers;
+ mutable llvm::StringMap<size_t> Packages;
+};
+
+} // end namespace ento
+} // end namespace clang
+
+#endif
diff --git a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/IssueHash.h b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/IssueHash.h
new file mode 100644
index 0000000..b3c4f14
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/IssueHash.h
@@ -0,0 +1,51 @@
+//===---------- IssueHash.h - Generate identification hashes ----*- 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_STATICANALYZER_CORE_ISSUE_HASH_H
+#define LLVM_CLANG_STATICANALYZER_CORE_ISSUE_HASH_H
+
+#include "llvm/ADT/SmallString.h"
+
+namespace clang {
+class Decl;
+class SourceManager;
+class FullSourceLoc;
+class LangOptions;
+
+/// \brief Get an MD5 hash to help identify bugs.
+///
+/// This function returns a hash that helps identify bugs within a source file.
+/// This identification can be utilized to diff diagnostic results on different
+/// snapshots of a projects, or maintain a database of suppressed diagnotics.
+///
+/// The hash contains the normalized text of the location associated with the
+/// diagnostic. Normalization means removing the whitespaces. The associated
+/// location is the either the last location of a diagnostic path or a uniqueing
+/// location. The bugtype and the name of the checker is also part of the hash.
+/// The last component is the string representation of the enclosing declaration
+/// of the associated location.
+///
+/// In case a new hash is introduced, the old one should still be maintained for
+/// a while. One should not introduce a new hash for every change, it is
+/// possible to introduce experimental hashes that may change in the future.
+/// Such hashes should be marked as experimental using a comment in the plist
+/// files.
+llvm::SmallString<32> GetIssueHash(const SourceManager &SM,
+ FullSourceLoc &IssueLoc,
+ llvm::StringRef CheckerName,
+ llvm::StringRef BugType, const Decl *D,
+ const LangOptions &LangOpts);
+
+/// \brief Get the string representation of issue hash. See GetIssueHash() for
+/// more information.
+std::string GetIssueString(const SourceManager &SM, FullSourceLoc &IssueLoc,
+ llvm::StringRef CheckerName, llvm::StringRef BugType,
+ const Decl *D, const LangOptions &LangOpts);
+} // namespace clang
+
+#endif
diff --git a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathDiagnosticConsumers.h b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathDiagnosticConsumers.h
new file mode 100644
index 0000000..ce512fd
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathDiagnosticConsumers.h
@@ -0,0 +1,40 @@
+//===--- 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_STATICANALYZER_CORE_PATHDIAGNOSTICCONSUMERS_H
+#define LLVM_CLANG_STATICANALYZER_CORE_PATHDIAGNOSTICCONSUMERS_H
+
+#include <string>
+#include <vector>
+
+namespace clang {
+
+class AnalyzerOptions;
+class Preprocessor;
+
+namespace ento {
+
+class PathDiagnosticConsumer;
+typedef std::vector<PathDiagnosticConsumer*> PathDiagnosticConsumers;
+
+#define ANALYSIS_DIAGNOSTICS(NAME, CMDFLAG, DESC, CREATEFN)\
+void CREATEFN(AnalyzerOptions &AnalyzerOpts,\
+ PathDiagnosticConsumers &C,\
+ const std::string &Prefix,\
+ const Preprocessor &PP);
+#include "clang/StaticAnalyzer/Core/Analyses.def"
+
+} // end 'ento' namespace
+} // end 'clang' namespace
+
+#endif
diff --git a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/APSIntType.h b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/APSIntType.h
new file mode 100644
index 0000000..cc8a9b8
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/APSIntType.h
@@ -0,0 +1,109 @@
+//== APSIntType.h - Simple record of the type of APSInts --------*- 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_STATICANALYZER_CORE_PATHSENSITIVE_APSINTTYPE_H
+#define LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_APSINTTYPE_H
+
+#include "llvm/ADT/APSInt.h"
+#include <tuple>
+
+namespace clang {
+namespace ento {
+
+/// \brief A record of the "type" of an APSInt, used for conversions.
+class APSIntType {
+ uint32_t BitWidth;
+ bool IsUnsigned;
+
+public:
+ APSIntType(uint32_t Width, bool Unsigned)
+ : BitWidth(Width), IsUnsigned(Unsigned) {}
+
+ /* implicit */ APSIntType(const llvm::APSInt &Value)
+ : BitWidth(Value.getBitWidth()), IsUnsigned(Value.isUnsigned()) {}
+
+ uint32_t getBitWidth() const { return BitWidth; }
+ bool isUnsigned() const { return IsUnsigned; }
+
+ /// \brief Convert a given APSInt, in place, to match this type.
+ ///
+ /// This behaves like a C cast: converting 255u8 (0xFF) to s16 gives
+ /// 255 (0x00FF), and converting -1s8 (0xFF) to u16 gives 65535 (0xFFFF).
+ void apply(llvm::APSInt &Value) const {
+ // Note the order here. We extend first to preserve the sign, if this value
+ // is signed, /then/ match the signedness of the result type.
+ Value = Value.extOrTrunc(BitWidth);
+ Value.setIsUnsigned(IsUnsigned);
+ }
+
+ /// Convert and return a new APSInt with the given value, but this
+ /// type's bit width and signedness.
+ ///
+ /// \see apply
+ llvm::APSInt convert(const llvm::APSInt &Value) const LLVM_READONLY {
+ llvm::APSInt Result(Value, Value.isUnsigned());
+ apply(Result);
+ return Result;
+ }
+
+ /// Returns an all-zero value for this type.
+ llvm::APSInt getZeroValue() const LLVM_READONLY {
+ return llvm::APSInt(BitWidth, IsUnsigned);
+ }
+
+ /// Returns the minimum value for this type.
+ llvm::APSInt getMinValue() const LLVM_READONLY {
+ return llvm::APSInt::getMinValue(BitWidth, IsUnsigned);
+ }
+
+ /// Returns the maximum value for this type.
+ llvm::APSInt getMaxValue() const LLVM_READONLY {
+ return llvm::APSInt::getMaxValue(BitWidth, IsUnsigned);
+ }
+
+ llvm::APSInt getValue(uint64_t RawValue) const LLVM_READONLY {
+ return (llvm::APSInt(BitWidth, IsUnsigned) = RawValue);
+ }
+
+ /// Used to classify whether a value is representable using this type.
+ ///
+ /// \see testInRange
+ enum RangeTestResultKind {
+ RTR_Below = -1, ///< Value is less than the minimum representable value.
+ RTR_Within = 0, ///< Value is representable using this type.
+ RTR_Above = 1 ///< Value is greater than the maximum representable value.
+ };
+
+ /// Tests whether a given value is losslessly representable using this type.
+ ///
+ /// \param Val The value to test.
+ /// \param AllowMixedSign Whether or not to allow signedness conversions.
+ /// This determines whether -1s8 is considered in range
+ /// for 'unsigned char' (u8).
+ RangeTestResultKind testInRange(const llvm::APSInt &Val,
+ bool AllowMixedSign) const LLVM_READONLY;
+
+ bool operator==(const APSIntType &Other) const {
+ return BitWidth == Other.BitWidth && IsUnsigned == Other.IsUnsigned;
+ }
+
+ /// \brief Provide an ordering for finding a common conversion type.
+ ///
+ /// Unsigned integers are considered to be better conversion types than
+ /// signed integers of the same width.
+ bool operator<(const APSIntType &Other) const {
+ return std::tie(BitWidth, IsUnsigned) <
+ std::tie(Other.BitWidth, Other.IsUnsigned);
+ }
+};
+
+} // end ento 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..3e0913e
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h
@@ -0,0 +1,135 @@
+//== 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_STATICANALYZER_CORE_PATHSENSITIVE_ANALYSISMANAGER_H
+#define LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_ANALYSISMANAGER_H
+
+#include "clang/Analysis/AnalysisContext.h"
+#include "clang/StaticAnalyzer/Core/AnalyzerOptions.h"
+#include "clang/StaticAnalyzer/Core/BugReporter/BugReporter.h"
+#include "clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h"
+#include "clang/StaticAnalyzer/Core/PathDiagnosticConsumers.h"
+
+namespace clang {
+
+class CodeInjector;
+
+namespace ento {
+ class CheckerManager;
+
+class AnalysisManager : public BugReporterData {
+ virtual void anchor();
+ AnalysisDeclContextManager AnaCtxMgr;
+
+ ASTContext &Ctx;
+ DiagnosticsEngine &Diags;
+ const LangOptions &LangOpts;
+ PathDiagnosticConsumers PathConsumers;
+
+ // Configurable components creators.
+ StoreManagerCreator CreateStoreMgr;
+ ConstraintManagerCreator CreateConstraintMgr;
+
+ CheckerManager *CheckerMgr;
+
+public:
+ AnalyzerOptions &options;
+
+ AnalysisManager(ASTContext &ctx,DiagnosticsEngine &diags,
+ const LangOptions &lang,
+ const PathDiagnosticConsumers &Consumers,
+ StoreManagerCreator storemgr,
+ ConstraintManagerCreator constraintmgr,
+ CheckerManager *checkerMgr,
+ AnalyzerOptions &Options,
+ CodeInjector* injector = nullptr);
+
+ ~AnalysisManager() override;
+
+ void ClearContexts() {
+ AnaCtxMgr.clear();
+ }
+
+ AnalysisDeclContextManager& getAnalysisDeclContextManager() {
+ return AnaCtxMgr;
+ }
+
+ StoreManagerCreator getStoreManagerCreator() {
+ return CreateStoreMgr;
+ }
+
+ AnalyzerOptions& getAnalyzerOptions() override {
+ return options;
+ }
+
+ ConstraintManagerCreator getConstraintManagerCreator() {
+ return CreateConstraintMgr;
+ }
+
+ CheckerManager *getCheckerManager() const { return CheckerMgr; }
+
+ ASTContext &getASTContext() override {
+ return Ctx;
+ }
+
+ SourceManager &getSourceManager() override {
+ return getASTContext().getSourceManager();
+ }
+
+ DiagnosticsEngine &getDiagnostic() override {
+ return Diags;
+ }
+
+ const LangOptions &getLangOpts() const {
+ return LangOpts;
+ }
+
+ ArrayRef<PathDiagnosticConsumer*> getPathDiagnosticConsumers() override {
+ return PathConsumers;
+ }
+
+ void FlushDiagnostics();
+
+ bool shouldVisualize() const {
+ return options.visualizeExplodedGraphWithGraphViz ||
+ options.visualizeExplodedGraphWithUbiGraph;
+ }
+
+ bool shouldInlineCall() const {
+ return options.getIPAMode() != IPAK_None;
+ }
+
+ CFG *getCFG(Decl const *D) {
+ return AnaCtxMgr.getContext(D)->getCFG();
+ }
+
+ template <typename T>
+ T *getAnalysis(Decl const *D) {
+ return AnaCtxMgr.getContext(D)->getAnalysis<T>();
+ }
+
+ ParentMap &getParentMap(Decl const *D) {
+ return AnaCtxMgr.getContext(D)->getParentMap();
+ }
+
+ AnalysisDeclContext *getAnalysisDeclContext(const Decl *D) {
+ return AnaCtxMgr.getContext(D);
+ }
+};
+
+} // enAnaCtxMgrspace
+
+} // 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..5b007f1
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/BasicValueFactory.h
@@ -0,0 +1,200 @@
+//=== 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_STATICANALYZER_CORE_PATHSENSITIVE_BASICVALUEFACTORY_H
+#define LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_BASICVALUEFACTORY_H
+
+#include "clang/AST/ASTContext.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/APSIntType.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/SVals.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/StoreRef.h"
+
+namespace clang {
+namespace ento {
+
+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 {
+ StoreRef store;
+ const TypedValueRegion *region;
+public:
+ LazyCompoundValData(const StoreRef &st, const TypedValueRegion *r)
+ : store(st), region(r) {}
+
+ const void *getStore() const { return store.getStore(); }
+ const TypedValueRegion *getRegion() const { return region; }
+
+ static void Profile(llvm::FoldingSetNodeID& ID,
+ const StoreRef &store,
+ const TypedValueRegion *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;
+
+ // This is private because external clients should use the factory
+ // method that takes a QualType.
+ const llvm::APSInt& getValue(uint64_t X, unsigned BitWidth, bool isUnsigned);
+
+public:
+ BasicValueFactory(ASTContext &ctx, llvm::BumpPtrAllocator &Alloc)
+ : Ctx(ctx), BPAlloc(Alloc), PersistentSVals(nullptr),
+ PersistentSValPairs(nullptr), 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, QualType T);
+
+ /// Returns the type of the APSInt used to store values of the given QualType.
+ APSIntType getAPSIntType(QualType T) const {
+ assert(T->isIntegralOrEnumerationType() || Loc::isLocType(T));
+ return APSIntType(Ctx.getTypeSize(T),
+ !T->isSignedIntegerOrEnumerationType());
+ }
+
+ /// 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) {
+ APSIntType TargetType(To);
+ if (TargetType == APSIntType(From))
+ return From;
+
+ return getValue(TargetType.convert(From));
+ }
+
+ const llvm::APSInt &Convert(QualType T, const llvm::APSInt &From) {
+ APSIntType TargetType = getAPSIntType(T);
+ if (TargetType == APSIntType(From))
+ return From;
+
+ return getValue(TargetType.convert(From));
+ }
+
+ 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(APSIntType(v).getMaxValue());
+ }
+
+ inline const llvm::APSInt& getMinValue(const llvm::APSInt &v) {
+ return getValue(APSIntType(v).getMinValue());
+ }
+
+ inline const llvm::APSInt& getMaxValue(QualType T) {
+ return getValue(getAPSIntType(T).getMaxValue());
+ }
+
+ inline const llvm::APSInt& getMinValue(QualType T) {
+ return getValue(getAPSIntType(T).getMinValue());
+ }
+
+ 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 StoreRef &store,
+ const TypedValueRegion *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..1d779e6
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/BlockCounter.h
@@ -0,0 +1,60 @@
+//==- 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_STATICANALYZER_CORE_PATHSENSITIVE_BLOCKCOUNTER_H
+#define LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_BLOCKCOUNTER_H
+
+#include "llvm/Support/Allocator.h"
+
+namespace clang {
+
+class StackFrameContext;
+
+namespace ento {
+
+/// \class BlockCounter
+/// \brief An abstract data type used to count the number of times a given
+/// block has been visited along a path analyzed by CoreEngine.
+class BlockCounter {
+ void *Data;
+
+ BlockCounter(void *D) : Data(D) {}
+
+public:
+ BlockCounter() : Data(nullptr) {}
+
+ 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/CallEvent.h b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h
new file mode 100644
index 0000000..b09dffa
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h
@@ -0,0 +1,1091 @@
+//===- CallEvent.h - Wrapper for all function and method calls ----*- C++ -*--//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+/// \file This file defines CallEvent and its subclasses, which represent path-
+/// sensitive instances of different kinds of function and method calls
+/// (C, C++, and Objective-C).
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_CALLEVENT_H
+#define LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_CALLEVENT_H
+
+#include "clang/AST/DeclCXX.h"
+#include "clang/AST/ExprCXX.h"
+#include "clang/AST/ExprObjC.h"
+#include "clang/Analysis/AnalysisContext.h"
+#include "clang/Basic/SourceManager.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/SVals.h"
+#include "llvm/ADT/PointerIntPair.h"
+
+namespace clang {
+class ProgramPoint;
+class ProgramPointTag;
+
+namespace ento {
+
+enum CallEventKind {
+ CE_Function,
+ CE_CXXMember,
+ CE_CXXMemberOperator,
+ CE_CXXDestructor,
+ CE_BEG_CXX_INSTANCE_CALLS = CE_CXXMember,
+ CE_END_CXX_INSTANCE_CALLS = CE_CXXDestructor,
+ CE_CXXConstructor,
+ CE_CXXAllocator,
+ CE_BEG_FUNCTION_CALLS = CE_Function,
+ CE_END_FUNCTION_CALLS = CE_CXXAllocator,
+ CE_Block,
+ CE_ObjCMessage
+};
+
+class CallEvent;
+class CallEventManager;
+
+template<typename T = CallEvent>
+class CallEventRef : public IntrusiveRefCntPtr<const T> {
+public:
+ CallEventRef(const T *Call) : IntrusiveRefCntPtr<const T>(Call) {}
+ CallEventRef(const CallEventRef &Orig) : IntrusiveRefCntPtr<const T>(Orig) {}
+
+ CallEventRef<T> cloneWithState(ProgramStateRef State) const {
+ return this->get()->template cloneWithState<T>(State);
+ }
+
+ // Allow implicit conversions to a superclass type, since CallEventRef
+ // behaves like a pointer-to-const.
+ template <typename SuperT>
+ operator CallEventRef<SuperT> () const {
+ return this->get();
+ }
+};
+
+/// \class RuntimeDefinition
+/// \brief Defines the runtime definition of the called function.
+///
+/// Encapsulates the information we have about which Decl will be used
+/// when the call is executed on the given path. When dealing with dynamic
+/// dispatch, the information is based on DynamicTypeInfo and might not be
+/// precise.
+class RuntimeDefinition {
+ /// The Declaration of the function which could be called at runtime.
+ /// NULL if not available.
+ const Decl *D;
+
+ /// The region representing an object (ObjC/C++) on which the method is
+ /// called. With dynamic dispatch, the method definition depends on the
+ /// runtime type of this object. NULL when the DynamicTypeInfo is
+ /// precise.
+ const MemRegion *R;
+
+public:
+ RuntimeDefinition(): D(nullptr), R(nullptr) {}
+ RuntimeDefinition(const Decl *InD): D(InD), R(nullptr) {}
+ RuntimeDefinition(const Decl *InD, const MemRegion *InR): D(InD), R(InR) {}
+ const Decl *getDecl() { return D; }
+
+ /// \brief Check if the definition we have is precise.
+ /// If not, it is possible that the call dispatches to another definition at
+ /// execution time.
+ bool mayHaveOtherDefinitions() { return R != nullptr; }
+
+ /// When other definitions are possible, returns the region whose runtime type
+ /// determines the method definition.
+ const MemRegion *getDispatchRegion() { return R; }
+};
+
+/// \brief Represents an abstract call to a function or method along a
+/// particular path.
+///
+/// CallEvents are created through the factory methods of CallEventManager.
+///
+/// CallEvents should always be cheap to create and destroy. In order for
+/// CallEventManager to be able to re-use CallEvent-sized memory blocks,
+/// subclasses of CallEvent may not add any data members to the base class.
+/// Use the "Data" and "Location" fields instead.
+class CallEvent {
+public:
+ typedef CallEventKind Kind;
+
+private:
+ ProgramStateRef State;
+ const LocationContext *LCtx;
+ llvm::PointerUnion<const Expr *, const Decl *> Origin;
+
+ void operator=(const CallEvent &) = delete;
+
+protected:
+ // This is user data for subclasses.
+ const void *Data;
+
+ // This is user data for subclasses.
+ // This should come right before RefCount, so that the two fields can be
+ // packed together on LP64 platforms.
+ SourceLocation Location;
+
+private:
+ mutable unsigned RefCount;
+
+ template <typename T> friend struct llvm::IntrusiveRefCntPtrInfo;
+ void Retain() const { ++RefCount; }
+ void Release() const;
+
+protected:
+ friend class CallEventManager;
+
+ CallEvent(const Expr *E, ProgramStateRef state, const LocationContext *lctx)
+ : State(state), LCtx(lctx), Origin(E), RefCount(0) {}
+
+ CallEvent(const Decl *D, ProgramStateRef state, const LocationContext *lctx)
+ : State(state), LCtx(lctx), Origin(D), RefCount(0) {}
+
+ // DO NOT MAKE PUBLIC
+ CallEvent(const CallEvent &Original)
+ : State(Original.State), LCtx(Original.LCtx), Origin(Original.Origin),
+ Data(Original.Data), Location(Original.Location), RefCount(0) {}
+
+ /// Copies this CallEvent, with vtable intact, into a new block of memory.
+ virtual void cloneTo(void *Dest) const = 0;
+
+ /// \brief Get the value of arbitrary expressions at this point in the path.
+ SVal getSVal(const Stmt *S) const {
+ return getState()->getSVal(S, getLocationContext());
+ }
+
+
+ typedef SmallVectorImpl<SVal> ValueList;
+
+ /// \brief Used to specify non-argument regions that will be invalidated as a
+ /// result of this call.
+ virtual void getExtraInvalidatedValues(ValueList &Values,
+ RegionAndSymbolInvalidationTraits *ETraits) const {}
+
+public:
+ virtual ~CallEvent() {}
+
+ /// \brief Returns the kind of call this is.
+ virtual Kind getKind() const = 0;
+
+ /// \brief Returns the declaration of the function or method that will be
+ /// called. May be null.
+ virtual const Decl *getDecl() const {
+ return Origin.dyn_cast<const Decl *>();
+ }
+
+ /// \brief The state in which the call is being evaluated.
+ const ProgramStateRef &getState() const {
+ return State;
+ }
+
+ /// \brief The context in which the call is being evaluated.
+ const LocationContext *getLocationContext() const {
+ return LCtx;
+ }
+
+ /// \brief Returns the definition of the function or method that will be
+ /// called.
+ virtual RuntimeDefinition getRuntimeDefinition() const = 0;
+
+ /// \brief Returns the expression whose value will be the result of this call.
+ /// May be null.
+ const Expr *getOriginExpr() const {
+ return Origin.dyn_cast<const Expr *>();
+ }
+
+ /// \brief Returns the number of arguments (explicit and implicit).
+ ///
+ /// Note that this may be greater than the number of parameters in the
+ /// callee's declaration, and that it may include arguments not written in
+ /// the source.
+ virtual unsigned getNumArgs() const = 0;
+
+ /// \brief Returns true if the callee is known to be from a system header.
+ bool isInSystemHeader() const {
+ const Decl *D = getDecl();
+ if (!D)
+ return false;
+
+ SourceLocation Loc = D->getLocation();
+ if (Loc.isValid()) {
+ const SourceManager &SM =
+ getState()->getStateManager().getContext().getSourceManager();
+ return SM.isInSystemHeader(D->getLocation());
+ }
+
+ // Special case for implicitly-declared global operator new/delete.
+ // These should be considered system functions.
+ if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D))
+ return FD->isOverloadedOperator() && FD->isImplicit() && FD->isGlobal();
+
+ return false;
+ }
+
+ /// \brief Returns a source range for the entire call, suitable for
+ /// outputting in diagnostics.
+ virtual SourceRange getSourceRange() const {
+ return getOriginExpr()->getSourceRange();
+ }
+
+ /// \brief Returns the value of a given argument at the time of the call.
+ virtual SVal getArgSVal(unsigned Index) const;
+
+ /// \brief Returns the expression associated with a given argument.
+ /// May be null if this expression does not appear in the source.
+ virtual const Expr *getArgExpr(unsigned Index) const { return nullptr; }
+
+ /// \brief Returns the source range for errors associated with this argument.
+ ///
+ /// May be invalid if the argument is not written in the source.
+ virtual SourceRange getArgSourceRange(unsigned Index) const;
+
+ /// \brief Returns the result type, adjusted for references.
+ QualType getResultType() const;
+
+ /// \brief Returns the return value of the call.
+ ///
+ /// This should only be called if the CallEvent was created using a state in
+ /// which the return value has already been bound to the origin expression.
+ SVal getReturnValue() const;
+
+ /// \brief Returns true if the type of any of the non-null arguments satisfies
+ /// the condition.
+ bool hasNonNullArgumentsWithType(bool (*Condition)(QualType)) const;
+
+ /// \brief Returns true if any of the arguments appear to represent callbacks.
+ bool hasNonZeroCallbackArg() const;
+
+ /// \brief Returns true if any of the arguments is void*.
+ bool hasVoidPointerToNonConstArg() const;
+
+ /// \brief Returns true if any of the arguments are known to escape to long-
+ /// term storage, even if this method will not modify them.
+ // NOTE: The exact semantics of this are still being defined!
+ // We don't really want a list of hardcoded exceptions in the long run,
+ // but we don't want duplicated lists of known APIs in the short term either.
+ virtual bool argumentsMayEscape() const {
+ return hasNonZeroCallbackArg();
+ }
+
+ /// \brief Returns true if the callee is an externally-visible function in the
+ /// top-level namespace, such as \c malloc.
+ ///
+ /// You can use this call to determine that a particular function really is
+ /// a library function and not, say, a C++ member function with the same name.
+ ///
+ /// If a name is provided, the function must additionally match the given
+ /// name.
+ ///
+ /// Note that this deliberately excludes C++ library functions in the \c std
+ /// namespace, but will include C library functions accessed through the
+ /// \c std namespace. This also does not check if the function is declared
+ /// as 'extern "C"', or if it uses C++ name mangling.
+ // FIXME: Add a helper for checking namespaces.
+ // FIXME: Move this down to AnyFunctionCall once checkers have more
+ // precise callbacks.
+ bool isGlobalCFunction(StringRef SpecificName = StringRef()) const;
+
+ /// \brief Returns the name of the callee, if its name is a simple identifier.
+ ///
+ /// Note that this will fail for Objective-C methods, blocks, and C++
+ /// overloaded operators. The former is named by a Selector rather than a
+ /// simple identifier, and the latter two do not have names.
+ // FIXME: Move this down to AnyFunctionCall once checkers have more
+ // precise callbacks.
+ const IdentifierInfo *getCalleeIdentifier() const {
+ const NamedDecl *ND = dyn_cast_or_null<NamedDecl>(getDecl());
+ if (!ND)
+ return nullptr;
+ return ND->getIdentifier();
+ }
+
+ /// \brief Returns an appropriate ProgramPoint for this call.
+ ProgramPoint getProgramPoint(bool IsPreVisit = false,
+ const ProgramPointTag *Tag = nullptr) const;
+
+ /// \brief Returns a new state with all argument regions invalidated.
+ ///
+ /// This accepts an alternate state in case some processing has already
+ /// occurred.
+ ProgramStateRef invalidateRegions(unsigned BlockCount,
+ ProgramStateRef Orig = nullptr) const;
+
+ typedef std::pair<Loc, SVal> FrameBindingTy;
+ typedef SmallVectorImpl<FrameBindingTy> BindingsTy;
+
+ /// Populates the given SmallVector with the bindings in the callee's stack
+ /// frame at the start of this call.
+ virtual void getInitialStackFrameContents(const StackFrameContext *CalleeCtx,
+ BindingsTy &Bindings) const = 0;
+
+ /// Returns a copy of this CallEvent, but using the given state.
+ template <typename T>
+ CallEventRef<T> cloneWithState(ProgramStateRef NewState) const;
+
+ /// Returns a copy of this CallEvent, but using the given state.
+ CallEventRef<> cloneWithState(ProgramStateRef NewState) const {
+ return cloneWithState<CallEvent>(NewState);
+ }
+
+ /// \brief Returns true if this is a statement is a function or method call
+ /// of some kind.
+ static bool isCallStmt(const Stmt *S);
+
+ /// \brief Returns the result type of a function or method declaration.
+ ///
+ /// This will return a null QualType if the result type cannot be determined.
+ static QualType getDeclaredResultType(const Decl *D);
+
+ /// \brief Returns true if the given decl is known to be variadic.
+ ///
+ /// \p D must not be null.
+ static bool isVariadic(const Decl *D);
+
+ // Iterator access to formal parameters and their types.
+private:
+ typedef std::const_mem_fun_t<QualType, ParmVarDecl> get_type_fun;
+
+public:
+ /// Return call's formal parameters.
+ ///
+ /// Remember that the number of formal parameters may not match the number
+ /// of arguments for all calls. However, the first parameter will always
+ /// correspond with the argument value returned by \c getArgSVal(0).
+ virtual ArrayRef<ParmVarDecl*> parameters() const = 0;
+
+ typedef llvm::mapped_iterator<ArrayRef<ParmVarDecl*>::iterator, get_type_fun>
+ param_type_iterator;
+
+ /// Returns an iterator over the types of the call's formal parameters.
+ ///
+ /// This uses the callee decl found by default name lookup rather than the
+ /// definition because it represents a public interface, and probably has
+ /// more annotations.
+ param_type_iterator param_type_begin() const {
+ return llvm::map_iterator(parameters().begin(),
+ get_type_fun(&ParmVarDecl::getType));
+ }
+ /// \sa param_type_begin()
+ param_type_iterator param_type_end() const {
+ return llvm::map_iterator(parameters().end(),
+ get_type_fun(&ParmVarDecl::getType));
+ }
+
+ // For debugging purposes only
+ void dump(raw_ostream &Out) const;
+ void dump() const;
+};
+
+
+/// \brief Represents a call to any sort of function that might have a
+/// FunctionDecl.
+class AnyFunctionCall : public CallEvent {
+protected:
+ AnyFunctionCall(const Expr *E, ProgramStateRef St,
+ const LocationContext *LCtx)
+ : CallEvent(E, St, LCtx) {}
+ AnyFunctionCall(const Decl *D, ProgramStateRef St,
+ const LocationContext *LCtx)
+ : CallEvent(D, St, LCtx) {}
+ AnyFunctionCall(const AnyFunctionCall &Other) : CallEvent(Other) {}
+
+public:
+ // This function is overridden by subclasses, but they must return
+ // a FunctionDecl.
+ const FunctionDecl *getDecl() const override {
+ return cast<FunctionDecl>(CallEvent::getDecl());
+ }
+
+ RuntimeDefinition getRuntimeDefinition() const override {
+ const FunctionDecl *FD = getDecl();
+ // Note that the AnalysisDeclContext will have the FunctionDecl with
+ // the definition (if one exists).
+ if (FD) {
+ AnalysisDeclContext *AD =
+ getLocationContext()->getAnalysisDeclContext()->
+ getManager()->getContext(FD);
+ if (AD->getBody())
+ return RuntimeDefinition(AD->getDecl());
+ }
+
+ return RuntimeDefinition();
+ }
+
+ bool argumentsMayEscape() const override;
+
+ void getInitialStackFrameContents(const StackFrameContext *CalleeCtx,
+ BindingsTy &Bindings) const override;
+
+ ArrayRef<ParmVarDecl *> parameters() const override;
+
+ static bool classof(const CallEvent *CA) {
+ return CA->getKind() >= CE_BEG_FUNCTION_CALLS &&
+ CA->getKind() <= CE_END_FUNCTION_CALLS;
+ }
+};
+
+/// \brief Represents a C function or static C++ member function call.
+///
+/// Example: \c fun()
+class SimpleFunctionCall : public AnyFunctionCall {
+ friend class CallEventManager;
+
+protected:
+ SimpleFunctionCall(const CallExpr *CE, ProgramStateRef St,
+ const LocationContext *LCtx)
+ : AnyFunctionCall(CE, St, LCtx) {}
+ SimpleFunctionCall(const SimpleFunctionCall &Other)
+ : AnyFunctionCall(Other) {}
+ void cloneTo(void *Dest) const override {
+ new (Dest) SimpleFunctionCall(*this);
+ }
+
+public:
+ virtual const CallExpr *getOriginExpr() const {
+ return cast<CallExpr>(AnyFunctionCall::getOriginExpr());
+ }
+
+ const FunctionDecl *getDecl() const override;
+
+ unsigned getNumArgs() const override { return getOriginExpr()->getNumArgs(); }
+
+ const Expr *getArgExpr(unsigned Index) const override {
+ return getOriginExpr()->getArg(Index);
+ }
+
+ Kind getKind() const override { return CE_Function; }
+
+ static bool classof(const CallEvent *CA) {
+ return CA->getKind() == CE_Function;
+ }
+};
+
+/// \brief Represents a call to a block.
+///
+/// Example: <tt>^{ /* ... */ }()</tt>
+class BlockCall : public CallEvent {
+ friend class CallEventManager;
+
+protected:
+ BlockCall(const CallExpr *CE, ProgramStateRef St,
+ const LocationContext *LCtx)
+ : CallEvent(CE, St, LCtx) {}
+
+ BlockCall(const BlockCall &Other) : CallEvent(Other) {}
+ void cloneTo(void *Dest) const override { new (Dest) BlockCall(*this); }
+
+ void getExtraInvalidatedValues(ValueList &Values,
+ RegionAndSymbolInvalidationTraits *ETraits) const override;
+
+public:
+ virtual const CallExpr *getOriginExpr() const {
+ return cast<CallExpr>(CallEvent::getOriginExpr());
+ }
+
+ unsigned getNumArgs() const override { return getOriginExpr()->getNumArgs(); }
+
+ const Expr *getArgExpr(unsigned Index) const override {
+ return getOriginExpr()->getArg(Index);
+ }
+
+ /// \brief Returns the region associated with this instance of the block.
+ ///
+ /// This may be NULL if the block's origin is unknown.
+ const BlockDataRegion *getBlockRegion() const;
+
+ const BlockDecl *getDecl() const override {
+ const BlockDataRegion *BR = getBlockRegion();
+ if (!BR)
+ return nullptr;
+ return BR->getDecl();
+ }
+
+ bool isConversionFromLambda() const {
+ const BlockDecl *BD = getDecl();
+ if (!BD)
+ return false;
+
+ return BD->isConversionFromLambda();
+ }
+
+ /// \brief For a block converted from a C++ lambda, returns the block
+ /// VarRegion for the variable holding the captured C++ lambda record.
+ const VarRegion *getRegionStoringCapturedLambda() const {
+ assert(isConversionFromLambda());
+ const BlockDataRegion *BR = getBlockRegion();
+ assert(BR && "Block converted from lambda must have a block region");
+
+ auto I = BR->referenced_vars_begin();
+ assert(I != BR->referenced_vars_end());
+
+ return I.getCapturedRegion();
+ }
+
+ RuntimeDefinition getRuntimeDefinition() const override {
+ if (!isConversionFromLambda())
+ return RuntimeDefinition(getDecl());
+
+ // Clang converts lambdas to blocks with an implicit user-defined
+ // conversion operator method on the lambda record that looks (roughly)
+ // like:
+ //
+ // typedef R(^block_type)(P1, P2, ...);
+ // operator block_type() const {
+ // auto Lambda = *this;
+ // return ^(P1 p1, P2 p2, ...){
+ // /* return Lambda(p1, p2, ...); */
+ // };
+ // }
+ //
+ // Here R is the return type of the lambda and P1, P2, ... are
+ // its parameter types. 'Lambda' is a fake VarDecl captured by the block
+ // that is initialized to a copy of the lambda.
+ //
+ // Sema leaves the body of a lambda-converted block empty (it is
+ // produced by CodeGen), so we can't analyze it directly. Instead, we skip
+ // the block body and analyze the operator() method on the captured lambda.
+ const VarDecl *LambdaVD = getRegionStoringCapturedLambda()->getDecl();
+ const CXXRecordDecl *LambdaDecl = LambdaVD->getType()->getAsCXXRecordDecl();
+ CXXMethodDecl* LambdaCallOperator = LambdaDecl->getLambdaCallOperator();
+
+ return RuntimeDefinition(LambdaCallOperator);
+ }
+
+ bool argumentsMayEscape() const override {
+ return true;
+ }
+
+ void getInitialStackFrameContents(const StackFrameContext *CalleeCtx,
+ BindingsTy &Bindings) const override;
+
+ ArrayRef<ParmVarDecl*> parameters() const override;
+
+ Kind getKind() const override { return CE_Block; }
+
+ static bool classof(const CallEvent *CA) {
+ return CA->getKind() == CE_Block;
+ }
+};
+
+/// \brief Represents a non-static C++ member function call, no matter how
+/// it is written.
+class CXXInstanceCall : public AnyFunctionCall {
+protected:
+ void getExtraInvalidatedValues(ValueList &Values,
+ RegionAndSymbolInvalidationTraits *ETraits) const override;
+
+ CXXInstanceCall(const CallExpr *CE, ProgramStateRef St,
+ const LocationContext *LCtx)
+ : AnyFunctionCall(CE, St, LCtx) {}
+ CXXInstanceCall(const FunctionDecl *D, ProgramStateRef St,
+ const LocationContext *LCtx)
+ : AnyFunctionCall(D, St, LCtx) {}
+
+
+ CXXInstanceCall(const CXXInstanceCall &Other) : AnyFunctionCall(Other) {}
+
+public:
+ /// \brief Returns the expression representing the implicit 'this' object.
+ virtual const Expr *getCXXThisExpr() const { return nullptr; }
+
+ /// \brief Returns the value of the implicit 'this' object.
+ virtual SVal getCXXThisVal() const;
+
+ const FunctionDecl *getDecl() const override;
+
+ RuntimeDefinition getRuntimeDefinition() const override;
+
+ void getInitialStackFrameContents(const StackFrameContext *CalleeCtx,
+ BindingsTy &Bindings) const override;
+
+ static bool classof(const CallEvent *CA) {
+ return CA->getKind() >= CE_BEG_CXX_INSTANCE_CALLS &&
+ CA->getKind() <= CE_END_CXX_INSTANCE_CALLS;
+ }
+};
+
+/// \brief Represents a non-static C++ member function call.
+///
+/// Example: \c obj.fun()
+class CXXMemberCall : public CXXInstanceCall {
+ friend class CallEventManager;
+
+protected:
+ CXXMemberCall(const CXXMemberCallExpr *CE, ProgramStateRef St,
+ const LocationContext *LCtx)
+ : CXXInstanceCall(CE, St, LCtx) {}
+
+ CXXMemberCall(const CXXMemberCall &Other) : CXXInstanceCall(Other) {}
+ void cloneTo(void *Dest) const override { new (Dest) CXXMemberCall(*this); }
+
+public:
+ virtual const CXXMemberCallExpr *getOriginExpr() const {
+ return cast<CXXMemberCallExpr>(CXXInstanceCall::getOriginExpr());
+ }
+
+ unsigned getNumArgs() const override {
+ if (const CallExpr *CE = getOriginExpr())
+ return CE->getNumArgs();
+ return 0;
+ }
+
+ const Expr *getArgExpr(unsigned Index) const override {
+ return getOriginExpr()->getArg(Index);
+ }
+
+ const Expr *getCXXThisExpr() const override;
+
+ RuntimeDefinition getRuntimeDefinition() const override;
+
+ Kind getKind() const override { return CE_CXXMember; }
+
+ static bool classof(const CallEvent *CA) {
+ return CA->getKind() == CE_CXXMember;
+ }
+};
+
+/// \brief Represents a C++ overloaded operator call where the operator is
+/// implemented as a non-static member function.
+///
+/// Example: <tt>iter + 1</tt>
+class CXXMemberOperatorCall : public CXXInstanceCall {
+ friend class CallEventManager;
+
+protected:
+ CXXMemberOperatorCall(const CXXOperatorCallExpr *CE, ProgramStateRef St,
+ const LocationContext *LCtx)
+ : CXXInstanceCall(CE, St, LCtx) {}
+
+ CXXMemberOperatorCall(const CXXMemberOperatorCall &Other)
+ : CXXInstanceCall(Other) {}
+ void cloneTo(void *Dest) const override {
+ new (Dest) CXXMemberOperatorCall(*this);
+ }
+
+public:
+ virtual const CXXOperatorCallExpr *getOriginExpr() const {
+ return cast<CXXOperatorCallExpr>(CXXInstanceCall::getOriginExpr());
+ }
+
+ unsigned getNumArgs() const override {
+ return getOriginExpr()->getNumArgs() - 1;
+ }
+ const Expr *getArgExpr(unsigned Index) const override {
+ return getOriginExpr()->getArg(Index + 1);
+ }
+
+ const Expr *getCXXThisExpr() const override;
+
+ Kind getKind() const override { return CE_CXXMemberOperator; }
+
+ static bool classof(const CallEvent *CA) {
+ return CA->getKind() == CE_CXXMemberOperator;
+ }
+};
+
+/// \brief Represents an implicit call to a C++ destructor.
+///
+/// This can occur at the end of a scope (for automatic objects), at the end
+/// of a full-expression (for temporaries), or as part of a delete.
+class CXXDestructorCall : public CXXInstanceCall {
+ friend class CallEventManager;
+
+protected:
+ typedef llvm::PointerIntPair<const MemRegion *, 1, bool> DtorDataTy;
+
+ /// Creates an implicit destructor.
+ ///
+ /// \param DD The destructor that will be called.
+ /// \param Trigger The statement whose completion causes this destructor call.
+ /// \param Target The object region to be destructed.
+ /// \param St The path-sensitive state at this point in the program.
+ /// \param LCtx The location context at this point in the program.
+ CXXDestructorCall(const CXXDestructorDecl *DD, const Stmt *Trigger,
+ const MemRegion *Target, bool IsBaseDestructor,
+ ProgramStateRef St, const LocationContext *LCtx)
+ : CXXInstanceCall(DD, St, LCtx) {
+ Data = DtorDataTy(Target, IsBaseDestructor).getOpaqueValue();
+ Location = Trigger->getLocEnd();
+ }
+
+ CXXDestructorCall(const CXXDestructorCall &Other) : CXXInstanceCall(Other) {}
+ void cloneTo(void *Dest) const override {new (Dest) CXXDestructorCall(*this);}
+
+public:
+ SourceRange getSourceRange() const override { return Location; }
+ unsigned getNumArgs() const override { return 0; }
+
+ RuntimeDefinition getRuntimeDefinition() const override;
+
+ /// \brief Returns the value of the implicit 'this' object.
+ SVal getCXXThisVal() const override;
+
+ /// Returns true if this is a call to a base class destructor.
+ bool isBaseDestructor() const {
+ return DtorDataTy::getFromOpaqueValue(Data).getInt();
+ }
+
+ Kind getKind() const override { return CE_CXXDestructor; }
+
+ static bool classof(const CallEvent *CA) {
+ return CA->getKind() == CE_CXXDestructor;
+ }
+};
+
+/// \brief Represents a call to a C++ constructor.
+///
+/// Example: \c T(1)
+class CXXConstructorCall : public AnyFunctionCall {
+ friend class CallEventManager;
+
+protected:
+ /// Creates a constructor call.
+ ///
+ /// \param CE The constructor expression as written in the source.
+ /// \param Target The region where the object should be constructed. If NULL,
+ /// a new symbolic region will be used.
+ /// \param St The path-sensitive state at this point in the program.
+ /// \param LCtx The location context at this point in the program.
+ CXXConstructorCall(const CXXConstructExpr *CE, const MemRegion *Target,
+ ProgramStateRef St, const LocationContext *LCtx)
+ : AnyFunctionCall(CE, St, LCtx) {
+ Data = Target;
+ }
+
+ CXXConstructorCall(const CXXConstructorCall &Other) : AnyFunctionCall(Other){}
+ void cloneTo(void *Dest) const override { new (Dest) CXXConstructorCall(*this); }
+
+ void getExtraInvalidatedValues(ValueList &Values,
+ RegionAndSymbolInvalidationTraits *ETraits) const override;
+
+public:
+ virtual const CXXConstructExpr *getOriginExpr() const {
+ return cast<CXXConstructExpr>(AnyFunctionCall::getOriginExpr());
+ }
+
+ const CXXConstructorDecl *getDecl() const override {
+ return getOriginExpr()->getConstructor();
+ }
+
+ unsigned getNumArgs() const override { return getOriginExpr()->getNumArgs(); }
+
+ const Expr *getArgExpr(unsigned Index) const override {
+ return getOriginExpr()->getArg(Index);
+ }
+
+ /// \brief Returns the value of the implicit 'this' object.
+ SVal getCXXThisVal() const;
+
+ void getInitialStackFrameContents(const StackFrameContext *CalleeCtx,
+ BindingsTy &Bindings) const override;
+
+ Kind getKind() const override { return CE_CXXConstructor; }
+
+ static bool classof(const CallEvent *CA) {
+ return CA->getKind() == CE_CXXConstructor;
+ }
+};
+
+/// \brief Represents the memory allocation call in a C++ new-expression.
+///
+/// This is a call to "operator new".
+class CXXAllocatorCall : public AnyFunctionCall {
+ friend class CallEventManager;
+
+protected:
+ CXXAllocatorCall(const CXXNewExpr *E, ProgramStateRef St,
+ const LocationContext *LCtx)
+ : AnyFunctionCall(E, St, LCtx) {}
+
+ CXXAllocatorCall(const CXXAllocatorCall &Other) : AnyFunctionCall(Other) {}
+ void cloneTo(void *Dest) const override { new (Dest) CXXAllocatorCall(*this); }
+
+public:
+ virtual const CXXNewExpr *getOriginExpr() const {
+ return cast<CXXNewExpr>(AnyFunctionCall::getOriginExpr());
+ }
+
+ const FunctionDecl *getDecl() const override {
+ return getOriginExpr()->getOperatorNew();
+ }
+
+ unsigned getNumArgs() const override {
+ return getOriginExpr()->getNumPlacementArgs() + 1;
+ }
+
+ const Expr *getArgExpr(unsigned Index) const override {
+ // The first argument of an allocator call is the size of the allocation.
+ if (Index == 0)
+ return nullptr;
+ return getOriginExpr()->getPlacementArg(Index - 1);
+ }
+
+ Kind getKind() const override { return CE_CXXAllocator; }
+
+ static bool classof(const CallEvent *CE) {
+ return CE->getKind() == CE_CXXAllocator;
+ }
+};
+
+/// \brief Represents the ways an Objective-C message send can occur.
+//
+// Note to maintainers: OCM_Message should always be last, since it does not
+// need to fit in the Data field's low bits.
+enum ObjCMessageKind {
+ OCM_PropertyAccess,
+ OCM_Subscript,
+ OCM_Message
+};
+
+/// \brief Represents any expression that calls an Objective-C method.
+///
+/// This includes all of the kinds listed in ObjCMessageKind.
+class ObjCMethodCall : public CallEvent {
+ friend class CallEventManager;
+
+ const PseudoObjectExpr *getContainingPseudoObjectExpr() const;
+
+protected:
+ ObjCMethodCall(const ObjCMessageExpr *Msg, ProgramStateRef St,
+ const LocationContext *LCtx)
+ : CallEvent(Msg, St, LCtx) {
+ Data = nullptr;
+ }
+
+ ObjCMethodCall(const ObjCMethodCall &Other) : CallEvent(Other) {}
+ void cloneTo(void *Dest) const override { new (Dest) ObjCMethodCall(*this); }
+
+ void getExtraInvalidatedValues(ValueList &Values,
+ RegionAndSymbolInvalidationTraits *ETraits) const override;
+
+ /// Check if the selector may have multiple definitions (may have overrides).
+ virtual bool canBeOverridenInSubclass(ObjCInterfaceDecl *IDecl,
+ Selector Sel) const;
+
+public:
+ virtual const ObjCMessageExpr *getOriginExpr() const {
+ return cast<ObjCMessageExpr>(CallEvent::getOriginExpr());
+ }
+ const ObjCMethodDecl *getDecl() const override {
+ return getOriginExpr()->getMethodDecl();
+ }
+ unsigned getNumArgs() const override {
+ return getOriginExpr()->getNumArgs();
+ }
+ const Expr *getArgExpr(unsigned Index) const override {
+ return getOriginExpr()->getArg(Index);
+ }
+
+ bool isInstanceMessage() const {
+ return getOriginExpr()->isInstanceMessage();
+ }
+ ObjCMethodFamily getMethodFamily() const {
+ return getOriginExpr()->getMethodFamily();
+ }
+ Selector getSelector() const {
+ return getOriginExpr()->getSelector();
+ }
+
+ SourceRange getSourceRange() const override;
+
+ /// \brief Returns the value of the receiver at the time of this call.
+ SVal getReceiverSVal() const;
+
+ /// \brief Return the value of 'self' if available.
+ SVal getSelfSVal() const;
+
+ /// \brief Get the interface for the receiver.
+ ///
+ /// This works whether this is an instance message or a class message.
+ /// However, it currently just uses the static type of the receiver.
+ const ObjCInterfaceDecl *getReceiverInterface() const {
+ return getOriginExpr()->getReceiverInterface();
+ }
+
+ /// \brief Checks if the receiver refers to 'self' or 'super'.
+ bool isReceiverSelfOrSuper() const;
+
+ /// Returns how the message was written in the source (property access,
+ /// subscript, or explicit message send).
+ ObjCMessageKind getMessageKind() const;
+
+ /// Returns true if this property access or subscript is a setter (has the
+ /// form of an assignment).
+ bool isSetter() const {
+ switch (getMessageKind()) {
+ case OCM_Message:
+ llvm_unreachable("This is not a pseudo-object access!");
+ case OCM_PropertyAccess:
+ return getNumArgs() > 0;
+ case OCM_Subscript:
+ return getNumArgs() > 1;
+ }
+ llvm_unreachable("Unknown message kind");
+ }
+
+ RuntimeDefinition getRuntimeDefinition() const override;
+
+ bool argumentsMayEscape() const override;
+
+ void getInitialStackFrameContents(const StackFrameContext *CalleeCtx,
+ BindingsTy &Bindings) const override;
+
+ ArrayRef<ParmVarDecl*> parameters() const override;
+
+ Kind getKind() const override { return CE_ObjCMessage; }
+
+ static bool classof(const CallEvent *CA) {
+ return CA->getKind() == CE_ObjCMessage;
+ }
+};
+
+
+/// \brief Manages the lifetime of CallEvent objects.
+///
+/// CallEventManager provides a way to create arbitrary CallEvents "on the
+/// stack" as if they were value objects by keeping a cache of CallEvent-sized
+/// memory blocks. The CallEvents created by CallEventManager are only valid
+/// for the lifetime of the OwnedCallEvent that holds them; right now these
+/// objects cannot be copied and ownership cannot be transferred.
+class CallEventManager {
+ friend class CallEvent;
+
+ llvm::BumpPtrAllocator &Alloc;
+ SmallVector<void *, 8> Cache;
+ typedef SimpleFunctionCall CallEventTemplateTy;
+
+ void reclaim(const void *Memory) {
+ Cache.push_back(const_cast<void *>(Memory));
+ }
+
+ /// Returns memory that can be initialized as a CallEvent.
+ void *allocate() {
+ if (Cache.empty())
+ return Alloc.Allocate<CallEventTemplateTy>();
+ else
+ return Cache.pop_back_val();
+ }
+
+ template <typename T, typename Arg>
+ T *create(Arg A, ProgramStateRef St, const LocationContext *LCtx) {
+ static_assert(sizeof(T) == sizeof(CallEventTemplateTy),
+ "CallEvent subclasses are not all the same size");
+ return new (allocate()) T(A, St, LCtx);
+ }
+
+ template <typename T, typename Arg1, typename Arg2>
+ T *create(Arg1 A1, Arg2 A2, ProgramStateRef St, const LocationContext *LCtx) {
+ static_assert(sizeof(T) == sizeof(CallEventTemplateTy),
+ "CallEvent subclasses are not all the same size");
+ return new (allocate()) T(A1, A2, St, LCtx);
+ }
+
+ template <typename T, typename Arg1, typename Arg2, typename Arg3>
+ T *create(Arg1 A1, Arg2 A2, Arg3 A3, ProgramStateRef St,
+ const LocationContext *LCtx) {
+ static_assert(sizeof(T) == sizeof(CallEventTemplateTy),
+ "CallEvent subclasses are not all the same size");
+ return new (allocate()) T(A1, A2, A3, St, LCtx);
+ }
+
+ template <typename T, typename Arg1, typename Arg2, typename Arg3,
+ typename Arg4>
+ T *create(Arg1 A1, Arg2 A2, Arg3 A3, Arg4 A4, ProgramStateRef St,
+ const LocationContext *LCtx) {
+ static_assert(sizeof(T) == sizeof(CallEventTemplateTy),
+ "CallEvent subclasses are not all the same size");
+ return new (allocate()) T(A1, A2, A3, A4, St, LCtx);
+ }
+
+public:
+ CallEventManager(llvm::BumpPtrAllocator &alloc) : Alloc(alloc) {}
+
+
+ CallEventRef<>
+ getCaller(const StackFrameContext *CalleeCtx, ProgramStateRef State);
+
+
+ CallEventRef<>
+ getSimpleCall(const CallExpr *E, ProgramStateRef State,
+ const LocationContext *LCtx);
+
+ CallEventRef<ObjCMethodCall>
+ getObjCMethodCall(const ObjCMessageExpr *E, ProgramStateRef State,
+ const LocationContext *LCtx) {
+ return create<ObjCMethodCall>(E, State, LCtx);
+ }
+
+ CallEventRef<CXXConstructorCall>
+ getCXXConstructorCall(const CXXConstructExpr *E, const MemRegion *Target,
+ ProgramStateRef State, const LocationContext *LCtx) {
+ return create<CXXConstructorCall>(E, Target, State, LCtx);
+ }
+
+ CallEventRef<CXXDestructorCall>
+ getCXXDestructorCall(const CXXDestructorDecl *DD, const Stmt *Trigger,
+ const MemRegion *Target, bool IsBase,
+ ProgramStateRef State, const LocationContext *LCtx) {
+ return create<CXXDestructorCall>(DD, Trigger, Target, IsBase, State, LCtx);
+ }
+
+ CallEventRef<CXXAllocatorCall>
+ getCXXAllocatorCall(const CXXNewExpr *E, ProgramStateRef State,
+ const LocationContext *LCtx) {
+ return create<CXXAllocatorCall>(E, State, LCtx);
+ }
+};
+
+
+template <typename T>
+CallEventRef<T> CallEvent::cloneWithState(ProgramStateRef NewState) const {
+ assert(isa<T>(*this) && "Cloning to unrelated type");
+ static_assert(sizeof(T) == sizeof(CallEvent),
+ "Subclasses may not add fields");
+
+ if (NewState == State)
+ return cast<T>(this);
+
+ CallEventManager &Mgr = State->getStateManager().getCallEventManager();
+ T *Copy = static_cast<T *>(Mgr.allocate());
+ cloneTo(Copy);
+ assert(Copy->getKind() == this->getKind() && "Bad copy");
+
+ Copy->State = NewState;
+ return Copy;
+}
+
+inline void CallEvent::Release() const {
+ assert(RefCount > 0 && "Reference count is already zero.");
+ --RefCount;
+
+ if (RefCount > 0)
+ return;
+
+ CallEventManager &Mgr = State->getStateManager().getCallEventManager();
+ Mgr.reclaim(this);
+
+ this->~CallEvent();
+}
+
+} // end namespace ento
+} // end namespace clang
+
+namespace llvm {
+ // Support isa<>, cast<>, and dyn_cast<> for CallEventRef.
+ template<class T> struct simplify_type< clang::ento::CallEventRef<T> > {
+ typedef const T *SimpleType;
+
+ static SimpleType
+ getSimplifiedValue(clang::ento::CallEventRef<T> Val) {
+ return Val.get();
+ }
+ };
+}
+
+#endif
diff --git a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h
new file mode 100644
index 0000000..d4f014d
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h
@@ -0,0 +1,349 @@
+//== CheckerContext.h - Context info for path-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 CheckerContext that provides contextual info for
+// path-sensitive checkers.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_CHECKERCONTEXT_H
+#define LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_CHECKERCONTEXT_H
+
+#include "clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramStateTrait.h"
+
+namespace clang {
+namespace ento {
+
+ /// Declares an immutable map of type \p NameTy, suitable for placement into
+ /// the ProgramState. This is implementing using llvm::ImmutableMap.
+ ///
+ /// \code
+ /// State = State->set<Name>(K, V);
+ /// const Value *V = State->get<Name>(K); // Returns NULL if not in the map.
+ /// State = State->remove<Name>(K);
+ /// NameTy Map = State->get<Name>();
+ /// \endcode
+ ///
+ /// The macro should not be used inside namespaces, or for traits that must
+ /// be accessible from more than one translation unit.
+ #define REGISTER_MAP_WITH_PROGRAMSTATE(Name, Key, Value) \
+ REGISTER_TRAIT_WITH_PROGRAMSTATE(Name, \
+ CLANG_ENTO_PROGRAMSTATE_MAP(Key, Value))
+
+ /// Declares an immutable set of type \p NameTy, suitable for placement into
+ /// the ProgramState. This is implementing using llvm::ImmutableSet.
+ ///
+ /// \code
+ /// State = State->add<Name>(E);
+ /// State = State->remove<Name>(E);
+ /// bool Present = State->contains<Name>(E);
+ /// NameTy Set = State->get<Name>();
+ /// \endcode
+ ///
+ /// The macro should not be used inside namespaces, or for traits that must
+ /// be accessible from more than one translation unit.
+ #define REGISTER_SET_WITH_PROGRAMSTATE(Name, Elem) \
+ REGISTER_TRAIT_WITH_PROGRAMSTATE(Name, llvm::ImmutableSet<Elem>)
+
+ /// Declares an immutable list of type \p NameTy, suitable for placement into
+ /// the ProgramState. This is implementing using llvm::ImmutableList.
+ ///
+ /// \code
+ /// State = State->add<Name>(E); // Adds to the /end/ of the list.
+ /// bool Present = State->contains<Name>(E);
+ /// NameTy List = State->get<Name>();
+ /// \endcode
+ ///
+ /// The macro should not be used inside namespaces, or for traits that must
+ /// be accessible from more than one translation unit.
+ #define REGISTER_LIST_WITH_PROGRAMSTATE(Name, Elem) \
+ REGISTER_TRAIT_WITH_PROGRAMSTATE(Name, llvm::ImmutableList<Elem>)
+
+
+class CheckerContext {
+ ExprEngine &Eng;
+ /// The current exploded(symbolic execution) graph node.
+ ExplodedNode *Pred;
+ /// The flag is true if the (state of the execution) has been modified
+ /// by the checker using this context. For example, a new transition has been
+ /// added or a bug report issued.
+ bool Changed;
+ /// The tagged location, which is used to generate all new nodes.
+ const ProgramPoint Location;
+ NodeBuilder &NB;
+
+public:
+ /// If we are post visiting a call, this flag will be set if the
+ /// call was inlined. In all other cases it will be false.
+ const bool wasInlined;
+
+ CheckerContext(NodeBuilder &builder,
+ ExprEngine &eng,
+ ExplodedNode *pred,
+ const ProgramPoint &loc,
+ bool wasInlined = false)
+ : Eng(eng),
+ Pred(pred),
+ Changed(false),
+ Location(loc),
+ NB(builder),
+ wasInlined(wasInlined) {
+ assert(Pred->getState() &&
+ "We should not call the checkers on an empty state.");
+ }
+
+ AnalysisManager &getAnalysisManager() {
+ return Eng.getAnalysisManager();
+ }
+
+ ConstraintManager &getConstraintManager() {
+ return Eng.getConstraintManager();
+ }
+
+ StoreManager &getStoreManager() {
+ return Eng.getStoreManager();
+ }
+
+ /// \brief Returns the previous node in the exploded graph, which includes
+ /// the state of the program before the checker ran. Note, checkers should
+ /// not retain the node in their state since the nodes might get invalidated.
+ ExplodedNode *getPredecessor() { return Pred; }
+ const ProgramStateRef &getState() const { return Pred->getState(); }
+
+ /// \brief Check if the checker changed the state of the execution; ex: added
+ /// a new transition or a bug report.
+ bool isDifferent() { return Changed; }
+
+ /// \brief Returns the number of times the current block has been visited
+ /// along the analyzed path.
+ unsigned blockCount() const {
+ return NB.getContext().blockCount();
+ }
+
+ ASTContext &getASTContext() {
+ return Eng.getContext();
+ }
+
+ const LangOptions &getLangOpts() const {
+ return Eng.getContext().getLangOpts();
+ }
+
+ const LocationContext *getLocationContext() const {
+ return Pred->getLocationContext();
+ }
+
+ const StackFrameContext *getStackFrame() const {
+ return Pred->getStackFrame();
+ }
+
+ /// Return true if the current LocationContext has no caller context.
+ bool inTopFrame() const { return getLocationContext()->inTopFrame(); }
+
+ BugReporter &getBugReporter() {
+ return Eng.getBugReporter();
+ }
+
+ SourceManager &getSourceManager() {
+ return getBugReporter().getSourceManager();
+ }
+
+ SValBuilder &getSValBuilder() {
+ return Eng.getSValBuilder();
+ }
+
+ SymbolManager &getSymbolManager() {
+ return getSValBuilder().getSymbolManager();
+ }
+
+ bool isObjCGCEnabled() const {
+ return Eng.isObjCGCEnabled();
+ }
+
+ ProgramStateManager &getStateManager() {
+ return Eng.getStateManager();
+ }
+
+ AnalysisDeclContext *getCurrentAnalysisDeclContext() const {
+ return Pred->getLocationContext()->getAnalysisDeclContext();
+ }
+
+ /// \brief Get the blockID.
+ unsigned getBlockID() const {
+ return NB.getContext().getBlock()->getBlockID();
+ }
+
+ /// \brief If the given node corresponds to a PostStore program point,
+ /// retrieve the location region as it was uttered in the code.
+ ///
+ /// This utility can be useful for generating extensive diagnostics, for
+ /// example, for finding variables that the given symbol was assigned to.
+ static const MemRegion *getLocationRegionIfPostStore(const ExplodedNode *N) {
+ ProgramPoint L = N->getLocation();
+ if (Optional<PostStore> PSL = L.getAs<PostStore>())
+ return reinterpret_cast<const MemRegion*>(PSL->getLocationValue());
+ return nullptr;
+ }
+
+ /// \brief Get the value of arbitrary expressions at this point in the path.
+ SVal getSVal(const Stmt *S) const {
+ return getState()->getSVal(S, getLocationContext());
+ }
+
+ /// \brief Generates a new transition in the program state graph
+ /// (ExplodedGraph). Uses the default CheckerContext predecessor node.
+ ///
+ /// @param State The state of the generated node. If not specified, the state
+ /// will not be changed, but the new node will have the checker's tag.
+ /// @param Tag The tag is used to uniquely identify the creation site. If no
+ /// tag is specified, a default tag, unique to the given checker,
+ /// will be used. Tags are used to prevent states generated at
+ /// different sites from caching out.
+ ExplodedNode *addTransition(ProgramStateRef State = nullptr,
+ const ProgramPointTag *Tag = nullptr) {
+ return addTransitionImpl(State ? State : getState(), false, nullptr, Tag);
+ }
+
+ /// \brief Generates a new transition with the given predecessor.
+ /// Allows checkers to generate a chain of nodes.
+ ///
+ /// @param State The state of the generated node.
+ /// @param Pred The transition will be generated from the specified Pred node
+ /// to the newly generated node.
+ /// @param Tag The tag to uniquely identify the creation site.
+ ExplodedNode *addTransition(ProgramStateRef State,
+ ExplodedNode *Pred,
+ const ProgramPointTag *Tag = nullptr) {
+ return addTransitionImpl(State, false, Pred, Tag);
+ }
+
+ /// \brief Generate a sink node. Generating a sink stops exploration of the
+ /// given path. To create a sink node for the purpose of reporting an error,
+ /// checkers should use generateErrorNode() instead.
+ ExplodedNode *generateSink(ProgramStateRef State, ExplodedNode *Pred,
+ const ProgramPointTag *Tag = nullptr) {
+ return addTransitionImpl(State ? State : getState(), true, Pred, Tag);
+ }
+
+ /// \brief Generate a transition to a node that will be used to report
+ /// an error. This node will be a sink. That is, it will stop exploration of
+ /// the given path.
+ ///
+ /// @param State The state of the generated node.
+ /// @param Tag The tag to uniquely identify the creation site. If null,
+ /// the default tag for the checker will be used.
+ ExplodedNode *generateErrorNode(ProgramStateRef State = nullptr,
+ const ProgramPointTag *Tag = nullptr) {
+ return generateSink(State, Pred,
+ (Tag ? Tag : Location.getTag()));
+ }
+
+ /// \brief Generate a transition to a node that will be used to report
+ /// an error. This node will not be a sink. That is, exploration will
+ /// continue along this path.
+ ///
+ /// @param State The state of the generated node.
+ /// @param Tag The tag to uniquely identify the creation site. If null,
+ /// the default tag for the checker will be used.
+ ExplodedNode *
+ generateNonFatalErrorNode(ProgramStateRef State = nullptr,
+ const ProgramPointTag *Tag = nullptr) {
+ return addTransition(State, (Tag ? Tag : Location.getTag()));
+ }
+
+ /// \brief Emit the diagnostics report.
+ void emitReport(std::unique_ptr<BugReport> R) {
+ Changed = true;
+ Eng.getBugReporter().emitReport(std::move(R));
+ }
+
+ /// \brief Get the declaration of the called function (path-sensitive).
+ const FunctionDecl *getCalleeDecl(const CallExpr *CE) const;
+
+ /// \brief Get the name of the called function (path-sensitive).
+ StringRef getCalleeName(const FunctionDecl *FunDecl) const;
+
+ /// \brief Get the identifier of the called function (path-sensitive).
+ const IdentifierInfo *getCalleeIdentifier(const CallExpr *CE) const {
+ const FunctionDecl *FunDecl = getCalleeDecl(CE);
+ if (FunDecl)
+ return FunDecl->getIdentifier();
+ else
+ return nullptr;
+ }
+
+ /// \brief Get the name of the called function (path-sensitive).
+ StringRef getCalleeName(const CallExpr *CE) const {
+ const FunctionDecl *FunDecl = getCalleeDecl(CE);
+ return getCalleeName(FunDecl);
+ }
+
+ /// \brief Returns true if the callee is an externally-visible function in the
+ /// top-level namespace, such as \c malloc.
+ ///
+ /// If a name is provided, the function must additionally match the given
+ /// name.
+ ///
+ /// Note that this deliberately excludes C++ library functions in the \c std
+ /// namespace, but will include C library functions accessed through the
+ /// \c std namespace. This also does not check if the function is declared
+ /// as 'extern "C"', or if it uses C++ name mangling.
+ static bool isCLibraryFunction(const FunctionDecl *FD,
+ StringRef Name = StringRef());
+
+ /// \brief Depending on wither the location corresponds to a macro, return
+ /// either the macro name or the token spelling.
+ ///
+ /// This could be useful when checkers' logic depends on whether a function
+ /// is called with a given macro argument. For example:
+ /// s = socket(AF_INET,..)
+ /// If AF_INET is a macro, the result should be treated as a source of taint.
+ ///
+ /// \sa clang::Lexer::getSpelling(), clang::Lexer::getImmediateMacroName().
+ StringRef getMacroNameOrSpelling(SourceLocation &Loc);
+
+private:
+ ExplodedNode *addTransitionImpl(ProgramStateRef State,
+ bool MarkAsSink,
+ ExplodedNode *P = nullptr,
+ const ProgramPointTag *Tag = nullptr) {
+ // The analyzer may stop exploring if it sees a state it has previously
+ // visited ("cache out"). The early return here is a defensive check to
+ // prevent accidental caching out by checker API clients. Unless there is a
+ // tag or the client checker has requested that the generated node be
+ // marked as a sink, we assume that a client requesting a transition to a
+ // state that is the same as the predecessor state has made a mistake. We
+ // return the predecessor rather than cache out.
+ //
+ // TODO: We could potentially change the return to an assertion to alert
+ // clients to their mistake, but several checkers (including
+ // DereferenceChecker, CallAndMessageChecker, and DynamicTypePropagation)
+ // rely upon the defensive behavior and would need to be updated.
+ if (!State || (State == Pred->getState() && !Tag && !MarkAsSink))
+ return Pred;
+
+ Changed = true;
+ const ProgramPoint &LocalLoc = (Tag ? Location.withTag(Tag) : Location);
+ if (!P)
+ P = Pred;
+
+ ExplodedNode *node;
+ if (MarkAsSink)
+ node = NB.generateSink(LocalLoc, State, P);
+ else
+ node = NB.generateNode(LocalLoc, State, P);
+ return node;
+ }
+};
+
+} // 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..8dda636
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/CheckerHelpers.h
@@ -0,0 +1,49 @@
+//== 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_STATICANALYZER_CORE_PATHSENSITIVE_CHECKERHELPERS_H
+#define LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_CHECKERHELPERS_H
+
+#include "clang/AST/Stmt.h"
+#include <tuple>
+
+namespace clang {
+
+class Expr;
+class VarDecl;
+
+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 (const Stmt *Child : S->children())
+ if (Child && containsStmt<T>(Child))
+ return true;
+
+ return false;
+}
+
+std::pair<const clang::VarDecl *, const clang::Expr *>
+parseAssignment(const Stmt *S);
+
+} // 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..9a858c2
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ConstraintManager.h
@@ -0,0 +1,188 @@
+//== 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_STATICANALYZER_CORE_PATHSENSITIVE_CONSTRAINTMANAGER_H
+#define LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_CONSTRAINTMANAGER_H
+
+#include "clang/StaticAnalyzer/Core/PathSensitive/SVals.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.h"
+#include "llvm/Support/SaveAndRestore.h"
+
+namespace llvm {
+class APSInt;
+}
+
+namespace clang {
+namespace ento {
+
+class SubEngine;
+
+class ConditionTruthVal {
+ Optional<bool> Val;
+public:
+ /// Construct a ConditionTruthVal indicating the constraint is constrained
+ /// to either true or false, depending on the boolean value provided.
+ ConditionTruthVal(bool constraint) : Val(constraint) {}
+
+ /// Construct a ConstraintVal indicating the constraint is underconstrained.
+ ConditionTruthVal() {}
+
+ /// Return true if the constraint is perfectly constrained to 'true'.
+ bool isConstrainedTrue() const {
+ return Val.hasValue() && Val.getValue();
+ }
+
+ /// Return true if the constraint is perfectly constrained to 'false'.
+ bool isConstrainedFalse() const {
+ return Val.hasValue() && !Val.getValue();
+ }
+
+ /// Return true if the constrained is perfectly constrained.
+ bool isConstrained() const {
+ return Val.hasValue();
+ }
+
+ /// Return true if the constrained is underconstrained and we do not know
+ /// if the constraint is true of value.
+ bool isUnderconstrained() const {
+ return !Val.hasValue();
+ }
+};
+
+class ConstraintManager {
+public:
+ ConstraintManager() : NotifyAssumeClients(true) {}
+
+ virtual ~ConstraintManager();
+ virtual ProgramStateRef assume(ProgramStateRef state,
+ DefinedSVal Cond,
+ bool Assumption) = 0;
+
+ typedef std::pair<ProgramStateRef, ProgramStateRef> ProgramStatePair;
+
+ /// Returns a pair of states (StTrue, StFalse) where the given condition is
+ /// assumed to be true or false, respectively.
+ ProgramStatePair assumeDual(ProgramStateRef State, DefinedSVal Cond) {
+ ProgramStateRef StTrue = assume(State, Cond, true);
+
+ // If StTrue is infeasible, asserting the falseness of Cond is unnecessary
+ // because the existing constraints already establish this.
+ if (!StTrue) {
+#ifndef __OPTIMIZE__
+ // This check is expensive and should be disabled even in Release+Asserts
+ // builds.
+ // FIXME: __OPTIMIZE__ is a GNU extension that Clang implements but MSVC
+ // does not. Is there a good equivalent there?
+ assert(assume(State, Cond, false) && "System is over constrained.");
+#endif
+ return ProgramStatePair((ProgramStateRef)nullptr, State);
+ }
+
+ ProgramStateRef StFalse = assume(State, Cond, false);
+ if (!StFalse) {
+ // We are careful to return the original state, /not/ StTrue,
+ // because we want to avoid having callers generate a new node
+ // in the ExplodedGraph.
+ return ProgramStatePair(State, (ProgramStateRef)nullptr);
+ }
+
+ return ProgramStatePair(StTrue, StFalse);
+ }
+
+ virtual ProgramStateRef assumeWithinInclusiveRange(ProgramStateRef State,
+ NonLoc Value,
+ const llvm::APSInt &From,
+ const llvm::APSInt &To,
+ bool InBound) = 0;
+
+ virtual ProgramStatePair assumeWithinInclusiveRangeDual(
+ ProgramStateRef State, NonLoc Value, const llvm::APSInt &From,
+ const llvm::APSInt &To) {
+ ProgramStateRef StInRange = assumeWithinInclusiveRange(State, Value, From,
+ To, true);
+
+ // If StTrue is infeasible, asserting the falseness of Cond is unnecessary
+ // because the existing constraints already establish this.
+ if (!StInRange)
+ return ProgramStatePair((ProgramStateRef)nullptr, State);
+
+ ProgramStateRef StOutOfRange = assumeWithinInclusiveRange(State, Value,
+ From, To, false);
+ if (!StOutOfRange) {
+ // We are careful to return the original state, /not/ StTrue,
+ // because we want to avoid having callers generate a new node
+ // in the ExplodedGraph.
+ return ProgramStatePair(State, (ProgramStateRef)nullptr);
+ }
+
+ return ProgramStatePair(StInRange, StOutOfRange);
+ }
+
+ /// \brief If a symbol is perfectly constrained to a constant, attempt
+ /// to return the concrete value.
+ ///
+ /// Note that a ConstraintManager is not obligated to return a concretized
+ /// value for a symbol, even if it is perfectly constrained.
+ virtual const llvm::APSInt* getSymVal(ProgramStateRef state,
+ SymbolRef sym) const {
+ return nullptr;
+ }
+
+ virtual ProgramStateRef removeDeadBindings(ProgramStateRef state,
+ SymbolReaper& SymReaper) = 0;
+
+ virtual void print(ProgramStateRef state,
+ raw_ostream &Out,
+ const char* nl,
+ const char *sep) = 0;
+
+ virtual void EndPath(ProgramStateRef state) {}
+
+ /// Convenience method to query the state to see if a symbol is null or
+ /// not null, or if neither assumption can be made.
+ ConditionTruthVal isNull(ProgramStateRef State, SymbolRef Sym) {
+ SaveAndRestore<bool> DisableNotify(NotifyAssumeClients, false);
+
+ return checkNull(State, Sym);
+ }
+
+protected:
+ /// A flag to indicate that clients should be notified of assumptions.
+ /// By default this is the case, but sometimes this needs to be restricted
+ /// to avoid infinite recursions within the ConstraintManager.
+ ///
+ /// Note that this flag allows the ConstraintManager to be re-entrant,
+ /// but not thread-safe.
+ bool NotifyAssumeClients;
+
+ /// 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;
+
+ /// Returns whether or not a symbol is known to be null ("true"), known to be
+ /// non-null ("false"), or may be either ("underconstrained").
+ virtual ConditionTruthVal checkNull(ProgramStateRef State, SymbolRef Sym);
+};
+
+std::unique_ptr<ConstraintManager>
+CreateRangeConstraintManager(ProgramStateManager &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..d5822e2
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/CoreEngine.h
@@ -0,0 +1,547 @@
+//==- 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_STATICANALYZER_CORE_PATHSENSITIVE_COREENGINE_H
+#define LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_COREENGINE_H
+
+#include "clang/AST/Expr.h"
+#include "clang/Analysis/AnalysisContext.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/BlockCounter.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/ExplodedGraph.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/FunctionSummary.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/WorkList.h"
+#include <memory>
+
+namespace clang {
+
+class ProgramPointTag;
+
+namespace ento {
+
+class NodeBuilder;
+
+//===----------------------------------------------------------------------===//
+/// 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 struct NodeBuilderContext;
+ friend class NodeBuilder;
+ friend class ExprEngine;
+ friend class CommonNodeBuilder;
+ friend class IndirectGotoNodeBuilder;
+ friend class SwitchNodeBuilder;
+ friend class EndOfFunctionNodeBuilder;
+public:
+ typedef std::vector<std::pair<BlockEdge, const ExplodedNode*> >
+ BlocksExhausted;
+
+ typedef std::vector<std::pair<const CFGBlock*, const ExplodedNode*> >
+ BlocksAborted;
+
+private:
+
+ SubEngine& SubEng;
+
+ /// G - The simulation graph. Each node is a (location,state) pair.
+ mutable 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.
+ std::unique_ptr<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.
+ BlocksExhausted blocksExhausted;
+
+ /// The locations where we stopped because the engine aborted analysis,
+ /// usually because it could not reason about something.
+ BlocksAborted blocksAborted;
+
+ /// The information about functions shared by the whole translation unit.
+ /// (This data is owned by AnalysisConsumer.)
+ FunctionSummariesTy *FunctionSummaries;
+
+ void generateNode(const ProgramPoint &Loc,
+ ProgramStateRef 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 HandleCleanupTemporaryBranch(const CXXBindTemporaryExpr *BTE,
+ const CFGBlock *B, ExplodedNode *Pred);
+
+ /// Handle conditional logic for running static initializers.
+ void HandleStaticInit(const DeclStmt *DS, const CFGBlock *B,
+ ExplodedNode *Pred);
+
+private:
+ CoreEngine(const CoreEngine &) = delete;
+ void operator=(const CoreEngine &) = delete;
+
+ ExplodedNode *generateCallExitBeginNode(ExplodedNode *N);
+
+public:
+ /// Construct a CoreEngine object to analyze the provided CFG.
+ CoreEngine(SubEngine &subengine, FunctionSummariesTy *FS)
+ : SubEng(subengine), WList(WorkList::makeDFS()),
+ BCounterFactory(G.getAllocator()), FunctionSummaries(FS) {}
+
+ /// getGraph - Returns the exploded graph.
+ ExplodedGraph &getGraph() { return G; }
+
+ /// 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,
+ ProgramStateRef InitState);
+ /// Returns true if there is still simulation state on the worklist.
+ bool ExecuteWorkListWithInitialState(const LocationContext *L,
+ unsigned Steps,
+ ProgramStateRef InitState,
+ ExplodedNodeSet &Dst);
+
+ /// Dispatch the work list item based on the given location information.
+ /// Use Pred parameter as the predecessor state.
+ void dispatchWorkItem(ExplodedNode* Pred, ProgramPoint Loc,
+ const WorkListUnit& WU);
+
+ // Functions for external checking of whether we have unfinished work
+ bool wasBlockAborted() const { return !blocksAborted.empty(); }
+ bool wasBlocksExhausted() const { return !blocksExhausted.empty(); }
+ bool hasWorkRemaining() const { return wasBlocksExhausted() ||
+ WList->hasWork() ||
+ wasBlockAborted(); }
+
+ /// Inform the CoreEngine that a basic block was aborted because
+ /// it could not be completely analyzed.
+ void addAbortedBlock(const ExplodedNode *node, const CFGBlock *block) {
+ blocksAborted.push_back(std::make_pair(block, node));
+ }
+
+ WorkList *getWorkList() const { return WList.get(); }
+
+ BlocksExhausted::const_iterator blocks_exhausted_begin() const {
+ return blocksExhausted.begin();
+ }
+ BlocksExhausted::const_iterator blocks_exhausted_end() const {
+ return blocksExhausted.end();
+ }
+ BlocksAborted::const_iterator blocks_aborted_begin() const {
+ return blocksAborted.begin();
+ }
+ BlocksAborted::const_iterator blocks_aborted_end() const {
+ return blocksAborted.end();
+ }
+
+ /// \brief Enqueue the given set of nodes onto the work list.
+ void enqueue(ExplodedNodeSet &Set);
+
+ /// \brief Enqueue nodes that were created as a result of processing
+ /// a statement onto the work list.
+ void enqueue(ExplodedNodeSet &Set, const CFGBlock *Block, unsigned Idx);
+
+ /// \brief enqueue the nodes corresponding to the end of function onto the
+ /// end of path / work list.
+ void enqueueEndOfFunction(ExplodedNodeSet &Set);
+
+ /// \brief Enqueue a single node created as a result of statement processing.
+ void enqueueStmtNode(ExplodedNode *N, const CFGBlock *Block, unsigned Idx);
+};
+
+// TODO: Turn into a calss.
+struct NodeBuilderContext {
+ const CoreEngine &Eng;
+ const CFGBlock *Block;
+ const LocationContext *LC;
+ NodeBuilderContext(const CoreEngine &E, const CFGBlock *B, ExplodedNode *N)
+ : Eng(E), Block(B), LC(N->getLocationContext()) { assert(B); }
+
+ /// \brief Return the CFGBlock associated with this builder.
+ const CFGBlock *getBlock() const { return Block; }
+
+ /// \brief Returns the number of times the current basic block has been
+ /// visited on the exploded graph path.
+ unsigned blockCount() const {
+ return Eng.WList->getBlockCounter().getNumVisited(
+ LC->getCurrentStackFrame(),
+ Block->getBlockID());
+ }
+};
+
+/// \class NodeBuilder
+/// \brief This is the simplest builder which generates nodes in the
+/// ExplodedGraph.
+///
+/// The main benefit of the builder is that it automatically tracks the
+/// frontier nodes (or destination set). This is the set of nodes which should
+/// be propagated to the next step / builder. They are the nodes which have been
+/// added to the builder (either as the input node set or as the newly
+/// constructed nodes) but did not have any outgoing transitions added.
+class NodeBuilder {
+ virtual void anchor();
+protected:
+ const NodeBuilderContext &C;
+
+ /// Specifies if the builder results have been finalized. For example, if it
+ /// is set to false, autotransitions are yet to be generated.
+ bool Finalized;
+ bool HasGeneratedNodes;
+ /// \brief The frontier set - a set of nodes which need to be propagated after
+ /// the builder dies.
+ ExplodedNodeSet &Frontier;
+
+ /// Checkes if the results are ready.
+ virtual bool checkResults() {
+ if (!Finalized)
+ return false;
+ return true;
+ }
+
+ bool hasNoSinksInFrontier() {
+ for (iterator I = Frontier.begin(), E = Frontier.end(); I != E; ++I) {
+ if ((*I)->isSink())
+ return false;
+ }
+ return true;
+ }
+
+ /// Allow subclasses to finalize results before result_begin() is executed.
+ virtual void finalizeResults() {}
+
+ ExplodedNode *generateNodeImpl(const ProgramPoint &PP,
+ ProgramStateRef State,
+ ExplodedNode *Pred,
+ bool MarkAsSink = false);
+
+public:
+ NodeBuilder(ExplodedNode *SrcNode, ExplodedNodeSet &DstSet,
+ const NodeBuilderContext &Ctx, bool F = true)
+ : C(Ctx), Finalized(F), HasGeneratedNodes(false), Frontier(DstSet) {
+ Frontier.Add(SrcNode);
+ }
+
+ NodeBuilder(const ExplodedNodeSet &SrcSet, ExplodedNodeSet &DstSet,
+ const NodeBuilderContext &Ctx, bool F = true)
+ : C(Ctx), Finalized(F), HasGeneratedNodes(false), Frontier(DstSet) {
+ Frontier.insert(SrcSet);
+ assert(hasNoSinksInFrontier());
+ }
+
+ virtual ~NodeBuilder() {}
+
+ /// \brief Generates a node in the ExplodedGraph.
+ ExplodedNode *generateNode(const ProgramPoint &PP,
+ ProgramStateRef State,
+ ExplodedNode *Pred) {
+ return generateNodeImpl(PP, State, Pred, false);
+ }
+
+ /// \brief Generates a sink in the ExplodedGraph.
+ ///
+ /// When a node is marked as sink, the exploration from the node is stopped -
+ /// the node becomes the last node on the path and certain kinds of bugs are
+ /// suppressed.
+ ExplodedNode *generateSink(const ProgramPoint &PP,
+ ProgramStateRef State,
+ ExplodedNode *Pred) {
+ return generateNodeImpl(PP, State, Pred, true);
+ }
+
+ const ExplodedNodeSet &getResults() {
+ finalizeResults();
+ assert(checkResults());
+ return Frontier;
+ }
+
+ typedef ExplodedNodeSet::iterator iterator;
+ /// \brief Iterators through the results frontier.
+ inline iterator begin() {
+ finalizeResults();
+ assert(checkResults());
+ return Frontier.begin();
+ }
+ inline iterator end() {
+ finalizeResults();
+ return Frontier.end();
+ }
+
+ const NodeBuilderContext &getContext() { return C; }
+ bool hasGeneratedNodes() { return HasGeneratedNodes; }
+
+ void takeNodes(const ExplodedNodeSet &S) {
+ for (ExplodedNodeSet::iterator I = S.begin(), E = S.end(); I != E; ++I )
+ Frontier.erase(*I);
+ }
+ void takeNodes(ExplodedNode *N) { Frontier.erase(N); }
+ void addNodes(const ExplodedNodeSet &S) { Frontier.insert(S); }
+ void addNodes(ExplodedNode *N) { Frontier.Add(N); }
+};
+
+/// \class NodeBuilderWithSinks
+/// \brief This node builder keeps track of the generated sink nodes.
+class NodeBuilderWithSinks: public NodeBuilder {
+ void anchor() override;
+protected:
+ SmallVector<ExplodedNode*, 2> sinksGenerated;
+ ProgramPoint &Location;
+
+public:
+ NodeBuilderWithSinks(ExplodedNode *Pred, ExplodedNodeSet &DstSet,
+ const NodeBuilderContext &Ctx, ProgramPoint &L)
+ : NodeBuilder(Pred, DstSet, Ctx), Location(L) {}
+
+ ExplodedNode *generateNode(ProgramStateRef State,
+ ExplodedNode *Pred,
+ const ProgramPointTag *Tag = nullptr) {
+ const ProgramPoint &LocalLoc = (Tag ? Location.withTag(Tag) : Location);
+ return NodeBuilder::generateNode(LocalLoc, State, Pred);
+ }
+
+ ExplodedNode *generateSink(ProgramStateRef State, ExplodedNode *Pred,
+ const ProgramPointTag *Tag = nullptr) {
+ const ProgramPoint &LocalLoc = (Tag ? Location.withTag(Tag) : Location);
+ ExplodedNode *N = NodeBuilder::generateSink(LocalLoc, State, Pred);
+ if (N && N->isSink())
+ sinksGenerated.push_back(N);
+ return N;
+ }
+
+ const SmallVectorImpl<ExplodedNode*> &getSinks() const {
+ return sinksGenerated;
+ }
+};
+
+/// \class StmtNodeBuilder
+/// \brief This builder class is useful for generating nodes that resulted from
+/// visiting a statement. The main difference from its parent NodeBuilder is
+/// that it creates a statement specific ProgramPoint.
+class StmtNodeBuilder: public NodeBuilder {
+ NodeBuilder *EnclosingBldr;
+public:
+
+ /// \brief Constructs a StmtNodeBuilder. If the builder is going to process
+ /// nodes currently owned by another builder(with larger scope), use
+ /// Enclosing builder to transfer ownership.
+ StmtNodeBuilder(ExplodedNode *SrcNode, ExplodedNodeSet &DstSet,
+ const NodeBuilderContext &Ctx,
+ NodeBuilder *Enclosing = nullptr)
+ : NodeBuilder(SrcNode, DstSet, Ctx), EnclosingBldr(Enclosing) {
+ if (EnclosingBldr)
+ EnclosingBldr->takeNodes(SrcNode);
+ }
+
+ StmtNodeBuilder(ExplodedNodeSet &SrcSet, ExplodedNodeSet &DstSet,
+ const NodeBuilderContext &Ctx,
+ NodeBuilder *Enclosing = nullptr)
+ : NodeBuilder(SrcSet, DstSet, Ctx), EnclosingBldr(Enclosing) {
+ if (EnclosingBldr)
+ for (ExplodedNodeSet::iterator I = SrcSet.begin(),
+ E = SrcSet.end(); I != E; ++I )
+ EnclosingBldr->takeNodes(*I);
+ }
+
+ ~StmtNodeBuilder() override;
+
+ using NodeBuilder::generateNode;
+ using NodeBuilder::generateSink;
+
+ ExplodedNode *generateNode(const Stmt *S,
+ ExplodedNode *Pred,
+ ProgramStateRef St,
+ const ProgramPointTag *tag = nullptr,
+ ProgramPoint::Kind K = ProgramPoint::PostStmtKind){
+ const ProgramPoint &L = ProgramPoint::getProgramPoint(S, K,
+ Pred->getLocationContext(), tag);
+ return NodeBuilder::generateNode(L, St, Pred);
+ }
+
+ ExplodedNode *generateSink(const Stmt *S,
+ ExplodedNode *Pred,
+ ProgramStateRef St,
+ const ProgramPointTag *tag = nullptr,
+ ProgramPoint::Kind K = ProgramPoint::PostStmtKind){
+ const ProgramPoint &L = ProgramPoint::getProgramPoint(S, K,
+ Pred->getLocationContext(), tag);
+ return NodeBuilder::generateSink(L, St, Pred);
+ }
+};
+
+/// \brief BranchNodeBuilder is responsible for constructing the nodes
+/// corresponding to the two branches of the if statement - true and false.
+class BranchNodeBuilder: public NodeBuilder {
+ void anchor() override;
+ const CFGBlock *DstT;
+ const CFGBlock *DstF;
+
+ bool InFeasibleTrue;
+ bool InFeasibleFalse;
+
+public:
+ BranchNodeBuilder(ExplodedNode *SrcNode, ExplodedNodeSet &DstSet,
+ const NodeBuilderContext &C,
+ const CFGBlock *dstT, const CFGBlock *dstF)
+ : NodeBuilder(SrcNode, DstSet, C), DstT(dstT), DstF(dstF),
+ InFeasibleTrue(!DstT), InFeasibleFalse(!DstF) {
+ // The branch node builder does not generate autotransitions.
+ // If there are no successors it means that both branches are infeasible.
+ takeNodes(SrcNode);
+ }
+
+ BranchNodeBuilder(const ExplodedNodeSet &SrcSet, ExplodedNodeSet &DstSet,
+ const NodeBuilderContext &C,
+ const CFGBlock *dstT, const CFGBlock *dstF)
+ : NodeBuilder(SrcSet, DstSet, C), DstT(dstT), DstF(dstF),
+ InFeasibleTrue(!DstT), InFeasibleFalse(!DstF) {
+ takeNodes(SrcSet);
+ }
+
+ ExplodedNode *generateNode(ProgramStateRef State, bool branch,
+ ExplodedNode *Pred);
+
+ const CFGBlock *getTargetBlock(bool branch) const {
+ return branch ? DstT : DstF;
+ }
+
+ void markInfeasible(bool branch) {
+ if (branch)
+ InFeasibleTrue = true;
+ else
+ InFeasibleFalse = true;
+ }
+
+ bool isFeasible(bool branch) {
+ return branch ? !InFeasibleTrue : !InFeasibleFalse;
+ }
+};
+
+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 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,
+ ProgramStateRef State,
+ bool isSink = false);
+
+ const Expr *getTarget() const { return E; }
+
+ ProgramStateRef getState() const { return Pred->State; }
+
+ const LocationContext *getLocationContext() const {
+ return Pred->getLocationContext();
+ }
+};
+
+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 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 cast<SwitchStmt>(Src->getTerminator());
+ }
+
+ ExplodedNode *generateCaseStmtNode(const iterator &I,
+ ProgramStateRef State);
+
+ ExplodedNode *generateDefaultCaseNode(ProgramStateRef State,
+ bool isSink = false);
+
+ const Expr *getCondition() const { return Condition; }
+
+ ProgramStateRef getState() const { return Pred->State; }
+
+ const LocationContext *getLocationContext() const {
+ return Pred->getLocationContext();
+ }
+};
+
+} // end ento namespace
+} // end clang namespace
+
+#endif
diff --git a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/DynamicTypeInfo.h b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/DynamicTypeInfo.h
new file mode 100644
index 0000000..e13c641
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/DynamicTypeInfo.h
@@ -0,0 +1,52 @@
+//== DynamicTypeInfo.h - Runtime 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 LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_DYNAMICTYPEINFO_H
+#define LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_DYNAMICTYPEINFO_H
+
+#include "clang/AST/Type.h"
+
+namespace clang {
+namespace ento {
+
+/// \brief Stores the currently inferred strictest bound on the runtime type
+/// of a region in a given state along the analysis path.
+class DynamicTypeInfo {
+private:
+ QualType T;
+ bool CanBeASubClass;
+
+public:
+
+ DynamicTypeInfo() : T(QualType()) {}
+ DynamicTypeInfo(QualType WithType, bool CanBeSub = true)
+ : T(WithType), CanBeASubClass(CanBeSub) {}
+
+ /// \brief Return false if no dynamic type info is available.
+ bool isValid() const { return !T.isNull(); }
+
+ /// \brief Returns the currently inferred upper bound on the runtime type.
+ QualType getType() const { return T; }
+
+ /// \brief Returns false if the type information is precise (the type T is
+ /// the only type in the lattice), true otherwise.
+ bool canBeASubClass() const { return CanBeASubClass; }
+
+ void Profile(llvm::FoldingSetNodeID &ID) const {
+ ID.Add(T);
+ ID.AddInteger((unsigned)CanBeASubClass);
+ }
+ bool operator==(const DynamicTypeInfo &X) const {
+ return T == X.T && CanBeASubClass == X.CanBeASubClass;
+ }
+};
+
+} // end ento
+} // end clang
+
+#endif
diff --git a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/DynamicTypeMap.h b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/DynamicTypeMap.h
new file mode 100644
index 0000000..555191d
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/DynamicTypeMap.h
@@ -0,0 +1,57 @@
+//== DynamicTypeMap.h - Dynamic type map ----------------------- -*- 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 APIs for tracking dynamic type information.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_DYNAMICTYPEMAP_H
+#define LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_DYNAMICTYPEMAP_H
+#include "clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramStateTrait.h"
+#include "llvm/ADT/ImmutableMap.h"
+
+namespace clang {
+namespace ento {
+
+/// The GDM component containing the dynamic type info. This is a map from a
+/// symbol to its most likely type.
+struct DynamicTypeMap {};
+typedef llvm::ImmutableMap<const MemRegion *, DynamicTypeInfo>
+ DynamicTypeMapImpl;
+template <>
+struct ProgramStateTrait<DynamicTypeMap>
+ : public ProgramStatePartialTrait<DynamicTypeMapImpl> {
+ static void *GDMIndex() {
+ static int index = 0;
+ return &index;
+ }
+};
+
+/// \brief Get dynamic type information for a region.
+DynamicTypeInfo getDynamicTypeInfo(ProgramStateRef State,
+ const MemRegion *Reg);
+
+/// \brief Set dynamic type information of the region; return the new state.
+ProgramStateRef setDynamicTypeInfo(ProgramStateRef State, const MemRegion *Reg,
+ DynamicTypeInfo NewTy);
+
+/// \brief Set dynamic type information of the region; return the new state.
+inline ProgramStateRef setDynamicTypeInfo(ProgramStateRef State,
+ const MemRegion *Reg, QualType NewTy,
+ bool CanBeSubClassed = true) {
+ return setDynamicTypeInfo(State, Reg,
+ DynamicTypeInfo(NewTy, CanBeSubClassed));
+}
+
+} // ento
+} // clang
+
+#endif // LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_DYNAMICTYPEMAP_H
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..cc3779d
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/Environment.h
@@ -0,0 +1,127 @@
+//== 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_STATICANALYZER_CORE_PATHSENSITIVE_ENVIRONMENT_H
+#define LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_ENVIRONMENT_H
+
+#include "clang/Analysis/AnalysisContext.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/SVals.h"
+#include "llvm/ADT/ImmutableMap.h"
+
+namespace clang {
+
+class LiveVariables;
+
+namespace ento {
+
+class EnvironmentManager;
+class SValBuilder;
+
+/// An entry in the environment consists of a Stmt and an LocationContext.
+/// This allows the environment to manage context-sensitive bindings,
+/// which is essentially for modeling recursive function analysis, among
+/// other things.
+class EnvironmentEntry : public std::pair<const Stmt*,
+ const StackFrameContext *> {
+public:
+ EnvironmentEntry(const Stmt *s, const LocationContext *L);
+
+ const Stmt *getStmt() const { return first; }
+ const LocationContext *getLocationContext() const { return second; }
+
+ /// Profile an EnvironmentEntry for inclusion in a FoldingSet.
+ static void Profile(llvm::FoldingSetNodeID &ID,
+ const EnvironmentEntry &E) {
+ ID.AddPointer(E.getStmt());
+ ID.AddPointer(E.getLocationContext());
+ }
+
+ void Profile(llvm::FoldingSetNodeID &ID) const {
+ Profile(ID, *this);
+ }
+};
+
+/// An immutable map from EnvironemntEntries to SVals.
+class Environment {
+private:
+ friend class EnvironmentManager;
+
+ // Type definitions.
+ typedef llvm::ImmutableMap<EnvironmentEntry, SVal> BindingsTy;
+
+ // Data.
+ BindingsTy ExprBindings;
+
+ Environment(BindingsTy eb)
+ : ExprBindings(eb) {}
+
+ SVal lookupExpr(const EnvironmentEntry &E) const;
+
+public:
+ typedef BindingsTy::iterator iterator;
+ iterator begin() const { return ExprBindings.begin(); }
+ iterator end() const { return ExprBindings.end(); }
+
+ /// Fetches the current binding of the expression in the
+ /// Environment.
+ SVal getSVal(const EnvironmentEntry &E, 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;
+ }
+
+ void print(raw_ostream &Out, const char *NL, const char *Sep) const;
+
+private:
+ void printAux(raw_ostream &Out, bool printLocations,
+ const char *NL, const char *Sep) const;
+};
+
+class EnvironmentManager {
+private:
+ typedef Environment::BindingsTy::Factory FactoryTy;
+ FactoryTy F;
+
+public:
+ EnvironmentManager(llvm::BumpPtrAllocator& Allocator) : F(Allocator) {}
+
+ Environment getInitialEnvironment() {
+ return Environment(F.getEmptyMap());
+ }
+
+ /// Bind a symbolic value to the given environment entry.
+ Environment bindExpr(Environment Env, const EnvironmentEntry &E, SVal V,
+ bool Invalidate);
+
+ Environment removeDeadBindings(Environment Env,
+ SymbolReaper &SymReaper,
+ ProgramStateRef state);
+};
+
+} // 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..cfb1b92
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ExplodedGraph.h
@@ -0,0 +1,497 @@
+//=-- 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_STATICANALYZER_CORE_PATHSENSITIVE_EXPLODEDGRAPH_H
+#define LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_EXPLODEDGRAPH_H
+
+#include "clang/AST/Decl.h"
+#include "clang/Analysis/AnalysisContext.h"
+#include "clang/Analysis/ProgramPoint.h"
+#include "clang/Analysis/Support/BumpVector.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h"
+#include "llvm/ADT/DepthFirstIterator.h"
+#include "llvm/ADT/FoldingSet.h"
+#include "llvm/ADT/GraphTraits.h"
+#include "llvm/ADT/SmallPtrSet.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/Support/Allocator.h"
+#include "llvm/Support/Casting.h"
+#include <memory>
+#include <vector>
+
+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 NodeBuilder;
+ friend class BranchNodeBuilder;
+ friend class IndirectGotoNodeBuilder;
+ friend class SwitchNodeBuilder;
+ friend class EndOfFunctionNodeBuilder;
+
+ /// Efficiently stores a list of ExplodedNodes, or an optional flag.
+ ///
+ /// NodeGroup provides opaque storage for a list of ExplodedNodes, optimizing
+ /// for the case when there is only one node in the group. This is a fairly
+ /// common case in an ExplodedGraph, where most nodes have only one
+ /// predecessor and many have only one successor. It can also be used to
+ /// store a flag rather than a node list, which ExplodedNode uses to mark
+ /// whether a node is a sink. If the flag is set, the group is implicitly
+ /// empty and no nodes may be added.
+ class NodeGroup {
+ // Conceptually a discriminated union. If the low bit is set, the node is
+ // a sink. If the low bit is not set, the pointer refers to the storage
+ // for the nodes in the group.
+ // This is not a PointerIntPair in order to keep the storage type opaque.
+ uintptr_t P;
+
+ public:
+ NodeGroup(bool Flag = false) : P(Flag) {
+ assert(getFlag() == Flag);
+ }
+
+ ExplodedNode * const *begin() const;
+
+ ExplodedNode * const *end() const;
+
+ unsigned size() const;
+
+ bool empty() const { return P == 0 || getFlag() != 0; }
+
+ /// Adds a node to the list.
+ ///
+ /// The group must not have been created with its flag set.
+ void addNode(ExplodedNode *N, ExplodedGraph &G);
+
+ /// Replaces the single node in this group with a new node.
+ ///
+ /// Note that this should only be used when you know the group was not
+ /// created with its flag set, and that the group is empty or contains
+ /// only a single node.
+ void replaceNode(ExplodedNode *node);
+
+ /// Returns whether this group was created with its flag set.
+ bool getFlag() const {
+ return (P & 1);
+ }
+ };
+
+ /// Location - The program location (within a function body) associated
+ /// with this node.
+ const ProgramPoint Location;
+
+ /// State - The state associated with this node.
+ ProgramStateRef State;
+
+ /// Preds - The predecessors of this node.
+ NodeGroup Preds;
+
+ /// Succs - The successors of this node.
+ NodeGroup Succs;
+
+public:
+
+ explicit ExplodedNode(const ProgramPoint &loc, ProgramStateRef state,
+ bool IsSink)
+ : Location(loc), State(state), Succs(IsSink) {
+ assert(isSink() == IsSink);
+ }
+
+ /// getLocation - Returns the edge associated with the given node.
+ ProgramPoint getLocation() const { return Location; }
+
+ const LocationContext *getLocationContext() const {
+ return getLocation().getLocationContext();
+ }
+
+ const StackFrameContext *getStackFrame() const {
+ return getLocationContext()->getCurrentStackFrame();
+ }
+
+ const Decl &getCodeDecl() const { return *getLocationContext()->getDecl(); }
+
+ CFG &getCFG() const { return *getLocationContext()->getCFG(); }
+
+ ParentMap &getParentMap() const {return getLocationContext()->getParentMap();}
+
+ template <typename T>
+ T &getAnalysis() const {
+ return *getLocationContext()->getAnalysis<T>();
+ }
+
+ const ProgramStateRef &getState() const { return State; }
+
+ template <typename T>
+ Optional<T> getLocationAs() const LLVM_LVALUE_FUNCTION {
+ return Location.getAs<T>();
+ }
+
+ static void Profile(llvm::FoldingSetNodeID &ID,
+ const ProgramPoint &Loc,
+ const ProgramStateRef &state,
+ bool IsSink) {
+ ID.Add(Loc);
+ ID.AddPointer(state.get());
+ ID.AddBoolean(IsSink);
+ }
+
+ void Profile(llvm::FoldingSetNodeID& ID) const {
+ // We avoid copy constructors by not using accessors.
+ Profile(ID, Location, State, isSink());
+ }
+
+ /// 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(); }
+
+ bool hasSinglePred() const {
+ return (pred_size() == 1);
+ }
+
+ ExplodedNode *getFirstPred() {
+ return pred_empty() ? nullptr : *(pred_begin());
+ }
+
+ const ExplodedNode *getFirstPred() const {
+ return const_cast<ExplodedNode*>(this)->getFirstPred();
+ }
+
+ const ExplodedNode *getFirstSucc() const {
+ return succ_empty() ? nullptr : *(succ_begin());
+ }
+
+ // Iterators over successor and predecessor vertices.
+ typedef ExplodedNode* const * succ_iterator;
+ typedef const ExplodedNode* const * const_succ_iterator;
+ typedef ExplodedNode* const * 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); }
+};
+
+typedef llvm::DenseMap<const ExplodedNode *, const ExplodedNode *>
+ InterExplodedGraphMap;
+
+class ExplodedGraph {
+protected:
+ friend class CoreEngine;
+
+ // Type definitions.
+ typedef std::vector<ExplodedNode *> NodeVector;
+
+ /// 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.
+ NodeVector Roots;
+
+ /// The nodes in the simulation graph which have been
+ /// specially marked as the endpoint of an abstract simulation path.
+ NodeVector 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.
+ NodeVector ChangedNodes;
+
+ /// A list of nodes that can be reused.
+ NodeVector FreeNodes;
+
+ /// Determines how often nodes are reclaimed.
+ ///
+ /// If this is 0, nodes will never be reclaimed.
+ unsigned ReclaimNodeInterval;
+
+ /// Counter to determine when to reclaim nodes.
+ unsigned ReclaimCounter;
+
+public:
+
+ /// \brief 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, ProgramStateRef State,
+ bool IsSink = false,
+ bool* IsNew = nullptr);
+
+ std::unique_ptr<ExplodedGraph> MakeEmptyGraph() const {
+ return llvm::make_unique<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();
+
+ ~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 NodeVector::iterator roots_iterator;
+ typedef NodeVector::const_iterator const_roots_iterator;
+ typedef NodeVector::iterator eop_iterator;
+ typedef NodeVector::const_iterator 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;
+
+ /// Creates a trimmed version of the graph that only contains paths leading
+ /// to the given nodes.
+ ///
+ /// \param Nodes The nodes which must appear in the final graph. Presumably
+ /// these are end-of-path nodes (i.e. they have no successors).
+ /// \param[out] ForwardMap A optional map from nodes in this graph to nodes in
+ /// the returned graph.
+ /// \param[out] InverseMap An optional map from nodes in the returned graph to
+ /// nodes in this graph.
+ /// \returns The trimmed graph
+ std::unique_ptr<ExplodedGraph>
+ trim(ArrayRef<const NodeTy *> Nodes,
+ InterExplodedGraphMap *ForwardMap = nullptr,
+ InterExplodedGraphMap *InverseMap = nullptr) const;
+
+ /// Enable tracking of recently allocated nodes for potential reclamation
+ /// when calling reclaimRecentlyAllocatedNodes().
+ void enableNodeReclamation(unsigned Interval) {
+ ReclaimCounter = ReclaimNodeInterval = Interval;
+ }
+
+ /// Reclaim "uninteresting" nodes created since the last time this method
+ /// was called.
+ void reclaimRecentlyAllocatedNodes();
+
+ /// \brief Returns true if nodes for the given expression kind are always
+ /// kept around.
+ static bool isInterestingLValueExpr(const Expr *Ex);
+
+private:
+ bool shouldCollect(const ExplodedNode *node);
+ void collectNode(ExplodedNode *node);
+};
+
+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);
+ }
+
+ typedef ImplTy::iterator iterator;
+ typedef ImplTy::const_iterator const_iterator;
+
+ unsigned size() const { return Impl.size(); }
+ bool empty() const { return Impl.empty(); }
+ bool erase(ExplodedNode *N) { return Impl.erase(N); }
+
+ void clear() { Impl.clear(); }
+ void insert(const ExplodedNodeSet &S) {
+ assert(&S != this);
+ 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..99083c9
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h
@@ -0,0 +1,646 @@
+//===-- 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_STATICANALYZER_CORE_PATHSENSITIVE_EXPRENGINE_H
+#define LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_EXPRENGINE_H
+
+#include "clang/AST/Expr.h"
+#include "clang/AST/Type.h"
+#include "clang/Analysis/DomainSpecific/ObjCNoReturn.h"
+#include "clang/StaticAnalyzer/Core/BugReporter/BugReporter.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/CoreEngine.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramStateTrait.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/SubEngine.h"
+
+namespace clang {
+
+class AnalysisDeclContextManager;
+class CXXCatchStmt;
+class CXXConstructExpr;
+class CXXDeleteExpr;
+class CXXNewExpr;
+class CXXTemporaryObjectExpr;
+class CXXThisExpr;
+class MaterializeTemporaryExpr;
+class ObjCAtSynchronizedStmt;
+class ObjCForCollectionStmt;
+
+namespace ento {
+
+class AnalysisManager;
+class CallEvent;
+class CXXConstructorCall;
+
+class ExprEngine : public SubEngine {
+public:
+ /// The modes of inlining, which override the default analysis-wide settings.
+ enum InliningModes {
+ /// Follow the default settings for inlining callees.
+ Inline_Regular = 0,
+ /// Do minimal inlining of callees.
+ Inline_Minimal = 0x1
+ };
+
+private:
+ AnalysisManager &AMgr;
+
+ AnalysisDeclContextManager &AnalysisDeclContexts;
+
+ CoreEngine Engine;
+
+ /// G - the simulation graph.
+ ExplodedGraph& G;
+
+ /// StateMgr - Object that manages the data for all created states.
+ ProgramStateManager StateMgr;
+
+ /// SymMgr - Object that manages the symbol information.
+ SymbolManager& SymMgr;
+
+ /// svalBuilder - SValBuilder object that creates SVals from expressions.
+ SValBuilder &svalBuilder;
+
+ unsigned int currStmtIdx;
+ const NodeBuilderContext *currBldrCtx;
+
+ /// Helper object to determine if an Objective-C message expression
+ /// implicitly never returns.
+ ObjCNoReturn ObjCNoRet;
+
+ /// Whether or not GC is enabled in this analysis.
+ bool ObjCGCEnabled;
+
+ /// 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;
+
+ /// The functions which have been analyzed through inlining. This is owned by
+ /// AnalysisConsumer. It can be null.
+ SetOfConstDecls *VisitedCallees;
+
+ /// The flag, which specifies the mode of inlining for the engine.
+ InliningModes HowToInline;
+
+public:
+ ExprEngine(AnalysisManager &mgr, bool gcEnabled,
+ SetOfConstDecls *VisitedCalleesIn,
+ FunctionSummariesTy *FS,
+ InliningModes HowToInlineIn);
+
+ ~ExprEngine() override;
+
+ /// Returns true if there is still simulation state on the worklist.
+ bool ExecuteWorkList(const LocationContext *L, unsigned Steps = 150000) {
+ return Engine.ExecuteWorkList(L, Steps, nullptr);
+ }
+
+ /// 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. Returns true if there is still simulation
+ /// state on the worklist.
+ bool ExecuteWorkListWithInitialState(const LocationContext *L, unsigned Steps,
+ ProgramStateRef InitState,
+ ExplodedNodeSet &Dst) {
+ return Engine.ExecuteWorkListWithInitialState(L, Steps, InitState, Dst);
+ }
+
+ /// getContext - Return the ASTContext associated with this analysis.
+ ASTContext &getContext() const { return AMgr.getASTContext(); }
+
+ AnalysisManager &getAnalysisManager() override { return AMgr; }
+
+ CheckerManager &getCheckerManager() const {
+ return *AMgr.getCheckerManager();
+ }
+
+ SValBuilder &getSValBuilder() { return svalBuilder; }
+
+ BugReporter& getBugReporter() { return BR; }
+
+ const NodeBuilderContext &getBuilderContext() {
+ assert(currBldrCtx);
+ return *currBldrCtx;
+ }
+
+ bool isObjCGCEnabled() { return ObjCGCEnabled; }
+
+ const Stmt *getStmt() const;
+
+ void GenerateAutoTransition(ExplodedNode *N);
+ void enqueueEndOfPath(ExplodedNodeSet &S);
+ void GenerateCallExitNode(ExplodedNode *N);
+
+ /// Visualize the ExplodedGraph created by executing the simulation.
+ void ViewGraph(bool trim = false);
+
+ /// Visualize a trimmed ExplodedGraph that only contains paths to the given
+ /// nodes.
+ void ViewGraph(ArrayRef<const ExplodedNode*> Nodes);
+
+ /// getInitialState - Return the initial state used for the root vertex
+ /// in the ExplodedGraph.
+ ProgramStateRef getInitialState(const LocationContext *InitLoc) override;
+
+ ExplodedGraph& getGraph() { return G; }
+ const ExplodedGraph& getGraph() const { return G; }
+
+ /// \brief Run the analyzer's garbage collection - remove dead symbols and
+ /// bindings from the state.
+ ///
+ /// Checkers can participate in this process with two callbacks:
+ /// \c checkLiveSymbols and \c checkDeadSymbols. See the CheckerDocumentation
+ /// class for more information.
+ ///
+ /// \param Node The predecessor node, from which the processing should start.
+ /// \param Out The returned set of output nodes.
+ /// \param ReferenceStmt The statement which is about to be processed.
+ /// Everything needed for this statement should be considered live.
+ /// A null statement means that everything in child LocationContexts
+ /// is dead.
+ /// \param LC The location context of the \p ReferenceStmt. A null location
+ /// context means that we have reached the end of analysis and that
+ /// all statements and local variables should be considered dead.
+ /// \param DiagnosticStmt Used as a location for any warnings that should
+ /// occur while removing the dead (e.g. leaks). By default, the
+ /// \p ReferenceStmt is used.
+ /// \param K Denotes whether this is a pre- or post-statement purge. This
+ /// must only be ProgramPoint::PostStmtPurgeDeadSymbolsKind if an
+ /// entire location context is being cleared, in which case the
+ /// \p ReferenceStmt must either be a ReturnStmt or \c NULL. Otherwise,
+ /// it must be ProgramPoint::PreStmtPurgeDeadSymbolsKind (the default)
+ /// and \p ReferenceStmt must be valid (non-null).
+ void removeDead(ExplodedNode *Node, ExplodedNodeSet &Out,
+ const Stmt *ReferenceStmt, const LocationContext *LC,
+ const Stmt *DiagnosticStmt = nullptr,
+ ProgramPoint::Kind K = ProgramPoint::PreStmtPurgeDeadSymbolsKind);
+
+ /// processCFGElement - Called by CoreEngine. Used to generate new successor
+ /// nodes by processing the 'effects' of a CFG element.
+ void processCFGElement(const CFGElement E, ExplodedNode *Pred,
+ unsigned StmtIdx, NodeBuilderContext *Ctx) override;
+
+ void ProcessStmt(const CFGStmt S, ExplodedNode *Pred);
+
+ void ProcessInitializer(const CFGInitializer I, ExplodedNode *Pred);
+
+ void ProcessImplicitDtor(const CFGImplicitDtor D, ExplodedNode *Pred);
+
+ void ProcessNewAllocator(const CXXNewExpr *NE, ExplodedNode *Pred);
+
+ void ProcessAutomaticObjDtor(const CFGAutomaticObjDtor D,
+ ExplodedNode *Pred, ExplodedNodeSet &Dst);
+ void ProcessDeleteDtor(const CFGDeleteDtor D,
+ ExplodedNode *Pred, ExplodedNodeSet &Dst);
+ void ProcessBaseDtor(const CFGBaseDtor D,
+ ExplodedNode *Pred, ExplodedNodeSet &Dst);
+ void ProcessMemberDtor(const CFGMemberDtor D,
+ ExplodedNode *Pred, ExplodedNodeSet &Dst);
+ void ProcessTemporaryDtor(const CFGTemporaryDtor D,
+ ExplodedNode *Pred, ExplodedNodeSet &Dst);
+
+ /// Called by CoreEngine when processing the entrance of a CFGBlock.
+ void processCFGBlockEntrance(const BlockEdge &L,
+ NodeBuilderWithSinks &nodeBuilder,
+ ExplodedNode *Pred) override;
+
+ /// 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,
+ NodeBuilderContext& BuilderCtx,
+ ExplodedNode *Pred,
+ ExplodedNodeSet &Dst,
+ const CFGBlock *DstT,
+ const CFGBlock *DstF) override;
+
+ /// Called by CoreEngine.
+ /// Used to generate successor nodes for temporary destructors depending
+ /// on whether the corresponding constructor was visited.
+ void processCleanupTemporaryBranch(const CXXBindTemporaryExpr *BTE,
+ NodeBuilderContext &BldCtx,
+ ExplodedNode *Pred, ExplodedNodeSet &Dst,
+ const CFGBlock *DstT,
+ const CFGBlock *DstF) override;
+
+ /// Called by CoreEngine. Used to processing branching behavior
+ /// at static initalizers.
+ void processStaticInitializer(const DeclStmt *DS,
+ NodeBuilderContext& BuilderCtx,
+ ExplodedNode *Pred,
+ ExplodedNodeSet &Dst,
+ const CFGBlock *DstT,
+ const CFGBlock *DstF) override;
+
+ /// processIndirectGoto - Called by CoreEngine. Used to generate successor
+ /// nodes by processing the 'effects' of a computed goto jump.
+ void processIndirectGoto(IndirectGotoNodeBuilder& builder) override;
+
+ /// ProcessSwitch - Called by CoreEngine. Used to generate successor
+ /// nodes by processing the 'effects' of a switch statement.
+ void processSwitch(SwitchNodeBuilder& builder) override;
+
+ /// Called by CoreEngine. Used to generate end-of-path
+ /// nodes when the control reaches the end of a function.
+ void processEndOfFunction(NodeBuilderContext& BC,
+ ExplodedNode *Pred) override;
+
+ /// Remove dead bindings/symbols before exiting a function.
+ void removeDeadOnEndOfFunction(NodeBuilderContext& BC,
+ ExplodedNode *Pred,
+ ExplodedNodeSet &Dst);
+
+ /// Generate the entry node of the callee.
+ void processCallEnter(CallEnter CE, ExplodedNode *Pred) override;
+
+ /// Generate the sequence of nodes that simulate the call exit and the post
+ /// visit for CallExpr.
+ void processCallExit(ExplodedNode *Pred) override;
+
+ /// Called by CoreEngine when the analysis worklist has terminated.
+ void processEndWorklist(bool hasWorkRemaining) override;
+
+ /// evalAssume - Callback function invoked by the ConstraintManager when
+ /// making assumptions about state values.
+ ProgramStateRef processAssume(ProgramStateRef state, SVal cond,
+ bool assumption) override;
+
+ /// wantsRegionChangeUpdate - Called by ProgramStateManager to determine if a
+ /// region change should trigger a processRegionChanges update.
+ bool wantsRegionChangeUpdate(ProgramStateRef state) override;
+
+ /// processRegionChanges - Called by ProgramStateManager whenever a change is made
+ /// to the store. Used to update checkers that track region values.
+ ProgramStateRef
+ processRegionChanges(ProgramStateRef state,
+ const InvalidatedSymbols *invalidated,
+ ArrayRef<const MemRegion *> ExplicitRegions,
+ ArrayRef<const MemRegion *> Regions,
+ const CallEvent *Call) override;
+
+ /// printState - Called by ProgramStateManager to print checker-specific data.
+ void printState(raw_ostream &Out, ProgramStateRef State,
+ const char *NL, const char *Sep) override;
+
+ ProgramStateManager& getStateManager() override { 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();
+ }
+
+ // 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 wasBlocksExhausted() const { return Engine.wasBlocksExhausted(); }
+ bool hasEmptyWorkList() const { return !Engine.getWorkList()->hasWork(); }
+ bool hasWorkRemaining() const { return Engine.hasWorkRemaining(); }
+
+ const CoreEngine &getCoreEngine() const { return Engine; }
+
+public:
+ /// 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);
+
+ /// VisitGCCAsmStmt - Transfer function logic for inline asm.
+ void VisitGCCAsmStmt(const GCCAsmStmt *A, ExplodedNode *Pred,
+ ExplodedNodeSet &Dst);
+
+ /// VisitMSAsmStmt - Transfer function logic for MS inline asm.
+ void VisitMSAsmStmt(const MSAsmStmt *A, ExplodedNode *Pred,
+ ExplodedNodeSet &Dst);
+
+ /// VisitBlockExpr - Transfer function logic for BlockExprs.
+ void VisitBlockExpr(const BlockExpr *BE, ExplodedNode *Pred,
+ ExplodedNodeSet &Dst);
+
+ /// VisitLambdaExpr - Transfer function logic for LambdaExprs.
+ void VisitLambdaExpr(const LambdaExpr *LE, 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 VisitCallExpr(const CallExpr *CE, ExplodedNode *Pred,
+ 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);
+
+ 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);
+
+ /// 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 VisitObjCMessage(const ObjCMessageExpr *ME, ExplodedNode *Pred,
+ 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);
+
+ /// VisitUnaryExprOrTypeTraitExpr - Transfer function for sizeof.
+ void VisitUnaryExprOrTypeTraitExpr(const UnaryExprOrTypeTraitExpr *Ex,
+ ExplodedNode *Pred, ExplodedNodeSet &Dst);
+
+ /// VisitUnaryOperator - Transfer function logic for unary operators.
+ void VisitUnaryOperator(const UnaryOperator* B, ExplodedNode *Pred,
+ ExplodedNodeSet &Dst);
+
+ /// Handle ++ and -- (both pre- and post-increment).
+ void VisitIncrementDecrementOperator(const UnaryOperator* U,
+ ExplodedNode *Pred,
+ ExplodedNodeSet &Dst);
+
+ void VisitCXXBindTemporaryExpr(const CXXBindTemporaryExpr *BTE,
+ ExplodedNodeSet &PreVisit,
+ ExplodedNodeSet &Dst);
+
+ void VisitCXXCatchStmt(const CXXCatchStmt *CS, ExplodedNode *Pred,
+ ExplodedNodeSet &Dst);
+
+ void VisitCXXThisExpr(const CXXThisExpr *TE, ExplodedNode *Pred,
+ ExplodedNodeSet & Dst);
+
+ void VisitCXXConstructExpr(const CXXConstructExpr *E, ExplodedNode *Pred,
+ ExplodedNodeSet &Dst);
+
+ void VisitCXXDestructor(QualType ObjectType, const MemRegion *Dest,
+ const Stmt *S, bool IsBaseDtor,
+ ExplodedNode *Pred, ExplodedNodeSet &Dst);
+
+ void VisitCXXNewAllocatorCall(const CXXNewExpr *CNE,
+ ExplodedNode *Pred,
+ ExplodedNodeSet &Dst);
+
+ void VisitCXXNewExpr(const CXXNewExpr *CNE, ExplodedNode *Pred,
+ ExplodedNodeSet &Dst);
+
+ void VisitCXXDeleteExpr(const CXXDeleteExpr *CDE, ExplodedNode *Pred,
+ ExplodedNodeSet &Dst);
+
+ /// Create a C++ temporary object for an rvalue.
+ void CreateCXXTemporaryObject(const MaterializeTemporaryExpr *ME,
+ ExplodedNode *Pred,
+ ExplodedNodeSet &Dst);
+
+ /// evalEagerlyAssumeBinOpBifurcation - 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 evalEagerlyAssumeBinOpBifurcation(ExplodedNodeSet &Dst, ExplodedNodeSet &Src,
+ const Expr *Ex);
+
+ std::pair<const ProgramPointTag *, const ProgramPointTag*>
+ geteagerlyAssumeBinOpBifurcationTags();
+
+ SVal evalMinus(SVal X) {
+ return X.isValid() ? svalBuilder.evalMinus(X.castAs<NonLoc>()) : X;
+ }
+
+ SVal evalComplement(SVal X) {
+ return X.isValid() ? svalBuilder.evalComplement(X.castAs<NonLoc>()) : X;
+ }
+
+public:
+
+ SVal evalBinOp(ProgramStateRef state, BinaryOperator::Opcode op,
+ NonLoc L, NonLoc R, QualType T) {
+ return svalBuilder.evalBinOpNN(state, op, L, R, T);
+ }
+
+ SVal evalBinOp(ProgramStateRef state, BinaryOperator::Opcode op,
+ NonLoc L, SVal R, QualType T) {
+ return R.isValid() ? svalBuilder.evalBinOpNN(state, op, L,
+ R.castAs<NonLoc>(), T) : R;
+ }
+
+ SVal evalBinOp(ProgramStateRef ST, BinaryOperator::Opcode Op,
+ SVal LHS, SVal RHS, QualType T) {
+ return svalBuilder.evalBinOp(ST, Op, LHS, RHS, T);
+ }
+
+protected:
+ /// 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,
+ SVal location, SVal Val, bool atDeclInit = false,
+ const ProgramPoint *PP = nullptr);
+
+ /// Call PointerEscape callback when a value escapes as a result of bind.
+ ProgramStateRef processPointerEscapedOnBind(ProgramStateRef State,
+ SVal Loc, SVal Val) override;
+ /// Call PointerEscape callback when a value escapes as a result of
+ /// region invalidation.
+ /// \param[in] ITraits Specifies invalidation traits for regions/symbols.
+ ProgramStateRef notifyCheckersOfPointerEscape(
+ ProgramStateRef State,
+ const InvalidatedSymbols *Invalidated,
+ ArrayRef<const MemRegion *> ExplicitRegions,
+ ArrayRef<const MemRegion *> Regions,
+ const CallEvent *Call,
+ RegionAndSymbolInvalidationTraits &ITraits) override;
+
+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 *NodeEx, /* Eventually will be a CFGStmt */
+ const Expr *BoundExpr,
+ ExplodedNode *Pred,
+ ProgramStateRef St,
+ SVal location,
+ const ProgramPointTag *tag = nullptr,
+ 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, ProgramStateRef St, SVal TargetLV, SVal Val,
+ const ProgramPointTag *tag = nullptr);
+
+ /// \brief Create a new state in which the call return value is binded to the
+ /// call origin expression.
+ ProgramStateRef bindReturnValue(const CallEvent &Call,
+ const LocationContext *LCtx,
+ ProgramStateRef State);
+
+ /// Evaluate a call, running pre- and post-call checks and allowing checkers
+ /// to be responsible for handling the evaluation of the call itself.
+ void evalCall(ExplodedNodeSet &Dst, ExplodedNode *Pred,
+ const CallEvent &Call);
+
+ /// \brief Default implementation of call evaluation.
+ void defaultEvalCall(NodeBuilder &B, ExplodedNode *Pred,
+ const CallEvent &Call);
+private:
+ void evalLoadCommon(ExplodedNodeSet &Dst,
+ const Expr *NodeEx, /* Eventually will be a CFGStmt */
+ const Expr *BoundEx,
+ ExplodedNode *Pred,
+ ProgramStateRef St,
+ SVal location,
+ const ProgramPointTag *tag,
+ QualType LoadTy);
+
+ // FIXME: 'tag' should be removed, and a LocationContext should be used
+ // instead.
+ void evalLocation(ExplodedNodeSet &Dst,
+ const Stmt *NodeEx, /* This will eventually be a CFGStmt */
+ const Stmt *BoundEx,
+ ExplodedNode *Pred,
+ ProgramStateRef St, SVal location,
+ const ProgramPointTag *tag, bool isLoad);
+
+ /// Count the stack depth and determine if the call is recursive.
+ void examineStackFrames(const Decl *D, const LocationContext *LCtx,
+ bool &IsRecursive, unsigned &StackDepth);
+
+ /// Checks our policies and decides weither the given call should be inlined.
+ bool shouldInlineCall(const CallEvent &Call, const Decl *D,
+ const ExplodedNode *Pred);
+
+ bool inlineCall(const CallEvent &Call, const Decl *D, NodeBuilder &Bldr,
+ ExplodedNode *Pred, ProgramStateRef State);
+
+ /// \brief Conservatively evaluate call by invalidating regions and binding
+ /// a conjured return value.
+ void conservativeEvalCall(const CallEvent &Call, NodeBuilder &Bldr,
+ ExplodedNode *Pred, ProgramStateRef State);
+
+ /// \brief Either inline or process the call conservatively (or both), based
+ /// on DynamicDispatchBifurcation data.
+ void BifurcateCall(const MemRegion *BifurReg,
+ const CallEvent &Call, const Decl *D, NodeBuilder &Bldr,
+ ExplodedNode *Pred);
+
+ bool replayWithoutInlining(ExplodedNode *P, const LocationContext *CalleeLC);
+
+ /// Models a trivial copy or move constructor or trivial assignment operator
+ /// call with a simple bind.
+ void performTrivialCopy(NodeBuilder &Bldr, ExplodedNode *Pred,
+ const CallEvent &Call);
+
+ /// If the value of the given expression is a NonLoc, copy it into a new
+ /// temporary object region, and replace the value of the expression with
+ /// that.
+ ///
+ /// If \p ResultE is provided, the new region will be bound to this expression
+ /// instead of \p E.
+ ProgramStateRef createTemporaryRegionIfNeeded(ProgramStateRef State,
+ const LocationContext *LC,
+ const Expr *E,
+ const Expr *ResultE = nullptr);
+
+ /// For a DeclStmt or CXXInitCtorInitializer, walk backward in the current CFG
+ /// block to find the constructor expression that directly constructed into
+ /// the storage for this statement. Returns null if the constructor for this
+ /// statement created a temporary object region rather than directly
+ /// constructing into an existing region.
+ const CXXConstructExpr *findDirectConstructorForCurrentCFGElement();
+
+ /// For a CXXConstructExpr, walk forward in the current CFG block to find the
+ /// CFGElement for the DeclStmt or CXXInitCtorInitializer for which is
+ /// directly constructed by this constructor. Returns None if the current
+ /// constructor expression did not directly construct into an existing
+ /// region.
+ Optional<CFGElement> findElementDirectlyInitializedByCurrentConstructor();
+
+ /// For a given constructor, look forward in the current CFG block to
+ /// determine the region into which an object will be constructed by \p CE.
+ /// Returns either a field or local variable region if the object will be
+ /// directly constructed in an existing region or a temporary object region
+ /// if not.
+ const MemRegion *getRegionForConstructedObject(const CXXConstructExpr *CE,
+ ExplodedNode *Pred);
+};
+
+/// Traits for storing the call processing policy inside GDM.
+/// The GDM stores the corresponding CallExpr pointer.
+// FIXME: This does not use the nice trait macros because it must be accessible
+// from multiple translation units.
+struct ReplayWithoutInlining{};
+template <>
+struct ProgramStateTrait<ReplayWithoutInlining> :
+ public ProgramStatePartialTrait<const void*> {
+ static void *GDMIndex() { static int index = 0; return &index; }
+};
+
+} // end ento namespace
+
+} // end clang namespace
+
+#endif
diff --git a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/FunctionSummary.h b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/FunctionSummary.h
new file mode 100644
index 0000000..ce81c98
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/FunctionSummary.h
@@ -0,0 +1,140 @@
+//== FunctionSummary.h - Stores summaries of functions. ------------*- C++ -*-//
+//
+// 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 summary of a function gathered/used by static analysis.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_FUNCTIONSUMMARY_H
+#define LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_FUNCTIONSUMMARY_H
+
+#include "clang/AST/Decl.h"
+#include "clang/Basic/LLVM.h"
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/DenseSet.h"
+#include "llvm/ADT/Optional.h"
+#include "llvm/ADT/SmallBitVector.h"
+#include <deque>
+
+namespace clang {
+
+namespace ento {
+typedef std::deque<Decl*> SetOfDecls;
+typedef llvm::DenseSet<const Decl*> SetOfConstDecls;
+
+class FunctionSummariesTy {
+ class FunctionSummary {
+ public:
+ /// Marks the IDs of the basic blocks visited during the analyzes.
+ llvm::SmallBitVector VisitedBasicBlocks;
+
+ /// Total number of blocks in the function.
+ unsigned TotalBasicBlocks : 30;
+
+ /// True if this function has been checked against the rules for which
+ /// functions may be inlined.
+ unsigned InlineChecked : 1;
+
+ /// True if this function may be inlined.
+ unsigned MayInline : 1;
+
+ /// The number of times the function has been inlined.
+ unsigned TimesInlined : 32;
+
+ FunctionSummary() :
+ TotalBasicBlocks(0),
+ InlineChecked(0),
+ TimesInlined(0) {}
+ };
+
+ typedef llvm::DenseMap<const Decl *, FunctionSummary> MapTy;
+ MapTy Map;
+
+public:
+ MapTy::iterator findOrInsertSummary(const Decl *D) {
+ MapTy::iterator I = Map.find(D);
+ if (I != Map.end())
+ return I;
+
+ typedef std::pair<const Decl *, FunctionSummary> KVPair;
+ I = Map.insert(KVPair(D, FunctionSummary())).first;
+ assert(I != Map.end());
+ return I;
+ }
+
+ void markMayInline(const Decl *D) {
+ MapTy::iterator I = findOrInsertSummary(D);
+ I->second.InlineChecked = 1;
+ I->second.MayInline = 1;
+ }
+
+ void markShouldNotInline(const Decl *D) {
+ MapTy::iterator I = findOrInsertSummary(D);
+ I->second.InlineChecked = 1;
+ I->second.MayInline = 0;
+ }
+
+ void markReachedMaxBlockCount(const Decl *D) {
+ markShouldNotInline(D);
+ }
+
+ Optional<bool> mayInline(const Decl *D) {
+ MapTy::const_iterator I = Map.find(D);
+ if (I != Map.end() && I->second.InlineChecked)
+ return I->second.MayInline;
+ return None;
+ }
+
+ void markVisitedBasicBlock(unsigned ID, const Decl* D, unsigned TotalIDs) {
+ MapTy::iterator I = findOrInsertSummary(D);
+ llvm::SmallBitVector &Blocks = I->second.VisitedBasicBlocks;
+ assert(ID < TotalIDs);
+ if (TotalIDs > Blocks.size()) {
+ Blocks.resize(TotalIDs);
+ I->second.TotalBasicBlocks = TotalIDs;
+ }
+ Blocks.set(ID);
+ }
+
+ unsigned getNumVisitedBasicBlocks(const Decl* D) {
+ MapTy::const_iterator I = Map.find(D);
+ if (I != Map.end())
+ return I->second.VisitedBasicBlocks.count();
+ return 0;
+ }
+
+ unsigned getNumTimesInlined(const Decl* D) {
+ MapTy::const_iterator I = Map.find(D);
+ if (I != Map.end())
+ return I->second.TimesInlined;
+ return 0;
+ }
+
+ void bumpNumTimesInlined(const Decl* D) {
+ MapTy::iterator I = findOrInsertSummary(D);
+ I->second.TimesInlined++;
+ }
+
+ /// Get the percentage of the reachable blocks.
+ unsigned getPercentBlocksReachable(const Decl *D) {
+ MapTy::const_iterator I = Map.find(D);
+ if (I != Map.end())
+ return ((I->second.VisitedBasicBlocks.count() * 100) /
+ I->second.TotalBasicBlocks);
+ return 0;
+ }
+
+ unsigned getTotalNumBasicBlocks();
+ unsigned getTotalNumVisitedBasicBlocks();
+
+};
+
+}} // end clang ento namespaces
+
+#endif
diff --git a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/LoopWidening.h b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/LoopWidening.h
new file mode 100644
index 0000000..3168733
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/LoopWidening.h
@@ -0,0 +1,36 @@
+//===--- LoopWidening.h - Widen loops ---------------------------*- 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 declarations of functions which are used to widen
+/// loops which do not otherwise exit. The widening is done by invalidating
+/// anything which might be modified by the body of the loop.
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_LOOPWIDENING_H
+#define LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_LOOPWIDENING_H
+
+#include "clang/Analysis/CFG.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h"
+
+namespace clang {
+namespace ento {
+
+/// \brief Get the states that result from widening the loop.
+///
+/// Widen the loop by invalidating anything that might be modified
+/// by the loop body in any iteration.
+ProgramStateRef getWidenedLoopState(ProgramStateRef PrevState,
+ const LocationContext *LCtx,
+ unsigned BlockCount, const Stmt *LoopStmt);
+
+} // end namespace ento
+} // end namespace clang
+
+#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..bb835c4
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h
@@ -0,0 +1,1370 @@
+//== 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_STATICANALYZER_CORE_PATHSENSITIVE_MEMREGION_H
+#define LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_MEMREGION_H
+
+#include "clang/AST/ASTContext.h"
+#include "clang/AST/CharUnits.h"
+#include "clang/AST/Decl.h"
+#include "clang/AST/DeclCXX.h"
+#include "clang/AST/ExprObjC.h"
+#include "clang/Basic/LLVM.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/SVals.h"
+#include "llvm/ADT/FoldingSet.h"
+#include "llvm/Support/Allocator.h"
+#include "llvm/Support/ErrorHandling.h"
+#include <string>
+
+namespace clang {
+
+class LocationContext;
+class StackFrameContext;
+
+namespace ento {
+
+class CodeTextRegion;
+class MemRegionManager;
+class MemSpaceRegion;
+class SValBuilder;
+class SymbolicRegion;
+class VarRegion;
+
+/// 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. Can be negative.
+ int64_t Offset;
+
+public:
+ // We're using a const instead of an enumeration due to the size required;
+ // Visual Studio will only create enumerations of size int, not long long.
+ static const int64_t Symbolic = INT64_MAX;
+
+ RegionOffset() : R(nullptr) {}
+ RegionOffset(const MemRegion *r, int64_t off) : R(r), Offset(off) {}
+
+ const MemRegion *getRegion() const { return R; }
+
+ bool hasSymbolicOffset() const { return Offset == Symbolic; }
+
+ int64_t getOffset() const {
+ assert(!hasSymbolicOffset());
+ return Offset;
+ }
+
+ bool isValid() const { return R; }
+};
+
+//===----------------------------------------------------------------------===//
+// 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,
+ StaticGlobalSpaceRegionKind,
+ GlobalInternalSpaceRegionKind,
+ GlobalSystemSpaceRegionKind,
+ GlobalImmutableSpaceRegionKind,
+ BEG_NON_STATIC_GLOBAL_MEMSPACES = GlobalInternalSpaceRegionKind,
+ END_NON_STATIC_GLOBAL_MEMSPACES = GlobalImmutableSpaceRegionKind,
+ BEG_GLOBAL_MEMSPACES = StaticGlobalSpaceRegionKind,
+ END_GLOBAL_MEMSPACES = GlobalImmutableSpaceRegionKind,
+ BEG_MEMSPACES = GenericMemSpaceRegionKind,
+ END_MEMSPACES = GlobalImmutableSpaceRegionKind,
+ // Untyped regions.
+ SymbolicRegionKind,
+ AllocaRegionKind,
+ // Typed regions.
+ BEG_TYPED_REGIONS,
+ FunctionTextRegionKind = BEG_TYPED_REGIONS,
+ BlockTextRegionKind,
+ BlockDataRegionKind,
+ BEG_TYPED_VALUE_REGIONS,
+ CompoundLiteralRegionKind = BEG_TYPED_VALUE_REGIONS,
+ CXXThisRegionKind,
+ StringRegionKind,
+ ObjCStringRegionKind,
+ ElementRegionKind,
+ // Decl Regions.
+ BEG_DECL_REGIONS,
+ VarRegionKind = BEG_DECL_REGIONS,
+ FieldRegionKind,
+ ObjCIvarRegionKind,
+ END_DECL_REGIONS = ObjCIvarRegionKind,
+ CXXTempObjectRegionKind,
+ CXXBaseObjectRegionKind,
+ END_TYPED_VALUE_REGIONS = 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;
+
+ const MemSpaceRegion *getMemorySpace() const;
+
+ const MemRegion *getBaseRegion() const;
+
+ /// Check if the region is a subregion of the given region.
+ virtual bool isSubRegionOf(const MemRegion *R) const;
+
+ const MemRegion *StripCasts(bool StripBaseCasts = true) const;
+
+ /// \brief If this is a symbolic region, returns the region. Otherwise,
+ /// goes up the base chain looking for the first symbolic base region.
+ const SymbolicRegion *getSymbolicBase() 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;
+
+ /// \brief Get a string representation of a region for debug use.
+ std::string getString() const;
+
+ virtual void dumpToStream(raw_ostream &os) const;
+
+ void dump() const;
+
+ /// \brief Returns true if this region can be printed in a user-friendly way.
+ virtual bool canPrintPretty() const;
+
+ /// \brief Print the region for use in diagnostics.
+ virtual void printPretty(raw_ostream &os) const;
+
+ /// \brief Returns true if this region's textual representation can be used
+ /// as part of a larger expression.
+ virtual bool canPrintPrettyAsExpr() const;
+
+ /// \brief Print the region as expression.
+ ///
+ /// When this region represents a subexpression, the method is for printing
+ /// an expression containing it.
+ virtual void printPrettyAsExpr(raw_ostream &os) const;
+
+ Kind getKind() const { return kind; }
+
+ template<typename RegionTy> const RegionTy* getAs() const;
+
+ virtual bool isBoundable() const { return false; }
+};
+
+/// MemSpaceRegion - A memory region that represents a "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 override { return Mgr; }
+
+public:
+ bool isBoundable() const override { return false; }
+
+ void Profile(llvm::FoldingSetNodeID &ID) const override;
+
+ static bool classof(const MemRegion *R) {
+ Kind k = R->getKind();
+ return k >= BEG_MEMSPACES && k <= END_MEMSPACES;
+ }
+};
+
+class GlobalsSpaceRegion : public MemSpaceRegion {
+ virtual void anchor();
+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;
+ }
+};
+
+/// \brief The region of the static variables within the current CodeTextRegion
+/// scope.
+///
+/// Currently, only the static locals are placed there, so we know that these
+/// variables do not get invalidated by calls to other functions.
+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 override;
+
+ void dumpToStream(raw_ostream &os) const override;
+
+ const CodeTextRegion *getCodeRegion() const { return CR; }
+
+ static bool classof(const MemRegion *R) {
+ return R->getKind() == StaticGlobalSpaceRegionKind;
+ }
+};
+
+/// \brief The region for all the non-static global variables.
+///
+/// This class is further split into subclasses for efficient implementation of
+/// invalidating a set of related global values as is done in
+/// RegionStoreManager::invalidateRegions (instead of finding all the dependent
+/// globals, we invalidate the whole parent region).
+class NonStaticGlobalSpaceRegion : public GlobalsSpaceRegion {
+ friend class MemRegionManager;
+
+protected:
+ NonStaticGlobalSpaceRegion(MemRegionManager *mgr, Kind k)
+ : GlobalsSpaceRegion(mgr, k) {}
+
+public:
+
+ static bool classof(const MemRegion *R) {
+ Kind k = R->getKind();
+ return k >= BEG_NON_STATIC_GLOBAL_MEMSPACES &&
+ k <= END_NON_STATIC_GLOBAL_MEMSPACES;
+ }
+};
+
+/// \brief The region containing globals which are defined in system/external
+/// headers and are considered modifiable by system calls (ex: errno).
+class GlobalSystemSpaceRegion : public NonStaticGlobalSpaceRegion {
+ friend class MemRegionManager;
+
+ GlobalSystemSpaceRegion(MemRegionManager *mgr)
+ : NonStaticGlobalSpaceRegion(mgr, GlobalSystemSpaceRegionKind) {}
+
+public:
+
+ void dumpToStream(raw_ostream &os) const override;
+
+ static bool classof(const MemRegion *R) {
+ return R->getKind() == GlobalSystemSpaceRegionKind;
+ }
+};
+
+/// \brief The region containing globals which are considered not to be modified
+/// or point to data which could be modified as a result of a function call
+/// (system or internal). Ex: Const global scalars would be modeled as part of
+/// this region. This region also includes most system globals since they have
+/// low chance of being modified.
+class GlobalImmutableSpaceRegion : public NonStaticGlobalSpaceRegion {
+ friend class MemRegionManager;
+
+ GlobalImmutableSpaceRegion(MemRegionManager *mgr)
+ : NonStaticGlobalSpaceRegion(mgr, GlobalImmutableSpaceRegionKind) {}
+
+public:
+
+ void dumpToStream(raw_ostream &os) const override;
+
+ static bool classof(const MemRegion *R) {
+ return R->getKind() == GlobalImmutableSpaceRegionKind;
+ }
+};
+
+/// \brief The region containing globals which can be modified by calls to
+/// "internally" defined functions - (for now just) functions other then system
+/// calls.
+class GlobalInternalSpaceRegion : public NonStaticGlobalSpaceRegion {
+ friend class MemRegionManager;
+
+ GlobalInternalSpaceRegion(MemRegionManager *mgr)
+ : NonStaticGlobalSpaceRegion(mgr, GlobalInternalSpaceRegionKind) {}
+
+public:
+
+ void dumpToStream(raw_ostream &os) const override;
+
+ static bool classof(const MemRegion *R) {
+ return R->getKind() == GlobalInternalSpaceRegionKind;
+ }
+};
+
+class HeapSpaceRegion : public MemSpaceRegion {
+ virtual void anchor();
+ friend class MemRegionManager;
+
+ HeapSpaceRegion(MemRegionManager *mgr)
+ : MemSpaceRegion(mgr, HeapSpaceRegionKind) {}
+public:
+
+ void dumpToStream(raw_ostream &os) const override;
+
+ static bool classof(const MemRegion *R) {
+ return R->getKind() == HeapSpaceRegionKind;
+ }
+};
+
+class UnknownSpaceRegion : public MemSpaceRegion {
+ virtual void anchor();
+ friend class MemRegionManager;
+ UnknownSpaceRegion(MemRegionManager *mgr)
+ : MemSpaceRegion(mgr, UnknownSpaceRegionKind) {}
+public:
+
+ void dumpToStream(raw_ostream &os) const override;
+
+ 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 override;
+
+ static bool classof(const MemRegion *R) {
+ Kind k = R->getKind();
+ return k >= StackLocalsSpaceRegionKind &&
+ k <= StackArgumentsSpaceRegionKind;
+ }
+};
+
+class StackLocalsSpaceRegion : public StackSpaceRegion {
+ virtual void anchor();
+ friend class MemRegionManager;
+ StackLocalsSpaceRegion(MemRegionManager *mgr, const StackFrameContext *sfc)
+ : StackSpaceRegion(mgr, StackLocalsSpaceRegionKind, sfc) {}
+public:
+
+ void dumpToStream(raw_ostream &os) const override;
+
+ static bool classof(const MemRegion *R) {
+ return R->getKind() == StackLocalsSpaceRegionKind;
+ }
+};
+
+class StackArgumentsSpaceRegion : public StackSpaceRegion {
+private:
+ virtual void anchor();
+ friend class MemRegionManager;
+ StackArgumentsSpaceRegion(MemRegionManager *mgr, const StackFrameContext *sfc)
+ : StackSpaceRegion(mgr, StackArgumentsSpaceRegionKind, sfc) {}
+public:
+
+ void dumpToStream(raw_ostream &os) const override;
+
+ 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 {
+private:
+ virtual void anchor();
+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 override;
+
+ bool isSubRegionOf(const MemRegion* R) const override;
+
+ 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 override { return true; }
+
+ DefinedOrUnknownSVal getExtent(SValBuilder &svalBuilder) const override;
+
+ void Profile(llvm::FoldingSetNodeID& ID) const override;
+
+ static void ProfileRegion(llvm::FoldingSetNodeID& ID, const Expr *Ex,
+ unsigned Cnt, const MemRegion *superRegion);
+
+ void dumpToStream(raw_ostream &os) const override;
+
+ static bool classof(const MemRegion* R) {
+ return R->getKind() == AllocaRegionKind;
+ }
+};
+
+/// TypedRegion - An abstract class representing regions that are typed.
+class TypedRegion : public SubRegion {
+public:
+ void anchor() override;
+protected:
+ TypedRegion(const MemRegion* sReg, Kind k) : SubRegion(sReg, k) {}
+
+public:
+ virtual QualType getLocationType() const = 0;
+
+ QualType getDesugaredLocationType(ASTContext &Context) const {
+ return getLocationType().getDesugaredType(Context);
+ }
+
+ bool isBoundable() const override { return true; }
+
+ static bool classof(const MemRegion* R) {
+ unsigned k = R->getKind();
+ return k >= BEG_TYPED_REGIONS && k <= END_TYPED_REGIONS;
+ }
+};
+
+/// TypedValueRegion - An abstract class representing regions having a typed value.
+class TypedValueRegion : public TypedRegion {
+public:
+ void anchor() override;
+protected:
+ TypedValueRegion(const MemRegion* sReg, Kind k) : TypedRegion(sReg, k) {}
+
+public:
+ virtual QualType getValueType() const = 0;
+
+ QualType getLocationType() const override {
+ // 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;
+ }
+
+ DefinedOrUnknownSVal getExtent(SValBuilder &svalBuilder) const override;
+
+ static bool classof(const MemRegion* R) {
+ unsigned k = R->getKind();
+ return k >= BEG_TYPED_VALUE_REGIONS && k <= END_TYPED_VALUE_REGIONS;
+ }
+};
+
+
+class CodeTextRegion : public TypedRegion {
+public:
+ void anchor() override;
+protected:
+ CodeTextRegion(const MemRegion *sreg, Kind k) : TypedRegion(sreg, k) {}
+public:
+ bool isBoundable() const override { 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 NamedDecl *FD;
+public:
+ FunctionTextRegion(const NamedDecl *fd, const MemRegion* sreg)
+ : CodeTextRegion(sreg, FunctionTextRegionKind), FD(fd) {
+ assert(isa<ObjCMethodDecl>(fd) || isa<FunctionDecl>(fd));
+ }
+
+ QualType getLocationType() const override {
+ const ASTContext &Ctx = getContext();
+ if (const FunctionDecl *D = dyn_cast<FunctionDecl>(FD)) {
+ return Ctx.getPointerType(D->getType());
+ }
+
+ assert(isa<ObjCMethodDecl>(FD));
+ assert(false && "Getting the type of ObjCMethod is not supported yet");
+
+ // TODO: We might want to return a different type here (ex: id (*ty)(...))
+ // depending on how it is used.
+ return QualType();
+ }
+
+ const NamedDecl *getDecl() const {
+ return FD;
+ }
+
+ void dumpToStream(raw_ostream &os) const override;
+
+ void Profile(llvm::FoldingSetNodeID& ID) const override;
+
+ static void ProfileRegion(llvm::FoldingSetNodeID& ID, const NamedDecl *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;
+ AnalysisDeclContext *AC;
+ CanQualType locTy;
+
+ BlockTextRegion(const BlockDecl *bd, CanQualType lTy,
+ AnalysisDeclContext *ac, const MemRegion* sreg)
+ : CodeTextRegion(sreg, BlockTextRegionKind), BD(bd), AC(ac), locTy(lTy) {}
+
+public:
+ QualType getLocationType() const override {
+ return locTy;
+ }
+
+ const BlockDecl *getDecl() const {
+ return BD;
+ }
+
+ AnalysisDeclContext *getAnalysisDeclContext() const { return AC; }
+
+ void dumpToStream(raw_ostream &os) const override;
+
+ void Profile(llvm::FoldingSetNodeID& ID) const override;
+
+ static void ProfileRegion(llvm::FoldingSetNodeID& ID, const BlockDecl *BD,
+ CanQualType, const AnalysisDeclContext*,
+ 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 TypedRegion {
+ friend class MemRegionManager;
+ const BlockTextRegion *BC;
+ const LocationContext *LC; // Can be null */
+ unsigned BlockCount;
+ void *ReferencedVars;
+ void *OriginalVars;
+
+ BlockDataRegion(const BlockTextRegion *bc, const LocationContext *lc,
+ unsigned count, const MemRegion *sreg)
+ : TypedRegion(sreg, BlockDataRegionKind), BC(bc), LC(lc),
+ BlockCount(count),
+ ReferencedVars(nullptr), OriginalVars(nullptr) {}
+
+public:
+ const BlockTextRegion *getCodeRegion() const { return BC; }
+
+ const BlockDecl *getDecl() const { return BC->getDecl(); }
+
+ QualType getLocationType() const override { return BC->getLocationType(); }
+
+ class referenced_vars_iterator {
+ const MemRegion * const *R;
+ const MemRegion * const *OriginalR;
+ public:
+ explicit referenced_vars_iterator(const MemRegion * const *r,
+ const MemRegion * const *originalR)
+ : R(r), OriginalR(originalR) {}
+
+ const VarRegion *getCapturedRegion() const {
+ return cast<VarRegion>(*R);
+ }
+ const VarRegion *getOriginalRegion() const {
+ return cast<VarRegion>(*OriginalR);
+ }
+
+ bool operator==(const referenced_vars_iterator &I) const {
+ assert((R == nullptr) == (I.R == nullptr));
+ return I.R == R;
+ }
+ bool operator!=(const referenced_vars_iterator &I) const {
+ assert((R == nullptr) == (I.R == nullptr));
+ return I.R != R;
+ }
+ referenced_vars_iterator &operator++() {
+ ++R;
+ ++OriginalR;
+ return *this;
+ }
+ };
+
+ /// Return the original region for a captured region, if
+ /// one exists.
+ const VarRegion *getOriginalRegion(const VarRegion *VR) const;
+
+ referenced_vars_iterator referenced_vars_begin() const;
+ referenced_vars_iterator referenced_vars_end() const;
+
+ void dumpToStream(raw_ostream &os) const override;
+
+ void Profile(llvm::FoldingSetNodeID& ID) const override;
+
+ static void ProfileRegion(llvm::FoldingSetNodeID&, const BlockTextRegion *,
+ const LocationContext *, unsigned,
+ const MemRegion *);
+
+ static bool classof(const MemRegion* R) {
+ return R->getKind() == BlockDataRegionKind;
+ }
+private:
+ void LazyInitializeReferencedVars();
+ std::pair<const VarRegion *, const VarRegion *>
+ getCaptureRegions(const VarDecl *VD);
+};
+
+/// SymbolicRegion - A special, "non-concrete" region. Unlike other region
+/// classes, 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 override { return true; }
+
+ DefinedOrUnknownSVal getExtent(SValBuilder &svalBuilder) const override;
+
+ void Profile(llvm::FoldingSetNodeID& ID) const override;
+
+ static void ProfileRegion(llvm::FoldingSetNodeID& ID,
+ SymbolRef sym,
+ const MemRegion* superRegion);
+
+ void dumpToStream(raw_ostream &os) const override;
+
+ static bool classof(const MemRegion* R) {
+ return R->getKind() == SymbolicRegionKind;
+ }
+};
+
+/// StringRegion - Region associated with a StringLiteral.
+class StringRegion : public TypedValueRegion {
+ friend class MemRegionManager;
+ const StringLiteral* Str;
+protected:
+
+ StringRegion(const StringLiteral* str, const MemRegion* sreg)
+ : TypedValueRegion(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 override {
+ return Str->getType();
+ }
+
+ DefinedOrUnknownSVal getExtent(SValBuilder &svalBuilder) const override;
+
+ bool isBoundable() const override { return false; }
+
+ void Profile(llvm::FoldingSetNodeID& ID) const override {
+ ProfileRegion(ID, Str, superRegion);
+ }
+
+ void dumpToStream(raw_ostream &os) const override;
+
+ static bool classof(const MemRegion* R) {
+ return R->getKind() == StringRegionKind;
+ }
+};
+
+/// The region associated with an ObjCStringLiteral.
+class ObjCStringRegion : public TypedValueRegion {
+ friend class MemRegionManager;
+ const ObjCStringLiteral* Str;
+protected:
+
+ ObjCStringRegion(const ObjCStringLiteral* str, const MemRegion* sreg)
+ : TypedValueRegion(sreg, ObjCStringRegionKind), Str(str) {}
+
+ static void ProfileRegion(llvm::FoldingSetNodeID& ID,
+ const ObjCStringLiteral* Str,
+ const MemRegion* superRegion);
+
+public:
+
+ const ObjCStringLiteral* getObjCStringLiteral() const { return Str; }
+
+ QualType getValueType() const override {
+ return Str->getType();
+ }
+
+ bool isBoundable() const override { return false; }
+
+ void Profile(llvm::FoldingSetNodeID& ID) const override {
+ ProfileRegion(ID, Str, superRegion);
+ }
+
+ void dumpToStream(raw_ostream &os) const override;
+
+ static bool classof(const MemRegion* R) {
+ return R->getKind() == ObjCStringRegionKind;
+ }
+};
+
+/// 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 TypedValueRegion {
+private:
+ friend class MemRegionManager;
+ const CompoundLiteralExpr *CL;
+
+ CompoundLiteralRegion(const CompoundLiteralExpr *cl, const MemRegion* sReg)
+ : TypedValueRegion(sReg, CompoundLiteralRegionKind), CL(cl) {}
+
+ static void ProfileRegion(llvm::FoldingSetNodeID& ID,
+ const CompoundLiteralExpr *CL,
+ const MemRegion* superRegion);
+public:
+ QualType getValueType() const override {
+ return CL->getType();
+ }
+
+ bool isBoundable() const override { return !CL->isFileScope(); }
+
+ void Profile(llvm::FoldingSetNodeID& ID) const override;
+
+ void dumpToStream(raw_ostream &os) const override;
+
+ const CompoundLiteralExpr *getLiteralExpr() const { return CL; }
+
+ static bool classof(const MemRegion* R) {
+ return R->getKind() == CompoundLiteralRegionKind;
+ }
+};
+
+class DeclRegion : public TypedValueRegion {
+protected:
+ const Decl *D;
+
+ DeclRegion(const Decl *d, const MemRegion* sReg, Kind k)
+ : TypedValueRegion(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 override;
+
+ 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 override;
+
+public:
+ const VarDecl *getDecl() const { return cast<VarDecl>(D); }
+
+ const StackFrameContext *getStackFrame() const;
+
+ QualType getValueType() const override {
+ // FIXME: We can cache this if needed.
+ return getDecl()->getType();
+ }
+
+ void dumpToStream(raw_ostream &os) const override;
+
+ static bool classof(const MemRegion* R) {
+ return R->getKind() == VarRegionKind;
+ }
+
+ bool canPrintPrettyAsExpr() const override;
+
+ void printPrettyAsExpr(raw_ostream &os) const override;
+};
+
+/// 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 TypedValueRegion {
+ friend class MemRegionManager;
+ CXXThisRegion(const PointerType *thisPointerTy,
+ const MemRegion *sReg)
+ : TypedValueRegion(sReg, CXXThisRegionKind), ThisPointerTy(thisPointerTy) {}
+
+ static void ProfileRegion(llvm::FoldingSetNodeID &ID,
+ const PointerType *PT,
+ const MemRegion *sReg);
+
+ void Profile(llvm::FoldingSetNodeID &ID) const override;
+
+public:
+ QualType getValueType() const override {
+ return QualType(ThisPointerTy, 0);
+ }
+
+ void dumpToStream(raw_ostream &os) const override;
+
+ 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:
+ const FieldDecl *getDecl() const { return cast<FieldDecl>(D); }
+
+ QualType getValueType() const override {
+ // FIXME: We can cache this if needed.
+ return getDecl()->getType();
+ }
+
+ DefinedOrUnknownSVal getExtent(SValBuilder &svalBuilder) const override;
+
+ 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;
+ }
+
+ void dumpToStream(raw_ostream &os) const override;
+
+ bool canPrintPretty() const override;
+ void printPretty(raw_ostream &os) const override;
+ bool canPrintPrettyAsExpr() const override;
+ void printPrettyAsExpr(raw_ostream &os) const override;
+};
+
+class ObjCIvarRegion : public DeclRegion {
+
+ friend class MemRegionManager;
+
+ ObjCIvarRegion(const ObjCIvarDecl *ivd, const MemRegion* sReg);
+
+ static void ProfileRegion(llvm::FoldingSetNodeID& ID, const ObjCIvarDecl *ivd,
+ const MemRegion* superRegion);
+
+public:
+ const ObjCIvarDecl *getDecl() const;
+ QualType getValueType() const override;
+
+ bool canPrintPrettyAsExpr() const override;
+ void printPrettyAsExpr(raw_ostream &os) const override;
+
+ void dumpToStream(raw_ostream &os) const override;
+
+ static bool classof(const MemRegion* R) {
+ return R->getKind() == ObjCIvarRegionKind;
+ }
+};
+//===----------------------------------------------------------------------===//
+// Auxiliary 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(raw_ostream &os) const;
+ void dump() const;
+};
+
+/// \brief ElementRegin is used to represent both array elements and casts.
+class ElementRegion : public TypedValueRegion {
+ friend class MemRegionManager;
+
+ QualType ElementType;
+ NonLoc Index;
+
+ ElementRegion(QualType elementType, NonLoc Idx, const MemRegion* sReg)
+ : TypedValueRegion(sReg, ElementRegionKind),
+ ElementType(elementType), Index(Idx) {
+ assert((!Idx.getAs<nonloc::ConcreteInt>() ||
+ Idx.castAs<nonloc::ConcreteInt>().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 override {
+ 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(raw_ostream &os) const override;
+
+ void Profile(llvm::FoldingSetNodeID& ID) const override;
+
+ static bool classof(const MemRegion* R) {
+ return R->getKind() == ElementRegionKind;
+ }
+};
+
+// C++ temporary object associated with an expression.
+class CXXTempObjectRegion : public TypedValueRegion {
+ friend class MemRegionManager;
+
+ Expr const *Ex;
+
+ CXXTempObjectRegion(Expr const *E, MemRegion const *sReg)
+ : TypedValueRegion(sReg, CXXTempObjectRegionKind), Ex(E) {}
+
+ static void ProfileRegion(llvm::FoldingSetNodeID &ID,
+ Expr const *E, const MemRegion *sReg);
+
+public:
+ const Expr *getExpr() const { return Ex; }
+
+ QualType getValueType() const override {
+ return Ex->getType();
+ }
+
+ void dumpToStream(raw_ostream &os) const override;
+
+ void Profile(llvm::FoldingSetNodeID &ID) const override;
+
+ 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 TypedValueRegion {
+ friend class MemRegionManager;
+
+ llvm::PointerIntPair<const CXXRecordDecl *, 1, bool> Data;
+
+ CXXBaseObjectRegion(const CXXRecordDecl *RD, bool IsVirtual,
+ const MemRegion *SReg)
+ : TypedValueRegion(SReg, CXXBaseObjectRegionKind), Data(RD, IsVirtual) {}
+
+ static void ProfileRegion(llvm::FoldingSetNodeID &ID, const CXXRecordDecl *RD,
+ bool IsVirtual, const MemRegion *SReg);
+
+public:
+ const CXXRecordDecl *getDecl() const { return Data.getPointer(); }
+ bool isVirtual() const { return Data.getInt(); }
+
+ QualType getValueType() const override;
+
+ void dumpToStream(raw_ostream &os) const override;
+
+ void Profile(llvm::FoldingSetNodeID &ID) const override;
+
+ static bool classof(const MemRegion *region) {
+ return region->getKind() == CXXBaseObjectRegionKind;
+ }
+
+ bool canPrintPrettyAsExpr() const override;
+
+ void printPrettyAsExpr(raw_ostream &os) const override;
+};
+
+template<typename RegionTy>
+const RegionTy* MemRegion::getAs() const {
+ if (const RegionTy* RT = dyn_cast<RegionTy>(this))
+ return RT;
+
+ return nullptr;
+}
+
+//===----------------------------------------------------------------------===//
+// MemRegionManager - Factory object for creating regions.
+//===----------------------------------------------------------------------===//
+
+class MemRegionManager {
+ ASTContext &C;
+ llvm::BumpPtrAllocator& A;
+ llvm::FoldingSet<MemRegion> Regions;
+
+ GlobalInternalSpaceRegion *InternalGlobals;
+ GlobalSystemSpaceRegion *SystemGlobals;
+ GlobalImmutableSpaceRegion *ImmutableGlobals;
+
+
+ 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), InternalGlobals(nullptr), SystemGlobals(nullptr),
+ ImmutableGlobals(nullptr), heap(nullptr), unknown(nullptr),
+ code(nullptr) {}
+
+ ~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(
+ MemRegion::Kind K = MemRegion::GlobalInternalSpaceRegionKind,
+ const CodeTextRegion *R = nullptr);
+
+ /// 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 [artificial] region associated with the
+ /// parameter 'this'.
+ const CXXThisRegion *getCXXThisRegion(QualType thisPointerTy,
+ const LocationContext *LC);
+
+ /// \brief Retrieve or create a "symbolic" memory region.
+ const SymbolicRegion* getSymbolicRegion(SymbolRef Sym);
+
+ /// \brief Return a unique symbolic region belonging to heap memory space.
+ const SymbolicRegion *getSymbolicHeapRegion(SymbolRef sym);
+
+ const StringRegion *getStringRegion(const StringLiteral* Str);
+
+ const ObjCStringRegion *getObjCStringRegion(const ObjCStringLiteral *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);
+
+ /// Create a CXXBaseObjectRegion with the given base class for region
+ /// \p Super.
+ ///
+ /// The type of \p Super is assumed be a class deriving from \p BaseClass.
+ const CXXBaseObjectRegion *
+ getCXXBaseObjectRegion(const CXXRecordDecl *BaseClass, const MemRegion *Super,
+ bool IsVirtual);
+
+ /// 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,
+ baseReg->isVirtual());
+ }
+
+ const FunctionTextRegion *getFunctionTextRegion(const NamedDecl *FD);
+ const BlockTextRegion *getBlockTextRegion(const BlockDecl *BD,
+ CanQualType locTy,
+ AnalysisDeclContext *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,
+ unsigned blockCount);
+
+ /// Create a CXXTempObjectRegion for temporaries which are lifetime-extended
+ /// by static references. This differs from getCXXTempObjectRegion in the
+ /// super-region used.
+ const CXXTempObjectRegion *getCXXStaticTempObjectRegion(const Expr *Ex);
+
+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();
+}
+
+//===----------------------------------------------------------------------===//
+// Means for storing region/symbol handling traits.
+//===----------------------------------------------------------------------===//
+
+/// Information about invalidation for a particular region/symbol.
+class RegionAndSymbolInvalidationTraits {
+ typedef unsigned char StorageTypeForKinds;
+ llvm::DenseMap<const MemRegion *, StorageTypeForKinds> MRTraitsMap;
+ llvm::DenseMap<SymbolRef, StorageTypeForKinds> SymTraitsMap;
+
+ typedef llvm::DenseMap<const MemRegion *, StorageTypeForKinds>::const_iterator
+ const_region_iterator;
+ typedef llvm::DenseMap<SymbolRef, StorageTypeForKinds>::const_iterator
+ const_symbol_iterator;
+
+public:
+ /// \brief Describes different invalidation traits.
+ enum InvalidationKinds {
+ /// Tells that a region's contents is not changed.
+ TK_PreserveContents = 0x1,
+ /// Suppress pointer-escaping of a region.
+ TK_SuppressEscape = 0x2,
+ // Do not invalidate super region.
+ TK_DoNotInvalidateSuperRegion = 0x4,
+ /// When applied to a MemSpaceRegion, indicates the entire memory space
+ /// should be invalidated.
+ TK_EntireMemSpace = 0x8
+
+ // Do not forget to extend StorageTypeForKinds if number of traits exceed
+ // the number of bits StorageTypeForKinds can store.
+ };
+
+ void setTrait(SymbolRef Sym, InvalidationKinds IK);
+ void setTrait(const MemRegion *MR, InvalidationKinds IK);
+ bool hasTrait(SymbolRef Sym, InvalidationKinds IK);
+ bool hasTrait(const MemRegion *MR, InvalidationKinds IK);
+};
+
+} // 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/ProgramState.h b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h
new file mode 100644
index 0000000..c4a62ec
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h
@@ -0,0 +1,854 @@
+//== ProgramState.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 the state of the program along the analysisa path.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_PROGRAMSTATE_H
+#define LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_PROGRAMSTATE_H
+
+#include "clang/Basic/LLVM.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/ConstraintManager.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/DynamicTypeInfo.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/Environment.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState_Fwd.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/SValBuilder.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/Store.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/TaintTag.h"
+#include "llvm/ADT/FoldingSet.h"
+#include "llvm/ADT/ImmutableMap.h"
+#include "llvm/ADT/PointerIntPair.h"
+#include "llvm/Support/Allocator.h"
+
+namespace llvm {
+class APSInt;
+}
+
+namespace clang {
+class ASTContext;
+
+namespace ento {
+
+class CallEvent;
+class CallEventManager;
+
+typedef std::unique_ptr<ConstraintManager>(*ConstraintManagerCreator)(
+ ProgramStateManager &, SubEngine *);
+typedef std::unique_ptr<StoreManager>(*StoreManagerCreator)(
+ ProgramStateManager &);
+
+//===----------------------------------------------------------------------===//
+// ProgramStateTrait - Traits used by the Generic Data Map of a ProgramState.
+//===----------------------------------------------------------------------===//
+
+template <typename T> struct ProgramStatePartialTrait;
+
+template <typename T> struct ProgramStateTrait {
+ typedef typename T::data_type data_type;
+ 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 ProgramState
+/// ProgramState - 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.
+///
+/// ProgramState 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 ProgramState : public llvm::FoldingSetNode {
+public:
+ typedef llvm::ImmutableSet<llvm::APSInt*> IntSetTy;
+ typedef llvm::ImmutableMap<void*, void*> GenericDataMap;
+
+private:
+ void operator=(const ProgramState& R) = delete;
+
+ friend class ProgramStateManager;
+ friend class ExplodedGraph;
+ friend class ExplodedNode;
+
+ ProgramStateManager *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 ProgramState with the same values as the current
+ /// state with the exception of using the specified Store.
+ ProgramStateRef makeWithStore(const StoreRef &store) const;
+
+ void setStore(const StoreRef &storeRef);
+
+public:
+ /// This ctor is used when creating the first ProgramState object.
+ ProgramState(ProgramStateManager *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.
+ ProgramState(const ProgramState &RHS);
+
+ ~ProgramState();
+
+ /// Return the ProgramStateManager associated with this state.
+ ProgramStateManager &getStateManager() const {
+ return *stateMgr;
+ }
+
+ /// Return the ConstraintManager.
+ ConstraintManager &getConstraintManager() const;
+
+ /// 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 ProgramState object for use in a
+ /// FoldingSet. Two ProgramState objects are considered equal if they
+ /// have the same Environment, Store, and GenericDataMap.
+ static void Profile(llvm::FoldingSetNodeID& ID, const ProgramState *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 ProgramState records constraints on symbolic values. These constraints
+ // are managed using the ConstraintManager associated with a ProgramStateManager.
+ // 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/ProgramState.
+ //
+ // 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 ProgramState 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 ProgramState object with the added constraints.
+ // If no new state is feasible, NULL is returned.
+ //
+
+ /// Assumes that the value of \p cond is zero (if \p assumption is "false")
+ /// or non-zero (if \p assumption is "true").
+ ///
+ /// This returns a new state with the added constraint on \p cond.
+ /// If no new state is feasible, NULL is returned.
+ ProgramStateRef assume(DefinedOrUnknownSVal cond, bool assumption) const;
+
+ /// Assumes both "true" and "false" for \p cond, and returns both
+ /// corresponding states (respectively).
+ ///
+ /// This is more efficient than calling assume() twice. Note that one (but not
+ /// both) of the returned states may be NULL.
+ std::pair<ProgramStateRef, ProgramStateRef>
+ assume(DefinedOrUnknownSVal cond) const;
+
+ ProgramStateRef assumeInBound(DefinedOrUnknownSVal idx,
+ DefinedOrUnknownSVal upperBound,
+ bool assumption,
+ QualType IndexType = QualType()) const;
+
+ /// Assumes that the value of \p Val is bounded with [\p From; \p To]
+ /// (if \p assumption is "true") or it is fully out of this range
+ /// (if \p assumption is "false").
+ ///
+ /// This returns a new state with the added constraint on \p cond.
+ /// If no new state is feasible, NULL is returned.
+ ProgramStateRef assumeWithinInclusiveRange(DefinedOrUnknownSVal Val,
+ const llvm::APSInt &From,
+ const llvm::APSInt &To,
+ bool assumption) const;
+
+ /// Assumes given range both "true" and "false" for \p Val, and returns both
+ /// corresponding states (respectively).
+ ///
+ /// This is more efficient than calling assume() twice. Note that one (but not
+ /// both) of the returned states may be NULL.
+ std::pair<ProgramStateRef, ProgramStateRef>
+ assumeWithinInclusiveRange(DefinedOrUnknownSVal Val, const llvm::APSInt &From,
+ const llvm::APSInt &To) const;
+
+
+ /// \brief Check if the given SVal is constrained to zero or is a zero
+ /// constant.
+ ConditionTruthVal isNull(SVal V) const;
+
+ /// Utility method for getting regions.
+ const VarRegion* getRegion(const VarDecl *D, const LocationContext *LC) const;
+
+ //==---------------------------------------------------------------------==//
+ // Binding and retrieving values to/from the environment and symbolic store.
+ //==---------------------------------------------------------------------==//
+
+ /// Create a new state by binding the value 'V' to the statement 'S' in the
+ /// state's environment.
+ ProgramStateRef BindExpr(const Stmt *S, const LocationContext *LCtx,
+ SVal V, bool Invalidate = true) const;
+
+ ProgramStateRef bindLoc(Loc location,
+ SVal V,
+ bool notifyChanges = true) const;
+
+ ProgramStateRef bindLoc(SVal location, SVal V) const;
+
+ ProgramStateRef bindDefault(SVal loc, SVal V) const;
+
+ ProgramStateRef killBinding(Loc LV) const;
+
+ /// \brief Returns the state with bindings for the given regions
+ /// cleared from the store.
+ ///
+ /// Optionally invalidates global regions as well.
+ ///
+ /// \param Regions the set of regions to be invalidated.
+ /// \param E the expression that caused the invalidation.
+ /// \param BlockCount The number of times the current basic block has been
+ // visited.
+ /// \param CausesPointerEscape the flag is set to true when
+ /// the invalidation entails escape of a symbol (representing a
+ /// pointer). For example, due to it being passed as an argument in a
+ /// call.
+ /// \param IS the set of invalidated symbols.
+ /// \param Call if non-null, the invalidated regions represent parameters to
+ /// the call and should be considered directly invalidated.
+ /// \param ITraits information about special handling for a particular
+ /// region/symbol.
+ ProgramStateRef
+ invalidateRegions(ArrayRef<const MemRegion *> Regions, const Expr *E,
+ unsigned BlockCount, const LocationContext *LCtx,
+ bool CausesPointerEscape, InvalidatedSymbols *IS = nullptr,
+ const CallEvent *Call = nullptr,
+ RegionAndSymbolInvalidationTraits *ITraits = nullptr) const;
+
+ ProgramStateRef
+ invalidateRegions(ArrayRef<SVal> Regions, const Expr *E,
+ unsigned BlockCount, const LocationContext *LCtx,
+ bool CausesPointerEscape, InvalidatedSymbols *IS = nullptr,
+ const CallEvent *Call = nullptr,
+ RegionAndSymbolInvalidationTraits *ITraits = nullptr) const;
+
+ /// enterStackFrame - Returns the state for entry to the given stack frame,
+ /// preserving the current state.
+ ProgramStateRef enterStackFrame(const CallEvent &Call,
+ const StackFrameContext *CalleeCtx) const;
+
+ /// Get the lvalue for a variable reference.
+ Loc getLValue(const VarDecl *D, const LocationContext *LC) 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 indirect field reference.
+ SVal getLValue(const IndirectFieldDecl *decl, SVal Base) const;
+
+ /// Get the lvalue for an array index.
+ SVal getLValue(QualType ElementType, SVal Idx, SVal Base) const;
+
+ /// Returns the SVal bound to the statement 'S' in the state's environment.
+ SVal getSVal(const Stmt *S, const LocationContext *LCtx) const;
+
+ SVal getSValAsScalarOrLoc(const Stmt *Ex, const LocationContext *LCtx) const;
+
+ /// \brief Return the value bound to the specified location.
+ /// Returns UnknownVal() if none found.
+ 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;
+
+ /// \brief Return the value bound to the specified location.
+ /// Returns UnknownVal() if none found.
+ SVal getSVal(const MemRegion* R) const;
+
+ SVal getSValAsScalarOrLoc(const MemRegion *R) const;
+
+ /// \brief Visits the symbols reachable from the given SVal using the provided
+ /// SymbolVisitor.
+ ///
+ /// This is a convenience API. Consider using ScanReachableSymbols class
+ /// directly when making multiple scans on the same state with the same
+ /// visitor to avoid repeated initialization cost.
+ /// \sa ScanReachableSymbols
+ bool scanReachableSymbols(SVal val, SymbolVisitor& visitor) const;
+
+ /// \brief Visits the symbols reachable from the SVals in the given range
+ /// using the provided SymbolVisitor.
+ bool scanReachableSymbols(const SVal *I, const SVal *E,
+ SymbolVisitor &visitor) const;
+
+ /// \brief Visits the symbols reachable from the regions in the given
+ /// MemRegions range using the provided SymbolVisitor.
+ 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;
+
+ /// Create a new state in which the statement is marked as tainted.
+ ProgramStateRef addTaint(const Stmt *S, const LocationContext *LCtx,
+ TaintTagType Kind = TaintTagGeneric) const;
+
+ /// Create a new state in which the symbol is marked as tainted.
+ ProgramStateRef addTaint(SymbolRef S,
+ TaintTagType Kind = TaintTagGeneric) const;
+
+ /// Create a new state in which the region symbol is marked as tainted.
+ ProgramStateRef addTaint(const MemRegion *R,
+ TaintTagType Kind = TaintTagGeneric) const;
+
+ /// Check if the statement is tainted in the current state.
+ bool isTainted(const Stmt *S, const LocationContext *LCtx,
+ TaintTagType Kind = TaintTagGeneric) const;
+ bool isTainted(SVal V, TaintTagType Kind = TaintTagGeneric) const;
+ bool isTainted(SymbolRef Sym, TaintTagType Kind = TaintTagGeneric) const;
+ bool isTainted(const MemRegion *Reg, TaintTagType Kind=TaintTagGeneric) const;
+
+ //==---------------------------------------------------------------------==//
+ // Accessing the Generic Data Map (GDM).
+ //==---------------------------------------------------------------------==//
+
+ void *const* FindGDM(void *K) const;
+
+ template<typename T>
+ ProgramStateRef add(typename ProgramStateTrait<T>::key_type K) const;
+
+ template <typename T>
+ typename ProgramStateTrait<T>::data_type
+ get() const {
+ return ProgramStateTrait<T>::MakeData(FindGDM(ProgramStateTrait<T>::GDMIndex()));
+ }
+
+ template<typename T>
+ typename ProgramStateTrait<T>::lookup_type
+ get(typename ProgramStateTrait<T>::key_type key) const {
+ void *const* d = FindGDM(ProgramStateTrait<T>::GDMIndex());
+ return ProgramStateTrait<T>::Lookup(ProgramStateTrait<T>::MakeData(d), key);
+ }
+
+ template <typename T>
+ typename ProgramStateTrait<T>::context_type get_context() const;
+
+
+ template<typename T>
+ ProgramStateRef remove(typename ProgramStateTrait<T>::key_type K) const;
+
+ template<typename T>
+ ProgramStateRef remove(typename ProgramStateTrait<T>::key_type K,
+ typename ProgramStateTrait<T>::context_type C) const;
+ template <typename T>
+ ProgramStateRef remove() const;
+
+ template<typename T>
+ ProgramStateRef set(typename ProgramStateTrait<T>::data_type D) const;
+
+ template<typename T>
+ ProgramStateRef set(typename ProgramStateTrait<T>::key_type K,
+ typename ProgramStateTrait<T>::value_type E) const;
+
+ template<typename T>
+ ProgramStateRef set(typename ProgramStateTrait<T>::key_type K,
+ typename ProgramStateTrait<T>::value_type E,
+ typename ProgramStateTrait<T>::context_type C) const;
+
+ template<typename T>
+ bool contains(typename ProgramStateTrait<T>::key_type key) const {
+ void *const* d = FindGDM(ProgramStateTrait<T>::GDMIndex());
+ return ProgramStateTrait<T>::Contains(ProgramStateTrait<T>::MakeData(d), key);
+ }
+
+ // Pretty-printing.
+ void print(raw_ostream &Out, const char *nl = "\n",
+ const char *sep = "") const;
+ void printDOT(raw_ostream &Out) const;
+ void printTaint(raw_ostream &Out, const char *nl = "\n",
+ const char *sep = "") const;
+
+ void dump() const;
+ void dumpTaint() const;
+
+private:
+ friend void ProgramStateRetain(const ProgramState *state);
+ friend void ProgramStateRelease(const ProgramState *state);
+
+ /// \sa invalidateValues()
+ /// \sa invalidateRegions()
+ ProgramStateRef
+ invalidateRegionsImpl(ArrayRef<SVal> Values,
+ const Expr *E, unsigned BlockCount,
+ const LocationContext *LCtx,
+ bool ResultsInSymbolEscape,
+ InvalidatedSymbols *IS,
+ RegionAndSymbolInvalidationTraits *HTraits,
+ const CallEvent *Call) const;
+};
+
+//===----------------------------------------------------------------------===//
+// ProgramStateManager - Factory object for ProgramStates.
+//===----------------------------------------------------------------------===//
+
+class ProgramStateManager {
+ friend class ProgramState;
+ friend void ProgramStateRelease(const ProgramState *state);
+private:
+ /// Eng - The SubEngine that owns this state manager.
+ SubEngine *Eng; /* Can be null. */
+
+ EnvironmentManager EnvMgr;
+ std::unique_ptr<StoreManager> StoreMgr;
+ std::unique_ptr<ConstraintManager> ConstraintMgr;
+
+ ProgramState::GenericDataMap::Factory GDMFactory;
+
+ typedef llvm::DenseMap<void*,std::pair<void*,void (*)(void*)> > GDMContextsTy;
+ GDMContextsTy GDMContexts;
+
+ /// StateSet - FoldingSet containing all the states created for analyzing
+ /// a particular function. This is used to unique states.
+ llvm::FoldingSet<ProgramState> StateSet;
+
+ /// Object that manages the data for all created SVals.
+ std::unique_ptr<SValBuilder> svalBuilder;
+
+ /// Manages memory for created CallEvents.
+ std::unique_ptr<CallEventManager> CallEventMgr;
+
+ /// A BumpPtrAllocator to allocate states.
+ llvm::BumpPtrAllocator &Alloc;
+
+ /// A vector of ProgramStates that we can reuse.
+ std::vector<ProgramState *> freeStates;
+
+public:
+ ProgramStateManager(ASTContext &Ctx,
+ StoreManagerCreator CreateStoreManager,
+ ConstraintManagerCreator CreateConstraintManager,
+ llvm::BumpPtrAllocator& alloc,
+ SubEngine *subeng);
+
+ ~ProgramStateManager();
+
+ ProgramStateRef getInitialState(const LocationContext *InitLoc);
+
+ ASTContext &getContext() { return svalBuilder->getContext(); }
+ const ASTContext &getContext() const { return svalBuilder->getContext(); }
+
+ BasicValueFactory &getBasicVals() {
+ 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();
+ }
+
+ CallEventManager &getCallEventManager() { return *CallEventMgr; }
+
+ StoreManager& getStoreManager() { return *StoreMgr; }
+ ConstraintManager& getConstraintManager() { return *ConstraintMgr; }
+ SubEngine* getOwningEngine() { return Eng; }
+
+ ProgramStateRef removeDeadBindings(ProgramStateRef St,
+ const StackFrameContext *LCtx,
+ SymbolReaper& SymReaper);
+
+public:
+
+ SVal ArrayToPointer(Loc Array, QualType ElementTy) {
+ return StoreMgr->ArrayToPointer(Array, ElementTy);
+ }
+
+ // Methods that manipulate the GDM.
+ ProgramStateRef addGDM(ProgramStateRef St, void *Key, void *Data);
+ ProgramStateRef removeGDM(ProgramStateRef state, void *Key);
+
+ // Methods that query & manipulate the Store.
+
+ void iterBindings(ProgramStateRef state, StoreManager::BindingsHandler& F) {
+ StoreMgr->iterBindings(state->getStore(), F);
+ }
+
+ ProgramStateRef getPersistentState(ProgramState &Impl);
+ ProgramStateRef getPersistentStateWithGDM(ProgramStateRef FromState,
+ ProgramStateRef GDMState);
+
+ bool haveEqualEnvironments(ProgramStateRef S1, ProgramStateRef S2) {
+ return S1->Env == S2->Env;
+ }
+
+ bool haveEqualStores(ProgramStateRef S1, ProgramStateRef S2) {
+ return S1->store == S2->store;
+ }
+
+ //==---------------------------------------------------------------------==//
+ // Generic Data Map methods.
+ //==---------------------------------------------------------------------==//
+ //
+ // ProgramStateManager and ProgramState support a "generic data map" that allows
+ // different clients of ProgramState objects to embed arbitrary data within a
+ // ProgramState 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 ProgramStateTrait<T> class
+ // to resolve keys into the GDM and to return data values to clients.
+ //
+
+ // Trait based GDM dispatch.
+ template <typename T>
+ ProgramStateRef set(ProgramStateRef st, typename ProgramStateTrait<T>::data_type D) {
+ return addGDM(st, ProgramStateTrait<T>::GDMIndex(),
+ ProgramStateTrait<T>::MakeVoidPtr(D));
+ }
+
+ template<typename T>
+ ProgramStateRef set(ProgramStateRef st,
+ typename ProgramStateTrait<T>::key_type K,
+ typename ProgramStateTrait<T>::value_type V,
+ typename ProgramStateTrait<T>::context_type C) {
+
+ return addGDM(st, ProgramStateTrait<T>::GDMIndex(),
+ ProgramStateTrait<T>::MakeVoidPtr(ProgramStateTrait<T>::Set(st->get<T>(), K, V, C)));
+ }
+
+ template <typename T>
+ ProgramStateRef add(ProgramStateRef st,
+ typename ProgramStateTrait<T>::key_type K,
+ typename ProgramStateTrait<T>::context_type C) {
+ return addGDM(st, ProgramStateTrait<T>::GDMIndex(),
+ ProgramStateTrait<T>::MakeVoidPtr(ProgramStateTrait<T>::Add(st->get<T>(), K, C)));
+ }
+
+ template <typename T>
+ ProgramStateRef remove(ProgramStateRef st,
+ typename ProgramStateTrait<T>::key_type K,
+ typename ProgramStateTrait<T>::context_type C) {
+
+ return addGDM(st, ProgramStateTrait<T>::GDMIndex(),
+ ProgramStateTrait<T>::MakeVoidPtr(ProgramStateTrait<T>::Remove(st->get<T>(), K, C)));
+ }
+
+ template <typename T>
+ ProgramStateRef remove(ProgramStateRef st) {
+ return removeGDM(st, ProgramStateTrait<T>::GDMIndex());
+ }
+
+ void *FindGDMContext(void *index,
+ void *(*CreateContext)(llvm::BumpPtrAllocator&),
+ void (*DeleteContext)(void*));
+
+ template <typename T>
+ typename ProgramStateTrait<T>::context_type get_context() {
+ void *p = FindGDMContext(ProgramStateTrait<T>::GDMIndex(),
+ ProgramStateTrait<T>::CreateContext,
+ ProgramStateTrait<T>::DeleteContext);
+
+ return ProgramStateTrait<T>::MakeContext(p);
+ }
+
+ void EndPath(ProgramStateRef St) {
+ ConstraintMgr->EndPath(St);
+ }
+};
+
+
+//===----------------------------------------------------------------------===//
+// Out-of-line method definitions for ProgramState.
+//===----------------------------------------------------------------------===//
+
+inline ConstraintManager &ProgramState::getConstraintManager() const {
+ return stateMgr->getConstraintManager();
+}
+
+inline const VarRegion* ProgramState::getRegion(const VarDecl *D,
+ const LocationContext *LC) const
+{
+ return getStateManager().getRegionManager().getVarRegion(D, LC);
+}
+
+inline ProgramStateRef ProgramState::assume(DefinedOrUnknownSVal Cond,
+ bool Assumption) const {
+ if (Cond.isUnknown())
+ return this;
+
+ return getStateManager().ConstraintMgr
+ ->assume(this, Cond.castAs<DefinedSVal>(), Assumption);
+}
+
+inline std::pair<ProgramStateRef , ProgramStateRef >
+ProgramState::assume(DefinedOrUnknownSVal Cond) const {
+ if (Cond.isUnknown())
+ return std::make_pair(this, this);
+
+ return getStateManager().ConstraintMgr
+ ->assumeDual(this, Cond.castAs<DefinedSVal>());
+}
+
+inline ProgramStateRef
+ProgramState::assumeWithinInclusiveRange(DefinedOrUnknownSVal Val,
+ const llvm::APSInt &From,
+ const llvm::APSInt &To,
+ bool Assumption) const {
+ if (Val.isUnknown())
+ return this;
+
+ assert(Val.getAs<NonLoc>() && "Only NonLocs are supported!");
+
+ return getStateManager().ConstraintMgr->assumeWithinInclusiveRange(
+ this, Val.castAs<NonLoc>(), From, To, Assumption);
+}
+
+inline std::pair<ProgramStateRef, ProgramStateRef>
+ProgramState::assumeWithinInclusiveRange(DefinedOrUnknownSVal Val,
+ const llvm::APSInt &From,
+ const llvm::APSInt &To) const {
+ if (Val.isUnknown())
+ return std::make_pair(this, this);
+
+ assert(Val.getAs<NonLoc>() && "Only NonLocs are supported!");
+
+ return getStateManager().ConstraintMgr
+ ->assumeWithinInclusiveRangeDual(this, Val.castAs<NonLoc>(), From, To);
+}
+
+inline ProgramStateRef ProgramState::bindLoc(SVal LV, SVal V) const {
+ if (Optional<Loc> L = LV.getAs<Loc>())
+ return bindLoc(*L, V);
+ return this;
+}
+
+inline Loc ProgramState::getLValue(const VarDecl *VD,
+ const LocationContext *LC) const {
+ return getStateManager().StoreMgr->getLValueVar(VD, LC);
+}
+
+inline Loc ProgramState::getLValue(const CompoundLiteralExpr *literal,
+ const LocationContext *LC) const {
+ return getStateManager().StoreMgr->getLValueCompoundLiteral(literal, LC);
+}
+
+inline SVal ProgramState::getLValue(const ObjCIvarDecl *D, SVal Base) const {
+ return getStateManager().StoreMgr->getLValueIvar(D, Base);
+}
+
+inline SVal ProgramState::getLValue(const FieldDecl *D, SVal Base) const {
+ return getStateManager().StoreMgr->getLValueField(D, Base);
+}
+
+inline SVal ProgramState::getLValue(const IndirectFieldDecl *D,
+ SVal Base) const {
+ StoreManager &SM = *getStateManager().StoreMgr;
+ for (const auto *I : D->chain()) {
+ Base = SM.getLValueField(cast<FieldDecl>(I), Base);
+ }
+
+ return Base;
+}
+
+inline SVal ProgramState::getLValue(QualType ElementType, SVal Idx, SVal Base) const{
+ if (Optional<NonLoc> N = Idx.getAs<NonLoc>())
+ return getStateManager().StoreMgr->getLValueElement(ElementType, *N, Base);
+ return UnknownVal();
+}
+
+inline SVal ProgramState::getSVal(const Stmt *Ex,
+ const LocationContext *LCtx) const{
+ return Env.getSVal(EnvironmentEntry(Ex, LCtx),
+ *getStateManager().svalBuilder);
+}
+
+inline SVal
+ProgramState::getSValAsScalarOrLoc(const Stmt *S,
+ const LocationContext *LCtx) const {
+ if (const Expr *Ex = dyn_cast<Expr>(S)) {
+ QualType T = Ex->getType();
+ if (Ex->isGLValue() || Loc::isLocType(T) ||
+ T->isIntegralOrEnumerationType())
+ return getSVal(S, LCtx);
+ }
+
+ return UnknownVal();
+}
+
+inline SVal ProgramState::getRawSVal(Loc LV, QualType T) const {
+ return getStateManager().StoreMgr->getBinding(getStore(), LV, T);
+}
+
+inline SVal ProgramState::getSVal(const MemRegion* R) const {
+ return getStateManager().StoreMgr->getBinding(getStore(),
+ loc::MemRegionVal(R));
+}
+
+inline BasicValueFactory &ProgramState::getBasicVals() const {
+ return getStateManager().getBasicVals();
+}
+
+inline SymbolManager &ProgramState::getSymbolManager() const {
+ return getStateManager().getSymbolManager();
+}
+
+template<typename T>
+ProgramStateRef ProgramState::add(typename ProgramStateTrait<T>::key_type K) const {
+ return getStateManager().add<T>(this, K, get_context<T>());
+}
+
+template <typename T>
+typename ProgramStateTrait<T>::context_type ProgramState::get_context() const {
+ return getStateManager().get_context<T>();
+}
+
+template<typename T>
+ProgramStateRef ProgramState::remove(typename ProgramStateTrait<T>::key_type K) const {
+ return getStateManager().remove<T>(this, K, get_context<T>());
+}
+
+template<typename T>
+ProgramStateRef ProgramState::remove(typename ProgramStateTrait<T>::key_type K,
+ typename ProgramStateTrait<T>::context_type C) const {
+ return getStateManager().remove<T>(this, K, C);
+}
+
+template <typename T>
+ProgramStateRef ProgramState::remove() const {
+ return getStateManager().remove<T>(this);
+}
+
+template<typename T>
+ProgramStateRef ProgramState::set(typename ProgramStateTrait<T>::data_type D) const {
+ return getStateManager().set<T>(this, D);
+}
+
+template<typename T>
+ProgramStateRef ProgramState::set(typename ProgramStateTrait<T>::key_type K,
+ typename ProgramStateTrait<T>::value_type E) const {
+ return getStateManager().set<T>(this, K, E, get_context<T>());
+}
+
+template<typename T>
+ProgramStateRef ProgramState::set(typename ProgramStateTrait<T>::key_type K,
+ typename ProgramStateTrait<T>::value_type E,
+ typename ProgramStateTrait<T>::context_type C) const {
+ return getStateManager().set<T>(this, K, E, C);
+}
+
+template <typename CB>
+CB ProgramState::scanReachableSymbols(SVal val) const {
+ CB cb(this);
+ scanReachableSymbols(val, cb);
+ return cb;
+}
+
+template <typename CB>
+CB ProgramState::scanReachableSymbols(const SVal *beg, const SVal *end) const {
+ CB cb(this);
+ scanReachableSymbols(beg, end, cb);
+ return cb;
+}
+
+template <typename CB>
+CB ProgramState::scanReachableSymbols(const MemRegion * const *beg,
+ const MemRegion * const *end) const {
+ CB cb(this);
+ scanReachableSymbols(beg, end, cb);
+ return cb;
+}
+
+/// \class ScanReachableSymbols
+/// A Utility class that allows to visit the reachable symbols using a custom
+/// SymbolVisitor.
+class ScanReachableSymbols {
+ typedef llvm::DenseSet<const void*> VisitedItems;
+
+ VisitedItems visited;
+ ProgramStateRef state;
+ SymbolVisitor &visitor;
+public:
+
+ ScanReachableSymbols(ProgramStateRef st, SymbolVisitor& v)
+ : state(st), visitor(v) {}
+
+ bool scan(nonloc::LazyCompoundVal val);
+ bool scan(nonloc::CompoundVal val);
+ bool scan(SVal val);
+ bool scan(const MemRegion *R);
+ bool scan(const SymExpr *sym);
+};
+
+} // end ento namespace
+
+} // end clang namespace
+
+#endif
diff --git a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ProgramStateTrait.h b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ProgramStateTrait.h
new file mode 100644
index 0000000..6b4da7d
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ProgramStateTrait.h
@@ -0,0 +1,245 @@
+//ProgramStateTrait.h - Partial implementations of ProgramStateTrait -*- C++ -*-
+//
+// 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 ProgramStateTrait<>. ProgramStateTrait<> is used by ProgramState
+// to implement set/get methods for manipulating a ProgramState's
+// generic data map.
+//
+//===----------------------------------------------------------------------===//
+
+
+#ifndef LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_PROGRAMSTATETRAIT_H
+#define LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_PROGRAMSTATETRAIT_H
+
+#include "llvm/Support/Allocator.h"
+#include "llvm/Support/DataTypes.h"
+
+namespace llvm {
+ 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 ProgramStatePartialTrait;
+
+ /// Declares a program state trait for type \p Type called \p Name, and
+ /// introduce a typedef named \c NameTy.
+ /// The macro should not be used inside namespaces, or for traits that must
+ /// be accessible from more than one translation unit.
+ #define REGISTER_TRAIT_WITH_PROGRAMSTATE(Name, Type) \
+ namespace { \
+ class Name {}; \
+ typedef Type Name ## Ty; \
+ } \
+ namespace clang { \
+ namespace ento { \
+ template <> \
+ struct ProgramStateTrait<Name> \
+ : public ProgramStatePartialTrait<Name ## Ty> { \
+ static void *GDMIndex() { static int Index; return &Index; } \
+ }; \
+ } \
+ }
+
+
+ // Partial-specialization for ImmutableMap.
+
+ template <typename Key, typename Data, typename Info>
+ struct ProgramStatePartialTrait< 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(nullptr);
+ }
+ 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;
+ }
+ };
+
+ /// Helper for registering a map trait.
+ ///
+ /// If the map type were written directly in the invocation of
+ /// REGISTER_TRAIT_WITH_PROGRAMSTATE, the comma in the template arguments
+ /// would be treated as a macro argument separator, which is wrong.
+ /// This allows the user to specify a map type in a way that the preprocessor
+ /// can deal with.
+ #define CLANG_ENTO_PROGRAMSTATE_MAP(Key, Value) llvm::ImmutableMap<Key, Value>
+
+
+ // Partial-specialization for ImmutableSet.
+
+ template <typename Key, typename Info>
+ struct ProgramStatePartialTrait< 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(nullptr);
+ }
+
+ 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 ProgramStatePartialTrait< 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 bool Contains(data_type L, key_type K) {
+ return L.contains(K);
+ }
+
+ static inline data_type MakeData(void *const* p) {
+ return p ? data_type((const llvm::ImmutableListImpl<T>*) *p)
+ : data_type(nullptr);
+ }
+
+ static inline void *MakeVoidPtr(data_type D) {
+ return const_cast<llvm::ImmutableListImpl<T> *>(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 ProgramStatePartialTrait<bool> {
+ typedef bool data_type;
+
+ static inline data_type MakeData(void *const* p) {
+ return p ? (data_type) (uintptr_t) *p
+ : data_type();
+ }
+ static inline void *MakeVoidPtr(data_type d) {
+ return (void*) (uintptr_t) d;
+ }
+ };
+
+ // Partial specialization for unsigned.
+ template <> struct ProgramStatePartialTrait<unsigned> {
+ typedef unsigned data_type;
+
+ static inline data_type MakeData(void *const* p) {
+ return p ? (data_type) (uintptr_t) *p
+ : data_type();
+ }
+ static inline void *MakeVoidPtr(data_type d) {
+ return (void*) (uintptr_t) d;
+ }
+ };
+
+ // Partial specialization for void*.
+ template <> struct ProgramStatePartialTrait<void*> {
+ typedef void *data_type;
+
+ static inline data_type MakeData(void *const* p) {
+ return p ? *p
+ : data_type();
+ }
+ static inline void *MakeVoidPtr(data_type d) {
+ return d;
+ }
+ };
+
+ // Partial specialization for const void *.
+ template <> struct ProgramStatePartialTrait<const void *> {
+ typedef const void *data_type;
+
+ static inline data_type MakeData(void * const *p) {
+ return p ? *p : data_type();
+ }
+
+ static inline void *MakeVoidPtr(data_type d) {
+ return const_cast<void *>(d);
+ }
+ };
+
+} // end ento namespace
+
+} // end clang namespace
+
+#endif
diff --git a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ProgramState_Fwd.h b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ProgramState_Fwd.h
new file mode 100644
index 0000000..415bb77
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ProgramState_Fwd.h
@@ -0,0 +1,43 @@
+//== ProgramState_Fwd.h - Incomplete declarations of ProgramState -*- 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_STATICANALYZER_CORE_PATHSENSITIVE_PROGRAMSTATE_FWD_H
+#define LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_PROGRAMSTATE_FWD_H
+
+#include "clang/Basic/LLVM.h"
+#include "llvm/ADT/IntrusiveRefCntPtr.h"
+
+namespace clang {
+namespace ento {
+ class ProgramState;
+ class ProgramStateManager;
+ void ProgramStateRetain(const ProgramState *state);
+ void ProgramStateRelease(const ProgramState *state);
+}
+}
+
+namespace llvm {
+ template <> struct IntrusiveRefCntPtrInfo<const clang::ento::ProgramState> {
+ static void retain(const clang::ento::ProgramState *state) {
+ clang::ento::ProgramStateRetain(state);
+ }
+ static void release(const clang::ento::ProgramState *state) {
+ clang::ento::ProgramStateRelease(state);
+ }
+ };
+}
+
+namespace clang {
+namespace ento {
+ typedef IntrusiveRefCntPtr<const ProgramState> ProgramStateRef;
+}
+}
+
+#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..a68d341
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/SValBuilder.h
@@ -0,0 +1,333 @@
+// 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_STATICANALYZER_CORE_PATHSENSITIVE_SVALBUILDER_H
+#define LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_SVALBUILDER_H
+
+#include "clang/AST/ASTContext.h"
+#include "clang/AST/Expr.h"
+#include "clang/AST/ExprObjC.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/BasicValueFactory.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/SVals.h"
+
+namespace clang {
+
+class CXXBoolLiteralExpr;
+
+namespace ento {
+
+class SValBuilder {
+ virtual void anchor();
+protected:
+ ASTContext &Context;
+
+ /// Manager of APSInt values.
+ BasicValueFactory BasicVals;
+
+ /// Manages the creation of symbols.
+ SymbolManager SymMgr;
+
+ /// Manages the creation of memory regions.
+ MemRegionManager MemMgr;
+
+ ProgramStateManager &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;
+
+ virtual SVal evalCastFromNonLoc(NonLoc val, QualType castTy) = 0;
+ virtual SVal evalCastFromLoc(Loc val, QualType castTy) = 0;
+
+public:
+ // FIXME: Make these protected again once RegionStoreManager correctly
+ // handles loads from different bound value types.
+ virtual SVal dispatchCast(SVal val, QualType castTy) = 0;
+
+public:
+ SValBuilder(llvm::BumpPtrAllocator &alloc, ASTContext &context,
+ ProgramStateManager &stateMgr)
+ : Context(context), BasicVals(context, alloc),
+ SymMgr(context, BasicVals, alloc),
+ MemMgr(context, alloc),
+ StateMgr(stateMgr),
+ ArrayIndexTy(context.IntTy),
+ ArrayIndexWidth(context.getTypeSize(ArrayIndexTy)) {}
+
+ virtual ~SValBuilder() {}
+
+ bool haveSameType(const SymExpr *Sym1, const SymExpr *Sym2) {
+ return haveSameType(Sym1->getType(), Sym2->getType());
+ }
+
+ bool haveSameType(QualType Ty1, QualType Ty2) {
+ // FIXME: Remove the second disjunct when we support symbolic
+ // truncation/extension.
+ return (Context.getCanonicalType(Ty1) == Context.getCanonicalType(Ty2) ||
+ (Ty1->isIntegralOrEnumerationType() &&
+ Ty2->isIntegralOrEnumerationType()));
+ }
+
+ SVal evalCast(SVal val, QualType castTy, QualType originalType);
+
+ virtual SVal evalMinus(NonLoc val) = 0;
+
+ virtual SVal evalComplement(NonLoc val) = 0;
+
+ /// Create a new value which represents a binary expression with two non-
+ /// location operands.
+ virtual SVal evalBinOpNN(ProgramStateRef state, BinaryOperator::Opcode op,
+ NonLoc lhs, NonLoc rhs, QualType resultTy) = 0;
+
+ /// Create a new value which represents a binary expression with two memory
+ /// location operands.
+ virtual SVal evalBinOpLL(ProgramStateRef state, BinaryOperator::Opcode op,
+ Loc lhs, Loc rhs, QualType resultTy) = 0;
+
+ /// Create a new value which represents a binary expression with a memory
+ /// location and non-location operands. For example, this would be used to
+ /// evaluate a pointer arithmetic operation.
+ virtual SVal evalBinOpLN(ProgramStateRef state, BinaryOperator::Opcode op,
+ Loc lhs, NonLoc rhs, QualType resultTy) = 0;
+
+ /// 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(ProgramStateRef state, SVal val) = 0;
+
+ /// Constructs a symbolic expression for two non-location values.
+ SVal makeSymExprValNN(ProgramStateRef state, BinaryOperator::Opcode op,
+ NonLoc lhs, NonLoc rhs, QualType resultTy);
+
+ SVal evalBinOp(ProgramStateRef state, BinaryOperator::Opcode op,
+ SVal lhs, SVal rhs, QualType type);
+
+ DefinedOrUnknownSVal evalEQ(ProgramStateRef state, DefinedOrUnknownSVal lhs,
+ DefinedOrUnknownSVal rhs);
+
+ ASTContext &getContext() { return Context; }
+ const ASTContext &getContext() const { return Context; }
+
+ ProgramStateManager &getStateManager() { return StateMgr; }
+
+ QualType getConditionType() const {
+ return Context.getLangOpts().CPlusPlus ? Context.BoolTy : Context.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* conjureSymbol(const Stmt *stmt,
+ const LocationContext *LCtx,
+ QualType type,
+ unsigned visitCount,
+ const void *symbolTag = nullptr) {
+ return SymMgr.conjureSymbol(stmt, LCtx, type, visitCount, symbolTag);
+ }
+
+ const SymbolConjured* conjureSymbol(const Expr *expr,
+ const LocationContext *LCtx,
+ unsigned visitCount,
+ const void *symbolTag = nullptr) {
+ return SymMgr.conjureSymbol(expr, LCtx, visitCount, symbolTag);
+ }
+
+ /// Construct an SVal representing '0' for the specified type.
+ DefinedOrUnknownSVal makeZeroVal(QualType type);
+
+ /// Make a unique symbol for value of region.
+ DefinedOrUnknownSVal getRegionValueSymbolVal(const TypedValueRegion *region);
+
+ /// \brief Create a new symbol with a unique 'name'.
+ ///
+ /// We resort to conjured symbols when we cannot construct a derived symbol.
+ /// The advantage of symbols derived/built from other symbols is that we
+ /// preserve the relation between related(or even equivalent) expressions, so
+ /// conjured symbols should be used sparingly.
+ DefinedOrUnknownSVal conjureSymbolVal(const void *symbolTag,
+ const Expr *expr,
+ const LocationContext *LCtx,
+ unsigned count);
+ DefinedOrUnknownSVal conjureSymbolVal(const void *symbolTag,
+ const Expr *expr,
+ const LocationContext *LCtx,
+ QualType type,
+ unsigned count);
+
+ DefinedOrUnknownSVal conjureSymbolVal(const Stmt *stmt,
+ const LocationContext *LCtx,
+ QualType type,
+ unsigned visitCount);
+ /// \brief Conjure a symbol representing heap allocated memory region.
+ ///
+ /// Note, the expression should represent a location.
+ DefinedOrUnknownSVal getConjuredHeapSymbolVal(const Expr *E,
+ const LocationContext *LCtx,
+ unsigned Count);
+
+ DefinedOrUnknownSVal getDerivedRegionValueSymbolVal(
+ SymbolRef parentSymbol, const TypedValueRegion *region);
+
+ DefinedSVal getMetadataSymbolVal(
+ const void *symbolTag, const MemRegion *region,
+ const Expr *expr, QualType type, unsigned count);
+
+ DefinedSVal getFunctionPointer(const FunctionDecl *func);
+
+ DefinedSVal getBlockPointer(const BlockDecl *block, CanQualType locTy,
+ const LocationContext *locContext,
+ unsigned blockCount);
+
+ /// Returns the value of \p E, if it can be determined in a non-path-sensitive
+ /// manner.
+ ///
+ /// If \p E is not a constant or cannot be modeled, returns \c None.
+ Optional<SVal> getConstantVal(const Expr *E);
+
+ NonLoc makeCompoundVal(QualType type, llvm::ImmutableList<SVal> vals) {
+ return nonloc::CompoundVal(BasicVals.getCompoundValData(type, vals));
+ }
+
+ NonLoc makeLazyCompoundVal(const StoreRef &store,
+ const TypedValueRegion *region) {
+ return nonloc::LazyCompoundVal(
+ BasicVals.getLazyCompoundValData(store, region));
+ }
+
+ NonLoc makeZeroArrayIndex() {
+ return nonloc::ConcreteInt(BasicVals.getValue(0, ArrayIndexTy));
+ }
+
+ NonLoc makeArrayIndex(uint64_t idx) {
+ return nonloc::ConcreteInt(BasicVals.getValue(idx, ArrayIndexTy));
+ }
+
+ SVal convertToArrayIndex(SVal val);
+
+ nonloc::ConcreteInt makeIntVal(const IntegerLiteral* integer) {
+ return nonloc::ConcreteInt(
+ BasicVals.getValue(integer->getValue(),
+ integer->getType()->isUnsignedIntegerOrEnumerationType()));
+ }
+
+ nonloc::ConcreteInt makeBoolVal(const ObjCBoolLiteralExpr *boolean) {
+ return makeTruthVal(boolean->getValue(), boolean->getType());
+ }
+
+ nonloc::ConcreteInt makeBoolVal(const CXXBoolLiteralExpr *boolean);
+
+ nonloc::ConcreteInt makeIntVal(const llvm::APSInt& integer) {
+ return nonloc::ConcreteInt(BasicVals.getValue(integer));
+ }
+
+ loc::ConcreteInt makeIntLocVal(const llvm::APSInt &integer) {
+ return loc::ConcreteInt(BasicVals.getValue(integer));
+ }
+
+ NonLoc makeIntVal(const llvm::APInt& integer, bool isUnsigned) {
+ return nonloc::ConcreteInt(BasicVals.getValue(integer, isUnsigned));
+ }
+
+ DefinedSVal makeIntVal(uint64_t integer, QualType type) {
+ if (Loc::isLocType(type))
+ return loc::ConcreteInt(BasicVals.getValue(integer, type));
+
+ return nonloc::ConcreteInt(BasicVals.getValue(integer, type));
+ }
+
+ NonLoc makeIntVal(uint64_t integer, bool isUnsigned) {
+ return nonloc::ConcreteInt(BasicVals.getIntValue(integer, isUnsigned));
+ }
+
+ NonLoc makeIntValWithPtrWidth(uint64_t integer, bool isUnsigned) {
+ return nonloc::ConcreteInt(
+ BasicVals.getIntWithPtrWidth(integer, isUnsigned));
+ }
+
+ NonLoc makeLocAsInteger(Loc loc, unsigned bits) {
+ return nonloc::LocAsInteger(BasicVals.getPersistentSValWithData(loc, bits));
+ }
+
+ NonLoc makeNonLoc(const SymExpr *lhs, BinaryOperator::Opcode op,
+ const llvm::APSInt& rhs, QualType type);
+
+ NonLoc makeNonLoc(const llvm::APSInt& rhs, BinaryOperator::Opcode op,
+ const SymExpr *lhs, QualType type);
+
+ NonLoc makeNonLoc(const SymExpr *lhs, BinaryOperator::Opcode op,
+ const SymExpr *rhs, QualType type);
+
+ /// \brief Create a NonLoc value for cast.
+ NonLoc makeNonLoc(const SymExpr *operand, QualType fromTy, QualType toTy);
+
+ nonloc::ConcreteInt makeTruthVal(bool b, QualType type) {
+ return nonloc::ConcreteInt(BasicVals.getTruthValue(b, type));
+ }
+
+ 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* region) {
+ return loc::MemRegionVal(region);
+ }
+
+ Loc makeLoc(const AddrLabelExpr *expr) {
+ return loc::GotoLabel(expr->getLabel());
+ }
+
+ Loc makeLoc(const llvm::APSInt& integer) {
+ return loc::ConcreteInt(BasicVals.getValue(integer));
+ }
+
+ /// Return a memory region for the 'this' object reference.
+ loc::MemRegionVal getCXXThis(const CXXMethodDecl *D,
+ const StackFrameContext *SFC);
+
+ /// Return a memory region for the 'this' object reference.
+ loc::MemRegionVal getCXXThis(const CXXRecordDecl *D,
+ const StackFrameContext *SFC);
+};
+
+SValBuilder* createSimpleSValBuilder(llvm::BumpPtrAllocator &alloc,
+ ASTContext &context,
+ ProgramStateManager &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..642e11a
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/SVals.h
@@ -0,0 +1,574 @@
+//== 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_STATICANALYZER_CORE_PATHSENSITIVE_SVALS_H
+#define LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_SVALS_H
+
+#include "clang/Basic/LLVM.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState_Fwd.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.h"
+#include "llvm/ADT/ImmutableList.h"
+
+//==------------------------------------------------------------------------==//
+// Base SVal types.
+//==------------------------------------------------------------------------==//
+
+namespace clang {
+
+namespace ento {
+
+class CompoundValData;
+class LazyCompoundValData;
+class ProgramState;
+class BasicValueFactory;
+class MemRegion;
+class TypedValueRegion;
+class MemRegionManager;
+class ProgramStateManager;
+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 = nullptr)
+ : Data(D), Kind(k) {}
+
+public:
+ explicit SVal() : Data(nullptr), Kind(0) {}
+
+ /// \brief Convert to the specified SVal type, asserting that this SVal is of
+ /// the desired type.
+ template<typename T>
+ T castAs() const {
+ assert(T::isKind(*this));
+ T t;
+ SVal& sv = t;
+ sv = *this;
+ return t;
+ }
+
+ /// \brief Convert to the specified SVal type, returning None if this SVal is
+ /// not of the desired type.
+ template<typename T>
+ Optional<T> getAs() const {
+ if (!T::isKind(*this))
+ return None;
+ T t;
+ SVal& sv = t;
+ sv = *this;
+ return t;
+ }
+
+ /// BufferTy - A temporary buffer to hold a set of SVals.
+ typedef 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;
+
+ /// \brief If this SVal is a location and wraps a symbol, return that
+ /// SymbolRef. Otherwise return 0.
+ ///
+ /// Casts are ignored during lookup.
+ /// \param IncludeBaseRegions The boolean that controls whether the search
+ /// should continue to the base regions if the region is not symbolic.
+ SymbolRef getAsLocSymbol(bool IncludeBaseRegions = false) const;
+
+ /// Get the symbol in the SVal or its base region.
+ SymbolRef getLocSymbolInBase() const;
+
+ /// \brief If this SVal wraps a symbol return that SymbolRef.
+ /// Otherwise, return 0.
+ ///
+ /// Casts are ignored during lookup.
+ /// \param IncludeBaseRegions The boolean that controls whether the search
+ /// should continue to the base regions if the region is not symbolic.
+ SymbolRef getAsSymbol(bool IncludeBaseRegions = false) const;
+
+ /// getAsSymbolicExpression - If this Sval wraps a symbolic expression then
+ /// return that expression. Otherwise return NULL.
+ const SymExpr *getAsSymbolicExpression() const;
+
+ const SymExpr* getAsSymExpr() const;
+
+ const MemRegion *getAsRegion() const;
+
+ void dumpToStream(raw_ostream &OS) const;
+ void dump() const;
+
+ SymExpr::symbol_iterator symbol_begin() const {
+ const SymExpr *SE = getAsSymbolicExpression();
+ if (SE)
+ return SE->symbol_begin();
+ else
+ return SymExpr::symbol_iterator();
+ }
+
+ SymExpr::symbol_iterator symbol_end() const {
+ return SymExpr::symbol_end();
+ }
+};
+
+
+class UndefinedVal : public SVal {
+public:
+ UndefinedVal() : SVal(UndefinedKind) {}
+
+private:
+ friend class SVal;
+ static bool isKind(const SVal& V) {
+ return V.getBaseKind() == UndefinedKind;
+ }
+};
+
+class DefinedOrUnknownSVal : public SVal {
+private:
+ // We want calling these methods to be a compiler error since they are
+ // tautologically false.
+ bool isUndef() const = delete;
+ bool isValid() const = delete;
+
+protected:
+ DefinedOrUnknownSVal() {}
+ explicit DefinedOrUnknownSVal(const void *d, bool isLoc, unsigned ValKind)
+ : SVal(d, isLoc, ValKind) {}
+
+ explicit DefinedOrUnknownSVal(BaseKind k, void *D = nullptr)
+ : SVal(k, D) {}
+
+private:
+ friend class SVal;
+ static bool isKind(const SVal& V) {
+ return !V.isUndef();
+ }
+};
+
+class UnknownVal : public DefinedOrUnknownSVal {
+public:
+ explicit UnknownVal() : DefinedOrUnknownSVal(UnknownKind) {}
+
+private:
+ friend class SVal;
+ static bool isKind(const SVal &V) {
+ return V.getBaseKind() == UnknownKind;
+ }
+};
+
+class DefinedSVal : public DefinedOrUnknownSVal {
+private:
+ // We want calling these methods to be a compiler error since they are
+ // tautologically true/false.
+ bool isUnknown() const = delete;
+ bool isUnknownOrUndef() const = delete;
+ bool isValid() const = delete;
+protected:
+ DefinedSVal() {}
+ explicit DefinedSVal(const void *d, bool isLoc, unsigned ValKind)
+ : DefinedOrUnknownSVal(d, isLoc, ValKind) {}
+private:
+ friend class SVal;
+ static bool isKind(const SVal& V) {
+ return !V.isUnknownOrUndef();
+ }
+};
+
+
+/// \brief Represents an SVal that is guaranteed to not be UnknownVal.
+class KnownSVal : public SVal {
+ KnownSVal() {}
+ friend class SVal;
+ static bool isKind(const SVal &V) {
+ return !V.isUnknown();
+ }
+public:
+ KnownSVal(const DefinedSVal &V) : SVal(V) {}
+ KnownSVal(const UndefinedVal &V) : SVal(V) {}
+};
+
+class NonLoc : public DefinedSVal {
+protected:
+ NonLoc() {}
+ explicit NonLoc(unsigned SubKind, const void *d)
+ : DefinedSVal(d, false, SubKind) {}
+
+public:
+ void dumpToStream(raw_ostream &Out) const;
+
+private:
+ friend class SVal;
+ static bool isKind(const SVal& V) {
+ return V.getBaseKind() == NonLocKind;
+ }
+};
+
+class Loc : public DefinedSVal {
+protected:
+ Loc() {}
+ explicit Loc(unsigned SubKind, const void *D)
+ : DefinedSVal(const_cast<void*>(D), true, SubKind) {}
+
+public:
+ void dumpToStream(raw_ostream &Out) const;
+
+ static inline bool isLocType(QualType T) {
+ return T->isAnyPointerType() || T->isBlockPointerType() ||
+ T->isReferenceType() || T->isNullPtrType();
+ }
+
+private:
+ friend class SVal;
+ static bool isKind(const SVal& V) {
+ return V.getBaseKind() == LocKind;
+ }
+};
+
+//==------------------------------------------------------------------------==//
+// Subclasses of NonLoc.
+//==------------------------------------------------------------------------==//
+
+namespace nonloc {
+
+enum Kind { ConcreteIntKind, SymbolValKind,
+ LocAsIntegerKind, CompoundValKind, LazyCompoundValKind };
+
+/// \brief Represents symbolic expression.
+class SymbolVal : public NonLoc {
+public:
+ SymbolVal(SymbolRef sym) : NonLoc(SymbolValKind, sym) {}
+
+ SymbolRef getSymbol() const {
+ return (const SymExpr*) Data;
+ }
+
+ bool isExpression() const {
+ return !isa<SymbolData>(getSymbol());
+ }
+
+private:
+ friend class SVal;
+ SymbolVal() {}
+ static bool isKind(const SVal& V) {
+ return V.getBaseKind() == NonLocKind &&
+ V.getSubKind() == SymbolValKind;
+ }
+
+ static bool isKind(const NonLoc& V) {
+ return V.getSubKind() == SymbolValKind;
+ }
+};
+
+/// \brief Value representing integer constant.
+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;
+
+private:
+ friend class SVal;
+ ConcreteInt() {}
+ static bool isKind(const SVal& V) {
+ return V.getBaseKind() == NonLocKind &&
+ V.getSubKind() == ConcreteIntKind;
+ }
+
+ static bool isKind(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 (data.first.getAs<Loc>());
+ }
+
+public:
+
+ Loc getLoc() const {
+ const std::pair<SVal, uintptr_t> *D =
+ static_cast<const std::pair<SVal, uintptr_t> *>(Data);
+ return D->first.castAs<Loc>();
+ }
+
+ Loc getPersistentLoc() const {
+ const std::pair<SVal, uintptr_t> *D =
+ static_cast<const std::pair<SVal, uintptr_t> *>(Data);
+ const SVal& V = D->first;
+ return V.castAs<Loc>();
+ }
+
+ unsigned getNumBits() const {
+ const std::pair<SVal, uintptr_t> *D =
+ static_cast<const std::pair<SVal, uintptr_t> *>(Data);
+ return D->second;
+ }
+
+private:
+ friend class SVal;
+ LocAsInteger() {}
+ static bool isKind(const SVal& V) {
+ return V.getBaseKind() == NonLocKind &&
+ V.getSubKind() == LocAsIntegerKind;
+ }
+
+ static bool isKind(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;
+
+private:
+ friend class SVal;
+ CompoundVal() {}
+ static bool isKind(const SVal& V) {
+ return V.getBaseKind() == NonLocKind && V.getSubKind() == CompoundValKind;
+ }
+
+ static bool isKind(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 TypedValueRegion *getRegion() const;
+
+private:
+ friend class SVal;
+ LazyCompoundVal() {}
+ static bool isKind(const SVal& V) {
+ return V.getBaseKind() == NonLocKind &&
+ V.getSubKind() == LazyCompoundValKind;
+ }
+ static bool isKind(const NonLoc& V) {
+ return V.getSubKind() == LazyCompoundValKind;
+ }
+};
+
+} // end namespace ento::nonloc
+
+//==------------------------------------------------------------------------==//
+// Subclasses of Loc.
+//==------------------------------------------------------------------------==//
+
+namespace loc {
+
+enum Kind { GotoLabelKind, MemRegionKind, ConcreteIntKind };
+
+class GotoLabel : public Loc {
+public:
+ explicit GotoLabel(LabelDecl *Label) : Loc(GotoLabelKind, Label) {}
+
+ const LabelDecl *getLabel() const {
+ return static_cast<const LabelDecl*>(Data);
+ }
+
+private:
+ friend class SVal;
+ GotoLabel() {}
+ static bool isKind(const SVal& V) {
+ return V.getBaseKind() == LocKind && V.getSubKind() == GotoLabelKind;
+ }
+
+ static bool isKind(const Loc& V) {
+ return V.getSubKind() == GotoLabelKind;
+ }
+};
+
+
+class MemRegionVal : public Loc {
+public:
+ explicit MemRegionVal(const MemRegion* r) : Loc(MemRegionKind, r) {}
+
+ /// \brief Get the underlining region.
+ const MemRegion* getRegion() const {
+ return static_cast<const MemRegion*>(Data);
+ }
+
+ /// \brief Get the underlining region and strip casts.
+ const MemRegion* stripCasts(bool StripBaseCasts = true) const;
+
+ template <typename REGION>
+ const REGION* getRegionAs() const {
+ return 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();
+ }
+
+private:
+ friend class SVal;
+ MemRegionVal() {}
+ static bool isKind(const SVal& V) {
+ return V.getBaseKind() == LocKind &&
+ V.getSubKind() == MemRegionKind;
+ }
+
+ static bool isKind(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;
+
+private:
+ friend class SVal;
+ ConcreteInt() {}
+ static bool isKind(const SVal& V) {
+ return V.getBaseKind() == LocKind &&
+ V.getSubKind() == ConcreteIntKind;
+ }
+
+ static bool isKind(const Loc& V) {
+ return V.getSubKind() == ConcreteIntKind;
+ }
+};
+
+} // end ento::loc namespace
+
+} // end ento namespace
+
+} // end clang namespace
+
+namespace llvm {
+static inline raw_ostream &operator<<(raw_ostream &os,
+ clang::ento::SVal V) {
+ V.dumpToStream(os);
+ return os;
+}
+
+template <typename T> struct isPodLike;
+template <> struct isPodLike<clang::ento::SVal> {
+ static const bool value = true;
+};
+
+} // 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..a03b630
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/Store.h
@@ -0,0 +1,288 @@
+//== 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_STATICANALYZER_CORE_PATHSENSITIVE_STORE_H
+#define LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_STORE_H
+
+#include "clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/SValBuilder.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/StoreRef.h"
+#include "llvm/ADT/DenseSet.h"
+#include "llvm/ADT/Optional.h"
+
+namespace clang {
+
+class Stmt;
+class Expr;
+class ObjCIvarDecl;
+class CXXBasePath;
+class StackFrameContext;
+
+namespace ento {
+
+class CallEvent;
+class ProgramState;
+class ProgramStateManager;
+class ScanReachableSymbols;
+
+typedef llvm::DenseSet<SymbolRef> InvalidatedSymbols;
+
+class StoreManager {
+protected:
+ SValBuilder &svalBuilder;
+ ProgramStateManager &StateMgr;
+
+ /// MRMgr - Manages region objects associated with this StoreManager.
+ MemRegionManager &MRMgr;
+ ASTContext &Ctx;
+
+ StoreManager(ProgramStateManager &stateMgr);
+
+public:
+ virtual ~StoreManager() {}
+
+ /// Return the value bound to specified location in a given state.
+ /// \param[in] store 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 getBinding(Store store, Loc loc, QualType T = QualType()) = 0;
+
+ /// Return a state with the specified value bound to the given location.
+ /// \param[in] store 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 ProgramState 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);
+
+ /// \brief Create a new store with the specified binding removed.
+ /// \param ST the original store, that is the basis for the new store.
+ /// \param L the location whose binding should be removed.
+ virtual StoreRef killBinding(Store ST, Loc L) = 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; }
+
+ virtual Loc getLValueVar(const VarDecl *VD, const LocationContext *LC) {
+ return svalBuilder.makeLoc(MRMgr.getVarRegion(VD, LC));
+ }
+
+ Loc getLValueCompoundLiteral(const CompoundLiteralExpr *CL,
+ const LocationContext *LC) {
+ return loc::MemRegionVal(MRMgr.getCompoundLiteralRegion(CL, LC));
+ }
+
+ virtual SVal getLValueIvar(const ObjCIvarDecl *decl, SVal 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(ProgramStateRef 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, QualType ElementTy) = 0;
+
+ /// Evaluates a chain of derived-to-base casts through the path specified in
+ /// \p Cast.
+ SVal evalDerivedToBase(SVal Derived, const CastExpr *Cast);
+
+ /// Evaluates a chain of derived-to-base casts through the specified path.
+ SVal evalDerivedToBase(SVal Derived, const CXXBasePath &CastPath);
+
+ /// Evaluates a derived-to-base cast through a single level of derivation.
+ SVal evalDerivedToBase(SVal Derived, QualType DerivedPtrType,
+ bool IsVirtual);
+
+ /// \brief Evaluates C++ dynamic_cast cast.
+ /// The callback may result in the following 3 scenarios:
+ /// - Successful cast (ex: derived is subclass of base).
+ /// - Failed cast (ex: derived is definitely not a subclass of base).
+ /// - We don't know (base is a symbolic region and we don't have
+ /// enough info to determine if the cast will succeed at run time).
+ /// The function returns an SVal representing the derived class; it's
+ /// valid only if Failed flag is set to false.
+ SVal evalDynamicCast(SVal Base, QualType DerivedPtrType, bool &Failed);
+
+ 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) = 0;
+
+ virtual bool includedInBindings(Store store,
+ const MemRegion *region) const = 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 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] Values The values 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] Call The call expression which will be used to determine which
+ /// globals should get invalidated.
+ /// \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] ITraits Information about invalidation for a particular
+ /// region/symbol.
+ /// \param[in,out] InvalidatedTopLevel A vector to fill with regions
+ //// explicitly being invalidated. Pass \c NULL if this
+ /// information will not be used.
+ /// \param[in,out] Invalidated 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,
+ ArrayRef<SVal> Values,
+ const Expr *E, unsigned Count,
+ const LocationContext *LCtx,
+ const CallEvent *Call,
+ InvalidatedSymbols &IS,
+ RegionAndSymbolInvalidationTraits &ITraits,
+ InvalidatedRegions *InvalidatedTopLevel,
+ InvalidatedRegions *Invalidated) = 0;
+
+ /// enterStackFrame - Let the StoreManager to do something when execution
+ /// engine is about to execute into a callee.
+ StoreRef enterStackFrame(Store store,
+ const CallEvent &Call,
+ const StackFrameContext *CalleeCtx);
+
+ /// Finds the transitive closure of symbols within the given region.
+ ///
+ /// Returns false if the visitor aborted the scan.
+ virtual bool scanReachableSymbols(Store S, const MemRegion *R,
+ ScanReachableSymbols &Visitor) = 0;
+
+ virtual void print(Store store, 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;
+ };
+
+ class FindUniqueBinding :
+ public BindingsHandler {
+ SymbolRef Sym;
+ const MemRegion* Binding;
+ bool First;
+
+ public:
+ FindUniqueBinding(SymbolRef sym)
+ : Sym(sym), Binding(nullptr), First(true) {}
+
+ bool HandleBinding(StoreManager& SMgr, Store store, const MemRegion* R,
+ SVal val) override;
+ explicit operator bool() { return First && Binding; }
+ const MemRegion *getRegion() { return Binding; }
+ };
+
+ /// 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 TypedValueRegion *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 need to pass ProgramStateManager anymore?
+std::unique_ptr<StoreManager>
+CreateRegionStoreManager(ProgramStateManager &StMgr);
+std::unique_ptr<StoreManager>
+CreateFieldsOnlyRegionStoreManager(ProgramStateManager &StMgr);
+
+} // end GR namespace
+
+} // end clang namespace
+
+#endif
diff --git a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/StoreRef.h b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/StoreRef.h
new file mode 100644
index 0000000..958c8c3
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/StoreRef.h
@@ -0,0 +1,51 @@
+//== StoreRef.h - Smart pointer for store objects ---------------*- 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 type StoreRef.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_STOREREF_H
+#define LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_STOREREF_H
+
+#include <cassert>
+
+namespace clang {
+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 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; }
+ const StoreManager &getStoreManager() const { return mgr; }
+};
+
+}}
+#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..741ba0e
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/SubEngine.h
@@ -0,0 +1,162 @@
+//== 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_STATICANALYZER_CORE_PATHSENSITIVE_SUBENGINE_H
+#define LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_SUBENGINE_H
+
+#include "clang/Analysis/ProgramPoint.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/SVals.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/Store.h"
+
+namespace clang {
+
+class CFGBlock;
+class CFGElement;
+class LocationContext;
+class Stmt;
+
+namespace ento {
+
+struct NodeBuilderContext;
+class AnalysisManager;
+class ExplodedNodeSet;
+class ExplodedNode;
+class ProgramState;
+class ProgramStateManager;
+class BlockCounter;
+class BranchNodeBuilder;
+class IndirectGotoNodeBuilder;
+class SwitchNodeBuilder;
+class EndOfFunctionNodeBuilder;
+class NodeBuilderWithSinks;
+class MemRegion;
+
+class SubEngine {
+ virtual void anchor();
+public:
+ virtual ~SubEngine() {}
+
+ virtual ProgramStateRef getInitialState(const LocationContext *InitLoc) = 0;
+
+ virtual AnalysisManager &getAnalysisManager() = 0;
+
+ virtual ProgramStateManager &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, ExplodedNode* Pred,
+ unsigned StmtIdx, NodeBuilderContext *Ctx)=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(const BlockEdge &L,
+ NodeBuilderWithSinks &nodeBuilder,
+ ExplodedNode *Pred) = 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,
+ NodeBuilderContext& BuilderCtx,
+ ExplodedNode *Pred,
+ ExplodedNodeSet &Dst,
+ const CFGBlock *DstT,
+ const CFGBlock *DstF) = 0;
+
+ /// Called by CoreEngine.
+ /// Used to generate successor nodes for temporary destructors depending
+ /// on whether the corresponding constructor was visited.
+ virtual void processCleanupTemporaryBranch(const CXXBindTemporaryExpr *BTE,
+ NodeBuilderContext &BldCtx,
+ ExplodedNode *Pred,
+ ExplodedNodeSet &Dst,
+ const CFGBlock *DstT,
+ const CFGBlock *DstF) = 0;
+
+ /// Called by CoreEngine. Used to processing branching behavior
+ /// at static initalizers.
+ virtual void processStaticInitializer(const DeclStmt *DS,
+ NodeBuilderContext& BuilderCtx,
+ ExplodedNode *Pred,
+ ExplodedNodeSet &Dst,
+ const CFGBlock *DstT,
+ const CFGBlock *DstF) = 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(NodeBuilderContext& BC,
+ ExplodedNode *Pred) = 0;
+
+ // Generate the entry node of the callee.
+ virtual void processCallEnter(CallEnter CE, ExplodedNode *Pred) = 0;
+
+ // Generate the first post callsite node.
+ virtual void processCallExit(ExplodedNode *Pred) = 0;
+
+ /// Called by ConstraintManager. Used to call checker-specific
+ /// logic for handling assumptions on symbolic values.
+ virtual ProgramStateRef processAssume(ProgramStateRef state,
+ SVal cond, bool assumption) = 0;
+
+ /// wantsRegionChangeUpdate - Called by ProgramStateManager to determine if a
+ /// region change should trigger a processRegionChanges update.
+ virtual bool wantsRegionChangeUpdate(ProgramStateRef state) = 0;
+
+ /// processRegionChanges - Called by ProgramStateManager whenever a change is
+ /// made to the store. Used to update checkers that track region values.
+ virtual ProgramStateRef
+ processRegionChanges(ProgramStateRef state,
+ const InvalidatedSymbols *invalidated,
+ ArrayRef<const MemRegion *> ExplicitRegions,
+ ArrayRef<const MemRegion *> Regions,
+ const CallEvent *Call) = 0;
+
+
+ inline ProgramStateRef
+ processRegionChange(ProgramStateRef state,
+ const MemRegion* MR) {
+ return processRegionChanges(state, nullptr, MR, MR, nullptr);
+ }
+
+ virtual ProgramStateRef
+ processPointerEscapedOnBind(ProgramStateRef State, SVal Loc, SVal Val) = 0;
+
+ virtual ProgramStateRef
+ notifyCheckersOfPointerEscape(ProgramStateRef State,
+ const InvalidatedSymbols *Invalidated,
+ ArrayRef<const MemRegion *> ExplicitRegions,
+ ArrayRef<const MemRegion *> Regions,
+ const CallEvent *Call,
+ RegionAndSymbolInvalidationTraits &HTraits) = 0;
+
+ /// printState - Called by ProgramStateManager to print checker-specific data.
+ virtual void printState(raw_ostream &Out, ProgramStateRef State,
+ const char *NL, const char *Sep) = 0;
+
+ /// 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..9dbfab2
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.h
@@ -0,0 +1,681 @@
+//== 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_STATICANALYZER_CORE_PATHSENSITIVE_SYMBOLMANAGER_H
+#define LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_SYMBOLMANAGER_H
+
+#include "clang/AST/Decl.h"
+#include "clang/AST/Expr.h"
+#include "clang/Analysis/AnalysisContext.h"
+#include "clang/Basic/LLVM.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/StoreRef.h"
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/DenseSet.h"
+#include "llvm/ADT/FoldingSet.h"
+#include "llvm/Support/Allocator.h"
+#include "llvm/Support/DataTypes.h"
+
+namespace clang {
+ class ASTContext;
+ class StackFrameContext;
+
+namespace ento {
+ class BasicValueFactory;
+ class MemRegion;
+ class SubRegion;
+ class TypedValueRegion;
+ class VarRegion;
+
+/// \brief Symbolic value. These values used to capture symbolic execution of
+/// the program.
+class SymExpr : public llvm::FoldingSetNode {
+ virtual void anchor();
+public:
+ enum Kind { RegionValueKind, ConjuredKind, DerivedKind, ExtentKind,
+ MetadataKind,
+ BEGIN_SYMBOLS = RegionValueKind,
+ END_SYMBOLS = MetadataKind,
+ SymIntKind, IntSymKind, SymSymKind,
+ BEGIN_BINARYSYMEXPRS = SymIntKind,
+ END_BINARYSYMEXPRS = SymSymKind,
+ CastSymbolKind };
+private:
+ Kind K;
+
+protected:
+ SymExpr(Kind k) : K(k) {}
+
+public:
+ virtual ~SymExpr() {}
+
+ Kind getKind() const { return K; }
+
+ virtual void dump() const;
+
+ virtual void dumpToStream(raw_ostream &os) const {}
+
+ virtual QualType getType() const = 0;
+ virtual void Profile(llvm::FoldingSetNodeID& profile) = 0;
+
+ /// \brief Iterator over symbols that the current symbol depends on.
+ ///
+ /// For SymbolData, it's the symbol itself; for expressions, it's the
+ /// expression symbol and all the operands in it. Note, SymbolDerived is
+ /// treated as SymbolData - the iterator will NOT visit the parent region.
+ class symbol_iterator {
+ SmallVector<const SymExpr*, 5> itr;
+ void expand();
+ public:
+ symbol_iterator() {}
+ symbol_iterator(const SymExpr *SE);
+
+ symbol_iterator &operator++();
+ const SymExpr* operator*();
+
+ bool operator==(const symbol_iterator &X) const;
+ bool operator!=(const symbol_iterator &X) const;
+ };
+
+ symbol_iterator symbol_begin() const {
+ return symbol_iterator(this);
+ }
+ static symbol_iterator symbol_end() { return symbol_iterator(); }
+
+ unsigned computeComplexity() const;
+};
+
+typedef const SymExpr* SymbolRef;
+typedef SmallVector<SymbolRef, 2> SymbolRefSmallVectorTy;
+
+typedef unsigned SymbolID;
+/// \brief A symbol representing data which can be stored in a memory location
+/// (region).
+class SymbolData : public SymExpr {
+ void anchor() override;
+ const SymbolID Sym;
+
+protected:
+ SymbolData(Kind k, SymbolID sym) : SymExpr(k), Sym(sym) {}
+
+public:
+ ~SymbolData() override {}
+
+ 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;
+ }
+};
+
+///\brief A symbol representing the value stored at a MemRegion.
+class SymbolRegionValue : public SymbolData {
+ const TypedValueRegion *R;
+
+public:
+ SymbolRegionValue(SymbolID sym, const TypedValueRegion *r)
+ : SymbolData(RegionValueKind, sym), R(r) {}
+
+ const TypedValueRegion* getRegion() const { return R; }
+
+ static void Profile(llvm::FoldingSetNodeID& profile, const TypedValueRegion* R) {
+ profile.AddInteger((unsigned) RegionValueKind);
+ profile.AddPointer(R);
+ }
+
+ void Profile(llvm::FoldingSetNodeID& profile) override {
+ Profile(profile, R);
+ }
+
+ void dumpToStream(raw_ostream &os) const override;
+
+ QualType getType() const override;
+
+ // Implement isa<T> support.
+ static inline bool classof(const SymExpr *SE) {
+ return SE->getKind() == RegionValueKind;
+ }
+};
+
+/// A symbol representing the result of an expression in the case when we do
+/// not know anything about what the expression is.
+class SymbolConjured : public SymbolData {
+ const Stmt *S;
+ QualType T;
+ unsigned Count;
+ const LocationContext *LCtx;
+ const void *SymbolTag;
+
+public:
+ SymbolConjured(SymbolID sym, const Stmt *s, const LocationContext *lctx,
+ QualType t, unsigned count,
+ const void *symbolTag)
+ : SymbolData(ConjuredKind, sym), S(s), T(t), Count(count),
+ LCtx(lctx),
+ SymbolTag(symbolTag) {}
+
+ const Stmt *getStmt() const { return S; }
+ unsigned getCount() const { return Count; }
+ const void *getTag() const { return SymbolTag; }
+
+ QualType getType() const override;
+
+ void dumpToStream(raw_ostream &os) const override;
+
+ static void Profile(llvm::FoldingSetNodeID& profile, const Stmt *S,
+ QualType T, unsigned Count, const LocationContext *LCtx,
+ const void *SymbolTag) {
+ profile.AddInteger((unsigned) ConjuredKind);
+ profile.AddPointer(S);
+ profile.AddPointer(LCtx);
+ profile.Add(T);
+ profile.AddInteger(Count);
+ profile.AddPointer(SymbolTag);
+ }
+
+ void Profile(llvm::FoldingSetNodeID& profile) override {
+ Profile(profile, S, T, Count, LCtx, 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 TypedValueRegion *R;
+
+public:
+ SymbolDerived(SymbolID sym, SymbolRef parent, const TypedValueRegion *r)
+ : SymbolData(DerivedKind, sym), parentSymbol(parent), R(r) {}
+
+ SymbolRef getParentSymbol() const { return parentSymbol; }
+ const TypedValueRegion *getRegion() const { return R; }
+
+ QualType getType() const override;
+
+ void dumpToStream(raw_ostream &os) const override;
+
+ static void Profile(llvm::FoldingSetNodeID& profile, SymbolRef parent,
+ const TypedValueRegion *r) {
+ profile.AddInteger((unsigned) DerivedKind);
+ profile.AddPointer(r);
+ profile.AddPointer(parent);
+ }
+
+ void Profile(llvm::FoldingSetNodeID& profile) override {
+ 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() const override;
+
+ void dumpToStream(raw_ostream &os) const override;
+
+ static void Profile(llvm::FoldingSetNodeID& profile, const SubRegion *R) {
+ profile.AddInteger((unsigned) ExtentKind);
+ profile.AddPointer(R);
+ }
+
+ void Profile(llvm::FoldingSetNodeID& profile) override {
+ 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() const override;
+
+ void dumpToStream(raw_ostream &os) const override;
+
+ 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);
+ }
+
+ void Profile(llvm::FoldingSetNodeID& profile) override {
+ Profile(profile, R, S, T, Count, Tag);
+ }
+
+ // Implement isa<T> support.
+ static inline bool classof(const SymExpr *SE) {
+ return SE->getKind() == MetadataKind;
+ }
+};
+
+/// \brief Represents a cast expression.
+class SymbolCast : public SymExpr {
+ const SymExpr *Operand;
+ /// Type of the operand.
+ QualType FromTy;
+ /// The type of the result.
+ QualType ToTy;
+
+public:
+ SymbolCast(const SymExpr *In, QualType From, QualType To) :
+ SymExpr(CastSymbolKind), Operand(In), FromTy(From), ToTy(To) { }
+
+ QualType getType() const override { return ToTy; }
+
+ const SymExpr *getOperand() const { return Operand; }
+
+ void dumpToStream(raw_ostream &os) const override;
+
+ static void Profile(llvm::FoldingSetNodeID& ID,
+ const SymExpr *In, QualType From, QualType To) {
+ ID.AddInteger((unsigned) CastSymbolKind);
+ ID.AddPointer(In);
+ ID.Add(From);
+ ID.Add(To);
+ }
+
+ void Profile(llvm::FoldingSetNodeID& ID) override {
+ Profile(ID, Operand, FromTy, ToTy);
+ }
+
+ // Implement isa<T> support.
+ static inline bool classof(const SymExpr *SE) {
+ return SE->getKind() == CastSymbolKind;
+ }
+};
+
+/// \brief Represents a symbolic expression involving a binary operator
+class BinarySymExpr : public SymExpr {
+ BinaryOperator::Opcode Op;
+ QualType T;
+
+protected:
+ BinarySymExpr(Kind k, BinaryOperator::Opcode op, QualType t)
+ : SymExpr(k), Op(op), T(t) {}
+
+public:
+ // FIXME: We probably need to make this out-of-line to avoid redundant
+ // generation of virtual functions.
+ QualType getType() const override { return T; }
+
+ BinaryOperator::Opcode getOpcode() const { return Op; }
+
+ // Implement isa<T> support.
+ static inline bool classof(const SymExpr *SE) {
+ Kind k = SE->getKind();
+ return k >= BEGIN_BINARYSYMEXPRS && k <= END_BINARYSYMEXPRS;
+ }
+};
+
+/// \brief Represents a symbolic expression like 'x' + 3.
+class SymIntExpr : public BinarySymExpr {
+ const SymExpr *LHS;
+ const llvm::APSInt& RHS;
+
+public:
+ SymIntExpr(const SymExpr *lhs, BinaryOperator::Opcode op,
+ const llvm::APSInt& rhs, QualType t)
+ : BinarySymExpr(SymIntKind, op, t), LHS(lhs), RHS(rhs) {}
+
+ void dumpToStream(raw_ostream &os) const override;
+
+ 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) override {
+ Profile(ID, LHS, getOpcode(), RHS, getType());
+ }
+
+ // Implement isa<T> support.
+ static inline bool classof(const SymExpr *SE) {
+ return SE->getKind() == SymIntKind;
+ }
+};
+
+/// \brief Represents a symbolic expression like 3 - 'x'.
+class IntSymExpr : public BinarySymExpr {
+ const llvm::APSInt& LHS;
+ const SymExpr *RHS;
+
+public:
+ IntSymExpr(const llvm::APSInt& lhs, BinaryOperator::Opcode op,
+ const SymExpr *rhs, QualType t)
+ : BinarySymExpr(IntSymKind, op, t), LHS(lhs), RHS(rhs) {}
+
+ void dumpToStream(raw_ostream &os) const override;
+
+ const SymExpr *getRHS() const { return RHS; }
+ const llvm::APSInt &getLHS() const { return LHS; }
+
+ static void Profile(llvm::FoldingSetNodeID& ID, const llvm::APSInt& lhs,
+ BinaryOperator::Opcode op, const SymExpr *rhs,
+ QualType t) {
+ ID.AddInteger((unsigned) IntSymKind);
+ ID.AddPointer(&lhs);
+ ID.AddInteger(op);
+ ID.AddPointer(rhs);
+ ID.Add(t);
+ }
+
+ void Profile(llvm::FoldingSetNodeID& ID) override {
+ Profile(ID, LHS, getOpcode(), RHS, getType());
+ }
+
+ // Implement isa<T> support.
+ static inline bool classof(const SymExpr *SE) {
+ return SE->getKind() == IntSymKind;
+ }
+};
+
+/// \brief Represents a symbolic expression like 'x' + 'y'.
+class SymSymExpr : public BinarySymExpr {
+ const SymExpr *LHS;
+ const SymExpr *RHS;
+
+public:
+ SymSymExpr(const SymExpr *lhs, BinaryOperator::Opcode op, const SymExpr *rhs,
+ QualType t)
+ : BinarySymExpr(SymSymKind, op, t), LHS(lhs), RHS(rhs) {}
+
+ const SymExpr *getLHS() const { return LHS; }
+ const SymExpr *getRHS() const { return RHS; }
+
+ void dumpToStream(raw_ostream &os) const override;
+
+ 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) override {
+ Profile(ID, LHS, getOpcode(), RHS, getType());
+ }
+
+ // Implement isa<T> support.
+ static inline bool classof(const SymExpr *SE) {
+ return SE->getKind() == SymSymKind;
+ }
+};
+
+class SymbolManager {
+ typedef llvm::FoldingSet<SymExpr> DataSetTy;
+ typedef llvm::DenseMap<SymbolRef, SymbolRefSmallVectorTy*> SymbolDependTy;
+
+ DataSetTy DataSet;
+ /// Stores the extra dependencies between symbols: the data should be kept
+ /// alive as long as the key is live.
+ SymbolDependTy SymbolDependencies;
+ unsigned SymbolCounter;
+ llvm::BumpPtrAllocator& BPAlloc;
+ BasicValueFactory &BV;
+ ASTContext &Ctx;
+
+public:
+ SymbolManager(ASTContext &ctx, BasicValueFactory &bv,
+ llvm::BumpPtrAllocator& bpalloc)
+ : SymbolDependencies(16), SymbolCounter(0),
+ BPAlloc(bpalloc), BV(bv), Ctx(ctx) {}
+
+ ~SymbolManager();
+
+ static bool canSymbolicate(QualType T);
+
+ /// \brief Make a unique symbol for MemRegion R according to its kind.
+ const SymbolRegionValue* getRegionValueSymbol(const TypedValueRegion* R);
+
+ const SymbolConjured* conjureSymbol(const Stmt *E,
+ const LocationContext *LCtx,
+ QualType T,
+ unsigned VisitCount,
+ const void *SymbolTag = nullptr);
+
+ const SymbolConjured* conjureSymbol(const Expr *E,
+ const LocationContext *LCtx,
+ unsigned VisitCount,
+ const void *SymbolTag = nullptr) {
+ return conjureSymbol(E, LCtx, E->getType(), VisitCount, SymbolTag);
+ }
+
+ const SymbolDerived *getDerivedSymbol(SymbolRef parentSymbol,
+ const TypedValueRegion *R);
+
+ const SymbolExtent *getExtentSymbol(const SubRegion *R);
+
+ /// \brief Creates a metadata symbol associated with a specific region.
+ ///
+ /// VisitCount can be used to differentiate regions corresponding to
+ /// different loop iterations, thus, making the symbol path-dependent.
+ const SymbolMetadata *getMetadataSymbol(const MemRegion *R, const Stmt *S,
+ QualType T, unsigned VisitCount,
+ const void *SymbolTag = nullptr);
+
+ const SymbolCast* getCastSymbol(const SymExpr *Operand,
+ QualType From, QualType To);
+
+ 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 IntSymExpr *getIntSymExpr(const llvm::APSInt& lhs,
+ BinaryOperator::Opcode op,
+ const SymExpr *rhs, QualType t);
+
+ const SymSymExpr *getSymSymExpr(const SymExpr *lhs, BinaryOperator::Opcode op,
+ const SymExpr *rhs, QualType t);
+
+ QualType getType(const SymExpr *SE) const {
+ return SE->getType();
+ }
+
+ /// \brief Add artificial symbol dependency.
+ ///
+ /// The dependent symbol should stay alive as long as the primary is alive.
+ void addSymbolDependency(const SymbolRef Primary, const SymbolRef Dependent);
+
+ const SymbolRefSmallVectorTy *getDependentSymbols(const SymbolRef Primary);
+
+ ASTContext &getContext() { return Ctx; }
+ BasicValueFactory &getBasicVals() { return BV; }
+};
+
+/// \brief A class responsible for cleaning up unused symbols.
+class SymbolReaper {
+ enum SymbolStatus {
+ NotProcessed,
+ HaveMarkedDependents
+ };
+
+ typedef llvm::DenseSet<SymbolRef> SymbolSetTy;
+ typedef llvm::DenseMap<SymbolRef, SymbolStatus> SymbolMapTy;
+ typedef llvm::DenseSet<const MemRegion *> RegionSetTy;
+
+ SymbolMapTy TheLiving;
+ SymbolSetTy MetadataInUse;
+ SymbolSetTy TheDead;
+
+ RegionSetTy RegionRoots;
+
+ const StackFrameContext *LCtx;
+ const Stmt *Loc;
+ SymbolManager& SymMgr;
+ StoreRef reapedStore;
+ llvm::DenseMap<const MemRegion *, unsigned> includedRegionCache;
+
+public:
+ /// \brief Construct a reaper object, which removes everything which is not
+ /// live before we execute statement s in the given location context.
+ ///
+ /// If the statement is NULL, everything is this and parent contexts is
+ /// considered live.
+ /// If the stack frame context is NULL, everything on stack is considered
+ /// dead.
+ SymbolReaper(const StackFrameContext *Ctx, const Stmt *s, SymbolManager& symmgr,
+ StoreManager &storeMgr)
+ : LCtx(Ctx), Loc(s), SymMgr(symmgr),
+ reapedStore(nullptr, storeMgr) {}
+
+ const LocationContext *getLocationContext() const { return LCtx; }
+
+ bool isLive(SymbolRef sym);
+ bool isLiveRegion(const MemRegion *region);
+ bool isLive(const Stmt *ExprVal, const LocationContext *LCtx) const;
+ bool isLive(const VarRegion *VR, bool includeStoreBindings = false) const;
+
+ /// \brief 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);
+
+ /// \brief 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);
+
+ /// \brief 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 SymbolSetTy::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();
+ }
+
+ typedef RegionSetTy::const_iterator region_iterator;
+ region_iterator region_begin() const { return RegionRoots.begin(); }
+ region_iterator region_end() const { return RegionRoots.end(); }
+
+ /// \brief 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);
+ }
+
+ void markLive(const MemRegion *region);
+ void markElementIndicesLive(const MemRegion *region);
+
+ /// \brief Set to the value of the symbolic store after
+ /// StoreManager::removeDeadBindings has been called.
+ void setReapedStore(StoreRef st) { reapedStore = st; }
+
+private:
+ /// Mark the symbols dependent on the input symbol as live.
+ void markDependentsLive(SymbolRef sym);
+};
+
+class SymbolVisitor {
+protected:
+ ~SymbolVisitor() = default;
+
+public:
+ SymbolVisitor() = default;
+ SymbolVisitor(const SymbolVisitor &) = default;
+ SymbolVisitor(SymbolVisitor &&) {}
+
+ /// \brief A visitor method invoked by ProgramStateManager::scanReachableSymbols.
+ ///
+ /// The method returns \c true if symbols should continue be scanned and \c
+ /// false otherwise.
+ virtual bool VisitSymbol(SymbolRef sym) = 0;
+ virtual bool VisitMemRegion(const MemRegion *region) { return true; }
+};
+
+} // end GR namespace
+
+} // end clang namespace
+
+namespace llvm {
+static inline raw_ostream &operator<<(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/TaintManager.h b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/TaintManager.h
new file mode 100644
index 0000000..d39b501
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/TaintManager.h
@@ -0,0 +1,46 @@
+//== TaintManager.h - Managing taint --------------------------- -*- 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 APIs for adding, removing, querying symbol taint.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_TAINTMANAGER_H
+#define LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_TAINTMANAGER_H
+
+#include "clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramStateTrait.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/TaintTag.h"
+#include "llvm/ADT/ImmutableMap.h"
+
+namespace clang {
+namespace ento {
+
+/// The GDM component containing the tainted root symbols. We lazily infer the
+/// taint of the dependent symbols. Currently, this is a map from a symbol to
+/// tag kind. TODO: Should support multiple tag kinds.
+// FIXME: This does not use the nice trait macros because it must be accessible
+// from multiple translation units.
+struct TaintMap {};
+typedef llvm::ImmutableMap<SymbolRef, TaintTagType> TaintMapImpl;
+template<> struct ProgramStateTrait<TaintMap>
+ : public ProgramStatePartialTrait<TaintMapImpl> {
+ static void *GDMIndex() { static int index = 0; return &index; }
+};
+
+class TaintManager {
+
+ TaintManager() {}
+};
+
+}
+}
+
+#endif
diff --git a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/TaintTag.h b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/TaintTag.h
new file mode 100644
index 0000000..0c56e7d
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/TaintTag.h
@@ -0,0 +1,27 @@
+//== TaintTag.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.
+//
+//===----------------------------------------------------------------------===//
+//
+// Defines a set of taint tags. Several tags are used to differentiate kinds
+// of taint.
+//
+//===----------------------------------------------------------------------===//
+#ifndef LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_TAINTTAG_H
+#define LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_TAINTTAG_H
+
+namespace clang {
+namespace ento {
+
+/// The type of taint, which helps to differentiate between different types of
+/// taint.
+typedef unsigned TaintTagType;
+static const TaintTagType TaintTagGeneric = 0;
+
+}}
+
+#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..4f1a60e
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/WorkList.h
@@ -0,0 +1,100 @@
+//==- 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_STATICANALYZER_CORE_PATHSENSITIVE_WORKLIST_H
+#define LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_WORKLIST_H
+
+#include "clang/StaticAnalyzer/Core/PathSensitive/BlockCounter.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/ExplodedGraph.h"
+#include <cassert>
+
+namespace clang {
+
+class CFGBlock;
+
+namespace ento {
+
+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(nullptr),
+ 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) {
+ assert(N->getLocation().getKind() != ProgramPoint::PostStmtKind);
+ 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/AnalysisConsumer.h b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Frontend/AnalysisConsumer.h
new file mode 100644
index 0000000..37ea05f
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Frontend/AnalysisConsumer.h
@@ -0,0 +1,49 @@
+//===--- 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_STATICANALYZER_FRONTEND_ANALYSISCONSUMER_H
+#define LLVM_CLANG_STATICANALYZER_FRONTEND_ANALYSISCONSUMER_H
+
+#include "clang/AST/ASTConsumer.h"
+#include "clang/Basic/LLVM.h"
+#include "clang/StaticAnalyzer/Core/AnalyzerOptions.h"
+#include "clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h"
+#include <string>
+
+namespace clang {
+
+class Preprocessor;
+class DiagnosticsEngine;
+class CodeInjector;
+class CompilerInstance;
+
+namespace ento {
+class CheckerManager;
+
+class AnalysisASTConsumer : public ASTConsumer {
+public:
+ virtual void AddDiagnosticConsumer(PathDiagnosticConsumer *Consumer) = 0;
+};
+
+/// CreateAnalysisConsumer - Creates an ASTConsumer to run various code
+/// analysis passes. (The set of analyses run is controlled by command-line
+/// options.)
+std::unique_ptr<AnalysisASTConsumer>
+CreateAnalysisConsumer(CompilerInstance &CI);
+
+} // 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..2985b7c
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Frontend/CheckerRegistration.h
@@ -0,0 +1,33 @@
+//===-- 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_STATICANALYZER_FRONTEND_CHECKERREGISTRATION_H
+#define LLVM_CLANG_STATICANALYZER_FRONTEND_CHECKERREGISTRATION_H
+
+#include "clang/Basic/LLVM.h"
+#include <memory>
+#include <string>
+
+namespace clang {
+ class AnalyzerOptions;
+ class LangOptions;
+ class DiagnosticsEngine;
+
+namespace ento {
+ class CheckerManager;
+
+ std::unique_ptr<CheckerManager>
+ createCheckerManager(AnalyzerOptions &opts, const LangOptions &langOpts,
+ ArrayRef<std::string> plugins, DiagnosticsEngine &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..36afb4b
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Frontend/FrontendActions.h
@@ -0,0 +1,60 @@
+//===-- 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_STATICANALYZER_FRONTEND_FRONTENDACTIONS_H
+#define LLVM_CLANG_STATICANALYZER_FRONTEND_FRONTENDACTIONS_H
+
+#include "clang/Frontend/FrontendAction.h"
+#include "llvm/ADT/StringMap.h"
+#include "llvm/ADT/StringRef.h"
+
+namespace clang {
+
+class Stmt;
+
+namespace ento {
+
+//===----------------------------------------------------------------------===//
+// AST Consumer Actions
+//===----------------------------------------------------------------------===//
+
+class AnalysisAction : public ASTFrontendAction {
+protected:
+ std::unique_ptr<ASTConsumer> CreateASTConsumer(CompilerInstance &CI,
+ StringRef InFile) override;
+};
+
+/// \brief Frontend action to parse model files.
+///
+/// This frontend action is responsible for parsing model files. Model files can
+/// not be parsed on their own, they rely on type information that is available
+/// in another translation unit. The parsing of model files is done by a
+/// separate compiler instance that reuses the ASTContext and othen information
+/// from the main translation unit that is being compiled. After a model file is
+/// parsed, the function definitions will be collected into a StringMap.
+class ParseModelFileAction : public ASTFrontendAction {
+public:
+ ParseModelFileAction(llvm::StringMap<Stmt *> &Bodies);
+ bool isModelParsingAction() const override { return true; }
+
+protected:
+ std::unique_ptr<ASTConsumer> CreateASTConsumer(CompilerInstance &CI,
+ StringRef InFile) override;
+
+private:
+ llvm::StringMap<Stmt *> &Bodies;
+};
+
+void printCheckerHelp(raw_ostream &OS, ArrayRef<std::string> plugins);
+
+} // end GR namespace
+
+} // end namespace clang
+
+#endif
diff --git a/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Frontend/ModelConsumer.h b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Frontend/ModelConsumer.h
new file mode 100644
index 0000000..24f8042
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Frontend/ModelConsumer.h
@@ -0,0 +1,44 @@
+//===-- ModelConsumer.h -----------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+///
+/// \file
+/// \brief This file implements clang::ento::ModelConsumer which is an
+/// ASTConsumer for model files.
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_GR_MODELCONSUMER_H
+#define LLVM_CLANG_GR_MODELCONSUMER_H
+
+#include "clang/AST/ASTConsumer.h"
+#include "llvm/ADT/StringMap.h"
+
+namespace clang {
+
+class Stmt;
+
+namespace ento {
+
+/// \brief ASTConsumer to consume model files' AST.
+///
+/// This consumer collects the bodies of function definitions into a StringMap
+/// from a model file.
+class ModelConsumer : public ASTConsumer {
+public:
+ ModelConsumer(llvm::StringMap<Stmt *> &Bodies);
+
+ bool HandleTopLevelDecl(DeclGroupRef D) override;
+
+private:
+ llvm::StringMap<Stmt *> &Bodies;
+};
+}
+}
+
+#endif
diff --git a/contrib/llvm/tools/clang/include/clang/Tooling/ArgumentsAdjusters.h b/contrib/llvm/tools/clang/include/clang/Tooling/ArgumentsAdjusters.h
new file mode 100644
index 0000000..1fd7be6
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Tooling/ArgumentsAdjusters.h
@@ -0,0 +1,69 @@
+//===--- ArgumentsAdjusters.h - Command line arguments adjuster -*- 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 typedef ArgumentsAdjuster and functions to create several
+// useful argument adjusters.
+// ArgumentsAdjusters modify command line arguments obtained from a compilation
+// database before they are used to run a frontend action.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_TOOLING_ARGUMENTSADJUSTERS_H
+#define LLVM_CLANG_TOOLING_ARGUMENTSADJUSTERS_H
+
+#include "clang/Basic/LLVM.h"
+#include "llvm/ADT/StringRef.h"
+#include <functional>
+#include <string>
+#include <vector>
+
+namespace clang {
+namespace tooling {
+
+/// \brief A sequence of command line arguments.
+typedef std::vector<std::string> CommandLineArguments;
+
+/// \brief A prototype of a command line adjuster.
+///
+/// Command line argument adjuster is responsible for command line arguments
+/// modification before the arguments are used to run a frontend action.
+typedef std::function<CommandLineArguments(
+ const CommandLineArguments &, StringRef Filename)> ArgumentsAdjuster;
+
+/// \brief Gets an argument adjuster that converts input command line arguments
+/// to the "syntax check only" variant.
+ArgumentsAdjuster getClangSyntaxOnlyAdjuster();
+
+/// \brief Gets an argument adjuster which removes output-related command line
+/// arguments.
+ArgumentsAdjuster getClangStripOutputAdjuster();
+
+enum class ArgumentInsertPosition { BEGIN, END };
+
+/// \brief Gets an argument adjuster which inserts \p Extra arguments in the
+/// specified position.
+ArgumentsAdjuster getInsertArgumentAdjuster(const CommandLineArguments &Extra,
+ ArgumentInsertPosition Pos);
+
+/// \brief Gets an argument adjuster which inserts an \p Extra argument in the
+/// specified position.
+ArgumentsAdjuster getInsertArgumentAdjuster(
+ const char *Extra,
+ ArgumentInsertPosition Pos = ArgumentInsertPosition::END);
+
+/// \brief Gets an argument adjuster which adjusts the arguments in sequence
+/// with the \p First adjuster and then with the \p Second one.
+ArgumentsAdjuster combineAdjusters(ArgumentsAdjuster First,
+ ArgumentsAdjuster Second);
+
+} // namespace tooling
+} // namespace clang
+
+#endif // LLVM_CLANG_TOOLING_ARGUMENTSADJUSTERS_H
+
diff --git a/contrib/llvm/tools/clang/include/clang/Tooling/CommonOptionsParser.h b/contrib/llvm/tools/clang/include/clang/Tooling/CommonOptionsParser.h
new file mode 100644
index 0000000..1e8462c
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Tooling/CommonOptionsParser.h
@@ -0,0 +1,117 @@
+//===- CommonOptionsParser.h - common options for clang tools -*- 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 CommonOptionsParser class used to parse common
+// command-line options for clang tools, so that they can be run as separate
+// command-line applications with a consistent common interface for handling
+// compilation database and input files.
+//
+// It provides a common subset of command-line options, common algorithm
+// for locating a compilation database and source files, and help messages
+// for the basic command-line interface.
+//
+// It creates a CompilationDatabase and reads common command-line options.
+//
+// This class uses the Clang Tooling infrastructure, see
+// http://clang.llvm.org/docs/HowToSetupToolingForLLVM.html
+// for details on setting it up with LLVM source tree.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_TOOLING_COMMONOPTIONSPARSER_H
+#define LLVM_CLANG_TOOLING_COMMONOPTIONSPARSER_H
+
+#include "clang/Tooling/CompilationDatabase.h"
+#include "llvm/Support/CommandLine.h"
+
+namespace clang {
+namespace tooling {
+/// \brief A parser for options common to all command-line Clang tools.
+///
+/// Parses a common subset of command-line arguments, locates and loads a
+/// compilation commands database and runs a tool with user-specified action. It
+/// also contains a help message for the common command-line options.
+///
+/// An example of usage:
+/// \code
+/// #include "clang/Frontend/FrontendActions.h"
+/// #include "clang/Tooling/CommonOptionsParser.h"
+/// #include "clang/Tooling/Tooling.h"
+/// #include "llvm/Support/CommandLine.h"
+///
+/// using namespace clang::tooling;
+/// using namespace llvm;
+///
+/// static cl::OptionCategory MyToolCategory("My tool options");
+/// static cl::extrahelp CommonHelp(CommonOptionsParser::HelpMessage);
+/// static cl::extrahelp MoreHelp("\nMore help text...");
+/// static cl::opt<bool> YourOwnOption(...);
+/// ...
+///
+/// int main(int argc, const char **argv) {
+/// CommonOptionsParser OptionsParser(argc, argv, MyToolCategory);
+/// ClangTool Tool(OptionsParser.getCompilations(),
+/// OptionsParser.getSourcePathList());
+/// return Tool.run(newFrontendActionFactory<SyntaxOnlyAction>().get());
+/// }
+/// \endcode
+class CommonOptionsParser {
+public:
+ /// \brief Parses command-line, initializes a compilation database.
+ ///
+ /// This constructor can change argc and argv contents, e.g. consume
+ /// command-line options used for creating FixedCompilationDatabase.
+ ///
+ /// All options not belonging to \p Category become hidden.
+ ///
+ /// This constructor exits program in case of error.
+ CommonOptionsParser(int &argc, const char **argv,
+ llvm::cl::OptionCategory &Category,
+ const char *Overview = nullptr)
+ : CommonOptionsParser(argc, argv, Category, llvm::cl::OneOrMore,
+ Overview) {}
+
+ /// \brief Parses command-line, initializes a compilation database.
+ ///
+ /// This constructor can change argc and argv contents, e.g. consume
+ /// command-line options used for creating FixedCompilationDatabase.
+ ///
+ /// All options not belonging to \p Category become hidden.
+ ///
+ /// I also allows calls to set the required number of positional parameters.
+ ///
+ /// This constructor exits program in case of error.
+ CommonOptionsParser(int &argc, const char **argv,
+ llvm::cl::OptionCategory &Category,
+ llvm::cl::NumOccurrencesFlag OccurrencesFlag,
+ const char *Overview = nullptr);
+
+ /// Returns a reference to the loaded compilations database.
+ CompilationDatabase &getCompilations() {
+ return *Compilations;
+ }
+
+ /// Returns a list of source file paths to process.
+ std::vector<std::string> getSourcePathList() {
+ return SourcePathList;
+ }
+
+ static const char *const HelpMessage;
+
+private:
+ std::unique_ptr<CompilationDatabase> Compilations;
+ std::vector<std::string> SourcePathList;
+ std::vector<std::string> ExtraArgsBefore;
+ std::vector<std::string> ExtraArgsAfter;
+};
+
+} // namespace tooling
+} // namespace clang
+
+#endif // LLVM_TOOLS_CLANG_INCLUDE_CLANG_TOOLING_COMMONOPTIONSPARSER_H
diff --git a/contrib/llvm/tools/clang/include/clang/Tooling/CompilationDatabase.h b/contrib/llvm/tools/clang/include/clang/Tooling/CompilationDatabase.h
new file mode 100644
index 0000000..08a0ffe
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Tooling/CompilationDatabase.h
@@ -0,0 +1,222 @@
+//===--- CompilationDatabase.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 provides an interface and multiple implementations for
+// CompilationDatabases.
+//
+// While C++ refactoring and analysis tools are not compilers, and thus
+// don't run as part of the build system, they need the exact information
+// of a build in order to be able to correctly understand the C++ code of
+// the project. This information is provided via the CompilationDatabase
+// interface.
+//
+// To create a CompilationDatabase from a build directory one can call
+// CompilationDatabase::loadFromDirectory(), which deduces the correct
+// compilation database from the root of the build tree.
+//
+// See the concrete subclasses of CompilationDatabase for currently supported
+// formats.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_TOOLING_COMPILATIONDATABASE_H
+#define LLVM_CLANG_TOOLING_COMPILATIONDATABASE_H
+
+#include "clang/Basic/LLVM.h"
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/ADT/Twine.h"
+#include <memory>
+#include <string>
+#include <vector>
+
+namespace clang {
+namespace tooling {
+
+/// \brief Specifies the working directory and command of a compilation.
+struct CompileCommand {
+ CompileCommand() {}
+ CompileCommand(Twine Directory, Twine Filename,
+ std::vector<std::string> CommandLine)
+ : Directory(Directory.str()),
+ Filename(Filename.str()),
+ CommandLine(std::move(CommandLine)) {}
+
+ /// \brief The working directory the command was executed from.
+ std::string Directory;
+
+ /// The source file associated with the command.
+ std::string Filename;
+
+ /// \brief The command line that was executed.
+ std::vector<std::string> CommandLine;
+
+ /// \brief An optional mapping from each file's path to its content for all
+ /// files needed for the compilation that are not available via the file
+ /// system.
+ ///
+ /// Note that a tool implementation is required to fall back to the file
+ /// system if a source file is not provided in the mapped sources, as
+ /// compilation databases will usually not provide all files in mapped sources
+ /// for performance reasons.
+ std::vector<std::pair<std::string, std::string> > MappedSources;
+};
+
+/// \brief Interface for compilation databases.
+///
+/// A compilation database allows the user to retrieve all compile command lines
+/// that a specified file is compiled with in a project.
+/// The retrieved compile command lines can be used to run clang tools over
+/// a subset of the files in a project.
+class CompilationDatabase {
+public:
+ virtual ~CompilationDatabase();
+
+ /// \brief Loads a compilation database from a build directory.
+ ///
+ /// Looks at the specified 'BuildDirectory' and creates a compilation database
+ /// that allows to query compile commands for source files in the
+ /// corresponding source tree.
+ ///
+ /// Returns NULL and sets ErrorMessage if we were not able to build up a
+ /// compilation database for the build directory.
+ ///
+ /// FIXME: Currently only supports JSON compilation databases, which
+ /// are named 'compile_commands.json' in the given directory. Extend this
+ /// for other build types (like ninja build files).
+ static std::unique_ptr<CompilationDatabase>
+ loadFromDirectory(StringRef BuildDirectory, std::string &ErrorMessage);
+
+ /// \brief Tries to detect a compilation database location and load it.
+ ///
+ /// Looks for a compilation database in all parent paths of file 'SourceFile'
+ /// by calling loadFromDirectory.
+ static std::unique_ptr<CompilationDatabase>
+ autoDetectFromSource(StringRef SourceFile, std::string &ErrorMessage);
+
+ /// \brief Tries to detect a compilation database location and load it.
+ ///
+ /// Looks for a compilation database in directory 'SourceDir' and all
+ /// its parent paths by calling loadFromDirectory.
+ static std::unique_ptr<CompilationDatabase>
+ autoDetectFromDirectory(StringRef SourceDir, std::string &ErrorMessage);
+
+ /// \brief Returns all compile commands in which the specified file was
+ /// compiled.
+ ///
+ /// This includes compile comamnds that span multiple source files.
+ /// For example, consider a project with the following compilations:
+ /// $ clang++ -o test a.cc b.cc t.cc
+ /// $ clang++ -o production a.cc b.cc -DPRODUCTION
+ /// A compilation database representing the project would return both command
+ /// lines for a.cc and b.cc and only the first command line for t.cc.
+ virtual std::vector<CompileCommand> getCompileCommands(
+ StringRef FilePath) const = 0;
+
+ /// \brief Returns the list of all files available in the compilation database.
+ virtual std::vector<std::string> getAllFiles() const = 0;
+
+ /// \brief Returns all compile commands for all the files in the compilation
+ /// database.
+ ///
+ /// FIXME: Add a layer in Tooling that provides an interface to run a tool
+ /// over all files in a compilation database. Not all build systems have the
+ /// ability to provide a feasible implementation for \c getAllCompileCommands.
+ virtual std::vector<CompileCommand> getAllCompileCommands() const = 0;
+};
+
+/// \brief Interface for compilation database plugins.
+///
+/// A compilation database plugin allows the user to register custom compilation
+/// databases that are picked up as compilation database if the corresponding
+/// library is linked in. To register a plugin, declare a static variable like:
+///
+/// \code
+/// static CompilationDatabasePluginRegistry::Add<MyDatabasePlugin>
+/// X("my-compilation-database", "Reads my own compilation database");
+/// \endcode
+class CompilationDatabasePlugin {
+public:
+ virtual ~CompilationDatabasePlugin();
+
+ /// \brief Loads a compilation database from a build directory.
+ ///
+ /// \see CompilationDatabase::loadFromDirectory().
+ virtual std::unique_ptr<CompilationDatabase>
+ loadFromDirectory(StringRef Directory, std::string &ErrorMessage) = 0;
+};
+
+/// \brief A compilation database that returns a single compile command line.
+///
+/// Useful when we want a tool to behave more like a compiler invocation.
+class FixedCompilationDatabase : public CompilationDatabase {
+public:
+ /// \brief Creates a FixedCompilationDatabase from the arguments after "--".
+ ///
+ /// Parses the given command line for "--". If "--" is found, the rest of
+ /// the arguments will make up the command line in the returned
+ /// FixedCompilationDatabase.
+ /// The arguments after "--" must not include positional parameters or the
+ /// argv[0] of the tool. Those will be added by the FixedCompilationDatabase
+ /// when a CompileCommand is requested. The argv[0] of the returned command
+ /// line will be "clang-tool".
+ ///
+ /// Returns NULL in case "--" is not found.
+ ///
+ /// The argument list is meant to be compatible with normal llvm command line
+ /// parsing in main methods.
+ /// int main(int argc, char **argv) {
+ /// std::unique_ptr<FixedCompilationDatabase> Compilations(
+ /// FixedCompilationDatabase::loadFromCommandLine(argc, argv));
+ /// cl::ParseCommandLineOptions(argc, argv);
+ /// ...
+ /// }
+ ///
+ /// \param Argc The number of command line arguments - will be changed to
+ /// the number of arguments before "--", if "--" was found in the argument
+ /// list.
+ /// \param Argv Points to the command line arguments.
+ /// \param Directory The base directory used in the FixedCompilationDatabase.
+ static FixedCompilationDatabase *loadFromCommandLine(int &Argc,
+ const char *const *Argv,
+ Twine Directory = ".");
+
+ /// \brief Constructs a compilation data base from a specified directory
+ /// and command line.
+ FixedCompilationDatabase(Twine Directory, ArrayRef<std::string> CommandLine);
+
+ /// \brief Returns the given compile command.
+ ///
+ /// Will always return a vector with one entry that contains the directory
+ /// and command line specified at construction with "clang-tool" as argv[0]
+ /// and 'FilePath' as positional argument.
+ std::vector<CompileCommand>
+ getCompileCommands(StringRef FilePath) const override;
+
+ /// \brief Returns the list of all files available in the compilation database.
+ ///
+ /// Note: This is always an empty list for the fixed compilation database.
+ std::vector<std::string> getAllFiles() const override;
+
+ /// \brief Returns all compile commands for all the files in the compilation
+ /// database.
+ ///
+ /// Note: This is always an empty list for the fixed compilation database.
+ std::vector<CompileCommand> getAllCompileCommands() const override;
+
+private:
+ /// This is built up to contain a single entry vector to be returned from
+ /// getCompileCommands after adding the positional argument.
+ std::vector<CompileCommand> CompileCommands;
+};
+
+} // end namespace tooling
+} // end namespace clang
+
+#endif
diff --git a/contrib/llvm/tools/clang/include/clang/Tooling/CompilationDatabasePluginRegistry.h b/contrib/llvm/tools/clang/include/clang/Tooling/CompilationDatabasePluginRegistry.h
new file mode 100644
index 0000000..7323ec8
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Tooling/CompilationDatabasePluginRegistry.h
@@ -0,0 +1,27 @@
+//===--- CompilationDatabasePluginRegistry.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_TOOLING_COMPILATIONDATABASEPLUGINREGISTRY_H
+#define LLVM_CLANG_TOOLING_COMPILATIONDATABASEPLUGINREGISTRY_H
+
+#include "clang/Tooling/CompilationDatabase.h"
+#include "llvm/Support/Registry.h"
+
+namespace clang {
+namespace tooling {
+
+class CompilationDatabasePlugin;
+
+typedef llvm::Registry<CompilationDatabasePlugin>
+ CompilationDatabasePluginRegistry;
+
+} // end namespace tooling
+} // end namespace clang
+
+#endif
diff --git a/contrib/llvm/tools/clang/include/clang/Tooling/Core/Lookup.h b/contrib/llvm/tools/clang/include/clang/Tooling/Core/Lookup.h
new file mode 100644
index 0000000..bc2b4db
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Tooling/Core/Lookup.h
@@ -0,0 +1,48 @@
+//===--- Lookup.h - Framework for clang refactoring tools --*- C++ -*------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines helper methods for clang tools performing name lookup.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_TOOLING_CORE_LOOKUP_H
+#define LLVM_CLANG_TOOLING_CORE_LOOKUP_H
+
+#include "clang/Basic/LLVM.h"
+#include <string>
+
+namespace clang {
+
+class DeclContext;
+class NamedDecl;
+class NestedNameSpecifier;
+
+namespace tooling {
+
+/// Emulate a lookup to replace one nested name specifier with another using as
+/// few additional namespace qualifications as possible.
+///
+/// This does not perform a full C++ lookup so ADL will not work.
+///
+/// \param Use The nested name to be replaced.
+/// \param UseContext The context in which the nested name is contained. This
+/// will be used to minimize namespace qualifications.
+/// \param FromDecl The declaration to which the nested name points.
+/// \param ReplacementString The replacement nested name. Must be fully
+/// qualified including a leading "::".
+/// \returns The new name to be inserted in place of the current nested name.
+std::string replaceNestedName(const NestedNameSpecifier *Use,
+ const DeclContext *UseContext,
+ const NamedDecl *FromDecl,
+ StringRef ReplacementString);
+
+} // end namespace tooling
+} // end namespace clang
+
+#endif // LLVM_CLANG_TOOLING_CORE_LOOKUP_H
diff --git a/contrib/llvm/tools/clang/include/clang/Tooling/Core/Replacement.h b/contrib/llvm/tools/clang/include/clang/Tooling/Core/Replacement.h
new file mode 100644
index 0000000..37389ac
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Tooling/Core/Replacement.h
@@ -0,0 +1,241 @@
+//===--- Replacement.h - Framework for clang refactoring tools --*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// Classes supporting refactorings that span multiple translation units.
+// While single translation unit refactorings are supported via the Rewriter,
+// when refactoring multiple translation units changes must be stored in a
+// SourceManager independent form, duplicate changes need to be removed, and
+// all changes must be applied at once at the end of the refactoring so that
+// the code is always parseable.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_TOOLING_CORE_REPLACEMENT_H
+#define LLVM_CLANG_TOOLING_CORE_REPLACEMENT_H
+
+#include "clang/Basic/LangOptions.h"
+#include "clang/Basic/SourceLocation.h"
+#include "llvm/ADT/StringRef.h"
+#include <set>
+#include <string>
+#include <vector>
+
+namespace clang {
+
+class Rewriter;
+
+namespace tooling {
+
+/// \brief A source range independent of the \c SourceManager.
+class Range {
+public:
+ Range() : Offset(0), Length(0) {}
+ Range(unsigned Offset, unsigned Length) : Offset(Offset), Length(Length) {}
+
+ /// \brief Accessors.
+ /// @{
+ unsigned getOffset() const { return Offset; }
+ unsigned getLength() const { return Length; }
+ /// @}
+
+ /// \name Range Predicates
+ /// @{
+ /// \brief Whether this range overlaps with \p RHS or not.
+ bool overlapsWith(Range RHS) const {
+ return Offset + Length > RHS.Offset && Offset < RHS.Offset + RHS.Length;
+ }
+
+ /// \brief Whether this range contains \p RHS or not.
+ bool contains(Range RHS) const {
+ return RHS.Offset >= Offset &&
+ (RHS.Offset + RHS.Length) <= (Offset + Length);
+ }
+ /// @}
+
+private:
+ unsigned Offset;
+ unsigned Length;
+};
+
+/// \brief A text replacement.
+///
+/// Represents a SourceManager independent replacement of a range of text in a
+/// specific file.
+class Replacement {
+public:
+ /// \brief Creates an invalid (not applicable) replacement.
+ Replacement();
+
+ /// \brief Creates a replacement of the range [Offset, Offset+Length) in
+ /// FilePath with ReplacementText.
+ ///
+ /// \param FilePath A source file accessible via a SourceManager.
+ /// \param Offset The byte offset of the start of the range in the file.
+ /// \param Length The length of the range in bytes.
+ Replacement(StringRef FilePath, unsigned Offset, unsigned Length,
+ StringRef ReplacementText);
+
+ /// \brief Creates a Replacement of the range [Start, Start+Length) with
+ /// ReplacementText.
+ Replacement(const SourceManager &Sources, SourceLocation Start,
+ unsigned Length, StringRef ReplacementText);
+
+ /// \brief Creates a Replacement of the given range with ReplacementText.
+ Replacement(const SourceManager &Sources, const CharSourceRange &Range,
+ StringRef ReplacementText,
+ const LangOptions &LangOpts = LangOptions());
+
+ /// \brief Creates a Replacement of the node with ReplacementText.
+ template <typename Node>
+ Replacement(const SourceManager &Sources, const Node &NodeToReplace,
+ StringRef ReplacementText,
+ const LangOptions &LangOpts = LangOptions());
+
+ /// \brief Returns whether this replacement can be applied to a file.
+ ///
+ /// Only replacements that are in a valid file can be applied.
+ bool isApplicable() const;
+
+ /// \brief Accessors.
+ /// @{
+ StringRef getFilePath() const { return FilePath; }
+ unsigned getOffset() const { return ReplacementRange.getOffset(); }
+ unsigned getLength() const { return ReplacementRange.getLength(); }
+ StringRef getReplacementText() const { return ReplacementText; }
+ /// @}
+
+ /// \brief Applies the replacement on the Rewriter.
+ bool apply(Rewriter &Rewrite) const;
+
+ /// \brief Returns a human readable string representation.
+ std::string toString() const;
+
+ private:
+ void setFromSourceLocation(const SourceManager &Sources,
+ SourceLocation Start, unsigned Length,
+ StringRef ReplacementText);
+ void setFromSourceRange(const SourceManager &Sources,
+ const CharSourceRange &Range,
+ StringRef ReplacementText,
+ const LangOptions &LangOpts);
+
+ std::string FilePath;
+ Range ReplacementRange;
+ std::string ReplacementText;
+};
+
+/// \brief Less-than operator between two Replacements.
+bool operator<(const Replacement &LHS, const Replacement &RHS);
+
+/// \brief Equal-to operator between two Replacements.
+bool operator==(const Replacement &LHS, const Replacement &RHS);
+
+/// \brief A set of Replacements.
+/// FIXME: Change to a vector and deduplicate in the RefactoringTool.
+typedef std::set<Replacement> Replacements;
+
+/// \brief Apply all replacements in \p Replaces to the Rewriter \p Rewrite.
+///
+/// Replacement applications happen independently of the success of
+/// other applications.
+///
+/// \returns true if all replacements apply. false otherwise.
+bool applyAllReplacements(const Replacements &Replaces, Rewriter &Rewrite);
+
+/// \brief Apply all replacements in \p Replaces to the Rewriter \p Rewrite.
+///
+/// Replacement applications happen independently of the success of
+/// other applications.
+///
+/// \returns true if all replacements apply. false otherwise.
+bool applyAllReplacements(const std::vector<Replacement> &Replaces,
+ Rewriter &Rewrite);
+
+/// \brief Applies all replacements in \p Replaces to \p Code.
+///
+/// This completely ignores the path stored in each replacement. If one or more
+/// replacements cannot be applied, this returns an empty \c string.
+std::string applyAllReplacements(StringRef Code, const Replacements &Replaces);
+
+/// \brief Calculates how a code \p Position is shifted when \p Replaces are
+/// applied.
+unsigned shiftedCodePosition(const Replacements& Replaces, unsigned Position);
+
+/// \brief Calculates how a code \p Position is shifted when \p Replaces are
+/// applied.
+///
+/// \pre Replaces[i].getOffset() <= Replaces[i+1].getOffset().
+unsigned shiftedCodePosition(const std::vector<Replacement> &Replaces,
+ unsigned Position);
+
+/// \brief Removes duplicate Replacements and reports if Replacements conflict
+/// with one another. All Replacements are assumed to be in the same file.
+///
+/// \post Replaces[i].getOffset() <= Replaces[i+1].getOffset().
+///
+/// This function sorts \p Replaces so that conflicts can be reported simply by
+/// offset into \p Replaces and number of elements in the conflict.
+void deduplicate(std::vector<Replacement> &Replaces,
+ std::vector<Range> &Conflicts);
+
+/// \brief Collection of Replacements generated from a single translation unit.
+struct TranslationUnitReplacements {
+ /// Name of the main source for the translation unit.
+ std::string MainSourceFile;
+
+ /// A freeform chunk of text to describe the context of the replacements.
+ /// Will be printed, for example, when detecting conflicts during replacement
+ /// deduplication.
+ std::string Context;
+
+ std::vector<Replacement> Replacements;
+};
+
+/// \brief Apply all replacements in \p Replaces to the Rewriter \p Rewrite.
+///
+/// Replacement applications happen independently of the success of
+/// other applications.
+///
+/// \returns true if all replacements apply. false otherwise.
+bool applyAllReplacements(const Replacements &Replaces, Rewriter &Rewrite);
+
+/// \brief Apply all replacements in \p Replaces to the Rewriter \p Rewrite.
+///
+/// Replacement applications happen independently of the success of
+/// other applications.
+///
+/// \returns true if all replacements apply. false otherwise.
+bool applyAllReplacements(const std::vector<Replacement> &Replaces,
+ Rewriter &Rewrite);
+
+/// \brief Applies all replacements in \p Replaces to \p Code.
+///
+/// This completely ignores the path stored in each replacement. If one or more
+/// replacements cannot be applied, this returns an empty \c string.
+std::string applyAllReplacements(StringRef Code, const Replacements &Replaces);
+
+/// \brief Merges two sets of replacements with the second set referring to the
+/// code after applying the first set. Within both 'First' and 'Second',
+/// replacements must not overlap.
+Replacements mergeReplacements(const Replacements &First,
+ const Replacements &Second);
+
+template <typename Node>
+Replacement::Replacement(const SourceManager &Sources,
+ const Node &NodeToReplace, StringRef ReplacementText,
+ const LangOptions &LangOpts) {
+ const CharSourceRange Range =
+ CharSourceRange::getTokenRange(NodeToReplace->getSourceRange());
+ setFromSourceRange(Sources, Range, ReplacementText, LangOpts);
+}
+
+} // end namespace tooling
+} // end namespace clang
+
+#endif // LLVM_CLANG_TOOLING_CORE_REPLACEMENT_H
diff --git a/contrib/llvm/tools/clang/include/clang/Tooling/FileMatchTrie.h b/contrib/llvm/tools/clang/include/clang/Tooling/FileMatchTrie.h
new file mode 100644
index 0000000..745c164
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Tooling/FileMatchTrie.h
@@ -0,0 +1,89 @@
+//===--- FileMatchTrie.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 implements a match trie to find the matching file in a compilation
+// database based on a given path in the presence of symlinks.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_TOOLING_FILEMATCHTRIE_H
+#define LLVM_CLANG_TOOLING_FILEMATCHTRIE_H
+
+#include "clang/Basic/LLVM.h"
+#include "llvm/ADT/StringRef.h"
+#include <memory>
+#include <string>
+#include <vector>
+
+namespace clang {
+namespace tooling {
+
+struct PathComparator {
+ virtual ~PathComparator() {}
+ virtual bool equivalent(StringRef FileA, StringRef FileB) const = 0;
+};
+class FileMatchTrieNode;
+
+/// \brief A trie to efficiently match against the entries of the compilation
+/// database in order of matching suffix length.
+///
+/// When a clang tool is supposed to operate on a specific file, we have to
+/// find the corresponding file in the compilation database. Although entries
+/// in the compilation database are keyed by filename, a simple string match
+/// is insufficient because of symlinks. Commonly, a project hierarchy looks
+/// like this:
+/// /<project-root>/src/<path>/<somefile>.cc (used as input for the tool)
+/// /<project-root>/build/<symlink-to-src>/<path>/<somefile>.cc (stored in DB)
+///
+/// Furthermore, there might be symlinks inside the source folder or inside the
+/// database, so that the same source file is translated with different build
+/// options.
+///
+/// For a given input file, the \c FileMatchTrie finds its entries in order
+/// of matching suffix length. For each suffix length, there might be one or
+/// more entries in the database. For each of those entries, it calls
+/// \c llvm::sys::fs::equivalent() (injected as \c PathComparator). There might
+/// be zero or more entries with the same matching suffix length that are
+/// equivalent to the input file. Three cases are distinguished:
+/// 0 equivalent files: Continue with the next suffix length.
+/// 1 equivalent file: Best match found, return it.
+/// >1 equivalent files: Match is ambiguous, return error.
+class FileMatchTrie {
+public:
+ FileMatchTrie();
+
+ /// \brief Construct a new \c FileMatchTrie with the given \c PathComparator.
+ ///
+ /// The \c FileMatchTrie takes ownership of 'Comparator'. Used for testing.
+ FileMatchTrie(PathComparator* Comparator);
+
+ ~FileMatchTrie();
+
+ /// \brief Insert a new absolute path. Relative paths are ignored.
+ void insert(StringRef NewPath);
+
+ /// \brief Finds the corresponding file in this trie.
+ ///
+ /// Returns file name stored in this trie that is equivalent to 'FileName'
+ /// according to 'Comparator', if it can be uniquely identified. If there
+ /// are no matches an empty \c StringRef is returned. If there are ambigious
+ /// matches, an empty \c StringRef is returned and a corresponding message
+ /// written to 'Error'.
+ StringRef findEquivalent(StringRef FileName,
+ raw_ostream &Error) const;
+private:
+ FileMatchTrieNode *Root;
+ std::unique_ptr<PathComparator> Comparator;
+};
+
+
+} // end namespace tooling
+} // end namespace clang
+
+#endif
diff --git a/contrib/llvm/tools/clang/include/clang/Tooling/JSONCompilationDatabase.h b/contrib/llvm/tools/clang/include/clang/Tooling/JSONCompilationDatabase.h
new file mode 100644
index 0000000..2a13fc1
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Tooling/JSONCompilationDatabase.h
@@ -0,0 +1,133 @@
+//===--- JSONCompilationDatabase.h - ----------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// The JSONCompilationDatabase finds compilation databases supplied as a file
+// 'compile_commands.json'.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_TOOLING_JSONCOMPILATIONDATABASE_H
+#define LLVM_CLANG_TOOLING_JSONCOMPILATIONDATABASE_H
+
+#include "clang/Basic/LLVM.h"
+#include "clang/Tooling/CompilationDatabase.h"
+#include "clang/Tooling/FileMatchTrie.h"
+#include "llvm/ADT/StringMap.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/Support/MemoryBuffer.h"
+#include "llvm/Support/SourceMgr.h"
+#include "llvm/Support/YAMLParser.h"
+#include <memory>
+#include <string>
+#include <vector>
+
+namespace clang {
+namespace tooling {
+
+/// \brief A JSON based compilation database.
+///
+/// JSON compilation database files must contain a list of JSON objects which
+/// provide the command lines in the attributes 'directory', 'command',
+/// 'arguments' and 'file':
+/// [
+/// { "directory": "<working directory of the compile>",
+/// "command": "<compile command line>",
+/// "file": "<path to source file>"
+/// },
+/// { "directory": "<working directory of the compile>",
+/// "arguments": ["<raw>", "<command>" "<line>" "<parameters>"],
+/// "file": "<path to source file>"
+/// },
+/// ...
+/// ]
+/// Each object entry defines one compile action. The specified file is
+/// considered to be the main source file for the translation unit.
+///
+/// 'command' is a full command line that will be unescaped.
+///
+/// 'arguments' is a list of command line arguments that will not be unescaped.
+///
+/// JSON compilation databases can for example be generated in CMake projects
+/// by setting the flag -DCMAKE_EXPORT_COMPILE_COMMANDS.
+class JSONCompilationDatabase : public CompilationDatabase {
+public:
+ /// \brief Loads a JSON compilation database from the specified file.
+ ///
+ /// Returns NULL and sets ErrorMessage if the database could not be
+ /// loaded from the given file.
+ static std::unique_ptr<JSONCompilationDatabase>
+ loadFromFile(StringRef FilePath, std::string &ErrorMessage);
+
+ /// \brief Loads a JSON compilation database from a data buffer.
+ ///
+ /// Returns NULL and sets ErrorMessage if the database could not be loaded.
+ static std::unique_ptr<JSONCompilationDatabase>
+ loadFromBuffer(StringRef DatabaseString, std::string &ErrorMessage);
+
+ /// \brief Returns all compile comamnds in which the specified file was
+ /// compiled.
+ ///
+ /// FIXME: Currently FilePath must be an absolute path inside the
+ /// source directory which does not have symlinks resolved.
+ std::vector<CompileCommand>
+ getCompileCommands(StringRef FilePath) const override;
+
+ /// \brief Returns the list of all files available in the compilation database.
+ ///
+ /// These are the 'file' entries of the JSON objects.
+ std::vector<std::string> getAllFiles() const override;
+
+ /// \brief Returns all compile commands for all the files in the compilation
+ /// database.
+ std::vector<CompileCommand> getAllCompileCommands() const override;
+
+private:
+ /// \brief Constructs a JSON compilation database on a memory buffer.
+ JSONCompilationDatabase(std::unique_ptr<llvm::MemoryBuffer> Database)
+ : Database(std::move(Database)),
+ YAMLStream(this->Database->getBuffer(), SM) {}
+
+ /// \brief Parses the database file and creates the index.
+ ///
+ /// Returns whether parsing succeeded. Sets ErrorMessage if parsing
+ /// failed.
+ bool parse(std::string &ErrorMessage);
+
+ // Tuple (directory, filename, commandline) where 'commandline' points to the
+ // corresponding scalar nodes in the YAML stream.
+ // If the command line contains a single argument, it is a shell-escaped
+ // command line.
+ // Otherwise, each entry in the command line vector is a literal
+ // argument to the compiler.
+ typedef std::tuple<llvm::yaml::ScalarNode *,
+ llvm::yaml::ScalarNode *,
+ std::vector<llvm::yaml::ScalarNode *>> CompileCommandRef;
+
+ /// \brief Converts the given array of CompileCommandRefs to CompileCommands.
+ void getCommands(ArrayRef<CompileCommandRef> CommandsRef,
+ std::vector<CompileCommand> &Commands) const;
+
+ // Maps file paths to the compile command lines for that file.
+ llvm::StringMap<std::vector<CompileCommandRef>> IndexByFile;
+
+ /// All the compile commands in the order that they were provided in the
+ /// JSON stream.
+ std::vector<CompileCommandRef> AllCommands;
+
+ FileMatchTrie MatchTrie;
+
+ std::unique_ptr<llvm::MemoryBuffer> Database;
+ llvm::SourceMgr SM;
+ llvm::yaml::Stream YAMLStream;
+};
+
+} // end namespace tooling
+} // end namespace clang
+
+#endif
diff --git a/contrib/llvm/tools/clang/include/clang/Tooling/Refactoring.h b/contrib/llvm/tools/clang/include/clang/Tooling/Refactoring.h
new file mode 100644
index 0000000..54deff6
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Tooling/Refactoring.h
@@ -0,0 +1,74 @@
+//===--- Refactoring.h - Framework for clang refactoring tools --*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// Interfaces supporting refactorings that span multiple translation units.
+// While single translation unit refactorings are supported via the Rewriter,
+// when refactoring multiple translation units changes must be stored in a
+// SourceManager independent form, duplicate changes need to be removed, and
+// all changes must be applied at once at the end of the refactoring so that
+// the code is always parseable.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_TOOLING_REFACTORING_H
+#define LLVM_CLANG_TOOLING_REFACTORING_H
+
+#include "clang/Tooling/Core/Replacement.h"
+#include "clang/Tooling/Tooling.h"
+#include <string>
+
+namespace clang {
+
+class Rewriter;
+
+namespace tooling {
+
+/// \brief A tool to run refactorings.
+///
+/// This is a refactoring specific version of \see ClangTool. FrontendActions
+/// passed to run() and runAndSave() should add replacements to
+/// getReplacements().
+class RefactoringTool : public ClangTool {
+public:
+ /// \see ClangTool::ClangTool.
+ RefactoringTool(const CompilationDatabase &Compilations,
+ ArrayRef<std::string> SourcePaths,
+ std::shared_ptr<PCHContainerOperations> PCHContainerOps =
+ std::make_shared<PCHContainerOperations>());
+
+ /// \brief Returns the set of replacements to which replacements should
+ /// be added during the run of the tool.
+ Replacements &getReplacements();
+
+ /// \brief Call run(), apply all generated replacements, and immediately save
+ /// the results to disk.
+ ///
+ /// \returns 0 upon success. Non-zero upon failure.
+ int runAndSave(FrontendActionFactory *ActionFactory);
+
+ /// \brief Apply all stored replacements to the given Rewriter.
+ ///
+ /// Replacement applications happen independently of the success of other
+ /// applications.
+ ///
+ /// \returns true if all replacements apply. false otherwise.
+ bool applyAllReplacements(Rewriter &Rewrite);
+
+private:
+ /// \brief Write all refactored files to disk.
+ int saveRewrittenFiles(Rewriter &Rewrite);
+
+private:
+ Replacements Replace;
+};
+
+} // end namespace tooling
+} // end namespace clang
+
+#endif // LLVM_CLANG_TOOLING_REFACTORING_H
diff --git a/contrib/llvm/tools/clang/include/clang/Tooling/RefactoringCallbacks.h b/contrib/llvm/tools/clang/include/clang/Tooling/RefactoringCallbacks.h
new file mode 100644
index 0000000..6ef9ea1
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Tooling/RefactoringCallbacks.h
@@ -0,0 +1,90 @@
+//===--- RefactoringCallbacks.h - Structural query framework ----*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// Provides callbacks to make common kinds of refactorings easy.
+//
+// The general idea is to construct a matcher expression that describes a
+// subtree match on the AST and then replace the corresponding source code
+// either by some specific text or some other AST node.
+//
+// Example:
+// int main(int argc, char **argv) {
+// ClangTool Tool(argc, argv);
+// MatchFinder Finder;
+// ReplaceStmtWithText Callback("integer", "42");
+// Finder.AddMatcher(id("integer", expression(integerLiteral())), Callback);
+// return Tool.run(newFrontendActionFactory(&Finder));
+// }
+//
+// This will replace all integer literals with "42".
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_TOOLING_REFACTORINGCALLBACKS_H
+#define LLVM_CLANG_TOOLING_REFACTORINGCALLBACKS_H
+
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+#include "clang/Tooling/Refactoring.h"
+
+namespace clang {
+namespace tooling {
+
+/// \brief Base class for RefactoringCallbacks.
+///
+/// Collects \c tooling::Replacements while running.
+class RefactoringCallback : public ast_matchers::MatchFinder::MatchCallback {
+public:
+ RefactoringCallback();
+ Replacements &getReplacements();
+
+protected:
+ Replacements Replace;
+};
+
+/// \brief Replace the text of the statement bound to \c FromId with the text in
+/// \c ToText.
+class ReplaceStmtWithText : public RefactoringCallback {
+public:
+ ReplaceStmtWithText(StringRef FromId, StringRef ToText);
+ void run(const ast_matchers::MatchFinder::MatchResult &Result) override;
+
+private:
+ std::string FromId;
+ std::string ToText;
+};
+
+/// \brief Replace the text of the statement bound to \c FromId with the text of
+/// the statement bound to \c ToId.
+class ReplaceStmtWithStmt : public RefactoringCallback {
+public:
+ ReplaceStmtWithStmt(StringRef FromId, StringRef ToId);
+ void run(const ast_matchers::MatchFinder::MatchResult &Result) override;
+
+private:
+ std::string FromId;
+ std::string ToId;
+};
+
+/// \brief Replace an if-statement bound to \c Id with the outdented text of its
+/// body, choosing the consequent or the alternative based on whether
+/// \c PickTrueBranch is true.
+class ReplaceIfStmtWithItsBody : public RefactoringCallback {
+public:
+ ReplaceIfStmtWithItsBody(StringRef Id, bool PickTrueBranch);
+ void run(const ast_matchers::MatchFinder::MatchResult &Result) override;
+
+private:
+ std::string Id;
+ const bool PickTrueBranch;
+};
+
+} // end namespace tooling
+} // end namespace clang
+
+#endif
diff --git a/contrib/llvm/tools/clang/include/clang/Tooling/ReplacementsYaml.h b/contrib/llvm/tools/clang/include/clang/Tooling/ReplacementsYaml.h
new file mode 100644
index 0000000..4a7666d
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Tooling/ReplacementsYaml.h
@@ -0,0 +1,76 @@
+//===-- ReplacementsYaml.h -- Serialiazation for Replacements ---*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+///
+/// \file
+/// \brief This file defines the structure of a YAML document for serializing
+/// replacements.
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_TOOLING_REPLACEMENTSYAML_H
+#define LLVM_CLANG_TOOLING_REPLACEMENTSYAML_H
+
+#include "clang/Tooling/Refactoring.h"
+#include "llvm/Support/YAMLTraits.h"
+#include <string>
+#include <vector>
+
+LLVM_YAML_IS_SEQUENCE_VECTOR(clang::tooling::Replacement)
+
+namespace llvm {
+namespace yaml {
+
+/// \brief Specialized MappingTraits to describe how a Replacement is
+/// (de)serialized.
+template <> struct MappingTraits<clang::tooling::Replacement> {
+ /// \brief Helper to (de)serialize a Replacement since we don't have direct
+ /// access to its data members.
+ struct NormalizedReplacement {
+ NormalizedReplacement(const IO &)
+ : FilePath(""), Offset(0), Length(0), ReplacementText("") {}
+
+ NormalizedReplacement(const IO &, const clang::tooling::Replacement &R)
+ : FilePath(R.getFilePath()), Offset(R.getOffset()),
+ Length(R.getLength()), ReplacementText(R.getReplacementText()) {}
+
+ clang::tooling::Replacement denormalize(const IO &) {
+ return clang::tooling::Replacement(FilePath, Offset, Length,
+ ReplacementText);
+ }
+
+ std::string FilePath;
+ unsigned int Offset;
+ unsigned int Length;
+ std::string ReplacementText;
+ };
+
+ static void mapping(IO &Io, clang::tooling::Replacement &R) {
+ MappingNormalization<NormalizedReplacement, clang::tooling::Replacement>
+ Keys(Io, R);
+ Io.mapRequired("FilePath", Keys->FilePath);
+ Io.mapRequired("Offset", Keys->Offset);
+ Io.mapRequired("Length", Keys->Length);
+ Io.mapRequired("ReplacementText", Keys->ReplacementText);
+ }
+};
+
+/// \brief Specialized MappingTraits to describe how a
+/// TranslationUnitReplacements is (de)serialized.
+template <> struct MappingTraits<clang::tooling::TranslationUnitReplacements> {
+ static void mapping(IO &Io,
+ clang::tooling::TranslationUnitReplacements &Doc) {
+ Io.mapRequired("MainSourceFile", Doc.MainSourceFile);
+ Io.mapOptional("Context", Doc.Context, std::string());
+ Io.mapRequired("Replacements", Doc.Replacements);
+ }
+};
+} // end namespace yaml
+} // end namespace llvm
+
+#endif
diff --git a/contrib/llvm/tools/clang/include/clang/Tooling/Tooling.h b/contrib/llvm/tools/clang/include/clang/Tooling/Tooling.h
new file mode 100644
index 0000000..b7a9b25
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/Tooling/Tooling.h
@@ -0,0 +1,455 @@
+//===--- Tooling.h - Framework for standalone Clang tools -------*- 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 functions to run clang tools standalone instead
+// of running them as a plugin.
+//
+// A ClangTool is initialized with a CompilationDatabase and a set of files
+// to run over. The tool will then run a user-specified FrontendAction over
+// all TUs in which the given files are compiled.
+//
+// It is also possible to run a FrontendAction over a snippet of code by
+// calling runToolOnCode, which is useful for unit testing.
+//
+// Applications that need more fine grained control over how to run
+// multiple FrontendActions over code can use ToolInvocation.
+//
+// Example tools:
+// - running clang -fsyntax-only over source code from an editor to get
+// fast syntax checks
+// - running match/replace tools over C++ code
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_TOOLING_TOOLING_H
+#define LLVM_CLANG_TOOLING_TOOLING_H
+
+#include "clang/AST/ASTConsumer.h"
+#include "clang/Frontend/PCHContainerOperations.h"
+#include "clang/Basic/Diagnostic.h"
+#include "clang/Basic/FileManager.h"
+#include "clang/Basic/LLVM.h"
+#include "clang/Driver/Util.h"
+#include "clang/Frontend/FrontendAction.h"
+#include "clang/Lex/ModuleLoader.h"
+#include "clang/Tooling/ArgumentsAdjusters.h"
+#include "clang/Tooling/CompilationDatabase.h"
+#include "llvm/ADT/StringMap.h"
+#include "llvm/ADT/Twine.h"
+#include "llvm/Option/Option.h"
+#include <memory>
+#include <string>
+#include <vector>
+
+namespace clang {
+
+namespace driver {
+class Compilation;
+} // end namespace driver
+
+class CompilerInvocation;
+class SourceManager;
+class FrontendAction;
+
+namespace tooling {
+
+/// \brief Interface to process a clang::CompilerInvocation.
+///
+/// If your tool is based on FrontendAction, you should be deriving from
+/// FrontendActionFactory instead.
+class ToolAction {
+public:
+ virtual ~ToolAction();
+
+ /// \brief Perform an action for an invocation.
+ virtual bool
+ runInvocation(clang::CompilerInvocation *Invocation, FileManager *Files,
+ std::shared_ptr<PCHContainerOperations> PCHContainerOps,
+ DiagnosticConsumer *DiagConsumer) = 0;
+};
+
+/// \brief Interface to generate clang::FrontendActions.
+///
+/// Having a factory interface allows, for example, a new FrontendAction to be
+/// created for each translation unit processed by ClangTool. This class is
+/// also a ToolAction which uses the FrontendActions created by create() to
+/// process each translation unit.
+class FrontendActionFactory : public ToolAction {
+public:
+ ~FrontendActionFactory() override;
+
+ /// \brief Invokes the compiler with a FrontendAction created by create().
+ bool runInvocation(clang::CompilerInvocation *Invocation, FileManager *Files,
+ std::shared_ptr<PCHContainerOperations> PCHContainerOps,
+ DiagnosticConsumer *DiagConsumer) override;
+
+ /// \brief Returns a new clang::FrontendAction.
+ ///
+ /// The caller takes ownership of the returned action.
+ virtual clang::FrontendAction *create() = 0;
+};
+
+/// \brief Returns a new FrontendActionFactory for a given type.
+///
+/// T must derive from clang::FrontendAction.
+///
+/// Example:
+/// FrontendActionFactory *Factory =
+/// newFrontendActionFactory<clang::SyntaxOnlyAction>();
+template <typename T>
+std::unique_ptr<FrontendActionFactory> newFrontendActionFactory();
+
+/// \brief Callbacks called before and after each source file processed by a
+/// FrontendAction created by the FrontedActionFactory returned by \c
+/// newFrontendActionFactory.
+class SourceFileCallbacks {
+public:
+ virtual ~SourceFileCallbacks() {}
+
+ /// \brief Called before a source file is processed by a FrontEndAction.
+ /// \see clang::FrontendAction::BeginSourceFileAction
+ virtual bool handleBeginSource(CompilerInstance &CI, StringRef Filename) {
+ return true;
+ }
+
+ /// \brief Called after a source file is processed by a FrontendAction.
+ /// \see clang::FrontendAction::EndSourceFileAction
+ virtual void handleEndSource() {}
+};
+
+/// \brief Returns a new FrontendActionFactory for any type that provides an
+/// implementation of newASTConsumer().
+///
+/// FactoryT must implement: ASTConsumer *newASTConsumer().
+///
+/// Example:
+/// struct ProvidesASTConsumers {
+/// clang::ASTConsumer *newASTConsumer();
+/// } Factory;
+/// std::unique_ptr<FrontendActionFactory> FactoryAdapter(
+/// newFrontendActionFactory(&Factory));
+template <typename FactoryT>
+inline std::unique_ptr<FrontendActionFactory> newFrontendActionFactory(
+ FactoryT *ConsumerFactory, SourceFileCallbacks *Callbacks = nullptr);
+
+/// \brief Runs (and deletes) the tool on 'Code' with the -fsyntax-only flag.
+///
+/// \param ToolAction The action to run over the code.
+/// \param Code C++ code.
+/// \param FileName The file name which 'Code' will be mapped as.
+/// \param PCHContainerOps The PCHContainerOperations for loading and creating
+/// clang modules.
+///
+/// \return - True if 'ToolAction' was successfully executed.
+bool runToolOnCode(clang::FrontendAction *ToolAction, const Twine &Code,
+ const Twine &FileName = "input.cc",
+ std::shared_ptr<PCHContainerOperations> PCHContainerOps =
+ std::make_shared<PCHContainerOperations>());
+
+/// The first part of the pair is the filename, the second part the
+/// file-content.
+typedef std::vector<std::pair<std::string, std::string>> FileContentMappings;
+
+/// \brief Runs (and deletes) the tool on 'Code' with the -fsyntax-only flag and
+/// with additional other flags.
+///
+/// \param ToolAction The action to run over the code.
+/// \param Code C++ code.
+/// \param Args Additional flags to pass on.
+/// \param FileName The file name which 'Code' will be mapped as.
+/// \param PCHContainerOps The PCHContainerOperations for loading and creating
+/// clang modules.
+///
+/// \return - True if 'ToolAction' was successfully executed.
+bool runToolOnCodeWithArgs(
+ clang::FrontendAction *ToolAction, const Twine &Code,
+ const std::vector<std::string> &Args, const Twine &FileName = "input.cc",
+ std::shared_ptr<PCHContainerOperations> PCHContainerOps =
+ std::make_shared<PCHContainerOperations>(),
+ const FileContentMappings &VirtualMappedFiles = FileContentMappings());
+
+/// \brief Builds an AST for 'Code'.
+///
+/// \param Code C++ code.
+/// \param FileName The file name which 'Code' will be mapped as.
+/// \param PCHContainerOps The PCHContainerOperations for loading and creating
+/// clang modules.
+///
+/// \return The resulting AST or null if an error occurred.
+std::unique_ptr<ASTUnit>
+buildASTFromCode(const Twine &Code, const Twine &FileName = "input.cc",
+ std::shared_ptr<PCHContainerOperations> PCHContainerOps =
+ std::make_shared<PCHContainerOperations>());
+
+/// \brief Builds an AST for 'Code' with additional flags.
+///
+/// \param Code C++ code.
+/// \param Args Additional flags to pass on.
+/// \param FileName The file name which 'Code' will be mapped as.
+/// \param PCHContainerOps The PCHContainerOperations for loading and creating
+/// clang modules.
+///
+/// \return The resulting AST or null if an error occurred.
+std::unique_ptr<ASTUnit> buildASTFromCodeWithArgs(
+ const Twine &Code, const std::vector<std::string> &Args,
+ const Twine &FileName = "input.cc",
+ std::shared_ptr<PCHContainerOperations> PCHContainerOps =
+ std::make_shared<PCHContainerOperations>());
+
+/// \brief Utility to run a FrontendAction in a single clang invocation.
+class ToolInvocation {
+public:
+ /// \brief Create a tool invocation.
+ ///
+ /// \param CommandLine The command line arguments to clang. Note that clang
+ /// uses its binary name (CommandLine[0]) to locate its builtin headers.
+ /// Callers have to ensure that they are installed in a compatible location
+ /// (see clang driver implementation) or mapped in via mapVirtualFile.
+ /// \param FAction The action to be executed. Class takes ownership.
+ /// \param Files The FileManager used for the execution. Class does not take
+ /// ownership.
+ /// \param PCHContainerOps The PCHContainerOperations for loading and creating
+ /// clang modules.
+ ToolInvocation(std::vector<std::string> CommandLine, FrontendAction *FAction,
+ FileManager *Files,
+ std::shared_ptr<PCHContainerOperations> PCHContainerOps =
+ std::make_shared<PCHContainerOperations>());
+
+ /// \brief Create a tool invocation.
+ ///
+ /// \param CommandLine The command line arguments to clang.
+ /// \param Action The action to be executed.
+ /// \param Files The FileManager used for the execution.
+ /// \param PCHContainerOps The PCHContainerOperations for loading and creating
+ /// clang modules.
+ ToolInvocation(std::vector<std::string> CommandLine, ToolAction *Action,
+ FileManager *Files,
+ std::shared_ptr<PCHContainerOperations> PCHContainerOps);
+
+ ~ToolInvocation();
+
+ /// \brief Set a \c DiagnosticConsumer to use during parsing.
+ void setDiagnosticConsumer(DiagnosticConsumer *DiagConsumer) {
+ this->DiagConsumer = DiagConsumer;
+ }
+
+ /// \brief Map a virtual file to be used while running the tool.
+ ///
+ /// \param FilePath The path at which the content will be mapped.
+ /// \param Content A null terminated buffer of the file's content.
+ // FIXME: remove this when all users have migrated!
+ void mapVirtualFile(StringRef FilePath, StringRef Content);
+
+ /// \brief Run the clang invocation.
+ ///
+ /// \returns True if there were no errors during execution.
+ bool run();
+
+ private:
+ void addFileMappingsTo(SourceManager &SourceManager);
+
+ bool runInvocation(const char *BinaryName,
+ clang::driver::Compilation *Compilation,
+ clang::CompilerInvocation *Invocation,
+ std::shared_ptr<PCHContainerOperations> PCHContainerOps);
+
+ std::vector<std::string> CommandLine;
+ ToolAction *Action;
+ bool OwnsAction;
+ FileManager *Files;
+ std::shared_ptr<PCHContainerOperations> PCHContainerOps;
+ // Maps <file name> -> <file content>.
+ llvm::StringMap<StringRef> MappedFileContents;
+ DiagnosticConsumer *DiagConsumer;
+};
+
+/// \brief Utility to run a FrontendAction over a set of files.
+///
+/// This class is written to be usable for command line utilities.
+/// By default the class uses ClangSyntaxOnlyAdjuster to modify
+/// command line arguments before the arguments are used to run
+/// a frontend action. One could install an additional command line
+/// arguments adjuster by calling the appendArgumentsAdjuster() method.
+class ClangTool {
+ public:
+ /// \brief Constructs a clang tool to run over a list of files.
+ ///
+ /// \param Compilations The CompilationDatabase which contains the compile
+ /// command lines for the given source paths.
+ /// \param SourcePaths The source files to run over. If a source files is
+ /// not found in Compilations, it is skipped.
+ /// \param PCHContainerOps The PCHContainerOperations for loading and creating
+ /// clang modules.
+ ClangTool(const CompilationDatabase &Compilations,
+ ArrayRef<std::string> SourcePaths,
+ std::shared_ptr<PCHContainerOperations> PCHContainerOps =
+ std::make_shared<PCHContainerOperations>());
+
+ ~ClangTool();
+
+ /// \brief Set a \c DiagnosticConsumer to use during parsing.
+ void setDiagnosticConsumer(DiagnosticConsumer *DiagConsumer) {
+ this->DiagConsumer = DiagConsumer;
+ }
+
+ /// \brief Map a virtual file to be used while running the tool.
+ ///
+ /// \param FilePath The path at which the content will be mapped.
+ /// \param Content A null terminated buffer of the file's content.
+ void mapVirtualFile(StringRef FilePath, StringRef Content);
+
+ /// \brief Append a command line arguments adjuster to the adjuster chain.
+ ///
+ /// \param Adjuster An argument adjuster, which will be run on the output of
+ /// previous argument adjusters.
+ void appendArgumentsAdjuster(ArgumentsAdjuster Adjuster);
+
+ /// \brief Clear the command line arguments adjuster chain.
+ void clearArgumentsAdjusters();
+
+ /// Runs an action over all files specified in the command line.
+ ///
+ /// \param Action Tool action.
+ int run(ToolAction *Action);
+
+ /// \brief Create an AST for each file specified in the command line and
+ /// append them to ASTs.
+ int buildASTs(std::vector<std::unique_ptr<ASTUnit>> &ASTs);
+
+ /// \brief Returns the file manager used in the tool.
+ ///
+ /// The file manager is shared between all translation units.
+ FileManager &getFiles() { return *Files; }
+
+ private:
+ const CompilationDatabase &Compilations;
+ std::vector<std::string> SourcePaths;
+ std::shared_ptr<PCHContainerOperations> PCHContainerOps;
+
+ llvm::IntrusiveRefCntPtr<vfs::OverlayFileSystem> OverlayFileSystem;
+ llvm::IntrusiveRefCntPtr<vfs::InMemoryFileSystem> InMemoryFileSystem;
+ llvm::IntrusiveRefCntPtr<FileManager> Files;
+ // Contains a list of pairs (<file name>, <file content>).
+ std::vector< std::pair<StringRef, StringRef> > MappedFileContents;
+ llvm::StringSet<> SeenWorkingDirectories;
+
+ ArgumentsAdjuster ArgsAdjuster;
+
+ DiagnosticConsumer *DiagConsumer;
+};
+
+template <typename T>
+std::unique_ptr<FrontendActionFactory> newFrontendActionFactory() {
+ class SimpleFrontendActionFactory : public FrontendActionFactory {
+ public:
+ clang::FrontendAction *create() override { return new T; }
+ };
+
+ return std::unique_ptr<FrontendActionFactory>(
+ new SimpleFrontendActionFactory);
+}
+
+template <typename FactoryT>
+inline std::unique_ptr<FrontendActionFactory> newFrontendActionFactory(
+ FactoryT *ConsumerFactory, SourceFileCallbacks *Callbacks) {
+ class FrontendActionFactoryAdapter : public FrontendActionFactory {
+ public:
+ explicit FrontendActionFactoryAdapter(FactoryT *ConsumerFactory,
+ SourceFileCallbacks *Callbacks)
+ : ConsumerFactory(ConsumerFactory), Callbacks(Callbacks) {}
+
+ clang::FrontendAction *create() override {
+ return new ConsumerFactoryAdaptor(ConsumerFactory, Callbacks);
+ }
+
+ private:
+ class ConsumerFactoryAdaptor : public clang::ASTFrontendAction {
+ public:
+ ConsumerFactoryAdaptor(FactoryT *ConsumerFactory,
+ SourceFileCallbacks *Callbacks)
+ : ConsumerFactory(ConsumerFactory), Callbacks(Callbacks) {}
+
+ std::unique_ptr<clang::ASTConsumer>
+ CreateASTConsumer(clang::CompilerInstance &, StringRef) override {
+ return ConsumerFactory->newASTConsumer();
+ }
+
+ protected:
+ bool BeginSourceFileAction(CompilerInstance &CI,
+ StringRef Filename) override {
+ if (!clang::ASTFrontendAction::BeginSourceFileAction(CI, Filename))
+ return false;
+ if (Callbacks)
+ return Callbacks->handleBeginSource(CI, Filename);
+ return true;
+ }
+ void EndSourceFileAction() override {
+ if (Callbacks)
+ Callbacks->handleEndSource();
+ clang::ASTFrontendAction::EndSourceFileAction();
+ }
+
+ private:
+ FactoryT *ConsumerFactory;
+ SourceFileCallbacks *Callbacks;
+ };
+ FactoryT *ConsumerFactory;
+ SourceFileCallbacks *Callbacks;
+ };
+
+ return std::unique_ptr<FrontendActionFactory>(
+ new FrontendActionFactoryAdapter(ConsumerFactory, Callbacks));
+}
+
+/// \brief Returns the absolute path of \c File, by prepending it with
+/// the current directory if \c File is not absolute.
+///
+/// Otherwise returns \c File.
+/// If 'File' starts with "./", the returned path will not contain the "./".
+/// Otherwise, the returned path will contain the literal path-concatenation of
+/// the current directory and \c File.
+///
+/// The difference to llvm::sys::fs::make_absolute is the canonicalization this
+/// does by removing "./" and computing native paths.
+///
+/// \param File Either an absolute or relative path.
+std::string getAbsolutePath(StringRef File);
+
+/// \brief Changes CommandLine to contain implicit flags that would have been
+/// defined had the compiler driver been invoked through the path InvokedAs.
+///
+/// For example, when called with \c InvokedAs set to `i686-linux-android-g++`,
+/// the arguments '-target', 'i686-linux-android`, `--driver-mode=g++` will
+/// be inserted after the first argument in \c CommandLine.
+///
+/// This function will not add new `-target` or `--driver-mode` flags if they
+/// are already present in `CommandLine` (even if they have different settings
+/// than would have been inserted).
+///
+/// \pre `llvm::InitializeAllTargets()` has been called.
+///
+/// \param CommandLine the command line used to invoke the compiler driver or
+/// Clang tool, including the path to the executable as \c CommandLine[0].
+/// \param InvokedAs the path to the driver used to infer implicit flags.
+///
+/// \note This will not set \c CommandLine[0] to \c InvokedAs. The tooling
+/// infrastructure expects that CommandLine[0] is a tool path relative to which
+/// the builtin headers can be found.
+void addTargetAndModeForProgramName(std::vector<std::string> &CommandLine,
+ StringRef InvokedAs);
+
+/// \brief Creates a \c CompilerInvocation.
+clang::CompilerInvocation *newInvocation(
+ clang::DiagnosticsEngine *Diagnostics,
+ const llvm::opt::ArgStringList &CC1Args);
+
+} // end namespace tooling
+} // end namespace clang
+
+#endif // LLVM_CLANG_TOOLING_TOOLING_H
diff --git a/contrib/llvm/tools/clang/include/clang/module.modulemap b/contrib/llvm/tools/clang/include/clang/module.modulemap
new file mode 100644
index 0000000..28b6d16
--- /dev/null
+++ b/contrib/llvm/tools/clang/include/clang/module.modulemap
@@ -0,0 +1,134 @@
+module Clang_Analysis {
+ requires cplusplus
+ umbrella "Analysis"
+
+ textual header "Analysis/Analyses/ThreadSafetyOps.def"
+
+ module * { export * }
+}
+
+module Clang_AST {
+ requires cplusplus
+ umbrella "AST"
+
+ textual header "AST/BuiltinTypes.def"
+ textual header "AST/TypeLocNodes.def"
+ textual header "AST/TypeNodes.def"
+
+ module * { export * }
+}
+
+module Clang_ASTMatchers { requires cplusplus umbrella "ASTMatchers" module * { export * } }
+
+module Clang_Basic {
+ requires cplusplus
+ umbrella "Basic"
+
+ textual header "Basic/BuiltinsAArch64.def"
+ textual header "Basic/BuiltinsAMDGPU.def"
+ textual header "Basic/BuiltinsARM.def"
+ textual header "Basic/Builtins.def"
+ textual header "Basic/BuiltinsHexagon.def"
+ textual header "Basic/BuiltinsLe64.def"
+ textual header "Basic/BuiltinsMips.def"
+ textual header "Basic/BuiltinsNEON.def"
+ textual header "Basic/BuiltinsNVPTX.def"
+ textual header "Basic/BuiltinsPPC.def"
+ textual header "Basic/BuiltinsSystemZ.def"
+ textual header "Basic/BuiltinsWebAssembly.def"
+ textual header "Basic/BuiltinsX86.def"
+ textual header "Basic/BuiltinsXCore.def"
+ textual header "Basic/DiagnosticOptions.def"
+ textual header "Basic/LangOptions.def"
+ textual header "Basic/OpenCLExtensions.def"
+ textual header "Basic/OpenMPKinds.def"
+ textual header "Basic/OperatorKinds.def"
+ textual header "Basic/Sanitizers.def"
+ textual header "Basic/TokenKinds.def"
+
+ module * { export * }
+}
+
+module Clang_CodeGen { requires cplusplus umbrella "CodeGen" module * { export * } }
+module Clang_Config { requires cplusplus umbrella "Config" module * { export * } }
+
+// Files for diagnostic groups are spread all over the include/clang/ tree, but
+// logically form a single module.
+module Clang_Diagnostics {
+ requires cplusplus
+
+ module All { header "Basic/AllDiagnostics.h" export * }
+ module Analysis { header "Analysis/AnalysisDiagnostic.h" export * }
+ module AST { header "AST/ASTDiagnostic.h" export * }
+ module Comment { header "AST/CommentDiagnostic.h" export * }
+ module Driver { header "Driver/DriverDiagnostic.h" export * }
+ module Frontend { header "Frontend/FrontendDiagnostic.h" export * }
+ module Lex { header "Lex/LexDiagnostic.h" export * }
+ module Parse { header "Parse/ParseDiagnostic.h" export * }
+ // FIXME: This breaks the build of Clang_Sema, for unknown reasons.
+ //module Sema { header "Sema/SemaDiagnostic.h" export * }
+ module Serialization { header "Serialization/SerializationDiagnostic.h" export * }
+}
+
+module Clang_Driver {
+ requires cplusplus
+ umbrella "Driver"
+
+ textual header "Driver/Types.def"
+
+ module * { export * }
+}
+
+module Clang_Edit { requires cplusplus umbrella "Edit" module * { export * } }
+module Clang_Format { requires cplusplus umbrella "Format" module * { export * } }
+
+module Clang_Frontend {
+ requires cplusplus
+ umbrella "Frontend"
+
+ textual header "Frontend/CodeGenOptions.def"
+ textual header "Frontend/LangStandards.def"
+
+ module * { export * }
+
+ // FIXME: This violates layers.
+ exclude header "Frontend/PCHContainerOperations.h"
+}
+
+module Clang_FrontendTool { requires cplusplus umbrella "FrontendTool" module * { export * } }
+module Clang_Index { requires cplusplus umbrella "Index" module * { export * } }
+module Clang_Lex { requires cplusplus umbrella "Lex" module * { export * } }
+module Clang_Parse { requires cplusplus umbrella "Parse" module * { export * } }
+module Clang_Rewrite { requires cplusplus umbrella "Rewrite" module * { export * } }
+module Clang_Sema { requires cplusplus umbrella "Sema" module * { export * } }
+module Clang_Serialization { requires cplusplus umbrella "Serialization" module * { export * } }
+
+module Clang_StaticAnalyzer_Core {
+ requires cplusplus
+ umbrella "StaticAnalyzer/Core"
+
+ textual header "StaticAnalyzer/Core/Analyses.def"
+
+ module * { export * }
+}
+
+module Clang_StaticAnalyzer_Checkers {
+ requires cplusplus
+ umbrella "StaticAnalyzer/Checkers"
+ module * { export * }
+}
+
+module Clang_StaticAnalyzer_Frontend {
+ requires cplusplus
+ umbrella "StaticAnalyzer/Frontend"
+ module * { export * }
+}
+
+module Clang_Tooling {
+ requires cplusplus umbrella "Tooling" module * { export * }
+ // FIXME: Exclude this header to avoid pulling all of the AST matchers
+ // library into clang-format. Due to inline key functions in the headers,
+ // importing the AST matchers library gives a link dependency on the AST
+ // matchers (and thus the AST), which clang-format should not have.
+ exclude header "Tooling/RefactoringCallbacks.h"
+}
OpenPOWER on IntegriCloud