aboutsummaryrefslogtreecommitdiff
path: root/include
diff options
context:
space:
mode:
authorDimitry Andric <dim@FreeBSD.org>2014-11-24 09:15:30 +0000
committerDimitry Andric <dim@FreeBSD.org>2014-11-24 09:15:30 +0000
commit9f4dbff6669c8037f3b036bcf580d14f1a4f12a5 (patch)
tree47df2c12b57214af6c31e47404b005675b8b7ffc /include
parentf73d5f23a889b93d89ddef61ac0995df40286bb8 (diff)
downloadsrc-9f4dbff6669c8037f3b036bcf580d14f1a4f12a5.tar.gz
src-9f4dbff6669c8037f3b036bcf580d14f1a4f12a5.zip
Vendor import of clang RELEASE_350/final tag r216957 (effectively, 3.5.0 release):vendor/clang/clang-release_350-r216957
Notes
Notes: svn path=/vendor/clang/dist/; revision=274958 svn path=/vendor/clang/clang-release_350-r216957/; revision=274959; tag=vendor/clang/clang-release_350-r216957
Diffstat (limited to 'include')
-rw-r--r--include/clang-c/BuildSystem.h148
-rw-r--r--include/clang-c/CXErrorCode.h64
-rw-r--r--include/clang-c/CXString.h2
-rw-r--r--include/clang-c/Documentation.h554
-rw-r--r--include/clang-c/Index.h825
-rw-r--r--include/clang-c/module.modulemap4
-rw-r--r--include/clang/ARCMigrate/ARCMT.h2
-rw-r--r--include/clang/ARCMigrate/ARCMTActions.h19
-rw-r--r--include/clang/ARCMigrate/FileRemapper.h6
-rw-r--r--include/clang/AST/APValue.h123
-rw-r--r--include/clang/AST/ASTConsumer.h14
-rw-r--r--include/clang/AST/ASTContext.h227
-rw-r--r--include/clang/AST/ASTDiagnostic.h9
-rw-r--r--include/clang/AST/ASTImporter.h2
-rw-r--r--include/clang/AST/ASTLambda.h4
-rw-r--r--include/clang/AST/ASTMutationListener.h7
-rw-r--r--include/clang/AST/ASTTypeTraits.h42
-rw-r--r--include/clang/AST/ASTUnresolvedSet.h3
-rw-r--r--include/clang/AST/ASTVector.h49
-rw-r--r--include/clang/AST/Attr.h48
-rw-r--r--include/clang/AST/AttrIterator.h8
-rw-r--r--include/clang/AST/CMakeLists.txt5
-rw-r--r--include/clang/AST/CXXInheritance.h11
-rw-r--r--include/clang/AST/CanonicalType.h31
-rw-r--r--include/clang/AST/CharUnits.h9
-rw-r--r--include/clang/AST/Comment.h67
-rw-r--r--include/clang/AST/CommentCommands.td2
-rw-r--r--include/clang/AST/CommentHTMLTags.td13
-rw-r--r--include/clang/AST/CommentLexer.h16
-rw-r--r--include/clang/AST/CommentSema.h4
-rw-r--r--include/clang/AST/DataRecursiveASTVisitor.h2519
-rw-r--r--include/clang/AST/Decl.h474
-rw-r--r--include/clang/AST/DeclBase.h200
-rw-r--r--include/clang/AST/DeclCXX.h383
-rw-r--r--include/clang/AST/DeclContextInternals.h19
-rw-r--r--include/clang/AST/DeclFriend.h15
-rw-r--r--include/clang/AST/DeclGroup.h12
-rw-r--r--include/clang/AST/DeclLookups.h34
-rw-r--r--include/clang/AST/DeclObjC.h504
-rw-r--r--include/clang/AST/DeclOpenMP.h19
-rw-r--r--include/clang/AST/DeclTemplate.h288
-rw-r--r--include/clang/AST/DeclarationName.h9
-rw-r--r--include/clang/AST/DependentDiagnostic.h12
-rw-r--r--include/clang/AST/Expr.h186
-rw-r--r--include/clang/AST/ExprCXX.h392
-rw-r--r--include/clang/AST/ExprObjC.h20
-rw-r--r--include/clang/AST/ExternalASTSource.h161
-rw-r--r--include/clang/AST/LambdaCapture.h123
-rw-r--r--include/clang/AST/Makefile8
-rw-r--r--include/clang/AST/Mangle.h58
-rw-r--r--include/clang/AST/MangleNumberingContext.h10
-rw-r--r--include/clang/AST/NestedNameSpecifier.h14
-rw-r--r--include/clang/AST/OpenMPClause.h1455
-rw-r--r--include/clang/AST/OperationKinds.h5
-rw-r--r--include/clang/AST/ParentMap.h2
-rw-r--r--include/clang/AST/PrettyPrinter.h12
-rw-r--r--include/clang/AST/RawCommentList.h4
-rw-r--r--include/clang/AST/RecordLayout.h44
-rw-r--r--include/clang/AST/RecursiveASTVisitor.h2320
-rw-r--r--include/clang/AST/Redeclarable.h121
-rw-r--r--include/clang/AST/Stmt.h146
-rw-r--r--include/clang/AST/StmtCXX.h2
-rw-r--r--include/clang/AST/StmtIterator.h6
-rw-r--r--include/clang/AST/StmtObjC.h6
-rw-r--r--include/clang/AST/StmtOpenMP.h1159
-rw-r--r--include/clang/AST/TemplateBase.h36
-rw-r--r--include/clang/AST/TemplateName.h18
-rw-r--r--include/clang/AST/Type.h256
-rw-r--r--include/clang/AST/TypeLoc.h49
-rw-r--r--include/clang/AST/TypeNodes.def3
-rw-r--r--include/clang/AST/UnresolvedSet.h2
-rw-r--r--include/clang/AST/VTableBuilder.h177
-rw-r--r--include/clang/ASTMatchers/ASTMatchFinder.h4
-rw-r--r--include/clang/ASTMatchers/ASTMatchers.h316
-rw-r--r--include/clang/ASTMatchers/ASTMatchersInternal.h470
-rw-r--r--include/clang/ASTMatchers/ASTMatchersMacros.h87
-rw-r--r--include/clang/ASTMatchers/Dynamic/Diagnostics.h8
-rw-r--r--include/clang/ASTMatchers/Dynamic/Parser.h70
-rw-r--r--include/clang/ASTMatchers/Dynamic/Registry.h67
-rw-r--r--include/clang/ASTMatchers/Dynamic/VariantValue.h49
-rw-r--r--include/clang/Analysis/Analyses/Consumed.h13
-rw-r--r--include/clang/Analysis/Analyses/Dominators.h19
-rw-r--r--include/clang/Analysis/Analyses/FormatString.h23
-rw-r--r--include/clang/Analysis/Analyses/LiveVariables.h2
-rw-r--r--include/clang/Analysis/Analyses/PostOrderCFGView.h10
-rw-r--r--include/clang/Analysis/Analyses/ReachableCode.h17
-rw-r--r--include/clang/Analysis/Analyses/ThreadSafety.h52
-rw-r--r--include/clang/Analysis/Analyses/ThreadSafetyCommon.h393
-rw-r--r--include/clang/Analysis/Analyses/ThreadSafetyLogical.h108
-rw-r--r--include/clang/Analysis/Analyses/ThreadSafetyOps.def54
-rw-r--r--include/clang/Analysis/Analyses/ThreadSafetyTIL.h1813
-rw-r--r--include/clang/Analysis/Analyses/ThreadSafetyTraverse.h936
-rw-r--r--include/clang/Analysis/Analyses/ThreadSafetyUtil.h316
-rw-r--r--include/clang/Analysis/AnalysisContext.h28
-rw-r--r--include/clang/Analysis/CFG.h167
-rw-r--r--include/clang/Analysis/FlowSensitive/DataflowSolver.h342
-rw-r--r--include/clang/Analysis/ProgramPoint.h77
-rw-r--r--include/clang/Analysis/Support/BumpVector.h8
-rw-r--r--include/clang/Basic/ABI.h8
-rw-r--r--include/clang/Basic/Attr.td1211
-rw-r--r--include/clang/Basic/AttrDocs.td1105
-rw-r--r--include/clang/Basic/AttrKinds.h1
-rw-r--r--include/clang/Basic/Attributes.h41
-rw-r--r--include/clang/Basic/Builtins.def54
-rw-r--r--include/clang/Basic/Builtins.h24
-rw-r--r--include/clang/Basic/BuiltinsAArch64.def40
-rw-r--r--include/clang/Basic/BuiltinsARM.def35
-rw-r--r--include/clang/Basic/BuiltinsMips.def18
-rw-r--r--include/clang/Basic/BuiltinsNEON.def21
-rw-r--r--include/clang/Basic/BuiltinsR600.def32
-rw-r--r--include/clang/Basic/BuiltinsX86.def7
-rw-r--r--include/clang/Basic/CMakeLists.txt7
-rw-r--r--include/clang/Basic/Diagnostic.h287
-rw-r--r--include/clang/Basic/Diagnostic.td55
-rw-r--r--include/clang/Basic/DiagnosticASTKinds.td4
-rw-r--r--include/clang/Basic/DiagnosticCategories.td1
-rw-r--r--include/clang/Basic/DiagnosticCommentKinds.td6
-rw-r--r--include/clang/Basic/DiagnosticCommonKinds.td23
-rw-r--r--include/clang/Basic/DiagnosticDriverKinds.td29
-rw-r--r--include/clang/Basic/DiagnosticFrontendKinds.td52
-rw-r--r--include/clang/Basic/DiagnosticGroups.td141
-rw-r--r--include/clang/Basic/DiagnosticIDs.h86
-rw-r--r--include/clang/Basic/DiagnosticLexKinds.td50
-rw-r--r--include/clang/Basic/DiagnosticOptions.h6
-rw-r--r--include/clang/Basic/DiagnosticParseKinds.td214
-rw-r--r--include/clang/Basic/DiagnosticSemaKinds.td1023
-rw-r--r--include/clang/Basic/DiagnosticSerializationKinds.td29
-rw-r--r--include/clang/Basic/FileManager.h82
-rw-r--r--include/clang/Basic/FileSystemStatCache.h48
-rw-r--r--include/clang/Basic/IdentifierTable.h13
-rw-r--r--include/clang/Basic/LLVM.h6
-rw-r--r--include/clang/Basic/LangOptions.def19
-rw-r--r--include/clang/Basic/LangOptions.h12
-rw-r--r--include/clang/Basic/Linkage.h9
-rw-r--r--include/clang/Basic/Makefile10
-rw-r--r--include/clang/Basic/Module.h88
-rw-r--r--include/clang/Basic/ObjCRuntime.h5
-rw-r--r--include/clang/Basic/OnDiskHashTable.h485
-rw-r--r--include/clang/Basic/OpenCL.h29
-rw-r--r--include/clang/Basic/OpenMPKinds.def160
-rw-r--r--include/clang/Basic/OpenMPKinds.h64
-rw-r--r--include/clang/Basic/OperatorKinds.h2
-rw-r--r--include/clang/Basic/PartialDiagnostic.h48
-rw-r--r--include/clang/Basic/PlistSupport.h122
-rw-r--r--include/clang/Basic/PrettyStackTrace.h2
-rw-r--r--include/clang/Basic/Sanitizers.def10
-rw-r--r--include/clang/Basic/SourceLocation.h30
-rw-r--r--include/clang/Basic/SourceManager.h184
-rw-r--r--include/clang/Basic/Specifiers.h10
-rw-r--r--include/clang/Basic/StmtNodes.td17
-rw-r--r--include/clang/Basic/TargetBuiltins.h42
-rw-r--r--include/clang/Basic/TargetCXXABI.h22
-rw-r--r--include/clang/Basic/TargetInfo.h84
-rw-r--r--include/clang/Basic/TargetOptions.h8
-rw-r--r--include/clang/Basic/TemplateKinds.h1
-rw-r--r--include/clang/Basic/TokenKinds.def191
-rw-r--r--include/clang/Basic/TokenKinds.h12
-rw-r--r--include/clang/Basic/TypeTraits.h26
-rw-r--r--include/clang/Basic/Version.h3
-rw-r--r--include/clang/Basic/VersionTuple.h10
-rw-r--r--include/clang/Basic/VirtualFileSystem.h283
-rw-r--r--include/clang/Basic/arm_neon.td954
-rw-r--r--include/clang/CMakeLists.txt1
-rw-r--r--include/clang/CodeGen/BackendUtil.h8
-rw-r--r--include/clang/CodeGen/CGFunctionInfo.h237
-rw-r--r--include/clang/CodeGen/CodeGenABITypes.h19
-rw-r--r--include/clang/CodeGen/CodeGenAction.h28
-rw-r--r--include/clang/CodeGen/ModuleBuilder.h2
-rw-r--r--include/clang/Config/config.h.cmake15
-rw-r--r--include/clang/Config/config.h.in14
-rw-r--r--include/clang/Driver/Action.h49
-rw-r--r--include/clang/Driver/CC1AsOptions.h37
-rw-r--r--include/clang/Driver/CC1AsOptions.td95
-rw-r--r--include/clang/Driver/CC1Options.h0
-rw-r--r--include/clang/Driver/CC1Options.td115
-rw-r--r--include/clang/Driver/CLCompatOptions.td61
-rw-r--r--include/clang/Driver/CMakeLists.txt4
-rw-r--r--include/clang/Driver/Compilation.h6
-rw-r--r--include/clang/Driver/Driver.h7
-rw-r--r--include/clang/Driver/Job.h22
-rw-r--r--include/clang/Driver/Makefile6
-rw-r--r--include/clang/Driver/Multilib.h167
-rw-r--r--include/clang/Driver/Options.h3
-rw-r--r--include/clang/Driver/Options.td391
-rw-r--r--include/clang/Driver/SanitizerArgs.h13
-rw-r--r--include/clang/Driver/ToolChain.h30
-rw-r--r--include/clang/Driver/Types.def22
-rw-r--r--include/clang/Edit/Commit.h13
-rw-r--r--include/clang/Edit/EditedSource.h11
-rw-r--r--include/clang/Edit/FileOffset.h12
-rw-r--r--include/clang/Format/Format.h208
-rw-r--r--include/clang/Frontend/ASTUnit.h201
-rw-r--r--include/clang/Frontend/ChainedDiagnosticConsumer.h20
-rw-r--r--include/clang/Frontend/ChainedIncludesSource.h75
-rw-r--r--include/clang/Frontend/CodeGenOptions.def12
-rw-r--r--include/clang/Frontend/CodeGenOptions.h53
-rw-r--r--include/clang/Frontend/CompilerInstance.h157
-rw-r--r--include/clang/Frontend/CompilerInvocation.h28
-rw-r--r--include/clang/Frontend/DependencyOutputOptions.h7
-rw-r--r--include/clang/Frontend/DiagnosticRenderer.h28
-rw-r--r--include/clang/Frontend/FrontendAction.h54
-rw-r--r--include/clang/Frontend/FrontendActions.h149
-rw-r--r--include/clang/Frontend/FrontendOptions.h14
-rw-r--r--include/clang/Frontend/FrontendPluginRegistry.h3
-rw-r--r--include/clang/Frontend/LangStandard.h16
-rw-r--r--include/clang/Frontend/LangStandards.def20
-rw-r--r--include/clang/Frontend/LayoutOverrideSource.h5
-rw-r--r--include/clang/Frontend/LogDiagnosticPrinter.h13
-rw-r--r--include/clang/Frontend/MultiplexConsumer.h43
-rw-r--r--include/clang/Frontend/SerializedDiagnosticPrinter.h13
-rw-r--r--include/clang/Frontend/TextDiagnostic.h64
-rw-r--r--include/clang/Frontend/TextDiagnosticBuffer.h9
-rw-r--r--include/clang/Frontend/TextDiagnosticPrinter.h11
-rw-r--r--include/clang/Frontend/Utils.h108
-rw-r--r--include/clang/Frontend/VerifyDiagnosticConsumer.h62
-rw-r--r--include/clang/Index/CommentToXML.h6
-rw-r--r--include/clang/Index/USRGeneration.h12
-rw-r--r--include/clang/Lex/CMakeLists.txt5
-rw-r--r--include/clang/Lex/DirectoryLookup.h20
-rw-r--r--include/clang/Lex/HeaderMap.h5
-rw-r--r--include/clang/Lex/HeaderSearch.h98
-rw-r--r--include/clang/Lex/HeaderSearchOptions.h29
-rw-r--r--include/clang/Lex/Lexer.h47
-rw-r--r--include/clang/Lex/LiteralSupport.h20
-rw-r--r--include/clang/Lex/MacroArgs.h5
-rw-r--r--include/clang/Lex/MacroInfo.h72
-rw-r--r--include/clang/Lex/Makefile13
-rw-r--r--include/clang/Lex/ModuleLoader.h36
-rw-r--r--include/clang/Lex/ModuleMap.h66
-rw-r--r--include/clang/Lex/MultipleIncludeOpt.h10
-rw-r--r--include/clang/Lex/PPCallbacks.h122
-rw-r--r--include/clang/Lex/PPConditionalDirectiveRecord.h20
-rw-r--r--include/clang/Lex/PTHLexer.h4
-rw-r--r--include/clang/Lex/PTHManager.h2
-rw-r--r--include/clang/Lex/Pragma.h12
-rw-r--r--include/clang/Lex/PreprocessingRecord.h47
-rw-r--r--include/clang/Lex/Preprocessor.h662
-rw-r--r--include/clang/Lex/PreprocessorLexer.h2
-rw-r--r--include/clang/Lex/PreprocessorOptions.h56
-rw-r--r--include/clang/Lex/Token.h28
-rw-r--r--include/clang/Lex/TokenLexer.h19
-rw-r--r--include/clang/Makefile2
-rw-r--r--include/clang/Parse/CMakeLists.txt14
-rw-r--r--include/clang/Parse/Makefile20
-rw-r--r--include/clang/Parse/ParseAST.h2
-rw-r--r--include/clang/Parse/Parser.h532
-rw-r--r--include/clang/Rewrite/Core/HTMLRewrite.h2
-rw-r--r--include/clang/Rewrite/Core/RewriteRope.h16
-rw-r--r--include/clang/Rewrite/Core/Rewriter.h4
-rw-r--r--include/clang/Rewrite/Core/TokenRewriter.h4
-rw-r--r--include/clang/Rewrite/Frontend/FixItRewriter.h10
-rw-r--r--include/clang/Rewrite/Frontend/FrontendActions.h32
-rw-r--r--include/clang/Sema/AttributeList.h220
-rw-r--r--include/clang/Sema/CodeCompleteConsumer.h48
-rw-r--r--include/clang/Sema/DeclSpec.h194
-rw-r--r--include/clang/Sema/DelayedDiagnostic.h30
-rw-r--r--include/clang/Sema/IdentifierResolver.h13
-rw-r--r--include/clang/Sema/Initialization.h73
-rw-r--r--include/clang/Sema/Lookup.h36
-rw-r--r--include/clang/Sema/LoopHint.h40
-rw-r--r--include/clang/Sema/MultiplexExternalSemaSource.h125
-rw-r--r--include/clang/Sema/ObjCMethodList.h2
-rw-r--r--include/clang/Sema/Overload.h40
-rw-r--r--include/clang/Sema/Ownership.h26
-rw-r--r--include/clang/Sema/ParsedTemplate.h4
-rw-r--r--include/clang/Sema/PrettyDeclStackTrace.h2
-rw-r--r--include/clang/Sema/Scope.h168
-rw-r--r--include/clang/Sema/ScopeInfo.h59
-rw-r--r--include/clang/Sema/Sema.h1062
-rw-r--r--include/clang/Sema/SemaInternal.h98
-rw-r--r--include/clang/Sema/SemaLambda.h75
-rw-r--r--include/clang/Sema/Template.h26
-rw-r--r--include/clang/Sema/TemplateDeduction.h11
-rw-r--r--include/clang/Sema/TypoCorrection.h32
-rw-r--r--include/clang/Sema/Weak.h2
-rw-r--r--include/clang/Serialization/ASTBitCodes.h48
-rw-r--r--include/clang/Serialization/ASTDeserializationListener.h5
-rw-r--r--include/clang/Serialization/ASTReader.h427
-rw-r--r--include/clang/Serialization/ASTWriter.h121
-rw-r--r--include/clang/Serialization/GlobalModuleIndex.h7
-rw-r--r--include/clang/Serialization/Module.h42
-rw-r--r--include/clang/Serialization/ModuleManager.h6
-rw-r--r--include/clang/StaticAnalyzer/Checkers/ObjCRetainCount.h9
-rw-r--r--include/clang/StaticAnalyzer/Core/AnalyzerOptions.h31
-rw-r--r--include/clang/StaticAnalyzer/Core/BugReporter/BugReporter.h31
-rw-r--r--include/clang/StaticAnalyzer/Core/BugReporter/BugReporterVisitor.h54
-rw-r--r--include/clang/StaticAnalyzer/Core/BugReporter/BugType.h32
-rw-r--r--include/clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h92
-rw-r--r--include/clang/StaticAnalyzer/Core/Checker.h21
-rw-r--r--include/clang/StaticAnalyzer/Core/CheckerManager.h26
-rw-r--r--include/clang/StaticAnalyzer/Core/PathSensitive/APSIntType.h10
-rw-r--r--include/clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h12
-rw-r--r--include/clang/StaticAnalyzer/Core/PathSensitive/BasicValueFactory.h6
-rw-r--r--include/clang/StaticAnalyzer/Core/PathSensitive/BlockCounter.h6
-rw-r--r--include/clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h268
-rw-r--r--include/clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h31
-rw-r--r--include/clang/StaticAnalyzer/Core/PathSensitive/ConstraintManager.h6
-rw-r--r--include/clang/StaticAnalyzer/Core/PathSensitive/CoreEngine.h26
-rw-r--r--include/clang/StaticAnalyzer/Core/PathSensitive/ExplodedGraph.h14
-rw-r--r--include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h76
-rw-r--r--include/clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h236
-rw-r--r--include/clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h28
-rw-r--r--include/clang/StaticAnalyzer/Core/PathSensitive/ProgramStateTrait.h10
-rw-r--r--include/clang/StaticAnalyzer/Core/PathSensitive/SValBuilder.h8
-rw-r--r--include/clang/StaticAnalyzer/Core/PathSensitive/SVals.h6
-rw-r--r--include/clang/StaticAnalyzer/Core/PathSensitive/Store.h5
-rw-r--r--include/clang/StaticAnalyzer/Core/PathSensitive/SubEngine.h2
-rw-r--r--include/clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.h67
-rw-r--r--include/clang/StaticAnalyzer/Core/PathSensitive/WorkList.h2
-rw-r--r--include/clang/StaticAnalyzer/Frontend/AnalysisConsumer.h49
-rw-r--r--include/clang/StaticAnalyzer/Frontend/FrontendActions.h4
-rw-r--r--include/clang/Tooling/ArgumentsAdjusters.h4
-rw-r--r--include/clang/Tooling/CommonOptionsParser.h16
-rw-r--r--include/clang/Tooling/CompilationDatabase.h16
-rw-r--r--include/clang/Tooling/FileMatchTrie.h4
-rw-r--r--include/clang/Tooling/JSONCompilationDatabase.h12
-rw-r--r--include/clang/Tooling/Refactoring.h15
-rw-r--r--include/clang/Tooling/RefactoringCallbacks.h6
-rw-r--r--include/clang/Tooling/ReplacementsYaml.h14
-rw-r--r--include/clang/Tooling/Tooling.h56
-rw-r--r--include/clang/module.modulemap110
321 files changed, 25702 insertions, 10329 deletions
diff --git a/include/clang-c/BuildSystem.h b/include/clang-c/BuildSystem.h
new file mode 100644
index 000000000000..ed3e8d9a28b3
--- /dev/null
+++ b/include/clang-c/BuildSystem.h
@@ -0,0 +1,148 @@
+/*==-- 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 CLANG_C_BUILD_SYSTEM_H
+#define CLANG_C_BUILD_SYSTEM_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 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 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 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/include/clang-c/CXErrorCode.h b/include/clang-c/CXErrorCode.h
new file mode 100644
index 000000000000..a026c95a5bb9
--- /dev/null
+++ b/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 CLANG_C_CXERRORCODE_H
+#define 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/include/clang-c/CXString.h b/include/clang-c/CXString.h
index 592c4dc44e30..cf198cbf5d0f 100644
--- a/include/clang-c/CXString.h
+++ b/include/clang-c/CXString.h
@@ -31,7 +31,7 @@ extern "C" {
* \brief A character string.
*
* The \c CXString type is used to return strings from the interface when
- * the ownership of that string might different from one call to the next.
+ * 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.
*/
diff --git a/include/clang-c/Documentation.h b/include/clang-c/Documentation.h
new file mode 100644
index 000000000000..ad2da0778315
--- /dev/null
+++ b/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 CLANG_C_DOCUMENTATION_H
+#define 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/include/clang-c/Index.h b/include/clang-c/Index.h
index 95d54c279f03..f69f567c2690 100644
--- a/include/clang-c/Index.h
+++ b/include/clang-c/Index.h
@@ -19,7 +19,9 @@
#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.
@@ -30,7 +32,7 @@
* compatible, thus CINDEX_VERSION_MAJOR is expected to remain stable.
*/
#define CINDEX_VERSION_MAJOR 0
-#define CINDEX_VERSION_MINOR 20
+#define CINDEX_VERSION_MINOR 27
#define CINDEX_VERSION_ENCODE(major, minor) ( \
((major) * 10000) \
@@ -599,6 +601,32 @@ CINDEX_LINKAGE CXSourceLocation clang_getRangeStart(CXSourceRange 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);
+
+/**
* @}
*/
@@ -1050,10 +1078,27 @@ CINDEX_LINKAGE CXTranslationUnit clang_createTranslationUnitFromSourceFile(
struct CXUnsavedFile *unsaved_files);
/**
- * \brief Create a translation unit from an AST file (-emit-ast).
+ * \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,
- const char *ast_filename);
+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.
@@ -1167,7 +1212,22 @@ enum CXTranslationUnit_Flags {
* 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.
@@ -1182,7 +1242,7 @@ CINDEX_LINKAGE unsigned clang_defaultEditingTranslationUnitOptions(void);
* associated.
*
* \param source_filename The name of the source file to load, or NULL if the
- * source file is included in \p command_line_args.
+ * 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.
@@ -1191,7 +1251,7 @@ CINDEX_LINKAGE unsigned clang_defaultEditingTranslationUnitOptions(void);
* '-emit-ast', '-fsyntax-only' (which is the default), and '-o \<output file>'.
*
* \param num_command_line_args The number of command-line arguments in
- * \p command_line_args.
+ * \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
@@ -1206,18 +1266,22 @@ CINDEX_LINKAGE unsigned clang_defaultEditingTranslationUnitOptions(void);
* is managed but not its compilation. This should be a bitwise OR of the
* CXTranslationUnit_XXX flags.
*
- * \returns A new translation unit describing the parsed code and containing
- * any diagnostics produced by the compiler. If there is a failure from which
- * the compiler cannot recover, returns NULL.
+ * \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 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);
-
+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 Flags that control how translation units are saved.
*
@@ -1369,10 +1433,11 @@ CINDEX_LINKAGE unsigned clang_defaultReparseOptions(CXTranslationUnit TU);
* The function \c clang_defaultReparseOptions() produces a default set of
* options recommended for most uses, based on the translation unit.
*
- * \returns 0 if the sources could be reparsed. A non-zero value will be
+ * \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 \p TU is
- * \c clang_disposeTranslationUnit(TU).
+ * 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,
@@ -1669,7 +1734,7 @@ enum CXCursorKind {
/**
* \brief An expression that refers to some value declaration, such
- * as a function, varible, or enumerator.
+ * as a function, variable, or enumerator.
*/
CXCursor_DeclRefExpr = 101,
@@ -1907,7 +1972,7 @@ enum CXCursorKind {
*/
CXCursor_ObjCBoolLiteralExpr = 145,
- /** \brief Represents the "self" expression in a ObjC method.
+ /** \brief Represents the "self" expression in an Objective-C method.
*/
CXCursor_ObjCSelfExpr = 146,
@@ -2070,7 +2135,67 @@ enum CXCursorKind {
*/
CXCursor_OMPParallelDirective = 232,
- CXCursor_LastStmt = CXCursor_OMPParallelDirective,
+ /** \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,
+
+ CXCursor_LastStmt = CXCursor_SEHLeaveStmt,
/**
* \brief Cursor that represents the translation unit itself.
@@ -2096,8 +2221,15 @@ enum CXCursorKind {
CXCursor_AnnotateAttr = 406,
CXCursor_AsmLabelAttr = 407,
CXCursor_PackedAttr = 408,
- CXCursor_LastAttr = CXCursor_PackedAttr,
-
+ CXCursor_PureAttr = 409,
+ CXCursor_ConstAttr = 410,
+ CXCursor_NoDuplicateAttr = 411,
+ CXCursor_CUDAConstantAttr = 412,
+ CXCursor_CUDADeviceAttr = 413,
+ CXCursor_CUDAGlobalAttr = 414,
+ CXCursor_CUDAHostAttr = 415,
+ CXCursor_LastAttr = CXCursor_CUDAHostAttr,
+
/* Preprocessing */
CXCursor_PreprocessingDirective = 500,
CXCursor_MacroDefinition = 501,
@@ -2141,14 +2273,6 @@ typedef struct {
} CXCursor;
/**
- * \brief A comment AST node.
- */
-typedef struct {
- const void *ASTNode;
- CXTranslationUnit TranslationUnit;
-} CXComment;
-
-/**
* \defgroup CINDEX_CURSOR_MANIP Cursor manipulations
*
* @{
@@ -2369,7 +2493,7 @@ clang_disposeCXPlatformAvailability(CXPlatformAvailability *availability);
/**
* \brief Describe the "language" of the entity referred to by a cursor.
*/
-CINDEX_LINKAGE enum CXLanguageKind {
+enum CXLanguageKind {
CXLanguage_Invalid = 0,
CXLanguage_C,
CXLanguage_ObjC,
@@ -2435,10 +2559,10 @@ CINDEX_LINKAGE unsigned clang_CXCursorSet_insert(CXCursorSet cset,
* void C::f() { }
* \endcode
*
- * In the out-of-line definition of \c C::f, the semantic parent is the
+ * 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
+ * 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,
@@ -2470,10 +2594,10 @@ CINDEX_LINKAGE CXCursor clang_getCursorSemanticParent(CXCursor cursor);
* void C::f() { }
* \endcode
*
- * In the out-of-line definition of \c C::f, the semantic parent is the
+ * 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
+ * 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,
@@ -2598,7 +2722,7 @@ CINDEX_LINKAGE CXSourceLocation clang_getCursorLocation(CXCursor);
*
* The extent of a cursor starts with the file/line/column pointing at the
* first character within the source construct that the cursor refers to and
- * ends with the last character withinin that source construct. For a
+ * 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).
@@ -2620,7 +2744,7 @@ CINDEX_LINKAGE CXSourceRange clang_getCursorExtent(CXCursor);
*/
enum CXTypeKind {
/**
- * \brief Reprents an invalid type (e.g., where no type is available).
+ * \brief Represents an invalid type (e.g., where no type is available).
*/
CXType_Invalid = 0,
@@ -2854,14 +2978,14 @@ CINDEX_LINKAGE CXString clang_getTypeKindSpelling(enum CXTypeKind K);
CINDEX_LINKAGE enum CXCallingConv clang_getFunctionTypeCallingConv(CXType T);
/**
- * \brief Retrieve the result type associated with a function type.
+ * \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 arguments associated with a
+ * \brief Retrieve the number of non-variadic parameters associated with a
* function type.
*
* If a non-function type is passed in, -1 is returned.
@@ -2869,7 +2993,7 @@ CINDEX_LINKAGE CXType clang_getResultType(CXType T);
CINDEX_LINKAGE int clang_getNumArgTypes(CXType T);
/**
- * \brief Retrieve the type of an argument of a function type.
+ * \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.
@@ -2882,7 +3006,7 @@ CINDEX_LINKAGE CXType clang_getArgType(CXType T, unsigned i);
CINDEX_LINKAGE unsigned clang_isFunctionTypeVariadic(CXType T);
/**
- * \brief Retrieve the result type associated with a given cursor.
+ * \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.
*/
@@ -3012,6 +3136,24 @@ enum CXRefQualifierKind {
};
/**
+ * \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
@@ -3274,8 +3416,8 @@ 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
- * objc methods and objc message expressions, there are multiple pieces for each
- * selector identifier.
+ * 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.
@@ -3371,25 +3513,25 @@ CINDEX_LINKAGE CXCursor clang_getCanonicalCursor(CXCursor);
/**
- * \brief If the cursor points to a selector identifier in a objc method or
- * message expression, this returns the selector index.
+ * \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 objc method or message
+ * \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 ObjC message,
- * returns non-zero if the method/message is "dynamic", meaning:
+ * \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 ObjC message: the receiver is an object instance, not 'super' or a
- * specific class.
+ * 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.
@@ -3397,8 +3539,8 @@ CINDEX_LINKAGE int clang_Cursor_getObjCSelectorIndex(CXCursor);
CINDEX_LINKAGE int clang_Cursor_isDynamicCall(CXCursor C);
/**
- * \brief Given a cursor pointing to an ObjC message, returns the CXType of the
- * receiver.
+ * \brief Given a cursor pointing to an Objective-C message, returns the CXType
+ * of the receiver.
*/
CINDEX_LINKAGE CXType clang_Cursor_getReceiverType(CXCursor C);
@@ -3433,7 +3575,7 @@ CINDEX_LINKAGE unsigned clang_Cursor_getObjCPropertyAttributes(CXCursor C,
/**
* \brief 'Qualifiers' written next to the return and parameter types in
- * ObjC method declarations.
+ * Objective-C method declarations.
*/
typedef enum {
CXObjCDeclQualifier_None = 0x0,
@@ -3446,15 +3588,16 @@ typedef enum {
} CXObjCDeclQualifierKind;
/**
- * \brief Given a cursor that represents an ObjC method or parameter
- * declaration, return the associated ObjC qualifiers for the return type or the
- * parameter respectively. The bits are formed from 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 ObjC method or property declaration,
- * return non-zero if the declaration was affected by "@optional".
+ * \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);
@@ -3485,13 +3628,6 @@ CINDEX_LINKAGE CXString clang_Cursor_getRawCommentText(CXCursor C);
CINDEX_LINKAGE CXString clang_Cursor_getBriefCommentText(CXCursor C);
/**
- * \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);
-
-/**
* @}
*/
@@ -3511,6 +3647,12 @@ typedef void *CXModule;
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.
@@ -3543,6 +3685,13 @@ 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,
@@ -3564,514 +3713,6 @@ CXFile clang_Module_getTopLevelHeader(CXTranslationUnit,
*/
/**
- * \defgroup CINDEX_COMMENT Comment AST introspection
- *
- * The routines in this group provide access to information in the
- * documentation comment ASTs.
- *
- * @{
- */
-
-/**
- * \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);
-
-/**
- * @}
- */
-
-/**
* \defgroup CINDEX_CPP C++ AST introspection
*
* The routines in this group provide access information in the ASTs specific
@@ -4100,6 +3741,12 @@ CINDEX_LINKAGE unsigned clang_CXXMethod_isStatic(CXCursor C);
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.
@@ -4189,7 +3836,7 @@ enum CXNameRefFlags {
* 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]; // ObjC
+ * [object doSomething:here withValue:there]; // Objective-C
* return some_vector[1]; // C++
* \endcode
*/
@@ -5022,7 +4669,7 @@ CXDiagnostic clang_codeCompleteGetDiagnostic(CXCodeCompleteResults *Results,
unsigned Index);
/**
- * \brief Determines what compeltions are appropriate for the context
+ * \brief Determines what completions are appropriate for the context
* the given code completion.
*
* \param Results the code completion results to query
@@ -5472,7 +5119,7 @@ typedef struct {
const CXIdxContainerInfo *declAsContainer;
/**
* \brief Whether the declaration exists in code or was created implicitly
- * by the compiler, e.g. implicit objc methods for properties.
+ * by the compiler, e.g. implicit Objective-C methods for properties.
*/
int isImplicit;
const CXIdxAttrInfo *const *attributes;
@@ -5545,8 +5192,8 @@ typedef enum {
*/
CXIdxEntityRef_Direct = 1,
/**
- * \brief An implicit reference, e.g. a reference of an ObjC method via the
- * dot syntax.
+ * \brief An implicit reference, e.g. a reference of an Objective-C method
+ * via the dot syntax.
*/
CXIdxEntityRef_Implicit = 2
} CXIdxEntityRefKind;
@@ -5740,7 +5387,7 @@ typedef enum {
/**
* \brief Skip a function/method body that was already parsed during an
- * indexing session assosiated with a \c CXIndexAction object.
+ * indexing session associated with a \c CXIndexAction object.
* Bodies in system headers are always skipped.
*/
CXIndexOpt_SkipParsedBodiesInSession = 0x10
@@ -5763,11 +5410,12 @@ typedef enum {
* \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_TU [out] pointer to store a CXTranslationUnit that can be reused
- * after indexing is finished. Set to NULL if you do not require it.
+ * \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 If there is a failure from which the there is no recovery, returns
- * non-zero, otherwise returns 0.
+ * \returns 0 on success or if there were errors from which the compiler could
+ * recover. If there is a failure from which the there is no recovery, returns
+ * a non-zero \c CXErrorCode.
*
* The rest of the parameters are the same as #clang_parseTranslationUnit.
*/
@@ -5836,6 +5484,9 @@ CXSourceLocation clang_indexLoc_getCXSourceLocation(CXIdxLoc loc);
* @}
*/
+/* Include the comment API for compatibility. This will eventually go away. */
+#include "clang-c/Documentation.h"
+
#ifdef __cplusplus
}
#endif
diff --git a/include/clang-c/module.modulemap b/include/clang-c/module.modulemap
new file mode 100644
index 000000000000..95a59d62344c
--- /dev/null
+++ b/include/clang-c/module.modulemap
@@ -0,0 +1,4 @@
+module Clang_C {
+ umbrella "."
+ module * { export * }
+}
diff --git a/include/clang/ARCMigrate/ARCMT.h b/include/clang/ARCMigrate/ARCMT.h
index 196f6c0b731f..ad4f23c604b3 100644
--- a/include/clang/ARCMigrate/ARCMT.h
+++ b/include/clang/ARCMigrate/ARCMT.h
@@ -113,7 +113,7 @@ public:
virtual void remove(CharSourceRange range) { }
};
- bool applyTransform(TransformFn trans, RewriteListener *listener = 0);
+ bool applyTransform(TransformFn trans, RewriteListener *listener = nullptr);
FileRemapper &getRemapper() { return Remapper; }
};
diff --git a/include/clang/ARCMigrate/ARCMTActions.h b/include/clang/ARCMigrate/ARCMTActions.h
index 45c8b4ed1a39..b3e74b996678 100644
--- a/include/clang/ARCMigrate/ARCMTActions.h
+++ b/include/clang/ARCMigrate/ARCMTActions.h
@@ -12,14 +12,14 @@
#include "clang/ARCMigrate/FileRemapper.h"
#include "clang/Frontend/FrontendAction.h"
-#include "llvm/ADT/OwningPtr.h"
+#include <memory>
namespace clang {
namespace arcmt {
class CheckAction : public WrapperFrontendAction {
protected:
- virtual bool BeginInvocation(CompilerInstance &CI);
+ bool BeginInvocation(CompilerInstance &CI) override;
public:
CheckAction(FrontendAction *WrappedAction);
@@ -27,7 +27,7 @@ public:
class ModifyAction : public WrapperFrontendAction {
protected:
- virtual bool BeginInvocation(CompilerInstance &CI);
+ bool BeginInvocation(CompilerInstance &CI) override;
public:
ModifyAction(FrontendAction *WrappedAction);
@@ -36,9 +36,9 @@ public:
class MigrateSourceAction : public ASTFrontendAction {
FileRemapper Remapper;
protected:
- virtual bool BeginInvocation(CompilerInstance &CI);
- virtual ASTConsumer *CreateASTConsumer(CompilerInstance &CI,
- StringRef InFile);
+ bool BeginInvocation(CompilerInstance &CI) override;
+ ASTConsumer *CreateASTConsumer(CompilerInstance &CI,
+ StringRef InFile) override;
};
class MigrateAction : public WrapperFrontendAction {
@@ -46,7 +46,7 @@ class MigrateAction : public WrapperFrontendAction {
std::string PlistOut;
bool EmitPremigrationARCErros;
protected:
- virtual bool BeginInvocation(CompilerInstance &CI);
+ bool BeginInvocation(CompilerInstance &CI) override;
public:
MigrateAction(FrontendAction *WrappedAction, StringRef migrateDir,
@@ -65,8 +65,9 @@ public:
unsigned migrateAction);
protected:
- virtual ASTConsumer *CreateASTConsumer(CompilerInstance &CI,StringRef InFile);
- virtual bool BeginInvocation(CompilerInstance &CI);
+ ASTConsumer *CreateASTConsumer(CompilerInstance &CI,
+ StringRef InFile) override;
+ bool BeginInvocation(CompilerInstance &CI) override;
};
}
diff --git a/include/clang/ARCMigrate/FileRemapper.h b/include/clang/ARCMigrate/FileRemapper.h
index f7677cc8620a..e094301ae6c4 100644
--- a/include/clang/ARCMigrate/FileRemapper.h
+++ b/include/clang/ARCMigrate/FileRemapper.h
@@ -12,9 +12,9 @@
#include "clang/Basic/LLVM.h"
#include "llvm/ADT/DenseMap.h"
-#include "llvm/ADT/OwningPtr.h"
#include "llvm/ADT/PointerUnion.h"
#include "llvm/ADT/StringRef.h"
+#include <memory>
namespace llvm {
class MemoryBuffer;
@@ -30,7 +30,7 @@ namespace arcmt {
class FileRemapper {
// FIXME: Reuse the same FileManager for multiple ASTContexts.
- OwningPtr<FileManager> FileMgr;
+ std::unique_ptr<FileManager> FileMgr;
typedef llvm::PointerUnion<const FileEntry *, llvm::MemoryBuffer *> Target;
typedef llvm::DenseMap<const FileEntry *, Target> MappingsTy;
@@ -56,8 +56,6 @@ public:
void applyMappings(PreprocessorOptions &PPOpts) const;
- void transferMappingsAndClear(PreprocessorOptions &PPOpts);
-
void clear(StringRef outputDir = StringRef());
private:
diff --git a/include/clang/AST/APValue.h b/include/clang/AST/APValue.h
index b4fd2affa653..e58c21923f51 100644
--- a/include/clang/AST/APValue.h
+++ b/include/clang/AST/APValue.h
@@ -80,7 +80,7 @@ private:
struct Vec {
APValue *Elts;
unsigned NumElts;
- Vec() : Elts(0), NumElts(0) {}
+ Vec() : Elts(nullptr), NumElts(0) {}
~Vec() { delete[] Elts; }
};
struct Arr {
@@ -108,34 +108,33 @@ private:
};
struct MemberPointerData;
- enum {
- MaxSize = (sizeof(ComplexAPSInt) > sizeof(ComplexAPFloat) ?
- sizeof(ComplexAPSInt) : sizeof(ComplexAPFloat))
- };
+ // 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);
- union {
- void *Aligner;
- char Data[MaxSize];
- };
+ DataType Data;
public:
APValue() : Kind(Uninitialized) {}
- explicit APValue(const APSInt &I) : Kind(Uninitialized) {
- MakeInt(); setInt(I);
+ explicit APValue(APSInt I) : Kind(Uninitialized) {
+ MakeInt(); setInt(std::move(I));
}
- explicit APValue(const APFloat &F) : Kind(Uninitialized) {
- MakeFloat(); setFloat(F);
+ 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(const APSInt &R, const APSInt &I) : Kind(Uninitialized) {
- MakeComplexInt(); setComplexInt(R, I);
+ APValue(APSInt R, APSInt I) : Kind(Uninitialized) {
+ MakeComplexInt(); setComplexInt(std::move(R), std::move(I));
}
- APValue(const APFloat &R, const APFloat &I) : Kind(Uninitialized) {
- MakeComplexFloat(); setComplexFloat(R, 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);
@@ -200,7 +199,7 @@ public:
APSInt &getInt() {
assert(isInt() && "Invalid accessor");
- return *(APSInt*)(char*)Data;
+ return *(APSInt*)(char*)Data.buffer;
}
const APSInt &getInt() const {
return const_cast<APValue*>(this)->getInt();
@@ -208,7 +207,7 @@ public:
APFloat &getFloat() {
assert(isFloat() && "Invalid accessor");
- return *(APFloat*)(char*)Data;
+ return *(APFloat*)(char*)Data.buffer;
}
const APFloat &getFloat() const {
return const_cast<APValue*>(this)->getFloat();
@@ -216,7 +215,7 @@ public:
APSInt &getComplexIntReal() {
assert(isComplexInt() && "Invalid accessor");
- return ((ComplexAPSInt*)(char*)Data)->Real;
+ return ((ComplexAPSInt*)(char*)Data.buffer)->Real;
}
const APSInt &getComplexIntReal() const {
return const_cast<APValue*>(this)->getComplexIntReal();
@@ -224,7 +223,7 @@ public:
APSInt &getComplexIntImag() {
assert(isComplexInt() && "Invalid accessor");
- return ((ComplexAPSInt*)(char*)Data)->Imag;
+ return ((ComplexAPSInt*)(char*)Data.buffer)->Imag;
}
const APSInt &getComplexIntImag() const {
return const_cast<APValue*>(this)->getComplexIntImag();
@@ -232,7 +231,7 @@ public:
APFloat &getComplexFloatReal() {
assert(isComplexFloat() && "Invalid accessor");
- return ((ComplexAPFloat*)(char*)Data)->Real;
+ return ((ComplexAPFloat*)(char*)Data.buffer)->Real;
}
const APFloat &getComplexFloatReal() const {
return const_cast<APValue*>(this)->getComplexFloatReal();
@@ -240,7 +239,7 @@ public:
APFloat &getComplexFloatImag() {
assert(isComplexFloat() && "Invalid accessor");
- return ((ComplexAPFloat*)(char*)Data)->Imag;
+ return ((ComplexAPFloat*)(char*)Data.buffer)->Imag;
}
const APFloat &getComplexFloatImag() const {
return const_cast<APValue*>(this)->getComplexFloatImag();
@@ -259,20 +258,20 @@ public:
APValue &getVectorElt(unsigned I) {
assert(isVector() && "Invalid accessor");
assert(I < getVectorLength() && "Index out of range");
- return ((Vec*)(char*)Data)->Elts[I];
+ 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)->NumElts;
+ 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)->Elts[I];
+ return ((Arr*)(char*)Data.buffer)->Elts[I];
}
const APValue &getArrayInitializedElt(unsigned I) const {
return const_cast<APValue*>(this)->getArrayInitializedElt(I);
@@ -283,35 +282,35 @@ public:
APValue &getArrayFiller() {
assert(isArray() && "Invalid accessor");
assert(hasArrayFiller() && "No array filler");
- return ((Arr*)(char*)Data)->Elts[getArrayInitializedElts()];
+ 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)->NumElts;
+ return ((const Arr*)(const void *)Data.buffer)->NumElts;
}
unsigned getArraySize() const {
assert(isArray() && "Invalid accessor");
- return ((const Arr*)(const void *)Data)->ArrSize;
+ return ((const Arr*)(const void *)Data.buffer)->ArrSize;
}
unsigned getStructNumBases() const {
assert(isStruct() && "Invalid accessor");
- return ((const StructData*)(const char*)Data)->NumBases;
+ return ((const StructData*)(const char*)Data.buffer)->NumBases;
}
unsigned getStructNumFields() const {
assert(isStruct() && "Invalid accessor");
- return ((const StructData*)(const char*)Data)->NumFields;
+ return ((const StructData*)(const char*)Data.buffer)->NumFields;
}
APValue &getStructBase(unsigned i) {
assert(isStruct() && "Invalid accessor");
- return ((StructData*)(char*)Data)->Elts[i];
+ return ((StructData*)(char*)Data.buffer)->Elts[i];
}
APValue &getStructField(unsigned i) {
assert(isStruct() && "Invalid accessor");
- return ((StructData*)(char*)Data)->Elts[getStructNumBases() + i];
+ return ((StructData*)(char*)Data.buffer)->Elts[getStructNumBases() + i];
}
const APValue &getStructBase(unsigned i) const {
return const_cast<APValue*>(this)->getStructBase(i);
@@ -322,11 +321,11 @@ public:
const FieldDecl *getUnionField() const {
assert(isUnion() && "Invalid accessor");
- return ((const UnionData*)(const char*)Data)->Field;
+ return ((const UnionData*)(const char*)Data.buffer)->Field;
}
APValue &getUnionValue() {
assert(isUnion() && "Invalid accessor");
- return *((UnionData*)(char*)Data)->Value;
+ return *((UnionData*)(char*)Data.buffer)->Value;
}
const APValue &getUnionValue() const {
return const_cast<APValue*>(this)->getUnionValue();
@@ -338,41 +337,41 @@ public:
const AddrLabelExpr* getAddrLabelDiffLHS() const {
assert(isAddrLabelDiff() && "Invalid accessor");
- return ((const AddrLabelDiffData*)(const char*)Data)->LHSExpr;
+ return ((const AddrLabelDiffData*)(const char*)Data.buffer)->LHSExpr;
}
const AddrLabelExpr* getAddrLabelDiffRHS() const {
assert(isAddrLabelDiff() && "Invalid accessor");
- return ((const AddrLabelDiffData*)(const char*)Data)->RHSExpr;
+ return ((const AddrLabelDiffData*)(const char*)Data.buffer)->RHSExpr;
}
- void setInt(const APSInt &I) {
+ void setInt(APSInt I) {
assert(isInt() && "Invalid accessor");
- *(APSInt*)(char*)Data = I;
+ *(APSInt *)(char *)Data.buffer = std::move(I);
}
- void setFloat(const APFloat &F) {
+ void setFloat(APFloat F) {
assert(isFloat() && "Invalid accessor");
- *(APFloat*)(char*)Data = F;
+ *(APFloat *)(char *)Data.buffer = std::move(F);
}
void setVector(const APValue *E, unsigned N) {
assert(isVector() && "Invalid accessor");
- ((Vec*)(char*)Data)->Elts = new APValue[N];
- ((Vec*)(char*)Data)->NumElts = N;
+ ((Vec*)(char*)Data.buffer)->Elts = new APValue[N];
+ ((Vec*)(char*)Data.buffer)->NumElts = N;
for (unsigned i = 0; i != N; ++i)
- ((Vec*)(char*)Data)->Elts[i] = E[i];
+ ((Vec*)(char*)Data.buffer)->Elts[i] = E[i];
}
- void setComplexInt(const APSInt &R, const APSInt &I) {
+ void setComplexInt(APSInt R, APSInt I) {
assert(R.getBitWidth() == I.getBitWidth() &&
"Invalid complex int (type mismatch).");
assert(isComplexInt() && "Invalid accessor");
- ((ComplexAPSInt*)(char*)Data)->Real = R;
- ((ComplexAPSInt*)(char*)Data)->Imag = I;
+ ((ComplexAPSInt *)(char *)Data.buffer)->Real = std::move(R);
+ ((ComplexAPSInt *)(char *)Data.buffer)->Imag = std::move(I);
}
- void setComplexFloat(const APFloat &R, const APFloat &I) {
+ void setComplexFloat(APFloat R, APFloat I) {
assert(&R.getSemantics() == &I.getSemantics() &&
"Invalid complex float (type mismatch).");
assert(isComplexFloat() && "Invalid accessor");
- ((ComplexAPFloat*)(char*)Data)->Real = R;
- ((ComplexAPFloat*)(char*)Data)->Imag = I;
+ ((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);
@@ -381,13 +380,13 @@ public:
unsigned CallIndex);
void setUnion(const FieldDecl *Field, const APValue &Value) {
assert(isUnion() && "Invalid accessor");
- ((UnionData*)(char*)Data)->Field = Field;
- *((UnionData*)(char*)Data)->Value = Value;
+ ((UnionData*)(char*)Data.buffer)->Field = Field;
+ *((UnionData*)(char*)Data.buffer)->Value = Value;
}
void setAddrLabelDiff(const AddrLabelExpr* LHSExpr,
const AddrLabelExpr* RHSExpr) {
- ((AddrLabelDiffData*)(char*)Data)->LHSExpr = LHSExpr;
- ((AddrLabelDiffData*)(char*)Data)->RHSExpr = RHSExpr;
+ ((AddrLabelDiffData*)(char*)Data.buffer)->LHSExpr = LHSExpr;
+ ((AddrLabelDiffData*)(char*)Data.buffer)->RHSExpr = RHSExpr;
}
/// Assign by swapping from a copy of the RHS.
@@ -404,46 +403,46 @@ private:
}
void MakeInt() {
assert(isUninit() && "Bad state change");
- new ((void*)Data) APSInt(1);
+ new ((void*)Data.buffer) APSInt(1);
Kind = Int;
}
void MakeFloat() {
assert(isUninit() && "Bad state change");
- new ((void*)(char*)Data) APFloat(0.0);
+ new ((void*)(char*)Data.buffer) APFloat(0.0);
Kind = Float;
}
void MakeVector() {
assert(isUninit() && "Bad state change");
- new ((void*)(char*)Data) Vec();
+ new ((void*)(char*)Data.buffer) Vec();
Kind = Vector;
}
void MakeComplexInt() {
assert(isUninit() && "Bad state change");
- new ((void*)(char*)Data) ComplexAPSInt();
+ new ((void*)(char*)Data.buffer) ComplexAPSInt();
Kind = ComplexInt;
}
void MakeComplexFloat() {
assert(isUninit() && "Bad state change");
- new ((void*)(char*)Data) ComplexAPFloat();
+ 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) StructData(B, M);
+ new ((void*)(char*)Data.buffer) StructData(B, M);
Kind = Struct;
}
void MakeUnion() {
assert(isUninit() && "Bad state change");
- new ((void*)(char*)Data) UnionData();
+ 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) AddrLabelDiffData();
+ new ((void*)(char*)Data.buffer) AddrLabelDiffData();
Kind = AddrLabelDiff;
}
};
diff --git a/include/clang/AST/ASTConsumer.h b/include/clang/AST/ASTConsumer.h
index 7b6fa94b2043..736a10bec9b4 100644
--- a/include/clang/AST/ASTConsumer.h
+++ b/include/clang/AST/ASTConsumer.h
@@ -18,10 +18,10 @@
namespace clang {
class ASTContext;
+ class CXXMethodDecl;
class CXXRecordDecl;
class Decl;
class DeclGroupRef;
- class HandleTagDeclDefinition;
class ASTMutationListener;
class ASTDeserializationListener; // layering violation because void* is ugly
class SemaConsumer; // layering violation required for safe SemaConsumer
@@ -50,13 +50,15 @@ public:
virtual void Initialize(ASTContext &Context) {}
/// HandleTopLevelDecl - Handle the specified top-level declaration. This is
- /// called by the parser to process every top-level Decl*. Note that D can be
- /// the head of a chain of Decls (e.g. for `int a, b` the chain will have two
- /// elements). Use Decl::getNextDeclarator() to walk the chain.
+ /// 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.
@@ -136,12 +138,12 @@ public:
/// \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 0; }
+ 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 0;
+ return nullptr;
}
/// PrintStats - If desired, print any statistics.
diff --git a/include/clang/AST/ASTContext.h b/include/clang/AST/ASTContext.h
index f420e85ee146..8134f6b080b7 100644
--- a/include/clang/AST/ASTContext.h
+++ b/include/clang/AST/ASTContext.h
@@ -19,6 +19,7 @@
#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"
@@ -33,10 +34,10 @@
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/FoldingSet.h"
#include "llvm/ADT/IntrusiveRefCntPtr.h"
-#include "llvm/ADT/OwningPtr.h"
#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/ADT/TinyPtrVector.h"
#include "llvm/Support/Allocator.h"
+#include <memory>
#include <vector>
namespace llvm {
@@ -51,7 +52,6 @@ namespace clang {
class CharUnits;
class DiagnosticsEngine;
class Expr;
- class ExternalASTSource;
class ASTMutationListener;
class IdentifierTable;
class MaterializeTemporaryExpr;
@@ -66,6 +66,7 @@ namespace clang {
class UnresolvedSetIterator;
class UsingDecl;
class UsingShadowDecl;
+ class VTableContextBase;
namespace Builtin { class Context; }
@@ -82,7 +83,7 @@ class ASTContext : public RefCountedBase<ASTContext> {
mutable llvm::FoldingSet<ExtQuals> ExtQualNodes;
mutable llvm::FoldingSet<ComplexType> ComplexTypes;
mutable llvm::FoldingSet<PointerType> PointerTypes;
- mutable llvm::FoldingSet<DecayedType> DecayedTypes;
+ mutable llvm::FoldingSet<AdjustedType> AdjustedTypes;
mutable llvm::FoldingSet<BlockPointerType> BlockPointerTypes;
mutable llvm::FoldingSet<LValueReferenceType> LValueReferenceTypes;
mutable llvm::FoldingSet<RValueReferenceType> RValueReferenceTypes;
@@ -364,6 +365,7 @@ private:
/// \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.
@@ -392,7 +394,7 @@ private:
PartialDiagnostic::StorageAllocator DiagAllocator;
/// \brief The current C++ ABI.
- OwningPtr<CXXABI> ABI;
+ std::unique_ptr<CXXABI> ABI;
CXXABI *createCXXABI(const TargetInfo &T);
/// \brief The logical -> physical address space map.
@@ -415,14 +417,16 @@ public:
SelectorTable &Selectors;
Builtin::Context &BuiltinInfo;
mutable DeclarationNameTable DeclarationNames;
- OwningPtr<ExternalASTSource> ExternalSource;
+ IntrusiveRefCntPtr<ExternalASTSource> ExternalSource;
ASTMutationListener *Listener;
/// \brief Contains parents of a node.
- typedef llvm::SmallVector<ast_type_traits::DynTypedNode, 1> ParentVector;
+ typedef llvm::SmallVector<ast_type_traits::DynTypedNode, 2> ParentVector;
/// \brief Maps from a node to its parents.
- typedef llvm::DenseMap<const void *, ParentVector> ParentMap;
+ typedef llvm::DenseMap<const void *,
+ llvm::PointerUnion<ast_type_traits::DynTypedNode *,
+ ParentVector *>> ParentMap;
/// \brief Returns the parents of the given node.
///
@@ -601,9 +605,9 @@ public:
///
/// \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 = NULL) const;
+ 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.
@@ -624,6 +628,43 @@ public:
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;
@@ -710,47 +751,10 @@ public:
return Import->NextLocalImport;
}
- /// \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;
- }
- };
-
- import_iterator local_import_begin() const {
- return import_iterator(FirstLocalImport);
+ typedef llvm::iterator_range<import_iterator> import_range;
+ import_range local_imports() const {
+ return import_range(import_iterator(FirstLocalImport), import_iterator());
}
- import_iterator local_import_end() const { return import_iterator(); }
Decl *getPrimaryMergedDecl(Decl *D) {
Decl *Result = MergedDecls.lookup(D);
@@ -797,11 +801,8 @@ public:
// The type is built when constructing 'BuiltinVaListDecl'.
mutable QualType VaListTagTy;
- ASTContext(LangOptions& LOpts, SourceManager &SM, const TargetInfo *t,
- IdentifierTable &idents, SelectorTable &sels,
- Builtin::Context &builtins,
- unsigned size_reserve,
- bool DelayInitialization = false);
+ ASTContext(LangOptions &LOpts, SourceManager &SM, IdentifierTable &idents,
+ SelectorTable &sels, Builtin::Context &builtins);
~ASTContext();
@@ -810,11 +811,13 @@ public:
/// 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(OwningPtr<ExternalASTSource> &Source);
+ 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(); }
+ ExternalASTSource *getExternalSource() const {
+ return ExternalSource.get();
+ }
/// \brief Attach an AST mutation listener to the AST context.
///
@@ -832,6 +835,14 @@ public:
void PrintStats() const;
const SmallVectorImpl<Type *>& getTypes() const { return Types; }
+ /// \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;
@@ -840,7 +851,7 @@ public:
/// \brief Retrieve the declaration for a 128-bit float stub type.
TypeDecl *getFloat128StubType() const;
-
+
//===--------------------------------------------------------------------===//
// Type Constructors
//===--------------------------------------------------------------------===//
@@ -915,6 +926,14 @@ public:
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.
@@ -1041,7 +1060,7 @@ public:
/// \brief Return the unique reference to the type for the specified type
/// declaration.
QualType getTypeDeclType(const TypeDecl *Decl,
- const TypeDecl *PrevDecl = 0) const {
+ const TypeDecl *PrevDecl = nullptr) const {
assert(Decl && "Passed null for Decl param");
if (Decl->TypeForDecl) return QualType(Decl->TypeForDecl, 0);
@@ -1075,9 +1094,10 @@ public:
const TemplateTypeParmType *Replaced,
const TemplateArgument &ArgPack);
- QualType getTemplateTypeParmType(unsigned Depth, unsigned Index,
- bool ParameterPack,
- TemplateTypeParmDecl *ParmDecl = 0) const;
+ QualType
+ getTemplateTypeParmType(unsigned Depth, unsigned Index,
+ bool ParameterPack,
+ TemplateTypeParmDecl *ParmDecl = nullptr) const;
QualType getTemplateSpecializationType(TemplateName T,
const TemplateArgument *Args,
@@ -1121,11 +1141,18 @@ public:
Optional<unsigned> NumExpansions);
QualType getObjCInterfaceType(const ObjCInterfaceDecl *Decl,
- ObjCInterfaceDecl *PrevDecl = 0) const;
+ ObjCInterfaceDecl *PrevDecl = nullptr) const;
QualType getObjCObjectType(QualType Base,
ObjCProtocolDecl * const *Protocols,
unsigned NumProtocols) 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;
@@ -1344,7 +1371,11 @@ public:
///
/// If \p Field is specified then record field names are also encoded.
void getObjCEncodingForType(QualType T, std::string &S,
- const FieldDecl *Field=0) const;
+ const FieldDecl *Field=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;
@@ -1382,6 +1413,10 @@ public:
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.
@@ -1542,7 +1577,7 @@ public:
/// arguments to the builtin that are required to be integer constant
/// expressions.
QualType GetBuiltinType(unsigned ID, GetBuiltinTypeError &Error,
- unsigned *IntegerConstantArgs = 0) const;
+ unsigned *IntegerConstantArgs = nullptr) const;
private:
CanQualType getFromTargetType(unsigned Type) const;
@@ -1704,6 +1739,8 @@ public:
bool isNearlyEmpty(const CXXRecordDecl *RD) const;
+ VTableContextBase *getVTableContext();
+
MangleContext *createMangleContext();
void DeepCollectObjCIvars(const ObjCInterfaceDecl *OI, bool leafClass,
@@ -1745,6 +1782,10 @@ public:
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.
///
@@ -1994,9 +2035,9 @@ public:
bool Unqualified = false, bool BlockReturnType = false);
QualType mergeFunctionTypes(QualType, QualType, bool OfBlockPointer=false,
bool Unqualified = false);
- QualType mergeFunctionArgumentTypes(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);
@@ -2008,7 +2049,7 @@ public:
const FunctionProtoType *ToFunctionType);
void ResetObjCLayout(const ObjCContainerDecl *CD) {
- ObjCLayouts[CD] = 0;
+ ObjCLayouts[CD] = nullptr;
}
//===--------------------------------------------------------------------===//
@@ -2027,14 +2068,12 @@ public:
//===--------------------------------------------------------------------===//
// Type Iterators.
//===--------------------------------------------------------------------===//
+ typedef llvm::iterator_range<SmallVectorImpl<Type *>::const_iterator>
+ type_const_range;
- typedef SmallVectorImpl<Type *>::iterator type_iterator;
- typedef SmallVectorImpl<Type *>::const_iterator const_type_iterator;
-
- type_iterator types_begin() { return Types.begin(); }
- type_iterator types_end() { return Types.end(); }
- const_type_iterator types_begin() const { return Types.begin(); }
- const_type_iterator types_end() const { return Types.end(); }
+ type_const_range types() const {
+ return type_const_range(Types.begin(), Types.end());
+ }
//===--------------------------------------------------------------------===//
// Integer Values
@@ -2125,7 +2164,7 @@ public:
/// when it is called.
void AddDeallocation(void (*Callback)(void*), void *Data);
- GVALinkage GetGVALinkageForFunction(const FunctionDecl *FD);
+ GVALinkage GetGVALinkageForFunction(const FunctionDecl *FD) const;
GVALinkage GetGVALinkageForVariable(const VarDecl *VD);
/// \brief Determines if the decl can be CodeGen'ed or deserialized from PCH
@@ -2139,6 +2178,9 @@ public:
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);
@@ -2212,9 +2254,7 @@ public:
/// \brief Initialize built-in types.
///
/// This routine may only be invoked once for a given ASTContext object.
- /// It is normally invoked by the ASTContext constructor. However, the
- /// constructor can be asked to delay initialization, which places the burden
- /// of calling this function on the user of that object.
+ /// It is normally invoked after ASTContext construction.
///
/// \param Target The target
void InitBuiltinTypes(const TargetInfo &Target);
@@ -2238,17 +2278,21 @@ private:
void getObjCEncodingForStructureImpl(RecordDecl *RD, std::string &S,
const FieldDecl *Field,
bool includeVBases = true) 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;
-private:
/// \brief A set of deallocations that should be performed when the
/// ASTContext is destroyed.
typedef llvm::SmallDenseMap<void(*)(void*), llvm::SmallVector<void*, 16> >
@@ -2263,8 +2307,11 @@ private:
friend class DeclContext;
friend class DeclarationNameTable;
void ReleaseDeclContextMaps();
+ void ReleaseParentMapEntries();
- llvm::OwningPtr<ParentMap> AllParents;
+ std::unique_ptr<ParentMap> AllParents;
+
+ std::unique_ptr<VTableContextBase> VTContext;
};
/// \brief Utility function for constructing a nullary selector.
@@ -2363,4 +2410,18 @@ 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/include/clang/AST/ASTDiagnostic.h b/include/clang/AST/ASTDiagnostic.h
index 1635511984dc..484ca4cb8632 100644
--- a/include/clang/AST/ASTDiagnostic.h
+++ b/include/clang/AST/ASTDiagnostic.h
@@ -36,12 +36,9 @@ namespace clang {
void FormatASTNodeDiagnosticArgument(
DiagnosticsEngine::ArgumentKind Kind,
intptr_t Val,
- const char *Modifier,
- unsigned ModLen,
- const char *Argument,
- unsigned ArgLen,
- const DiagnosticsEngine::ArgumentValue *PrevArgs,
- unsigned NumPrevArgs,
+ StringRef Modifier,
+ StringRef Argument,
+ ArrayRef<DiagnosticsEngine::ArgumentValue> PrevArgs,
SmallVectorImpl<char> &Output,
void *Cookie,
ArrayRef<intptr_t> QualTypeVals);
diff --git a/include/clang/AST/ASTImporter.h b/include/clang/AST/ASTImporter.h
index b74c8ee1bf47..a335f980e6c5 100644
--- a/include/clang/AST/ASTImporter.h
+++ b/include/clang/AST/ASTImporter.h
@@ -278,7 +278,7 @@ namespace clang {
/// 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 NULL; }
+ virtual Decl *GetOriginalDecl(Decl *To) { return nullptr; }
/// \brief Determine whether the given types are structurally
/// equivalent.
diff --git a/include/clang/AST/ASTLambda.h b/include/clang/AST/ASTLambda.h
index 358ac7131e40..9af016b13d45 100644
--- a/include/clang/AST/ASTLambda.h
+++ b/include/clang/AST/ASTLambda.h
@@ -36,9 +36,9 @@ inline bool isLambdaCallOperator(const DeclContext *DC) {
return isLambdaCallOperator(cast<CXXMethodDecl>(DC));
}
-inline bool isGenericLambdaCallOperatorSpecialization(CXXMethodDecl *MD) {
+inline bool isGenericLambdaCallOperatorSpecialization(const CXXMethodDecl *MD) {
if (!MD) return false;
- CXXRecordDecl *LambdaClass = MD->getParent();
+ const CXXRecordDecl *LambdaClass = MD->getParent();
if (LambdaClass && LambdaClass->isGenericLambda())
return isLambdaCallOperator(MD) &&
MD->isFunctionTemplateSpecialization();
diff --git a/include/clang/AST/ASTMutationListener.h b/include/clang/AST/ASTMutationListener.h
index 6d12a92c61bf..a89bfed53fbd 100644
--- a/include/clang/AST/ASTMutationListener.h
+++ b/include/clang/AST/ASTMutationListener.h
@@ -65,6 +65,10 @@ public:
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);
@@ -74,6 +78,9 @@ public:
/// \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) {}
diff --git a/include/clang/AST/ASTTypeTraits.h b/include/clang/AST/ASTTypeTraits.h
index 087ad5609001..0e06e26e6d80 100644
--- a/include/clang/AST/ASTTypeTraits.h
+++ b/include/clang/AST/ASTTypeTraits.h
@@ -57,11 +57,18 @@ public:
bool isSame(ASTNodeKind Other) const;
/// \brief Returns \c true if \c this is a base kind of (or same as) \c Other.
- bool isBaseOf(ASTNodeKind Other) const;
+ /// \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;
+ }
+
private:
/// \brief Kind ids.
///
@@ -91,7 +98,9 @@ private:
/// \brief Returns \c true if \c Base is a base kind of (or same as) \c
/// Derived.
- static bool isBaseOf(NodeKindId Base, NodeKindId 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.
///
@@ -133,6 +142,11 @@ KIND_TO_KIND_ID(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
@@ -198,8 +212,8 @@ public:
return getMemoizationData() < Other.getMemoizationData();
}
bool operator==(const DynTypedNode &Other) const {
- // Nodes with different types cannot be equal.
- if (!NodeKind.isSame(Other.NodeKind))
+ if (!NodeKind.isBaseOf(Other.NodeKind) &&
+ !Other.NodeKind.isBaseOf(NodeKind))
return false;
// FIXME: Implement for other types.
@@ -223,7 +237,7 @@ private:
static const T *get(ASTNodeKind NodeKind, const char Storage[]) {
if (ASTNodeKind::getFromNodeKind<BaseT>().isBaseOf(NodeKind))
return dyn_cast<T>(*reinterpret_cast<BaseT *const *>(Storage));
- return NULL;
+ return nullptr;
}
static DynTypedNode create(const BaseT &Node) {
DynTypedNode Result;
@@ -238,7 +252,7 @@ private:
static const T *get(ASTNodeKind NodeKind, const char Storage[]) {
if (ASTNodeKind::getFromNodeKind<T>().isSame(NodeKind))
return *reinterpret_cast<T *const *>(Storage);
- return NULL;
+ return nullptr;
}
static DynTypedNode create(const T &Node) {
DynTypedNode Result;
@@ -253,7 +267,7 @@ private:
static const T *get(ASTNodeKind NodeKind, const char Storage[]) {
if (ASTNodeKind::getFromNodeKind<T>().isSame(NodeKind))
return reinterpret_cast<const T *>(Storage);
- return NULL;
+ return nullptr;
}
static DynTypedNode create(const T &Node) {
DynTypedNode Result;
@@ -283,18 +297,18 @@ private:
template <typename T>
struct DynTypedNode::BaseConverter<
- T, typename llvm::enable_if<llvm::is_base_of<
- Decl, T> >::type> : public DynCastPtrConverter<T, Decl> {};
+ 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 llvm::enable_if<llvm::is_base_of<
- Stmt, T> >::type> : public DynCastPtrConverter<T, Stmt> {};
+ 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 llvm::enable_if<llvm::is_base_of<
- Type, T> >::type> : public DynCastPtrConverter<T, Type> {};
+ T, typename std::enable_if<std::is_base_of<Type, T>::value>::type>
+ : public DynCastPtrConverter<T, Type> {};
template <>
struct DynTypedNode::BaseConverter<
@@ -341,7 +355,7 @@ inline const void *DynTypedNode::getMemoizationData() const {
} else if (ASTNodeKind::getFromNodeKind<NestedNameSpecifier>().isBaseOf(NodeKind)) {
return BaseConverter<NestedNameSpecifier>::get(NodeKind, Storage.buffer);
}
- return NULL;
+ return nullptr;
}
} // end namespace ast_type_traits
diff --git a/include/clang/AST/ASTUnresolvedSet.h b/include/clang/AST/ASTUnresolvedSet.h
index e8be67006c5b..84b0842492ad 100644
--- a/include/clang/AST/ASTUnresolvedSet.h
+++ b/include/clang/AST/ASTUnresolvedSet.h
@@ -32,9 +32,6 @@ class ASTUnresolvedSet {
DeclsTy Decls;
- ASTUnresolvedSet(const ASTUnresolvedSet &) LLVM_DELETED_FUNCTION;
- void operator=(const ASTUnresolvedSet &) LLVM_DELETED_FUNCTION;
-
friend class LazyASTUnresolvedSet;
public:
diff --git a/include/clang/AST/ASTVector.h b/include/clang/AST/ASTVector.h
index 6db918eaa631..d92167e95992 100644
--- a/include/clang/AST/ASTVector.h
+++ b/include/clang/AST/ASTVector.h
@@ -26,30 +26,6 @@
#include <cstring>
#include <memory>
-#ifdef _MSC_VER
-namespace std {
-#if _MSC_VER <= 1310
- // Work around flawed VC++ implementation of std::uninitialized_copy. Define
- // additional overloads so that elements with pointer types are recognized as
- // scalars and not objects, causing bizarre type conversion errors.
- template<class T1, class T2>
- inline _Scalar_ptr_iterator_tag _Ptr_cat(T1 **, T2 **) {
- _Scalar_ptr_iterator_tag _Cat;
- return _Cat;
- }
-
- template<class T1, class T2>
- inline _Scalar_ptr_iterator_tag _Ptr_cat(T1* const *, T2 **) {
- _Scalar_ptr_iterator_tag _Cat;
- return _Cat;
- }
-#else
- // FIXME: It is not clear if the problem is fixed in VS 2005. What is clear
- // is that the above hack won't work if it wasn't fixed.
-#endif
-}
-#endif
-
namespace clang {
class ASTContext;
@@ -69,15 +45,30 @@ protected:
public:
// Default ctor - Initialize to empty.
- ASTVector() : Begin(0), End(0), Capacity(0, false) {}
+ 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(0), End(0), Capacity(0, false) {
+ : 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 (llvm::is_class<T>::value) {
+ if (std::is_class<T>::value) {
// Destroy the constructed elements in the vector.
destroy_range(Begin, End);
}
@@ -147,7 +138,7 @@ public:
}
void clear() {
- if (llvm::is_class<T>::value) {
+ if (std::is_class<T>::value) {
destroy_range(Begin, End);
}
End = Begin;
@@ -392,7 +383,7 @@ void ASTVector<T>::grow(const ASTContext &C, size_t MinSize) {
T *NewElts = new (C, llvm::alignOf<T>()) T[NewCapacity];
// Copy the elements over.
- if (llvm::is_class<T>::value) {
+ if (std::is_class<T>::value) {
std::uninitialized_copy(Begin, End, NewElts);
// Destroy the original elements.
destroy_range(Begin, End);
diff --git a/include/clang/AST/Attr.h b/include/clang/AST/Attr.h
index 7dbf41350a0f..fc4881619bce 100644
--- a/include/clang/AST/Attr.h
+++ b/include/clang/AST/Attr.h
@@ -26,8 +26,8 @@
#include "llvm/ADT/StringSwitch.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/raw_ostream.h"
+#include <algorithm>
#include <cassert>
-#include <cstring>
namespace clang {
class ASTContext;
@@ -48,10 +48,9 @@ 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;
virtual ~Attr();
@@ -76,7 +75,7 @@ public:
protected:
Attr(attr::Kind AK, SourceRange R, unsigned SpellingListIndex = 0)
: Range(R), AttrKind(AK), SpellingListIndex(SpellingListIndex),
- Inherited(false), IsPackExpansion(false) {}
+ Inherited(false), IsPackExpansion(false), Implicit(false) {}
public:
@@ -85,6 +84,7 @@ public:
}
unsigned getSpellingListIndex() const { return SpellingListIndex; }
+ virtual const char *getSpelling() const = 0;
SourceLocation getLocation() const { return Range.getBegin(); }
SourceRange getRange() const { return Range; }
@@ -92,6 +92,11 @@ public:
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; }
@@ -103,6 +108,11 @@ public:
// Pretty print this attribute.
virtual void printPretty(raw_ostream &OS,
const PrintingPolicy &Policy) const = 0;
+
+ /// \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.
+ virtual bool duplicatesAllowed() const { return false; }
};
class InheritableAttr : public Attr {
@@ -121,7 +131,7 @@ public:
};
class InheritableParamAttr : public InheritableAttr {
- virtual void anchor();
+ void anchor() override;
protected:
InheritableParamAttr(attr::Kind AK, SourceRange R,
unsigned SpellingListIndex = 0)
@@ -136,23 +146,21 @@ public:
}
};
-class MSInheritanceAttr : public InheritableAttr {
- virtual void anchor();
-protected:
- MSInheritanceAttr(attr::Kind AK, SourceRange R, unsigned SpellingListIndex = 0)
- : InheritableAttr(AK, R, SpellingListIndex) {}
-
-public:
- // Implement isa/cast/dyncast/etc.
- static bool classof(const Attr *A) {
- // Relies on relative order of enum emission with respect to param attrs.
- return (A->getKind() <= attr::LAST_MS_INHERITANCE &&
- 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/include/clang/AST/AttrIterator.h b/include/clang/AST/AttrIterator.h
index 8bd8fbec895d..39ee81f1201c 100644
--- a/include/clang/AST/AttrIterator.h
+++ b/include/clang/AST/AttrIterator.h
@@ -43,7 +43,7 @@ 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 specifc type.
+/// providing attributes that are of a specific type.
template <typename SpecificAttr, typename Container = AttrVec>
class specific_attr_iterator {
typedef typename Container::const_iterator Iterator;
@@ -53,7 +53,7 @@ class specific_attr_iterator {
/// specifically requested, we don't necessarily advance this all the
/// way. Instead, we advance it when an operation is requested; if the
/// operation is acting on what should be a past-the-end iterator,
- /// then we offer no guarantees, but this way we do not dererence a
+ /// 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;
@@ -98,7 +98,7 @@ public:
friend bool operator==(specific_attr_iterator Left,
specific_attr_iterator Right) {
- assert((Left.Current == 0) == (Right.Current == 0));
+ assert((Left.Current == nullptr) == (Right.Current == nullptr));
if (Left.Current < Right.Current)
Left.AdvanceToNext(Right.Current);
else
@@ -134,7 +134,7 @@ inline SpecificAttr *getSpecificAttr(const Container& container) {
if (i != specific_attr_end<SpecificAttr>(container))
return *i;
else
- return 0;
+ return nullptr;
}
} // end namespace clang
diff --git a/include/clang/AST/CMakeLists.txt b/include/clang/AST/CMakeLists.txt
index ba54fa2aa92b..260734f2200a 100644
--- a/include/clang/AST/CMakeLists.txt
+++ b/include/clang/AST/CMakeLists.txt
@@ -13,6 +13,11 @@ clang_tablegen(AttrDump.inc -gen-clang-attr-dump
SOURCE ../Basic/Attr.td
TARGET ClangAttrDump)
+clang_tablegen(AttrVisitor.inc -gen-clang-attr-ast-visitor
+ -I ${CMAKE_CURRENT_SOURCE_DIR}/../../
+ SOURCE ../Basic/Attr.td
+ TARGET ClangAttrVisitor)
+
clang_tablegen(StmtNodes.inc -gen-clang-stmt-nodes
SOURCE ../Basic/StmtNodes.td
TARGET ClangStmtNodes)
diff --git a/include/clang/AST/CXXInheritance.h b/include/clang/AST/CXXInheritance.h
index dbe4ad0f5a1d..37f6748ace90 100644
--- a/include/clang/AST/CXXInheritance.h
+++ b/include/clang/AST/CXXInheritance.h
@@ -177,8 +177,8 @@ public:
bool RecordPaths = true,
bool DetectVirtual = true)
: FindAmbiguities(FindAmbiguities), RecordPaths(RecordPaths),
- DetectVirtual(DetectVirtual), DetectedVirtual(0), DeclsFound(0),
- NumDeclsFound(0) { }
+ DetectVirtual(DetectVirtual), DetectedVirtual(nullptr),
+ DeclsFound(nullptr), NumDeclsFound(0) { }
~CXXBasePaths() { delete [] DeclsFound; }
@@ -190,8 +190,8 @@ public:
CXXBasePath& front() { return Paths.front(); }
const CXXBasePath& front() const { return Paths.front(); }
- decl_iterator found_decls_begin();
- decl_iterator found_decls_end();
+ 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
@@ -232,7 +232,8 @@ public:
/// \brief Uniquely identifies a virtual method within a class
/// hierarchy by the method itself and a class subobject number.
struct UniqueVirtualMethod {
- UniqueVirtualMethod() : Method(0), Subobject(0), InVirtualSubobject(0) { }
+ UniqueVirtualMethod()
+ : Method(nullptr), Subobject(0), InVirtualSubobject(nullptr) { }
UniqueVirtualMethod(CXXMethodDecl *Method, unsigned Subobject,
const CXXRecordDecl *InVirtualSubobject)
diff --git a/include/clang/AST/CanonicalType.h b/include/clang/AST/CanonicalType.h
index 9c699b7e0ae2..7cccef69ddf8 100644
--- a/include/clang/AST/CanonicalType.h
+++ b/include/clang/AST/CanonicalType.h
@@ -17,7 +17,6 @@
#include "clang/AST/Type.h"
#include "llvm/Support/Casting.h"
-#include "llvm/Support/type_traits.h"
#include <iterator>
namespace clang {
@@ -60,9 +59,9 @@ public:
/// \brief Converting constructor that permits implicit upcasting of
/// canonical type pointers.
- template<typename U>
- CanQual(const CanQual<U>& Other,
- typename llvm::enable_if<llvm::is_base_of<T, U>, int>::type = 0);
+ 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.
@@ -541,39 +540,39 @@ struct CanProxyAdaptor<ExtVectorType> : public CanProxyBase<ExtVectorType> {
template<>
struct CanProxyAdaptor<FunctionType> : public CanProxyBase<FunctionType> {
- LLVM_CLANG_CANPROXY_TYPE_ACCESSOR(getResultType)
+ 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(getResultType)
+ 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(getResultType)
+ LLVM_CLANG_CANPROXY_TYPE_ACCESSOR(getReturnType)
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(FunctionType::ExtInfo, getExtInfo)
- LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(unsigned, getNumArgs)
- CanQualType getArgType(unsigned i) const {
- return CanQualType::CreateUnsafe(this->getTypePtr()->getArgType(i));
+ LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(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::arg_type_iterator>
- arg_type_iterator;
+ typedef CanTypeIterator<FunctionProtoType::param_type_iterator>
+ param_type_iterator;
- arg_type_iterator arg_type_begin() const {
- return arg_type_iterator(this->getTypePtr()->arg_type_begin());
+ param_type_iterator param_type_begin() const {
+ return param_type_iterator(this->getTypePtr()->param_type_begin());
}
- arg_type_iterator arg_type_end() const {
- return arg_type_iterator(this->getTypePtr()->arg_type_end());
+ param_type_iterator param_type_end() const {
+ return param_type_iterator(this->getTypePtr()->param_type_end());
}
// Note: canonical function types never have exception specifications
diff --git a/include/clang/AST/CharUnits.h b/include/clang/AST/CharUnits.h
index 09ff6828ef5c..72ca9f5cd67d 100644
--- a/include/clang/AST/CharUnits.h
+++ b/include/clang/AST/CharUnits.h
@@ -165,7 +165,7 @@ namespace clang {
/// 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) {
+ CharUnits RoundUpToAlignment(const CharUnits &Align) const {
return CharUnits(llvm::RoundUpToAlignment(Quantity,
Align.Quantity));
}
@@ -173,12 +173,7 @@ namespace clang {
/// Given that this is a non-zero alignment value, what is the
/// alignment at the given offset?
CharUnits alignmentAtOffset(CharUnits offset) {
- // alignment: 0010000
- // offset: 1011100
- // lowBits: 0001011
- // result: 0000100
- QuantityType lowBits = (Quantity-1) & (offset.Quantity-1);
- return CharUnits((lowBits + 1) & ~lowBits);
+ return CharUnits(llvm::MinAlign(Quantity, offset.Quantity));
}
diff --git a/include/clang/AST/Comment.h b/include/clang/AST/Comment.h
index 28849f58a8ec..e18fe9ab86a0 100644
--- a/include/clang/AST/Comment.h
+++ b/include/clang/AST/Comment.h
@@ -100,16 +100,26 @@ protected:
};
enum { NumInlineCommandCommentBits = NumInlineContentCommentBits + 10 };
+ 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 : NumInlineContentCommentBits;
+ 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 = NumInlineContentCommentBits + 1 };
+ enum { NumHTMLStartTagCommentBits = NumHTMLTagCommentBits + 1 };
class ParagraphCommentBitfields {
friend class ParagraphComment;
@@ -155,6 +165,7 @@ protected:
InlineContentCommentBitfields InlineContentCommentBits;
TextCommentBitfields TextCommentBits;
InlineCommandCommentBitfields InlineCommandCommentBits;
+ HTMLTagCommentBitfields HTMLTagCommentBits;
HTMLStartTagCommentBitfields HTMLStartTagCommentBits;
ParagraphCommentBitfields ParagraphCommentBits;
BlockCommandCommentBitfields BlockCommandCommentBits;
@@ -194,9 +205,9 @@ public:
const char *getCommentKindName() const;
- LLVM_ATTRIBUTE_USED void dump() const;
- LLVM_ATTRIBUTE_USED void dumpColor() const;
- LLVM_ATTRIBUTE_USED void dump(const ASTContext &Context) 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;
@@ -267,9 +278,9 @@ public:
return C->getCommentKind() == TextCommentKind;
}
- child_iterator child_begin() const { return NULL; }
+ child_iterator child_begin() const { return nullptr; }
- child_iterator child_end() const { return NULL; }
+ child_iterator child_end() const { return nullptr; }
StringRef getText() const LLVM_READONLY { return Text; }
@@ -325,9 +336,9 @@ public:
return C->getCommentKind() == InlineCommandCommentKind;
}
- child_iterator child_begin() const { return NULL; }
+ child_iterator child_begin() const { return nullptr; }
- child_iterator child_end() const { return NULL; }
+ child_iterator child_end() const { return nullptr; }
unsigned getCommandID() const {
return InlineCommandCommentBits.CommandID;
@@ -360,8 +371,7 @@ public:
};
/// Abstract class for opening and closing HTML tags. HTML tags are always
-/// treated as inline content (regardless HTML semantics); opening and closing
-/// tags are not matched.
+/// treated as inline content (regardless HTML semantics).
class HTMLTagComment : public InlineContentComment {
protected:
StringRef TagName;
@@ -377,6 +387,7 @@ protected:
TagName(TagName),
TagNameRange(TagNameBegin, TagNameEnd) {
setLocation(TagNameBegin);
+ HTMLTagCommentBits.IsMalformed = 0;
}
public:
@@ -392,6 +403,14 @@ public:
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.
@@ -450,9 +469,9 @@ public:
return C->getCommentKind() == HTMLStartTagCommentKind;
}
- child_iterator child_begin() const { return NULL; }
+ child_iterator child_begin() const { return nullptr; }
- child_iterator child_end() const { return NULL; }
+ child_iterator child_end() const { return nullptr; }
unsigned getNumAttrs() const {
return Attributes.size();
@@ -505,9 +524,9 @@ public:
return C->getCommentKind() == HTMLEndTagCommentKind;
}
- child_iterator child_begin() const { return NULL; }
+ child_iterator child_begin() const { return nullptr; }
- child_iterator child_end() const { return NULL; }
+ child_iterator child_end() const { return nullptr; }
};
/// Block content (contains inline content).
@@ -601,7 +620,7 @@ protected:
unsigned CommandID,
CommandMarkerKind CommandMarker) :
BlockContentComment(K, LocBegin, LocEnd),
- Paragraph(NULL) {
+ Paragraph(nullptr) {
setLocation(getCommandNameBeginLoc());
BlockCommandCommentBits.CommandID = CommandID;
BlockCommandCommentBits.CommandMarker = CommandMarker;
@@ -613,7 +632,7 @@ public:
unsigned CommandID,
CommandMarkerKind CommandMarker) :
BlockContentComment(BlockCommandCommentKind, LocBegin, LocEnd),
- Paragraph(NULL) {
+ Paragraph(nullptr) {
setLocation(getCommandNameBeginLoc());
BlockCommandCommentBits.CommandID = CommandID;
BlockCommandCommentBits.CommandMarker = CommandMarker;
@@ -699,7 +718,7 @@ private:
unsigned ParamIndex;
public:
- enum LLVM_ENUM_INT_TYPE(unsigned) {
+ enum : unsigned {
InvalidParamIndex = ~0U,
VarArgParamIndex = ~0U/*InvalidParamIndex*/ - 1U
};
@@ -861,9 +880,9 @@ public:
return C->getCommentKind() == VerbatimBlockLineCommentKind;
}
- child_iterator child_begin() const { return NULL; }
+ child_iterator child_begin() const { return nullptr; }
- child_iterator child_end() const { return NULL; }
+ child_iterator child_end() const { return nullptr; }
StringRef getText() const LLVM_READONLY {
return Text;
@@ -948,9 +967,9 @@ public:
return C->getCommentKind() == VerbatimLineCommentKind;
}
- child_iterator child_begin() const { return NULL; }
+ child_iterator child_begin() const { return nullptr; }
- child_iterator child_end() const { return NULL; }
+ child_iterator child_end() const { return nullptr; }
StringRef getText() const {
return Text;
@@ -981,9 +1000,9 @@ struct DeclInfo {
/// that we consider a "function".
ArrayRef<const ParmVarDecl *> ParamVars;
- /// Function result type if \c CommentDecl is something that we consider
+ /// Function return type if \c CommentDecl is something that we consider
/// a "function".
- QualType ResultType;
+ QualType ReturnType;
/// Template parameters that can be referenced by \\tparam if \c CommentDecl is
/// a template (\c IsTemplateDecl or \c IsTemplatePartialSpecialization is
diff --git a/include/clang/AST/CommentCommands.td b/include/clang/AST/CommentCommands.td
index ed323daa9f8b..958ee032e71f 100644
--- a/include/clang/AST/CommentCommands.td
+++ b/include/clang/AST/CommentCommands.td
@@ -146,7 +146,7 @@ def Todo : BlockCommand<"todo">;
def Version : BlockCommand<"version">;
def Warning : BlockCommand<"warning">;
// HeaderDoc commands
-def Abstract : BlockCommand<"abstract">;
+def Abstract : BlockCommand<"abstract"> { let IsBriefCommand = 1; }
def ClassDesign : RecordLikeDetailCommand<"classdesign">;
def CoClass : RecordLikeDetailCommand<"coclass">;
def Dependency : RecordLikeDetailCommand<"dependency">;
diff --git a/include/clang/AST/CommentHTMLTags.td b/include/clang/AST/CommentHTMLTags.td
index f98e32ddca4f..251490094940 100644
--- a/include/clang/AST/CommentHTMLTags.td
+++ b/include/clang/AST/CommentHTMLTags.td
@@ -52,3 +52,16 @@ 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/include/clang/AST/CommentLexer.h b/include/clang/AST/CommentLexer.h
index f152c778c9aa..a6e3ed89b27e 100644
--- a/include/clang/AST/CommentLexer.h
+++ b/include/clang/AST/CommentLexer.h
@@ -14,8 +14,8 @@
#ifndef LLVM_CLANG_AST_COMMENT_LEXER_H
#define LLVM_CLANG_AST_COMMENT_LEXER_H
-#include "clang/Basic/SourceManager.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"
@@ -293,17 +293,7 @@ private:
StringRef resolveHTMLHexCharacterReference(StringRef Name) const;
void formTokenWithChars(Token &Result, const char *TokEnd,
- tok::TokenKind Kind) {
- const unsigned TokLen = TokEnd - BufferPtr;
- Result.setLocation(getSourceLocation(BufferPtr));
- Result.setKind(Kind);
- Result.setLength(TokLen);
-#ifndef NDEBUG
- Result.TextPtr = "<UNSET>";
- Result.IntVal = 7;
-#endif
- BufferPtr = TokEnd;
- }
+ tok::TokenKind Kind);
void formTextToken(Token &Result, const char *TokEnd) {
StringRef Text(BufferPtr, TokEnd - BufferPtr);
@@ -362,7 +352,7 @@ public:
StringRef getSpelling(const Token &Tok,
const SourceManager &SourceMgr,
- bool *Invalid = NULL) const;
+ bool *Invalid = nullptr) const;
};
} // end namespace comments
diff --git a/include/clang/AST/CommentSema.h b/include/clang/AST/CommentSema.h
index 39109602b148..027c3b929df6 100644
--- a/include/clang/AST/CommentSema.h
+++ b/include/clang/AST/CommentSema.h
@@ -84,8 +84,8 @@ public:
T *Mem = Allocator.Allocate<T>(Size);
std::uninitialized_copy(Source.begin(), Source.end(), Mem);
return llvm::makeArrayRef(Mem, Size);
- } else
- return llvm::makeArrayRef(static_cast<T *>(NULL), 0);
+ }
+ return ArrayRef<T>();
}
ParagraphComment *actOnParagraphComment(
diff --git a/include/clang/AST/DataRecursiveASTVisitor.h b/include/clang/AST/DataRecursiveASTVisitor.h
new file mode 100644
index 000000000000..9ef008717b1b
--- /dev/null
+++ b/include/clang/AST/DataRecursiveASTVisitor.h
@@ -0,0 +1,2519 @@
+//===--- DataRecursiveASTVisitor.h - Data-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 DataRecursiveASTVisitor interface, which recursively
+// traverses the entire AST, using data recursion for Stmts/Exprs.
+//
+//===----------------------------------------------------------------------===//
+#ifndef LLVM_CLANG_AST_DATARECURSIVEASTVISITOR_H
+#define LLVM_CLANG_AST_DATARECURSIVEASTVISITOR_H
+
+#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/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)
+
+// 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 {
+
+// Reduce the diff between RecursiveASTVisitor / DataRecursiveASTVisitor to
+// make it easier to track changes and keep the two in sync.
+#define RecursiveASTVisitor DataRecursiveASTVisitor
+
+// 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.
+///
+/// Stmts are traversed internally using a data queue to avoid a stack overflow
+/// with hugely nested ASTs.
+///
+/// Clients of this visitor should subclass the visitor (providing
+/// themselves as the template argument, using the curiously recurring
+/// template pattern) and override any of the Traverse*, WalkUpFrom*,
+/// and Visit* methods for declarations, types, statements,
+/// expressions, or other AST nodes where the visitor should customize
+/// behavior. Most users only need to override Visit*. Advanced
+/// users may override Traverse* and WalkUpFrom* to implement custom
+/// traversal strategies. Returning false from one of these overridden
+/// functions will abort the entire traversal.
+///
+/// By default, this visitor tries to visit every part of the explicit
+/// source code exactly once. The default policy towards templates
+/// is to descend into the 'pattern' class or function body, not any
+/// explicit or implicit instantiations. Explicit specializations
+/// are still visited, and the patterns of partial specializations
+/// are visited separately. This behavior can be changed by
+/// overriding shouldVisitTemplateInstantiations() in the derived class
+/// to return true, in which case all known implicit and explicit
+/// instantiations will be visited at the same time as the pattern
+/// from which they were produced.
+template <typename Derived> class RecursiveASTVisitor {
+public:
+ /// \brief Return a reference to the derived class.
+ Derived &getDerived() { return *static_cast<Derived *>(this); }
+
+ /// \brief Return whether this visitor should recurse into
+ /// template instantiations.
+ bool shouldVisitTemplateInstantiations() const { return false; }
+
+ /// \brief Return whether this visitor should recurse into the types of
+ /// TypeLocs.
+ bool shouldWalkTypesOfTypeLocs() const { return true; }
+
+ /// \brief Recursively visit a statement or expression, by
+ /// dispatching to Traverse*() based on the argument's dynamic type.
+ ///
+ /// \returns false if the visitation was terminated early, true
+ /// otherwise (including when the argument is NULL).
+ bool TraverseStmt(Stmt *S);
+
+ /// \brief Recursively visit a type, by dispatching to
+ /// Traverse*Type() based on the argument's getTypeClass() property.
+ ///
+ /// \returns false if the visitation was terminated early, true
+ /// otherwise (including when the argument is a Null type).
+ bool TraverseType(QualType T);
+
+ /// \brief Recursively visit a type with location, by dispatching to
+ /// Traverse*TypeLoc() based on the argument type's getTypeClass() property.
+ ///
+ /// \returns false if the visitation was terminated early, true
+ /// otherwise (including when the argument is a Null type location).
+ bool TraverseTypeLoc(TypeLoc TL);
+
+ /// \brief Recursively visit 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);
+
+ // ---- 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 ----
+
+// Declare Traverse*() for all concrete Stmt classes.
+#define ABSTRACT_STMT(STMT)
+#define STMT(CLASS, PARENT) bool Traverse##CLASS(CLASS *S);
+#include "clang/AST/StmtNodes.inc"
+ // The above header #undefs ABSTRACT_STMT and STMT upon exit.
+
+ // Define WalkUpFrom*() and empty Visit*() for all Stmt classes.
+ bool WalkUpFromStmt(Stmt *S) { return getDerived().VisitStmt(S); }
+ bool VisitStmt(Stmt *S) { return true; }
+#define STMT(CLASS, PARENT) \
+ bool WalkUpFrom##CLASS(CLASS *S) { \
+ TRY_TO(WalkUpFrom##PARENT(S)); \
+ TRY_TO(Visit##CLASS(S)); \
+ return true; \
+ } \
+ bool Visit##CLASS(CLASS *S) { return true; }
+#include "clang/AST/StmtNodes.inc"
+
+// Define Traverse*(), WalkUpFrom*(), and Visit*() for unary
+// operator methods. Unary operators are not classes in themselves
+// (they're all opcodes in UnaryOperator) but do have visitors.
+#define OPERATOR(NAME) \
+ bool TraverseUnary##NAME(UnaryOperator *S) { \
+ TRY_TO(WalkUpFromUnary##NAME(S)); \
+ StmtQueueAction StmtQueue(*this); \
+ StmtQueue.queue(S->getSubExpr()); \
+ return true; \
+ } \
+ bool WalkUpFromUnary##NAME(UnaryOperator *S) { \
+ TRY_TO(WalkUpFromUnaryOperator(S)); \
+ TRY_TO(VisitUnary##NAME(S)); \
+ return true; \
+ } \
+ bool VisitUnary##NAME(UnaryOperator *S) { return true; }
+
+ UNARYOP_LIST()
+#undef OPERATOR
+
+// Define Traverse*(), WalkUpFrom*(), and Visit*() for binary
+// operator methods. Binary operators are not classes in themselves
+// (they're all opcodes in BinaryOperator) but do have visitors.
+#define GENERAL_BINOP_FALLBACK(NAME, BINOP_TYPE) \
+ bool TraverseBin##NAME(BINOP_TYPE *S) { \
+ TRY_TO(WalkUpFromBin##NAME(S)); \
+ StmtQueueAction StmtQueue(*this); \
+ StmtQueue.queue(S->getLHS()); \
+ StmtQueue.queue(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);
+ bool TraverseClassInstantiations(ClassTemplateDecl *D);
+ bool TraverseVariableInstantiations(VarTemplateDecl *D);
+ bool TraverseFunctionInstantiations(FunctionTemplateDecl *D);
+ bool TraverseTemplateArgumentLocsHelper(const TemplateArgumentLoc *TAL,
+ unsigned Count);
+ bool TraverseArrayTypeLocHelper(ArrayTypeLoc TL);
+ bool TraverseRecordHelper(RecordDecl *D);
+ bool TraverseCXXRecordHelper(CXXRecordDecl *D);
+ bool TraverseDeclaratorHelper(DeclaratorDecl *D);
+ bool TraverseDeclContextHelper(DeclContext *DC);
+ bool TraverseFunctionHelper(FunctionDecl *D);
+ bool TraverseVarHelper(VarDecl *D);
+ bool TraverseOMPExecutableDirective(OMPExecutableDirective *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);
+
+ typedef SmallVector<Stmt *, 16> StmtsTy;
+ typedef SmallVector<StmtsTy *, 4> QueuesTy;
+
+ QueuesTy Queues;
+
+ class NewQueueRAII {
+ RecursiveASTVisitor &RAV;
+
+ public:
+ NewQueueRAII(StmtsTy &queue, RecursiveASTVisitor &RAV) : RAV(RAV) {
+ RAV.Queues.push_back(&queue);
+ }
+ ~NewQueueRAII() { RAV.Queues.pop_back(); }
+ };
+
+ StmtsTy &getCurrentQueue() {
+ assert(!Queues.empty() && "base TraverseStmt was never called?");
+ return *Queues.back();
+ }
+
+public:
+ class StmtQueueAction {
+ StmtsTy &CurrQueue;
+
+ public:
+ explicit StmtQueueAction(RecursiveASTVisitor &RAV)
+ : CurrQueue(RAV.getCurrentQueue()) {}
+
+ void queue(Stmt *S) { CurrQueue.push_back(S); }
+ };
+};
+
+#define DISPATCH(NAME, CLASS, VAR) \
+ return getDerived().Traverse##NAME(static_cast<CLASS *>(VAR))
+
+template <typename Derived>
+bool RecursiveASTVisitor<Derived>::TraverseStmt(Stmt *S) {
+ if (!S)
+ return true;
+
+ StmtsTy Queue, StmtsToEnqueue;
+ Queue.push_back(S);
+ NewQueueRAII NQ(StmtsToEnqueue, *this);
+
+ while (!Queue.empty()) {
+ S = Queue.pop_back_val();
+ if (!S)
+ continue;
+
+ StmtsToEnqueue.clear();
+
+#define DISPATCH_STMT(NAME, CLASS, VAR) \
+ TRY_TO(Traverse##NAME(static_cast<CLASS *>(VAR))); \
+ break
+
+ // 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
+ }
+ } else {
+
+ // 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"
+ }
+ }
+
+ for (SmallVectorImpl<Stmt *>::reverse_iterator RI = StmtsToEnqueue.rbegin(),
+ RE = StmtsToEnqueue.rend();
+ RI != RE; ++RI)
+ Queue.push_back(*RI);
+ }
+
+ return true;
+}
+
+#undef DISPATCH_STMT
+
+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, we want to ignore declarations for
+ // implicitly-defined declarations (ones not typed explicitly by the
+ // user).
+ if (D->isImplicit())
+ return true;
+
+ switch (D->getKind()) {
+#define ABSTRACT_DECL(DECL)
+#define DECL(CLASS, BASE) \
+ case Decl::CLASS: \
+ 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:
+ 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:
+ 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())
+ TRY_TO(TraverseStmt(Init->getInit()));
+ return true;
+}
+
+template <typename Derived>
+bool
+RecursiveASTVisitor<Derived>::TraverseLambdaCapture(LambdaExpr *LE,
+ const LambdaCapture *C) {
+ if (C->isInitCapture())
+ TRY_TO(TraverseDecl(C->getCapturedVar()));
+ return true;
+}
+
+template <typename Derived>
+bool RecursiveASTVisitor<Derived>::TraverseLambdaBody(LambdaExpr *LE) {
+ StmtQueueAction StmtQueue(*this);
+ StmtQueue.queue(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));
+ }
+})
+
+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()));
+})
+
+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));
+ }
+})
+
+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()));
+})
+
+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())); })
+
+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(NamespaceAliasDecl, {
+ // We shouldn't traverse an aliased namespace, since it will be
+ // defined (and, therefore, traversed) somewhere else.
+ //
+ // This return statement makes sure the traversal of nodes in
+ // decls_begin()/decls_end() (done in the DEF_TRAVERSE_DECL macro)
+ // is skipped - don't remove it.
+ return true;
+})
+
+DEF_TRAVERSE_DECL(LabelDecl, {// There is no code in a LabelDecl.
+ })
+
+DEF_TRAVERSE_DECL(
+ NamespaceDecl,
+ {// Code in an unnamed namespace shows up automatically in
+ // decls_begin()/decls_end(). Thus we don't need to recurse on
+ // D->getAnonymousNamespace().
+ })
+
+DEF_TRAVERSE_DECL(ObjCCompatibleAliasDecl, {// FIXME: implement
+ })
+
+DEF_TRAVERSE_DECL(ObjCCategoryDecl, {// FIXME: implement
+ })
+
+DEF_TRAVERSE_DECL(ObjCCategoryImplDecl, {// FIXME: implement
+ })
+
+DEF_TRAVERSE_DECL(ObjCImplementationDecl, {// FIXME: implement
+ })
+
+DEF_TRAVERSE_DECL(ObjCInterfaceDecl, {// FIXME: implement
+ })
+
+DEF_TRAVERSE_DECL(ObjCProtocolDecl, {// FIXME: implement
+ })
+
+DEF_TRAVERSE_DECL(ObjCMethodDecl, {
+ 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(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;
+}
+
+// A helper method for traversing the implicit instantiations of a
+// class template.
+template <typename Derived>
+bool RecursiveASTVisitor<Derived>::TraverseClassInstantiations(
+ 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;
+}
+
+DEF_TRAVERSE_DECL(ClassTemplateDecl, {
+ CXXRecordDecl *TempDecl = D->getTemplatedDecl();
+ TRY_TO(TraverseDecl(TempDecl));
+ TRY_TO(TraverseTemplateParameterListHelper(D->getTemplateParameters()));
+
+ // By default, we do not traverse the instantiations of
+ // class templates since they do not 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(TraverseClassInstantiations(D));
+
+ // Note that getInstantiatedFromMemberTemplate() is just a link
+ // from a template instantiation back to the template from which
+ // it was instantiated, and thus should not be traversed.
+})
+
+// A helper method for traversing the implicit instantiations of a
+// class template.
+template <typename Derived>
+bool RecursiveASTVisitor<Derived>::TraverseVariableInstantiations(
+ VarTemplateDecl *D) {
+ for (auto *SD : D->specializations()) {
+ for (auto *RD : SD->redecls()) {
+ switch (
+ cast<VarTemplateSpecializationDecl>(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;
+}
+
+DEF_TRAVERSE_DECL(VarTemplateDecl, {
+ VarDecl *TempDecl = D->getTemplatedDecl();
+ TRY_TO(TraverseDecl(TempDecl));
+ TRY_TO(TraverseTemplateParameterListHelper(D->getTemplateParameters()));
+
+ // By default, we do not traverse the instantiations of
+ // variable templates since they do not appear in the user code. The
+ // following code optionally traverses them.
+ //
+ // We only traverse the variable 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(TraverseVariableInstantiations(D));
+
+ // Note that getInstantiatedFromMemberTemplate() is just a link
+ // from a template instantiation back to the template from which
+ // it was instantiated, and thus should not be traversed.
+})
+
+// A helper method for traversing the instantiations of a
+// function while skipping its specializations.
+template <typename Derived>
+bool RecursiveASTVisitor<Derived>::TraverseFunctionInstantiations(
+ FunctionTemplateDecl *D) {
+ 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;
+
+ // No need to visit explicit instantiations, we'll find the node
+ // eventually.
+ // FIXME: This is incorrect; there is no other node for an explicit
+ // instantiation of a function template specialization.
+ case TSK_ExplicitInstantiationDeclaration:
+ case TSK_ExplicitInstantiationDefinition:
+ break;
+
+ case TSK_ExplicitSpecialization:
+ break;
+ }
+ }
+ }
+
+ return true;
+}
+
+DEF_TRAVERSE_DECL(FunctionTemplateDecl, {
+ TRY_TO(TraverseDecl(D->getTemplatedDecl()));
+ TRY_TO(TraverseTemplateParameterListHelper(D->getTemplateParameters()));
+
+ // By default, we do not traverse the instantiations of
+ // function templates since they do not appear in the user code. The
+ // following code optionally traverses them.
+ //
+ // We only traverse the function 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(TraverseFunctionInstantiations(D));
+})
+
+DEF_TRAVERSE_DECL(TemplateTemplateParmDecl, {
+ // D is the "T" in something like
+ // template <template <typename> class T> class container { };
+ TRY_TO(TraverseDecl(D->getTemplatedDecl()));
+ if (D->hasDefaultArgument()) {
+ TRY_TO(TraverseTemplateArgumentLoc(D->getDefaultArgument()));
+ }
+ TRY_TO(TraverseTemplateParameterListHelper(D->getTemplateParameters()));
+})
+
+DEF_TRAVERSE_DECL(TemplateTypeParmDecl, {
+ // D is the "T" in something like "template<typename T> class vector;"
+ if (D->getTypeForDecl())
+ TRY_TO(TraverseType(QualType(D->getTypeForDecl(), 0)));
+ if (D->hasDefaultArgument())
+ TRY_TO(TraverseTypeLoc(D->getDefaultArgumentInfo()->getTypeLoc()));
+})
+
+DEF_TRAVERSE_DECL(TypedefDecl, {
+ TRY_TO(TraverseTypeLoc(D->getTypeSourceInfo()->getTypeLoc()));
+ // We shouldn't traverse D->getTypeForDecl(); it's a result of
+ // declaring the typedef, not something that was written in the
+ // source.
+})
+
+DEF_TRAVERSE_DECL(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)); })
+
+DEF_TRAVERSE_DECL(ClassTemplateSpecializationDecl, {
+ // For implicit instantiations ("set<int> x;"), we don't want to
+ // recurse at all, since the instatiated class isn't written in
+ // the source code anywhere. (Note the instatiated *type* --
+ // set<int> -- is written, and will still get a callback of
+ // TemplateSpecializationType). For explicit instantiations
+ // ("template set<int>;"), we do need a callback, since this
+ // is the only callback that's made for this instantiation.
+ // We use getTypeAsWritten() to distinguish.
+ if (TypeSourceInfo *TSI = D->getTypeAsWritten())
+ TRY_TO(TraverseTypeLoc(TSI->getTypeLoc()));
+
+ if (!getDerived().shouldVisitTemplateInstantiations() &&
+ D->getTemplateSpecializationKind() != TSK_ExplicitSpecialization)
+ // Returning from here skips traversing the
+ // declaration context of the ClassTemplateSpecializationDecl
+ // (embedded in the DEF_TRAVERSE_DECL() macro)
+ // which contains the instantiated members of the class.
+ return true;
+})
+
+template <typename Derived>
+bool RecursiveASTVisitor<Derived>::TraverseTemplateArgumentLocsHelper(
+ const TemplateArgumentLoc *TAL, unsigned Count) {
+ for (unsigned I = 0; I < Count; ++I) {
+ TRY_TO(TraverseTemplateArgumentLoc(TAL[I]));
+ }
+ return true;
+}
+
+DEF_TRAVERSE_DECL(ClassTemplatePartialSpecializationDecl, {
+ // The partial specialization.
+ if (TemplateParameterList *TPL = D->getTemplateParameters()) {
+ for (TemplateParameterList::iterator I = TPL->begin(), E = TPL->end();
+ I != E; ++I) {
+ TRY_TO(TraverseDecl(*I));
+ }
+ }
+ // The args that remains unspecialized.
+ TRY_TO(TraverseTemplateArgumentLocsHelper(
+ D->getTemplateArgsAsWritten()->getTemplateArgs(),
+ D->getTemplateArgsAsWritten()->NumTemplateArgs));
+
+ // Don't need the ClassTemplatePartialSpecializationHelper, even
+ // though that's our parent class -- we already visit all the
+ // template args here.
+ TRY_TO(TraverseCXXRecordHelper(D));
+
+ // Instantiations will have been visited with the primary template.
+})
+
+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.
+ TRY_TO(TraverseTypeLoc(D->getTypeSourceInfo()->getTypeLoc()));
+
+ 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))
+ TRY_TO(TraverseStmt(D->getInit()));
+ return true;
+}
+
+DEF_TRAVERSE_DECL(VarDecl, { TRY_TO(TraverseVarHelper(D)); })
+
+DEF_TRAVERSE_DECL(VarTemplateSpecializationDecl, {
+ // For implicit instantiations, we don't want to
+ // recurse at all, since the instatiated class isn't written in
+ // the source code anywhere.
+ 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 VarTemplateSpecializationDecl
+ // (embedded in the DEF_TRAVERSE_DECL() macro).
+ return true;
+})
+
+DEF_TRAVERSE_DECL(VarTemplatePartialSpecializationDecl, {
+ // 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 VarTemplatePartialSpecializationHelper, even
+ // though that's our parent class -- we already visit all the
+ // template args here.
+ TRY_TO(TraverseVarHelper(D));
+
+ // Instantiations will have been visited with the primary
+ // template.
+})
+
+DEF_TRAVERSE_DECL(ImplicitParamDecl, { TRY_TO(TraverseVarHelper(D)); })
+
+DEF_TRAVERSE_DECL(NonTypeTemplateParmDecl, {
+ // A non-type template parameter, e.g. "S" in template<int S> class Foo ...
+ TRY_TO(TraverseDeclaratorHelper(D));
+ TRY_TO(TraverseStmt(D->getDefaultArgument()));
+})
+
+DEF_TRAVERSE_DECL(ParmVarDecl, {
+ TRY_TO(TraverseVarHelper(D));
+
+ if (D->hasDefaultArg() && D->hasUninstantiatedDefaultArg() &&
+ !D->hasUnparsedDefaultArg())
+ TRY_TO(TraverseStmt(D->getUninstantiatedDefaultArg()));
+
+ if (D->hasDefaultArg() && !D->hasUninstantiatedDefaultArg() &&
+ !D->hasUnparsedDefaultArg())
+ TRY_TO(TraverseStmt(D->getDefaultArg()));
+})
+
+#undef DEF_TRAVERSE_DECL
+
+// ----------------- Stmt traversal -----------------
+//
+// For stmts, we automate (in the DEF_TRAVERSE_STMT macro) iterating
+// over the children defined in children() (every stmt defines these,
+// though sometimes the range is empty). Each individual Traverse*
+// method only needs to worry about children other than those. To see
+// what children() does for a given class, see, e.g.,
+// http://clang.llvm.org/doxygen/Stmt_8cpp_source.html
+
+// This macro makes available a variable S, the passed-in stmt.
+#define DEF_TRAVERSE_STMT(STMT, CODE) \
+ template <typename Derived> \
+ bool RecursiveASTVisitor<Derived>::Traverse##STMT(STMT *S) { \
+ TRY_TO(WalkUpFrom##STMT(S)); \
+ StmtQueueAction StmtQueue(*this); \
+ { CODE; } \
+ for (Stmt::child_range range = S->children(); range; ++range) { \
+ StmtQueue.queue(*range); \
+ } \
+ return true; \
+ }
+
+DEF_TRAVERSE_STMT(GCCAsmStmt, {
+ StmtQueue.queue(S->getAsmString());
+ for (unsigned I = 0, E = S->getNumInputs(); I < E; ++I) {
+ StmtQueue.queue(S->getInputConstraintLiteral(I));
+ }
+ for (unsigned I = 0, E = S->getNumOutputs(); I < E; ++I) {
+ StmtQueue.queue(S->getOutputConstraintLiteral(I));
+ }
+ for (unsigned I = 0, E = S->getNumClobbers(); I < E; ++I) {
+ StmtQueue.queue(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, {})
+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->getExplicitTemplateArgs().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()));
+})
+
+// InitListExpr is a tricky one, because we want to do all our work on
+// the syntactic form of the listexpr, but this method takes the
+// semantic form by default. We can't use the macro helper because it
+// calls WalkUp*() on the semantic form, before our code can convert
+// to the syntactic form.
+template <typename Derived>
+bool RecursiveASTVisitor<Derived>::TraverseInitListExpr(InitListExpr *S) {
+ if (InitListExpr *Syn = S->getSyntacticForm())
+ S = Syn;
+ TRY_TO(WalkUpFromInitListExpr(S));
+ StmtQueueAction StmtQueue(*this);
+ // All we need are the default actions. FIXME: use a helper function.
+ for (Stmt::child_range range = S->children(); range; ++range) {
+ StmtQueue.queue(*range);
+ }
+ 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).
+template <typename Derived>
+bool RecursiveASTVisitor<Derived>::TraverseGenericSelectionExpr(
+ GenericSelectionExpr *S) {
+ TRY_TO(WalkUpFromGenericSelectionExpr(S));
+ StmtQueueAction StmtQueue(*this);
+ StmtQueue.queue(S->getControllingExpr());
+ for (unsigned i = 0; i != S->getNumAssocs(); ++i) {
+ if (TypeSourceInfo *TS = S->getAssocTypeSourceInfo(i))
+ TRY_TO(TraverseTypeLoc(TS->getTypeLoc()));
+ StmtQueue.queue(S->getAssocExpr(i));
+ }
+ return true;
+}
+
+// PseudoObjectExpr is a special case because of the wierdness with
+// syntactic expressions and opaque values.
+template <typename Derived>
+bool
+RecursiveASTVisitor<Derived>::TraversePseudoObjectExpr(PseudoObjectExpr *S) {
+ TRY_TO(WalkUpFromPseudoObjectExpr(S));
+ StmtQueueAction StmtQueue(*this);
+ StmtQueue.queue(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();
+ StmtQueue.queue(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(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,
+ { StmtQueue.queue(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.
+template <typename Derived>
+bool RecursiveASTVisitor<Derived>::TraverseLambdaExpr(LambdaExpr *S) {
+ TRY_TO(WalkUpFromLambdaExpr(S));
+
+ for (LambdaExpr::capture_iterator C = S->explicit_capture_begin(),
+ CEnd = S->explicit_capture_end();
+ C != CEnd; ++C) {
+ TRY_TO(TraverseLambdaCapture(S, C));
+ }
+
+ if (S->hasExplicitParameters() || S->hasExplicitResultType()) {
+ TypeLoc TL = S->getCallOperator()->getTypeSourceInfo()->getTypeLoc();
+ if (S->hasExplicitParameters() && S->hasExplicitResultType()) {
+ // Visit the whole type.
+ TRY_TO(TraverseTypeLoc(TL));
+ } else if (FunctionProtoTypeLoc Proto = TL.getAs<FunctionProtoTypeLoc>()) {
+ if (S->hasExplicitParameters()) {
+ // Visit parameters.
+ for (unsigned I = 0, N = Proto.getNumParams(); I != N; ++I) {
+ TRY_TO(TraverseDecl(Proto.getParam(I)));
+ }
+ } else {
+ TRY_TO(TraverseTypeLoc(Proto.getReturnLoc()));
+ }
+ }
+ }
+
+ TRY_TO(TraverseLambdaBody(S));
+ return true;
+}
+
+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(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(ExtVectorElementExpr, {})
+DEF_TRAVERSE_STMT(GNUNullExpr, {})
+DEF_TRAVERSE_STMT(ImplicitValueInitExpr, {})
+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(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(AtomicExpr, {})
+
+// 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;
+}
+
+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(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(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(OMPFlushDirective,
+ { 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>::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()));
+ return true;
+}
+
+template <typename Derived>
+bool RecursiveASTVisitor<Derived>::VisitOMPOrderedClause(OMPOrderedClause *) {
+ 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>
+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));
+ return true;
+}
+
+template <typename Derived>
+bool RecursiveASTVisitor<Derived>::VisitOMPFirstprivateClause(
+ OMPFirstprivateClause *C) {
+ TRY_TO(VisitOMPClauseList(C));
+ return true;
+}
+
+template <typename Derived>
+bool RecursiveASTVisitor<Derived>::VisitOMPLastprivateClause(
+ OMPLastprivateClause *C) {
+ TRY_TO(VisitOMPClauseList(C));
+ 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(VisitOMPClauseList(C));
+ 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));
+ return true;
+}
+
+template <typename Derived>
+bool RecursiveASTVisitor<Derived>::VisitOMPCopyprivateClause(
+ OMPCopyprivateClause *C) {
+ TRY_TO(VisitOMPClauseList(C));
+ 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));
+ return true;
+}
+
+template <typename Derived>
+bool RecursiveASTVisitor<Derived>::VisitOMPFlushClause(OMPFlushClause *C) {
+ TRY_TO(VisitOMPClauseList(C));
+ 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 TRY_TO
+
+#undef RecursiveASTVisitor
+
+} // end namespace clang
+
+#endif // LLVM_CLANG_LIBCLANG_RECURSIVEASTVISITOR_H
diff --git a/include/clang/AST/Decl.h b/include/clang/AST/Decl.h
index 244a7b8d400c..ce8b8b7dbcd6 100644
--- a/include/clang/AST/Decl.h
+++ b/include/clang/AST/Decl.h
@@ -21,6 +21,7 @@
#include "clang/AST/Redeclarable.h"
#include "clang/AST/Type.h"
#include "clang/Basic/Linkage.h"
+#include "clang/Basic/OperatorKinds.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/Optional.h"
#include "llvm/Support/Compiler.h"
@@ -51,8 +52,7 @@ class VarTemplateDecl;
/// A client can read the relevant info using TypeLoc wrappers, e.g:
/// @code
/// TypeLoc TL = TypeSourceInfo->getTypeLoc();
-/// if (PointerLoc *PL = dyn_cast<PointerLoc>(&TL))
-/// PL->getStarLoc().print(OS, SrcMgr);
+/// TL.getStartLoc().print(OS, SrcMgr);
/// @endcode
///
class TypeSourceInfo {
@@ -79,9 +79,9 @@ class TranslationUnitDecl : public Decl, public DeclContext {
NamespaceDecl *AnonymousNamespace;
explicit TranslationUnitDecl(ASTContext &ctx)
- : Decl(TranslationUnit, 0, SourceLocation()),
+ : Decl(TranslationUnit, nullptr, SourceLocation()),
DeclContext(TranslationUnit),
- Ctx(ctx), AnonymousNamespace(0) {}
+ Ctx(ctx), AnonymousNamespace(nullptr) {}
public:
ASTContext &getASTContext() const { return Ctx; }
@@ -110,7 +110,7 @@ class NamedDecl : public Decl {
DeclarationName Name;
private:
- NamedDecl *getUnderlyingDeclImpl();
+ NamedDecl *getUnderlyingDeclImpl() LLVM_READONLY;
protected:
NamedDecl(Kind DK, DeclContext *DC, SourceLocation L, DeclarationName N)
@@ -161,9 +161,8 @@ public:
void printQualifiedName(raw_ostream &OS) const;
void printQualifiedName(raw_ostream &OS, const PrintingPolicy &Policy) const;
- // FIXME: Remove string versions.
+ // FIXME: Remove string version.
std::string getQualifiedNameAsString() const;
- std::string getQualifiedNameAsString(const PrintingPolicy &Policy) const;
/// getNameForDiagnostic - Appends a human-readable name for this
/// declaration into the given stream.
@@ -204,9 +203,8 @@ public:
// C++0x [class.mem]p1:
// The enumerators of an unscoped enumeration defined in
// the class are members of the class.
- // FIXME: support C++0x scoped enumerations.
if (isa<EnumDecl>(DC))
- DC = DC->getParent();
+ DC = DC->getRedeclContext();
return DC->isRecord();
}
@@ -259,6 +257,16 @@ public:
/// 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() {
@@ -295,7 +303,7 @@ inline raw_ostream &operator<<(raw_ostream &OS, const NamedDecl &ND) {
/// location of the statement. For GNU local labels (__label__), the decl
/// location is where the __label__ is.
class LabelDecl : public NamedDecl {
- virtual void anchor();
+ void anchor() override;
LabelStmt *TheStmt;
/// LocStart - For normal labels, this is the same as the main declaration
/// label, i.e., the location of the identifier; for GNU local labels,
@@ -320,7 +328,7 @@ public:
bool isGnuLocal() const { return LocStart != getLocation(); }
void setLocStart(SourceLocation L) { LocStart = L; }
- SourceRange getSourceRange() const LLVM_READONLY {
+ SourceRange getSourceRange() const override LLVM_READONLY {
return SourceRange(LocStart, getLocation());
}
@@ -333,8 +341,6 @@ public:
class NamespaceDecl : public NamedDecl, public DeclContext,
public Redeclarable<NamespaceDecl>
{
- virtual void anchor();
-
/// LocStart - The starting location of the source range, pointing
/// to either the namespace or the inline keyword.
SourceLocation LocStart;
@@ -347,21 +353,15 @@ class NamespaceDecl : public NamedDecl, public DeclContext,
/// boolean value indicating whether this is an inline namespace.
llvm::PointerIntPair<NamespaceDecl *, 1, bool> AnonOrFirstNamespaceAndInline;
- NamespaceDecl(DeclContext *DC, bool Inline, SourceLocation StartLoc,
- SourceLocation IdLoc, IdentifierInfo *Id,
- NamespaceDecl *PrevDecl);
-
+ NamespaceDecl(ASTContext &C, DeclContext *DC, bool Inline,
+ SourceLocation StartLoc, SourceLocation IdLoc,
+ IdentifierInfo *Id, NamespaceDecl *PrevDecl);
+
typedef Redeclarable<NamespaceDecl> redeclarable_base;
- virtual NamespaceDecl *getNextRedeclaration() {
- return RedeclLink.getNext();
- }
- virtual NamespaceDecl *getPreviousDeclImpl() {
- return getPreviousDecl();
- }
- virtual NamespaceDecl *getMostRecentDeclImpl() {
- return getMostRecentDecl();
- }
-
+ NamespaceDecl *getNextRedeclarationImpl() override;
+ NamespaceDecl *getPreviousDeclImpl() override;
+ NamespaceDecl *getMostRecentDeclImpl() override;
+
public:
static NamespaceDecl *Create(ASTContext &C, DeclContext *DC,
bool Inline, SourceLocation StartLoc,
@@ -370,9 +370,11 @@ public:
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;
@@ -432,14 +434,14 @@ public:
}
/// Retrieves the canonical declaration of this namespace.
- NamespaceDecl *getCanonicalDecl() {
+ NamespaceDecl *getCanonicalDecl() override {
return getOriginalNamespace();
}
const NamespaceDecl *getCanonicalDecl() const {
return getOriginalNamespace();
}
-
- virtual SourceRange getSourceRange() const LLVM_READONLY {
+
+ SourceRange getSourceRange() const override LLVM_READONLY {
return SourceRange(LocStart, RBraceLoc);
}
@@ -466,7 +468,7 @@ public:
/// an lvalue) a function (in which case it is a function designator) or
/// an enum constant.
class ValueDecl : public NamedDecl {
- virtual void anchor();
+ void anchor() override;
QualType DeclType;
protected:
@@ -505,7 +507,8 @@ struct QualifierInfo {
TemplateParameterList** TemplParamLists;
/// Default constructor.
- QualifierInfo() : QualifierLoc(), NumTemplParamLists(0), TemplParamLists(0) {}
+ QualifierInfo()
+ : QualifierLoc(), NumTemplParamLists(0), TemplParamLists(nullptr) {}
/// setTemplateParameterListsInfo - Sets info about "outer" template
/// parameter lists.
@@ -567,7 +570,7 @@ public:
/// range taking into account any outer template declarations.
SourceLocation getOuterLocStart() const;
- virtual SourceRange getSourceRange() const LLVM_READONLY;
+ SourceRange getSourceRange() const override LLVM_READONLY;
SourceLocation getLocStart() const LLVM_READONLY {
return getOuterLocStart();
}
@@ -576,7 +579,7 @@ public:
/// declaration, if it was present in the source.
NestedNameSpecifier *getQualifier() const {
return hasExtInfo() ? getExtInfo()->QualifierLoc.getNestedNameSpecifier()
- : 0;
+ : nullptr;
}
/// \brief Retrieve the nested-name-specifier (with source-location
@@ -764,23 +767,27 @@ protected:
ParmVarDeclBitfields ParmVarDeclBits;
};
- VarDecl(Kind DK, DeclContext *DC, SourceLocation StartLoc,
+ VarDecl(Kind DK, ASTContext &C, DeclContext *DC, SourceLocation StartLoc,
SourceLocation IdLoc, IdentifierInfo *Id, QualType T,
TypeSourceInfo *TInfo, StorageClass SC);
typedef Redeclarable<VarDecl> redeclarable_base;
- virtual VarDecl *getNextRedeclaration() { return RedeclLink.getNext(); }
- virtual VarDecl *getPreviousDeclImpl() {
+ VarDecl *getNextRedeclarationImpl() override {
+ return getNextRedeclaration();
+ }
+ VarDecl *getPreviousDeclImpl() override {
return getPreviousDecl();
}
- virtual VarDecl *getMostRecentDeclImpl() {
+ 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;
@@ -791,8 +798,8 @@ public:
StorageClass S);
static VarDecl *CreateDeserialized(ASTContext &C, unsigned ID);
-
- virtual SourceRange getSourceRange() const LLVM_READONLY;
+
+ SourceRange getSourceRange() const override LLVM_READONLY;
/// \brief Returns the storage class as written in the source. For the
/// computed linkage of symbol, see getLinkage.
@@ -803,22 +810,12 @@ public:
void setTSCSpec(ThreadStorageClassSpecifier TSC) {
VarDeclBits.TSCSpec = TSC;
+ assert(VarDeclBits.TSCSpec == TSC && "truncation");
}
ThreadStorageClassSpecifier getTSCSpec() const {
return static_cast<ThreadStorageClassSpecifier>(VarDeclBits.TSCSpec);
}
- TLSKind getTLSKind() const {
- switch (VarDeclBits.TSCSpec) {
- case TSCS_unspecified:
- return TLS_None;
- case TSCS___thread: // Fall through.
- case TSCS__Thread_local:
- return TLS_Static;
- case TSCS_thread_local:
- return TLS_Dynamic;
- }
- llvm_unreachable("Unknown thread storage class specifier!");
- }
+ TLSKind getTLSKind() const;
/// hasLocalStorage - Returns true if a variable with function scope
/// is a non-static local variable.
@@ -827,6 +824,10 @@ public:
// Second check is for C++11 [dcl.stc]p4.
return !isFileVarDecl() && getTSCSpec() == TSCS_unspecified;
+ // Global Named Register (GNU extension)
+ if (getStorageClass() == SC_Register && !isLocalVarDecl())
+ return false;
+
// Return true for: Auto, Register.
// Return false for: Extern, Static, PrivateExtern, OpenCLWorkGroupLocal.
@@ -913,7 +914,7 @@ public:
return getKind() != Decl::ParmVar && getDeclContext()->isRecord();
}
- virtual VarDecl *getCanonicalDecl();
+ VarDecl *getCanonicalDecl() override;
const VarDecl *getCanonicalDecl() const {
return const_cast<VarDecl*>(this)->getCanonicalDecl();
}
@@ -960,7 +961,7 @@ public:
/// \brief Determine whether this is or was instantiated from an out-of-line
/// definition of a static data member.
- virtual bool isOutOfLine() const;
+ bool isOutOfLine() const override;
/// \brief If this is a static data member, find its out-of-line definition.
VarDecl *getOutOfLineDefinition();
@@ -996,7 +997,7 @@ public:
}
const Expr *getInit() const {
if (Init.isNull())
- return 0;
+ return nullptr;
const Stmt *S = Init.dyn_cast<Stmt *>();
if (!S) {
@@ -1007,7 +1008,7 @@ public:
}
Expr *getInit() {
if (Init.isNull())
- return 0;
+ return nullptr;
Stmt *S = Init.dyn_cast<Stmt *>();
if (!S) {
@@ -1058,7 +1059,7 @@ public:
if (Eval->WasEvaluated)
return &Eval->Evaluated;
- return 0;
+ return nullptr;
}
/// \brief Determines whether it is already known whether the
@@ -1208,18 +1209,18 @@ public:
};
class ImplicitParamDecl : public VarDecl {
- virtual void anchor();
+ 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(DeclContext *DC, SourceLocation IdLoc,
+
+ ImplicitParamDecl(ASTContext &C, DeclContext *DC, SourceLocation IdLoc,
IdentifierInfo *Id, QualType Type)
- : VarDecl(ImplicitParam, DC, IdLoc, IdLoc, Id, Type,
- /*tinfo*/ 0, SC_None) {
+ : VarDecl(ImplicitParam, C, DC, IdLoc, IdLoc, Id, Type,
+ /*tinfo*/ nullptr, SC_None) {
setImplicit();
}
@@ -1235,11 +1236,10 @@ public:
enum { MaxFunctionScopeIndex = 255 };
protected:
- ParmVarDecl(Kind DK, DeclContext *DC, SourceLocation StartLoc,
- SourceLocation IdLoc, IdentifierInfo *Id,
- QualType T, TypeSourceInfo *TInfo,
- StorageClass S, Expr *DefArg)
- : VarDecl(DK, DC, StartLoc, IdLoc, Id, T, TInfo, S) {
+ 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.IsKNRPromoted == false);
assert(ParmVarDeclBits.IsObjCMethodParam == false);
@@ -1254,8 +1254,8 @@ public:
StorageClass S, Expr *DefArg);
static ParmVarDecl *CreateDeserialized(ASTContext &C, unsigned ID);
-
- virtual SourceRange getSourceRange() const LLVM_READONLY;
+
+ SourceRange getSourceRange() const override LLVM_READONLY;
void setObjCMethodScopeInfo(unsigned parameterIndex) {
ParmVarDeclBits.IsObjCMethodParam = true;
@@ -1362,9 +1362,7 @@ public:
/// real default argument via setDefaultArg when the class
/// definition enclosing the function declaration that owns this
/// default argument is completed.
- void setUnparsedDefaultArg() {
- Init = (UnparsedDefaultArgument *)0;
- }
+ void setUnparsedDefaultArg() { Init = (UnparsedDefaultArgument *)nullptr; }
bool hasInheritedDefaultArg() const {
return ParmVarDeclBits.HasInheritedDefaultArg;
@@ -1538,7 +1536,7 @@ private:
void setParams(ASTContext &C, ArrayRef<ParmVarDecl *> NewParamInfo);
protected:
- FunctionDecl(Kind DK, DeclContext *DC, SourceLocation StartLoc,
+ FunctionDecl(Kind DK, ASTContext &C, DeclContext *DC, SourceLocation StartLoc,
const DeclarationNameInfo &NameInfo,
QualType T, TypeSourceInfo *TInfo,
StorageClass S, bool isInlineSpecified,
@@ -1546,7 +1544,8 @@ protected:
: DeclaratorDecl(DK, DC, NameInfo.getLoc(), NameInfo.getName(), T, TInfo,
StartLoc),
DeclContext(DK),
- ParamInfo(0), Body(),
+ redeclarable_base(C),
+ ParamInfo(nullptr), Body(),
SClass(S),
IsInline(isInlineSpecified), IsInlineSpecified(isInlineSpecified),
IsVirtualAsWritten(false), IsPure(false), HasInheritedPrototype(false),
@@ -1559,18 +1558,22 @@ protected:
DNLoc(NameInfo.getInfo()) {}
typedef Redeclarable<FunctionDecl> redeclarable_base;
- virtual FunctionDecl *getNextRedeclaration() { return RedeclLink.getNext(); }
- virtual FunctionDecl *getPreviousDeclImpl() {
+ FunctionDecl *getNextRedeclarationImpl() override {
+ return getNextRedeclaration();
+ }
+ FunctionDecl *getPreviousDeclImpl() override {
return getPreviousDecl();
}
- virtual FunctionDecl *getMostRecentDeclImpl() {
+ 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;
@@ -1605,13 +1608,12 @@ public:
return DeclarationNameInfo(getDeclName(), getLocation(), DNLoc);
}
- virtual void getNameForDiagnostic(raw_ostream &OS,
- const PrintingPolicy &Policy,
- bool Qualified) const;
+ void getNameForDiagnostic(raw_ostream &OS, const PrintingPolicy &Policy,
+ bool Qualified) const override;
void setRangeEnd(SourceLocation E) { EndRangeLoc = E; }
- virtual SourceRange getSourceRange() const LLVM_READONLY;
+ 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
@@ -1620,7 +1622,7 @@ public:
/// containing the body (if there is one).
bool hasBody(const FunctionDecl *&Definition) const;
- virtual bool hasBody() const {
+ bool hasBody() const override {
const FunctionDecl* Definition;
return hasBody(Definition);
}
@@ -1648,7 +1650,7 @@ public:
/// unnecessary AST de-serialization of the body.
Stmt *getBody(const FunctionDecl *&Definition) const;
- virtual Stmt *getBody() const {
+ Stmt *getBody() const override {
const FunctionDecl* Definition;
return getBody(Definition);
}
@@ -1828,7 +1830,7 @@ public:
void setPreviousDeclaration(FunctionDecl * PrevDecl);
virtual const FunctionDecl *getCanonicalDecl() const;
- virtual FunctionDecl *getCanonicalDecl();
+ FunctionDecl *getCanonicalDecl() override;
unsigned getBuiltinID() const;
@@ -1836,12 +1838,24 @@ public:
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 ParamInfo; }
- param_iterator param_end() { return ParamInfo+param_size(); }
+ 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 ParamInfo; }
- param_const_iterator param_end() const { return ParamInfo+param_size(); }
+ 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
@@ -1860,6 +1874,12 @@ public:
setParams(getASTContext(), NewParamInfo);
}
+ // ArrayRef iterface to parameters.
+ // FIXME: Should one day replace iterator interface.
+ ArrayRef<ParmVarDecl*> parameters() const {
+ return llvm::makeArrayRef(ParamInfo, getNumParams());
+ }
+
const ArrayRef<NamedDecl *> &getDeclsInPrototypeScope() const {
return DeclsInPrototypeScope;
}
@@ -1871,10 +1891,15 @@ public:
/// arguments (in C++).
unsigned getMinRequiredArguments() const;
- QualType getResultType() const {
- return getType()->getAs<FunctionType>()->getResultType();
+ 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());
@@ -1906,6 +1931,8 @@ public:
bool isInlineDefinitionExternallyVisible() const;
+ bool isMSExternInline() const;
+
bool doesDeclarationForceExternallyVisibleDefinition() const;
/// isOverloadedOperator - Whether this function declaration
@@ -1981,7 +2008,7 @@ public:
/// \brief Determine whether this function is a function template
/// specialization.
bool isFunctionTemplateSpecialization() const {
- return getPrimaryTemplate() != 0;
+ return getPrimaryTemplate() != nullptr;
}
/// \brief Retrieve the class scope template pattern that this function
@@ -2054,11 +2081,11 @@ public:
/// \param PointOfInstantiation point at which the function template
/// specialization was first instantiated.
void setFunctionTemplateSpecialization(FunctionTemplateDecl *Template,
- const TemplateArgumentList *TemplateArgs,
- void *InsertPos,
- TemplateSpecializationKind TSK = TSK_ImplicitInstantiation,
- const TemplateArgumentListInfo *TemplateArgsAsWritten = 0,
- SourceLocation PointOfInstantiation = SourceLocation()) {
+ const TemplateArgumentList *TemplateArgs,
+ void *InsertPos,
+ TemplateSpecializationKind TSK = TSK_ImplicitInstantiation,
+ const TemplateArgumentListInfo *TemplateArgsAsWritten = nullptr,
+ SourceLocation PointOfInstantiation = SourceLocation()) {
setFunctionTemplateSpecialization(getASTContext(), Template, TemplateArgs,
InsertPos, TSK, TemplateArgsAsWritten,
PointOfInstantiation);
@@ -2095,7 +2122,7 @@ public:
/// \brief Determine whether this is or was instantiated from an out-of-line
/// definition of a member function.
- virtual bool isOutOfLine() const;
+ bool isOutOfLine() const override;
/// \brief Identify a memory copying or setting function.
/// If the given function is a memory copy or setting function, returns
@@ -2181,7 +2208,7 @@ public:
bool isAnonymousStructOrUnion() const;
Expr *getBitWidth() const {
- return isBitField() ? InitializerOrBitWidth.getPointer() : 0;
+ return isBitField() ? InitializerOrBitWidth.getPointer() : nullptr;
}
unsigned getBitWidthValue(const ASTContext &Ctx) const;
@@ -2192,7 +2219,7 @@ public:
// Note: used by some clients (i.e., do not remove it).
void removeBitWidth() {
assert(isBitField() && "no bitfield width to remove");
- InitializerOrBitWidth.setPointer(0);
+ InitializerOrBitWidth.setPointer(nullptr);
}
/// getInClassInitStyle - Get the kind of (C++11) in-class initializer which
@@ -2211,7 +2238,8 @@ public:
/// in-class initializer, but this returns null, then we have not parsed and
/// attached it yet.
Expr *getInClassInitializer() const {
- return hasInClassInitializer() ? InitializerOrBitWidth.getPointer() : 0;
+ return hasInClassInitializer() ? InitializerOrBitWidth.getPointer()
+ : nullptr;
}
/// setInClassInitializer - Set the C++11 in-class initializer for this
/// member.
@@ -2220,7 +2248,7 @@ public:
/// member.
void removeInClassInitializer() {
assert(hasInClassInitializer() && "no initializer to remove");
- InitializerOrBitWidth.setPointer(0);
+ InitializerOrBitWidth.setPointer(nullptr);
InitializerOrBitWidth.setInt(ICIS_NoInit);
}
@@ -2234,10 +2262,10 @@ public:
return cast<RecordDecl>(getDeclContext());
}
- SourceRange getSourceRange() const LLVM_READONLY;
+ SourceRange getSourceRange() const override LLVM_READONLY;
/// Retrieves the canonical declaration of this field.
- FieldDecl *getCanonicalDecl() { return getFirstDecl(); }
+ FieldDecl *getCanonicalDecl() override { return getFirstDecl(); }
const FieldDecl *getCanonicalDecl() const { return getFirstDecl(); }
// Implement isa/cast/dyncast/etc.
@@ -2276,10 +2304,10 @@ public:
void setInitExpr(Expr *E) { Init = (Stmt*) E; }
void setInitVal(const llvm::APSInt &V) { Val = V; }
- SourceRange getSourceRange() const LLVM_READONLY;
+ SourceRange getSourceRange() const override LLVM_READONLY;
/// Retrieves the canonical declaration of this enumerator.
- EnumConstantDecl *getCanonicalDecl() { return getFirstDecl(); }
+ EnumConstantDecl *getCanonicalDecl() override { return getFirstDecl(); }
const EnumConstantDecl *getCanonicalDecl() const { return getFirstDecl(); }
// Implement isa/cast/dyncast/etc.
@@ -2293,7 +2321,7 @@ public:
/// field injected from an anonymous union/struct into the parent scope.
/// IndirectFieldDecl are always implicit.
class IndirectFieldDecl : public ValueDecl {
- virtual void anchor();
+ void anchor() override;
NamedDecl **Chaining;
unsigned ChainingSize;
@@ -2310,8 +2338,13 @@ public:
static IndirectFieldDecl *CreateDeserialized(ASTContext &C, unsigned ID);
typedef NamedDecl * const *chain_iterator;
- chain_iterator chain_begin() const { return Chaining; }
- chain_iterator chain_end() const { return Chaining+ChainingSize; }
+ 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; }
@@ -2334,7 +2367,7 @@ public:
/// TypeDecl - Represents a declaration of a type.
///
class TypeDecl : public NamedDecl {
- virtual void anchor();
+ void anchor() override;
/// TypeForDecl - This indicates the Type object that represents
/// this TypeDecl. It is a cache maintained by
/// ASTContext::getTypedefType, ASTContext::getTagDeclType, and
@@ -2343,16 +2376,11 @@ class TypeDecl : public NamedDecl {
/// LocStart - The start of the source range for this declaration.
SourceLocation LocStart;
friend class ASTContext;
- friend class DeclContext;
- friend class TagDecl;
- friend class TemplateTypeParmDecl;
- friend class TagType;
- friend class ASTReader;
protected:
TypeDecl(Kind DK, DeclContext *DC, SourceLocation L, IdentifierInfo *Id,
SourceLocation StartL = SourceLocation())
- : NamedDecl(DK, DC, L, Id), TypeForDecl(0), LocStart(StartL) {}
+ : NamedDecl(DK, DC, L, Id), TypeForDecl(nullptr), LocStart(StartL) {}
public:
// Low-level accessor. If you just want the type defined by this node,
@@ -2364,7 +2392,7 @@ public:
SourceLocation getLocStart() const LLVM_READONLY { return LocStart; }
void setLocStart(SourceLocation L) { LocStart = L; }
- virtual SourceRange getSourceRange() const LLVM_READONLY {
+ SourceRange getSourceRange() const override LLVM_READONLY {
if (LocStart.isValid())
return SourceRange(LocStart, getLocation());
else
@@ -2379,31 +2407,34 @@ public:
/// Base class for declarations which introduce a typedef-name.
class TypedefNameDecl : public TypeDecl, public Redeclarable<TypedefNameDecl> {
- virtual void anchor();
+ void anchor() override;
typedef std::pair<TypeSourceInfo*, QualType> ModedTInfo;
llvm::PointerUnion<TypeSourceInfo*, ModedTInfo*> MaybeModedTInfo;
protected:
- TypedefNameDecl(Kind DK, DeclContext *DC, SourceLocation StartLoc,
- SourceLocation IdLoc, IdentifierInfo *Id,
- TypeSourceInfo *TInfo)
- : TypeDecl(DK, DC, IdLoc, Id, StartLoc), MaybeModedTInfo(TInfo) {}
+ 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;
- virtual TypedefNameDecl *getNextRedeclaration() {
- return RedeclLink.getNext();
+ TypedefNameDecl *getNextRedeclarationImpl() override {
+ return getNextRedeclaration();
}
- virtual TypedefNameDecl *getPreviousDeclImpl() {
+ TypedefNameDecl *getPreviousDeclImpl() override {
return getPreviousDecl();
}
- virtual TypedefNameDecl *getMostRecentDeclImpl() {
+ 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;
@@ -2428,7 +2459,7 @@ public:
}
/// Retrieves the canonical declaration of this typedef-name.
- TypedefNameDecl *getCanonicalDecl() { return getFirstDecl(); }
+ TypedefNameDecl *getCanonicalDecl() override { return getFirstDecl(); }
const TypedefNameDecl *getCanonicalDecl() const { return getFirstDecl(); }
// Implement isa/cast/dyncast/etc.
@@ -2441,17 +2472,17 @@ public:
/// TypedefDecl - Represents the declaration of a typedef-name via the 'typedef'
/// type specifier.
class TypedefDecl : public TypedefNameDecl {
- TypedefDecl(DeclContext *DC, SourceLocation StartLoc, SourceLocation IdLoc,
- IdentifierInfo *Id, TypeSourceInfo *TInfo)
- : TypedefNameDecl(Typedef, DC, StartLoc, IdLoc, Id, TInfo) {}
+ 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 LLVM_READONLY;
+
+ SourceRange getSourceRange() const override LLVM_READONLY;
// Implement isa/cast/dyncast/etc.
static bool classof(const Decl *D) { return classofKind(D->getKind()); }
@@ -2461,9 +2492,9 @@ public:
/// TypeAliasDecl - Represents the declaration of a typedef-name via a C++0x
/// alias-declaration.
class TypeAliasDecl : public TypedefNameDecl {
- TypeAliasDecl(DeclContext *DC, SourceLocation StartLoc, SourceLocation IdLoc,
- IdentifierInfo *Id, TypeSourceInfo *TInfo)
- : TypedefNameDecl(TypeAlias, DC, StartLoc, IdLoc, Id, TInfo) {}
+ TypeAliasDecl(ASTContext &C, DeclContext *DC, SourceLocation StartLoc,
+ SourceLocation IdLoc, IdentifierInfo *Id, TypeSourceInfo *TInfo)
+ : TypedefNameDecl(TypeAlias, C, DC, StartLoc, IdLoc, Id, TInfo) {}
public:
static TypeAliasDecl *Create(ASTContext &C, DeclContext *DC,
@@ -2471,7 +2502,7 @@ public:
IdentifierInfo *Id, TypeSourceInfo *TInfo);
static TypeAliasDecl *CreateDeserialized(ASTContext &C, unsigned ID);
- SourceRange getSourceRange() const LLVM_READONLY;
+ SourceRange getSourceRange() const override LLVM_READONLY;
// Implement isa/cast/dyncast/etc.
static bool classof(const Decl *D) { return classofKind(D->getKind()); }
@@ -2559,24 +2590,27 @@ private:
}
protected:
- TagDecl(Kind DK, TagKind TK, DeclContext *DC, SourceLocation L,
- IdentifierInfo *Id, TagDecl *PrevDecl, SourceLocation StartL)
- : TypeDecl(DK, DC, L, Id, StartL), DeclContext(DK), TagDeclKind(TK),
- IsCompleteDefinition(false), IsBeingDefined(false),
+ 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),
- NamedDeclOrQualifier((NamedDecl *)0) {
+ NamedDeclOrQualifier((NamedDecl *)nullptr) {
assert((DK != Enum || TK == TTK_Enum) &&
"EnumDecl not matched with TTK_Enum");
setPreviousDecl(PrevDecl);
}
typedef Redeclarable<TagDecl> redeclarable_base;
- virtual TagDecl *getNextRedeclaration() { return RedeclLink.getNext(); }
- virtual TagDecl *getPreviousDeclImpl() {
+ TagDecl *getNextRedeclarationImpl() override {
+ return getNextRedeclaration();
+ }
+ TagDecl *getPreviousDeclImpl() override {
return getPreviousDecl();
}
- virtual TagDecl *getMostRecentDeclImpl() {
+ TagDecl *getMostRecentDeclImpl() override {
return getMostRecentDecl();
}
@@ -2586,9 +2620,11 @@ protected:
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;
@@ -2603,10 +2639,10 @@ public:
/// getOuterLocStart - Return SourceLocation representing start of source
/// range taking into account any outer template declarations.
SourceLocation getOuterLocStart() const;
- virtual SourceRange getSourceRange() const LLVM_READONLY;
+ SourceRange getSourceRange() const override LLVM_READONLY;
- virtual TagDecl* getCanonicalDecl();
- const TagDecl* getCanonicalDecl() const {
+ TagDecl *getCanonicalDecl() override;
+ const TagDecl *getCanonicalDecl() const {
return const_cast<TagDecl*>(this)->getCanonicalDecl();
}
@@ -2673,8 +2709,7 @@ public:
IsCompleteDefinitionRequired = V;
}
- // FIXME: Return StringRef;
- const char *getKindName() const {
+ StringRef getKindName() const {
return TypeWithKeyword::getTagTypeKindName(getTagKind());
}
@@ -2714,12 +2749,12 @@ public:
NamedDeclOrQualifier.get<NamedDecl *>());
}
DeclaratorDecl *getDeclaratorForAnonDecl() const {
- return hasExtInfo() ? 0 : dyn_cast_or_null<DeclaratorDecl>(
+ return hasExtInfo() ? nullptr : dyn_cast_or_null<DeclaratorDecl>(
NamedDeclOrQualifier.get<NamedDecl *>());
}
TypedefNameDecl *getTypedefNameForAnonDecl() const {
- return hasExtInfo() ? 0 : dyn_cast_or_null<TypedefNameDecl>(
+ return hasExtInfo() ? nullptr : dyn_cast_or_null<TypedefNameDecl>(
NamedDeclOrQualifier.get<NamedDecl *>());
}
@@ -2731,7 +2766,7 @@ public:
/// declaration, if it was present in the source.
NestedNameSpecifier *getQualifier() const {
return hasExtInfo() ? getExtInfo()->QualifierLoc.getNestedNameSpecifier()
- : 0;
+ : nullptr;
}
/// \brief Retrieve the nested-name-specifier (with source-location
@@ -2773,7 +2808,7 @@ public:
/// 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 {
- virtual void anchor();
+ 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.
@@ -2802,13 +2837,13 @@ class EnumDecl : public TagDecl {
/// information.
MemberSpecializationInfo *SpecializationInfo;
- EnumDecl(DeclContext *DC, SourceLocation StartLoc, SourceLocation IdLoc,
- IdentifierInfo *Id, EnumDecl *PrevDecl,
+ EnumDecl(ASTContext &C, DeclContext *DC, SourceLocation StartLoc,
+ SourceLocation IdLoc, IdentifierInfo *Id, EnumDecl *PrevDecl,
bool Scoped, bool ScopedUsingClassTag, bool Fixed)
- : TagDecl(Enum, TTK_Enum, DC, IdLoc, Id, PrevDecl, StartLoc),
- SpecializationInfo(0) {
+ : TagDecl(Enum, TTK_Enum, C, DC, IdLoc, Id, PrevDecl, StartLoc),
+ SpecializationInfo(nullptr) {
assert(Scoped || !ScopedUsingClassTag);
- IntegerType = (const Type*)0;
+ IntegerType = (const Type *)nullptr;
NumNegativeBits = 0;
NumPositiveBits = 0;
IsScoped = Scoped;
@@ -2819,7 +2854,7 @@ class EnumDecl : public TagDecl {
void setInstantiationOfMemberEnum(ASTContext &C, EnumDecl *ED,
TemplateSpecializationKind TSK);
public:
- EnumDecl *getCanonicalDecl() {
+ EnumDecl *getCanonicalDecl() override {
return cast<EnumDecl>(TagDecl::getCanonicalDecl());
}
const EnumDecl *getCanonicalDecl() const {
@@ -2865,6 +2900,12 @@ public:
// 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();
@@ -2888,27 +2929,32 @@ public:
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.
+ /// 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*>())
+ if (const Type *T = IntegerType.dyn_cast<const Type*>())
return QualType(T, 0);
- return IntegerType.get<TypeSourceInfo*>()->getType();
+ 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; }
+ 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 {
+ 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 {
@@ -3024,14 +3070,14 @@ class RecordDecl : public TagDecl {
friend class DeclContext;
protected:
- RecordDecl(Kind DK, TagKind TK, DeclContext *DC,
+ 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 = 0);
+ IdentifierInfo *Id, RecordDecl* PrevDecl = nullptr);
static RecordDecl *CreateDeserialized(const ASTContext &C, unsigned ID);
RecordDecl *getPreviousDecl() {
@@ -3106,7 +3152,9 @@ public:
// 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 {
@@ -3155,7 +3203,7 @@ public:
SourceLocation getAsmLoc() const { return getLocation(); }
SourceLocation getRParenLoc() const { return RParenLoc; }
void setRParenLoc(SourceLocation L) { RParenLoc = L; }
- SourceRange getSourceRange() const LLVM_READONLY {
+ SourceRange getSourceRange() const override LLVM_READONLY {
return SourceRange(getAsmLoc(), getRParenLoc());
}
@@ -3206,7 +3254,7 @@ public:
/// is not from outside the immediately enclosing function/block.
bool isNested() const { return VariableAndFlags.getInt() & flag_isNested; }
- bool hasCopyExpr() const { return CopyExpr != 0; }
+ bool hasCopyExpr() const { return CopyExpr != nullptr; }
Expr *getCopyExpr() const { return CopyExpr; }
void setCopyExpr(Expr *e) { CopyExpr = e; }
};
@@ -3237,9 +3285,9 @@ protected:
: Decl(Block, DC, CaretLoc), DeclContext(Block),
IsVariadic(false), CapturesCXXThis(false),
BlockMissingReturnType(true), IsConversionFromLambda(false),
- ParamInfo(0), NumParams(0), Body(0),
- SignatureAsWritten(0), Captures(0), NumCaptures(0),
- ManglingNumber(0), ManglingContextDecl(0) {}
+ 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);
@@ -3251,7 +3299,7 @@ public:
void setIsVariadic(bool value) { IsVariadic = value; }
CompoundStmt *getCompoundBody() const { return (CompoundStmt*) Body; }
- Stmt *getBody() const { return (Stmt*) Body; }
+ Stmt *getBody() const override { return (Stmt*) Body; }
void setBody(CompoundStmt *B) { Body = (Stmt*) B; }
void setSignatureAsWritten(TypeSourceInfo *Sig) { SignatureAsWritten = Sig; }
@@ -3261,13 +3309,31 @@ public:
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_iterator param_begin() { return ParamInfo; }
- param_iterator param_end() { return ParamInfo+param_size(); }
+ 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_iterator param_begin() const { return ParamInfo; }
- param_const_iterator param_end() const { return 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 {
@@ -3290,6 +3356,16 @@ public:
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; }
@@ -3321,7 +3397,7 @@ public:
ManglingContextDecl = Ctx;
}
- virtual SourceRange getSourceRange() const LLVM_READONLY;
+ SourceRange getSourceRange() const override LLVM_READONLY;
// Implement isa/cast/dyncast/etc.
static bool classof(const Decl *D) { return classofKind(D->getKind()); }
@@ -3340,12 +3416,14 @@ class CapturedDecl : public Decl, public DeclContext {
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.
- Stmt *Body;
+ llvm::PointerIntPair<Stmt *, 1, bool> BodyAndNothrow;
explicit CapturedDecl(DeclContext *DC, unsigned NumParams)
: Decl(Captured, DC, SourceLocation()), DeclContext(Captured),
- NumParams(NumParams), Body(0) { }
+ NumParams(NumParams), ContextParam(0), BodyAndNothrow(nullptr, false) { }
ImplicitParamDecl **getParams() const {
return reinterpret_cast<ImplicitParamDecl **>(
@@ -3353,12 +3431,16 @@ private:
}
public:
- static CapturedDecl *Create(ASTContext &C, DeclContext *DC, unsigned NumParams);
+ static CapturedDecl *Create(ASTContext &C, DeclContext *DC,
+ unsigned NumParams);
static CapturedDecl *CreateDeserialized(ASTContext &C, unsigned ID,
unsigned NumParams);
- Stmt *getBody() const { return Body; }
- void setBody(Stmt *B) { Body = B; }
+ Stmt *getBody() const override { return BodyAndNothrow.getPointer(); }
+ void setBody(Stmt *B) { BodyAndNothrow.setPointer(B); }
+
+ bool isNothrow() const { return BodyAndNothrow.getInt(); }
+ void setNothrow(bool Nothrow = true) { BodyAndNothrow.setInt(Nothrow); }
unsigned getNumParams() const { return NumParams; }
@@ -3372,15 +3454,28 @@ public:
}
/// \brief Retrieve the parameter containing captured variables.
- ImplicitParamDecl *getContextParam() const { return getParam(0); }
- void setContextParam(ImplicitParamDecl *P) { setParam(0, P); }
+ 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 **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; }
@@ -3455,9 +3550,9 @@ public:
/// This will return an empty array if the locations of the individual
/// identifiers aren't available.
ArrayRef<SourceLocation> getIdentifierLocs() const;
-
- virtual SourceRange getSourceRange() const LLVM_READONLY;
-
+
+ SourceRange getSourceRange() const override LLVM_READONLY;
+
static bool classof(const Decl *D) { return classofKind(D->getKind()); }
static bool classofKind(Kind K) { return K == Import; }
};
@@ -3496,6 +3591,8 @@ 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");
decl_type *First;
@@ -3505,7 +3602,7 @@ void Redeclarable<decl_type>::setPreviousDecl(decl_type *PrevDecl) {
// 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->RedeclLink.getNext();
+ decl_type *MostRecent = First->getNextRedeclaration();
RedeclLink = PreviousDeclLink(cast<decl_type>(MostRecent));
// If the declaration was previously visible, a redeclaration of it remains
@@ -3519,7 +3616,8 @@ void Redeclarable<decl_type>::setPreviousDecl(decl_type *PrevDecl) {
}
// First one will point to this one as latest.
- First->RedeclLink = LatestDeclLink(static_cast<decl_type*>(this));
+ First->RedeclLink.setLatest(static_cast<decl_type*>(this));
+
assert(!isa<NamedDecl>(static_cast<decl_type*>(this)) ||
cast<NamedDecl>(static_cast<decl_type*>(this))->isLinkageValid());
}
diff --git a/include/clang/AST/DeclBase.h b/include/clang/AST/DeclBase.h
index 26eea64f9d34..607ca4ec27c6 100644
--- a/include/clang/AST/DeclBase.h
+++ b/include/clang/AST/DeclBase.h
@@ -16,9 +16,9 @@
#include "clang/AST/AttrIterator.h"
#include "clang/AST/DeclarationName.h"
-#include "clang/Basic/Linkage.h"
#include "clang/Basic/Specifiers.h"
#include "llvm/ADT/PointerUnion.h"
+#include "llvm/ADT/iterator_range.h"
#include "llvm/Support/Compiler.h"
#include "llvm/Support/PrettyStackTrace.h"
@@ -32,6 +32,8 @@ class DeclarationName;
class DependentDiagnostic;
class EnumDecl;
class FunctionDecl;
+class FunctionType;
+enum Linkage : unsigned char;
class LinkageComputer;
class LinkageSpecDecl;
class Module;
@@ -52,20 +54,6 @@ class TranslationUnitDecl;
class UsingDirectiveDecl;
}
-namespace llvm {
-// DeclContext* is only 4-byte aligned on 32-bit systems.
-template<>
- class PointerLikeTypeTraits<clang::DeclContext*> {
- typedef clang::DeclContext* PT;
-public:
- static inline void *getAsVoidPointer(PT P) { return P; }
- static inline PT getFromVoidPointer(void *P) {
- return static_cast<PT>(P);
- }
- enum { NumLowBitsAvailable = 2 };
-};
-}
-
namespace clang {
/// \brief Captures the result of checking the availability of a
@@ -302,8 +290,24 @@ protected:
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:
- void CheckAccessDeclContext() const;
+ bool AccessDeclContextSanity() const;
protected:
@@ -330,18 +334,6 @@ protected:
virtual ~Decl();
- /// \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 Context The context in which we will allocate memory.
- /// \param ID The global ID of the deserialized declaration.
- /// \param Size The size of the allocated object.
- static void *AllocateDeserializedDecl(const ASTContext &Context,
- unsigned ID,
- unsigned Size);
-
/// \brief Update a potentially out-of-date declaration.
void updateOutOfDate(IdentifierInfo &II) const;
@@ -405,19 +397,17 @@ public:
bool isInAnonymousNamespace() const;
+ bool isInStdNamespace() const;
+
ASTContext &getASTContext() const LLVM_READONLY;
void setAccess(AccessSpecifier AS) {
Access = AS;
-#ifndef NDEBUG
- CheckAccessDeclContext();
-#endif
+ assert(AccessDeclContextSanity());
}
AccessSpecifier getAccess() const {
-#ifndef NDEBUG
- CheckAccessDeclContext();
-#endif
+ assert(AccessDeclContextSanity());
return AccessSpecifier(Access);
}
@@ -445,14 +435,17 @@ public:
}
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());
+ }
- // FIXME: Do not rely on iterators having comparable singular values.
- // Note that this should error out if they do not.
attr_iterator attr_begin() const {
- return hasAttrs() ? getAttrs().begin() : 0;
+ return hasAttrs() ? getAttrs().begin() : nullptr;
}
attr_iterator attr_end() const {
- return hasAttrs() ? getAttrs().end() : 0;
+ return hasAttrs() ? getAttrs().end() : nullptr;
}
template <typename T>
@@ -467,6 +460,12 @@ public:
}
template <typename T>
+ llvm::iterator_range<specific_attr_iterator<T>> specific_attrs() const {
+ return llvm::iterator_range<specific_attr_iterator<T>>(
+ 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());
}
@@ -476,7 +475,7 @@ public:
}
template<typename T> T *getAttr() const {
- return hasAttrs() ? getSpecificAttr<T>(getAttrs()) : 0;
+ return hasAttrs() ? getSpecificAttr<T>(getAttrs()) : nullptr;
}
template<typename T> bool hasAttr() const {
return hasAttrs() && hasSpecificAttr<T>(getAttrs());
@@ -573,14 +572,14 @@ public:
/// 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 = 0) const;
+ 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 = 0) const {
+ bool isDeprecated(std::string *Message = nullptr) const {
return getAvailability(Message) == AR_Deprecated;
}
@@ -589,7 +588,7 @@ public:
/// \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 = 0) const {
+ bool isUnavailable(std::string *Message = nullptr) const {
return getAvailability(Message) == AR_Unavailable;
}
@@ -636,7 +635,7 @@ private:
public:
Module *getOwningModule() const {
if (!isFromASTFile())
- return 0;
+ return nullptr;
return getOwningModuleSlow();
}
@@ -691,7 +690,7 @@ public:
/// roughly global variables and functions, but also handles enums (which
/// could be defined inside or outside a function etc).
bool isDefinedOutsideFunctionOrMethod() const {
- return getParentFunctionOrMethod() == 0;
+ return getParentFunctionOrMethod() == nullptr;
}
/// \brief If this decl is defined inside a function/method/block it returns
@@ -716,16 +715,16 @@ protected:
///
/// Decl subclasses that can be redeclared should override this method so that
/// Decl::redecl_iterator can iterate over them.
- virtual Decl *getNextRedeclaration() { return this; }
+ virtual Decl *getNextRedeclarationImpl() { return this; }
/// \brief Implementation of getPreviousDecl(), to be overridden by any
/// subclass that has a redeclaration chain.
- virtual Decl *getPreviousDeclImpl() { return 0; }
-
+ virtual Decl *getPreviousDeclImpl() { return nullptr; }
+
/// \brief Implementation of getMostRecentDecl(), to be overridden by any
- /// subclass that has a redeclaration chain.
+ /// 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 {
@@ -740,7 +739,7 @@ public:
typedef std::forward_iterator_tag iterator_category;
typedef std::ptrdiff_t difference_type;
- redecl_iterator() : Current(0) { }
+ redecl_iterator() : Current(nullptr) { }
explicit redecl_iterator(Decl *C) : Current(C), Starter(C) { }
reference operator*() const { return Current; }
@@ -749,9 +748,9 @@ public:
redecl_iterator& operator++() {
assert(Current && "Advancing while iterator has reached end");
// Get either previous decl or latest decl.
- Decl *Next = Current->getNextRedeclaration();
+ Decl *Next = Current->getNextRedeclarationImpl();
assert(Next && "Should return next redeclaration or itself, never null!");
- Current = (Next != Starter ? Next : 0);
+ Current = (Next != Starter) ? Next : nullptr;
return *this;
}
@@ -769,10 +768,16 @@ public:
}
};
- /// \brief Returns iterator for all the redeclarations of the same decl.
- /// It will iterate at least once (when this decl is the only one).
+ 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));
+ return redecl_iterator(const_cast<Decl *>(this));
}
redecl_iterator redecls_end() const { return redecl_iterator(); }
@@ -788,7 +793,7 @@ public:
/// \brief True if this is the first declaration in its redeclaration chain.
bool isFirstDecl() const {
- return getPreviousDecl() == 0;
+ return getPreviousDecl() == nullptr;
}
/// \brief Retrieve the most recent declaration that declares the same entity
@@ -804,13 +809,13 @@ public:
/// getBody - If this Decl represents a declaration for a body of code,
/// such as a function or method definition, this method returns the
/// top-level Stmt* of that body. Otherwise this method returns null.
- virtual Stmt* getBody() const { return 0; }
+ 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() != 0; }
+ 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.
@@ -836,7 +841,19 @@ public:
bool isTemplateDecl() const;
/// \brief Whether this declaration is a function or function template.
- bool isFunctionOrFunctionTemplate() const;
+ 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.
@@ -938,11 +955,16 @@ public:
raw_ostream &Out, const PrintingPolicy &Policy,
unsigned Indentation = 0);
// Debuggers don't usually respect default arguments.
- LLVM_ATTRIBUTE_USED void dump() const;
+ void dump() const;
// Same as dump(), but forces color printing.
- LLVM_ATTRIBUTE_USED void dumpColor() const;
+ 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,
@@ -975,10 +997,10 @@ public:
SourceManager &sm, const char *Msg)
: TheDecl(theDecl), Loc(L), SM(sm), Message(Msg) {}
- virtual void print(raw_ostream &OS) const;
+ void print(raw_ostream &OS) const override;
};
-typedef llvm::MutableArrayRef<NamedDecl*> DeclContextLookupResult;
+typedef MutableArrayRef<NamedDecl *> DeclContextLookupResult;
typedef ArrayRef<NamedDecl *> DeclContextLookupConstResult;
@@ -1048,8 +1070,8 @@ protected:
DeclContext(Decl::Kind K)
: DeclKind(K), ExternalLexicalStorage(false),
ExternalVisibleStorage(false),
- NeedToReconcileExternalVisibleStorage(false), LookupPtr(0, false),
- FirstDecl(0), LastDecl(0) {}
+ NeedToReconcileExternalVisibleStorage(false), LookupPtr(nullptr, false),
+ FirstDecl(nullptr), LastDecl(nullptr) {}
public:
~DeclContext();
@@ -1136,6 +1158,8 @@ public:
return DeclKind == Decl::Namespace;
}
+ bool isStdNamespace() const;
+
bool isInlineNamespace() const;
/// \brief Determines whether this context is dependent on a
@@ -1256,7 +1280,7 @@ public:
typedef std::forward_iterator_tag iterator_category;
typedef std::ptrdiff_t difference_type;
- decl_iterator() : Current(0) { }
+ decl_iterator() : Current(nullptr) { }
explicit decl_iterator(Decl *C) : Current(C) { }
reference operator*() const { return Current; }
@@ -1282,8 +1306,11 @@ public:
}
};
+ 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;
@@ -1291,7 +1318,10 @@ public:
/// noload_decls_begin/end - Iterate over the declarations stored in this
/// context that are currently loaded; don't attempt to retrieve anything
/// from an external source.
- decl_iterator noload_decls_begin() const;
+ decl_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
@@ -1537,6 +1567,11 @@ public:
/// 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;
@@ -1547,26 +1582,15 @@ public:
all_lookups_iterator noload_lookups_begin() const;
all_lookups_iterator noload_lookups_end() const;
- /// udir_iterator - Iterates through the using-directives stored
- /// within this context.
- typedef UsingDirectiveDecl * const * udir_iterator;
-
- typedef std::pair<udir_iterator, udir_iterator> udir_iterator_range;
+ typedef llvm::iterator_range<UsingDirectiveDecl * const *> udir_range;
- udir_iterator_range getUsingDirectives() const;
-
- udir_iterator using_directives_begin() const {
- return getUsingDirectives().first;
- }
-
- udir_iterator using_directives_end() const {
- return getUsingDirectives().second;
- }
+ udir_range using_directives() const;
// These are all defined in DependentDiagnostic.h.
class ddiag_iterator;
- inline ddiag_iterator ddiag_begin() const;
- inline ddiag_iterator ddiag_end() const;
+ typedef llvm::iterator_range<DeclContext::ddiag_iterator> ddiag_range;
+
+ inline ddiag_range ddiags() const;
// Low-level accessors
@@ -1616,12 +1640,12 @@ public:
static bool classof(const Decl *D);
static bool classof(const DeclContext *D) { return true; }
- LLVM_ATTRIBUTE_USED void dumpDeclContext() const;
- LLVM_ATTRIBUTE_USED void dumpLookups() const;
- LLVM_ATTRIBUTE_USED void dumpLookups(llvm::raw_ostream &OS) const;
+ void dumpDeclContext() const;
+ void dumpLookups() const;
+ void dumpLookups(llvm::raw_ostream &OS) const;
private:
- void reconcileExternalVisibleStorage();
+ void reconcileExternalVisibleStorage() const;
void LoadLexicalDeclsFromExternalStorage() const;
/// @brief Makes a declaration visible within this context, but
@@ -1650,7 +1674,7 @@ inline bool Decl::isTemplateParameter() const {
// Specialization selected when ToTy is not a known subclass of DeclContext.
template <class ToTy,
- bool IsKnownSubtype = ::llvm::is_base_of< DeclContext, ToTy>::value>
+ 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));
diff --git a/include/clang/AST/DeclCXX.h b/include/clang/AST/DeclCXX.h
index dbc41320bd72..72fad7c28e49 100644
--- a/include/clang/AST/DeclCXX.h
+++ b/include/clang/AST/DeclCXX.h
@@ -17,13 +17,12 @@
#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/ExprCXX.h"
-#include "clang/AST/TypeLoc.h"
+#include "clang/AST/LambdaCapture.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/PointerIntPair.h"
-#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/Support/Compiler.h"
namespace clang {
@@ -122,14 +121,14 @@ public:
/// \brief Sets the location of the colon.
void setColonLoc(SourceLocation CLoc) { ColonLoc = CLoc; }
- SourceRange getSourceRange() const LLVM_READONLY {
+ 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) AccessSpecDecl(AS, DC, ASLoc, ColonLoc);
+ return new (C, DC) AccessSpecDecl(AS, DC, ASLoc, ColonLoc);
}
static AccessSpecDecl *CreateDeserialized(ASTContext &C, unsigned ID);
@@ -258,20 +257,31 @@ public:
TypeSourceInfo *getTypeSourceInfo() const { return BaseTypeInfo; }
};
-/// The inheritance model to use for member pointers of a given CXXRecordDecl.
-enum MSInheritanceModel {
- MSIM_Single,
- MSIM_SinglePolymorphic,
- MSIM_Multiple,
- MSIM_MultiplePolymorphic,
- MSIM_Virtual,
- MSIM_Unspecified
+/// \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.
-///
-/// FIXME: This class will disappear once we've properly taught RecordDecl
-/// to deal with C++-specific things.
class CXXRecordDecl : public RecordDecl {
friend void TagDecl::startDefinition();
@@ -350,10 +360,15 @@ class CXXRecordDecl : public RecordDecl {
/// \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.
+ /// \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
@@ -409,7 +424,7 @@ class CXXRecordDecl : public RecordDecl {
/// \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..
+ /// or an implicitly declared constexpr default constructor.
bool HasConstexprDefaultConstructor : 1;
/// \brief True when this class contains at least one non-static data
@@ -447,6 +462,9 @@ class CXXRecordDecl : public RecordDecl {
/// \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;
@@ -486,33 +504,39 @@ class CXXRecordDecl : public RecordDecl {
/// \brief Retrieve the set of direct base classes.
CXXBaseSpecifier *getBases() const {
if (!Bases.isOffset())
- return Bases.get(0);
+ return Bases.get(nullptr);
return getBasesSlowCase();
}
/// \brief Retrieve the set of virtual base classes.
CXXBaseSpecifier *getVBases() const {
if (!VBases.isOffset())
- return VBases.get(0);
+ return VBases.get(nullptr);
return getVBasesSlowCase();
}
private:
CXXBaseSpecifier *getBasesSlowCase() const;
CXXBaseSpecifier *getVBasesSlowCase() const;
- } *DefinitionData;
+ };
+
+ 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 LambdaExpr::Capture Capture;
-
- LambdaDefinitionData(CXXRecordDecl *D, TypeSourceInfo *Info,
+ 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(0), Captures(0), MethodTyInfo(Info)
- {
+ ManglingNumber(0), ContextDecl(nullptr), Captures(nullptr),
+ MethodTyInfo(Info) {
IsLambda = true;
}
@@ -557,23 +581,20 @@ class CXXRecordDecl : public RecordDecl {
};
- struct DefinitionData &data() {
- assert(DefinitionData && "queried property of class with no definition");
- return *DefinitionData;
- }
-
- const struct DefinitionData &data() const {
- assert(DefinitionData && "queried property of class with no definition");
- return *DefinitionData;
+ struct DefinitionData &data() const {
+ auto *DD = DefinitionData.get();
+ assert(DD && "queried property of class with no definition");
+ return *DD;
}
struct LambdaDefinitionData &getLambdaData() const {
- assert(DefinitionData && "queried property of lambda with no definition");
- assert(DefinitionData->IsLambda &&
- "queried lambda property of non-lambda class");
- return static_cast<LambdaDefinitionData &>(*DefinitionData);
+ // 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.
///
@@ -610,7 +631,7 @@ class CXXRecordDecl : public RecordDecl {
FriendDecl *getFirstFriend() const;
protected:
- CXXRecordDecl(Kind K, TagKind TK, DeclContext *DC,
+ CXXRecordDecl(Kind K, TagKind TK, const ASTContext &C, DeclContext *DC,
SourceLocation StartLoc, SourceLocation IdLoc,
IdentifierInfo *Id, CXXRecordDecl *PrevDecl);
@@ -621,17 +642,7 @@ public:
/// \brief Iterator that traverses the base classes of a class.
typedef const CXXBaseSpecifier* base_class_const_iterator;
- /// \brief Iterator that traverses the base classes of a class in reverse
- /// order.
- typedef std::reverse_iterator<base_class_iterator>
- reverse_base_class_iterator;
-
- /// \brief Iterator that traverses the base classes of a class in reverse
- /// order.
- typedef std::reverse_iterator<base_class_const_iterator>
- reverse_base_class_const_iterator;
-
- virtual CXXRecordDecl *getCanonicalDecl() {
+ CXXRecordDecl *getCanonicalDecl() override {
return cast<CXXRecordDecl>(RecordDecl::getCanonicalDecl());
}
virtual const CXXRecordDecl *getCanonicalDecl() const {
@@ -656,19 +667,20 @@ public:
}
CXXRecordDecl *getDefinition() const {
- if (!DefinitionData) return 0;
- return data().Definition;
+ auto *DD = DefinitionData.get();
+ return DD ? DD->Definition : nullptr;
}
- bool hasDefinition() const { return DefinitionData != 0; }
+ bool hasDefinition() const { return DefinitionData.get(); }
static CXXRecordDecl *Create(const ASTContext &C, TagKind TK, DeclContext *DC,
SourceLocation StartLoc, SourceLocation IdLoc,
- IdentifierInfo *Id, CXXRecordDecl* PrevDecl=0,
+ IdentifierInfo *Id,
+ CXXRecordDecl *PrevDecl = nullptr,
bool DelayTypeCreation = false);
static CXXRecordDecl *CreateLambda(const ASTContext &C, DeclContext *DC,
TypeSourceInfo *Info, SourceLocation Loc,
- bool DependentLambda, bool IsGeneric,
+ bool DependentLambda, bool IsGeneric,
LambdaCaptureDefault CaptureDefault);
static CXXRecordDecl *CreateDeserialized(const ASTContext &C, unsigned ID);
@@ -676,52 +688,52 @@ public:
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;
}
- reverse_base_class_iterator bases_rbegin() {
- return reverse_base_class_iterator(bases_end());
- }
- reverse_base_class_const_iterator bases_rbegin() const {
- return reverse_base_class_const_iterator(bases_end());
- }
- reverse_base_class_iterator bases_rend() {
- return reverse_base_class_iterator(bases_begin());
- }
- reverse_base_class_const_iterator bases_rend() const {
- return reverse_base_class_const_iterator(bases_begin());
- }
/// \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;
}
- reverse_base_class_iterator vbases_rbegin() {
- return reverse_base_class_iterator(vbases_end());
- }
- reverse_base_class_const_iterator vbases_rbegin() const {
- return reverse_base_class_const_iterator(vbases_end());
- }
- reverse_base_class_iterator vbases_rend() {
- return reverse_base_class_iterator(vbases_begin());
- }
- reverse_base_class_const_iterator vbases_rend() const {
- return reverse_base_class_const_iterator(vbases_begin());
- }
/// \brief Determine whether this class has any dependent base classes which
/// are not the current instantiation.
@@ -731,6 +743,12 @@ public:
/// 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.
@@ -744,6 +762,10 @@ public:
/// 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());
@@ -755,6 +777,9 @@ public:
/// 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);
@@ -984,7 +1009,11 @@ public:
}
/// \brief Determine whether this class describes a lambda function object.
- bool isLambda() const { return hasDefinition() && data().IsLambda; }
+ 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
@@ -1025,12 +1054,18 @@ public:
void getCaptureFields(llvm::DenseMap<const VarDecl *, FieldDecl *> &Captures,
FieldDecl *&ThisCapture) const;
- typedef const LambdaExpr::Capture* capture_const_iterator;
+ 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 : NULL;
+ return isLambda() ? getLambdaData().Captures : nullptr;
}
capture_const_iterator captures_end() const {
- return isLambda() ? captures_begin() + getLambdaData().NumCaptures : NULL;
+ return isLambda() ? captures_begin() + getLambdaData().NumCaptures
+ : nullptr;
}
typedef UnresolvedSetIterator conversion_iterator;
@@ -1058,7 +1093,8 @@ public:
bool isAggregate() const { return data().Aggregate; }
/// \brief Whether this class has any in-class initializers
- /// for non-static data members.
+ /// 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
@@ -1117,6 +1153,9 @@ public:
/// 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 {
@@ -1144,7 +1183,7 @@ public:
/// would be constexpr.
bool defaultedDefaultConstructorIsConstexpr() const {
return data().DefaultedDefaultConstructorIsConstexpr &&
- (!isUnion() || hasInClassInitializer());
+ (!isUnion() || hasInClassInitializer() || !hasVariantMembers());
}
/// \brief Determine whether this class has a constexpr default constructor.
@@ -1546,7 +1585,7 @@ public:
void finishedDefaultedOrDeletedMember(CXXMethodDecl *MD);
/// \brief Indicates that the definition of this class is now complete.
- virtual void completeDefinition();
+ void completeDefinition() override;
/// \brief Indicates that the definition of this class is now complete,
/// and provides a final overrider map to help determine
@@ -1599,7 +1638,25 @@ public:
}
/// \brief Returns the inheritance model used for this record.
- MSInheritanceModel getMSInheritanceModel() const;
+ 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
@@ -1636,14 +1693,14 @@ public:
/// In the terminology of the C++ Standard, these are the (static and
/// non-static) member functions, whether virtual or not.
class CXXMethodDecl : public FunctionDecl {
- virtual void anchor();
+ void anchor() override;
protected:
- CXXMethodDecl(Kind DK, CXXRecordDecl *RD, SourceLocation StartLoc,
- const DeclarationNameInfo &NameInfo,
+ 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, RD, StartLoc, NameInfo, T, TInfo,
+ : FunctionDecl(DK, C, RD, StartLoc, NameInfo, T, TInfo,
SC, isInline, isConstexpr) {
if (EndLocation.isValid())
setRangeEnd(EndLocation);
@@ -1683,9 +1740,9 @@ public:
CXXMethodDecl *CD =
cast<CXXMethodDecl>(const_cast<CXXMethodDecl*>(this)->getCanonicalDecl());
- // Methods declared in interfaces are automatically (pure) virtual.
- if (CD->isVirtualAsWritten() ||
- (CD->getParent()->isInterface() && CD->isUserProvided()))
+ // 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());
@@ -1703,10 +1760,10 @@ public:
/// \brief Determine whether this is a move assignment operator.
bool isMoveAssignmentOperator() const;
- CXXMethodDecl *getCanonicalDecl() {
+ CXXMethodDecl *getCanonicalDecl() override {
return cast<CXXMethodDecl>(FunctionDecl::getCanonicalDecl());
}
- const CXXMethodDecl *getCanonicalDecl() const {
+ const CXXMethodDecl *getCanonicalDecl() const override {
return const_cast<CXXMethodDecl*>(this)->getCanonicalDecl();
}
@@ -1921,7 +1978,7 @@ public:
/// In-class member initializers (also known as "non-static data member
/// initializations", NSDMIs) were introduced in C++11.
bool isInClassMemberInitializer() const {
- return isa<CXXDefaultInitExpr>(Init);
+ return Init->getStmtClass() == Stmt::CXXDefaultInitExprClass;
}
/// \brief Determine whether this initializer is creating a delegating
@@ -1968,20 +2025,20 @@ public:
FieldDecl *getMember() const {
if (isMemberInitializer())
return Initializee.get<FieldDecl*>();
- return 0;
+ return nullptr;
}
FieldDecl *getAnyMember() const {
if (isMemberInitializer())
return Initializee.get<FieldDecl*>();
if (isIndirectMemberInitializer())
return Initializee.get<IndirectFieldDecl*>()->getAnonField();
- return 0;
+ return nullptr;
}
IndirectFieldDecl *getIndirectMember() const {
if (isIndirectMemberInitializer())
return Initializee.get<IndirectFieldDecl*>();
- return 0;
+ return nullptr;
}
SourceLocation getMemberLocation() const {
@@ -2066,7 +2123,7 @@ public:
/// };
/// \endcode
class CXXConstructorDecl : public CXXMethodDecl {
- virtual void anchor();
+ void anchor() override;
/// \brief Whether this constructor declaration has the \c explicit keyword
/// specified.
bool IsExplicitSpecified : 1;
@@ -2078,14 +2135,14 @@ class CXXConstructorDecl : public CXXMethodDecl {
unsigned NumCtorInitializers;
/// \}
- CXXConstructorDecl(CXXRecordDecl *RD, SourceLocation StartLoc,
+ CXXConstructorDecl(ASTContext &C, CXXRecordDecl *RD, SourceLocation StartLoc,
const DeclarationNameInfo &NameInfo,
QualType T, TypeSourceInfo *TInfo,
bool isExplicitSpecified, bool isInline,
bool isImplicitlyDeclared, bool isConstexpr)
- : CXXMethodDecl(CXXConstructor, RD, StartLoc, NameInfo, T, TInfo,
+ : CXXMethodDecl(CXXConstructor, C, RD, StartLoc, NameInfo, T, TInfo,
SC_None, isInline, isConstexpr, SourceLocation()),
- IsExplicitSpecified(isExplicitSpecified), CtorInitializers(0),
+ IsExplicitSpecified(isExplicitSpecified), CtorInitializers(nullptr),
NumCtorInitializers(0) {
setImplicit(isImplicitlyDeclared);
}
@@ -2115,6 +2172,14 @@ public:
/// \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() { return CtorInitializers; }
/// \brief Retrieve an iterator to the first initializer.
@@ -2240,10 +2305,10 @@ public:
/// \brief Set the constructor that this inheriting constructor is based on.
void setInheritedConstructor(const CXXConstructorDecl *BaseCtor);
- const CXXConstructorDecl *getCanonicalDecl() const {
+ const CXXConstructorDecl *getCanonicalDecl() const override {
return cast<CXXConstructorDecl>(FunctionDecl::getCanonicalDecl());
}
- CXXConstructorDecl *getCanonicalDecl() {
+ CXXConstructorDecl *getCanonicalDecl() override {
return cast<CXXConstructorDecl>(FunctionDecl::getCanonicalDecl());
}
@@ -2266,17 +2331,17 @@ public:
/// };
/// \endcode
class CXXDestructorDecl : public CXXMethodDecl {
- virtual void anchor();
+ void anchor() override;
FunctionDecl *OperatorDelete;
- CXXDestructorDecl(CXXRecordDecl *RD, SourceLocation StartLoc,
+ CXXDestructorDecl(ASTContext &C, CXXRecordDecl *RD, SourceLocation StartLoc,
const DeclarationNameInfo &NameInfo,
QualType T, TypeSourceInfo *TInfo,
bool isInline, bool isImplicitlyDeclared)
- : CXXMethodDecl(CXXDestructor, RD, StartLoc, NameInfo, T, TInfo,
+ : CXXMethodDecl(CXXDestructor, C, RD, StartLoc, NameInfo, T, TInfo,
SC_None, isInline, /*isConstexpr=*/false, SourceLocation()),
- OperatorDelete(0) {
+ OperatorDelete(nullptr) {
setImplicit(isImplicitlyDeclared);
}
@@ -2289,8 +2354,12 @@ public:
bool isImplicitlyDeclared);
static CXXDestructorDecl *CreateDeserialized(ASTContext & C, unsigned ID);
- void setOperatorDelete(FunctionDecl *OD) { OperatorDelete = OD; }
- const FunctionDecl *getOperatorDelete() const { return OperatorDelete; }
+ void setOperatorDelete(FunctionDecl *OD) {
+ cast<CXXDestructorDecl>(getFirstDecl())->OperatorDelete = 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()); }
@@ -2311,18 +2380,18 @@ public:
/// };
/// \endcode
class CXXConversionDecl : public CXXMethodDecl {
- virtual void anchor();
+ 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++0x feature.
bool IsExplicitSpecified : 1;
- CXXConversionDecl(CXXRecordDecl *RD, SourceLocation StartLoc,
+ CXXConversionDecl(ASTContext &C, CXXRecordDecl *RD, SourceLocation StartLoc,
const DeclarationNameInfo &NameInfo,
QualType T, TypeSourceInfo *TInfo,
bool isInline, bool isExplicitSpecified,
bool isConstexpr, SourceLocation EndLocation)
- : CXXMethodDecl(CXXConversion, RD, StartLoc, NameInfo, T, TInfo,
+ : CXXMethodDecl(CXXConversion, C, RD, StartLoc, NameInfo, T, TInfo,
SC_None, isInline, isConstexpr, EndLocation),
IsExplicitSpecified(isExplicitSpecified) { }
@@ -2351,7 +2420,7 @@ public:
/// \brief Returns the type that this conversion function is converting to.
QualType getConversionType() const {
- return getType()->getAs<FunctionType>()->getResultType();
+ return getType()->getAs<FunctionType>()->getReturnType();
}
/// \brief Determine whether this conversion function is a conversion from
@@ -2440,7 +2509,7 @@ public:
return decls_empty() ? getLocation() : decls_begin()->getLocEnd();
}
- SourceRange getSourceRange() const LLVM_READONLY {
+ SourceRange getSourceRange() const override LLVM_READONLY {
return SourceRange(ExternLoc, getLocEnd());
}
@@ -2465,7 +2534,7 @@ public:
/// artificial names for all using-directives in order to store
/// them in DeclContext effectively.
class UsingDirectiveDecl : public NamedDecl {
- virtual void anchor();
+ void anchor() override;
/// \brief The location of the \c using keyword.
SourceLocation UsingLoc;
@@ -2546,8 +2615,8 @@ public:
NamedDecl *Nominated,
DeclContext *CommonAncestor);
static UsingDirectiveDecl *CreateDeserialized(ASTContext &C, unsigned ID);
-
- SourceRange getSourceRange() const LLVM_READONLY {
+
+ SourceRange getSourceRange() const override LLVM_READONLY {
return SourceRange(UsingLoc, getLocation());
}
@@ -2568,7 +2637,7 @@ public:
/// namespace Foo = Bar;
/// \endcode
class NamespaceAliasDecl : public NamedDecl {
- virtual void anchor();
+ void anchor() override;
/// \brief The location of the \c namespace keyword.
SourceLocation NamespaceLoc;
@@ -2641,8 +2710,8 @@ public:
NamedDecl *Namespace);
static NamespaceAliasDecl *CreateDeserialized(ASTContext &C, unsigned ID);
-
- virtual SourceRange getSourceRange() const LLVM_READONLY {
+
+ SourceRange getSourceRange() const override LLVM_READONLY {
return SourceRange(NamespaceLoc, IdentLoc);
}
@@ -2664,7 +2733,7 @@ public:
/// }
/// \endcode
class UsingShadowDecl : public NamedDecl, public Redeclarable<UsingShadowDecl> {
- virtual void anchor();
+ void anchor() override;
/// The referenced declaration.
NamedDecl *Underlying;
@@ -2674,10 +2743,10 @@ class UsingShadowDecl : public NamedDecl, public Redeclarable<UsingShadowDecl> {
NamedDecl *UsingOrNextShadow;
friend class UsingDecl;
- UsingShadowDecl(DeclContext *DC, SourceLocation Loc, UsingDecl *Using,
- NamedDecl *Target)
+ UsingShadowDecl(ASTContext &C, DeclContext *DC, SourceLocation Loc,
+ UsingDecl *Using, NamedDecl *Target)
: NamedDecl(UsingShadow, DC, Loc, DeclarationName()),
- Underlying(Target),
+ redeclarable_base(C), Underlying(Target),
UsingOrNextShadow(reinterpret_cast<NamedDecl *>(Using)) {
if (Target) {
setDeclName(Target->getDeclName());
@@ -2687,13 +2756,13 @@ class UsingShadowDecl : public NamedDecl, public Redeclarable<UsingShadowDecl> {
}
typedef Redeclarable<UsingShadowDecl> redeclarable_base;
- virtual UsingShadowDecl *getNextRedeclaration() {
- return RedeclLink.getNext();
+ UsingShadowDecl *getNextRedeclarationImpl() override {
+ return getNextRedeclaration();
}
- virtual UsingShadowDecl *getPreviousDeclImpl() {
+ UsingShadowDecl *getPreviousDeclImpl() override {
return getPreviousDecl();
}
- virtual UsingShadowDecl *getMostRecentDeclImpl() {
+ UsingShadowDecl *getMostRecentDeclImpl() override {
return getMostRecentDecl();
}
@@ -2701,21 +2770,23 @@ public:
static UsingShadowDecl *Create(ASTContext &C, DeclContext *DC,
SourceLocation Loc, UsingDecl *Using,
NamedDecl *Target) {
- return new (C) UsingShadowDecl(DC, Loc, Using, 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;
- virtual UsingShadowDecl *getCanonicalDecl() {
+ UsingShadowDecl *getCanonicalDecl() override {
return getFirstDecl();
}
- virtual const UsingShadowDecl *getCanonicalDecl() const {
+ const UsingShadowDecl *getCanonicalDecl() const {
return getFirstDecl();
}
@@ -2754,7 +2825,7 @@ public:
/// using someNameSpace::someIdentifier;
/// \endcode
class UsingDecl : public NamedDecl {
- virtual void anchor();
+ void anchor() override;
/// \brief The source location of the 'using' keyword itself.
SourceLocation UsingLocation;
@@ -2778,7 +2849,7 @@ class UsingDecl : public NamedDecl {
const DeclarationNameInfo &NameInfo, bool HasTypenameKeyword)
: NamedDecl(Using, DC, NameInfo.getLoc(), NameInfo.getName()),
UsingLocation(UL), QualifierLoc(QualifierLoc),
- DNLoc(NameInfo.getInfo()), FirstUsingShadow(0, HasTypenameKeyword) {
+ DNLoc(NameInfo.getInfo()), FirstUsingShadow(nullptr, HasTypenameKeyword) {
}
public:
@@ -2823,7 +2894,7 @@ public:
typedef std::forward_iterator_tag iterator_category;
typedef std::ptrdiff_t difference_type;
- shadow_iterator() : Current(0) { }
+ shadow_iterator() : Current(nullptr) { }
explicit shadow_iterator(UsingShadowDecl *C) : Current(C) { }
reference operator*() const { return Current; }
@@ -2848,6 +2919,11 @@ public:
}
};
+ 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());
}
@@ -2870,7 +2946,7 @@ public:
static UsingDecl *CreateDeserialized(ASTContext &C, unsigned ID);
- SourceRange getSourceRange() const LLVM_READONLY;
+ SourceRange getSourceRange() const override LLVM_READONLY;
static bool classof(const Decl *D) { return classofKind(D->getKind()); }
static bool classofKind(Kind K) { return K == Using; }
@@ -2891,7 +2967,7 @@ public:
/// };
/// \endcode
class UnresolvedUsingValueDecl : public ValueDecl {
- virtual void anchor();
+ void anchor() override;
/// \brief The source location of the 'using' keyword
SourceLocation UsingLocation;
@@ -2944,7 +3020,7 @@ public:
static UnresolvedUsingValueDecl *
CreateDeserialized(ASTContext &C, unsigned ID);
- SourceRange getSourceRange() const LLVM_READONLY;
+ SourceRange getSourceRange() const override LLVM_READONLY;
static bool classof(const Decl *D) { return classofKind(D->getKind()); }
static bool classofKind(Kind K) { return K == UnresolvedUsingValue; }
@@ -2965,7 +3041,7 @@ public:
/// The type associated with an unresolved using typename decl is
/// currently always a typename type.
class UnresolvedUsingTypenameDecl : public TypeDecl {
- virtual void anchor();
+ void anchor() override;
/// \brief The source location of the 'typename' keyword
SourceLocation TypenameLocation;
@@ -3043,7 +3119,7 @@ public:
SourceLocation getRParenLoc() const { return RParenLoc; }
- SourceRange getSourceRange() const LLVM_READONLY {
+ SourceRange getSourceRange() const override LLVM_READONLY {
return SourceRange(getLocation(), getRParenLoc());
}
@@ -3083,21 +3159,24 @@ public:
class MSPropertyDecl : public DeclaratorDecl {
IdentifierInfo *GetterId, *SetterId;
-public:
- 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) {}
+ 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 != NULL; }
+ bool hasGetter() const { return GetterId != nullptr; }
IdentifierInfo* getGetterId() const { return GetterId; }
- bool hasSetter() const { return SetterId != NULL; }
+ bool hasSetter() const { return SetterId != nullptr; }
IdentifierInfo* getSetterId() const { return SetterId; }
friend class ASTDeclReader;
diff --git a/include/clang/AST/DeclContextInternals.h b/include/clang/AST/DeclContextInternals.h
index 9c626c80aaee..9068c00a799c 100644
--- a/include/clang/AST/DeclContextInternals.h
+++ b/include/clang/AST/DeclContextInternals.h
@@ -46,10 +46,8 @@ struct StoredDeclsList {
public:
StoredDeclsList() {}
- StoredDeclsList(const StoredDeclsList &RHS) : Data(RHS.Data) {
- if (DeclsTy *RHSVec = RHS.getAsVector())
- Data = DeclsAndHasExternalTy(new DeclsTy(*RHSVec),
- RHS.hasExternalDecls());
+ StoredDeclsList(StoredDeclsList &&RHS) : Data(RHS.Data) {
+ RHS.Data = (NamedDecl *)nullptr;
}
~StoredDeclsList() {
@@ -58,12 +56,11 @@ public:
delete Vector;
}
- StoredDeclsList &operator=(const StoredDeclsList &RHS) {
+ StoredDeclsList &operator=(StoredDeclsList &&RHS) {
if (DeclsTy *Vector = getAsVector())
delete Vector;
Data = RHS.Data;
- if (DeclsTy *RHSVec = RHS.getAsVector())
- Data = DeclsAndHasExternalTy(new DeclsTy(*RHSVec), hasExternalDecls());
+ RHS.Data = (NamedDecl *)nullptr;
return *this;
}
@@ -110,7 +107,7 @@ public:
if (NamedDecl *Singleton = getAsDecl()) {
assert(Singleton == D && "list is different singleton");
(void)Singleton;
- Data = (NamedDecl *)0;
+ Data = (NamedDecl *)nullptr;
return;
}
@@ -145,8 +142,8 @@ public:
/// represents.
DeclContext::lookup_result getLookupResult() {
if (isNull())
- return DeclContext::lookup_result(DeclContext::lookup_iterator(0),
- DeclContext::lookup_iterator(0));
+ return DeclContext::lookup_result(DeclContext::lookup_iterator(nullptr),
+ DeclContext::lookup_iterator(nullptr));
// If we have a single NamedDecl, return it.
if (getAsDecl()) {
@@ -255,7 +252,7 @@ private:
class DependentStoredDeclsMap : public StoredDeclsMap {
public:
- DependentStoredDeclsMap() : FirstDiagnostic(0) {}
+ DependentStoredDeclsMap() : FirstDiagnostic(nullptr) {}
private:
friend class DependentDiagnostic;
diff --git a/include/clang/AST/DeclFriend.h b/include/clang/AST/DeclFriend.h
index be6f2eb3e3ad..12b93b408a70 100644
--- a/include/clang/AST/DeclFriend.h
+++ b/include/clang/AST/DeclFriend.h
@@ -17,6 +17,7 @@
#include "clang/AST/DeclCXX.h"
#include "clang/AST/DeclTemplate.h"
+#include "clang/AST/TypeLoc.h"
#include "llvm/Support/Compiler.h"
namespace clang {
@@ -91,7 +92,7 @@ private:
FriendDecl *getNextFriend() {
if (!NextFriend.isOffset())
- return cast_or_null<FriendDecl>(NextFriend.get(0));
+ return cast_or_null<FriendDecl>(NextFriend.get(nullptr));
return getNextFriendSlowCase();
}
FriendDecl *getNextFriendSlowCase();
@@ -132,10 +133,14 @@ public:
}
/// Retrieves the source range for the friend declaration.
- SourceRange getSourceRange() const LLVM_READONLY {
+ 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();
@@ -224,7 +229,11 @@ inline CXXRecordDecl::friend_iterator CXXRecordDecl::friend_begin() const {
}
inline CXXRecordDecl::friend_iterator CXXRecordDecl::friend_end() const {
- return friend_iterator(0);
+ return friend_iterator(nullptr);
+}
+
+inline CXXRecordDecl::friend_range CXXRecordDecl::friends() const {
+ return friend_range(friend_begin(), friend_end());
}
inline void CXXRecordDecl::pushFriendDecl(FriendDecl *FD) {
diff --git a/include/clang/AST/DeclGroup.h b/include/clang/AST/DeclGroup.h
index cda6ae520af4..bd3dbd8fa787 100644
--- a/include/clang/AST/DeclGroup.h
+++ b/include/clang/AST/DeclGroup.h
@@ -63,7 +63,7 @@ class DeclGroupRef {
}
public:
- DeclGroupRef() : D(0) {}
+ DeclGroupRef() : D(nullptr) {}
explicit DeclGroupRef(Decl* d) : D(d) {}
explicit DeclGroupRef(DeclGroup* dg)
@@ -80,7 +80,7 @@ public:
typedef Decl** iterator;
typedef Decl* const * const_iterator;
- bool isNull() const { return D == 0; }
+ bool isNull() const { return D == nullptr; }
bool isSingleDecl() const { return getKind() == SingleDeclKind; }
bool isDeclGroup() const { return getKind() == DeclGroupKind; }
@@ -102,26 +102,26 @@ public:
iterator begin() {
if (isSingleDecl())
- return D ? &D : 0;
+ return D ? &D : nullptr;
return &getDeclGroup()[0];
}
iterator end() {
if (isSingleDecl())
- return D ? &D+1 : 0;
+ return D ? &D+1 : nullptr;
DeclGroup &G = getDeclGroup();
return &G[0] + G.size();
}
const_iterator begin() const {
if (isSingleDecl())
- return D ? &D : 0;
+ return D ? &D : nullptr;
return &getDeclGroup()[0];
}
const_iterator end() const {
if (isSingleDecl())
- return D ? &D+1 : 0;
+ return D ? &D+1 : nullptr;
const DeclGroup &G = getDeclGroup();
return &G[0] + G.size();
}
diff --git a/include/clang/AST/DeclLookups.h b/include/clang/AST/DeclLookups.h
index c16975a3307f..d2016af89f13 100644
--- a/include/clang/AST/DeclLookups.h
+++ b/include/clang/AST/DeclLookups.h
@@ -68,38 +68,40 @@ public:
}
};
-inline DeclContext::all_lookups_iterator DeclContext::lookups_begin() const {
+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 all_lookups_iterator(Map->begin(), Map->end());
- return all_lookups_iterator();
+ return lookups_range(all_lookups_iterator(Map->begin(), Map->end()),
+ all_lookups_iterator(Map->end(), Map->end()));
+ return lookups_range();
+}
+
+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 (Primary->hasExternalVisibleStorage())
- getParentASTContext().getExternalSource()->completeVisibleDeclsMap(Primary);
- if (StoredDeclsMap *Map = Primary->buildLookup())
- return all_lookups_iterator(Map->end(), Map->end());
- return all_lookups_iterator();
+ if (StoredDeclsMap *Map = Primary->getLookupPtr())
+ return lookups_range(all_lookups_iterator(Map->begin(), Map->end()),
+ all_lookups_iterator(Map->end(), Map->end()));
+ return lookups_range();
}
inline
DeclContext::all_lookups_iterator DeclContext::noload_lookups_begin() const {
- DeclContext *Primary = const_cast<DeclContext*>(this)->getPrimaryContext();
- if (StoredDeclsMap *Map = Primary->getLookupPtr())
- return all_lookups_iterator(Map->begin(), Map->end());
- return all_lookups_iterator();
+ return noload_lookups().begin();
}
inline
DeclContext::all_lookups_iterator DeclContext::noload_lookups_end() const {
- DeclContext *Primary = const_cast<DeclContext*>(this)->getPrimaryContext();
- if (StoredDeclsMap *Map = Primary->getLookupPtr())
- return all_lookups_iterator(Map->end(), Map->end());
- return all_lookups_iterator();
+ return noload_lookups().end();
}
} // end namespace clang
diff --git a/include/clang/AST/DeclObjC.h b/include/clang/AST/DeclObjC.h
index 2e760d658e43..db3b0849382a 100644
--- a/include/clang/AST/DeclObjC.h
+++ b/include/clang/AST/DeclObjC.h
@@ -41,7 +41,7 @@ protected:
unsigned NumElts;
public:
- ObjCListBase() : List(0), NumElts(0) {}
+ ObjCListBase() : List(nullptr), NumElts(0) {}
unsigned size() const { return NumElts; }
bool empty() const { return NumElts == 0; }
@@ -79,7 +79,7 @@ class ObjCProtocolList : public ObjCList<ObjCProtocolDecl> {
using ObjCList<ObjCProtocolDecl>::set;
public:
- ObjCProtocolList() : ObjCList<ObjCProtocolDecl>(), Locations(0) { }
+ ObjCProtocolList() : ObjCList<ObjCProtocolDecl>(), Locations(nullptr) { }
typedef const SourceLocation *loc_iterator;
loc_iterator loc_begin() const { return Locations; }
@@ -162,11 +162,11 @@ private:
/// \brief Indicates if the method was a definition but its body was skipped.
unsigned HasSkippedBody : 1;
- // Result type of this method.
+ // Return type of this method.
QualType MethodDeclType;
- // Type source information for the result type.
- TypeSourceInfo *ResultTInfo;
+ // 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.
@@ -224,54 +224,44 @@ private:
ArrayRef<SourceLocation> SelLocs);
ObjCMethodDecl(SourceLocation beginLoc, SourceLocation endLoc,
- Selector SelInfo, QualType T,
- TypeSourceInfo *ResultTInfo,
- DeclContext *contextDecl,
- bool isInstance = true,
- bool isVariadic = false,
- bool isPropertyAccessor = false,
- bool isImplicitlyDeclared = false,
- bool isDefined = false,
+ 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), ResultTInfo(ResultTInfo),
- ParamsAndSelLocs(0), NumParams(0),
- DeclEndLoc(endLoc), Body(), SelfDecl(0), CmdDecl(0) {
+ : 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.
- virtual ObjCMethodDecl *getNextRedeclaration();
+ ObjCMethodDecl *getNextRedeclarationImpl() override;
public:
- static ObjCMethodDecl *Create(ASTContext &C,
- SourceLocation beginLoc,
- SourceLocation endLoc,
- Selector SelInfo,
- QualType T,
- TypeSourceInfo *ResultTInfo,
- DeclContext *contextDecl,
- bool isInstance = true,
- bool isVariadic = false,
- bool isPropertyAccessor = false,
- bool isImplicitlyDeclared = false,
- bool isDefined = false,
- ImplementationControl impControl = None,
- bool HasRelatedResultType = false);
+ 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);
-
- virtual ObjCMethodDecl *getCanonicalDecl();
+
+ ObjCMethodDecl *getCanonicalDecl() override;
const ObjCMethodDecl *getCanonicalDecl() const {
return const_cast<ObjCMethodDecl*>(this)->getCanonicalDecl();
}
@@ -300,7 +290,7 @@ public:
// Location information, modeled after the Stmt API.
SourceLocation getLocStart() const LLVM_READONLY { return getLocation(); }
SourceLocation getLocEnd() const LLVM_READONLY;
- virtual SourceRange getSourceRange() const LLVM_READONLY {
+ SourceRange getSourceRange() const override LLVM_READONLY {
return SourceRange(getLocation(), getLocEnd());
}
@@ -314,8 +304,7 @@ public:
if (hasStandardSelLocs())
return getStandardSelectorLoc(Index, getSelector(),
getSelLocsKind() == SelLoc_StandardWithSpace,
- llvm::makeArrayRef(const_cast<ParmVarDecl**>(getParams()),
- NumParams),
+ parameters(),
DeclEndLoc);
return getStoredSelLocs()[Index];
}
@@ -338,32 +327,52 @@ public:
Selector getSelector() const { return getDeclName().getObjCSelector(); }
- QualType getResultType() const { return MethodDeclType; }
- void setResultType(QualType T) { MethodDeclType = T; }
+ QualType getReturnType() const { return MethodDeclType; }
+ void setReturnType(QualType T) { MethodDeclType = T; }
/// \brief Determine the type of an expression that sends a message to this
/// function.
QualType getSendResultType() const {
- return getResultType().getNonLValueExprType(getASTContext());
+ return getReturnType().getNonLValueExprType(getASTContext());
}
- TypeSourceInfo *getResultTypeSourceInfo() const { return ResultTInfo; }
- void setResultTypeSourceInfo(TypeSourceInfo *TInfo) { ResultTInfo = TInfo; }
+ 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;
- param_const_iterator param_begin() const { return getParams(); }
- param_const_iterator param_end() const { return getParams() + NumParams; }
- param_iterator param_begin() { return getParams(); }
- param_iterator param_end() { return getParams() + NumParams; }
+ 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.
@@ -375,12 +384,12 @@ public:
// Iterator access to parameter types.
typedef std::const_mem_fun_t<QualType, ParmVarDecl> deref_fun;
typedef llvm::mapped_iterator<param_const_iterator, deref_fun>
- arg_type_iterator;
+ param_type_iterator;
- arg_type_iterator arg_type_begin() const {
+ param_type_iterator param_type_begin() const {
return llvm::map_iterator(param_begin(), deref_fun(&ParmVarDecl::getType));
}
- arg_type_iterator arg_type_end() const {
+ param_type_iterator param_type_end() const {
return llvm::map_iterator(param_end(), deref_fun(&ParmVarDecl::getType));
}
@@ -451,11 +460,24 @@ public:
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.
- virtual bool hasBody() const { return Body.isValid(); }
+ bool hasBody() const override { return Body.isValid(); }
/// \brief Retrieve the body of this method, if it has one.
- virtual Stmt *getBody() const;
+ Stmt *getBody() const override;
void setLazyBody(uint64_t Offset) { Body = Offset; }
@@ -484,7 +506,7 @@ public:
/// ObjCProtocolDecl, and ObjCImplDecl.
///
class ObjCContainerDecl : public NamedDecl, public DeclContext {
- virtual void anchor();
+ void anchor() override;
SourceLocation AtStart;
@@ -500,6 +522,10 @@ public:
// 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());
}
@@ -509,6 +535,12 @@ public:
// 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());
}
@@ -519,6 +551,11 @@ public:
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());
}
@@ -529,6 +566,11 @@ public:
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());
}
@@ -575,7 +617,7 @@ public:
AtEnd = atEnd;
}
- virtual SourceRange getSourceRange() const LLVM_READONLY {
+ SourceRange getSourceRange() const override LLVM_READONLY {
return SourceRange(AtStart, getAtEndRange().getEnd());
}
@@ -621,7 +663,7 @@ public:
///
class ObjCInterfaceDecl : public ObjCContainerDecl
, public Redeclarable<ObjCInterfaceDecl> {
- virtual void anchor();
+ void anchor() override;
/// TypeForDecl - This indicates the Type object that represents this
/// TypeDecl. It is a cache maintained by ASTContext::getObjCInterfaceType
@@ -661,6 +703,22 @@ class ObjCInterfaceDecl : public ObjCContainerDecl
/// 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 superclass, if any.
SourceLocation SuperClassLoc;
@@ -671,12 +729,14 @@ class ObjCInterfaceDecl : public ObjCContainerDecl
DefinitionData() : Definition(), SuperClass(), CategoryList(), IvarList(),
ExternallyCompleted(),
- IvarListMissingImplementation(true) { }
+ IvarListMissingImplementation(true),
+ HasDesignatedInitializers(),
+ InheritedDesignatedInitializers(IDI_Unknown) { }
};
- ObjCInterfaceDecl(DeclContext *DC, SourceLocation atLoc, IdentifierInfo *Id,
- SourceLocation CLoc, ObjCInterfaceDecl *PrevDecl,
- bool isInternal);
+ ObjCInterfaceDecl(const ASTContext &C, DeclContext *DC, SourceLocation AtLoc,
+ IdentifierInfo *Id, SourceLocation CLoc,
+ ObjCInterfaceDecl *PrevDecl, bool IsInternal);
void LoadExternalDefinition() const;
@@ -696,13 +756,13 @@ class ObjCInterfaceDecl : public ObjCContainerDecl
void allocateDefinitionData();
typedef Redeclarable<ObjCInterfaceDecl> redeclarable_base;
- virtual ObjCInterfaceDecl *getNextRedeclaration() {
- return RedeclLink.getNext();
+ ObjCInterfaceDecl *getNextRedeclarationImpl() override {
+ return getNextRedeclaration();
}
- virtual ObjCInterfaceDecl *getPreviousDeclImpl() {
+ ObjCInterfaceDecl *getPreviousDeclImpl() override {
return getPreviousDecl();
}
- virtual ObjCInterfaceDecl *getMostRecentDeclImpl() {
+ ObjCInterfaceDecl *getMostRecentDeclImpl() override {
return getMostRecentDecl();
}
@@ -714,9 +774,9 @@ public:
SourceLocation ClassLoc = SourceLocation(),
bool isInternal = false);
- static ObjCInterfaceDecl *CreateDeserialized(ASTContext &C, unsigned ID);
+ static ObjCInterfaceDecl *CreateDeserialized(const ASTContext &C, unsigned ID);
- virtual SourceRange getSourceRange() const LLVM_READONLY {
+ SourceRange getSourceRange() const override LLVM_READONLY {
if (isThisDeclarationADefinition())
return ObjCContainerDecl::getSourceRange();
@@ -728,6 +788,20 @@ public:
/// 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)
@@ -750,7 +824,11 @@ public:
}
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())
@@ -773,7 +851,11 @@ public:
}
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())
@@ -797,7 +879,12 @@ public:
}
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())
@@ -824,7 +911,9 @@ public:
}
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());
@@ -867,6 +956,31 @@ public:
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 {
@@ -894,14 +1008,14 @@ public:
/// has been forward-declared (with \@class) but not yet defined (with
/// \@interface).
ObjCInterfaceDecl *getDefinition() {
- return hasDefinition()? Data.getPointer()->Definition : 0;
+ 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 : 0;
+ return hasDefinition()? Data.getPointer()->Definition : nullptr;
}
/// \brief Starts the definition of this Objective-C class, taking it from
@@ -911,7 +1025,7 @@ public:
ObjCInterfaceDecl *getSuperClass() const {
// FIXME: Should make sure no callers ever do this.
if (!hasDefinition())
- return 0;
+ return nullptr;
if (data().ExternallyCompleted)
LoadExternalDefinition();
@@ -943,7 +1057,7 @@ public:
typedef std::ptrdiff_t difference_type;
typedef std::input_iterator_tag iterator_category;
- filtered_category_iterator() : Current(0) { }
+ filtered_category_iterator() : Current(nullptr) { }
explicit filtered_category_iterator(ObjCCategoryDecl *Current)
: Current(Current)
{
@@ -984,6 +1098,14 @@ public:
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 {
@@ -1010,6 +1132,13 @@ 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.
@@ -1039,6 +1168,14 @@ public:
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 {
@@ -1065,6 +1202,13 @@ 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.
@@ -1087,7 +1231,7 @@ public:
ObjCCategoryDecl* getCategoryListRaw() const {
// FIXME: Should make sure no callers ever do this.
if (!hasDefinition())
- return 0;
+ return nullptr;
if (data().ExternallyCompleted)
LoadExternalDefinition();
@@ -1104,14 +1248,14 @@ public:
ObjCPropertyDecl
*FindPropertyVisibleInPrimaryClass(IdentifierInfo *PropertyId) const;
- virtual void collectPropertiesToImplement(PropertyMap &PM,
- PropertyDeclOrder &PO) 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 != NULL) {
+ while (I != nullptr) {
if (declaresSameEntity(this, I))
return true;
@@ -1141,15 +1285,18 @@ public:
// 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,
- const ObjCCategoryDecl *C= 0) const;
- ObjCMethodDecl *lookupInstanceMethod(Selector Sel,
- bool shallowCategoryLookup = false) const {
- return lookupMethod(Sel, true/*isInstance*/, shallowCategoryLookup);
+ 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*/);
}
- ObjCMethodDecl *lookupClassMethod(Selector Sel,
- bool shallowCategoryLookup = false) const {
- return lookupMethod(Sel, false/*isInstance*/, shallowCategoryLookup);
+
+ /// Lookup a class method for a given selector.
+ ObjCMethodDecl *lookupClassMethod(Selector Sel) const {
+ return lookupMethod(Sel, false/*isInstance*/);
}
ObjCInterfaceDecl *lookupInheritedClass(const IdentifierInfo *ICName);
@@ -1167,7 +1314,9 @@ public:
ObjCMethodDecl *lookupPropertyAccessor(const Selector Sel,
const ObjCCategoryDecl *Cat) const {
return lookupMethod(Sel, true/*isInstance*/,
- false/*shallowCategoryLookup*/, Cat);
+ false/*shallowCategoryLookup*/,
+ true /* followsSuper */,
+ Cat);
}
SourceLocation getEndOfDefinitionLoc() const {
@@ -1196,15 +1345,17 @@ public:
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() { return getFirstDecl(); }
+ ObjCInterfaceDecl *getCanonicalDecl() override { return getFirstDecl(); }
const ObjCInterfaceDecl *getCanonicalDecl() const { return getFirstDecl(); }
// Low-level accessor
@@ -1217,6 +1368,10 @@ public:
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
@@ -1235,7 +1390,7 @@ public:
/// }
///
class ObjCIvarDecl : public FieldDecl {
- virtual void anchor();
+ void anchor() override;
public:
enum AccessControl {
@@ -1246,21 +1401,18 @@ private:
ObjCIvarDecl(ObjCContainerDecl *DC, SourceLocation StartLoc,
SourceLocation IdLoc, IdentifierInfo *Id,
QualType T, TypeSourceInfo *TInfo, AccessControl ac, Expr *BW,
- bool synthesized,
- bool backingIvarReferencedInAccessor)
+ bool synthesized)
: FieldDecl(ObjCIvar, DC, StartLoc, IdLoc, Id, T, TInfo, BW,
/*Mutable=*/false, /*HasInit=*/ICIS_NoInit),
- NextIvar(0), DeclAccess(ac), Synthesized(synthesized),
- BackingIvarReferencedInAccessor(backingIvarReferencedInAccessor) {}
+ 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 = NULL,
- bool synthesized=false,
- bool backingIvarReferencedInAccessor=false);
+ AccessControl ac, Expr *BW = nullptr,
+ bool synthesized=false);
static ObjCIvarDecl *CreateDeserialized(ASTContext &C, unsigned ID);
@@ -1282,13 +1434,6 @@ public:
return DeclAccess == None ? Protected : AccessControl(DeclAccess);
}
- void setBackingIvarReferencedInAccessor(bool val) {
- BackingIvarReferencedInAccessor = val;
- }
- bool getBackingIvarReferencedInAccessor() const {
- return BackingIvarReferencedInAccessor;
- }
-
void setSynthesize(bool synth) { Synthesized = synth; }
bool getSynthesize() const { return Synthesized; }
@@ -1303,18 +1448,17 @@ private:
// NOTE: VC++ treats enums as signed, avoid using the AccessControl enum
unsigned DeclAccess : 3;
unsigned Synthesized : 1;
- unsigned BackingIvarReferencedInAccessor : 1;
};
/// \brief Represents a field declaration created by an \@defs(...).
class ObjCAtDefsFieldDecl : public FieldDecl {
- virtual void anchor();
+ void anchor() override;
ObjCAtDefsFieldDecl(DeclContext *DC, SourceLocation StartLoc,
SourceLocation IdLoc, IdentifierInfo *Id,
QualType T, Expr *BW)
: FieldDecl(ObjCAtDefsField, DC, StartLoc, IdLoc, Id, T,
- /*TInfo=*/0, // FIXME: Do ObjCAtDefs have declarators ?
+ /*TInfo=*/nullptr, // FIXME: Do ObjCAtDefs have declarators ?
BW, /*Mutable=*/false, /*HasInit=*/ICIS_NoInit) {}
public:
@@ -1362,7 +1506,7 @@ public:
///
class ObjCProtocolDecl : public ObjCContainerDecl,
public Redeclarable<ObjCProtocolDecl> {
- virtual void anchor();
+ void anchor() override;
struct DefinitionData {
// \brief The declaration that defines this protocol.
@@ -1384,20 +1528,20 @@ class ObjCProtocolDecl : public ObjCContainerDecl,
return *Data.getPointer();
}
- ObjCProtocolDecl(DeclContext *DC, IdentifierInfo *Id,
+ ObjCProtocolDecl(ASTContext &C, DeclContext *DC, IdentifierInfo *Id,
SourceLocation nameLoc, SourceLocation atStartLoc,
ObjCProtocolDecl *PrevDecl);
void allocateDefinitionData();
typedef Redeclarable<ObjCProtocolDecl> redeclarable_base;
- virtual ObjCProtocolDecl *getNextRedeclaration() {
- return RedeclLink.getNext();
+ ObjCProtocolDecl *getNextRedeclarationImpl() override {
+ return getNextRedeclaration();
}
- virtual ObjCProtocolDecl *getPreviousDeclImpl() {
+ ObjCProtocolDecl *getPreviousDeclImpl() override {
return getPreviousDecl();
}
- virtual ObjCProtocolDecl *getMostRecentDeclImpl() {
+ ObjCProtocolDecl *getMostRecentDeclImpl() override {
return getMostRecentDecl();
}
@@ -1409,12 +1553,17 @@ public:
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();
@@ -1428,6 +1577,11 @@ public:
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();
@@ -1486,12 +1640,12 @@ public:
/// \brief Retrieve the definition of this protocol, if any.
ObjCProtocolDecl *getDefinition() {
- return hasDefinition()? Data.getPointer()->Definition : 0;
+ return hasDefinition()? Data.getPointer()->Definition : nullptr;
}
/// \brief Retrieve the definition of this protocol, if any.
const ObjCProtocolDecl *getDefinition() const {
- return hasDefinition()? Data.getPointer()->Definition : 0;
+ return hasDefinition()? Data.getPointer()->Definition : nullptr;
}
/// \brief Determine whether this particular declaration is also the
@@ -1503,29 +1657,35 @@ public:
/// \brief Starts the definition of this Objective-C protocol.
void startDefinition();
- virtual SourceRange getSourceRange() const LLVM_READONLY {
+ /// 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() { return getFirstDecl(); }
+ ObjCProtocolDecl *getCanonicalDecl() override { return getFirstDecl(); }
const ObjCProtocolDecl *getCanonicalDecl() const { return getFirstDecl(); }
- virtual void collectPropertiesToImplement(PropertyMap &PM,
- PropertyDeclOrder &PO) const;
-
-void collectInheritedProtocolProperties(const ObjCPropertyDecl *Property,
- ProtocolPropertyMap &PM) const;
+ 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; }
@@ -1553,7 +1713,7 @@ void collectInheritedProtocolProperties(const ObjCPropertyDecl *Property,
/// don't support this level of dynamism, which is both powerful and dangerous.
///
class ObjCCategoryDecl : public ObjCContainerDecl {
- virtual void anchor();
+ void anchor() override;
/// Interface belonging to this category
ObjCInterfaceDecl *ClassInterface;
@@ -1578,7 +1738,7 @@ class ObjCCategoryDecl : public ObjCContainerDecl {
SourceLocation IvarLBraceLoc=SourceLocation(),
SourceLocation IvarRBraceLoc=SourceLocation())
: ObjCContainerDecl(ObjCCategory, DC, Id, ClassNameLoc, AtLoc),
- ClassInterface(IDecl), NextClassCategory(0),
+ ClassInterface(IDecl), NextClassCategory(nullptr),
CategoryNameLoc(CategoryNameLoc),
IvarLBraceLoc(IvarLBraceLoc), IvarRBraceLoc(IvarRBraceLoc) {
}
@@ -1613,10 +1773,22 @@ public:
}
typedef ObjCProtocolList::iterator protocol_iterator;
- protocol_iterator protocol_begin() const {return ReferencedProtocols.begin();}
+ 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();
}
@@ -1632,9 +1804,12 @@ public:
return NextClassCategory;
}
- bool IsClassExtension() const { return getIdentifier() == 0; }
+ 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());
}
@@ -1664,7 +1839,7 @@ public:
};
class ObjCImplDecl : public ObjCContainerDecl {
- virtual void anchor();
+ void anchor() override;
/// Class interface for this class/category implementation
ObjCInterfaceDecl *ClassInterface;
@@ -1674,7 +1849,8 @@ protected:
ObjCInterfaceDecl *classInterface,
SourceLocation nameLoc, SourceLocation atStartLoc)
: ObjCContainerDecl(DK, DC,
- classInterface? classInterface->getIdentifier() : 0,
+ classInterface? classInterface->getIdentifier()
+ : nullptr,
nameLoc, atStartLoc),
ClassInterface(classInterface) {}
@@ -1701,6 +1877,12 @@ public:
// 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());
}
@@ -1728,7 +1910,7 @@ public:
///
/// ObjCCategoryImplDecl
class ObjCCategoryImplDecl : public ObjCImplDecl {
- virtual void anchor();
+ void anchor() override;
// Category name
IdentifierInfo *Id;
@@ -1753,8 +1935,8 @@ public:
/// getIdentifier - Get the identifier that names the category
/// interface associated with this implementation.
- /// FIXME: This is a bad API, we are overriding the NamedDecl::getIdentifier()
- /// to mean something different. For example:
+ /// 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()
@@ -1771,11 +1953,9 @@ public:
/// getName - Get the name of identifier for the class interface associated
/// with this implementation as a StringRef.
//
- // FIXME: This is a bad API, we are overriding the NamedDecl::getName, to mean
- // something different.
- StringRef getName() const {
- return Id ? Id->getNameStart() : "";
- }
+ // 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.
//
@@ -1802,13 +1982,16 @@ raw_ostream &operator<<(raw_ostream &OS, const ObjCCategoryImplDecl &CID);
/// \@end
/// @endcode
///
-/// Typically, instance variables are specified in the class interface,
-/// *not* in the implementation. Nevertheless (for legacy reasons), we
-/// allow instance variables to be specified in the implementation. When
-/// specified, they need to be *identical* to the interface.
+/// 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 {
- virtual void anchor();
+ void anchor() override;
/// Implementation Class's super class.
ObjCInterfaceDecl *SuperClass;
SourceLocation SuperLoc;
@@ -1839,7 +2022,7 @@ class ObjCImplementationDecl : public ObjCImplDecl {
: ObjCImplDecl(ObjCImplementation, DC, classInterface, nameLoc, atStartLoc),
SuperClass(superDecl), SuperLoc(superLoc), IvarLBraceLoc(IvarLBraceLoc),
IvarRBraceLoc(IvarRBraceLoc),
- IvarInitializers(0), NumIvarInitializers(0),
+ IvarInitializers(nullptr), NumIvarInitializers(0),
HasNonZeroConstructors(false), HasDestructors(false) {}
public:
static ObjCImplementationDecl *Create(ASTContext &C, DeclContext *DC,
@@ -1859,6 +2042,14 @@ public:
/// 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() { return IvarInitializers; }
/// begin() - Retrieve an iterator to the first initializer.
@@ -1904,8 +2095,8 @@ public:
/// getName - Get the name of identifier for the class interface associated
/// with this implementation as a StringRef.
//
- // FIXME: This is a bad API, we are overriding the NamedDecl::getName, to mean
- // something different.
+ // 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();
@@ -1917,6 +2108,10 @@ public:
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; }
@@ -1930,6 +2125,9 @@ public:
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());
}
@@ -1955,7 +2153,7 @@ 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 {
- virtual void anchor();
+ void anchor() override;
/// Class that this is an alias of.
ObjCInterfaceDecl *AliasedClass;
@@ -1986,7 +2184,7 @@ public:
/// \@property (assign, readwrite) int MyProperty;
/// \endcode
class ObjCPropertyDecl : public NamedDecl {
- virtual void anchor();
+ void anchor() override;
public:
enum PropertyAttributeKind {
OBJC_PR_noattr = 0x00,
@@ -2038,7 +2236,9 @@ private:
PropertyImplementation(None),
GetterName(Selector()),
SetterName(Selector()),
- GetterMethodDecl(0), SetterMethodDecl(0) , PropertyIvarDecl(0) {}
+ GetterMethodDecl(nullptr), SetterMethodDecl(nullptr),
+ PropertyIvarDecl(nullptr) {}
+
public:
static ObjCPropertyDecl *Create(ASTContext &C, DeclContext *DC,
SourceLocation L,
@@ -2145,7 +2345,7 @@ public:
return PropertyIvarDecl;
}
- virtual SourceRange getSourceRange() const LLVM_READONLY {
+ SourceRange getSourceRange() const override LLVM_READONLY {
return SourceRange(AtLoc, getLocation());
}
@@ -2202,7 +2402,7 @@ private:
SourceLocation ivarLoc)
: Decl(ObjCPropertyImpl, DC, L), AtLoc(atLoc),
IvarLoc(ivarLoc), PropertyDecl(property), PropertyIvarDecl(ivarDecl),
- GetterCXXConstructor(0), SetterCXXAssignment(0) {
+ GetterCXXConstructor(nullptr), SetterCXXAssignment(nullptr) {
assert (PK == Dynamic || PropertyIvarDecl);
}
@@ -2215,8 +2415,8 @@ public:
SourceLocation ivarLoc);
static ObjCPropertyImplDecl *CreateDeserialized(ASTContext &C, unsigned ID);
-
- virtual SourceRange getSourceRange() const LLVM_READONLY;
+
+ SourceRange getSourceRange() const override LLVM_READONLY;
SourceLocation getLocStart() const LLVM_READONLY { return AtLoc; }
void setAtLoc(SourceLocation Loc) { AtLoc = Loc; }
diff --git a/include/clang/AST/DeclOpenMP.h b/include/clang/AST/DeclOpenMP.h
index 42fe907aa174..1b329dcd0052 100644
--- a/include/clang/AST/DeclOpenMP.h
+++ b/include/clang/AST/DeclOpenMP.h
@@ -47,10 +47,10 @@ class OMPThreadPrivateDecl : public Decl {
NumVars);
}
- llvm::MutableArrayRef<Expr *> getVars() {
- return llvm::MutableArrayRef<Expr *>(
- reinterpret_cast<Expr **>(this + 1),
- NumVars);
+ MutableArrayRef<Expr *> getVars() {
+ return MutableArrayRef<Expr *>(
+ reinterpret_cast<Expr **>(this + 1),
+ NumVars);
}
void setVars(ArrayRef<Expr *> VL);
@@ -62,11 +62,20 @@ public:
static OMPThreadPrivateDecl *CreateDeserialized(ASTContext &C,
unsigned ID, unsigned N);
- typedef llvm::MutableArrayRef<Expr *>::iterator varlist_iterator;
+ 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(); }
diff --git a/include/clang/AST/DeclTemplate.h b/include/clang/AST/DeclTemplate.h
index 24bd28a75aaa..980a06e35b70 100644
--- a/include/clang/AST/DeclTemplate.h
+++ b/include/clang/AST/DeclTemplate.h
@@ -86,11 +86,11 @@ public:
unsigned size() const { return NumParams; }
- llvm::ArrayRef<NamedDecl*> asArray() {
- return llvm::ArrayRef<NamedDecl*>(begin(), size());
+ ArrayRef<NamedDecl*> asArray() {
+ return ArrayRef<NamedDecl*>(begin(), size());
}
- llvm::ArrayRef<const NamedDecl*> asArray() const {
- return llvm::ArrayRef<const NamedDecl*>(begin(), size());
+ ArrayRef<const NamedDecl*> asArray() const {
+ return ArrayRef<const NamedDecl*>(begin(), size());
}
NamedDecl* getParam(unsigned Idx) {
@@ -203,8 +203,8 @@ public:
const TemplateArgument &operator[](unsigned Idx) const { return get(Idx); }
/// \brief Produce this as an array ref.
- llvm::ArrayRef<TemplateArgument> asArray() const {
- return llvm::ArrayRef<TemplateArgument>(data(), size());
+ ArrayRef<TemplateArgument> asArray() const {
+ return ArrayRef<TemplateArgument>(data(), size());
}
/// \brief Retrieve the number of template arguments in this
@@ -227,18 +227,20 @@ public:
/// 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 {
- virtual void anchor();
+ void anchor() override;
protected:
// This is probably never used.
TemplateDecl(Kind DK, DeclContext *DC, SourceLocation L,
DeclarationName Name)
- : NamedDecl(DK, DC, L, Name), TemplatedDecl(0), TemplateParams(0) { }
+ : 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, alias?).
TemplateDecl(Kind DK, DeclContext *DC, SourceLocation L,
DeclarationName Name, TemplateParameterList *Params)
- : NamedDecl(DK, DC, L, Name), TemplatedDecl(0), TemplateParams(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,
@@ -261,7 +263,7 @@ public:
return K >= firstTemplate && K <= lastTemplate;
}
- SourceRange getSourceRange() const LLVM_READONLY {
+ SourceRange getSourceRange() const override LLVM_READONLY {
return SourceRange(TemplateParams->getTemplateLoc(),
TemplatedDecl->getSourceRange().getEnd());
}
@@ -274,8 +276,8 @@ public:
/// \brief Initialize the underlying templated declaration and
/// template parameters.
void init(NamedDecl *templatedDecl, TemplateParameterList* templateParams) {
- assert(TemplatedDecl == 0 && "TemplatedDecl already set!");
- assert(TemplateParams == 0 && "TemplateParams already set!");
+ assert(!TemplatedDecl && "TemplatedDecl already set!");
+ assert(!TemplateParams && "TemplateParams already set!");
TemplatedDecl = templatedDecl;
TemplateParams = templateParams;
}
@@ -378,16 +380,15 @@ public:
}
void Profile(llvm::FoldingSetNodeID &ID) {
- Profile(ID, TemplateArguments->data(),
- TemplateArguments->size(),
+ Profile(ID, TemplateArguments->asArray(),
Function->getASTContext());
}
static void
- Profile(llvm::FoldingSetNodeID &ID, const TemplateArgument *TemplateArgs,
- unsigned NumTemplateArgs, ASTContext &Context) {
- ID.AddInteger(NumTemplateArgs);
- for (unsigned Arg = 0; Arg != NumTemplateArgs; ++Arg)
+ 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);
}
};
@@ -530,13 +531,13 @@ class RedeclarableTemplateDecl : public TemplateDecl,
public Redeclarable<RedeclarableTemplateDecl>
{
typedef Redeclarable<RedeclarableTemplateDecl> redeclarable_base;
- virtual RedeclarableTemplateDecl *getNextRedeclaration() {
- return RedeclLink.getNext();
+ RedeclarableTemplateDecl *getNextRedeclarationImpl() override {
+ return getNextRedeclaration();
}
- virtual RedeclarableTemplateDecl *getPreviousDeclImpl() {
+ RedeclarableTemplateDecl *getPreviousDeclImpl() override {
return getPreviousDecl();
}
- virtual RedeclarableTemplateDecl *getMostRecentDeclImpl() {
+ RedeclarableTemplateDecl *getMostRecentDeclImpl() override {
return getMostRecentDecl();
}
@@ -595,11 +596,10 @@ protected:
template <class EntryType> typename SpecEntryTraits<EntryType>::DeclType*
findSpecializationImpl(llvm::FoldingSetVector<EntryType> &Specs,
- const TemplateArgument *Args, unsigned NumArgs,
- void *&InsertPos);
+ ArrayRef<TemplateArgument> Args, void *&InsertPos);
struct CommonBase {
- CommonBase() : InstantiatedFromMember(0, false) { }
+ CommonBase() : InstantiatedFromMember(nullptr, false) { }
/// \brief The template from which this was most
/// directly instantiated (or null).
@@ -622,16 +622,19 @@ protected:
virtual CommonBase *newCommon(ASTContext &C) const = 0;
// Construct a template decl with name, parameters, and templated element.
- RedeclarableTemplateDecl(Kind DK, DeclContext *DC, SourceLocation L,
- DeclarationName Name, TemplateParameterList *Params,
- NamedDecl *Decl)
- : TemplateDecl(DK, DC, L, Name, Params, Decl), Common() { }
+ 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() { return getFirstDecl(); }
+ RedeclarableTemplateDecl *getCanonicalDecl() override {
+ return getFirstDecl();
+ }
const RedeclarableTemplateDecl *getCanonicalDecl() const {
return getFirstDecl();
}
@@ -710,9 +713,11 @@ public:
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;
@@ -769,11 +774,13 @@ protected:
uint32_t *LazySpecializations;
};
- FunctionTemplateDecl(DeclContext *DC, SourceLocation L, DeclarationName Name,
- TemplateParameterList *Params, NamedDecl *Decl)
- : RedeclarableTemplateDecl(FunctionTemplate, DC, L, Name, Params, Decl) { }
+ 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;
+ CommonBase *newCommon(ASTContext &C) const override;
Common *getCommonPtr() const {
return static_cast<Common *>(RedeclarableTemplateDecl::getCommonPtr());
@@ -810,10 +817,10 @@ public:
/// \brief Return the specialization with the provided arguments if it exists,
/// otherwise return the insertion point.
- FunctionDecl *findSpecialization(const TemplateArgument *Args,
- unsigned NumArgs, void *&InsertPos);
+ FunctionDecl *findSpecialization(ArrayRef<TemplateArgument> Args,
+ void *&InsertPos);
- FunctionTemplateDecl *getCanonicalDecl() {
+ FunctionTemplateDecl *getCanonicalDecl() override {
return cast<FunctionTemplateDecl>(
RedeclarableTemplateDecl::getCanonicalDecl());
}
@@ -842,7 +849,11 @@ public:
}
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);
}
@@ -892,12 +903,9 @@ public:
/// This class is inheritedly privately by different kinds of template
/// parameters and is not part of the Decl hierarchy. Just a facility.
class TemplateParmPosition {
-protected:
- // FIXME: This should probably never be called, but it's here as
- TemplateParmPosition()
- : Depth(0), Position(0)
- { /* llvm_unreachable("Cannot create positionless template parameter"); */ }
+ TemplateParmPosition() LLVM_DELETED_FUNCTION;
+protected:
TemplateParmPosition(unsigned D, unsigned P)
: Depth(D), Position(P)
{ }
@@ -967,7 +975,7 @@ public:
/// \brief Determine whether this template parameter has a default
/// argument.
- bool hasDefaultArgument() const { return DefaultArgument != 0; }
+ bool hasDefaultArgument() const { return DefaultArgument != nullptr; }
/// \brief Retrieve the default argument, if any.
QualType getDefaultArgument() const { return DefaultArgument->getType(); }
@@ -992,7 +1000,7 @@ public:
/// \brief Removes the default argument of this template parameter.
void removeDefaultArgument() {
- DefaultArgument = 0;
+ DefaultArgument = nullptr;
InheritedDefault = false;
}
@@ -1009,7 +1017,7 @@ public:
/// \brief Returns whether this is a parameter pack.
bool isParameterPack() const;
- SourceRange getSourceRange() const LLVM_READONLY;
+ SourceRange getSourceRange() const override LLVM_READONLY;
// Implement isa/cast/dyncast/etc.
static bool classof(const Decl *D) { return classofKind(D->getKind()); }
@@ -1046,7 +1054,7 @@ class NonTypeTemplateParmDecl
IdentifierInfo *Id, QualType T,
bool ParameterPack, TypeSourceInfo *TInfo)
: DeclaratorDecl(NonTypeTemplateParm, DC, IdLoc, Id, T, TInfo, StartLoc),
- TemplateParmPosition(D, P), DefaultArgumentAndInherited(0, false),
+ TemplateParmPosition(D, P), DefaultArgumentAndInherited(nullptr, false),
ParameterPack(ParameterPack), ExpandedParameterPack(false),
NumExpandedTypes(0)
{ }
@@ -1086,12 +1094,12 @@ public:
using TemplateParmPosition::setPosition;
using TemplateParmPosition::getIndex;
- SourceRange getSourceRange() const LLVM_READONLY;
+ SourceRange getSourceRange() const override LLVM_READONLY;
/// \brief Determine whether this template parameter has a default
/// argument.
bool hasDefaultArgument() const {
- return DefaultArgumentAndInherited.getPointer() != 0;
+ return DefaultArgumentAndInherited.getPointer() != nullptr;
}
/// \brief Retrieve the default argument, if any.
@@ -1118,7 +1126,7 @@ public:
/// \brief Removes the default argument of this template parameter.
void removeDefaultArgument() {
- DefaultArgumentAndInherited.setPointer(0);
+ DefaultArgumentAndInherited.setPointer(nullptr);
DefaultArgumentAndInherited.setInt(false);
}
@@ -1206,7 +1214,7 @@ public:
class TemplateTemplateParmDecl : public TemplateDecl,
protected TemplateParmPosition
{
- virtual void anchor();
+ void anchor() override;
/// DefaultArgument - The default template argument, if any.
TemplateArgumentLoc DefaultArgument;
@@ -1347,7 +1355,7 @@ public:
DefaultArgumentWasInherited = false;
}
- SourceRange getSourceRange() const LLVM_READONLY {
+ SourceRange getSourceRange() const override LLVM_READONLY {
SourceLocation End = getLocation();
if (hasDefaultArgument() && !defaultArgumentWasInherited())
End = getDefaultArgument().getSourceRange().getEnd();
@@ -1405,7 +1413,7 @@ class ClassTemplateSpecializationDecl
SourceLocation TemplateKeywordLoc;
ExplicitSpecializationInfo()
- : TypeAsWritten(0), ExternLoc(), TemplateKeywordLoc() {}
+ : TypeAsWritten(nullptr), ExternLoc(), TemplateKeywordLoc() {}
};
/// \brief Further info for explicit template specialization/instantiation.
@@ -1431,7 +1439,7 @@ protected:
unsigned NumArgs,
ClassTemplateSpecializationDecl *PrevDecl);
- explicit ClassTemplateSpecializationDecl(Kind DK);
+ explicit ClassTemplateSpecializationDecl(ASTContext &C, Kind DK);
public:
static ClassTemplateSpecializationDecl *
@@ -1444,10 +1452,14 @@ public:
static ClassTemplateSpecializationDecl *
CreateDeserialized(ASTContext &C, unsigned ID);
- virtual void getNameForDiagnostic(raw_ostream &OS,
- const PrintingPolicy &Policy,
- bool Qualified) const;
+ 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();
@@ -1516,17 +1528,11 @@ public:
llvm::PointerUnion<ClassTemplateDecl *,
ClassTemplatePartialSpecializationDecl *>
getInstantiatedFrom() const {
- if (getSpecializationKind() != TSK_ImplicitInstantiation &&
- getSpecializationKind() != TSK_ExplicitInstantiationDefinition &&
- getSpecializationKind() != TSK_ExplicitInstantiationDeclaration)
+ if (!isTemplateInstantiation(getSpecializationKind()))
return llvm::PointerUnion<ClassTemplateDecl *,
ClassTemplatePartialSpecializationDecl *>();
- if (SpecializedPartialSpecialization *PartialSpec
- = SpecializedTemplate.dyn_cast<SpecializedPartialSpecialization*>())
- return PartialSpec->PartialSpecialization;
-
- return SpecializedTemplate.get<ClassTemplateDecl*>();
+ return getSpecializedTemplateOrPartial();
}
/// \brief Retrieve the class template or class template partial
@@ -1592,7 +1598,7 @@ public:
/// \brief Gets the type of this specialization as it was written by
/// the user, if it was so written.
TypeSourceInfo *getTypeAsWritten() const {
- return ExplicitInfo ? ExplicitInfo->TypeAsWritten : 0;
+ return ExplicitInfo ? ExplicitInfo->TypeAsWritten : nullptr;
}
/// \brief Gets the location of the extern keyword, if present.
@@ -1617,17 +1623,17 @@ public:
return ExplicitInfo ? ExplicitInfo->TemplateKeywordLoc : SourceLocation();
}
- SourceRange getSourceRange() const LLVM_READONLY;
+ SourceRange getSourceRange() const override LLVM_READONLY;
void Profile(llvm::FoldingSetNodeID &ID) const {
- Profile(ID, TemplateArgs->data(), TemplateArgs->size(), getASTContext());
+ Profile(ID, TemplateArgs->asArray(), getASTContext());
}
static void
- Profile(llvm::FoldingSetNodeID &ID, const TemplateArgument *TemplateArgs,
- unsigned NumTemplateArgs, ASTContext &Context) {
- ID.AddInteger(NumTemplateArgs);
- for (unsigned Arg = 0; Arg != NumTemplateArgs; ++Arg)
+ 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);
}
@@ -1643,7 +1649,7 @@ public:
class ClassTemplatePartialSpecializationDecl
: public ClassTemplateSpecializationDecl {
- virtual void anchor();
+ void anchor() override;
/// \brief The list of template parameters
TemplateParameterList* TemplateParams;
@@ -1671,9 +1677,10 @@ class ClassTemplatePartialSpecializationDecl
const ASTTemplateArgumentListInfo *ArgsAsWritten,
ClassTemplatePartialSpecializationDecl *PrevDecl);
- ClassTemplatePartialSpecializationDecl()
- : ClassTemplateSpecializationDecl(ClassTemplatePartialSpecialization),
- TemplateParams(0), ArgsAsWritten(0), InstantiatedFromMember(0, false) { }
+ ClassTemplatePartialSpecializationDecl(ASTContext &C)
+ : ClassTemplateSpecializationDecl(C, ClassTemplatePartialSpecialization),
+ TemplateParams(nullptr), ArgsAsWritten(nullptr),
+ InstantiatedFromMember(nullptr, false) {}
public:
static ClassTemplatePartialSpecializationDecl *
@@ -1832,15 +1839,12 @@ protected:
llvm::FoldingSetVector<ClassTemplatePartialSpecializationDecl> &
getPartialSpecializations();
- ClassTemplateDecl(DeclContext *DC, SourceLocation L, DeclarationName Name,
- TemplateParameterList *Params, NamedDecl *Decl)
- : RedeclarableTemplateDecl(ClassTemplate, DC, L, Name, Params, Decl) { }
+ ClassTemplateDecl(ASTContext &C, DeclContext *DC, SourceLocation L,
+ DeclarationName Name, TemplateParameterList *Params,
+ NamedDecl *Decl)
+ : RedeclarableTemplateDecl(ClassTemplate, C, DC, L, Name, Params, Decl) {}
- ClassTemplateDecl(EmptyShell Empty)
- : RedeclarableTemplateDecl(ClassTemplate, 0, SourceLocation(),
- DeclarationName(), 0, 0) { }
-
- CommonBase *newCommon(ASTContext &C) const;
+ CommonBase *newCommon(ASTContext &C) const override;
Common *getCommonPtr() const {
return static_cast<Common *>(RedeclarableTemplateDecl::getCommonPtr());
@@ -1872,14 +1876,13 @@ public:
/// \brief Return the specialization with the provided arguments if it exists,
/// otherwise return the insertion point.
ClassTemplateSpecializationDecl *
- findSpecialization(const TemplateArgument *Args, unsigned NumArgs,
- void *&InsertPos);
+ 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() {
+ ClassTemplateDecl *getCanonicalDecl() override {
return cast<ClassTemplateDecl>(
RedeclarableTemplateDecl::getCanonicalDecl());
}
@@ -1919,8 +1922,7 @@ public:
/// \brief Return the partial specialization with the provided arguments if it
/// exists, otherwise return the insertion point.
ClassTemplatePartialSpecializationDecl *
- findPartialSpecialization(const TemplateArgument *Args, unsigned NumArgs,
- void *&InsertPos);
+ 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.
@@ -1970,6 +1972,11 @@ public:
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);
@@ -1979,17 +1986,6 @@ public:
return makeSpecIterator(getSpecializations(), true);
}
- typedef SpecIterator<ClassTemplatePartialSpecializationDecl>
- partial_spec_iterator;
-
- partial_spec_iterator partial_spec_begin() {
- return makeSpecIterator(getPartialSpecializations(), false);
- }
-
- partial_spec_iterator partial_spec_end() {
- return makeSpecIterator(getPartialSpecializations(), true);
- }
-
// Implement isa/cast/dyncast support
static bool classof(const Decl *D) { return classofKind(D->getKind()); }
static bool classofKind(Kind K) { return K == ClassTemplate; }
@@ -2045,7 +2041,7 @@ private:
FriendTemplateDecl(EmptyShell Empty)
: Decl(Decl::FriendTemplate, Empty),
NumParams(0),
- Params(0)
+ Params(nullptr)
{}
public:
@@ -2105,11 +2101,13 @@ class TypeAliasTemplateDecl : public RedeclarableTemplateDecl {
protected:
typedef CommonBase Common;
- TypeAliasTemplateDecl(DeclContext *DC, SourceLocation L, DeclarationName Name,
- TemplateParameterList *Params, NamedDecl *Decl)
- : RedeclarableTemplateDecl(TypeAliasTemplate, DC, L, Name, Params, Decl) { }
+ 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;
+ CommonBase *newCommon(ASTContext &C) const override;
Common *getCommonPtr() {
return static_cast<Common *>(RedeclarableTemplateDecl::getCommonPtr());
@@ -2122,7 +2120,7 @@ public:
}
- TypeAliasTemplateDecl *getCanonicalDecl() {
+ TypeAliasTemplateDecl *getCanonicalDecl() override {
return cast<TypeAliasTemplateDecl>(
RedeclarableTemplateDecl::getCanonicalDecl());
}
@@ -2172,7 +2170,7 @@ public:
/// \brief Declaration of a function specialization at template class scope.
///
-/// This is a non standard extension needed to support MSVC.
+/// This is a non-standard extension needed to support MSVC.
///
/// For example:
/// \code
@@ -2214,9 +2212,8 @@ public:
CXXMethodDecl *FD,
bool HasExplicitTemplateArgs,
TemplateArgumentListInfo TemplateArgs) {
- return new (C) ClassScopeFunctionSpecializationDecl(DC , Loc, FD,
- HasExplicitTemplateArgs,
- TemplateArgs);
+ return new (C, DC) ClassScopeFunctionSpecializationDecl(
+ DC, Loc, FD, HasExplicitTemplateArgs, TemplateArgs);
}
static ClassScopeFunctionSpecializationDecl *
@@ -2279,7 +2276,7 @@ class VarTemplateSpecializationDecl : public VarDecl,
SourceLocation TemplateKeywordLoc;
ExplicitSpecializationInfo()
- : TypeAsWritten(0), ExternLoc(), TemplateKeywordLoc() {}
+ : TypeAsWritten(nullptr), ExternLoc(), TemplateKeywordLoc() {}
};
/// \brief Further info for explicit template specialization/instantiation.
@@ -2298,14 +2295,14 @@ class VarTemplateSpecializationDecl : public VarDecl,
unsigned SpecializationKind : 3;
protected:
- VarTemplateSpecializationDecl(ASTContext &Context, Kind DK, DeclContext *DC,
+ 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);
+ explicit VarTemplateSpecializationDecl(Kind DK, ASTContext &Context);
public:
static VarTemplateSpecializationDecl *
@@ -2316,9 +2313,8 @@ public:
static VarTemplateSpecializationDecl *CreateDeserialized(ASTContext &C,
unsigned ID);
- virtual void getNameForDiagnostic(raw_ostream &OS,
- const PrintingPolicy &Policy,
- bool Qualified) const;
+ void getNameForDiagnostic(raw_ostream &OS, const PrintingPolicy &Policy,
+ bool Qualified) const override;
VarTemplateSpecializationDecl *getMostRecentDecl() {
VarDecl *Recent = static_cast<VarDecl *>(this)->getMostRecentDecl();
@@ -2461,7 +2457,7 @@ public:
/// \brief Gets the type of this specialization as it was written by
/// the user, if it was so written.
TypeSourceInfo *getTypeAsWritten() const {
- return ExplicitInfo ? ExplicitInfo->TypeAsWritten : 0;
+ return ExplicitInfo ? ExplicitInfo->TypeAsWritten : nullptr;
}
/// \brief Gets the location of the extern keyword, if present.
@@ -2487,14 +2483,14 @@ public:
}
void Profile(llvm::FoldingSetNodeID &ID) const {
- Profile(ID, TemplateArgs->data(), TemplateArgs->size(), getASTContext());
+ Profile(ID, TemplateArgs->asArray(), getASTContext());
}
static void Profile(llvm::FoldingSetNodeID &ID,
- const TemplateArgument *TemplateArgs,
- unsigned NumTemplateArgs, ASTContext &Context) {
- ID.AddInteger(NumTemplateArgs);
- for (unsigned Arg = 0; Arg != NumTemplateArgs; ++Arg)
+ ArrayRef<TemplateArgument> TemplateArgs,
+ ASTContext &Context) {
+ ID.AddInteger(TemplateArgs.size());
+ for (unsigned Arg = 0; Arg != TemplateArgs.size(); ++Arg)
TemplateArgs[Arg].Profile(ID, Context);
}
@@ -2510,7 +2506,7 @@ public:
class VarTemplatePartialSpecializationDecl
: public VarTemplateSpecializationDecl {
- virtual void anchor();
+ void anchor() override;
/// \brief The list of template parameters
TemplateParameterList *TemplateParams;
@@ -2534,9 +2530,10 @@ class VarTemplatePartialSpecializationDecl
StorageClass S, const TemplateArgument *Args, unsigned NumArgs,
const ASTTemplateArgumentListInfo *ArgInfos);
- VarTemplatePartialSpecializationDecl()
- : VarTemplateSpecializationDecl(VarTemplatePartialSpecialization),
- TemplateParams(0), ArgsAsWritten(0), InstantiatedFromMember(0, false) {}
+ VarTemplatePartialSpecializationDecl(ASTContext &Context)
+ : VarTemplateSpecializationDecl(VarTemplatePartialSpecialization, Context),
+ TemplateParams(nullptr), ArgsAsWritten(nullptr),
+ InstantiatedFromMember(nullptr, false) {}
public:
static VarTemplatePartialSpecializationDecl *
@@ -2677,15 +2674,12 @@ protected:
llvm::FoldingSetVector<VarTemplatePartialSpecializationDecl> &
getPartialSpecializations();
- VarTemplateDecl(DeclContext *DC, SourceLocation L, DeclarationName Name,
- TemplateParameterList *Params, NamedDecl *Decl)
- : RedeclarableTemplateDecl(VarTemplate, DC, L, Name, Params, Decl) {}
+ VarTemplateDecl(ASTContext &C, DeclContext *DC, SourceLocation L,
+ DeclarationName Name, TemplateParameterList *Params,
+ NamedDecl *Decl)
+ : RedeclarableTemplateDecl(VarTemplate, C, DC, L, Name, Params, Decl) {}
- VarTemplateDecl(EmptyShell Empty)
- : RedeclarableTemplateDecl(VarTemplate, 0, SourceLocation(),
- DeclarationName(), 0, 0) {}
-
- CommonBase *newCommon(ASTContext &C) const;
+ CommonBase *newCommon(ASTContext &C) const override;
Common *getCommonPtr() const {
return static_cast<Common *>(RedeclarableTemplateDecl::getCommonPtr());
@@ -2708,8 +2702,8 @@ public:
/// \brief Create a variable template node.
static VarTemplateDecl *Create(ASTContext &C, DeclContext *DC,
SourceLocation L, DeclarationName Name,
- TemplateParameterList *Params, NamedDecl *Decl,
- VarTemplateDecl *PrevDecl);
+ TemplateParameterList *Params,
+ VarDecl *Decl);
/// \brief Create an empty variable template node.
static VarTemplateDecl *CreateDeserialized(ASTContext &C, unsigned ID);
@@ -2717,14 +2711,13 @@ public:
/// \brief Return the specialization with the provided arguments if it exists,
/// otherwise return the insertion point.
VarTemplateSpecializationDecl *
- findSpecialization(const TemplateArgument *Args, unsigned NumArgs,
- void *&InsertPos);
+ 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() {
+ VarTemplateDecl *getCanonicalDecl() override {
return cast<VarTemplateDecl>(RedeclarableTemplateDecl::getCanonicalDecl());
}
const VarTemplateDecl *getCanonicalDecl() const {
@@ -2754,8 +2747,7 @@ public:
/// \brief Return the partial specialization with the provided arguments if it
/// exists, otherwise return the insertion point.
VarTemplatePartialSpecializationDecl *
- findPartialSpecialization(const TemplateArgument *Args, unsigned NumArgs,
- void *&InsertPos);
+ 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.
@@ -2780,6 +2772,11 @@ public:
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);
@@ -2789,17 +2786,6 @@ public:
return makeSpecIterator(getSpecializations(), true);
}
- typedef SpecIterator<VarTemplatePartialSpecializationDecl>
- partial_spec_iterator;
-
- partial_spec_iterator partial_spec_begin() {
- return makeSpecIterator(getPartialSpecializations(), false);
- }
-
- partial_spec_iterator partial_spec_end() {
- return makeSpecIterator(getPartialSpecializations(), true);
- }
-
// Implement isa/cast/dyncast support
static bool classof(const Decl *D) { return classofKind(D->getKind()); }
static bool classofKind(Kind K) { return K == VarTemplate; }
diff --git a/include/clang/AST/DeclarationName.h b/include/clang/AST/DeclarationName.h
index 00766c27c136..3076b30cd377 100644
--- a/include/clang/AST/DeclarationName.h
+++ b/include/clang/AST/DeclarationName.h
@@ -29,6 +29,7 @@ namespace clang {
class DeclarationNameExtra;
class IdentifierInfo;
class MultiKeywordSelector;
+ enum OverloadedOperatorKind : int;
class QualType;
class Type;
class TypeSourceInfo;
@@ -116,20 +117,20 @@ private:
NameKind Kind = getNameKind();
if (Kind >= CXXConstructorName && Kind <= CXXConversionFunctionName)
return reinterpret_cast<CXXSpecialName *>(Ptr & ~PtrMask);
- return 0;
+ return nullptr;
}
/// getAsCXXOperatorIdName
CXXOperatorIdName *getAsCXXOperatorIdName() const {
if (getNameKind() == CXXOperatorName)
return reinterpret_cast<CXXOperatorIdName *>(Ptr & ~PtrMask);
- return 0;
+ return nullptr;
}
CXXLiteralOperatorIdName *getAsCXXLiteralOperatorIdName() const {
if (getNameKind() == CXXLiteralOperatorName)
return reinterpret_cast<CXXLiteralOperatorIdName *>(Ptr & ~PtrMask);
- return 0;
+ return nullptr;
}
// Construct a declaration name from the name of a C++ constructor,
@@ -221,7 +222,7 @@ public:
IdentifierInfo *getAsIdentifierInfo() const {
if (isIdentifier())
return reinterpret_cast<IdentifierInfo *>(Ptr);
- return 0;
+ return nullptr;
}
/// getAsOpaqueInteger - Get the representation of this declaration
diff --git a/include/clang/AST/DependentDiagnostic.h b/include/clang/AST/DependentDiagnostic.h
index 004b45da0f34..63047ec4db84 100644
--- a/include/clang/AST/DependentDiagnostic.h
+++ b/include/clang/AST/DependentDiagnostic.h
@@ -123,7 +123,7 @@ private:
/// An iterator over the dependent diagnostics in a dependent context.
class DeclContext::ddiag_iterator {
public:
- ddiag_iterator() : Ptr(0) {}
+ ddiag_iterator() : Ptr(nullptr) {}
explicit ddiag_iterator(DependentDiagnostic *Ptr) : Ptr(Ptr) {}
typedef DependentDiagnostic *value_type;
@@ -171,18 +171,16 @@ private:
DependentDiagnostic *Ptr;
};
-inline DeclContext::ddiag_iterator DeclContext::ddiag_begin() const {
+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 ddiag_iterator();
- return ddiag_iterator(Map->FirstDiagnostic);
-}
+ if (!Map)
+ return ddiag_range();
-inline DeclContext::ddiag_iterator DeclContext::ddiag_end() const {
- return ddiag_iterator();
+ return ddiag_range(ddiag_iterator(Map->FirstDiagnostic), ddiag_iterator());
}
}
diff --git a/include/clang/AST/Expr.h b/include/clang/AST/Expr.h
index f2648b9a4a04..b4bb0b6b6440 100644
--- a/include/clang/AST/Expr.h
+++ b/include/clang/AST/Expr.h
@@ -293,8 +293,8 @@ public:
/// \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 = 0) const;
+ isModifiableLvalueResult
+ isModifiableLvalue(ASTContext &Ctx, SourceLocation *Loc = nullptr) const;
/// \brief The return type of classify(). Represents the C++11 expression
/// taxonomy.
@@ -372,7 +372,7 @@ public:
/// lvalues and xvalues are collectively referred to as glvalues, while
/// prvalues and xvalues together form rvalues.
Classification Classify(ASTContext &Ctx) const {
- return ClassifyImpl(Ctx, 0);
+ return ClassifyImpl(Ctx, nullptr);
}
/// \brief ClassifyModifiable - Classify this expression according to the
@@ -483,10 +483,10 @@ public:
/// 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 = 0,
+ SourceLocation *Loc = nullptr,
bool isEvaluated = true) const;
bool isIntegerConstantExpr(const ASTContext &Ctx,
- SourceLocation *Loc = 0) const;
+ SourceLocation *Loc = nullptr) const;
/// isCXX98IntegralConstantExpr - Return true if this expression is an
/// integral constant expression in C++98. Can only be used in C++.
@@ -497,8 +497,8 @@ public:
///
/// Note: This does not perform the implicit conversions required by C++11
/// [expr.const]p5.
- bool isCXX11ConstantExpr(const ASTContext &Ctx, APValue *Result = 0,
- SourceLocation *Loc = 0) const;
+ 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
@@ -508,9 +508,22 @@ public:
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.
- bool isConstantInitializer(ASTContext &Ctx, bool ForRef) const;
+ /// 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 {
@@ -527,7 +540,7 @@ public:
/// expression *is* a constant expression, no notes will be produced.
SmallVectorImpl<PartialDiagnosticAt> *Diag;
- EvalStatus() : HasSideEffects(false), Diag(0) {}
+ EvalStatus() : HasSideEffects(false), Diag(nullptr) {}
// hasSideEffects - Return true if the evaluated expression has
// side effects.
@@ -584,7 +597,7 @@ public:
/// integer. This must be called on an expression that constant folds to an
/// integer.
llvm::APSInt EvaluateKnownConstInt(const ASTContext &Ctx,
- SmallVectorImpl<PartialDiagnosticAt> *Diag=0) const;
+ SmallVectorImpl<PartialDiagnosticAt> *Diag = nullptr) const;
void EvaluateForOverflow(const ASTContext &Ctx) const;
@@ -600,6 +613,14 @@ public:
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 Enumeration used to describe the kind of Null pointer constant
/// returned from \c isNullPointerConstant().
enum NullPointerConstantKind {
@@ -681,6 +702,9 @@ public:
/// 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;
@@ -742,6 +766,11 @@ public:
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);
}
@@ -764,11 +793,6 @@ public:
SmallVectorImpl<const Expr *> &CommaLHS,
SmallVectorImpl<SubobjectAdjustment> &Adjustments) const;
- /// Skip irrelevant expressions to find what should be materialize for
- /// binding with a reference.
- const Expr *
- findMaterializedTemporary(const MaterializeTemporaryExpr *&MTE) const;
-
static bool classof(const Stmt *T) {
return T->getStmtClass() >= firstExprConstant &&
T->getStmtClass() <= lastExprConstant;
@@ -793,7 +817,7 @@ class OpaqueValueExpr : public Expr {
public:
OpaqueValueExpr(SourceLocation Loc, QualType T, ExprValueKind VK,
ExprObjectKind OK = OK_Ordinary,
- Expr *SourceExpr = 0)
+ Expr *SourceExpr = nullptr)
: Expr(OpaqueValueExprClass, T, VK, OK,
T->isDependentType(),
T->isDependentType() ||
@@ -937,25 +961,19 @@ public:
computeDependence(D->getASTContext());
}
- static DeclRefExpr *Create(const ASTContext &Context,
- NestedNameSpecifierLoc QualifierLoc,
- SourceLocation TemplateKWLoc,
- ValueDecl *D,
- bool isEnclosingLocal,
- SourceLocation NameLoc,
- QualType T, ExprValueKind VK,
- NamedDecl *FoundD = 0,
- const TemplateArgumentListInfo *TemplateArgs = 0);
-
- static DeclRefExpr *Create(const ASTContext &Context,
- NestedNameSpecifierLoc QualifierLoc,
- SourceLocation TemplateKWLoc,
- ValueDecl *D,
- bool isEnclosingLocal,
- const DeclarationNameInfo &NameInfo,
- QualType T, ExprValueKind VK,
- NamedDecl *FoundD = 0,
- const TemplateArgumentListInfo *TemplateArgs = 0);
+ static DeclRefExpr *
+ Create(const ASTContext &Context, NestedNameSpecifierLoc QualifierLoc,
+ SourceLocation TemplateKWLoc, ValueDecl *D, bool isEnclosingLocal,
+ 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 isEnclosingLocal,
+ 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,
@@ -985,7 +1003,7 @@ public:
/// that precedes the name. Otherwise, returns NULL.
NestedNameSpecifier *getQualifier() const {
if (!hasQualifier())
- return 0;
+ return nullptr;
return getInternalQualifierLoc().getNestedNameSpecifier();
}
@@ -1021,7 +1039,7 @@ public:
/// \brief Return the optional template keyword and arguments info.
ASTTemplateKWAndArgsInfo *getTemplateKWAndArgsInfo() {
if (!hasTemplateKWAndArgsInfo())
- return 0;
+ return nullptr;
if (hasFoundDecl())
return reinterpret_cast<ASTTemplateKWAndArgsInfo *>(
@@ -1085,7 +1103,7 @@ public:
/// This points to the same data as getExplicitTemplateArgs(), but
/// returns null if there are no explicit template arguments.
const ASTTemplateArgumentListInfo *getOptionalExplicitTemplateArgs() const {
- if (!hasExplicitTemplateArgs()) return 0;
+ if (!hasExplicitTemplateArgs()) return nullptr;
return &getExplicitTemplateArgs();
}
@@ -1100,7 +1118,7 @@ public:
/// template-id.
const TemplateArgumentLoc *getTemplateArgs() const {
if (!hasExplicitTemplateArgs())
- return 0;
+ return nullptr;
return getExplicitTemplateArgs().getTemplateArgs();
}
@@ -1151,6 +1169,7 @@ public:
Function,
LFunction, // Same as Function, but as wide string.
FuncDName,
+ FuncSig,
PrettyFunction,
/// PrettyFunctionNoVirtual - The same as PrettyFunction, except that the
/// 'virtual' keyword is omitted for virtual member functions.
@@ -1862,7 +1881,7 @@ private:
explicit OffsetOfExpr(unsigned numComps, unsigned numExprs)
: Expr(OffsetOfExprClass, EmptyShell()),
- TSInfo(0), NumComps(numComps), NumExprs(numExprs) {}
+ TSInfo(nullptr), NumComps(numComps), NumExprs(numExprs) {}
public:
@@ -2213,6 +2232,13 @@ public:
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() {
@@ -2238,9 +2264,9 @@ public:
/// this function call.
unsigned getNumCommas() const { return NumArgs ? NumArgs - 1 : 0; }
- /// isBuiltinCall - If this is a call to a builtin, return the builtin ID. If
- /// not, return 0.
- unsigned isBuiltinCall() const;
+ /// 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.
@@ -2392,14 +2418,14 @@ public:
/// \brief Determines whether this member expression actually had
/// a C++ nested-name-specifier prior to the name of the member, e.g.,
/// x->Base::foo.
- bool hasQualifier() const { return getQualifier() != 0; }
+ bool hasQualifier() const { return getQualifier() != nullptr; }
/// \brief If the member name was qualified, retrieves the
/// nested-name-specifier that precedes the member name. Otherwise, returns
/// NULL.
NestedNameSpecifier *getQualifier() const {
if (!HasQualifierOrFoundDecl)
- return 0;
+ return nullptr;
return getMemberQualifier()->QualifierLoc.getNestedNameSpecifier();
}
@@ -2417,7 +2443,7 @@ public:
/// \brief Return the optional template keyword and arguments info.
ASTTemplateKWAndArgsInfo *getTemplateKWAndArgsInfo() {
if (!HasTemplateKWAndArgsInfo)
- return 0;
+ return nullptr;
if (!HasQualifierOrFoundDecl)
return reinterpret_cast<ASTTemplateKWAndArgsInfo *>(this + 1);
@@ -2485,7 +2511,7 @@ public:
/// This points to the same data as getExplicitTemplateArgs(), but
/// returns null if there are no explicit template arguments.
const ASTTemplateArgumentListInfo *getOptionalExplicitTemplateArgs() const {
- if (!hasExplicitTemplateArgs()) return 0;
+ if (!hasExplicitTemplateArgs()) return nullptr;
return &getExplicitTemplateArgs();
}
@@ -2493,7 +2519,7 @@ public:
/// template-id.
const TemplateArgumentLoc *getTemplateArgs() const {
if (!hasExplicitTemplateArgs())
- return 0;
+ return nullptr;
return getExplicitTemplateArgs().getTemplateArgs();
}
@@ -2633,7 +2659,7 @@ public:
private:
Stmt *Op;
- void CheckCastConsistency() const;
+ bool CastConsistency() const;
const CXXBaseSpecifier * const *path_buffer() const {
return const_cast<CastExpr*>(this)->path_buffer();
@@ -2664,9 +2690,7 @@ protected:
assert(kind != CK_Invalid && "creating cast with invalid cast kind");
CastExprBits.Kind = kind;
setBasePathSize(BasePathSize);
-#ifndef NDEBUG
- CheckCastConsistency();
-#endif
+ assert(CastConsistency());
}
/// \brief Construct an empty cast.
@@ -3422,7 +3446,7 @@ public:
/// \brief Build an empty vector-shuffle expression.
explicit ShuffleVectorExpr(EmptyShell Empty)
- : Expr(ShuffleVectorExprClass, Empty), SubExprs(0) { }
+ : Expr(ShuffleVectorExprClass, Empty), SubExprs(nullptr) { }
SourceLocation getBuiltinLoc() const { return BuiltinLoc; }
void setBuiltinLoc(SourceLocation L) { BuiltinLoc = L; }
@@ -3774,6 +3798,14 @@ public:
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.
@@ -3824,8 +3856,8 @@ public:
return const_cast<InitListExpr *>(this)->getInitializedFieldInUnion();
}
void setInitializedFieldInUnion(FieldDecl *FD) {
- assert((FD == 0
- || getInitializedFieldInUnion() == 0
+ assert((FD == nullptr
+ || getInitializedFieldInUnion() == nullptr
|| getInitializedFieldInUnion() == FD)
&& "Only one field of a union may be initialized at a time!");
ArrayFillerOrUnionFieldInit = FD;
@@ -3848,10 +3880,10 @@ public:
bool isSemanticForm() const { return AltForm.getInt(); }
InitListExpr *getSemanticForm() const {
- return isSemanticForm() ? 0 : AltForm.getPointer();
+ return isSemanticForm() ? nullptr : AltForm.getPointer();
}
InitListExpr *getSyntacticForm() const {
- return isSemanticForm() ? AltForm.getPointer() : 0;
+ return isSemanticForm() ? AltForm.getPointer() : nullptr;
}
void setSyntacticForm(InitListExpr *Init) {
@@ -3877,6 +3909,7 @@ public:
// Iterators
child_range children() {
+ // FIXME: This does not include the array filler expression.
if (InitExprs.empty()) return child_range();
return child_range(&InitExprs[0], &InitExprs[0] + InitExprs.size());
}
@@ -3953,7 +3986,7 @@ private:
explicit DesignatedInitExpr(unsigned NumSubExprs)
: Expr(DesignatedInitExprClass, EmptyShell()),
- NumDesignators(0), NumSubExprs(NumSubExprs), Designators(0) { }
+ NumDesignators(0), NumSubExprs(NumSubExprs), Designators(nullptr) { }
public:
/// A field designator, e.g., ".x".
@@ -4050,7 +4083,7 @@ public:
FieldDecl *getField() const {
assert(Kind == FieldDesignator && "Only valid on a field designator");
if (Field.NameOrField & 0x01)
- return 0;
+ return nullptr;
else
return reinterpret_cast<FieldDecl *>(Field.NameOrField);
}
@@ -4134,6 +4167,17 @@ public:
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() {
@@ -4186,18 +4230,14 @@ public:
/// and array-range designators.
unsigned getNumSubExprs() const { return NumSubExprs; }
- Expr *getSubExpr(unsigned Idx) {
+ Expr *getSubExpr(unsigned Idx) const {
assert(Idx < NumSubExprs && "Subscript out of range");
- char* Ptr = static_cast<char*>(static_cast<void *>(this));
- Ptr += sizeof(DesignatedInitExpr);
- return reinterpret_cast<Expr**>(reinterpret_cast<void**>(Ptr))[Idx];
+ return cast<Expr>(reinterpret_cast<Stmt *const *>(this + 1)[Idx]);
}
void setSubExpr(unsigned Idx, Expr *E) {
assert(Idx < NumSubExprs && "Subscript out of range");
- char* Ptr = static_cast<char*>(static_cast<void *>(this));
- Ptr += sizeof(DesignatedInitExpr);
- reinterpret_cast<Expr**>(reinterpret_cast<void**>(Ptr))[Idx] = E;
+ reinterpret_cast<Stmt **>(this + 1)[Idx] = E;
}
/// \brief Replaces the designator at index @p Idx with the series
@@ -4621,7 +4661,7 @@ class PseudoObjectExpr : public Expr {
public:
/// NoResult - A value for the result index indicating that there is
/// no semantic result.
- enum LLVM_ENUM_INT_TYPE(unsigned) { NoResult = ~0U };
+ enum : unsigned { NoResult = ~0U };
static PseudoObjectExpr *Create(const ASTContext &Context, Expr *syntactic,
ArrayRef<Expr*> semantic,
@@ -4646,7 +4686,7 @@ public:
/// Return the result-bearing expression, or null if there is none.
Expr *getResultExpr() {
if (PseudoObjectExprBits.ResultIndex == 0)
- return 0;
+ return nullptr;
return getSubExprsBuffer()[PseudoObjectExprBits.ResultIndex];
}
const Expr *getResultExpr() const {
@@ -4713,6 +4753,16 @@ public:
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];
diff --git a/include/clang/AST/ExprCXX.h b/include/clang/AST/ExprCXX.h
index 6356ee7aee63..3a43d6dac140 100644
--- a/include/clang/AST/ExprCXX.h
+++ b/include/clang/AST/ExprCXX.h
@@ -20,7 +20,7 @@
#include "clang/AST/TemplateBase.h"
#include "clang/AST/UnresolvedSet.h"
#include "clang/Basic/ExpressionTraits.h"
-#include "clang/Basic/Lambda.h"
+#include "clang/AST/LambdaCapture.h"
#include "clang/Basic/TypeTraits.h"
#include "llvm/Support/Compiler.h"
@@ -486,7 +486,7 @@ class CXXStdInitializerListExpr : public Expr {
Stmt *SubExpr;
CXXStdInitializerListExpr(EmptyShell Empty)
- : Expr(CXXStdInitializerListExprClass, Empty), SubExpr(0) {}
+ : Expr(CXXStdInitializerListExprClass, Empty), SubExpr(nullptr) {}
public:
CXXStdInitializerListExpr(QualType Ty, Expr *SubExpr)
@@ -553,9 +553,9 @@ public:
CXXTypeidExpr(EmptyShell Empty, bool isExpr)
: Expr(CXXTypeidExprClass, Empty) {
if (isExpr)
- Operand = (Expr*)0;
+ Operand = (Expr*)nullptr;
else
- Operand = (TypeSourceInfo*)0;
+ Operand = (TypeSourceInfo*)nullptr;
}
/// Determine whether this typeid has a type operand which is potentially
@@ -692,9 +692,9 @@ public:
CXXUuidofExpr(EmptyShell Empty, bool isExpr)
: Expr(CXXUuidofExprClass, Empty) {
if (isExpr)
- Operand = (Expr*)0;
+ Operand = (Expr*)nullptr;
else
- Operand = (TypeSourceInfo*)0;
+ Operand = (TypeSourceInfo*)nullptr;
}
bool isTypeOperand() const { return Operand.is<TypeSourceInfo *>(); }
@@ -737,8 +737,8 @@ public:
/// Grabs __declspec(uuid()) off a type, or returns 0 if we cannot resolve to
/// a single GUID.
- static UuidAttr *GetUuidAttrOfType(QualType QT,
- bool *HasMultipleGUIDsPtr = 0);
+ static const UuidAttr *GetUuidAttrOfType(QualType QT,
+ bool *HasMultipleGUIDsPtr = nullptr);
// Iterators
child_range children() {
@@ -832,7 +832,7 @@ public:
SourceLocation getLocStart() const LLVM_READONLY { return ThrowLoc; }
SourceLocation getLocEnd() const LLVM_READONLY {
- if (getSubExpr() == 0)
+ if (!getSubExpr())
return ThrowLoc;
return getSubExpr()->getLocEnd();
}
@@ -1031,7 +1031,7 @@ class CXXBindTemporaryExpr : public Expr {
public:
CXXBindTemporaryExpr(EmptyShell Empty)
- : Expr(CXXBindTemporaryExprClass, Empty), Temp(0), SubExpr(0) {}
+ : Expr(CXXBindTemporaryExprClass, Empty), Temp(nullptr), SubExpr(nullptr) {}
static CXXBindTemporaryExpr *Create(const ASTContext &C, CXXTemporary *Temp,
Expr* SubExpr);
@@ -1077,6 +1077,7 @@ private:
bool Elidable : 1;
bool HadMultipleCandidates : 1;
bool ListInitialization : 1;
+ bool StdInitListInitialization : 1;
bool ZeroInitialization : 1;
unsigned ConstructKind : 2;
Stmt **Args;
@@ -1088,24 +1089,25 @@ protected:
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(0), NumArgs(0), Elidable(false),
+ : Expr(SC, Empty), Constructor(nullptr), NumArgs(0), Elidable(false),
HadMultipleCandidates(false), ListInitialization(false),
- ZeroInitialization(false), ConstructKind(0), Args(0)
+ ZeroInitialization(false), ConstructKind(0), Args(nullptr)
{ }
public:
/// \brief Construct an empty C++ construction expression.
explicit CXXConstructExpr(EmptyShell Empty)
- : Expr(CXXConstructExprClass, Empty), Constructor(0),
+ : Expr(CXXConstructExprClass, Empty), Constructor(nullptr),
NumArgs(0), Elidable(false), HadMultipleCandidates(false),
ListInitialization(false), ZeroInitialization(false),
- ConstructKind(0), Args(0)
+ ConstructKind(0), Args(nullptr)
{ }
static CXXConstructExpr *Create(const ASTContext &C, QualType T,
@@ -1114,6 +1116,7 @@ public:
ArrayRef<Expr *> Args,
bool HadMultipleCandidates,
bool ListInitialization,
+ bool StdInitListInitialization,
bool ZeroInitialization,
ConstructionKind ConstructKind,
SourceRange ParenOrBraceRange);
@@ -1137,6 +1140,13 @@ public:
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; }
@@ -1161,7 +1171,10 @@ public:
const_arg_iterator arg_begin() const { return Args; }
const_arg_iterator arg_end() const { return Args + NumArgs; }
- Expr **getArgs() const { return reinterpret_cast<Expr **>(Args); }
+ 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.
@@ -1269,6 +1282,7 @@ public:
SourceRange ParenOrBraceRange,
bool HadMultipleCandidates,
bool ListInitialization,
+ bool StdInitListInitialization,
bool ZeroInitialization);
explicit CXXTemporaryObjectExpr(EmptyShell Empty)
: CXXConstructExpr(CXXTemporaryObjectExprClass, Empty), Type() { }
@@ -1307,18 +1321,6 @@ public:
/// includes an initializing expression (rather than capturing a variable),
/// and which can never occur implicitly.
class LambdaExpr : public Expr {
- 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
- };
-
/// \brief The source range that covers the lambda introducer ([...]).
SourceRange IntroducerRange;
@@ -1357,93 +1359,8 @@ class LambdaExpr : public Expr {
// expression, along with the index variables used to initialize by-copy
// array captures.
-public:
- /// \brief Describes the capture of a variable or of \c this, or of a
- /// C++1y init-capture.
- class Capture {
- 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.
- Capture(SourceLocation Loc, bool Implicit,
- LambdaCaptureKind Kind, VarDecl *Var = 0,
- 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() == 0; }
-
- /// \brief Determine whether this capture handles a variable.
- bool capturesVariable() const {
- return dyn_cast_or_null<VarDecl>(DeclAndBits.getPointer());
- }
-
- /// \brief Determine whether this is an init-capture.
- bool isInitCapture() const {
- return capturesVariable() && getCapturedVar()->isInitCapture();
- }
-
- /// \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;
- }
- };
+ typedef LambdaCapture Capture;
-private:
/// \brief Construct a lambda expression.
LambdaExpr(QualType T, SourceRange IntroducerRange,
LambdaCaptureDefault CaptureDefault,
@@ -1462,7 +1379,7 @@ private:
: Expr(LambdaExprClass, Empty),
NumCaptures(NumCaptures), CaptureDefault(LCD_None), ExplicitParams(false),
ExplicitResultType(false), HasArrayIndexVars(true) {
- getStoredStmts()[NumCaptures] = 0;
+ getStoredStmts()[NumCaptures] = nullptr;
}
Stmt **getStoredStmts() const {
@@ -1520,6 +1437,12 @@ public:
/// both implicit and explicit.
typedef const Capture *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;
@@ -1529,6 +1452,9 @@ public:
/// \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.
@@ -1538,6 +1464,9 @@ public:
/// 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;
@@ -1550,6 +1479,12 @@ public:
/// arguments.
typedef Expr **capture_init_iterator;
+ /// \brief Retrieve the initialization expressions for this lambda's captures.
+ llvm::iterator_range<capture_init_iterator> capture_inits() const {
+ return llvm::iterator_range<capture_init_iterator>(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() const {
@@ -1717,7 +1652,7 @@ public:
QualType ty, TypeSourceInfo *AllocatedTypeInfo,
SourceRange Range, SourceRange directInitRange);
explicit CXXNewExpr(EmptyShell Shell)
- : Expr(CXXNewExprClass, Shell), SubExprs(0) { }
+ : Expr(CXXNewExprClass, Shell), SubExprs(nullptr) { }
void AllocateArgsArray(const ASTContext &C, bool isArray,
unsigned numPlaceArgs, bool hasInitializer);
@@ -1751,10 +1686,10 @@ public:
bool isArray() const { return Array; }
Expr *getArraySize() {
- return Array ? cast<Expr>(SubExprs[0]) : 0;
+ return Array ? cast<Expr>(SubExprs[0]) : nullptr;
}
const Expr *getArraySize() const {
- return Array ? cast<Expr>(SubExprs[0]) : 0;
+ return Array ? cast<Expr>(SubExprs[0]) : nullptr;
}
unsigned getNumPlacementArgs() const { return NumPlacementArgs; }
@@ -1788,10 +1723,10 @@ public:
/// \brief The initializer of this new-expression.
Expr *getInitializer() {
- return hasInitializer() ? cast<Expr>(SubExprs[Array]) : 0;
+ return hasInitializer() ? cast<Expr>(SubExprs[Array]) : nullptr;
}
const Expr *getInitializer() const {
- return hasInitializer() ? cast<Expr>(SubExprs[Array]) : 0;
+ return hasInitializer() ? cast<Expr>(SubExprs[Array]) : nullptr;
}
/// \brief Returns the CXXConstructExpr from this new-expression, or null.
@@ -1885,7 +1820,8 @@ public:
ArrayForm(arrayForm), ArrayFormAsWritten(arrayFormAsWritten),
UsualArrayDeleteWantsSize(usualArrayDeleteWantsSize) { }
explicit CXXDeleteExpr(EmptyShell Shell)
- : Expr(CXXDeleteExprClass, Shell), OperatorDelete(0), Argument(0) { }
+ : Expr(CXXDeleteExprClass, Shell), OperatorDelete(nullptr),
+ Argument(nullptr) {}
bool isGlobalDelete() const { return GlobalDelete; }
bool isArrayForm() const { return ArrayForm; }
@@ -2017,7 +1953,7 @@ public:
explicit CXXPseudoDestructorExpr(EmptyShell Shell)
: Expr(CXXPseudoDestructorExprClass, Shell),
- Base(0), IsArrow(false), QualifierLoc(), ScopeType(0) { }
+ Base(nullptr), IsArrow(false), QualifierLoc(), ScopeType(nullptr) { }
Expr *getBase() const { return cast<Expr>(Base); }
@@ -2110,138 +2046,12 @@ public:
child_range children() { return child_range(&Base, &Base + 1); }
};
-/// \brief Represents a GCC or MS unary type trait, as used in the
-/// implementation of TR1/C++11 type trait templates.
-///
-/// Example:
-/// \code
-/// __is_pod(int) == true
-/// __is_enum(std::string) == false
-/// \endcode
-class UnaryTypeTraitExpr : public Expr {
- /// \brief The trait. A UnaryTypeTrait enum in MSVC compatible unsigned.
- unsigned UTT : 31;
- /// 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 type being queried.
- TypeSourceInfo *QueriedType;
-
-public:
- UnaryTypeTraitExpr(SourceLocation loc, UnaryTypeTrait utt,
- TypeSourceInfo *queried, bool value,
- SourceLocation rparen, QualType ty)
- : Expr(UnaryTypeTraitExprClass, ty, VK_RValue, OK_Ordinary,
- false, queried->getType()->isDependentType(),
- queried->getType()->isInstantiationDependentType(),
- queried->getType()->containsUnexpandedParameterPack()),
- UTT(utt), Value(value), Loc(loc), RParen(rparen), QueriedType(queried) { }
-
- explicit UnaryTypeTraitExpr(EmptyShell Empty)
- : Expr(UnaryTypeTraitExprClass, Empty), UTT(0), Value(false),
- QueriedType() { }
-
- SourceLocation getLocStart() const LLVM_READONLY { return Loc; }
- SourceLocation getLocEnd() const LLVM_READONLY { return RParen; }
-
- UnaryTypeTrait getTrait() const { return static_cast<UnaryTypeTrait>(UTT); }
-
- QualType getQueriedType() const { return QueriedType->getType(); }
-
- TypeSourceInfo *getQueriedTypeSourceInfo() const { return QueriedType; }
-
- bool getValue() const { return Value; }
-
- static bool classof(const Stmt *T) {
- return T->getStmtClass() == UnaryTypeTraitExprClass;
- }
-
- // Iterators
- child_range children() { return child_range(); }
-
- friend class ASTStmtReader;
-};
-
-/// \brief Represents a GCC or MS binary type trait, as used in the
-/// implementation of TR1/C++11 type trait templates.
-///
-/// Example:
-/// \code
-/// __is_base_of(Base, Derived) == true
-/// \endcode
-class BinaryTypeTraitExpr : public Expr {
- /// \brief The trait. A BinaryTypeTrait enum in MSVC compatible unsigned.
- unsigned BTT : 8;
-
- /// 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 lhs type being queried.
- TypeSourceInfo *LhsType;
-
- /// \brief The rhs type being queried.
- TypeSourceInfo *RhsType;
-
-public:
- BinaryTypeTraitExpr(SourceLocation loc, BinaryTypeTrait btt,
- TypeSourceInfo *lhsType, TypeSourceInfo *rhsType,
- bool value, SourceLocation rparen, QualType ty)
- : Expr(BinaryTypeTraitExprClass, ty, VK_RValue, OK_Ordinary, false,
- lhsType->getType()->isDependentType() ||
- rhsType->getType()->isDependentType(),
- (lhsType->getType()->isInstantiationDependentType() ||
- rhsType->getType()->isInstantiationDependentType()),
- (lhsType->getType()->containsUnexpandedParameterPack() ||
- rhsType->getType()->containsUnexpandedParameterPack())),
- BTT(btt), Value(value), Loc(loc), RParen(rparen),
- LhsType(lhsType), RhsType(rhsType) { }
-
-
- explicit BinaryTypeTraitExpr(EmptyShell Empty)
- : Expr(BinaryTypeTraitExprClass, Empty), BTT(0), Value(false),
- LhsType(), RhsType() { }
-
- SourceLocation getLocStart() const LLVM_READONLY { return Loc; }
- SourceLocation getLocEnd() const LLVM_READONLY { return RParen; }
-
- BinaryTypeTrait getTrait() const {
- return static_cast<BinaryTypeTrait>(BTT);
- }
-
- QualType getLhsType() const { return LhsType->getType(); }
- QualType getRhsType() const { return RhsType->getType(); }
-
- TypeSourceInfo *getLhsTypeSourceInfo() const { return LhsType; }
- TypeSourceInfo *getRhsTypeSourceInfo() const { return RhsType; }
-
- bool getValue() const { assert(!isTypeDependent()); return Value; }
-
- static bool classof(const Stmt *T) {
- return T->getStmtClass() == BinaryTypeTraitExprClass;
- }
-
- // Iterators
- child_range children() { return child_range(); }
-
- friend class ASTStmtReader;
-};
-
/// \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 : public Expr {
@@ -2334,7 +2144,7 @@ public:
friend class ASTStmtWriter;
};
-
+
/// \brief An Embarcadero array type trait, as used in the implementation of
/// __array_rank and __array_extent.
///
@@ -2504,7 +2314,7 @@ protected:
bool KnownContainsUnexpandedParameterPack);
OverloadExpr(StmtClass K, EmptyShell Empty)
- : Expr(K, Empty), QualifierLoc(), Results(0), NumResults(0),
+ : Expr(K, Empty), QualifierLoc(), Results(nullptr), NumResults(0),
HasTemplateKWAndArgsInfo(false) { }
void initializeResults(const ASTContext &C,
@@ -2554,6 +2364,9 @@ public:
decls_iterator decls_end() const {
return UnresolvedSetIterator(Results + NumResults);
}
+ llvm::iterator_range<decls_iterator> decls() const {
+ return llvm::iterator_range<decls_iterator>(decls_begin(), decls_end());
+ }
/// \brief Gets the number of declarations in the unresolved set.
unsigned getNumDecls() const { return NumResults; }
@@ -2634,7 +2447,7 @@ public:
/// This points to the same data as getExplicitTemplateArgs(), but
/// returns null if there are no explicit template arguments.
const ASTTemplateArgumentListInfo *getOptionalExplicitTemplateArgs() const {
- if (!hasExplicitTemplateArgs()) return 0;
+ if (!hasExplicitTemplateArgs()) return nullptr;
return &getExplicitTemplateArgs();
}
@@ -2691,7 +2504,7 @@ class UnresolvedLookupExpr : public OverloadExpr {
UnresolvedLookupExpr(EmptyShell Empty)
: OverloadExpr(UnresolvedLookupExprClass, Empty),
- RequiresADL(false), Overloaded(false), NamingClass(0)
+ RequiresADL(false), Overloaded(false), NamingClass(nullptr)
{}
friend class ASTStmtReader;
@@ -2706,7 +2519,7 @@ public:
UnresolvedSetIterator End) {
return new(C) UnresolvedLookupExpr(C, NamingClass, QualifierLoc,
SourceLocation(), NameInfo,
- ADL, Overloaded, 0, Begin, End);
+ ADL, Overloaded, nullptr, Begin, End);
}
static UnresolvedLookupExpr *Create(const ASTContext &C,
@@ -2781,7 +2594,7 @@ class DependentScopeDeclRefExpr : public Expr {
/// \brief Return the optional template keyword and arguments info.
ASTTemplateKWAndArgsInfo *getTemplateKWAndArgsInfo() {
- if (!HasTemplateKWAndArgsInfo) return 0;
+ if (!HasTemplateKWAndArgsInfo) return nullptr;
return reinterpret_cast<ASTTemplateKWAndArgsInfo*>(this + 1);
}
/// \brief Return the optional template keyword and arguments info.
@@ -2875,7 +2688,7 @@ public:
/// This points to the same data as getExplicitTemplateArgs(), but
/// returns null if there are no explicit template arguments.
const ASTTemplateArgumentListInfo *getOptionalExplicitTemplateArgs() const {
- if (!hasExplicitTemplateArgs()) return 0;
+ if (!hasExplicitTemplateArgs()) return nullptr;
return &getExplicitTemplateArgs();
}
@@ -3151,7 +2964,7 @@ class CXXDependentScopeMemberExpr : public Expr {
/// \brief Return the optional template keyword and arguments info.
ASTTemplateKWAndArgsInfo *getTemplateKWAndArgsInfo() {
- if (!HasTemplateKWAndArgsInfo) return 0;
+ if (!HasTemplateKWAndArgsInfo) return nullptr;
return reinterpret_cast<ASTTemplateKWAndArgsInfo*>(this + 1);
}
/// \brief Return the optional template keyword and arguments info.
@@ -3296,7 +3109,7 @@ public:
/// This points to the same data as getExplicitTemplateArgs(), but
/// returns null if there are no explicit template arguments.
const ASTTemplateArgumentListInfo *getOptionalExplicitTemplateArgs() const {
- if (!hasExplicitTemplateArgs()) return 0;
+ if (!hasExplicitTemplateArgs()) return nullptr;
return &getExplicitTemplateArgs();
}
@@ -3398,7 +3211,7 @@ class UnresolvedMemberExpr : public OverloadExpr {
UnresolvedMemberExpr(EmptyShell Empty)
: OverloadExpr(UnresolvedMemberExprClass, Empty), IsArrow(false),
- HasUnresolvedUsing(false), Base(0) { }
+ HasUnresolvedUsing(false), Base(nullptr) { }
friend class ASTStmtReader;
@@ -3612,7 +3425,7 @@ public:
};
inline ASTTemplateKWAndArgsInfo *OverloadExpr::getTemplateKWAndArgsInfo() {
- if (!HasTemplateKWAndArgsInfo) return 0;
+ if (!HasTemplateKWAndArgsInfo) return nullptr;
if (isa<UnresolvedLookupExpr>(this))
return reinterpret_cast<ASTTemplateKWAndArgsInfo*>
(cast<UnresolvedLookupExpr>(this) + 1);
@@ -3904,39 +3717,51 @@ public:
/// temporary. When either happens, the expression will also track the
/// declaration which is responsible for the lifetime extension.
class MaterializeTemporaryExpr : public Expr {
-public:
- /// \brief The temporary-generating expression whose value will be
- /// materialized.
- Stmt *Temporary;
+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;
+ /// \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,
- const ValueDecl *ExtendedBy)
+ bool BoundToLvalueReference)
: Expr(MaterializeTemporaryExprClass, T,
BoundToLvalueReference? VK_LValue : VK_XValue, OK_Ordinary,
Temporary->isTypeDependent(), Temporary->isValueDependent(),
Temporary->isInstantiationDependent(),
Temporary->containsUnexpandedParameterPack()),
- Temporary(Temporary), ExtendingDecl(ExtendedBy) {
- }
+ 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 *>(Temporary); }
+ 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
@@ -3948,10 +3773,15 @@ public:
/// \brief Get the declaration which triggered the lifetime-extension of this
/// temporary, if any.
- const ValueDecl *getExtendingDecl() const { return ExtendingDecl; }
+ const ValueDecl *getExtendingDecl() const {
+ return State.is<Stmt *>() ? nullptr
+ : State.get<ExtraState *>()->ExtendingDecl;
+ }
+
+ void setExtendingDecl(const ValueDecl *ExtendedBy, unsigned ManglingNumber);
- void setExtendingDecl(const ValueDecl *ExtendedBy) {
- ExtendingDecl = ExtendedBy;
+ unsigned getManglingNumber() const {
+ return State.is<Stmt *>() ? 0 : State.get<ExtraState *>()->ManglingNumber;
}
/// \brief Determine whether this materialized temporary is bound to an
@@ -3961,10 +3791,10 @@ public:
}
SourceLocation getLocStart() const LLVM_READONLY {
- return Temporary->getLocStart();
+ return getTemporary()->getLocStart();
}
SourceLocation getLocEnd() const LLVM_READONLY {
- return Temporary->getLocEnd();
+ return getTemporary()->getLocEnd();
}
static bool classof(const Stmt *T) {
@@ -3972,7 +3802,13 @@ public:
}
// Iterators
- child_range children() { return child_range(&Temporary, &Temporary + 1); }
+ 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);
+ }
};
} // end namespace clang
diff --git a/include/clang/AST/ExprObjC.h b/include/clang/AST/ExprObjC.h
index aeb55da1fb91..817c0cc43131 100644
--- a/include/clang/AST/ExprObjC.h
+++ b/include/clang/AST/ExprObjC.h
@@ -215,7 +215,7 @@ struct ObjCDictionaryElement {
} // end namespace clang
namespace llvm {
-template <> struct isPodLike<clang::ObjCDictionaryElement> : llvm::true_type {};
+template <> struct isPodLike<clang::ObjCDictionaryElement> : std::true_type {};
}
namespace clang {
@@ -277,14 +277,14 @@ class ObjCDictionaryLiteral : public Expr {
ExpansionData *getExpansionData() {
if (!HasPackExpansions)
- return 0;
+ return nullptr;
return reinterpret_cast<ExpansionData *>(getKeyValues() + NumElements);
}
const ExpansionData *getExpansionData() const {
if (!HasPackExpansions)
- return 0;
+ return nullptr;
return reinterpret_cast<const ExpansionData *>(getKeyValues()+NumElements);
}
@@ -683,13 +683,13 @@ public:
if (isExplicitProperty()) {
const ObjCPropertyDecl *PDecl = getExplicitProperty();
if (const ObjCMethodDecl *Getter = PDecl->getGetterMethodDecl())
- ResultType = Getter->getResultType();
+ ResultType = Getter->getReturnType();
else
ResultType = PDecl->getType();
} else {
const ObjCMethodDecl *Getter = getImplicitPropertyGetter();
if (Getter)
- ResultType = Getter->getResultType(); // with reference!
+ ResultType = Getter->getReturnType(); // with reference!
}
return ResultType;
}
@@ -743,7 +743,7 @@ private:
void setExplicitProperty(ObjCPropertyDecl *D, unsigned methRefFlags) {
PropertyOrGetter.setPointer(D);
PropertyOrGetter.setInt(false);
- SetterAndMethodRefFlags.setPointer(0);
+ SetterAndMethodRefFlags.setPointer(nullptr);
SetterAndMethodRefFlags.setInt(methRefFlags);
}
void setImplicitProperty(ObjCMethodDecl *Getter, ObjCMethodDecl *Setter,
@@ -1174,7 +1174,7 @@ public:
if (getReceiverKind() == Instance)
return static_cast<Expr *>(getReceiverPointer());
- return 0;
+ return nullptr;
}
const Expr *getInstanceReceiver() const {
return const_cast<ObjCMessageExpr*>(this)->getInstanceReceiver();
@@ -1201,7 +1201,7 @@ public:
TypeSourceInfo *getClassReceiverTypeInfo() const {
if (getReceiverKind() == Class)
return reinterpret_cast<TypeSourceInfo *>(getReceiverPointer());
- return 0;
+ return nullptr;
}
void setClassReceiver(TypeSourceInfo *TSInfo) {
@@ -1270,14 +1270,14 @@ public:
if (HasMethod)
return reinterpret_cast<const ObjCMethodDecl *>(SelectorOrMethod);
- return 0;
+ return nullptr;
}
ObjCMethodDecl *getMethodDecl() {
if (HasMethod)
return reinterpret_cast<ObjCMethodDecl *>(SelectorOrMethod);
- return 0;
+ return nullptr;
}
void setMethodDecl(ObjCMethodDecl *MD) {
diff --git a/include/clang/AST/ExternalASTSource.h b/include/clang/AST/ExternalASTSource.h
index b077426e6a47..1e8eff38d3ec 100644
--- a/include/clang/AST/ExternalASTSource.h
+++ b/include/clang/AST/ExternalASTSource.h
@@ -45,7 +45,7 @@ enum ExternalLoadResult {
/// no additional processing is required.
ELR_AlreadyLoaded
};
-
+
/// \brief Abstract interface for external sources of AST nodes.
///
/// External AST sources provide AST nodes constructed from some
@@ -53,7 +53,11 @@ enum ExternalLoadResult {
/// sources can resolve types and declarations from abstract IDs into
/// actual type and declaration nodes, and read parts of declaration
/// contexts.
-class ExternalASTSource {
+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;
@@ -61,7 +65,7 @@ class ExternalASTSource {
friend class ExternalSemaSource;
public:
- ExternalASTSource() : SemaSource(false) { }
+ ExternalASTSource() : CurrentGeneration(0), SemaSource(false) { }
virtual ~ExternalASTSource();
@@ -79,6 +83,11 @@ public:
}
};
+ /// \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.
///
@@ -138,7 +147,7 @@ public:
virtual void completeVisibleDeclsMap(const DeclContext *DC);
/// \brief Retrieve the module that corresponds to the given module ID.
- virtual Module *getModule(unsigned ID) { return 0; }
+ virtual Module *getModule(unsigned ID) { return nullptr; }
/// \brief Finds all declarations lexically contained within the given
/// DeclContext, after applying an optional filter predicate.
@@ -160,7 +169,7 @@ public:
/// \return true if an error occurred
ExternalLoadResult FindExternalLexicalDecls(const DeclContext *DC,
SmallVectorImpl<Decl*> &Result) {
- return FindExternalLexicalDecls(DC, 0, Result);
+ return FindExternalLexicalDecls(DC, nullptr, Result);
}
template <typename DeclTy>
@@ -171,43 +180,50 @@ public:
/// \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) {}
+ /// 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) {}
+ 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
+ /// set on the ObjCInterfaceDecl via the function
/// \c ObjCInterfaceDecl::setExternallyCompleted().
- virtual void CompleteType(ObjCInterfaceDecl *Class) { }
+ virtual void CompleteType(ObjCInterfaceDecl *Class);
/// \brief Loads comment ranges.
- virtual void ReadComments() { }
+ 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() { }
+ 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() { }
+ 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) { }
+ virtual void StartTranslationUnit(ASTConsumer *Consumer);
/// \brief Print any statistics that have been gathered regarding
/// the external AST source.
@@ -243,16 +259,12 @@ public:
/// 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)
- {
- return false;
- }
-
+ 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.
//===--------------------------------------------------------------------===//
@@ -284,6 +296,9 @@ protected:
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
@@ -354,6 +369,100 @@ public:
}
};
+/// \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
@@ -519,7 +628,7 @@ public:
if (From.Position < 0) {
Loaded.erase(Loaded.end() + From.Position, Loaded.end());
- From = begin(0, true);
+ From = begin(nullptr, true);
}
Local.erase(Local.begin() + From.Position, Local.begin() + To.Position);
diff --git a/include/clang/AST/LambdaCapture.h b/include/clang/AST/LambdaCapture.h
new file mode 100644
index 000000000000..8633c9796523
--- /dev/null
+++ b/include/clang/AST/LambdaCapture.h
@@ -0,0 +1,123 @@
+//===--- 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; }
+
+ /// \brief Determine whether this capture handles a variable.
+ bool capturesVariable() const {
+ return dyn_cast_or_null<VarDecl>(DeclAndBits.getPointer());
+ }
+
+ /// \brief Determine whether this is an init-capture.
+ bool isInitCapture() const {
+ return capturesVariable() && getCapturedVar()->isInitCapture();
+ }
+
+ /// \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/include/clang/AST/Makefile b/include/clang/AST/Makefile
index ae84bcfd5817..85e6449c509a 100644
--- a/include/clang/AST/Makefile
+++ b/include/clang/AST/Makefile
@@ -1,6 +1,6 @@
CLANG_LEVEL := ../../..
TD_SRC_DIR = $(PROJ_SRC_DIR)/../Basic
-BUILT_SOURCES = Attrs.inc AttrImpl.inc AttrDump.inc \
+BUILT_SOURCES = Attrs.inc AttrImpl.inc AttrDump.inc AttrVisitor.inc \
StmtNodes.inc DeclNodes.inc \
CommentNodes.inc CommentHTMLTags.inc \
CommentHTMLTagsProperties.inc \
@@ -30,6 +30,12 @@ $(ObjDir)/AttrDump.inc.tmp : $(TD_SRC_DIR)/Attr.td $(CLANG_TBLGEN) \
$(Verb) $(ClangTableGen) -gen-clang-attr-dump -o $(call SYSPATH, $@) \
-I $(PROJ_SRC_DIR)/../../ $<
+$(ObjDir)/AttrVisitor.inc.tmp : $(TD_SRC_DIR)/Attr.td $(CLANG_TBLGEN) \
+ $(ObjDir)/.dir
+ $(Echo) "Building Clang attribute AST visitor with tblgen"
+ $(Verb) $(ClangTableGen) -gen-clang-attr-ast-visitor -o $(call SYSPATH, $@) \
+ -I $(PROJ_SRC_DIR)/../../ $<
+
$(ObjDir)/StmtNodes.inc.tmp : $(TD_SRC_DIR)/StmtNodes.td $(CLANG_TBLGEN) \
$(ObjDir)/.dir
$(Echo) "Building Clang statement node tables with tblgen"
diff --git a/include/clang/AST/Mangle.h b/include/clang/AST/Mangle.h
index c4d0d22cdf0a..a8d119971b33 100644
--- a/include/clang/AST/Mangle.h
+++ b/include/clang/AST/Mangle.h
@@ -31,36 +31,10 @@ namespace clang {
class FunctionDecl;
class NamedDecl;
class ObjCMethodDecl;
- class VarDecl;
+ class StringLiteral;
struct ThisAdjustment;
struct ThunkInfo;
-
-/// MangleBuffer - a convenient class for storing a name which is
-/// either the result of a mangling or is a constant string with
-/// external memory ownership.
-class MangleBuffer {
-public:
- void setString(StringRef Ref) {
- String = Ref;
- }
-
- SmallVectorImpl<char> &getBuffer() {
- return Buffer;
- }
-
- StringRef getString() const {
- if (!String.empty()) return String;
- return Buffer.str();
- }
-
- operator StringRef() const {
- return getString();
- }
-
-private:
- StringRef String;
- SmallString<256> Buffer;
-};
+ class VarDecl;
/// MangleContext - Context for tracking state which persists across multiple
/// calls to the C++ name mangler.
@@ -80,6 +54,7 @@ private:
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; }
@@ -104,12 +79,19 @@ public:
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 &);
@@ -121,6 +103,7 @@ public:
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;
@@ -128,6 +111,7 @@ public:
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,
@@ -200,9 +184,23 @@ public:
raw_ostream &Out) = 0;
virtual void mangleVirtualMemPtrThunk(const CXXMethodDecl *MD,
- uint64_t OffsetInVFTable,
raw_ostream &) = 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;
}
diff --git a/include/clang/AST/MangleNumberingContext.h b/include/clang/AST/MangleNumberingContext.h
index 5a227f201fbb..56c995264b32 100644
--- a/include/clang/AST/MangleNumberingContext.h
+++ b/include/clang/AST/MangleNumberingContext.h
@@ -33,7 +33,6 @@ class VarDecl;
class MangleNumberingContext
: public RefCountedBase<MangleNumberingContext> {
llvm::DenseMap<const Type *, unsigned> ManglingNumbers;
- llvm::DenseMap<IdentifierInfo*, unsigned> TagManglingNumbers;
public:
virtual ~MangleNumberingContext() {}
@@ -46,13 +45,18 @@ public:
/// context.
unsigned getManglingNumber(const BlockDecl *BD);
+ /// Static locals are numbered by source order.
+ unsigned getStaticLocalNumber(const VarDecl *VD);
+
/// \brief Retrieve the mangling number of a static local variable within
/// this context.
- virtual unsigned getManglingNumber(const VarDecl *VD) = 0;
+ virtual unsigned getManglingNumber(const VarDecl *VD,
+ unsigned MSLocalManglingNumber) = 0;
/// \brief Retrieve the mangling number of a static local variable within
/// this context.
- unsigned getManglingNumber(const TagDecl *TD);
+ virtual unsigned getManglingNumber(const TagDecl *TD,
+ unsigned MSLocalManglingNumber) = 0;
};
} // end namespace clang
diff --git a/include/clang/AST/NestedNameSpecifier.h b/include/clang/AST/NestedNameSpecifier.h
index b332b153fe8d..fc719bdc16c3 100644
--- a/include/clang/AST/NestedNameSpecifier.h
+++ b/include/clang/AST/NestedNameSpecifier.h
@@ -88,7 +88,8 @@ public:
private:
/// \brief Builds the global specifier.
- NestedNameSpecifier() : Prefix(0, StoredIdentifier), Specifier(0) { }
+ NestedNameSpecifier()
+ : Prefix(nullptr, StoredIdentifier), Specifier(nullptr) {}
/// \brief Copy constructor used internally to clone nested name
/// specifiers.
@@ -160,7 +161,7 @@ public:
if (Prefix.getInt() == StoredIdentifier)
return (IdentifierInfo *)Specifier;
- return 0;
+ return nullptr;
}
/// \brief Retrieve the namespace stored in this nested name
@@ -177,7 +178,7 @@ public:
Prefix.getInt() == StoredTypeSpecWithTemplate)
return (const Type *)Specifier;
- return 0;
+ return nullptr;
}
/// \brief Whether this nested name specifier refers to a dependent
@@ -222,7 +223,7 @@ class NestedNameSpecifierLoc {
public:
/// \brief Construct an empty nested-name-specifier.
- NestedNameSpecifierLoc() : Qualifier(0), Data(0) { }
+ NestedNameSpecifierLoc() : Qualifier(nullptr), Data(nullptr) { }
/// \brief Construct a nested-name-specifier with source location information
/// from
@@ -344,7 +345,8 @@ class NestedNameSpecifierLocBuilder {
public:
NestedNameSpecifierLocBuilder()
- : Representation(0), Buffer(0), BufferSize(0), BufferCapacity(0) { }
+ : Representation(nullptr), Buffer(nullptr), BufferSize(0),
+ BufferCapacity(0) {}
NestedNameSpecifierLocBuilder(const NestedNameSpecifierLocBuilder &Other);
@@ -457,7 +459,7 @@ public:
/// \brief Clear out this builder, and prepare it to build another
/// nested-name-specifier with source-location information.
void Clear() {
- Representation = 0;
+ Representation = nullptr;
BufferSize = 0;
}
diff --git a/include/clang/AST/OpenMPClause.h b/include/clang/AST/OpenMPClause.h
new file mode 100644
index 000000000000..3345959653a6
--- /dev/null
+++ b/include/clang/AST/OpenMPClause.h
@@ -0,0 +1,1455 @@
+//===- 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(); }
+
+ StmtRange children();
+ ConstStmtRange children() const {
+ return const_cast<OMPClause *>(this)->children();
+ }
+ static bool classof(const OMPClause *T) { 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 *>(
+ reinterpret_cast<Expr **>(
+ reinterpret_cast<char *>(this) +
+ llvm::RoundUpToAlignment(sizeof(T), llvm::alignOf<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(),
+ reinterpret_cast<Expr **>(
+ reinterpret_cast<char *>(this) +
+ llvm::RoundUpToAlignment(sizeof(T), llvm::alignOf<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 ArrayRef<const Expr *>(
+ reinterpret_cast<const Expr *const *>(
+ reinterpret_cast<const char *>(this) +
+ llvm::RoundUpToAlignment(sizeof(T), llvm::alignOf<Expr *>())),
+ NumVars);
+ }
+};
+
+/// \brief This represents 'if' clause in the '#pragma omp ...' directive.
+///
+/// \code
+/// #pragma omp parallel if(a > 5)
+/// \endcode
+/// In this example directive '#pragma omp parallel' has simple 'if'
+/// clause with condition 'a > 5'.
+///
+class OMPIfClause : 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 'if' 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.
+ ///
+ OMPIfClause(Expr *Cond, SourceLocation StartLoc, SourceLocation LParenLoc,
+ SourceLocation EndLoc)
+ : OMPClause(OMPC_if, StartLoc, EndLoc), LParenLoc(LParenLoc),
+ Condition(Cond) {}
+
+ /// \brief Build an empty clause.
+ ///
+ OMPIfClause()
+ : OMPClause(OMPC_if, 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_if;
+ }
+
+ StmtRange children() { return StmtRange(&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;
+ }
+
+ StmtRange children() { return StmtRange(&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;
+ }
+
+ StmtRange children() { return StmtRange(&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;
+ }
+
+ StmtRange children() { return StmtRange(&Safelen, &Safelen + 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;
+ }
+
+ StmtRange children() { return StmtRange(&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;
+ }
+
+ StmtRange children() { return StmtRange(); }
+};
+
+/// \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;
+ }
+
+ StmtRange children() { return StmtRange(); }
+};
+
+/// \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 Start location of the schedule ind in source code.
+ SourceLocation KindLoc;
+ /// \brief Location of ',' (if any).
+ SourceLocation CommaLoc;
+ /// \brief Chunk size.
+ Stmt *ChunkSize;
+
+ /// \brief Set schedule kind.
+ ///
+ /// \param K Schedule kind.
+ ///
+ void setScheduleKind(OpenMPScheduleClauseKind K) { Kind = K; }
+ /// \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) { ChunkSize = 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.
+ ///
+ OMPScheduleClause(SourceLocation StartLoc, SourceLocation LParenLoc,
+ SourceLocation KLoc, SourceLocation CommaLoc,
+ SourceLocation EndLoc, OpenMPScheduleClauseKind Kind,
+ Expr *ChunkSize)
+ : OMPClause(OMPC_schedule, StartLoc, EndLoc), LParenLoc(LParenLoc),
+ Kind(Kind), KindLoc(KLoc), CommaLoc(CommaLoc), ChunkSize(ChunkSize) {}
+
+ /// \brief Build an empty clause.
+ ///
+ explicit OMPScheduleClause()
+ : OMPClause(OMPC_schedule, SourceLocation(), SourceLocation()),
+ Kind(OMPC_SCHEDULE_unknown), ChunkSize(nullptr) {}
+
+ /// \brief Get kind of the clause.
+ ///
+ OpenMPScheduleClauseKind getScheduleKind() const { return Kind; }
+ /// \brief Get location of '('.
+ ///
+ SourceLocation getLParenLoc() { return LParenLoc; }
+ /// \brief Get kind location.
+ ///
+ SourceLocation getScheduleKindLoc() { return KindLoc; }
+ /// \brief Get location of ','.
+ ///
+ SourceLocation getCommaLoc() { return CommaLoc; }
+ /// \brief Get chunk size.
+ ///
+ Expr *getChunkSize() { return dyn_cast_or_null<Expr>(ChunkSize); }
+ /// \brief Get chunk size.
+ ///
+ Expr *getChunkSize() const { return dyn_cast_or_null<Expr>(ChunkSize); }
+
+ static bool classof(const OMPClause *T) {
+ return T->getClauseKind() == OMPC_schedule;
+ }
+
+ StmtRange children() { return StmtRange(&ChunkSize, &ChunkSize + 1); }
+};
+
+/// \brief This represents 'ordered' clause in the '#pragma omp ...' directive.
+///
+/// \code
+/// #pragma omp for ordered
+/// \endcode
+/// In this example directive '#pragma omp for' has 'ordered' clause.
+///
+class OMPOrderedClause : public OMPClause {
+public:
+ /// \brief Build 'ordered' clause.
+ ///
+ /// \param StartLoc Starting location of the clause.
+ /// \param EndLoc Ending location of the clause.
+ ///
+ OMPOrderedClause(SourceLocation StartLoc, SourceLocation EndLoc)
+ : OMPClause(OMPC_ordered, StartLoc, EndLoc) {}
+
+ /// \brief Build an empty clause.
+ ///
+ OMPOrderedClause()
+ : OMPClause(OMPC_ordered, SourceLocation(), SourceLocation()) {}
+
+ static bool classof(const OMPClause *T) {
+ return T->getClauseKind() == OMPC_ordered;
+ }
+
+ StmtRange children() { return StmtRange(); }
+};
+
+/// \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;
+ }
+
+ StmtRange children() { return StmtRange(); }
+};
+
+/// \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;
+ }
+
+ StmtRange children() { return StmtRange(); }
+};
+
+/// \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;
+ }
+
+ StmtRange children() { return StmtRange(); }
+};
+
+/// \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 : public OMPVarListClause<OMPPrivateClause> {
+ /// \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) {}
+
+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 OMPPrivateClause *Create(const ASTContext &C, SourceLocation StartLoc,
+ SourceLocation LParenLoc,
+ SourceLocation EndLoc, ArrayRef<Expr *> VL);
+ /// \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);
+
+ StmtRange children() {
+ return StmtRange(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 : public OMPVarListClause<OMPFirstprivateClause> {
+ /// \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) {}
+
+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 OMPFirstprivateClause *
+ Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc,
+ SourceLocation EndLoc, ArrayRef<Expr *> VL);
+ /// \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);
+
+ StmtRange children() {
+ return StmtRange(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 : public OMPVarListClause<OMPLastprivateClause> {
+ /// \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) {}
+
+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 OMPLastprivateClause *
+ Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc,
+ SourceLocation EndLoc, ArrayRef<Expr *> VL);
+ /// \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);
+
+ StmtRange children() {
+ return StmtRange(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 : public OMPVarListClause<OMPSharedClause> {
+ /// \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);
+
+ StmtRange children() {
+ return StmtRange(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 : public OMPVarListClause<OMPReductionClause> {
+ 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; }
+
+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.
+ ///
+ static OMPReductionClause *
+ Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc,
+ SourceLocation ColonLoc, SourceLocation EndLoc, ArrayRef<Expr *> VL,
+ NestedNameSpecifierLoc QualifierLoc,
+ const DeclarationNameInfo &NameInfo);
+ /// \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; }
+
+ StmtRange children() {
+ return StmtRange(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 : public OMPVarListClause<OMPLinearClause> {
+ friend class OMPClauseReader;
+ /// \brief Location of ':'.
+ SourceLocation ColonLoc;
+
+ /// \brief Sets the linear step for clause.
+ void setStep(Expr *Step) { *varlist_end() = Step; }
+
+ /// \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,
+ SourceLocation ColonLoc, SourceLocation EndLoc,
+ unsigned NumVars)
+ : OMPVarListClause<OMPLinearClause>(OMPC_linear, StartLoc, LParenLoc,
+ EndLoc, NumVars),
+ ColonLoc(ColonLoc) {}
+
+ /// \brief Build an empty clause.
+ ///
+ /// \param NumVars Number of variables.
+ ///
+ explicit OMPLinearClause(unsigned NumVars)
+ : OMPVarListClause<OMPLinearClause>(OMPC_linear, SourceLocation(),
+ SourceLocation(), SourceLocation(),
+ NumVars),
+ ColonLoc(SourceLocation()) {}
+
+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 ColonLoc Location of ':'.
+ /// \param EndLoc Ending location of the clause.
+ /// \param VL List of references to the variables.
+ /// \param Step Linear step.
+ static OMPLinearClause *Create(const ASTContext &C, SourceLocation StartLoc,
+ SourceLocation LParenLoc,
+ SourceLocation ColonLoc, SourceLocation EndLoc,
+ ArrayRef<Expr *> VL, Expr *Step);
+
+ /// \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 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 *varlist_end(); }
+ /// \brief Returns linear step.
+ const Expr *getStep() const { return *varlist_end(); }
+
+ StmtRange children() {
+ return StmtRange(reinterpret_cast<Stmt **>(varlist_begin()),
+ reinterpret_cast<Stmt **>(varlist_end() + 1));
+ }
+
+ 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 : public OMPVarListClause<OMPAlignedClause> {
+ 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(); }
+
+ StmtRange children() {
+ return StmtRange(reinterpret_cast<Stmt **>(varlist_begin()),
+ reinterpret_cast<Stmt **>(varlist_end() + 1));
+ }
+
+ 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 : public OMPVarListClause<OMPCopyinClause> {
+ /// \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) {}
+
+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 OMPCopyinClause *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 OMPCopyinClause *CreateEmpty(const ASTContext &C, unsigned N);
+
+ StmtRange children() {
+ return StmtRange(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 : public OMPVarListClause<OMPCopyprivateClause> {
+ /// \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) {}
+
+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 OMPCopyprivateClause *
+ 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 OMPCopyprivateClause *CreateEmpty(const ASTContext &C, unsigned N);
+
+ StmtRange children() {
+ return StmtRange(reinterpret_cast<Stmt **>(varlist_begin()),
+ reinterpret_cast<Stmt **>(varlist_end()));
+ }
+
+ static bool classof(const OMPClause *T) {
+ return T->getClauseKind() == OMPC_copyprivate;
+ }
+};
+
+/// \brief This represents pseudo clause 'flush' for the '#pragma omp flush'
+/// directive.
+///
+/// \code
+/// #pragma omp flush(a,b)
+/// \endcode
+/// In this example directive '#pragma omp flush' has pseudo clause 'flush'
+/// with the variables 'a' and 'b'.
+///
+class OMPFlushClause : public OMPVarListClause<OMPFlushClause> {
+ /// \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);
+
+ StmtRange children() {
+ return StmtRange(reinterpret_cast<Stmt **>(varlist_begin()),
+ reinterpret_cast<Stmt **>(varlist_end()));
+ }
+
+ static bool classof(const OMPClause *T) {
+ return T->getClauseKind() == OMPC_flush;
+ }
+};
+
+} // end namespace clang
+
+#endif
diff --git a/include/clang/AST/OperationKinds.h b/include/clang/AST/OperationKinds.h
index 5e41d955cfd7..aba88d6c5419 100644
--- a/include/clang/AST/OperationKinds.h
+++ b/include/clang/AST/OperationKinds.h
@@ -295,7 +295,10 @@ enum CastKind {
CK_BuiltinFnToFnPtr,
// Convert a zero value for OpenCL event_t initialization.
- CK_ZeroToOCLEvent
+ CK_ZeroToOCLEvent,
+
+ // Convert a pointer to a different address space.
+ CK_AddressSpaceConversion
};
static const CastKind CK_Invalid = static_cast<CastKind>(-1);
diff --git a/include/clang/AST/ParentMap.h b/include/clang/AST/ParentMap.h
index bd2ebf5dbedb..eece8510e9c4 100644
--- a/include/clang/AST/ParentMap.h
+++ b/include/clang/AST/ParentMap.h
@@ -53,7 +53,7 @@ public:
}
bool hasParent(Stmt* S) const {
- return getParent(S) != 0;
+ return getParent(S) != nullptr;
}
bool isConsumedExpr(Expr *E) const;
diff --git a/include/clang/AST/PrettyPrinter.h b/include/clang/AST/PrettyPrinter.h
index 76426991cf47..349f4c44a4e0 100644
--- a/include/clang/AST/PrettyPrinter.h
+++ b/include/clang/AST/PrettyPrinter.h
@@ -41,7 +41,8 @@ struct PrintingPolicy {
ConstantArraySizeAsWritten(false), AnonymousTagLocations(true),
SuppressStrongLifetime(false), SuppressLifetimeQualifiers(false),
Bool(LO.Bool), TerseOutput(false), PolishForDeclaration(false),
- MSWChar(LO.MicrosoftExt && !LO.WChar) { }
+ Half(LO.Half), MSWChar(LO.MicrosoftExt && !LO.WChar),
+ IncludeNewlines(true) { }
/// \brief What language we're printing.
LangOptions LangOpts;
@@ -125,7 +126,7 @@ struct PrintingPolicy {
/// \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.
+ /// prints "(anonymous)" for the name.
bool AnonymousTagLocations : 1;
/// \brief When true, suppress printing of the __strong lifetime qualifier in
@@ -152,9 +153,16 @@ struct PrintingPolicy {
///
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;
};
} // end namespace clang
diff --git a/include/clang/AST/RawCommentList.h b/include/clang/AST/RawCommentList.h
index a4fcc108eb5d..8ba85c43f657 100644
--- a/include/clang/AST/RawCommentList.h
+++ b/include/clang/AST/RawCommentList.h
@@ -193,9 +193,7 @@ private:
SourceManager &SourceMgr;
std::vector<RawComment *> Comments;
- void addCommentsToFront(const std::vector<RawComment *> &C) {
- Comments.insert(Comments.begin(), C.begin(), C.end());
- }
+ void addDeserializedComments(ArrayRef<RawComment *> DeserializedComments);
friend class ASTReader;
};
diff --git a/include/clang/AST/RecordLayout.h b/include/clang/AST/RecordLayout.h
index 7268b3a8240c..4befb4506212 100644
--- a/include/clang/AST/RecordLayout.h
+++ b/include/clang/AST/RecordLayout.h
@@ -66,6 +66,10 @@ private:
// 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;
@@ -78,9 +82,9 @@ private:
/// the size of the object without virtual bases.
CharUnits NonVirtualSize;
- /// NonVirtualAlign - The non-virtual alignment (in chars) of an object,
+ /// NonVirtualAlignment - The non-virtual alignment (in chars) of an object,
/// which is the alignment of the object without virtual bases.
- CharUnits NonVirtualAlign;
+ 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
@@ -100,10 +104,15 @@ private:
/// a primary base class.
bool HasExtendableVFPtr : 1;
- /// AlignAfterVBases - Force appropriate alignment after virtual bases are
- /// laid out in MS-C++-ABI.
- bool AlignAfterVBases : 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;
@@ -127,6 +136,7 @@ private:
friend class ASTContext;
ASTRecordLayout(const ASTContext &Ctx, CharUnits size, CharUnits alignment,
+ CharUnits requiredAlignment,
CharUnits datasize, const uint64_t *fieldoffsets,
unsigned fieldcount);
@@ -134,16 +144,18 @@ private:
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 nonvirtualalign,
+ CharUnits nonvirtualsize, CharUnits nonvirtualalignment,
CharUnits SizeOfLargestEmptySubobject,
const CXXRecordDecl *PrimaryBase,
bool IsPrimaryBaseVirtual,
const CXXRecordDecl *BaseSharingVBPtr,
- bool ForceAlign,
+ bool HasZeroSizedSubObject,
+ bool LeadsWithZeroSizedBase,
const BaseOffsetsMapTy& BaseOffsets,
const VBaseOffsetsMapTy& VBaseOffsets);
@@ -187,10 +199,10 @@ public:
/// getNonVirtualSize - Get the non-virtual alignment (in chars) of an object,
/// which is the alignment of the object without virtual bases.
- CharUnits getNonVirtualAlign() const {
+ CharUnits getNonVirtualAlignment() const {
assert(CXXInfo && "Record layout does not have C++ specific info!");
- return CXXInfo->NonVirtualAlign;
+ return CXXInfo->NonVirtualAlignment;
}
/// getPrimaryBase - Get the primary base for this record.
@@ -267,9 +279,17 @@ public:
return !CXXInfo->VBPtrOffset.isNegative();
}
- bool getAlignAfterVBases() const {
+ 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->AlignAfterVBases;
+ return CXXInfo->LeadsWithZeroSizedBase;
}
/// getVBPtrOffset - Get the offset for virtual base table pointer.
diff --git a/include/clang/AST/RecursiveASTVisitor.h b/include/clang/AST/RecursiveASTVisitor.h
index d09550f0e2c2..ff46ffb94e70 100644
--- a/include/clang/AST/RecursiveASTVisitor.h
+++ b/include/clang/AST/RecursiveASTVisitor.h
@@ -14,6 +14,7 @@
#ifndef LLVM_CLANG_AST_RECURSIVEASTVISITOR_H
#define LLVM_CLANG_AST_RECURSIVEASTVISITOR_H
+#include "clang/AST/Attr.h"
#include "clang/AST/Decl.h"
#include "clang/AST/DeclCXX.h"
#include "clang/AST/DeclFriend.h"
@@ -37,34 +38,24 @@
// 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)
+#define UNARYOP_LIST() \
+ OPERATOR(PostInc) OPERATOR(PostDec) OPERATOR(PreInc) OPERATOR(PreDec) \
+ OPERATOR(AddrOf) OPERATOR(Deref) OPERATOR(Plus) OPERATOR(Minus) \
+ OPERATOR(Not) OPERATOR(LNot) OPERATOR(Real) OPERATOR(Imag) \
+ OPERATOR(Extension)
// All binary operators (excluding compound assign operators).
-#define BINOP_LIST() \
- OPERATOR(PtrMemD) OPERATOR(PtrMemI) \
- OPERATOR(Mul) OPERATOR(Div) OPERATOR(Rem) \
- OPERATOR(Add) OPERATOR(Sub) OPERATOR(Shl) \
- OPERATOR(Shr) \
- \
- OPERATOR(LT) OPERATOR(GT) OPERATOR(LE) \
- OPERATOR(GE) OPERATOR(EQ) OPERATOR(NE) \
- OPERATOR(And) OPERATOR(Xor) OPERATOR(Or) \
- OPERATOR(LAnd) OPERATOR(LOr) \
- \
- OPERATOR(Assign) \
- OPERATOR(Comma)
+#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)
+#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 {
@@ -72,8 +63,11 @@ namespace clang {
// 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)
+#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.
@@ -136,11 +130,10 @@ namespace clang {
/// 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 {
+template <typename Derived> class RecursiveASTVisitor {
public:
/// \brief Return a reference to the derived class.
- Derived &getDerived() { return *static_cast<Derived*>(this); }
+ Derived &getDerived() { return *static_cast<Derived *>(this); }
/// \brief Return whether this visitor should recurse into
/// template instantiations.
@@ -182,6 +175,13 @@ public:
/// 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.
///
@@ -244,7 +244,7 @@ public:
/// \brief Recursively visit a lambda capture.
///
/// \returns false if the visitation was terminated early, true otherwise.
- bool TraverseLambdaCapture(LambdaExpr *LE, const LambdaExpr::Capture *C);
+ bool TraverseLambdaCapture(LambdaExpr *LE, const LambdaCapture *C);
/// \brief Recursively visit the body of a lambda expression.
///
@@ -254,107 +254,114 @@ public:
/// \returns false if the visitation was terminated early, true otherwise.
bool TraverseLambdaBody(LambdaExpr *LE);
- // ---- Methods on Stmts ----
+ // ---- Methods on Attrs ----
+
+ // \brief Visit an attribute.
+ bool VisitAttr(Attr *A) { return true; }
- // Declare Traverse*() for all concrete Stmt classes.
+// 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 ----
+
+// Declare Traverse*() for all concrete Stmt classes.
#define ABSTRACT_STMT(STMT)
-#define STMT(CLASS, PARENT) \
- bool Traverse##CLASS(CLASS *S);
+#define STMT(CLASS, PARENT) bool Traverse##CLASS(CLASS *S);
#include "clang/AST/StmtNodes.inc"
// The above header #undefs ABSTRACT_STMT and STMT upon exit.
// Define WalkUpFrom*() and empty Visit*() for all Stmt classes.
bool WalkUpFromStmt(Stmt *S) { return getDerived().VisitStmt(S); }
bool VisitStmt(Stmt *S) { return true; }
-#define STMT(CLASS, PARENT) \
- bool WalkUpFrom##CLASS(CLASS *S) { \
- TRY_TO(WalkUpFrom##PARENT(S)); \
- TRY_TO(Visit##CLASS(S)); \
- return true; \
- } \
+#define STMT(CLASS, PARENT) \
+ bool WalkUpFrom##CLASS(CLASS *S) { \
+ TRY_TO(WalkUpFrom##PARENT(S)); \
+ TRY_TO(Visit##CLASS(S)); \
+ return true; \
+ } \
bool Visit##CLASS(CLASS *S) { return true; }
#include "clang/AST/StmtNodes.inc"
- // Define Traverse*(), WalkUpFrom*(), and Visit*() for unary
- // operator methods. Unary operators are not classes in themselves
- // (they're all opcodes in UnaryOperator) but do have visitors.
-#define OPERATOR(NAME) \
- bool TraverseUnary##NAME(UnaryOperator *S) { \
- TRY_TO(WalkUpFromUnary##NAME(S)); \
- TRY_TO(TraverseStmt(S->getSubExpr())); \
- return true; \
- } \
- bool WalkUpFromUnary##NAME(UnaryOperator *S) { \
- TRY_TO(WalkUpFromUnaryOperator(S)); \
- TRY_TO(VisitUnary##NAME(S)); \
- return true; \
- } \
+// Define Traverse*(), WalkUpFrom*(), and Visit*() for unary
+// operator methods. Unary operators are not classes in themselves
+// (they're all opcodes in UnaryOperator) but do have visitors.
+#define OPERATOR(NAME) \
+ bool TraverseUnary##NAME(UnaryOperator *S) { \
+ TRY_TO(WalkUpFromUnary##NAME(S)); \
+ TRY_TO(TraverseStmt(S->getSubExpr())); \
+ return true; \
+ } \
+ bool WalkUpFromUnary##NAME(UnaryOperator *S) { \
+ TRY_TO(WalkUpFromUnaryOperator(S)); \
+ TRY_TO(VisitUnary##NAME(S)); \
+ return true; \
+ } \
bool VisitUnary##NAME(UnaryOperator *S) { return true; }
UNARYOP_LIST()
#undef OPERATOR
- // Define Traverse*(), WalkUpFrom*(), and Visit*() for binary
- // operator methods. Binary operators are not classes in themselves
- // (they're all opcodes in BinaryOperator) but do have visitors.
-#define GENERAL_BINOP_FALLBACK(NAME, BINOP_TYPE) \
- bool TraverseBin##NAME(BINOP_TYPE *S) { \
- TRY_TO(WalkUpFromBin##NAME(S)); \
- TRY_TO(TraverseStmt(S->getLHS())); \
- TRY_TO(TraverseStmt(S->getRHS())); \
- return true; \
- } \
- bool WalkUpFromBin##NAME(BINOP_TYPE *S) { \
- TRY_TO(WalkUpFrom##BINOP_TYPE(S)); \
- TRY_TO(VisitBin##NAME(S)); \
- return true; \
- } \
+// Define Traverse*(), WalkUpFrom*(), and Visit*() for binary
+// operator methods. Binary operators are not classes in themselves
+// (they're all opcodes in BinaryOperator) but do have visitors.
+#define GENERAL_BINOP_FALLBACK(NAME, BINOP_TYPE) \
+ bool TraverseBin##NAME(BINOP_TYPE *S) { \
+ TRY_TO(WalkUpFromBin##NAME(S)); \
+ TRY_TO(TraverseStmt(S->getLHS())); \
+ TRY_TO(TraverseStmt(S->getRHS())); \
+ return true; \
+ } \
+ bool WalkUpFromBin##NAME(BINOP_TYPE *S) { \
+ TRY_TO(WalkUpFrom##BINOP_TYPE(S)); \
+ TRY_TO(VisitBin##NAME(S)); \
+ return true; \
+ } \
bool VisitBin##NAME(BINOP_TYPE *S) { return true; }
#define OPERATOR(NAME) GENERAL_BINOP_FALLBACK(NAME, BinaryOperator)
BINOP_LIST()
#undef OPERATOR
- // Define Traverse*(), WalkUpFrom*(), and Visit*() for compound
- // assignment methods. Compound assignment operators are not
- // classes in themselves (they're all opcodes in
- // CompoundAssignOperator) but do have visitors.
-#define OPERATOR(NAME) \
+// 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.
+// ---- Methods on Types ----
+// FIXME: revamp to take TypeLoc's rather than Types.
- // Declare Traverse*() for all concrete Type classes.
+// Declare Traverse*() for all concrete Type classes.
#define ABSTRACT_TYPE(CLASS, BASE)
-#define TYPE(CLASS, BASE) \
- bool Traverse##CLASS##Type(CLASS##Type *T);
+#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; \
- } \
+#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
+// ---- Methods on TypeLocs ----
+// FIXME: this currently just calls the matching Type methods
- // Declare Traverse*() for all concrete TypeLoc classes.
+// Declare Traverse*() for all concrete TypeLoc classes.
#define ABSTRACT_TYPELOC(CLASS, BASE)
-#define TYPELOC(CLASS, BASE) \
- bool Traverse##CLASS##TypeLoc(CLASS##TypeLoc TL);
+#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.
@@ -373,34 +380,33 @@ public:
}
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; \
- } \
+// 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 ----
+// ---- Methods on Decls ----
- // Declare Traverse*() for all concrete Decl classes.
+// Declare Traverse*() for all concrete Decl classes.
#define ABSTRACT_DECL(DECL)
-#define DECL(CLASS, BASE) \
- bool Traverse##CLASS##Decl(CLASS##Decl *D);
+#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; \
- } \
+#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"
@@ -422,13 +428,12 @@ private:
bool TraverseDeclContextHelper(DeclContext *DC);
bool TraverseFunctionHelper(FunctionDecl *D);
bool TraverseVarHelper(VarDecl *D);
+ bool TraverseOMPExecutableDirective(OMPExecutableDirective *S);
bool TraverseOMPClause(OMPClause *C);
-#define OPENMP_CLAUSE(Name, Class) \
- bool Visit##Class(Class *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>
- void VisitOMPClauseList(T *Node);
+ template <typename T> bool VisitOMPClauseList(T *Node);
struct EnqueueJob {
Stmt *S;
@@ -440,7 +445,7 @@ private:
bool dataTraverseNode(Stmt *S, bool &EnqueueChildren);
};
-template<typename Derived>
+template <typename Derived>
bool RecursiveASTVisitor<Derived>::dataTraverse(Stmt *S) {
SmallVector<EnqueueJob, 16> Queue;
@@ -457,7 +462,8 @@ bool RecursiveASTVisitor<Derived>::dataTraverse(Stmt *S) {
if (getDerived().shouldUseDataRecursionFor(CurrS)) {
if (job.StmtIt == Stmt::child_iterator()) {
bool EnqueueChildren = true;
- if (!dataTraverseNode(CurrS, EnqueueChildren)) return false;
+ if (!dataTraverseNode(CurrS, EnqueueChildren))
+ return false;
if (!EnqueueChildren) {
Queue.pop_back();
continue;
@@ -481,53 +487,57 @@ bool RecursiveASTVisitor<Derived>::dataTraverse(Stmt *S) {
return true;
}
-template<typename Derived>
+template <typename Derived>
bool RecursiveASTVisitor<Derived>::dataTraverseNode(Stmt *S,
bool &EnqueueChildren) {
- // Dispatch to the corresponding WalkUpFrom* function only if the derived
- // class didn't override Traverse* (and thus the traversal is trivial).
-#define DISPATCH_WALK(NAME, CLASS, VAR) \
- { \
- bool (Derived::*DerivedFn)(CLASS*) = &Derived::Traverse##NAME; \
- bool (Derived::*BaseFn)(CLASS*) = &RecursiveASTVisitor::Traverse##NAME; \
- if (DerivedFn == BaseFn) \
- return getDerived().WalkUpFrom##NAME(static_cast<CLASS*>(VAR)); \
- } \
- EnqueueChildren = false; \
- return getDerived().Traverse##NAME(static_cast<CLASS*>(VAR));
+// Dispatch to the corresponding WalkUpFrom* function only if the derived
+// class didn't override Traverse* (and thus the traversal is trivial).
+#define DISPATCH_WALK(NAME, CLASS, VAR) \
+ { \
+ bool (Derived::*DerivedFn)(CLASS *) = &Derived::Traverse##NAME; \
+ bool (Derived::*BaseFn)(CLASS *) = &RecursiveASTVisitor::Traverse##NAME; \
+ if (DerivedFn == BaseFn) \
+ return getDerived().WalkUpFrom##NAME(static_cast<CLASS *>(VAR)); \
+ } \
+ EnqueueChildren = false; \
+ return getDerived().Traverse##NAME(static_cast<CLASS *>(VAR));
if (BinaryOperator *BinOp = dyn_cast<BinaryOperator>(S)) {
switch (BinOp->getOpcode()) {
-#define OPERATOR(NAME) \
- case BO_##NAME: DISPATCH_WALK(Bin##NAME, BinaryOperator, S);
+#define OPERATOR(NAME) \
+ case BO_##NAME: \
+ DISPATCH_WALK(Bin##NAME, BinaryOperator, S);
- BINOP_LIST()
+ BINOP_LIST()
#undef OPERATOR
-#define OPERATOR(NAME) \
- case BO_##NAME##Assign: \
+#define OPERATOR(NAME) \
+ case BO_##NAME##Assign: \
DISPATCH_WALK(Bin##NAME##Assign, CompoundAssignOperator, S);
- CAO_LIST()
+ CAO_LIST()
#undef OPERATOR
}
} else if (UnaryOperator *UnOp = dyn_cast<UnaryOperator>(S)) {
switch (UnOp->getOpcode()) {
-#define OPERATOR(NAME) \
- case UO_##NAME: DISPATCH_WALK(Unary##NAME, UnaryOperator, S);
+#define OPERATOR(NAME) \
+ case UO_##NAME: \
+ DISPATCH_WALK(Unary##NAME, UnaryOperator, S);
- UNARYOP_LIST()
+ UNARYOP_LIST()
#undef OPERATOR
}
}
// Top switch stmt: dispatch to TraverseFooStmt for each concrete FooStmt.
switch (S->getStmtClass()) {
- case Stmt::NoStmtClass: break;
+ case Stmt::NoStmtClass:
+ break;
#define ABSTRACT_STMT(STMT)
-#define STMT(CLASS, PARENT) \
- case Stmt::CLASS##Class: DISPATCH_WALK(CLASS, CLASS, S);
+#define STMT(CLASS, PARENT) \
+ case Stmt::CLASS##Class: \
+ DISPATCH_WALK(CLASS, CLASS, S);
#include "clang/AST/StmtNodes.inc"
}
@@ -536,14 +546,16 @@ bool RecursiveASTVisitor<Derived>::dataTraverseNode(Stmt *S,
return true;
}
-#define DISPATCH(NAME, CLASS, VAR) \
- return getDerived().Traverse##NAME(static_cast<CLASS*>(VAR))
+#define DISPATCH(NAME, CLASS, VAR) \
+ return getDerived().Traverse##NAME(static_cast<CLASS *>(VAR))
-template<typename Derived>
+template <typename Derived>
bool RecursiveASTVisitor<Derived>::TraverseStmt(Stmt *S) {
if (!S)
return true;
+#define DISPATCH_STMT(NAME, CLASS, VAR) DISPATCH(NAME, CLASS, VAR)
+
if (getDerived().shouldUseDataRecursionFor(S))
return dataTraverse(S);
@@ -552,27 +564,29 @@ bool RecursiveASTVisitor<Derived>::TraverseStmt(Stmt *S) {
// below.
if (BinaryOperator *BinOp = dyn_cast<BinaryOperator>(S)) {
switch (BinOp->getOpcode()) {
-#define OPERATOR(NAME) \
- case BO_##NAME: DISPATCH(Bin##NAME, BinaryOperator, S);
+#define OPERATOR(NAME) \
+ case BO_##NAME: \
+ DISPATCH_STMT(Bin##NAME, BinaryOperator, S);
- BINOP_LIST()
+ BINOP_LIST()
#undef OPERATOR
#undef BINOP_LIST
-#define OPERATOR(NAME) \
- case BO_##NAME##Assign: \
- DISPATCH(Bin##NAME##Assign, CompoundAssignOperator, S);
+#define OPERATOR(NAME) \
+ case BO_##NAME##Assign: \
+ DISPATCH_STMT(Bin##NAME##Assign, CompoundAssignOperator, S);
- CAO_LIST()
+ CAO_LIST()
#undef OPERATOR
#undef CAO_LIST
}
} else if (UnaryOperator *UnOp = dyn_cast<UnaryOperator>(S)) {
switch (UnOp->getOpcode()) {
-#define OPERATOR(NAME) \
- case UO_##NAME: DISPATCH(Unary##NAME, UnaryOperator, S);
+#define OPERATOR(NAME) \
+ case UO_##NAME: \
+ DISPATCH_STMT(Unary##NAME, UnaryOperator, S);
- UNARYOP_LIST()
+ UNARYOP_LIST()
#undef OPERATOR
#undef UNARYOP_LIST
}
@@ -580,41 +594,45 @@ bool RecursiveASTVisitor<Derived>::TraverseStmt(Stmt *S) {
// Top switch stmt: dispatch to TraverseFooStmt for each concrete FooStmt.
switch (S->getStmtClass()) {
- case Stmt::NoStmtClass: break;
+ case Stmt::NoStmtClass:
+ break;
#define ABSTRACT_STMT(STMT)
-#define STMT(CLASS, PARENT) \
- case Stmt::CLASS##Class: DISPATCH(CLASS, CLASS, S);
+#define STMT(CLASS, PARENT) \
+ case Stmt::CLASS##Class: \
+ DISPATCH_STMT(CLASS, CLASS, S);
#include "clang/AST/StmtNodes.inc"
}
return true;
}
-template<typename Derived>
+#undef DISPATCH_STMT
+
+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()));
+#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>
+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: \
+#define TYPELOC(CLASS, BASE) \
+ case TypeLoc::CLASS: \
return getDerived().Traverse##CLASS##TypeLoc(TL.castAs<CLASS##TypeLoc>());
#include "clang/AST/TypeLocNodes.def"
}
@@ -622,8 +640,12 @@ bool RecursiveASTVisitor<Derived>::TraverseTypeLoc(TypeLoc TL) {
return true;
}
+// Define the Traverse*Attr(Attr* A) methods
+#define VISITORCLASS RecursiveASTVisitor
+#include "clang/AST/AttrVisitor.inc"
+#undef VISITORCLASS
-template<typename Derived>
+template <typename Derived>
bool RecursiveASTVisitor<Derived>::TraverseDecl(Decl *D) {
if (!D)
return true;
@@ -635,19 +657,27 @@ bool RecursiveASTVisitor<Derived>::TraverseDecl(Decl *D) {
switch (D->getKind()) {
#define ABSTRACT_DECL(DECL)
-#define DECL(CLASS, BASE) \
- case Decl::CLASS: DISPATCH(CLASS##Decl, CLASS##Decl, D);
+#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>
+template <typename Derived>
bool RecursiveASTVisitor<Derived>::TraverseNestedNameSpecifier(
- NestedNameSpecifier *NNS) {
+ NestedNameSpecifier *NNS) {
if (!NNS)
return true;
@@ -669,14 +699,14 @@ bool RecursiveASTVisitor<Derived>::TraverseNestedNameSpecifier(
return true;
}
-template<typename Derived>
+template <typename Derived>
bool RecursiveASTVisitor<Derived>::TraverseNestedNameSpecifierLoc(
- NestedNameSpecifierLoc NNS) {
+ NestedNameSpecifierLoc NNS) {
if (!NNS)
return true;
- if (NestedNameSpecifierLoc Prefix = NNS.getPrefix())
- TRY_TO(TraverseNestedNameSpecifierLoc(Prefix));
+ if (NestedNameSpecifierLoc Prefix = NNS.getPrefix())
+ TRY_TO(TraverseNestedNameSpecifierLoc(Prefix));
switch (NNS.getNestedNameSpecifier()->getKind()) {
case NestedNameSpecifier::Identifier:
@@ -694,9 +724,9 @@ bool RecursiveASTVisitor<Derived>::TraverseNestedNameSpecifierLoc(
return true;
}
-template<typename Derived>
+template <typename Derived>
bool RecursiveASTVisitor<Derived>::TraverseDeclarationNameInfo(
- DeclarationNameInfo NameInfo) {
+ DeclarationNameInfo NameInfo) {
switch (NameInfo.getName().getNameKind()) {
case DeclarationName::CXXConstructorName:
case DeclarationName::CXXDestructorName:
@@ -719,7 +749,7 @@ bool RecursiveASTVisitor<Derived>::TraverseDeclarationNameInfo(
return true;
}
-template<typename Derived>
+template <typename Derived>
bool RecursiveASTVisitor<Derived>::TraverseTemplateName(TemplateName Template) {
if (DependentTemplateName *DTN = Template.getAsDependentTemplateName())
TRY_TO(TraverseNestedNameSpecifier(DTN->getQualifier()));
@@ -729,9 +759,9 @@ bool RecursiveASTVisitor<Derived>::TraverseTemplateName(TemplateName Template) {
return true;
}
-template<typename Derived>
+template <typename Derived>
bool RecursiveASTVisitor<Derived>::TraverseTemplateArgument(
- const TemplateArgument &Arg) {
+ const TemplateArgument &Arg) {
switch (Arg.getKind()) {
case TemplateArgument::Null:
case TemplateArgument::Declaration:
@@ -745,7 +775,7 @@ bool RecursiveASTVisitor<Derived>::TraverseTemplateArgument(
case TemplateArgument::Template:
case TemplateArgument::TemplateExpansion:
return getDerived().TraverseTemplateName(
- Arg.getAsTemplateOrTemplatePattern());
+ Arg.getAsTemplateOrTemplatePattern());
case TemplateArgument::Expression:
return getDerived().TraverseStmt(Arg.getAsExpr());
@@ -760,9 +790,9 @@ bool RecursiveASTVisitor<Derived>::TraverseTemplateArgument(
// FIXME: no template name location?
// FIXME: no source locations for a template argument pack?
-template<typename Derived>
+template <typename Derived>
bool RecursiveASTVisitor<Derived>::TraverseTemplateArgumentLoc(
- const TemplateArgumentLoc &ArgLoc) {
+ const TemplateArgumentLoc &ArgLoc) {
const TemplateArgument &Arg = ArgLoc.getArgument();
switch (Arg.getKind()) {
@@ -784,9 +814,9 @@ bool RecursiveASTVisitor<Derived>::TraverseTemplateArgumentLoc(
case TemplateArgument::TemplateExpansion:
if (ArgLoc.getTemplateQualifierLoc())
TRY_TO(getDerived().TraverseNestedNameSpecifierLoc(
- ArgLoc.getTemplateQualifierLoc()));
+ ArgLoc.getTemplateQualifierLoc()));
return getDerived().TraverseTemplateName(
- Arg.getAsTemplateOrTemplatePattern());
+ Arg.getAsTemplateOrTemplatePattern());
case TemplateArgument::Expression:
return getDerived().TraverseStmt(ArgLoc.getSourceExpression());
@@ -799,10 +829,9 @@ bool RecursiveASTVisitor<Derived>::TraverseTemplateArgumentLoc(
return true;
}
-template<typename Derived>
+template <typename Derived>
bool RecursiveASTVisitor<Derived>::TraverseTemplateArguments(
- const TemplateArgument *Args,
- unsigned NumArgs) {
+ const TemplateArgument *Args, unsigned NumArgs) {
for (unsigned I = 0; I != NumArgs; ++I) {
TRY_TO(TraverseTemplateArgument(Args[I]));
}
@@ -810,9 +839,9 @@ bool RecursiveASTVisitor<Derived>::TraverseTemplateArguments(
return true;
}
-template<typename Derived>
+template <typename Derived>
bool RecursiveASTVisitor<Derived>::TraverseConstructorInitializer(
- CXXCtorInitializer *Init) {
+ CXXCtorInitializer *Init) {
if (TypeSourceInfo *TInfo = Init->getTypeSourceInfo())
TRY_TO(TraverseTypeLoc(TInfo->getTypeLoc()));
@@ -821,197 +850,164 @@ bool RecursiveASTVisitor<Derived>::TraverseConstructorInitializer(
return true;
}
-template<typename Derived>
-bool RecursiveASTVisitor<Derived>::TraverseLambdaCapture(
- LambdaExpr *LE, const LambdaExpr::Capture *C) {
+template <typename Derived>
+bool
+RecursiveASTVisitor<Derived>::TraverseLambdaCapture(LambdaExpr *LE,
+ const LambdaCapture *C) {
if (C->isInitCapture())
TRY_TO(TraverseDecl(C->getCapturedVar()));
return true;
}
-template<typename Derived>
+template <typename Derived>
bool RecursiveASTVisitor<Derived>::TraverseLambdaBody(LambdaExpr *LE) {
TRY_TO(TraverseStmt(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; \
+#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(BuiltinType, {})
-DEF_TRAVERSE_TYPE(ComplexType, {
- TRY_TO(TraverseType(T->getElementType()));
- })
+DEF_TRAVERSE_TYPE(ComplexType, { TRY_TO(TraverseType(T->getElementType())); })
-DEF_TRAVERSE_TYPE(PointerType, {
- TRY_TO(TraverseType(T->getPointeeType()));
- })
+DEF_TRAVERSE_TYPE(PointerType, { TRY_TO(TraverseType(T->getPointeeType())); })
-DEF_TRAVERSE_TYPE(BlockPointerType, {
- 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(LValueReferenceType,
+ { TRY_TO(TraverseType(T->getPointeeType())); })
-DEF_TRAVERSE_TYPE(RValueReferenceType, {
- 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()));
- })
+ TRY_TO(TraverseType(QualType(T->getClass(), 0)));
+ TRY_TO(TraverseType(T->getPointeeType()));
+})
-DEF_TRAVERSE_TYPE(DecayedType, {
- TRY_TO(TraverseType(T->getOriginalType()));
- })
+DEF_TRAVERSE_TYPE(AdjustedType, { TRY_TO(TraverseType(T->getOriginalType())); })
-DEF_TRAVERSE_TYPE(ConstantArrayType, {
- TRY_TO(TraverseType(T->getElementType()));
- })
+DEF_TRAVERSE_TYPE(DecayedType, { TRY_TO(TraverseType(T->getOriginalType())); })
-DEF_TRAVERSE_TYPE(IncompleteArrayType, {
- TRY_TO(TraverseType(T->getElementType()));
- })
+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()));
- })
+ 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()));
- })
+ 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()));
- })
+ 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(VectorType, { TRY_TO(TraverseType(T->getElementType())); })
-DEF_TRAVERSE_TYPE(ExtVectorType, {
- TRY_TO(TraverseType(T->getElementType()));
- })
+DEF_TRAVERSE_TYPE(ExtVectorType, { TRY_TO(TraverseType(T->getElementType())); })
-DEF_TRAVERSE_TYPE(FunctionNoProtoType, {
- TRY_TO(TraverseType(T->getResultType()));
- })
+DEF_TRAVERSE_TYPE(FunctionNoProtoType,
+ { TRY_TO(TraverseType(T->getReturnType())); })
DEF_TRAVERSE_TYPE(FunctionProtoType, {
- TRY_TO(TraverseType(T->getResultType()));
+ TRY_TO(TraverseType(T->getReturnType()));
- for (FunctionProtoType::arg_type_iterator A = T->arg_type_begin(),
- AEnd = T->arg_type_end();
- A != AEnd; ++A) {
- TRY_TO(TraverseType(*A));
- }
+ for (const auto &A : T->param_types()) {
+ TRY_TO(TraverseType(A));
+ }
- for (FunctionProtoType::exception_iterator E = T->exception_begin(),
- EEnd = T->exception_end();
- E != EEnd; ++E) {
- TRY_TO(TraverseType(*E));
- }
- })
+ for (const auto &E : T->exceptions()) {
+ TRY_TO(TraverseType(E));
+ }
+})
-DEF_TRAVERSE_TYPE(UnresolvedUsingType, { })
-DEF_TRAVERSE_TYPE(TypedefType, { })
+DEF_TRAVERSE_TYPE(UnresolvedUsingType, {})
+DEF_TRAVERSE_TYPE(TypedefType, {})
-DEF_TRAVERSE_TYPE(TypeOfExprType, {
- TRY_TO(TraverseStmt(T->getUnderlyingExpr()));
- })
+DEF_TRAVERSE_TYPE(TypeOfExprType,
+ { TRY_TO(TraverseStmt(T->getUnderlyingExpr())); })
-DEF_TRAVERSE_TYPE(TypeOfType, {
- TRY_TO(TraverseType(T->getUnderlyingType()));
- })
+DEF_TRAVERSE_TYPE(TypeOfType, { TRY_TO(TraverseType(T->getUnderlyingType())); })
-DEF_TRAVERSE_TYPE(DecltypeType, {
- TRY_TO(TraverseStmt(T->getUnderlyingExpr()));
- })
+DEF_TRAVERSE_TYPE(DecltypeType,
+ { TRY_TO(TraverseStmt(T->getUnderlyingExpr())); })
DEF_TRAVERSE_TYPE(UnaryTransformType, {
- TRY_TO(TraverseType(T->getBaseType()));
- TRY_TO(TraverseType(T->getUnderlyingType()));
- })
+ TRY_TO(TraverseType(T->getBaseType()));
+ TRY_TO(TraverseType(T->getUnderlyingType()));
+})
-DEF_TRAVERSE_TYPE(AutoType, {
- TRY_TO(TraverseType(T->getDeducedType()));
- })
+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(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()));
- })
+ TRY_TO(TraverseTemplateName(T->getTemplateName()));
+ TRY_TO(TraverseTemplateArguments(T->getArgs(), T->getNumArgs()));
+})
-DEF_TRAVERSE_TYPE(InjectedClassNameType, { })
+DEF_TRAVERSE_TYPE(InjectedClassNameType, {})
-DEF_TRAVERSE_TYPE(AttributedType, {
- TRY_TO(TraverseType(T->getModifiedType()));
- })
+DEF_TRAVERSE_TYPE(AttributedType,
+ { TRY_TO(TraverseType(T->getModifiedType())); })
-DEF_TRAVERSE_TYPE(ParenType, {
- TRY_TO(TraverseType(T->getInnerType()));
- })
+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, {
+ 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()));
- })
+ TRY_TO(TraverseNestedNameSpecifier(T->getQualifier()));
+ TRY_TO(TraverseTemplateArguments(T->getArgs(), T->getNumArgs()));
+})
-DEF_TRAVERSE_TYPE(PackExpansionType, {
- TRY_TO(TraverseType(T->getPattern()));
- })
+DEF_TRAVERSE_TYPE(PackExpansionType, { TRY_TO(TraverseType(T->getPattern())); })
-DEF_TRAVERSE_TYPE(ObjCInterfaceType, { })
+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()));
- })
+ // We have to watch out here because an ObjCInterfaceType's base
+ // type is itself.
+ if (T->getBaseType().getTypePtr() != T)
+ TRY_TO(TraverseType(T->getBaseType()));
+})
-DEF_TRAVERSE_TYPE(ObjCObjectPointerType, {
- TRY_TO(TraverseType(T->getPointeeType()));
- })
+DEF_TRAVERSE_TYPE(ObjCObjectPointerType,
+ { TRY_TO(TraverseType(T->getPointeeType())); })
-DEF_TRAVERSE_TYPE(AtomicType, {
- TRY_TO(TraverseType(T->getValueType()));
- })
+DEF_TRAVERSE_TYPE(AtomicType, { TRY_TO(TraverseType(T->getValueType())); })
#undef DEF_TRAVERSE_TYPE
@@ -1022,19 +1018,19 @@ DEF_TRAVERSE_TYPE(AtomicType, {
// 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) {
+#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
@@ -1053,42 +1049,40 @@ bool RecursiveASTVisitor<Derived>::TraverseQualifiedTypeLoc(
return TraverseTypeLoc(TL.getUnqualifiedLoc());
}
-DEF_TRAVERSE_TYPELOC(BuiltinType, { })
+DEF_TRAVERSE_TYPELOC(BuiltinType, {})
// FIXME: ComplexTypeLoc is unfinished
DEF_TRAVERSE_TYPELOC(ComplexType, {
- TRY_TO(TraverseType(TL.getTypePtr()->getElementType()));
- })
+ TRY_TO(TraverseType(TL.getTypePtr()->getElementType()));
+})
-DEF_TRAVERSE_TYPELOC(PointerType, {
- TRY_TO(TraverseTypeLoc(TL.getPointeeLoc()));
- })
+DEF_TRAVERSE_TYPELOC(PointerType,
+ { TRY_TO(TraverseTypeLoc(TL.getPointeeLoc())); })
-DEF_TRAVERSE_TYPELOC(BlockPointerType, {
- 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(LValueReferenceType,
+ { TRY_TO(TraverseTypeLoc(TL.getPointeeLoc())); })
-DEF_TRAVERSE_TYPELOC(RValueReferenceType, {
- 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()));
- })
+ TRY_TO(TraverseType(QualType(TL.getTypePtr()->getClass(), 0)));
+ TRY_TO(TraverseTypeLoc(TL.getPointeeLoc()));
+})
-DEF_TRAVERSE_TYPELOC(DecayedType, {
- TRY_TO(TraverseTypeLoc(TL.getOriginalLoc()));
- })
+DEF_TRAVERSE_TYPELOC(AdjustedType,
+ { TRY_TO(TraverseTypeLoc(TL.getOriginalLoc())); })
+
+DEF_TRAVERSE_TYPELOC(DecayedType,
+ { TRY_TO(TraverseTypeLoc(TL.getOriginalLoc())); })
-template<typename Derived>
+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()));
@@ -1096,158 +1090,147 @@ bool RecursiveASTVisitor<Derived>::TraverseArrayTypeLocHelper(ArrayTypeLoc TL) {
}
DEF_TRAVERSE_TYPELOC(ConstantArrayType, {
- TRY_TO(TraverseTypeLoc(TL.getElementLoc()));
- return TraverseArrayTypeLocHelper(TL);
- })
+ TRY_TO(TraverseTypeLoc(TL.getElementLoc()));
+ return TraverseArrayTypeLocHelper(TL);
+})
DEF_TRAVERSE_TYPELOC(IncompleteArrayType, {
- TRY_TO(TraverseTypeLoc(TL.getElementLoc()));
- return TraverseArrayTypeLocHelper(TL);
- })
+ TRY_TO(TraverseTypeLoc(TL.getElementLoc()));
+ return TraverseArrayTypeLocHelper(TL);
+})
DEF_TRAVERSE_TYPELOC(VariableArrayType, {
- TRY_TO(TraverseTypeLoc(TL.getElementLoc()));
- return TraverseArrayTypeLocHelper(TL);
- })
+ TRY_TO(TraverseTypeLoc(TL.getElementLoc()));
+ return TraverseArrayTypeLocHelper(TL);
+})
DEF_TRAVERSE_TYPELOC(DependentSizedArrayType, {
- TRY_TO(TraverseTypeLoc(TL.getElementLoc()));
- return TraverseArrayTypeLocHelper(TL);
- })
+ 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()));
- })
+ 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()));
- })
+ 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()));
- })
+ TRY_TO(TraverseType(TL.getTypePtr()->getElementType()));
+})
-DEF_TRAVERSE_TYPELOC(FunctionNoProtoType, {
- TRY_TO(TraverseTypeLoc(TL.getResultLoc()));
- })
+DEF_TRAVERSE_TYPELOC(FunctionNoProtoType,
+ { TRY_TO(TraverseTypeLoc(TL.getReturnLoc())); })
// FIXME: location of exception specifications (attributes?)
DEF_TRAVERSE_TYPELOC(FunctionProtoType, {
- TRY_TO(TraverseTypeLoc(TL.getResultLoc()));
+ TRY_TO(TraverseTypeLoc(TL.getReturnLoc()));
- const FunctionProtoType *T = TL.getTypePtr();
+ const FunctionProtoType *T = TL.getTypePtr();
- for (unsigned I = 0, E = TL.getNumArgs(); I != E; ++I) {
- if (TL.getArg(I)) {
- TRY_TO(TraverseDecl(TL.getArg(I)));
- } else if (I < T->getNumArgs()) {
- TRY_TO(TraverseType(T->getArgType(I)));
- }
+ 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 (FunctionProtoType::exception_iterator E = T->exception_begin(),
- EEnd = T->exception_end();
- E != EEnd; ++E) {
- TRY_TO(TraverseType(*E));
- }
- })
+ for (const auto &E : T->exceptions()) {
+ TRY_TO(TraverseType(E));
+ }
+})
-DEF_TRAVERSE_TYPELOC(UnresolvedUsingType, { })
-DEF_TRAVERSE_TYPELOC(TypedefType, { })
+DEF_TRAVERSE_TYPELOC(UnresolvedUsingType, {})
+DEF_TRAVERSE_TYPELOC(TypedefType, {})
-DEF_TRAVERSE_TYPELOC(TypeOfExprType, {
- TRY_TO(TraverseStmt(TL.getUnderlyingExpr()));
- })
+DEF_TRAVERSE_TYPELOC(TypeOfExprType,
+ { TRY_TO(TraverseStmt(TL.getUnderlyingExpr())); })
DEF_TRAVERSE_TYPELOC(TypeOfType, {
- TRY_TO(TraverseTypeLoc(TL.getUnderlyingTInfo()->getTypeLoc()));
- })
+ TRY_TO(TraverseTypeLoc(TL.getUnderlyingTInfo()->getTypeLoc()));
+})
// FIXME: location of underlying expr
DEF_TRAVERSE_TYPELOC(DecltypeType, {
- TRY_TO(TraverseStmt(TL.getTypePtr()->getUnderlyingExpr()));
- })
+ TRY_TO(TraverseStmt(TL.getTypePtr()->getUnderlyingExpr()));
+})
DEF_TRAVERSE_TYPELOC(UnaryTransformType, {
- TRY_TO(TraverseTypeLoc(TL.getUnderlyingTInfo()->getTypeLoc()));
- })
+ TRY_TO(TraverseTypeLoc(TL.getUnderlyingTInfo()->getTypeLoc()));
+})
DEF_TRAVERSE_TYPELOC(AutoType, {
- TRY_TO(TraverseType(TL.getTypePtr()->getDeducedType()));
- })
+ 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, { })
+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)));
- }
- })
+ 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(InjectedClassNameType, {})
-DEF_TRAVERSE_TYPELOC(ParenType, {
- TRY_TO(TraverseTypeLoc(TL.getInnerLoc()));
- })
+DEF_TRAVERSE_TYPELOC(ParenType, { TRY_TO(TraverseTypeLoc(TL.getInnerLoc())); })
-DEF_TRAVERSE_TYPELOC(AttributedType, {
- TRY_TO(TraverseTypeLoc(TL.getModifiedLoc()));
- })
+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()));
- })
+ if (TL.getQualifierLoc()) {
+ TRY_TO(TraverseNestedNameSpecifierLoc(TL.getQualifierLoc()));
+ }
+ TRY_TO(TraverseTypeLoc(TL.getNamedTypeLoc()));
+})
DEF_TRAVERSE_TYPELOC(DependentNameType, {
- TRY_TO(TraverseNestedNameSpecifierLoc(TL.getQualifierLoc()));
- })
+ TRY_TO(TraverseNestedNameSpecifierLoc(TL.getQualifierLoc()));
+})
DEF_TRAVERSE_TYPELOC(DependentTemplateSpecializationType, {
- if (TL.getQualifierLoc()) {
- TRY_TO(TraverseNestedNameSpecifierLoc(TL.getQualifierLoc()));
- }
+ if (TL.getQualifierLoc()) {
+ TRY_TO(TraverseNestedNameSpecifierLoc(TL.getQualifierLoc()));
+ }
- for (unsigned I = 0, E = TL.getNumArgs(); I != E; ++I) {
- TRY_TO(TraverseTemplateArgumentLoc(TL.getArgLoc(I)));
- }
- })
+ 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(PackExpansionType,
+ { TRY_TO(TraverseTypeLoc(TL.getPatternLoc())); })
-DEF_TRAVERSE_TYPELOC(ObjCInterfaceType, { })
+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()));
- })
+ // We have to watch out here because an ObjCInterfaceType's base
+ // type is itself.
+ if (TL.getTypePtr()->getBaseType().getTypePtr() != TL.getTypePtr())
+ TRY_TO(TraverseTypeLoc(TL.getBaseLoc()));
+})
-DEF_TRAVERSE_TYPELOC(ObjCObjectPointerType, {
- TRY_TO(TraverseTypeLoc(TL.getPointeeLoc()));
- })
+DEF_TRAVERSE_TYPELOC(ObjCObjectPointerType,
+ { TRY_TO(TraverseTypeLoc(TL.getPointeeLoc())); })
-DEF_TRAVERSE_TYPELOC(AtomicType, {
- TRY_TO(TraverseTypeLoc(TL.getValueLoc()));
- })
+DEF_TRAVERSE_TYPELOC(AtomicType, { TRY_TO(TraverseTypeLoc(TL.getValueLoc())); })
#undef DEF_TRAVERSE_TYPELOC
@@ -1258,195 +1241,191 @@ DEF_TRAVERSE_TYPELOC(AtomicType, {
// Therefore each Traverse* only needs to worry about children other
// than those.
-template<typename Derived>
+template <typename Derived>
bool RecursiveASTVisitor<Derived>::TraverseDeclContextHelper(DeclContext *DC) {
if (!DC)
return true;
- for (DeclContext::decl_iterator Child = DC->decls_begin(),
- ChildEnd = DC->decls_end();
- Child != ChildEnd; ++Child) {
+ 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));
+ 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; \
-}
+#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(AccessSpecDecl, {})
DEF_TRAVERSE_DECL(BlockDecl, {
- if (TypeSourceInfo *TInfo = D->getSignatureAsWritten())
- TRY_TO(TraverseTypeLoc(TInfo->getTypeLoc()));
- 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;
- })
+ 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;
- })
+ 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(EmptyDecl, {})
-DEF_TRAVERSE_DECL(FileScopeAsmDecl, {
- TRY_TO(TraverseStmt(D->getAsmString()));
- })
+DEF_TRAVERSE_DECL(FileScopeAsmDecl,
+ { TRY_TO(TraverseStmt(D->getAsmString())); })
-DEF_TRAVERSE_DECL(ImportDecl, { })
+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()));
- })
+ // 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));
- }
+ 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()));
+ TRY_TO(TraverseDecl(D->getSpecialization()));
- if (D->hasExplicitTemplateArgs()) {
- const TemplateArgumentListInfo& args = D->templateArgs();
- TRY_TO(TraverseTemplateArgumentLocsHelper(
- args.getArgumentArray(), args.size()));
- }
- })
+ if (D->hasExplicitTemplateArgs()) {
+ const TemplateArgumentListInfo &args = D->templateArgs();
+ TRY_TO(TraverseTemplateArgumentLocsHelper(args.getArgumentArray(),
+ args.size()));
+ }
+})
-DEF_TRAVERSE_DECL(LinkageSpecDecl, { })
+DEF_TRAVERSE_DECL(LinkageSpecDecl, {})
-DEF_TRAVERSE_DECL(ObjCPropertyImplDecl, {
- // FIXME: implement this
- })
+DEF_TRAVERSE_DECL(ObjCPropertyImplDecl, {// FIXME: implement this
+ })
DEF_TRAVERSE_DECL(StaticAssertDecl, {
- TRY_TO(TraverseStmt(D->getAssertExpr()));
- TRY_TO(TraverseStmt(D->getMessage()));
- })
+ 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(
+ TranslationUnitDecl,
+ {// Code in an unnamed namespace shows up automatically in
+ // decls_begin()/decls_end(). Thus we don't need to recurse on
+ // D->getAnonymousNamespace().
+ })
DEF_TRAVERSE_DECL(NamespaceAliasDecl, {
- // We shouldn't traverse an aliased namespace, since it will be
- // defined (and, therefore, traversed) somewhere else.
- //
- // This return statement makes sure the traversal of nodes in
- // decls_begin()/decls_end() (done in the DEF_TRAVERSE_DECL macro)
- // is skipped - don't remove it.
- return true;
- })
-
-DEF_TRAVERSE_DECL(LabelDecl, {
- // There is no code in a LabelDecl.
+ // 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(
+ 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(ObjCCompatibleAliasDecl, {// FIXME: implement
+ })
-DEF_TRAVERSE_DECL(ObjCCategoryDecl, {
- // FIXME: implement
- })
+DEF_TRAVERSE_DECL(ObjCCategoryDecl, {// FIXME: implement
+ })
-DEF_TRAVERSE_DECL(ObjCCategoryImplDecl, {
- // FIXME: implement
- })
+DEF_TRAVERSE_DECL(ObjCCategoryImplDecl, {// FIXME: implement
+ })
-DEF_TRAVERSE_DECL(ObjCImplementationDecl, {
- // FIXME: implement
- })
+DEF_TRAVERSE_DECL(ObjCImplementationDecl, {// FIXME: implement
+ })
-DEF_TRAVERSE_DECL(ObjCInterfaceDecl, {
- // FIXME: implement
- })
+DEF_TRAVERSE_DECL(ObjCInterfaceDecl, {// FIXME: implement
+ })
-DEF_TRAVERSE_DECL(ObjCProtocolDecl, {
- // FIXME: implement
- })
+DEF_TRAVERSE_DECL(ObjCProtocolDecl, {// FIXME: implement
+ })
DEF_TRAVERSE_DECL(ObjCMethodDecl, {
- if (D->getResultTypeSourceInfo()) {
- TRY_TO(TraverseTypeLoc(D->getResultTypeSourceInfo()->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;
- })
+ 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(ObjCPropertyDecl, {
- // FIXME: implement
- })
+ 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()));
- })
+ TRY_TO(TraverseNestedNameSpecifierLoc(D->getQualifierLoc()));
+ TRY_TO(TraverseDeclarationNameInfo(D->getNameInfo()));
+})
DEF_TRAVERSE_DECL(UsingDirectiveDecl, {
- TRY_TO(TraverseNestedNameSpecifierLoc(D->getQualifierLoc()));
- })
+ TRY_TO(TraverseNestedNameSpecifierLoc(D->getQualifierLoc()));
+})
-DEF_TRAVERSE_DECL(UsingShadowDecl, { })
+DEF_TRAVERSE_DECL(UsingShadowDecl, {})
DEF_TRAVERSE_DECL(OMPThreadPrivateDecl, {
- for (OMPThreadPrivateDecl::varlist_iterator I = D->varlist_begin(),
- E = D->varlist_end();
- I != E; ++I) {
- TRY_TO(TraverseStmt(*I));
- }
- })
+ for (auto *I : D->varlists()) {
+ TRY_TO(TraverseStmt(I));
+ }
+})
// A helper method for TemplateDecl's children.
-template<typename Derived>
+template <typename Derived>
bool RecursiveASTVisitor<Derived>::TraverseTemplateParameterListHelper(
TemplateParameterList *TPL) {
if (TPL) {
@@ -1458,65 +1437,84 @@ bool RecursiveASTVisitor<Derived>::TraverseTemplateParameterListHelper(
return true;
}
-#define DEF_TRAVERSE_TMPL_INST(TMPLDECLKIND) \
-/* A helper method for traversing the implicit instantiations of a
- class or variable template. */ \
-template<typename Derived> \
-bool RecursiveASTVisitor<Derived>::TraverseTemplateInstantiations( \
- TMPLDECLKIND##TemplateDecl *D) { \
- TMPLDECLKIND##TemplateDecl::spec_iterator end = D->spec_end(); \
- for (TMPLDECLKIND##TemplateDecl::spec_iterator it = D->spec_begin(); \
- it != end; ++it) { \
- TMPLDECLKIND##TemplateSpecializationDecl* SD = *it; \
- \
- switch (SD->getSpecializationKind()) { \
- /* Visit the implicit instantiations with the requested pattern. */ \
- case TSK_Undeclared: \
- case TSK_ImplicitInstantiation: \
- TRY_TO(TraverseDecl(SD)); \
- break; \
- \
- /* We don't need to do anything on an explicit instantiation
- or explicit specialization because there will be an explicit
- node for it elsewhere. */ \
- case TSK_ExplicitInstantiationDeclaration: \
- case TSK_ExplicitInstantiationDefinition: \
- case TSK_ExplicitSpecialization: \
- break; \
- } \
- } \
- \
- 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;
}
-
-DEF_TRAVERSE_TMPL_INST(Class)
-DEF_TRAVERSE_TMPL_INST(Var)
// A helper method for traversing the instantiations of a
// function while skipping its specializations.
-template<typename Derived>
+template <typename Derived>
bool RecursiveASTVisitor<Derived>::TraverseTemplateInstantiations(
FunctionTemplateDecl *D) {
- FunctionTemplateDecl::spec_iterator end = D->spec_end();
- for (FunctionTemplateDecl::spec_iterator it = D->spec_begin(); it != end;
- ++it) {
- FunctionDecl* FD = *it;
- switch (FD->getTemplateSpecializationKind()) {
- case TSK_Undeclared:
- case TSK_ImplicitInstantiation:
- // We don't know what kind of FunctionDecl this is.
- TRY_TO(TraverseDecl(FD));
- 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(FD));
- break;
-
- case TSK_ExplicitSpecialization:
- break;
+ 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;
+ }
}
}
@@ -1525,24 +1523,24 @@ bool RecursiveASTVisitor<Derived>::TraverseTemplateInstantiations(
// 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. */ \
+#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)
@@ -1550,65 +1548,63 @@ 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()));
- })
+ // 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(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()));
- })
+ // 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.
- })
+ 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.
- })
+ 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()));
- })
+ 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.
- })
+ // 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().
- })
+ 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) {
+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.
@@ -1616,16 +1612,13 @@ bool RecursiveASTVisitor<Derived>::TraverseRecordHelper(
return true;
}
-template<typename Derived>
-bool RecursiveASTVisitor<Derived>::TraverseCXXRecordHelper(
- CXXRecordDecl *D) {
+template <typename Derived>
+bool RecursiveASTVisitor<Derived>::TraverseCXXRecordHelper(CXXRecordDecl *D) {
if (!TraverseRecordHelper(D))
return false;
if (D->isCompleteDefinition()) {
- for (CXXRecordDecl::base_class_iterator I = D->bases_begin(),
- E = D->bases_end();
- I != E; ++I) {
- TRY_TO(TraverseTypeLoc(I->getTypeSourceInfo()->getTypeLoc()));
+ 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().
@@ -1633,34 +1626,30 @@ bool RecursiveASTVisitor<Derived>::TraverseCXXRecordHelper(
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_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)
@@ -1675,45 +1664,43 @@ bool RecursiveASTVisitor<Derived>::TraverseTemplateArgumentLocsHelper(
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. */ \
+#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(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()));
- })
+ // 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>
+template <typename Derived>
bool RecursiveASTVisitor<Derived>::TraverseDeclaratorHelper(DeclaratorDecl *D) {
TRY_TO(TraverseNestedNameSpecifierLoc(D->getQualifierLoc()));
if (D->getTypeSourceInfo())
@@ -1723,33 +1710,31 @@ bool RecursiveASTVisitor<Derived>::TraverseDeclaratorHelper(DeclaratorDecl *D) {
return true;
}
-DEF_TRAVERSE_DECL(MSPropertyDecl, {
- TRY_TO(TraverseDeclaratorHelper(D));
- })
+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()));
- })
+ 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.
- })
+ 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.
- })
+ TRY_TO(TraverseDeclaratorHelper(D));
+ if (D->isBitField())
+ TRY_TO(TraverseStmt(D->getBitWidth()));
+ // FIXME: implement the rest.
+})
-template<typename Derived>
+template <typename Derived>
bool RecursiveASTVisitor<Derived>::TraverseFunctionHelper(FunctionDecl *D) {
TRY_TO(TraverseNestedNameSpecifierLoc(D->getQualifierLoc()));
TRY_TO(TraverseDeclarationNameInfo(D->getNameInfo()));
@@ -1760,13 +1745,13 @@ bool RecursiveASTVisitor<Derived>::TraverseFunctionHelper(FunctionDecl *D) {
// 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()) {
+ 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) {
+ FTSI->TemplateArgumentsAsWritten) {
TRY_TO(TraverseTemplateArgumentLocsHelper(TALI->getTemplateArgs(),
TALI->NumTemplateArgs));
}
@@ -1785,58 +1770,57 @@ bool RecursiveASTVisitor<Derived>::TraverseFunctionHelper(FunctionDecl *D) {
// 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)
+ E = D->param_end();
+ I != E; ++I)
TRY_TO(TraverseDecl(*I));
}
if (CXXConstructorDecl *Ctor = dyn_cast<CXXConstructorDecl>(D)) {
// Constructor initializers.
- for (CXXConstructorDecl::init_iterator I = Ctor->init_begin(),
- E = Ctor->init_end();
- I != E; ++I) {
- TRY_TO(TraverseConstructorInitializer(*I));
+ for (auto *I : Ctor->inits()) {
+ TRY_TO(TraverseConstructorInitializer(I));
}
}
if (D->isThisDeclarationADefinition()) {
- TRY_TO(TraverseStmt(D->getBody())); // Function body.
+ 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);
- })
+ // 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);
- })
+ // 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);
- })
+ // 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);
- })
+ // 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);
- })
+ // We skip decls_begin/decls_end, which are already covered by
+ // TraverseFunctionHelper().
+ return TraverseFunctionHelper(D);
+})
-template<typename Derived>
+template <typename Derived>
bool RecursiveASTVisitor<Derived>::TraverseVarHelper(VarDecl *D) {
TRY_TO(TraverseDeclaratorHelper(D));
// Default params are taken care of when we traverse the ParmVarDecl.
@@ -1846,34 +1830,28 @@ bool RecursiveASTVisitor<Derived>::TraverseVarHelper(VarDecl *D) {
return true;
}
-DEF_TRAVERSE_DECL(VarDecl, {
- TRY_TO(TraverseVarHelper(D));
- })
+DEF_TRAVERSE_DECL(VarDecl, { TRY_TO(TraverseVarHelper(D)); })
-DEF_TRAVERSE_DECL(ImplicitParamDecl, {
- 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()));
- })
+ // 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));
+ 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->getUninstantiatedDefaultArg()));
- if (D->hasDefaultArg() &&
- !D->hasUninstantiatedDefaultArg() &&
- !D->hasUnparsedDefaultArg())
- TRY_TO(TraverseStmt(D->getDefaultArg()));
- })
+ if (D->hasDefaultArg() && !D->hasUninstantiatedDefaultArg() &&
+ !D->hasUnparsedDefaultArg())
+ TRY_TO(TraverseStmt(D->getDefaultArg()));
+})
#undef DEF_TRAVERSE_DECL
@@ -1887,78 +1865,77 @@ DEF_TRAVERSE_DECL(ParmVarDecl, {
// http://clang.llvm.org/doxygen/Stmt_8cpp_source.html
// This macro makes available a variable S, the passed-in stmt.
-#define DEF_TRAVERSE_STMT(STMT, CODE) \
-template<typename Derived> \
-bool RecursiveASTVisitor<Derived>::Traverse##STMT (STMT *S) { \
- TRY_TO(WalkUpFrom##STMT(S)); \
- { CODE; } \
- for (Stmt::child_range range = S->children(); range; ++range) { \
- TRY_TO(TraverseStmt(*range)); \
- } \
- return true; \
-}
+#define DEF_TRAVERSE_STMT(STMT, CODE) \
+ template <typename Derived> \
+ bool RecursiveASTVisitor<Derived>::Traverse##STMT(STMT *S) { \
+ TRY_TO(WalkUpFrom##STMT(S)); \
+ { CODE; } \
+ for (Stmt::child_range range = S->children(); range; ++range) { \
+ TRY_TO(TraverseStmt(*range)); \
+ } \
+ return true; \
+ }
DEF_TRAVERSE_STMT(GCCAsmStmt, {
- TRY_TO(TraverseStmt(S->getAsmString()));
- for (unsigned I = 0, E = S->getNumInputs(); I < E; ++I) {
- TRY_TO(TraverseStmt(S->getInputConstraintLiteral(I)));
- }
- for (unsigned I = 0, E = S->getNumOutputs(); I < E; ++I) {
- TRY_TO(TraverseStmt(S->getOutputConstraintLiteral(I)));
- }
- for (unsigned I = 0, E = S->getNumClobbers(); I < E; ++I) {
- TRY_TO(TraverseStmt(S->getClobberStringLiteral(I)));
- }
- // children() iterates over inputExpr and outputExpr.
- })
+ TRY_TO(TraverseStmt(S->getAsmString()));
+ for (unsigned I = 0, E = S->getNumInputs(); I < E; ++I) {
+ TRY_TO(TraverseStmt(S->getInputConstraintLiteral(I)));
+ }
+ for (unsigned I = 0, E = S->getNumOutputs(); I < E; ++I) {
+ TRY_TO(TraverseStmt(S->getOutputConstraintLiteral(I)));
+ }
+ for (unsigned I = 0, E = S->getNumClobbers(); I < E; ++I) {
+ TRY_TO(TraverseStmt(S->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(
+ 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.
- })
+ TRY_TO(TraverseDecl(S->getExceptionDecl()));
+ // children() iterates over the handler block.
+})
DEF_TRAVERSE_STMT(DeclStmt, {
- for (DeclStmt::decl_iterator I = S->decl_begin(), E = S->decl_end();
- I != E; ++I) {
- TRY_TO(TraverseDecl(*I));
- }
- // Suppress the default iteration over children() by
- // returning. Here's why: A DeclStmt looks like 'type var [=
- // initializer]'. The decls above already traverse over the
- // initializers, so we don't have to do it again (which
- // children() would do).
- return true;
- })
-
+ 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(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(TraverseStmt(S->getLoopVarStmt()));
@@ -1969,82 +1946,82 @@ DEF_TRAVERSE_STMT(CXXForRangeStmt, {
}
})
DEF_TRAVERSE_STMT(MSDependentExistsStmt, {
- TRY_TO(TraverseNestedNameSpecifierLoc(S->getQualifierLoc()));
- TRY_TO(TraverseDeclarationNameInfo(S->getNameInfo()));
+ 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(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()));
- }
- })
+ 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()));
- })
+ 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->getExplicitTemplateArgs().getTemplateArgs(),
- S->getNumTemplateArgs()));
- }
- })
+ TRY_TO(TraverseNestedNameSpecifierLoc(S->getQualifierLoc()));
+ TRY_TO(TraverseDeclarationNameInfo(S->getNameInfo()));
+ if (S->hasExplicitTemplateArgs()) {
+ TRY_TO(TraverseTemplateArgumentLocsHelper(
+ S->getExplicitTemplateArgs().getTemplateArgs(),
+ S->getNumTemplateArgs()));
+ }
+})
DEF_TRAVERSE_STMT(MemberExpr, {
- TRY_TO(TraverseNestedNameSpecifierLoc(S->getQualifierLoc()));
- TRY_TO(TraverseDeclarationNameInfo(S->getMemberNameInfo()));
- TRY_TO(TraverseTemplateArgumentLocsHelper(
- S->getTemplateArgs(), S->getNumTemplateArgs()));
- })
+ 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(
+ 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()));
- })
+ TRY_TO(TraverseTypeLoc(S->getTypeInfoAsWritten()->getTypeLoc()));
+})
DEF_TRAVERSE_STMT(CXXFunctionalCastExpr, {
- TRY_TO(TraverseTypeLoc(S->getTypeInfoAsWritten()->getTypeLoc()));
- })
+ TRY_TO(TraverseTypeLoc(S->getTypeInfoAsWritten()->getTypeLoc()));
+})
DEF_TRAVERSE_STMT(CXXConstCastExpr, {
- TRY_TO(TraverseTypeLoc(S->getTypeInfoAsWritten()->getTypeLoc()));
- })
+ TRY_TO(TraverseTypeLoc(S->getTypeInfoAsWritten()->getTypeLoc()));
+})
DEF_TRAVERSE_STMT(CXXDynamicCastExpr, {
- TRY_TO(TraverseTypeLoc(S->getTypeInfoAsWritten()->getTypeLoc()));
- })
+ TRY_TO(TraverseTypeLoc(S->getTypeInfoAsWritten()->getTypeLoc()));
+})
DEF_TRAVERSE_STMT(CXXReinterpretCastExpr, {
- TRY_TO(TraverseTypeLoc(S->getTypeInfoAsWritten()->getTypeLoc()));
- })
+ TRY_TO(TraverseTypeLoc(S->getTypeInfoAsWritten()->getTypeLoc()));
+})
DEF_TRAVERSE_STMT(CXXStaticCastExpr, {
- TRY_TO(TraverseTypeLoc(S->getTypeInfoAsWritten()->getTypeLoc()));
- })
+ TRY_TO(TraverseTypeLoc(S->getTypeInfoAsWritten()->getTypeLoc()));
+})
// InitListExpr is a tricky one, because we want to do all our work on
// the syntactic form of the listexpr, but this method takes the
// semantic form by default. We can't use the macro helper because it
// calls WalkUp*() on the semantic form, before our code can convert
// to the syntactic form.
-template<typename Derived>
+template <typename Derived>
bool RecursiveASTVisitor<Derived>::TraverseInitListExpr(InitListExpr *S) {
if (InitListExpr *Syn = S->getSyntacticForm())
S = Syn;
@@ -2059,9 +2036,9 @@ bool RecursiveASTVisitor<Derived>::TraverseInitListExpr(InitListExpr *S) {
// GenericSelectionExpr is a special case because the types and expressions
// are interleaved. We also need to watch out for null types (default
// generic associations).
-template<typename Derived>
-bool RecursiveASTVisitor<Derived>::
-TraverseGenericSelectionExpr(GenericSelectionExpr *S) {
+template <typename Derived>
+bool RecursiveASTVisitor<Derived>::TraverseGenericSelectionExpr(
+ GenericSelectionExpr *S) {
TRY_TO(WalkUpFromGenericSelectionExpr(S));
TRY_TO(TraverseStmt(S->getControllingExpr()));
for (unsigned i = 0; i != S->getNumAssocs(); ++i) {
@@ -2074,13 +2051,14 @@ TraverseGenericSelectionExpr(GenericSelectionExpr *S) {
// PseudoObjectExpr is a special case because of the wierdness with
// syntactic expressions and opaque values.
-template<typename Derived>
-bool RecursiveASTVisitor<Derived>::
-TraversePseudoObjectExpr(PseudoObjectExpr *S) {
+template <typename Derived>
+bool
+RecursiveASTVisitor<Derived>::TraversePseudoObjectExpr(PseudoObjectExpr *S) {
TRY_TO(WalkUpFromPseudoObjectExpr(S));
TRY_TO(TraverseStmt(S->getSyntacticForm()));
- for (PseudoObjectExpr::semantics_iterator
- i = S->semantics_begin(), e = S->semantics_end(); i != e; ++i) {
+ 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();
@@ -2090,57 +2068,48 @@ TraversePseudoObjectExpr(PseudoObjectExpr *S) {
}
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()));
- })
+ // 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()));
- })
+ // 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()));
- })
+ // 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()));
- })
+ // 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(CXXUuidofExpr, {
- // The child-iterator will pick up the arg if it's an expression,
- // but not if it's a type.
- if (S->isTypeOperand())
- TRY_TO(TraverseTypeLoc(S->getTypeOperandSourceInfo()->getTypeLoc()));
- })
-
-DEF_TRAVERSE_STMT(UnaryTypeTraitExpr, {
- TRY_TO(TraverseTypeLoc(S->getQueriedTypeSourceInfo()->getTypeLoc()));
- })
-
-DEF_TRAVERSE_STMT(BinaryTypeTraitExpr, {
- TRY_TO(TraverseTypeLoc(S->getLhsTypeSourceInfo()->getTypeLoc()));
- TRY_TO(TraverseTypeLoc(S->getRhsTypeSourceInfo()->getTypeLoc()));
- })
+ // 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)
@@ -2148,30 +2117,29 @@ DEF_TRAVERSE_STMT(TypeTraitExpr, {
})
DEF_TRAVERSE_STMT(ArrayTypeTraitExpr, {
- TRY_TO(TraverseTypeLoc(S->getQueriedTypeSourceInfo()->getTypeLoc()));
- })
+ TRY_TO(TraverseTypeLoc(S->getQueriedTypeSourceInfo()->getTypeLoc()));
+})
-DEF_TRAVERSE_STMT(ExpressionTraitExpr, {
- TRY_TO(TraverseStmt(S->getQueriedExpression()));
- })
+DEF_TRAVERSE_STMT(ExpressionTraitExpr,
+ { TRY_TO(TraverseStmt(S->getQueriedExpression())); })
DEF_TRAVERSE_STMT(VAArgExpr, {
- // The child-iterator will pick up the expression argument.
- TRY_TO(TraverseTypeLoc(S->getWrittenTypeInfo()->getTypeLoc()));
- })
+ // 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()));
- })
+ // 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.
-template<typename Derived>
+// Walk only the visible parts of lambda expressions.
+template <typename Derived>
bool RecursiveASTVisitor<Derived>::TraverseLambdaExpr(LambdaExpr *S) {
TRY_TO(WalkUpFromLambdaExpr(S));
for (LambdaExpr::capture_iterator C = S->explicit_capture_begin(),
- CEnd = S->explicit_capture_end();
+ CEnd = S->explicit_capture_end();
C != CEnd; ++C) {
TRY_TO(TraverseLambdaCapture(S, C));
}
@@ -2184,12 +2152,12 @@ bool RecursiveASTVisitor<Derived>::TraverseLambdaExpr(LambdaExpr *S) {
} else if (FunctionProtoTypeLoc Proto = TL.getAs<FunctionProtoTypeLoc>()) {
if (S->hasExplicitParameters()) {
// Visit parameters.
- for (unsigned I = 0, N = Proto.getNumArgs(); I != N; ++I) {
- TRY_TO(TraverseDecl(Proto.getArg(I)));
+ for (unsigned I = 0, N = Proto.getNumParams(); I != N; ++I) {
+ TRY_TO(TraverseDecl(Proto.getParam(I)));
}
} else {
- TRY_TO(TraverseTypeLoc(Proto.getResultLoc()));
- }
+ TRY_TO(TraverseTypeLoc(Proto.getReturnLoc()));
+ }
}
}
@@ -2198,36 +2166,36 @@ bool RecursiveASTVisitor<Derived>::TraverseLambdaExpr(LambdaExpr *S) {
}
DEF_TRAVERSE_STMT(CXXUnresolvedConstructExpr, {
- // This is called for code like 'T()', where T is a template argument.
- TRY_TO(TraverseTypeLoc(S->getTypeSourceInfo()->getTypeLoc()));
- })
+ // 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, { })
+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(AddrLabelExpr, {})
+DEF_TRAVERSE_STMT(ArraySubscriptExpr, {})
DEF_TRAVERSE_STMT(BlockExpr, {
TRY_TO(TraverseDecl(S->getBlockDecl()));
return true; // no child statements to loop through.
})
-DEF_TRAVERSE_STMT(ChooseExpr, { })
+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(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())
@@ -2235,38 +2203,38 @@ DEF_TRAVERSE_STMT(CXXPseudoDestructorExpr, {
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(ExtVectorElementExpr, { })
-DEF_TRAVERSE_STMT(GNUNullExpr, { })
-DEF_TRAVERSE_STMT(ImplicitValueInitExpr, { })
-DEF_TRAVERSE_STMT(ObjCBoolLiteralExpr, { })
+DEF_TRAVERSE_STMT(CXXThisExpr, {})
+DEF_TRAVERSE_STMT(CXXThrowExpr, {})
+DEF_TRAVERSE_STMT(UserDefinedLiteral, {})
+DEF_TRAVERSE_STMT(DesignatedInitExpr, {})
+DEF_TRAVERSE_STMT(ExtVectorElementExpr, {})
+DEF_TRAVERSE_STMT(GNUNullExpr, {})
+DEF_TRAVERSE_STMT(ImplicitValueInitExpr, {})
+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(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(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(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()) {
@@ -2285,97 +2253,263 @@ DEF_TRAVERSE_STMT(UnresolvedMemberExpr, {
DEF_TRAVERSE_STMT(SEHTryStmt, {})
DEF_TRAVERSE_STMT(SEHExceptStmt, {})
-DEF_TRAVERSE_STMT(SEHFinallyStmt,{})
-DEF_TRAVERSE_STMT(CapturedStmt, {
- TRY_TO(TraverseDecl(S->getCapturedDecl()));
-})
+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(CUDAKernelCallExpr, { })
+DEF_TRAVERSE_STMT(CXXOperatorCallExpr, {})
+DEF_TRAVERSE_STMT(OpaqueValueExpr, {})
+DEF_TRAVERSE_STMT(CUDAKernelCallExpr, {})
// These operators (all of them) do not need any action except
// iterating over the children.
-DEF_TRAVERSE_STMT(BinaryConditionalOperator, { })
-DEF_TRAVERSE_STMT(ConditionalOperator, { })
-DEF_TRAVERSE_STMT(UnaryOperator, { })
-DEF_TRAVERSE_STMT(BinaryOperator, { })
-DEF_TRAVERSE_STMT(CompoundAssignOperator, { })
-DEF_TRAVERSE_STMT(CXXNoexceptExpr, { })
-DEF_TRAVERSE_STMT(PackExpansionExpr, { })
-DEF_TRAVERSE_STMT(SizeOfPackExpr, { })
-DEF_TRAVERSE_STMT(SubstNonTypeTemplateParmPackExpr, { })
-DEF_TRAVERSE_STMT(SubstNonTypeTemplateParmExpr, { })
-DEF_TRAVERSE_STMT(FunctionParmPackExpr, { })
-DEF_TRAVERSE_STMT(MaterializeTemporaryExpr, { })
-DEF_TRAVERSE_STMT(AtomicExpr, { })
+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(AtomicExpr, {})
// 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, { })
-
+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, { })
+DEF_TRAVERSE_STMT(AsTypeExpr, {})
// OpenMP directives.
-DEF_TRAVERSE_STMT(OMPParallelDirective, {
- ArrayRef<OMPClause *> Clauses = S->clauses();
- for (ArrayRef<OMPClause *>::iterator I = Clauses.begin(), E = Clauses.end();
- I != E; ++I)
- if (!TraverseOMPClause(*I)) return false;
+template <typename Derived>
+bool RecursiveASTVisitor<Derived>::TraverseOMPExecutableDirective(
+ OMPExecutableDirective *S) {
+ for (auto *C : S->clauses()) {
+ TRY_TO(TraverseOMPClause(C));
+ }
+ return true;
+}
+
+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(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(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(OMPFlushDirective,
+ { TRY_TO(TraverseOMPExecutableDirective(S)); })
+
// OpenMP clauses.
-template<typename Derived>
+template <typename Derived>
bool RecursiveASTVisitor<Derived>::TraverseOMPClause(OMPClause *C) {
- if (!C) return true;
+ if (!C)
+ return true;
switch (C->getClauseKind()) {
-#define OPENMP_CLAUSE(Name, Class) \
- case OMPC_##Name: \
- return getDerived().Visit##Class(static_cast<Class*>(C));
+#define OPENMP_CLAUSE(Name, Class) \
+ case OMPC_##Name: \
+ TRY_TO(Visit##Class(static_cast<Class *>(C))); \
+ break;
#include "clang/Basic/OpenMPKinds.def"
- default: break;
+ case OMPC_threadprivate:
+ case OMPC_unknown:
+ break;
}
return true;
}
-template<typename Derived>
-bool RecursiveASTVisitor<Derived>::VisitOMPDefaultClause(OMPDefaultClause *C) {
+template <typename Derived>
+bool RecursiveASTVisitor<Derived>::VisitOMPIfClause(OMPIfClause *C) {
+ TRY_TO(TraverseStmt(C->getCondition()));
return true;
}
-template<typename Derived>
-template<typename T>
-void RecursiveASTVisitor<Derived>::VisitOMPClauseList(T *Node) {
- for (typename T::varlist_iterator I = Node->varlist_begin(),
- E = Node->varlist_end();
- I != E; ++I)
- TraverseStmt(*I);
+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>::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()));
+ return true;
+}
+
+template <typename Derived>
+bool RecursiveASTVisitor<Derived>::VisitOMPOrderedClause(OMPOrderedClause *) {
+ 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>
+template <typename T>
+bool RecursiveASTVisitor<Derived>::VisitOMPClauseList(T *Node) {
+ for (auto *E : Node->varlists()) {
+ TRY_TO(TraverseStmt(E));
+ }
+ return true;
}
-template<typename Derived>
+template <typename Derived>
bool RecursiveASTVisitor<Derived>::VisitOMPPrivateClause(OMPPrivateClause *C) {
- VisitOMPClauseList(C);
+ TRY_TO(VisitOMPClauseList(C));
return true;
}
-template<typename Derived>
+template <typename Derived>
bool RecursiveASTVisitor<Derived>::VisitOMPFirstprivateClause(
- OMPFirstprivateClause *C) {
- VisitOMPClauseList(C);
+ OMPFirstprivateClause *C) {
+ TRY_TO(VisitOMPClauseList(C));
return true;
}
-template<typename Derived>
+template <typename Derived>
+bool RecursiveASTVisitor<Derived>::VisitOMPLastprivateClause(
+ OMPLastprivateClause *C) {
+ TRY_TO(VisitOMPClauseList(C));
+ return true;
+}
+
+template <typename Derived>
bool RecursiveASTVisitor<Derived>::VisitOMPSharedClause(OMPSharedClause *C) {
- VisitOMPClauseList(C);
+ TRY_TO(VisitOMPClauseList(C));
+ return true;
+}
+
+template <typename Derived>
+bool RecursiveASTVisitor<Derived>::VisitOMPLinearClause(OMPLinearClause *C) {
+ TRY_TO(TraverseStmt(C->getStep()));
+ TRY_TO(VisitOMPClauseList(C));
+ 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));
+ return true;
+}
+
+template <typename Derived>
+bool RecursiveASTVisitor<Derived>::VisitOMPCopyprivateClause(
+ OMPCopyprivateClause *C) {
+ TRY_TO(VisitOMPClauseList(C));
+ 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));
+ return true;
+}
+
+template <typename Derived>
+bool RecursiveASTVisitor<Derived>::VisitOMPFlushClause(OMPFlushClause *C) {
+ TRY_TO(VisitOMPClauseList(C));
return true;
}
diff --git a/include/clang/AST/Redeclarable.h b/include/clang/AST/Redeclarable.h
index cfe5a90be0d5..7aa11d403437 100644
--- a/include/clang/AST/Redeclarable.h
+++ b/include/clang/AST/Redeclarable.h
@@ -14,6 +14,7 @@
#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>
@@ -23,26 +24,82 @@ namespace clang {
/// \brief Provides common interface for the Decls that can be redeclared.
template<typename decl_type>
class Redeclarable {
-
protected:
class DeclLink {
- llvm::PointerIntPair<decl_type *, 1, bool> NextAndIsPrevious;
+ /// 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;
+
+ typedef const ASTContext *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:
- DeclLink(decl_type *D, bool isLatest)
- : NextAndIsPrevious(D, isLatest) { }
+ enum PreviousTag { PreviousLink };
+ enum LatestTag { LatestLink };
+
+ DeclLink(LatestTag, const ASTContext &Ctx)
+ : Next(NotKnownLatest(&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(*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(*NKL.get<UninitializedLatest>(), D);
+ } else {
+ auto Latest = Next.get<KnownLatest>();
+ Latest.set(D);
+ Next = Latest;
+ }
+ }
- bool NextIsPrevious() const { return !NextAndIsPrevious.getInt(); }
- bool NextIsLatest() const { return NextAndIsPrevious.getInt(); }
- decl_type *getNext() const { return NextAndIsPrevious.getPointer(); }
- void setNext(decl_type *D) { NextAndIsPrevious.setPointer(D); }
+ void markIncomplete() { Next.get<KnownLatest>().markIncomplete(); }
};
static DeclLink PreviousDeclLink(decl_type *D) {
- return DeclLink(D, false);
+ return DeclLink(DeclLink::PreviousLink, D);
}
- static DeclLink LatestDeclLink(decl_type *D) {
- return DeclLink(D, true);
+ static DeclLink LatestDeclLink(const ASTContext &Ctx) {
+ return DeclLink(DeclLink::LatestLink, Ctx);
}
/// \brief Points to the next redeclaration in the chain.
@@ -58,15 +115,20 @@ protected:
/// If there is only one declaration, it is <pointer to self, true>
DeclLink RedeclLink;
+ decl_type *getNextRedeclaration() const {
+ return RedeclLink.getNext(static_cast<const decl_type *>(this));
+ }
+
public:
- Redeclarable() : RedeclLink(LatestDeclLink(static_cast<decl_type*>(this))) { }
+ Redeclarable(const ASTContext &Ctx)
+ : RedeclLink(LatestDeclLink(Ctx)) {}
/// \brief Return the previous declaration of this declaration or NULL if this
/// is the first declaration.
decl_type *getPreviousDecl() {
if (RedeclLink.NextIsPrevious())
- return RedeclLink.getNext();
- return 0;
+ return getNextRedeclaration();
+ return nullptr;
}
const decl_type *getPreviousDecl() const {
return const_cast<decl_type *>(
@@ -96,14 +158,14 @@ public:
/// \brief Returns the most recent (re)declaration of this declaration.
decl_type *getMostRecentDecl() {
- return getFirstDecl()->RedeclLink.getNext();
+ return getFirstDecl()->getNextRedeclaration();
}
/// \brief Returns the most recent (re)declaration of this declaration.
const decl_type *getMostRecentDecl() const {
- return getFirstDecl()->RedeclLink.getNext();
+ 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);
@@ -122,7 +184,7 @@ public:
typedef std::forward_iterator_tag iterator_category;
typedef std::ptrdiff_t difference_type;
- redecl_iterator() : Current(0) { }
+ redecl_iterator() : Current(nullptr) { }
explicit redecl_iterator(decl_type *C)
: Current(C), Starter(C), PassedFirst(false) { }
@@ -135,15 +197,15 @@ public:
if (Current->isFirstDecl()) {
if (PassedFirst) {
assert(0 && "Passed first decl twice, invalid redecl chain!");
- Current = 0;
+ Current = nullptr;
return *this;
}
PassedFirst = true;
}
// Get either previous decl or latest decl.
- decl_type *Next = Current->RedeclLink.getNext();
- Current = (Next != Starter ? Next : 0);
+ decl_type *Next = Current->getNextRedeclaration();
+ Current = (Next != Starter) ? Next : nullptr;
return *this;
}
@@ -161,13 +223,18 @@ public:
}
};
- /// \brief Returns iterator for all the redeclarations of the same decl.
- /// It will iterate at least once (when this decl is the only one).
- redecl_iterator redecls_begin() const {
- return redecl_iterator(const_cast<decl_type*>(
- static_cast<const decl_type*>(this)));
+ 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_end() const { return redecl_iterator(); }
+
+ redecl_iterator redecls_begin() const { return redecls().begin(); }
+ redecl_iterator redecls_end() const { return redecls().end(); }
friend class ASTDeclReader;
friend class ASTDeclWriter;
diff --git a/include/clang/AST/Stmt.h b/include/clang/AST/Stmt.h
index ace53d83b3cf..fb94097cfac7 100644
--- a/include/clang/AST/Stmt.h
+++ b/include/clang/AST/Stmt.h
@@ -62,7 +62,7 @@ namespace clang {
Stmt** I;
public:
ExprIterator(Stmt** i) : I(i) {}
- ExprIterator() : I(0) {}
+ ExprIterator() : I(nullptr) {}
ExprIterator& operator++() { ++I; return *this; }
ExprIterator operator-(size_t i) { return I-i; }
ExprIterator operator+(size_t i) { return I+i; }
@@ -81,7 +81,7 @@ namespace clang {
const Stmt * const *I;
public:
ConstExprIterator(const Stmt * const *i) : I(i) {}
- ConstExprIterator() : I(0) {}
+ ConstExprIterator() : I(nullptr) {}
ConstExprIterator& operator++() { ++I; return *this; }
ConstExprIterator operator+(size_t i) const { return I+i; }
ConstExprIterator operator-(size_t i) const { return I-i; }
@@ -371,12 +371,12 @@ public:
/// \brief Dumps the specified AST fragment and all subtrees to
/// \c llvm::errs().
- LLVM_ATTRIBUTE_USED void dump() const;
- LLVM_ATTRIBUTE_USED void dump(SourceManager &SM) const;
+ void dump() const;
+ void dump(SourceManager &SM) const;
void dump(raw_ostream &OS, SourceManager &SM) const;
/// dumpColor - same as dump(), but forces color highlighting.
- LLVM_ATTRIBUTE_USED void dumpColor() const;
+ void dumpColor() const;
/// dumpPretty/printPretty - These two methods do a "pretty print" of the AST
/// back to its original source language syntax.
@@ -485,7 +485,13 @@ public:
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(); }
@@ -549,13 +555,13 @@ public:
// \brief Build an empty compound statement with a location.
explicit CompoundStmt(SourceLocation Loc)
- : Stmt(CompoundStmtClass), Body(0), LBracLoc(Loc), RBracLoc(Loc) {
+ : Stmt(CompoundStmtClass), Body(nullptr), LBracLoc(Loc), RBracLoc(Loc) {
CompoundStmtBits.NumStmts = 0;
}
// \brief Build an empty compound statement.
explicit CompoundStmt(EmptyShell Empty)
- : Stmt(CompoundStmtClass, Empty), Body(0) {
+ : Stmt(CompoundStmtClass, Empty), Body(nullptr) {
CompoundStmtBits.NumStmts = 0;
}
@@ -565,9 +571,12 @@ public:
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_back() { return !body_empty() ? Body[size()-1] : 0; }
+ Stmt *body_back() { return !body_empty() ? Body[size()-1] : nullptr; }
void setLastStmt(Stmt *S) {
assert(!body_empty() && "setLastStmt");
@@ -575,9 +584,16 @@ public:
}
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_back() const { return !body_empty() ? Body[size()-1] : 0; }
+ 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() {
@@ -612,11 +628,11 @@ public:
// Iterators
child_range children() {
- return child_range(&Body[0], &Body[0]+CompoundStmtBits.NumStmts);
+ return child_range(Body, Body + CompoundStmtBits.NumStmts);
}
const_child_range children() const {
- return child_range(&Body[0], &Body[0]+CompoundStmtBits.NumStmts);
+ return child_range(Body, Body + CompoundStmtBits.NumStmts);
}
};
@@ -630,10 +646,11 @@ protected:
SourceLocation ColonLoc;
SwitchCase(StmtClass SC, SourceLocation KWLoc, SourceLocation ColonLoc)
- : Stmt(SC), NextSwitchCase(0), KeywordLoc(KWLoc), ColonLoc(ColonLoc) {}
+ : Stmt(SC), NextSwitchCase(nullptr), KeywordLoc(KWLoc), ColonLoc(ColonLoc) {
+ }
SwitchCase(StmtClass SC, EmptyShell)
- : Stmt(SC), NextSwitchCase(0) {}
+ : Stmt(SC), NextSwitchCase(nullptr) {}
public:
const SwitchCase *getNextSwitchCase() const { return NextSwitchCase; }
@@ -670,7 +687,7 @@ public:
CaseStmt(Expr *lhs, Expr *rhs, SourceLocation caseLoc,
SourceLocation ellipsisLoc, SourceLocation colonLoc)
: SwitchCase(CaseStmtClass, caseLoc, colonLoc) {
- SubExprs[SUBSTMT] = 0;
+ SubExprs[SUBSTMT] = nullptr;
SubExprs[LHS] = reinterpret_cast<Stmt*>(lhs);
SubExprs[RHS] = reinterpret_cast<Stmt*>(rhs);
EllipsisLoc = ellipsisLoc;
@@ -802,20 +819,24 @@ class AttributedStmt : public Stmt {
Stmt *SubStmt;
SourceLocation AttrLoc;
unsigned NumAttrs;
- const Attr *Attrs[1];
friend class ASTStmtReader;
AttributedStmt(SourceLocation Loc, ArrayRef<const Attr*> Attrs, Stmt *SubStmt)
: Stmt(AttributedStmtClass), SubStmt(SubStmt), AttrLoc(Loc),
NumAttrs(Attrs.size()) {
- memcpy(this->Attrs, Attrs.data(), Attrs.size() * sizeof(Attr*));
+ memcpy(getAttrArrayPtr(), Attrs.data(), Attrs.size() * sizeof(Attr *));
}
explicit AttributedStmt(EmptyShell Empty, unsigned NumAttrs)
: Stmt(AttributedStmtClass, Empty), NumAttrs(NumAttrs) {
- memset(Attrs, 0, NumAttrs * sizeof(Attr*));
+ memset(getAttrArrayPtr(), 0, NumAttrs * sizeof(Attr *));
+ }
+
+ Attr *const *getAttrArrayPtr() const {
+ return reinterpret_cast<Attr *const *>(this + 1);
}
+ Attr **getAttrArrayPtr() { return reinterpret_cast<Attr **>(this + 1); }
public:
static AttributedStmt *Create(const ASTContext &C, SourceLocation Loc,
@@ -825,7 +846,7 @@ public:
SourceLocation getAttrLoc() const { return AttrLoc; }
ArrayRef<const Attr*> getAttrs() const {
- return ArrayRef<const Attr*>(Attrs, NumAttrs);
+ return ArrayRef<const Attr*>(getAttrArrayPtr(), NumAttrs);
}
Stmt *getSubStmt() { return SubStmt; }
const Stmt *getSubStmt() const { return SubStmt; }
@@ -852,7 +873,8 @@ class IfStmt : public Stmt {
public:
IfStmt(const ASTContext &C, SourceLocation IL, VarDecl *var, Expr *cond,
- Stmt *then, SourceLocation EL = SourceLocation(), Stmt *elsev = 0);
+ Stmt *then, SourceLocation EL = SourceLocation(),
+ Stmt *elsev = nullptr);
/// \brief Build an empty if/then/else statement
explicit IfStmt(EmptyShell Empty) : Stmt(IfStmtClass, Empty) { }
@@ -1320,7 +1342,8 @@ class ReturnStmt : public Stmt {
public:
ReturnStmt(SourceLocation RL)
- : Stmt(ReturnStmtClass), RetExpr(0), RetLoc(RL), NRVOCandidate(0) { }
+ : Stmt(ReturnStmtClass), RetExpr(nullptr), RetLoc(RL),
+ NRVOCandidate(nullptr) {}
ReturnStmt(SourceLocation RL, Expr *E, const VarDecl *NRVOCandidate)
: Stmt(ReturnStmtClass), RetExpr((Stmt*) E), RetLoc(RL),
@@ -1389,7 +1412,7 @@ protected:
public:
/// \brief Build an empty inline-assembly statement.
explicit AsmStmt(StmtClass SC, EmptyShell Empty) :
- Stmt(SC, Empty), Exprs(0) { }
+ Stmt(SC, Empty), Exprs(nullptr) { }
SourceLocation getAsmLoc() const { return AsmLoc; }
void setAsmLoc(SourceLocation L) { AsmLoc = L; }
@@ -1454,6 +1477,8 @@ public:
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;
@@ -1463,6 +1488,8 @@ public:
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;
}
@@ -1471,10 +1498,16 @@ public:
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];
@@ -1482,6 +1515,9 @@ public:
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];
@@ -1489,6 +1525,9 @@ public:
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);
@@ -1517,7 +1556,7 @@ public:
/// \brief Build an empty inline-assembly statement.
explicit GCCAsmStmt(EmptyShell Empty) : AsmStmt(GCCAsmStmtClass, Empty),
- Constraints(0), Clobbers(0), Names(0) { }
+ Constraints(nullptr), Clobbers(nullptr), Names(nullptr) { }
SourceLocation getRParenLoc() const { return RParenLoc; }
void setRParenLoc(SourceLocation L) { RParenLoc = L; }
@@ -1693,7 +1732,7 @@ public:
/// \brief Build an empty MS-style inline-assembly statement.
explicit MSAsmStmt(EmptyShell Empty) : AsmStmt(MSAsmStmtClass, Empty),
- NumAsmToks(0), AsmToks(0), Constraints(0), Clobbers(0) { }
+ NumAsmToks(0), AsmToks(nullptr), Constraints(nullptr), Clobbers(nullptr) { }
SourceLocation getLBraceLoc() const { return LBraceLoc; }
void setLBraceLoc(SourceLocation L) { LBraceLoc = L; }
@@ -1767,7 +1806,7 @@ public:
}
child_range children() {
- return child_range(&Exprs[0], &Exprs[0]);
+ return child_range(&Exprs[0], &Exprs[NumInputs + NumOutputs]);
}
};
@@ -1853,22 +1892,24 @@ class SEHTryStmt : public Stmt {
bool IsCXXTry;
SourceLocation TryLoc;
Stmt *Children[2];
+ int HandlerIndex;
+ int HandlerParentIndex;
enum { TRY = 0, HANDLER = 1 };
SEHTryStmt(bool isCXXTry, // true if 'try' otherwise '__try'
- SourceLocation TryLoc,
- Stmt *TryBlock,
- Stmt *Handler);
+ SourceLocation TryLoc, Stmt *TryBlock, Stmt *Handler,
+ int HandlerIndex, int HandlerParentIndex);
friend class ASTReader;
friend class ASTStmtReader;
explicit SEHTryStmt(EmptyShell E) : Stmt(SEHTryStmtClass, E) { }
public:
- static SEHTryStmt* Create(const ASTContext &C, bool isCXXTry,
+ static SEHTryStmt *Create(const ASTContext &C, bool isCXXTry,
SourceLocation TryLoc, Stmt *TryBlock,
- Stmt *Handler);
+ Stmt *Handler, int HandlerIndex,
+ int HandlerParentIndex);
SourceLocation getLocStart() const LLVM_READONLY { return getTryLoc(); }
SourceLocation getLocEnd() const LLVM_READONLY { return getEndLoc(); }
@@ -1895,6 +1936,34 @@ public:
static bool classof(const Stmt *T) {
return T->getStmtClass() == SEHTryStmtClass;
}
+
+ int getHandlerIndex() const { return HandlerIndex; }
+ int getHandlerParentIndex() const { return HandlerParentIndex; }
+};
+
+/// 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(); }
};
/// \brief This captures a statement into a function. For example, the following
@@ -1928,11 +1997,12 @@ public:
///
/// \param Var The variable being captured, or null if capturing this.
///
- Capture(SourceLocation Loc, VariableCaptureKind Kind, VarDecl *Var = 0)
+ Capture(SourceLocation Loc, VariableCaptureKind Kind,
+ VarDecl *Var = nullptr)
: VarAndKind(Var, Kind), Loc(Loc) {
switch (Kind) {
case VCK_This:
- assert(Var == 0 && "'this' capture cannot have a variable!");
+ assert(!Var && "'this' capture cannot have a variable!");
break;
case VCK_ByRef:
assert(Var && "capturing by reference must have a variable!");
@@ -2042,6 +2112,15 @@ public:
/// \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(); }
@@ -2058,6 +2137,11 @@ public:
/// \brief Iterator that walks over the capture initialization arguments.
typedef Expr **capture_init_iterator;
+ typedef llvm::iterator_range<capture_init_iterator> capture_init_range;
+
+ capture_init_range capture_inits() const {
+ return capture_init_range(capture_init_begin(), capture_init_end());
+ }
/// \brief Retrieve the first initialization argument.
capture_init_iterator capture_init_begin() const {
diff --git a/include/clang/AST/StmtCXX.h b/include/clang/AST/StmtCXX.h
index df98d41ad5fb..837dc45d1224 100644
--- a/include/clang/AST/StmtCXX.h
+++ b/include/clang/AST/StmtCXX.h
@@ -39,7 +39,7 @@ public:
HandlerBlock(handlerBlock) {}
CXXCatchStmt(EmptyShell Empty)
- : Stmt(CXXCatchStmtClass), ExceptionDecl(0), HandlerBlock(0) {}
+ : Stmt(CXXCatchStmtClass), ExceptionDecl(nullptr), HandlerBlock(nullptr) {}
SourceLocation getLocStart() const LLVM_READONLY { return CatchLoc; }
SourceLocation getLocEnd() const LLVM_READONLY {
diff --git a/include/clang/AST/StmtIterator.h b/include/clang/AST/StmtIterator.h
index fbc8e5d4ea71..18c55166beba 100644
--- a/include/clang/AST/StmtIterator.h
+++ b/include/clang/AST/StmtIterator.h
@@ -14,8 +14,8 @@
#ifndef LLVM_CLANG_AST_STMT_ITR_H
#define LLVM_CLANG_AST_STMT_ITR_H
-#include "llvm/Support/DataTypes.h"
#include "llvm/Support/Compiler.h"
+#include "llvm/Support/DataTypes.h"
#include <cassert>
#include <cstddef>
#include <iterator>
@@ -64,10 +64,10 @@ protected:
Stmt*& GetDeclExpr() const;
- StmtIteratorBase(Stmt **s) : stmt(s), DGI(0), RawVAPtr(0) {}
+ StmtIteratorBase(Stmt **s) : stmt(s), DGI(nullptr), RawVAPtr(0) {}
StmtIteratorBase(const VariableArrayType *t);
StmtIteratorBase(Decl **dgi, Decl **dge);
- StmtIteratorBase() : stmt(0), DGI(0), RawVAPtr(0) {}
+ StmtIteratorBase() : stmt(nullptr), DGI(nullptr), RawVAPtr(0) {}
};
diff --git a/include/clang/AST/StmtObjC.h b/include/clang/AST/StmtObjC.h
index bfb4a9b0bb7a..d0527e2d8b61 100644
--- a/include/clang/AST/StmtObjC.h
+++ b/include/clang/AST/StmtObjC.h
@@ -107,7 +107,7 @@ public:
SourceLocation getLocStart() const LLVM_READONLY { return AtCatchLoc; }
SourceLocation getLocEnd() const LLVM_READONLY { return Body->getLocEnd(); }
- bool hasEllipsis() const { return getCatchParamDecl() == 0; }
+ bool hasEllipsis() const { return getCatchParamDecl() == nullptr; }
static bool classof(const Stmt *T) {
return T->getStmtClass() == ObjCAtCatchStmtClass;
@@ -222,13 +222,13 @@ public:
/// \brief Retrieve the \@finally statement, if any.
const ObjCAtFinallyStmt *getFinallyStmt() const {
if (!HasFinally)
- return 0;
+ return nullptr;
return cast_or_null<ObjCAtFinallyStmt>(getStmts()[1 + NumCatchStmts]);
}
ObjCAtFinallyStmt *getFinallyStmt() {
if (!HasFinally)
- return 0;
+ return nullptr;
return cast_or_null<ObjCAtFinallyStmt>(getStmts()[1 + NumCatchStmts]);
}
diff --git a/include/clang/AST/StmtOpenMP.h b/include/clang/AST/StmtOpenMP.h
index 8570d8850a2f..db02afe0568b 100644
--- a/include/clang/AST/StmtOpenMP.h
+++ b/include/clang/AST/StmtOpenMP.h
@@ -1,4 +1,4 @@
-//===- StmtOpenMP.h - Classes for OpenMP directives and clauses --*- C++ -*-===//
+//===- StmtOpenMP.h - Classes for OpenMP directives ------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -15,514 +15,1019 @@
#ifndef LLVM_CLANG_AST_STMTOPENMP_H
#define LLVM_CLANG_AST_STMTOPENMP_H
-#include "clang/Basic/OpenMPKinds.h"
-#include "clang/Basic/SourceLocation.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 clauses.
+// AST classes for directives.
//===----------------------------------------------------------------------===//
-/// \brief This is a basic class for representing single OpenMP clause.
+/// \brief This is a basic class for representing single OpenMP executable
+/// directive.
///
-class OMPClause {
- /// \brief Starting location of the clause (the clause keyword).
+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 clause.
+ /// \brief Ending location of the directive.
SourceLocation EndLoc;
- /// \brief Kind of the clause.
- OpenMPClauseKind Kind;
+ /// \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:
- OMPClause(OpenMPClauseKind K, SourceLocation StartLoc, SourceLocation EndLoc)
- : StartLoc(StartLoc), EndLoc(EndLoc), Kind(K) {}
+ /// \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 those declarations that meet some run-time
+ /// criteria.
+ template <class FilterPredicate> class filtered_clause_iterator {
+ ArrayRef<OMPClause *>::const_iterator Current;
+ ArrayRef<OMPClause *>::const_iterator End;
+ FilterPredicate Pred;
+ void SkipToNextClause() {
+ while (Current != End && !Pred(*Current))
+ ++Current;
+ }
+
+ public:
+ typedef const OMPClause *value_type;
+ filtered_clause_iterator() : Current(), End() {}
+ filtered_clause_iterator(ArrayRef<OMPClause *> Arr, FilterPredicate Pred)
+ : Current(Arr.begin()), End(Arr.end()), Pred(Pred) {
+ SkipToNextClause();
+ }
+ value_type operator*() const { return *Current; }
+ value_type operator->() const { return *Current; }
+ filtered_clause_iterator &operator++() {
+ ++Current;
+ SkipToNextClause();
+ return *this;
+ }
+
+ filtered_clause_iterator operator++(int) {
+ filtered_clause_iterator tmp(*this);
+ ++(*this);
+ return tmp;
+ }
- /// \brief Returns the starting location of the clause.
+ bool operator!() { return Current == End; }
+ operator bool() { return Current != End; }
+ };
+
+ /// \brief Returns starting location of directive kind.
SourceLocation getLocStart() const { return StartLoc; }
- /// \brief Returns the ending location of the clause.
+ /// \brief Returns ending location of directive.
SourceLocation getLocEnd() const { return EndLoc; }
- /// \brief Sets the starting location of the clause.
+ /// \brief Set starting location of directive kind.
+ ///
+ /// \param Loc New starting location of directive.
+ ///
void setLocStart(SourceLocation Loc) { StartLoc = Loc; }
- /// \brief Sets the ending location of the clause.
+ /// \brief Set ending location of directive.
+ ///
+ /// \param Loc New ending location of directive.
+ ///
void setLocEnd(SourceLocation Loc) { EndLoc = Loc; }
- /// \brief Returns kind of OpenMP clause (private, shared, reduction, etc.).
- OpenMPClauseKind getClauseKind() const { return Kind; }
+ /// \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]; }
- bool isImplicit() const { return StartLoc.isInvalid();}
+ /// \brief Returns true if directive has associated statement.
+ bool hasAssociatedStmt() const { return NumChildren > 0; }
- StmtRange children();
- ConstStmtRange children() const {
- return const_cast<OMPClause *>(this)->children();
+ /// \brief Returns statement associated with the directive.
+ Stmt *getAssociatedStmt() const {
+ assert(hasAssociatedStmt() && "no associated statement.");
+ return const_cast<Stmt *>(*child_begin());
}
- static bool classof(const OMPClause *T) {
- return true;
+
+ OpenMPDirectiveKind getDirectiveKind() const { return Kind; }
+
+ static bool classof(const Stmt *S) {
+ return S->getStmtClass() >= firstOMPExecutableDirectiveConstant &&
+ S->getStmtClass() <= lastOMPExecutableDirectiveConstant;
}
-};
-/// \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 OMPVarList {
- 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.
- llvm::MutableArrayRef<Expr *> getVarRefs() {
- return llvm::MutableArrayRef<Expr *>(
- reinterpret_cast<Expr **>(static_cast<T *>(this) + 1),
- NumVars);
+ child_range children() {
+ if (!hasAssociatedStmt())
+ return child_range();
+ Stmt **ChildStorage = reinterpret_cast<Stmt **>(getClauses().end());
+ return child_range(ChildStorage, ChildStorage + NumChildren);
}
- /// \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(),
- reinterpret_cast<Expr **>(static_cast<T *>(this) + 1));
+ 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 {
+ /// \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) {}
- /// \brief Build clause with number of variables \a N.
+ /// \brief Build an empty directive.
///
- /// \param N Number of the variables in the clause.
+ /// \param NumClauses Number of clauses.
///
- OMPVarList(SourceLocation LParenLoc, unsigned N)
- : LParenLoc(LParenLoc), NumVars(N) { }
+ explicit OMPParallelDirective(unsigned NumClauses)
+ : OMPExecutableDirective(this, OMPParallelDirectiveClass, OMPD_parallel,
+ SourceLocation(), SourceLocation(), NumClauses,
+ 1) {}
+
public:
- typedef llvm::MutableArrayRef<Expr *>::iterator varlist_iterator;
- typedef ArrayRef<const Expr *>::iterator varlist_const_iterator;
-
- unsigned varlist_size() const { return NumVars; }
- bool varlist_empty() const { return NumVars == 0; }
- 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 ArrayRef<const Expr *>(
- reinterpret_cast<const Expr *const *>(static_cast<const T *>(this) + 1),
- NumVars);
+ /// \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 OMPParallelDirective *
+ 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 NumClauses Number of clauses.
+ ///
+ static OMPParallelDirective *CreateEmpty(const ASTContext &C,
+ unsigned NumClauses, EmptyShell);
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == OMPParallelDirectiveClass;
}
};
-/// \brief This represents 'default' clause in the '#pragma omp ...' directive.
+/// \brief This represents '#pragma omp simd' directive.
///
/// \code
-/// #pragma omp parallel default(shared)
+/// #pragma omp simd private(a,b) linear(i,j:s) reduction(+:c,d)
/// \endcode
-/// In this example directive '#pragma omp parallel' has simple 'default'
-/// clause with kind 'shared'.
+/// 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 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.
+class OMPSimdDirective : public OMPExecutableDirective {
+ friend class ASTStmtReader;
+ /// \brief Number of collapsed loops as specified by 'collapse' clause.
+ unsigned CollapsedNum;
+ /// \brief Build directive with the given start and end location.
///
- /// \param K Argument of clause.
+ /// \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.
///
- void setDefaultKind(OpenMPDefaultClauseKind K) { Kind = K; }
+ OMPSimdDirective(SourceLocation StartLoc, SourceLocation EndLoc,
+ unsigned CollapsedNum, unsigned NumClauses)
+ : OMPExecutableDirective(this, OMPSimdDirectiveClass, OMPD_simd, StartLoc,
+ EndLoc, NumClauses, 1),
+ CollapsedNum(CollapsedNum) {}
- /// \brief Set argument location.
+ /// \brief Build an empty directive.
///
- /// \param KLoc Argument location.
+ /// \param CollapsedNum Number of collapsed nested loops.
+ /// \param NumClauses Number of clauses.
///
- void setDefaultKindKwLoc(SourceLocation KLoc) { KindKwLoc = KLoc; }
+ explicit OMPSimdDirective(unsigned CollapsedNum, unsigned NumClauses)
+ : OMPExecutableDirective(this, OMPSimdDirectiveClass, OMPD_simd,
+ SourceLocation(), SourceLocation(), NumClauses,
+ 1),
+ CollapsedNum(CollapsedNum) {}
+
public:
- /// \brief Build 'default' clause with argument \a A ('none' or 'shared').
+ /// \brief Creates directive with a list of \a Clauses.
///
- /// \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.
+ /// \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.
///
- OMPDefaultClause(OpenMPDefaultClauseKind A, SourceLocation ALoc,
- SourceLocation StartLoc, SourceLocation LParenLoc,
- SourceLocation EndLoc)
- : OMPClause(OMPC_default, StartLoc, EndLoc), LParenLoc(LParenLoc),
- Kind(A), KindKwLoc(ALoc) { }
+ static OMPSimdDirective *Create(const ASTContext &C, SourceLocation StartLoc,
+ SourceLocation EndLoc, unsigned CollapsedNum,
+ ArrayRef<OMPClause *> Clauses,
+ Stmt *AssociatedStmt);
- /// \brief Build an empty clause.
+ /// \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.
///
- OMPDefaultClause()
- : OMPClause(OMPC_default, SourceLocation(), SourceLocation()),
- LParenLoc(SourceLocation()), Kind(OMPC_DEFAULT_unknown),
- KindKwLoc(SourceLocation()) { }
+ static OMPSimdDirective *CreateEmpty(const ASTContext &C, unsigned NumClauses,
+ unsigned CollapsedNum, EmptyShell);
- /// \brief Sets the location of '('.
- void setLParenLoc(SourceLocation Loc) { LParenLoc = Loc; }
- /// \brief Returns the location of '('.
- SourceLocation getLParenLoc() const { return LParenLoc; }
+ unsigned getCollapsedNumber() const { return CollapsedNum; }
- /// \brief Returns kind of the clause.
- OpenMPDefaultClauseKind getDefaultKind() const { return Kind; }
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == OMPSimdDirectiveClass;
+ }
+};
- /// \brief Returns location of clause kind.
- SourceLocation getDefaultKindKwLoc() const { return KindKwLoc; }
+/// \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 OMPExecutableDirective {
+ friend class ASTStmtReader;
+ /// \brief Number of collapsed loops as specified by 'collapse' clause.
+ unsigned CollapsedNum;
+ /// \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)
+ : OMPExecutableDirective(this, OMPForDirectiveClass, OMPD_for, StartLoc,
+ EndLoc, NumClauses, 1),
+ CollapsedNum(CollapsedNum) {}
- static bool classof(const OMPClause *T) {
- return T->getClauseKind() == OMPC_default;
- }
+ /// \brief Build an empty directive.
+ ///
+ /// \param CollapsedNum Number of collapsed nested loops.
+ /// \param NumClauses Number of clauses.
+ ///
+ explicit OMPForDirective(unsigned CollapsedNum, unsigned NumClauses)
+ : OMPExecutableDirective(this, OMPForDirectiveClass, OMPD_for,
+ SourceLocation(), SourceLocation(), NumClauses,
+ 1),
+ CollapsedNum(CollapsedNum) {}
+
+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.
+ ///
+ static OMPForDirective *Create(const ASTContext &C, SourceLocation StartLoc,
+ SourceLocation EndLoc, unsigned CollapsedNum,
+ ArrayRef<OMPClause *> Clauses,
+ Stmt *AssociatedStmt);
+
+ /// \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);
- StmtRange children() {
- return StmtRange();
+ unsigned getCollapsedNumber() const { return CollapsedNum; }
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == OMPForDirectiveClass;
}
};
-/// \brief This represents clause 'private' in the '#pragma omp ...' directives.
+/// \brief This represents '#pragma omp sections' directive.
///
/// \code
-/// #pragma omp parallel private(a,b)
+/// #pragma omp sections private(a,b) reduction(+:c,d)
/// \endcode
-/// In this example directive '#pragma omp parallel' has clause 'private'
-/// with the variables 'a' and 'b'.
+/// 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 OMPPrivateClause : public OMPClause, public OMPVarList<OMPPrivateClause> {
- /// \brief Build clause with number of variables \a N.
+class OMPSectionsDirective : public OMPExecutableDirective {
+ friend class ASTStmtReader;
+ /// \brief Build directive with the given start and end location.
///
- /// \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.
+ /// \param StartLoc Starting location of the directive kind.
+ /// \param EndLoc Ending location of the directive.
+ /// \param NumClauses Number of clauses.
///
- OMPPrivateClause(SourceLocation StartLoc, SourceLocation LParenLoc,
- SourceLocation EndLoc, unsigned N)
- : OMPClause(OMPC_private, StartLoc, EndLoc),
- OMPVarList<OMPPrivateClause>(LParenLoc, N) { }
+ OMPSectionsDirective(SourceLocation StartLoc, SourceLocation EndLoc,
+ unsigned NumClauses)
+ : OMPExecutableDirective(this, OMPSectionsDirectiveClass, OMPD_sections,
+ StartLoc, EndLoc, NumClauses, 1) {}
- /// \brief Build an empty clause.
+ /// \brief Build an empty directive.
///
- /// \param N Number of variables.
+ /// \param NumClauses Number of clauses.
///
- explicit OMPPrivateClause(unsigned N)
- : OMPClause(OMPC_private, SourceLocation(), SourceLocation()),
- OMPVarList<OMPPrivateClause>(SourceLocation(), N) { }
+ explicit OMPSectionsDirective(unsigned NumClauses)
+ : OMPExecutableDirective(this, OMPSectionsDirectiveClass, OMPD_sections,
+ SourceLocation(), SourceLocation(), NumClauses,
+ 1) {}
+
public:
- /// \brief Creates clause with a list of variables \a VL.
+ /// \brief Creates directive with a list of \a Clauses.
///
/// \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 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 OMPPrivateClause *Create(const ASTContext &C, SourceLocation StartLoc,
- SourceLocation LParenLoc,
- SourceLocation EndLoc,
- ArrayRef<Expr *> VL);
- /// \brief Creates an empty clause with the place for \a N variables.
+ static OMPSectionsDirective *
+ 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 N The number of variables.
+ /// \param NumClauses Number of clauses.
///
- static OMPPrivateClause *CreateEmpty(const ASTContext &C, unsigned N);
+ static OMPSectionsDirective *CreateEmpty(const ASTContext &C,
+ unsigned NumClauses, EmptyShell);
- StmtRange children() {
- return StmtRange(reinterpret_cast<Stmt **>(varlist_begin()),
- reinterpret_cast<Stmt **>(varlist_end()));
+ 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 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) {}
- static bool classof(const OMPClause *T) {
- return T->getClauseKind() == OMPC_private;
+ /// \brief Build an empty directive.
+ ///
+ explicit OMPSectionDirective()
+ : OMPExecutableDirective(this, OMPSectionDirectiveClass, OMPD_section,
+ 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 OMPSectionDirective *Create(const ASTContext &C,
+ SourceLocation StartLoc,
+ SourceLocation EndLoc,
+ Stmt *AssociatedStmt);
+
+ /// \brief Creates an empty directive.
+ ///
+ /// \param C AST context.
+ ///
+ static OMPSectionDirective *CreateEmpty(const ASTContext &C, EmptyShell);
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == OMPSectionDirectiveClass;
}
};
-/// \brief This represents clause 'firstprivate' in the '#pragma omp ...'
-/// directives.
+/// \brief This represents '#pragma omp single' directive.
///
/// \code
-/// #pragma omp parallel firstprivate(a,b)
+/// #pragma omp single private(a,b) copyprivate(c,d)
/// \endcode
-/// In this example directive '#pragma omp parallel' has clause 'firstprivate'
-/// with the variables 'a' and 'b'.
+/// In this example directive '#pragma omp single' has clauses 'private' with
+/// the variables 'a' and 'b' and 'copyprivate' with variables 'c' and 'd'.
///
-class OMPFirstprivateClause : public OMPClause,
- public OMPVarList<OMPFirstprivateClause> {
- /// \brief Build clause with number of variables \a N.
+class OMPSingleDirective : public OMPExecutableDirective {
+ friend class ASTStmtReader;
+ /// \brief Build directive with the given start and end location.
///
- /// \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.
+ /// \param StartLoc Starting location of the directive kind.
+ /// \param EndLoc Ending location of the directive.
+ /// \param NumClauses Number of clauses.
///
- OMPFirstprivateClause(SourceLocation StartLoc, SourceLocation LParenLoc,
- SourceLocation EndLoc, unsigned N)
- : OMPClause(OMPC_firstprivate, StartLoc, EndLoc),
- OMPVarList<OMPFirstprivateClause>(LParenLoc, N) { }
+ OMPSingleDirective(SourceLocation StartLoc, SourceLocation EndLoc,
+ unsigned NumClauses)
+ : OMPExecutableDirective(this, OMPSingleDirectiveClass, OMPD_single,
+ StartLoc, EndLoc, NumClauses, 1) {}
- /// \brief Build an empty clause.
+ /// \brief Build an empty directive.
///
- /// \param N Number of variables.
+ /// \param NumClauses Number of clauses.
///
- explicit OMPFirstprivateClause(unsigned N)
- : OMPClause(OMPC_firstprivate, SourceLocation(), SourceLocation()),
- OMPVarList<OMPFirstprivateClause>(SourceLocation(), N) { }
+ explicit OMPSingleDirective(unsigned NumClauses)
+ : OMPExecutableDirective(this, OMPSingleDirectiveClass, OMPD_single,
+ SourceLocation(), SourceLocation(), NumClauses,
+ 1) {}
+
public:
- /// \brief Creates clause with a list of variables \a VL.
+ /// \brief Creates directive with a list of \a Clauses.
///
/// \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 OMPFirstprivateClause *Create(const ASTContext &C,
- SourceLocation StartLoc,
- SourceLocation LParenLoc,
- SourceLocation EndLoc,
- ArrayRef<Expr *> VL);
- /// \brief Creates an empty clause with the place for \a N variables.
+ /// \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 N The number of variables.
+ /// \param NumClauses Number of clauses.
///
- static OMPFirstprivateClause *CreateEmpty(const ASTContext &C, unsigned N);
+ static OMPSingleDirective *CreateEmpty(const ASTContext &C,
+ unsigned NumClauses, EmptyShell);
- StmtRange children() {
- return StmtRange(reinterpret_cast<Stmt **>(varlist_begin()),
- reinterpret_cast<Stmt **>(varlist_end()));
+ 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 OMPClause *T) {
- return T->getClauseKind() == OMPC_firstprivate;
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == OMPMasterDirectiveClass;
}
};
-/// \brief This represents clause 'shared' in the '#pragma omp ...' directives.
+/// \brief This represents '#pragma omp critical' directive.
///
/// \code
-/// #pragma omp parallel shared(a,b)
+/// #pragma omp critical
/// \endcode
-/// In this example directive '#pragma omp parallel' has clause 'shared'
-/// with the variables 'a' and 'b'.
///
-class OMPSharedClause : public OMPClause, public OMPVarList<OMPSharedClause> {
- /// \brief Build clause with number of variables \a N.
+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 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.
+ OMPCriticalDirective(const DeclarationNameInfo &Name, SourceLocation StartLoc,
+ SourceLocation EndLoc)
+ : OMPExecutableDirective(this, OMPCriticalDirectiveClass, OMPD_critical,
+ StartLoc, EndLoc, 0, 1),
+ DirName(Name) {}
+
+ /// \brief Build an empty directive.
///
- OMPSharedClause(SourceLocation StartLoc, SourceLocation LParenLoc,
- SourceLocation EndLoc, unsigned N)
- : OMPClause(OMPC_shared, StartLoc, EndLoc),
- OMPVarList<OMPSharedClause>(LParenLoc, N) { }
+ explicit OMPCriticalDirective()
+ : OMPExecutableDirective(this, OMPCriticalDirectiveClass, OMPD_critical,
+ SourceLocation(), SourceLocation(), 0, 1),
+ DirName() {}
- /// \brief Build an empty clause.
+ /// \brief Set name of the directive.
///
- /// \param N Number of variables.
+ /// \param Name Name of the directive.
///
- explicit OMPSharedClause(unsigned N)
- : OMPClause(OMPC_shared, SourceLocation(), SourceLocation()),
- OMPVarList<OMPSharedClause>(SourceLocation(), N) { }
+ void setDirectiveName(const DeclarationNameInfo &Name) { DirName = Name; }
+
public:
- /// \brief Creates clause with a list of variables \a VL.
+ /// \brief Creates directive.
///
/// \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 Name Name of the directive.
+ /// \param StartLoc Starting location of the directive kind.
+ /// \param EndLoc Ending Location of the directive.
+ /// \param AssociatedStmt Statement, associated with the directive.
///
- static OMPSharedClause *Create(const ASTContext &C, SourceLocation StartLoc,
- SourceLocation LParenLoc,
- SourceLocation EndLoc, ArrayRef<Expr *> VL);
- /// \brief Creates an empty clause with \a N variables.
+ static OMPCriticalDirective *
+ Create(const ASTContext &C, const DeclarationNameInfo &Name,
+ SourceLocation StartLoc, SourceLocation EndLoc, Stmt *AssociatedStmt);
+
+ /// \brief Creates an empty directive.
///
/// \param C AST context.
- /// \param N The number of variables.
///
- static OMPSharedClause *CreateEmpty(const ASTContext &C, unsigned N);
+ static OMPCriticalDirective *CreateEmpty(const ASTContext &C, EmptyShell);
- StmtRange children() {
- return StmtRange(reinterpret_cast<Stmt **>(varlist_begin()),
- reinterpret_cast<Stmt **>(varlist_end()));
- }
+ /// \brief Return name of the directive.
+ ///
+ DeclarationNameInfo getDirectiveName() const { return DirName; }
- static bool classof(const OMPClause *T) {
- return T->getClauseKind() == OMPC_shared;
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == OMPCriticalDirectiveClass;
}
};
-//===----------------------------------------------------------------------===//
-// AST classes for directives.
-//===----------------------------------------------------------------------===//
-
-/// \brief This is a basic class for representing single OpenMP executable
-/// directive.
+/// \brief This represents '#pragma omp parallel for' directive.
///
-class OMPExecutableDirective : public Stmt {
+/// \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 OMPExecutableDirective {
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 Pointer to the list of clauses.
- llvm::MutableArrayRef<OMPClause *> Clauses;
- /// \brief Associated statement (if any) and expressions.
- llvm::MutableArrayRef<Stmt *> StmtAndExpressions;
-protected:
- /// \brief Build instance of directive of class \a K.
+ /// \brief Number of collapsed loops as specified by 'collapse' clause.
+ unsigned CollapsedNum;
+ /// \brief Build directive with the given start and end location.
///
- /// \param SC Statement class.
- /// \param K Kind of OpenMP directive.
- /// \param StartLoc Starting location of the directive (directive keyword).
+ /// \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.
///
- template <typename T>
- OMPExecutableDirective(const T *, StmtClass SC, OpenMPDirectiveKind K,
- SourceLocation StartLoc, SourceLocation EndLoc,
- unsigned NumClauses, unsigned NumberOfExpressions)
- : Stmt(SC), Kind(K), StartLoc(StartLoc), EndLoc(EndLoc),
- Clauses(reinterpret_cast<OMPClause **>(static_cast<T *>(this) + 1),
- NumClauses),
- StmtAndExpressions(reinterpret_cast<Stmt **>(Clauses.end()),
- NumberOfExpressions) { }
+ OMPParallelForDirective(SourceLocation StartLoc, SourceLocation EndLoc,
+ unsigned CollapsedNum, unsigned NumClauses)
+ : OMPExecutableDirective(this, OMPParallelForDirectiveClass,
+ OMPD_parallel_for, StartLoc, EndLoc, NumClauses,
+ 1),
+ CollapsedNum(CollapsedNum) {}
- /// \brief Sets the list of variables for this clause.
+ /// \brief Build an empty directive.
///
- /// \param Clauses The list of clauses for the directive.
+ /// \param CollapsedNum Number of collapsed nested loops.
+ /// \param NumClauses Number of clauses.
///
- void setClauses(ArrayRef<OMPClause *> Clauses);
+ explicit OMPParallelForDirective(unsigned CollapsedNum, unsigned NumClauses)
+ : OMPExecutableDirective(this, OMPParallelForDirectiveClass,
+ OMPD_parallel_for, SourceLocation(),
+ SourceLocation(), NumClauses, 1),
+ CollapsedNum(CollapsedNum) {}
- /// \brief Set the associated statement for the directive.
+public:
+ /// \brief Creates directive with a list of \a Clauses.
///
- /// /param S Associated statement.
+ /// \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.
///
- void setAssociatedStmt(Stmt *S) {
- StmtAndExpressions[0] = S;
+ static OMPParallelForDirective *
+ Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
+ unsigned CollapsedNum, ArrayRef<OMPClause *> Clauses,
+ Stmt *AssociatedStmt);
+
+ /// \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);
+
+ unsigned getCollapsedNumber() const { return CollapsedNum; }
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == OMPParallelForDirectiveClass;
}
+};
+
+/// \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 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) {}
+
+ /// \brief Build an empty directive.
+ ///
+ /// \param NumClauses Number of clauses.
+ ///
+ explicit OMPParallelSectionsDirective(unsigned NumClauses)
+ : OMPExecutableDirective(this, OMPParallelSectionsDirectiveClass,
+ OMPD_parallel_sections, SourceLocation(),
+ SourceLocation(), NumClauses, 1) {}
public:
- /// \brief Returns starting location of directive kind.
- SourceLocation getLocStart() const { return StartLoc; }
- /// \brief Returns ending location of directive.
- SourceLocation getLocEnd() const { return EndLoc; }
+ /// \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 OMPParallelSectionsDirective *
+ Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
+ ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt);
- /// \brief Set starting location of directive kind.
+ /// \brief Creates an empty directive with the place for \a NumClauses
+ /// clauses.
///
- /// \param Loc New starting location of directive.
+ /// \param C AST context.
+ /// \param NumClauses Number of clauses.
///
- void setLocStart(SourceLocation Loc) { StartLoc = Loc; }
- /// \brief Set ending location of directive.
+ static OMPParallelSectionsDirective *
+ CreateEmpty(const ASTContext &C, unsigned NumClauses, EmptyShell);
+
+ 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 Build directive with the given start and end location.
///
- /// \param Loc New ending location of directive.
+ /// \param StartLoc Starting location of the directive kind.
+ /// \param EndLoc Ending location of the directive.
+ /// \param NumClauses Number of clauses.
///
- void setLocEnd(SourceLocation Loc) { EndLoc = Loc; }
+ OMPTaskDirective(SourceLocation StartLoc, SourceLocation EndLoc,
+ unsigned NumClauses)
+ : OMPExecutableDirective(this, OMPTaskDirectiveClass, OMPD_task, StartLoc,
+ EndLoc, NumClauses, 1) {}
- /// \brief Get number of clauses.
- unsigned getNumClauses() const { return Clauses.size(); }
+ /// \brief Build an empty directive.
+ ///
+ /// \param NumClauses Number of clauses.
+ ///
+ explicit OMPTaskDirective(unsigned NumClauses)
+ : OMPExecutableDirective(this, OMPTaskDirectiveClass, OMPD_task,
+ SourceLocation(), SourceLocation(), NumClauses,
+ 1) {}
- /// \brief Returns specified clause.
+public:
+ /// \brief Creates directive with a list of \a Clauses.
///
- /// \param i Number of clause.
+ /// \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.
///
- OMPClause *getClause(unsigned i) const {
- assert(i < Clauses.size() && "index out of bound!");
- return Clauses[i];
- }
+ static OMPTaskDirective *Create(const ASTContext &C, SourceLocation StartLoc,
+ SourceLocation EndLoc,
+ ArrayRef<OMPClause *> Clauses,
+ Stmt *AssociatedStmt);
- /// \brief Returns statement associated with the directive.
- Stmt *getAssociatedStmt() const {
- return StmtAndExpressions[0];
+ /// \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);
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == OMPTaskDirectiveClass;
}
+};
- OpenMPDirectiveKind getDirectiveKind() const { return Kind; }
+/// \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) {}
- static bool classof(const Stmt *S) {
- return S->getStmtClass() >= firstOMPExecutableDirectiveConstant &&
- S->getStmtClass() <= lastOMPExecutableDirectiveConstant;
- }
+ /// \brief Build an empty directive.
+ ///
+ explicit OMPTaskyieldDirective()
+ : OMPExecutableDirective(this, OMPTaskyieldDirectiveClass, OMPD_taskyield,
+ SourceLocation(), SourceLocation(), 0, 0) {}
- child_range children() {
- return child_range(StmtAndExpressions.begin(), StmtAndExpressions.end());
+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) {}
- ArrayRef<OMPClause *> clauses() { return Clauses; }
+ /// \brief Build an empty directive.
+ ///
+ explicit OMPBarrierDirective()
+ : OMPExecutableDirective(this, OMPBarrierDirectiveClass, OMPD_barrier,
+ SourceLocation(), SourceLocation(), 0, 0) {}
- ArrayRef<OMPClause *> clauses() const { return Clauses; }
+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 parallel' directive.
+/// \brief This represents '#pragma omp taskwait' directive.
///
/// \code
-/// #pragma omp parallel private(a,b) reduction(+: c,d)
+/// #pragma omp taskwait
/// \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 {
+class OMPTaskwaitDirective : public OMPExecutableDirective {
+ friend class ASTStmtReader;
/// \brief Build directive with the given start and end location.
///
- /// \param StartLoc Starting location of the directive (directive keyword).
+ /// \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.
///
- OMPParallelDirective(SourceLocation StartLoc, SourceLocation EndLoc,
- unsigned N)
- : OMPExecutableDirective(this, OMPParallelDirectiveClass, OMPD_parallel,
- StartLoc, EndLoc, N, 1) { }
+ 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 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 N Number of clauses.
+ /// \param NumClauses Number of clauses.
///
- explicit OMPParallelDirective(unsigned N)
- : OMPExecutableDirective(this, OMPParallelDirectiveClass, OMPD_parallel,
- SourceLocation(), SourceLocation(), N, 1) { }
+ 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.
- /// \param AssociatedStmt Statement associated with the directive.
+ /// \param Clauses List of clauses (only single OMPFlushClause clause is
+ /// allowed).
///
- static OMPParallelDirective *Create(const ASTContext &C,
- SourceLocation StartLoc,
- SourceLocation EndLoc,
- ArrayRef<OMPClause *> Clauses,
- Stmt *AssociatedStmt);
+ static OMPFlushDirective *Create(const ASTContext &C, SourceLocation StartLoc,
+ SourceLocation EndLoc,
+ ArrayRef<OMPClause *> Clauses);
- /// \brief Creates an empty directive with the place for \a N clauses.
+ /// \brief Creates an empty directive with the place for \a NumClauses
+ /// clauses.
///
/// \param C AST context.
- /// \param N The number of clauses.
+ /// \param NumClauses Number of clauses.
///
- static OMPParallelDirective *CreateEmpty(const ASTContext &C, unsigned N,
- EmptyShell);
+ static OMPFlushDirective *CreateEmpty(const ASTContext &C,
+ unsigned NumClauses, EmptyShell);
static bool classof(const Stmt *T) {
- return T->getStmtClass() == OMPParallelDirectiveClass;
+ return T->getStmtClass() == OMPFlushDirectiveClass;
}
};
-} // end namespace clang
+} // end namespace clang
#endif
diff --git a/include/clang/AST/TemplateBase.h b/include/clang/AST/TemplateBase.h
index 6c40eb1168ce..1026a7807a60 100644
--- a/include/clang/AST/TemplateBase.h
+++ b/include/clang/AST/TemplateBase.h
@@ -18,6 +18,7 @@
#include "clang/AST/TemplateName.h"
#include "clang/AST/Type.h"
#include "llvm/ADT/APSInt.h"
+#include "llvm/ADT/iterator_range.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/Support/Compiler.h"
#include "llvm/Support/ErrorHandling.h"
@@ -34,8 +35,7 @@ struct PrintingPolicy;
class TypeSourceInfo;
class ValueDecl;
-/// \brief Represents a template argument within a class template
-/// specialization.
+/// \brief Represents a template argument.
class TemplateArgument {
public:
/// \brief The kind of template argument we're storing.
@@ -52,16 +52,19 @@ public:
/// 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.
+ /// that was provided for an integral non-type template parameter.
Integral,
- /// The template argument is a template name that was provided for a
+ /// 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
+ /// The template argument is a pack expansion of a template name that was
/// provided for a template template parameter.
TemplateExpansion,
- /// The template argument is a value- or type-dependent expression or a
- /// non-dependent __uuidof expression stored in an Expr*.
+ /// 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.
@@ -202,7 +205,7 @@ public:
}
static TemplateArgument getEmptyPack() {
- return TemplateArgument((TemplateArgument*)0, 0);
+ return TemplateArgument((TemplateArgument*)nullptr, 0);
}
/// \brief Create a new template argument pack by copying the given set of
@@ -325,6 +328,12 @@ public:
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 {
@@ -333,9 +342,9 @@ public:
}
/// \brief Return the array of arguments in this template argument pack.
- llvm::ArrayRef<TemplateArgument> getPackAsArray() const {
+ ArrayRef<TemplateArgument> getPackAsArray() const {
assert(getKind() == Pack);
- return llvm::ArrayRef<TemplateArgument>(Args.Args, Args.NumArgs);
+ return ArrayRef<TemplateArgument>(Args.Args, Args.NumArgs);
}
/// \brief Determines whether two template arguments are superficially the
@@ -541,6 +550,10 @@ public:
return Arguments[I];
}
+ TemplateArgumentLoc &operator[](unsigned I) {
+ return Arguments[I];
+ }
+
void addArgument(const TemplateArgumentLoc &Loc) {
Arguments.push_back(Loc);
}
@@ -565,7 +578,8 @@ struct ASTTemplateArgumentListInfo {
/// Force ASTTemplateArgumentListInfo to the right alignment
/// for the following array of TemplateArgumentLocs.
- void *Aligner;
+ llvm::AlignedCharArray<
+ llvm::AlignOf<TemplateArgumentLoc>::Alignment, 1> Aligner;
};
/// \brief Retrieve the template arguments
diff --git a/include/clang/AST/TemplateName.h b/include/clang/AST/TemplateName.h
index 0b9d4c85473c..f3d23b9260ae 100644
--- a/include/clang/AST/TemplateName.h
+++ b/include/clang/AST/TemplateName.h
@@ -15,7 +15,6 @@
#define LLVM_CLANG_AST_TEMPLATENAME_H
#include "clang/Basic/LLVM.h"
-#include "clang/Basic/OperatorKinds.h"
#include "llvm/ADT/FoldingSet.h"
#include "llvm/ADT/PointerUnion.h"
@@ -25,13 +24,14 @@ class ASTContext;
class DependentTemplateName;
class DiagnosticBuilder;
class IdentifierInfo;
+class NamedDecl;
class NestedNameSpecifier;
+enum OverloadedOperatorKind : int;
class OverloadedTemplateStorage;
struct PrintingPolicy;
class QualifiedTemplateName;
-class NamedDecl;
-class SubstTemplateTemplateParmStorage;
class SubstTemplateTemplateParmPackStorage;
+class SubstTemplateTemplateParmStorage;
class TemplateArgument;
class TemplateDecl;
class TemplateTemplateParmDecl;
@@ -71,19 +71,19 @@ public:
OverloadedTemplateStorage *getAsOverloadedStorage() {
return Bits.Kind == Overloaded
? reinterpret_cast<OverloadedTemplateStorage *>(this)
- : 0;
+ : nullptr;
}
SubstTemplateTemplateParmStorage *getAsSubstTemplateTemplateParm() {
return Bits.Kind == SubstTemplateTemplateParm
? reinterpret_cast<SubstTemplateTemplateParmStorage *>(this)
- : 0;
+ : nullptr;
}
SubstTemplateTemplateParmPackStorage *getAsSubstTemplateTemplateParmPack() {
return Bits.Kind == SubstTemplateTemplateParmPack
? reinterpret_cast<SubstTemplateTemplateParmPackStorage *>(this)
- : 0;
+ : nullptr;
}
};
@@ -243,7 +243,7 @@ public:
Storage.dyn_cast<UncommonTemplateNameStorage *>())
return Uncommon->getAsOverloadedStorage();
- return 0;
+ return nullptr;
}
/// \brief Retrieve the substituted template template parameter, if
@@ -256,7 +256,7 @@ public:
Storage.dyn_cast<UncommonTemplateNameStorage *>())
return uncommon->getAsSubstTemplateTemplateParm();
- return 0;
+ return nullptr;
}
/// \brief Retrieve the substituted template template parameter pack, if
@@ -270,7 +270,7 @@ public:
Storage.dyn_cast<UncommonTemplateNameStorage *>())
return Uncommon->getAsSubstTemplateTemplateParmPack();
- return 0;
+ return nullptr;
}
/// \brief Retrieve the underlying qualified template name
diff --git a/include/clang/AST/Type.h b/include/clang/AST/Type.h
index fb829e4d4103..09862e4fb7f7 100644
--- a/include/clang/AST/Type.h
+++ b/include/clang/AST/Type.h
@@ -18,20 +18,19 @@
#include "clang/AST/TemplateName.h"
#include "clang/Basic/Diagnostic.h"
#include "clang/Basic/ExceptionSpecificationType.h"
-#include "clang/Basic/IdentifierTable.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/APSInt.h"
+#include "llvm/ADT/APInt.h"
#include "llvm/ADT/FoldingSet.h"
+#include "llvm/ADT/iterator_range.h"
#include "llvm/ADT/Optional.h"
#include "llvm/ADT/PointerIntPair.h"
#include "llvm/ADT/PointerUnion.h"
#include "llvm/ADT/Twine.h"
#include "llvm/Support/ErrorHandling.h"
-#include "llvm/Support/type_traits.h"
namespace clang {
enum {
@@ -500,14 +499,14 @@ struct SplitQualType {
/// The local qualifiers.
Qualifiers Quals;
- SplitQualType() : Ty(0), Quals() {}
+ SplitQualType() : Ty(nullptr), Quals() {}
SplitQualType(const Type *ty, Qualifiers qs) : Ty(ty), Quals(qs) {}
SplitQualType getSingleStepDesugaredType() const; // end of this file
- // Make llvm::tie work.
- operator std::pair<const Type *,Qualifiers>() const {
- return std::pair<const Type *,Qualifiers>(Ty, Quals);
+ // 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) {
@@ -1438,7 +1437,7 @@ public:
/// \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 = 0) const;
+ bool isIncompleteType(NamedDecl **Def = nullptr) const;
/// isIncompleteOrObjectType - Return true if this is an incomplete or object
/// type, in other words, not a function type.
@@ -1797,7 +1796,7 @@ public:
return CanonicalType;
}
CanQualType getCanonicalTypeUnqualified() const; // in CanonicalType.h
- LLVM_ATTRIBUTE_USED void dump() const;
+ void dump() const;
friend class ASTReader;
friend class ASTWriter;
@@ -1996,39 +1995,59 @@ public:
static bool classof(const Type *T) { return T->getTypeClass() == Pointer; }
};
-/// \brief Represents a pointer type decayed from an array or function type.
-class DecayedType : public Type, public llvm::FoldingSetNode {
- QualType OriginalType;
- QualType DecayedPointer;
+/// \brief 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;
- DecayedType(QualType OriginalType, QualType DecayedPointer,
- QualType CanonicalPtr)
- : Type(Decayed, CanonicalPtr, OriginalType->isDependentType(),
- OriginalType->isInstantiationDependentType(),
- OriginalType->isVariablyModifiedType(),
- OriginalType->containsUnexpandedParameterPack()),
- OriginalType(OriginalType), DecayedPointer(DecayedPointer) {
- assert(isa<PointerType>(DecayedPointer));
- }
+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 getDecayedType() const { return DecayedPointer; }
- QualType getOriginalType() const { return OriginalType; }
-
- QualType getPointeeType() const {
- return cast<PointerType>(DecayedPointer)->getPointeeType();
- }
+ QualType getOriginalType() const { return OriginalTy; }
+ QualType getAdjustedType() const { return AdjustedTy; }
bool isSugared() const { return true; }
- QualType desugar() const { return DecayedPointer; }
+ QualType desugar() const { return AdjustedTy; }
void Profile(llvm::FoldingSetNodeID &ID) {
- Profile(ID, OriginalType);
+ 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;
}
- static void Profile(llvm::FoldingSetNodeID &ID, QualType OriginalType) {
- ID.AddPointer(OriginalType.getAsOpaquePtr());
+};
+
+/// \brief 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; }
@@ -2185,6 +2204,7 @@ public:
}
const Type *getClass() const { return Class; }
+ CXXRecordDecl *getMostRecentCXXRecordDecl() const;
bool isSugared() const { return false; }
QualType desugar() const { return QualType(this, 0); }
@@ -2758,8 +2778,7 @@ protected:
unsigned getTypeQuals() const { return FunctionTypeBits.TypeQuals; }
public:
-
- QualType getResultType() const { return ResultType; }
+ QualType getReturnType() const { return ResultType; }
bool getHasRegParm() const { return getExtInfo().getHasRegParm(); }
unsigned getRegParmType() const { return getExtInfo().getRegParm(); }
@@ -2776,7 +2795,7 @@ public:
/// \brief Determine the type of an expression that calls a function of
/// this type.
QualType getCallResultType(ASTContext &Context) const {
- return getResultType().getNonLValueExprType(Context);
+ return getReturnType().getNonLValueExprType(Context);
}
static StringRef getNameForCallConv(CallingConv CC);
@@ -2805,7 +2824,7 @@ public:
QualType desugar() const { return QualType(this, 0); }
void Profile(llvm::FoldingSetNodeID &ID) {
- Profile(ID, getResultType(), getExtInfo());
+ Profile(ID, getReturnType(), getExtInfo());
}
static void Profile(llvm::FoldingSetNodeID &ID, QualType ResultType,
ExtInfo Info) {
@@ -2818,27 +2837,28 @@ public:
}
};
-/// FunctionProtoType - Represents a prototype with argument type info, e.g.
+/// FunctionProtoType - Represents a prototype with parameter type info, e.g.
/// 'int foo(int)' or 'int foo(void)'. 'void' is represented as having no
-/// arguments, not as having a single void argument. Such a type can have an
+/// 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:
/// ExtProtoInfo - Extra information about a function prototype.
struct ExtProtoInfo {
- ExtProtoInfo() :
- Variadic(false), HasTrailingReturn(false), TypeQuals(0),
- ExceptionSpecType(EST_None), RefQualifier(RQ_None),
- NumExceptions(0), Exceptions(0), NoexceptExpr(0),
- ExceptionSpecDecl(0), ExceptionSpecTemplate(0),
- ConsumedArguments(0) {}
+ ExtProtoInfo()
+ : Variadic(false), HasTrailingReturn(false), TypeQuals(0),
+ ExceptionSpecType(EST_None), RefQualifier(RQ_None), NumExceptions(0),
+ Exceptions(nullptr), NoexceptExpr(nullptr),
+ ExceptionSpecDecl(nullptr), ExceptionSpecTemplate(nullptr),
+ ConsumedParameters(nullptr) {}
ExtProtoInfo(CallingConv CC)
: ExtInfo(CC), Variadic(false), HasTrailingReturn(false), TypeQuals(0),
ExceptionSpecType(EST_None), RefQualifier(RQ_None), NumExceptions(0),
- Exceptions(0), NoexceptExpr(0), ExceptionSpecDecl(0),
- ExceptionSpecTemplate(0), ConsumedArguments(0) {}
+ Exceptions(nullptr), NoexceptExpr(nullptr),
+ ExceptionSpecDecl(nullptr), ExceptionSpecTemplate(nullptr),
+ ConsumedParameters(nullptr) {}
FunctionType::ExtInfo ExtInfo;
bool Variadic : 1;
@@ -2851,7 +2871,7 @@ public:
Expr *NoexceptExpr;
FunctionDecl *ExceptionSpecDecl;
FunctionDecl *ExceptionSpecTemplate;
- const bool *ConsumedArguments;
+ const bool *ConsumedParameters;
};
private:
@@ -2866,11 +2886,11 @@ private:
return false;
}
- FunctionProtoType(QualType result, ArrayRef<QualType> args,
+ FunctionProtoType(QualType result, ArrayRef<QualType> params,
QualType canonical, const ExtProtoInfo &epi);
- /// NumArgs - The number of arguments this function has, not counting '...'.
- unsigned NumArgs : 15;
+ /// The number of parameters this function has, not counting '...'.
+ unsigned NumParams : 15;
/// NumExceptions - The number of types in the exception spec, if any.
unsigned NumExceptions : 9;
@@ -2878,8 +2898,8 @@ private:
/// ExceptionSpecType - The type of exception specification this function has.
unsigned ExceptionSpecType : 3;
- /// HasAnyConsumedArgs - Whether this function has any consumed arguments.
- unsigned HasAnyConsumedArgs : 1;
+ /// HasAnyConsumedParams - Whether this function has any consumed parameters.
+ unsigned HasAnyConsumedParams : 1;
/// Variadic - Whether the function is variadic.
unsigned Variadic : 1;
@@ -2892,8 +2912,8 @@ private:
/// This is a value of type \c RefQualifierKind.
unsigned RefQualifier : 2;
- // ArgInfo - There is an variable size array after the class in memory that
- // holds the argument types.
+ // 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.
@@ -2906,17 +2926,17 @@ private:
// instantiate this function type's exception specification, and the function
// from which it should be instantiated.
- // ConsumedArgs - A variable size array, following Exceptions
- // and of length NumArgs, holding flags indicating which arguments
- // are consumed. This only appears if HasAnyConsumedArgs is true.
+ // 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 *getConsumedArgsBuffer() const {
- assert(hasAnyConsumedArgs());
+ const bool *getConsumedParamsBuffer() const {
+ assert(hasAnyConsumedParams());
// Find the end of the exceptions.
- Expr * const *eh_end = reinterpret_cast<Expr * const *>(arg_type_end());
+ Expr *const *eh_end = reinterpret_cast<Expr *const *>(param_type_end());
if (getExceptionSpecType() != EST_ComputedNoexcept)
eh_end += NumExceptions;
else
@@ -2926,13 +2946,13 @@ private:
}
public:
- unsigned getNumArgs() const { return NumArgs; }
- QualType getArgType(unsigned i) const {
- assert(i < NumArgs && "Invalid argument number!");
- return arg_type_begin()[i];
+ unsigned getNumParams() const { return NumParams; }
+ QualType getParamType(unsigned i) const {
+ assert(i < NumParams && "invalid parameter index");
+ return param_type_begin()[i];
}
- ArrayRef<QualType> getArgTypes() const {
- return ArrayRef<QualType>(arg_type_begin(), arg_type_end());
+ ArrayRef<QualType> getParamTypes() const {
+ return ArrayRef<QualType>(param_type_begin(), param_type_end());
}
ExtProtoInfo getExtProtoInfo() const {
@@ -2954,8 +2974,8 @@ public:
} else if (EPI.ExceptionSpecType == EST_Unevaluated) {
EPI.ExceptionSpecDecl = getExceptionSpecDecl();
}
- if (hasAnyConsumedArgs())
- EPI.ConsumedArguments = getConsumedArgsBuffer();
+ if (hasAnyConsumedParams())
+ EPI.ConsumedParameters = getConsumedParamsBuffer();
return EPI;
}
@@ -2992,9 +3012,9 @@ public:
}
Expr *getNoexceptExpr() const {
if (getExceptionSpecType() != EST_ComputedNoexcept)
- return 0;
+ return nullptr;
// NoexceptExpr sits where the arguments end.
- return *reinterpret_cast<Expr *const *>(arg_type_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
@@ -3003,8 +3023,8 @@ public:
FunctionDecl *getExceptionSpecDecl() const {
if (getExceptionSpecType() != EST_Uninstantiated &&
getExceptionSpecType() != EST_Unevaluated)
- return 0;
- return reinterpret_cast<FunctionDecl * const *>(arg_type_end())[0];
+ 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
@@ -3012,18 +3032,13 @@ public:
/// this type.
FunctionDecl *getExceptionSpecTemplate() const {
if (getExceptionSpecType() != EST_Uninstantiated)
- return 0;
- return reinterpret_cast<FunctionDecl * const *>(arg_type_end())[1];
- }
- bool isNothrow(const ASTContext &Ctx) const {
- ExceptionSpecificationType EST = getExceptionSpecType();
- assert(EST != EST_Unevaluated && EST != EST_Uninstantiated);
- if (EST == EST_DynamicNone || EST == EST_BasicNoexcept)
- return true;
- if (EST != EST_ComputedNoexcept)
- return false;
- return getNoexceptSpec(Ctx) == NR_Nothrow;
+ return nullptr;
+ return reinterpret_cast<FunctionDecl *const *>(param_type_end())[1];
}
+ /// \brief 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; }
@@ -3045,16 +3060,28 @@ public:
return static_cast<RefQualifierKind>(RefQualifier);
}
- typedef const QualType *arg_type_iterator;
- arg_type_iterator arg_type_begin() const {
+ 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);
}
- arg_type_iterator arg_type_end() const { return arg_type_begin()+NumArgs; }
+ param_type_iterator param_type_end() const {
+ return param_type_begin() + NumParams;
+ }
typedef const QualType *exception_iterator;
+ typedef llvm::iterator_range<exception_iterator> exception_range;
+
+ exception_range exceptions() const {
+ return exception_range(exception_begin(), exception_end());
+ }
exception_iterator exception_begin() const {
// exceptions begin where arguments end
- return arg_type_end();
+ return param_type_end();
}
exception_iterator exception_end() const {
if (getExceptionSpecType() != EST_Dynamic)
@@ -3062,13 +3089,11 @@ public:
return exception_begin() + NumExceptions;
}
- bool hasAnyConsumedArgs() const {
- return HasAnyConsumedArgs;
- }
- bool isArgConsumed(unsigned I) const {
- assert(I < getNumArgs() && "argument index out of range!");
- if (hasAnyConsumedArgs())
- return getConsumedArgsBuffer()[I];
+ 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;
}
@@ -3084,7 +3109,7 @@ public:
void Profile(llvm::FoldingSetNodeID &ID, const ASTContext &Ctx);
static void Profile(llvm::FoldingSetNodeID &ID, QualType Result,
- arg_type_iterator ArgTys, unsigned NumArgs,
+ param_type_iterator ArgTys, unsigned NumArgs,
const ExtProtoInfo &EPI, const ASTContext &Context);
};
@@ -3495,7 +3520,7 @@ public:
bool isParameterPack() const { return getCanTTPTInfo().ParameterPack; }
TemplateTypeParmDecl *getDecl() const {
- return isCanonicalUnqualified() ? 0 : TTPDecl;
+ return isCanonicalUnqualified() ? nullptr : TTPDecl;
}
IdentifierInfo *getIdentifier() const;
@@ -3956,9 +3981,9 @@ public:
static bool KeywordIsTagTypeKind(ElaboratedTypeKeyword Keyword);
- static const char *getKeywordName(ElaboratedTypeKeyword Keyword);
+ static StringRef getKeywordName(ElaboratedTypeKeyword Keyword);
- static const char *getTagTypeKindName(TagTypeKind Kind) {
+ static StringRef getTagTypeKindName(TagTypeKind Kind) {
return getKeywordName(getKeywordForTagTypeKind(Kind));
}
@@ -3990,7 +4015,7 @@ class ElaboratedType : public TypeWithKeyword, public llvm::FoldingSetNode {
NamedType->isVariablyModifiedType(),
NamedType->containsUnexpandedParameterPack()),
NNS(NNS), NamedType(NamedType) {
- assert(!(Keyword == ETK_None && NNS == 0) &&
+ assert(!(Keyword == ETK_None && NNS == nullptr) &&
"ElaboratedType cannot have elaborated type keyword "
"and name qualifier both null.");
}
@@ -4032,11 +4057,14 @@ public:
/// dependent.
///
/// DependentNameType represents a class of dependent types that involve a
-/// dependent nested-name-specifier (e.g., "T::") followed by a (dependent)
+/// 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.
@@ -4051,10 +4079,7 @@ class DependentNameType : public TypeWithKeyword, public llvm::FoldingSetNode {
/*InstantiationDependent=*/true,
/*VariablyModified=*/false,
NNS->containsUnexpandedParameterPack()),
- NNS(NNS), Name(Name) {
- assert(NNS->isDependent() &&
- "DependentNameType requires a dependent nested-name-specifier");
- }
+ NNS(NNS), Name(Name) {}
friend class ASTContext; // ASTContext creates these
@@ -4199,7 +4224,7 @@ class PackExpansionType : public Type, public llvm::FoldingSetNode {
Optional<unsigned> NumExpansions)
: Type(PackExpansion, Canon, /*Dependent=*/Pattern->isDependentType(),
/*InstantiationDependent=*/true,
- /*VariableModified=*/Pattern->isVariablyModifiedType(),
+ /*VariablyModified=*/Pattern->isVariablyModifiedType(),
/*ContainsUnexpandedParameterPack=*/false),
Pattern(Pattern),
NumExpansions(NumExpansions? *NumExpansions + 1: 0) { }
@@ -4326,7 +4351,9 @@ public:
ObjCInterfaceDecl *getInterface() const;
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(); }
@@ -4430,7 +4457,7 @@ inline ObjCInterfaceDecl *ObjCObjectType::getInterface() const {
if (const ObjCInterfaceType *T =
getBaseType()->getAs<ObjCInterfaceType>())
return T->getDecl();
- return 0;
+ return nullptr;
}
/// ObjCObjectPointerType - Used to represent a pointer to an
@@ -4528,7 +4555,9 @@ public:
/// 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();
}
@@ -4633,7 +4662,7 @@ inline const Type *QualType::getTypePtr() const {
}
inline const Type *QualType::getTypePtrOrNull() const {
- return (isNull() ? 0 : getCommonPtr()->BaseType);
+ return (isNull() ? nullptr : getCommonPtr()->BaseType);
}
inline SplitQualType QualType::split() const {
@@ -5022,7 +5051,7 @@ inline const BuiltinType *Type::getAsPlaceholderType() const {
if (const BuiltinType *BT = dyn_cast<BuiltinType>(this))
if (BT->isPlaceholderType())
return BT;
- return 0;
+ return nullptr;
}
inline bool Type::isSpecificPlaceholderType(unsigned K) const {
@@ -5159,10 +5188,9 @@ inline const PartialDiagnostic &operator<<(const PartialDiagnostic &PD,
// Helper class template that is used by Type::getAs to ensure that one does
// not try to look through a qualified type to get to an array type.
-template<typename T,
- bool isArrayType = (llvm::is_same<T, ArrayType>::value ||
- llvm::is_base_of<ArrayType, T>::value)>
-struct ArrayType_cannot_be_used_with_getAs { };
+template <typename T, 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>;
@@ -5178,7 +5206,7 @@ template <typename T> const T *Type::getAs() const {
// If the canonical form of this type isn't the right kind, reject it.
if (!isa<T>(CanonicalType))
- return 0;
+ return nullptr;
// If this is a typedef for the type, strip the typedef off without
// losing all typedef information.
@@ -5192,7 +5220,7 @@ inline const ArrayType *Type::getAsArrayTypeUnsafe() const {
// If the canonical form of this type isn't the right kind, reject it.
if (!isa<ArrayType>(CanonicalType))
- return 0;
+ return nullptr;
// If this is a typedef for the type, strip the typedef off without
// losing all typedef information.
diff --git a/include/clang/AST/TypeLoc.h b/include/clang/AST/TypeLoc.h
index 8ddfac7ad373..3648d2a5c259 100644
--- a/include/clang/AST/TypeLoc.h
+++ b/include/clang/AST/TypeLoc.h
@@ -81,7 +81,7 @@ public:
Qualified
};
- TypeLoc() : Ty(0), Data(0) { }
+ TypeLoc() : Ty(nullptr), Data(nullptr) { }
TypeLoc(QualType ty, void *opaqueData)
: Ty(ty.getAsOpaquePtr()), Data(opaqueData) { }
TypeLoc(const Type *ty, void *opaqueData)
@@ -631,7 +631,7 @@ public:
bool isDefinition() const {
TagDecl *D = getDecl();
return D->isCompleteDefinition() &&
- (D->getIdentifier() == 0 || D->getLocation() == getNameLoc());
+ (D->getIdentifier() == nullptr || D->getLocation() == getNameLoc());
}
};
@@ -786,7 +786,7 @@ public:
setAttrNameLoc(loc);
if (hasAttrExprOperand()) {
setAttrOperandParensRange(SourceRange(loc));
- setAttrExprOperand(0);
+ setAttrExprOperand(nullptr);
} else if (hasAttrEnumOperand()) {
setAttrOperandParensRange(SourceRange(loc));
setAttrEnumOperandLoc(loc);
@@ -978,12 +978,10 @@ inline TypeLoc TypeLoc::IgnoreParens() const {
}
-struct DecayedLocInfo { }; // Nothing.
+struct AdjustedLocInfo { }; // Nothing.
-/// \brief Wrapper for source info for pointers decayed from arrays and
-/// functions.
-class DecayedTypeLoc : public ConcreteTypeLoc<UnqualTypeLoc, DecayedTypeLoc,
- DecayedType, DecayedLocInfo> {
+class AdjustedTypeLoc : public ConcreteTypeLoc<UnqualTypeLoc, AdjustedTypeLoc,
+ AdjustedType, AdjustedLocInfo> {
public:
TypeLoc getOriginalLoc() const {
return getInnerTypeLoc();
@@ -1004,12 +1002,17 @@ public:
}
unsigned getLocalDataSize() const {
- // sizeof(DecayedLocInfo) is 1, but we don't need its address to be unique
+ // 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;
@@ -1098,7 +1101,7 @@ public:
void initializeLocal(ASTContext &Context, SourceLocation Loc) {
setSigilLoc(Loc);
- setClassTInfo(0);
+ setClassTInfo(nullptr);
}
SourceRange getLocalSourceRange() const {
@@ -1205,23 +1208,23 @@ public:
}
ArrayRef<ParmVarDecl *> getParams() const {
- return ArrayRef<ParmVarDecl *>(getParmArray(), getNumArgs());
+ return ArrayRef<ParmVarDecl *>(getParmArray(), getNumParams());
}
- // ParmVarDecls* are stored after Info, one for each argument.
+ // ParmVarDecls* are stored after Info, one for each parameter.
ParmVarDecl **getParmArray() const {
return (ParmVarDecl**) getExtraLocalData();
}
- unsigned getNumArgs() const {
+ unsigned getNumParams() const {
if (isa<FunctionNoProtoType>(getTypePtr()))
return 0;
- return cast<FunctionProtoType>(getTypePtr())->getNumArgs();
+ return cast<FunctionProtoType>(getTypePtr())->getNumParams();
}
- ParmVarDecl *getArg(unsigned i) const { return getParmArray()[i]; }
- void setArg(unsigned i, ParmVarDecl *VD) { getParmArray()[i] = VD; }
+ ParmVarDecl *getParam(unsigned i) const { return getParmArray()[i]; }
+ void setParam(unsigned i, ParmVarDecl *VD) { getParmArray()[i] = VD; }
- TypeLoc getResultLoc() const {
+ TypeLoc getReturnLoc() const {
return getInnerTypeLoc();
}
@@ -1234,21 +1237,21 @@ public:
setLParenLoc(Loc);
setRParenLoc(Loc);
setLocalRangeEnd(Loc);
- for (unsigned i = 0, e = getNumArgs(); i != e; ++i)
- setArg(i, NULL);
+ 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 getNumArgs() * sizeof(ParmVarDecl*);
+ return getNumParams() * sizeof(ParmVarDecl *);
}
unsigned getExtraLocalDataAlignment() const {
return llvm::alignOf<ParmVarDecl*>();
}
- QualType getInnerType() const { return getTypePtr()->getResultType(); }
+ QualType getInnerType() const { return getTypePtr()->getReturnType(); }
};
class FunctionProtoTypeLoc :
@@ -1311,7 +1314,7 @@ public:
void initializeLocal(ASTContext &Context, SourceLocation Loc) {
setLBracketLoc(Loc);
setRBracketLoc(Loc);
- setSizeExpr(NULL);
+ setSizeExpr(nullptr);
}
QualType getInnerType() const { return getTypePtr()->getElementType(); }
@@ -1771,7 +1774,7 @@ public:
// 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 = 0;
+ getLocalData()->QualifierData = nullptr;
return;
}
diff --git a/include/clang/AST/TypeNodes.def b/include/clang/AST/TypeNodes.def
index 3126f48c644a..3b2665bb88e0 100644
--- a/include/clang/AST/TypeNodes.def
+++ b/include/clang/AST/TypeNodes.def
@@ -81,7 +81,8 @@ TYPE(FunctionNoProto, FunctionType)
DEPENDENT_TYPE(UnresolvedUsing, Type)
NON_CANONICAL_TYPE(Paren, Type)
NON_CANONICAL_TYPE(Typedef, Type)
-NON_CANONICAL_TYPE(Decayed, 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)
diff --git a/include/clang/AST/UnresolvedSet.h b/include/clang/AST/UnresolvedSet.h
index 759af2537f75..2ef5800c305f 100644
--- a/include/clang/AST/UnresolvedSet.h
+++ b/include/clang/AST/UnresolvedSet.h
@@ -27,7 +27,7 @@ namespace clang {
/// non-const iterator.
class UnresolvedSetIterator {
private:
- typedef llvm::MutableArrayRef<DeclAccessPair> DeclsTy;
+ typedef MutableArrayRef<DeclAccessPair> DeclsTy;
typedef DeclsTy::iterator IteratorTy;
IteratorTy ir;
diff --git a/include/clang/AST/VTableBuilder.h b/include/clang/AST/VTableBuilder.h
index 4e451324d734..4e24bdd73041 100644
--- a/include/clang/AST/VTableBuilder.h
+++ b/include/clang/AST/VTableBuilder.h
@@ -19,8 +19,9 @@
#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 "llvm/ADT/DenseSet.h"
+#include <memory>
#include <utility>
namespace clang {
@@ -208,11 +209,11 @@ public:
typedef llvm::DenseMap<BaseSubobject, uint64_t> AddressPointsMapTy;
private:
uint64_t NumVTableComponents;
- llvm::OwningArrayPtr<VTableComponent> VTableComponents;
+ std::unique_ptr<VTableComponent[]> VTableComponents;
/// \brief Contains thunks needed by vtables, sorted by indices.
uint64_t NumVTableThunks;
- llvm::OwningArrayPtr<VTableThunkTy> VTableThunks;
+ std::unique_ptr<VTableThunkTy[]> VTableThunks;
/// \brief Address points for all vtables.
AddressPointsMapTy AddressPoints;
@@ -270,6 +271,10 @@ class VTableContextBase {
public:
typedef SmallVector<ThunkInfo, 1> ThunkInfoVectorTy;
+ bool isMicrosoft() const { return IsMicrosoftABI; }
+
+ virtual ~VTableContextBase() {}
+
protected:
typedef llvm::DenseMap<const CXXMethodDecl *, ThunkInfoVectorTy> ThunksMapTy;
@@ -280,7 +285,7 @@ protected:
/// offset offsets, thunks etc) for the given record decl.
virtual void computeVTableRelatedInformation(const CXXRecordDecl *RD) = 0;
- virtual ~VTableContextBase() {}
+ VTableContextBase(bool MS) : IsMicrosoftABI(MS) {}
public:
virtual const ThunkInfoVectorTy *getThunkInfo(GlobalDecl GD) {
@@ -292,16 +297,17 @@ public:
ThunksMapTy::const_iterator I = Thunks.find(MD);
if (I == Thunks.end()) {
// We did not find a thunk for this method.
- return 0;
+ return nullptr;
}
return &I->second;
}
+
+ bool IsMicrosoftABI;
};
class ItaniumVTableContext : public VTableContextBase {
private:
- bool IsMicrosoftABI;
/// \brief Contains the index (relative to the vtable address point)
/// where the function pointer for a virtual function is stored.
@@ -323,7 +329,7 @@ private:
VirtualBaseClassOffsetOffsetsMapTy;
VirtualBaseClassOffsetOffsetsMapTy VirtualBaseClassOffsetOffsets;
- void computeVTableRelatedInformation(const CXXRecordDecl *RD);
+ void computeVTableRelatedInformation(const CXXRecordDecl *RD) override;
public:
ItaniumVTableContext(ASTContext &Context);
@@ -355,49 +361,83 @@ public:
/// 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();
+ }
};
-struct VFPtrInfo {
+/// 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;
- // Don't pass the PathToMangle as it should be calculated later.
- VFPtrInfo(CharUnits VFPtrOffset, const BasePath &PathToBaseWithVFPtr)
- : VBTableIndex(0), LastVBase(0), VFPtrOffset(VFPtrOffset),
- PathToBaseWithVFPtr(PathToBaseWithVFPtr), VFPtrFullOffset(VFPtrOffset) {
- }
+ VPtrInfo(const CXXRecordDecl *RD)
+ : ReusingBase(RD), BaseWithVPtr(RD), NextBaseToMangle(RD) {}
- // Don't pass the PathToMangle as it should be calculated later.
- VFPtrInfo(uint64_t VBTableIndex, const CXXRecordDecl *LastVBase,
- CharUnits VFPtrOffset, const BasePath &PathToBaseWithVFPtr,
- CharUnits VFPtrFullOffset)
- : VBTableIndex(VBTableIndex), LastVBase(LastVBase),
- VFPtrOffset(VFPtrOffset), PathToBaseWithVFPtr(PathToBaseWithVFPtr),
- VFPtrFullOffset(VFPtrFullOffset) {
- assert(VBTableIndex && "The full constructor should only be used "
- "for vfptrs in virtual bases");
- assert(LastVBase);
- }
+ // Copy constructor.
+ // FIXME: Uncomment when we've moved to C++11.
+ // VPtrInfo(const VPtrInfo &) = default;
+
+ /// 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;
- /// If nonzero, holds the vbtable index of the virtual base with the vfptr.
- uint64_t VBTableIndex;
+ /// The vptr is stored inside this subobject.
+ const CXXRecordDecl *BaseWithVPtr;
- /// Stores the last vbase on the path from the complete type to the vfptr.
- const CXXRecordDecl *LastVBase;
+ /// 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;
- /// 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;
+ /// 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.
- BasePath PathToBaseWithVFPtr;
+ /// 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;
- /// This holds the subset of records that need to be mangled into the vftable
- /// symbol name in order to get a unique name, in the derived-to-base order.
- BasePath PathToMangle;
+/// 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); }
- /// This is the full offset of the vfptr from the start of the complete type.
- CharUnits VFPtrFullOffset;
+ /// 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 {
@@ -418,7 +458,7 @@ public:
uint64_t Index;
MethodVFTableLocation()
- : VBTableIndex(0), VBase(0), VFPtrOffset(CharUnits::Zero()),
+ : VBTableIndex(0), VBase(nullptr), VFPtrOffset(CharUnits::Zero()),
Index(0) {}
MethodVFTableLocation(uint64_t VBTableIndex, const CXXRecordDecl *VBase,
@@ -431,16 +471,11 @@ public:
assert(VBase != other.VBase);
return VBTableIndex < other.VBTableIndex;
}
- if (VFPtrOffset != other.VFPtrOffset)
- return VFPtrOffset < other.VFPtrOffset;
- if (Index != other.Index)
- return Index < other.Index;
- return false;
+ return std::tie(VFPtrOffset, Index) <
+ std::tie(other.VFPtrOffset, other.Index);
}
};
- typedef SmallVector<VFPtrInfo, 1> VFPtrListTy;
-
private:
ASTContext &Context;
@@ -448,7 +483,7 @@ private:
MethodVFTableLocationsTy;
MethodVFTableLocationsTy MethodVFTableLocations;
- typedef llvm::DenseMap<const CXXRecordDecl *, VFPtrListTy>
+ typedef llvm::DenseMap<const CXXRecordDecl *, VPtrInfoVector *>
VFPtrLocationsMapTy;
VFPtrLocationsMapTy VFPtrLocations;
@@ -456,47 +491,40 @@ private:
typedef llvm::DenseMap<VFTableIdTy, const VTableLayout *> VFTableLayoutMapTy;
VFTableLayoutMapTy VFTableLayouts;
- typedef llvm::SmallSetVector<const CXXRecordDecl *, 8> BasesSetVectorTy;
- void enumerateVFPtrs(const CXXRecordDecl *MostDerivedClass,
- const ASTRecordLayout &MostDerivedClassLayout,
- BaseSubobject Base, const CXXRecordDecl *LastVBase,
- const VFPtrInfo::BasePath &PathFromCompleteClass,
- BasesSetVectorTy &VisitedVBases,
- MicrosoftVTableContext::VFPtrListTy &Result);
+ llvm::DenseMap<const CXXRecordDecl *, VirtualBaseInfo *> VBaseInfo;
- void enumerateVFPtrs(const CXXRecordDecl *ForClass,
- MicrosoftVTableContext::VFPtrListTy &Result);
+ void enumerateVFPtrs(const CXXRecordDecl *ForClass, VPtrInfoVector &Result);
- void computeVTableRelatedInformation(const CXXRecordDecl *RD);
+ void computeVTableRelatedInformation(const CXXRecordDecl *RD) override;
void dumpMethodLocations(const CXXRecordDecl *RD,
const MethodVFTableLocationsTy &NewMethods,
raw_ostream &);
- typedef std::pair<const CXXRecordDecl *, const CXXRecordDecl *> ClassPairTy;
- typedef llvm::DenseMap<ClassPairTy, unsigned> VBTableIndicesTy;
- VBTableIndicesTy VBTableIndices;
- llvm::DenseSet<const CXXRecordDecl *> ComputedVBTableIndices;
+ const VirtualBaseInfo *
+ computeVBTableRelatedInformation(const CXXRecordDecl *RD);
- void computeVBTableRelatedInformation(const CXXRecordDecl *RD);
+ void computeVTablePaths(bool ForVBTables, const CXXRecordDecl *RD,
+ VPtrInfoVector &Paths);
public:
- MicrosoftVTableContext(ASTContext &Context) : Context(Context) {}
+ MicrosoftVTableContext(ASTContext &Context)
+ : VTableContextBase(/*MS=*/true), Context(Context) {}
- ~MicrosoftVTableContext() { llvm::DeleteContainerSeconds(VFTableLayouts); }
+ ~MicrosoftVTableContext();
- const VFPtrListTy &getVFPtrOffsets(const CXXRecordDecl *RD);
+ const VPtrInfoVector &getVFPtrOffsets(const CXXRecordDecl *RD);
const VTableLayout &getVFTableLayout(const CXXRecordDecl *RD,
CharUnits VFPtrOffset);
const MethodVFTableLocation &getMethodVFTableLocation(GlobalDecl GD);
- const ThunkInfoVectorTy *getThunkInfo(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 0;
+ return nullptr;
return VTableContextBase::getThunkInfo(GD);
}
@@ -505,14 +533,13 @@ public:
/// 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) {
- computeVBTableRelatedInformation(Derived);
- ClassPairTy Pair(Derived, VBase);
- assert(VBTableIndices.count(Pair) == 1 &&
- "VBase must be a vbase of Derived");
- return VBTableIndices[Pair];
- }
+ const CXXRecordDecl *VBase);
+
+ const VPtrInfoVector &enumerateVBTables(const CXXRecordDecl *RD);
+
+ static bool classof(const VTableContextBase *VT) { return VT->isMicrosoft(); }
};
-}
+
+} // namespace clang
#endif
diff --git a/include/clang/ASTMatchers/ASTMatchFinder.h b/include/clang/ASTMatchers/ASTMatchFinder.h
index db0a83d72262..8af0546db57b 100644
--- a/include/clang/ASTMatchers/ASTMatchFinder.h
+++ b/include/clang/ASTMatchers/ASTMatchFinder.h
@@ -222,13 +222,13 @@ selectFirst(StringRef BoundTo, const SmallVectorImpl<BoundNodes> &Results) {
if (NodeT *Node = I->getNodeAs<NodeT>(BoundTo))
return Node;
}
- return NULL;
+ return nullptr;
}
namespace internal {
class CollectMatchesCallback : public MatchFinder::MatchCallback {
public:
- virtual void run(const MatchFinder::MatchResult &Result) {
+ void run(const MatchFinder::MatchResult &Result) override {
Nodes.push_back(Result.Nodes);
}
SmallVector<BoundNodes, 1> Nodes;
diff --git a/include/clang/ASTMatchers/ASTMatchers.h b/include/clang/ASTMatchers/ASTMatchers.h
index 0a3157dde817..1ff4ab367fd5 100644
--- a/include/clang/ASTMatchers/ASTMatchers.h
+++ b/include/clang/ASTMatchers/ASTMatchers.h
@@ -311,6 +311,12 @@ 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.
///
@@ -323,9 +329,13 @@ AST_MATCHER(Decl, isPrivate) {
/// classTemplateSpecializationDecl(hasAnyTemplateArgument(
/// refersToType(asString("int"))))
/// matches the specialization \c A<int>
-AST_MATCHER_P(ClassTemplateSpecializationDecl, hasAnyTemplateArgument,
- internal::Matcher<TemplateArgument>, InnerMatcher) {
- llvm::ArrayRef<TemplateArgument> List = Node.getTemplateArgs().asArray();
+AST_POLYMORPHIC_MATCHER_P(
+ hasAnyTemplateArgument,
+ AST_POLYMORPHIC_SUPPORTED_TYPES_2(ClassTemplateSpecializationDecl,
+ TemplateSpecializationType),
+ internal::Matcher<TemplateArgument>, InnerMatcher) {
+ ArrayRef<TemplateArgument> List =
+ internal::getTemplateSpecializationArgs(Node);
return matchesFirstInRange(InnerMatcher, List.begin(), List.end(), Finder,
Builder);
}
@@ -419,12 +429,16 @@ AST_MATCHER_P(Expr, ignoringParenImpCasts,
/// classTemplateSpecializationDecl(hasTemplateArgument(
/// 1, refersToType(asString("int"))))
/// matches the specialization \c A<bool, int>
-AST_MATCHER_P2(ClassTemplateSpecializationDecl, hasTemplateArgument,
- unsigned, N, internal::Matcher<TemplateArgument>, InnerMatcher) {
- const TemplateArgumentList &List = Node.getTemplateArgs();
+AST_POLYMORPHIC_MATCHER_P2(
+ hasTemplateArgument,
+ AST_POLYMORPHIC_SUPPORTED_TYPES_2(ClassTemplateSpecializationDecl,
+ TemplateSpecializationType),
+ unsigned, N, internal::Matcher<TemplateArgument>, InnerMatcher) {
+ ArrayRef<TemplateArgument> List =
+ internal::getTemplateSpecializationArgs(Node);
if (List.size() <= N)
return false;
- return InnerMatcher.matches(List.get(N), Finder, Builder);
+ return InnerMatcher.matches(List[N], Finder, Builder);
}
/// \brief Matches a TemplateArgument that refers to a certain type.
@@ -445,7 +459,8 @@ AST_MATCHER_P(TemplateArgument, refersToType,
return InnerMatcher.matches(Node.getAsType(), Finder, Builder);
}
-/// \brief Matches a TemplateArgument that refers to a certain declaration.
+/// \brief Matches a canonical TemplateArgument that refers to a certain
+/// declaration.
///
/// Given
/// \code
@@ -464,6 +479,24 @@ AST_MATCHER_P(TemplateArgument, refersToDeclaration,
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 C++ constructor declarations.
///
/// Example matches Foo::Foo() and Foo::Foo(int)
@@ -518,7 +551,7 @@ const internal::VariadicDynCastAllOfMatcher<
///
/// Example matches y
/// \code
-/// class X { void y() };
+/// class X { void y(); };
/// \endcode
const internal::VariadicDynCastAllOfMatcher<Decl, CXXMethodDecl> methodDecl;
@@ -635,6 +668,16 @@ const internal::VariadicDynCastAllOfMatcher<
Stmt,
CXXMemberCallExpr> memberCallExpr;
+/// \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
@@ -643,10 +686,23 @@ const internal::VariadicDynCastAllOfMatcher<
/// struct B { int x, y; };
/// B b = { 5, 6 };
/// \endcode
-/// initList()
+/// 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
@@ -658,6 +714,18 @@ const internal::VariadicDynCastAllOfMatcher<Stmt, InitListExpr> initListExpr;
/// 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
@@ -842,15 +910,6 @@ const internal::VariadicDynCastAllOfMatcher<Stmt, IfStmt> ifStmt;
/// \endcode
const internal::VariadicDynCastAllOfMatcher<Stmt, ForStmt> forStmt;
-/// \brief Matches range-based for statements.
-///
-/// forRangeStmt() 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> forRangeStmt;
-
/// \brief Matches the increment statement of a for loop.
///
/// Example:
@@ -862,7 +921,7 @@ const internal::VariadicDynCastAllOfMatcher<Stmt, CXXForRangeStmt> forRangeStmt;
AST_MATCHER_P(ForStmt, hasIncrement, internal::Matcher<Stmt>,
InnerMatcher) {
const Stmt *const Increment = Node.getInc();
- return (Increment != NULL &&
+ return (Increment != nullptr &&
InnerMatcher.matches(*Increment, Finder, Builder));
}
@@ -877,7 +936,44 @@ AST_MATCHER_P(ForStmt, hasIncrement, internal::Matcher<Stmt>,
AST_MATCHER_P(ForStmt, hasLoopInit, internal::Matcher<Stmt>,
InnerMatcher) {
const Stmt *const Init = Node.getInit();
- return (Init != NULL && InnerMatcher.matches(*Init, Finder, Builder));
+ return (Init != nullptr && InnerMatcher.matches(*Init, Finder, Builder));
+}
+
+/// \brief Matches range-based for statements.
+///
+/// forRangeStmt() 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> forRangeStmt;
+
+/// \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.
@@ -1317,21 +1413,21 @@ const internal::VariadicAllOfMatcher<TypeLoc> typeLoc;
/// \c b.
///
/// Usable as: Any Matcher
-const internal::VariadicOperatorMatcherFunc eachOf = {
+const internal::VariadicOperatorMatcherFunc<2, UINT_MAX> eachOf = {
internal::EachOfVariadicOperator
};
/// \brief Matches if any of the given matchers matches.
///
/// Usable as: Any Matcher
-const internal::VariadicOperatorMatcherFunc anyOf = {
+const internal::VariadicOperatorMatcherFunc<2, UINT_MAX> anyOf = {
internal::AnyOfVariadicOperator
};
/// \brief Matches if all given matchers match.
///
/// Usable as: Any Matcher
-const internal::VariadicOperatorMatcherFunc allOf = {
+const internal::VariadicOperatorMatcherFunc<2, UINT_MAX> allOf = {
internal::AllOfVariadicOperator
};
@@ -1458,14 +1554,14 @@ AST_MATCHER_P(NamedDecl, matchesName, std::string, RegExp) {
/// line and \c recordDecl(hasMethod(hasOverloadedOperatorName("*"))) matches
/// the declaration of \c A.
///
-/// Usable as: Matcher<CXXOperatorCallExpr>, Matcher<CXXMethodDecl>
+/// Usable as: Matcher<CXXOperatorCallExpr>, Matcher<FunctionDecl>
inline internal::PolymorphicMatcherWithParam1<
internal::HasOverloadedOperatorNameMatcher, StringRef,
- AST_POLYMORPHIC_SUPPORTED_TYPES_2(CXXOperatorCallExpr, CXXMethodDecl)>
+ AST_POLYMORPHIC_SUPPORTED_TYPES_2(CXXOperatorCallExpr, FunctionDecl)>
hasOverloadedOperatorName(const StringRef Name) {
return internal::PolymorphicMatcherWithParam1<
internal::HasOverloadedOperatorNameMatcher, StringRef,
- AST_POLYMORPHIC_SUPPORTED_TYPES_2(CXXOperatorCallExpr, CXXMethodDecl)>(
+ AST_POLYMORPHIC_SUPPORTED_TYPES_2(CXXOperatorCallExpr, FunctionDecl)>(
Name);
}
@@ -1671,12 +1767,9 @@ const internal::ArgumentAdaptingMatcherFunc<
/// \endcode
///
/// Usable as: Any Matcher
-template <typename M>
-internal::PolymorphicMatcherWithParam1<internal::NotMatcher, M>
-unless(const M &InnerMatcher) {
- return internal::PolymorphicMatcherWithParam1<
- internal::NotMatcher, M>(InnerMatcher);
-}
+const internal::VariadicOperatorMatcherFunc<1, 1> unless = {
+ internal::NotUnaryOperator
+};
/// \brief Matches a node if the declaration associated with that node
/// matches the given matcher.
@@ -1718,7 +1811,7 @@ AST_MATCHER_P(CXXMemberCallExpr, on, internal::Matcher<Expr>,
InnerMatcher) {
const Expr *ExprNode = Node.getImplicitObjectArgument()
->IgnoreParenImpCasts();
- return (ExprNode != NULL &&
+ return (ExprNode != nullptr &&
InnerMatcher.matches(*ExprNode, Finder, Builder));
}
@@ -1741,7 +1834,7 @@ AST_MATCHER_P(CXXMemberCallExpr, on, internal::Matcher<Expr>,
AST_MATCHER_P(CallExpr, callee, internal::Matcher<Stmt>,
InnerMatcher) {
const Expr *ExprNode = Node.getCallee();
- return (ExprNode != NULL &&
+ return (ExprNode != nullptr &&
InnerMatcher.matches(*ExprNode, Finder, Builder));
}
@@ -1896,7 +1989,7 @@ AST_MATCHER_P_OVERLOAD(QualType, references, internal::Matcher<Decl>,
AST_MATCHER_P(CXXMemberCallExpr, onImplicitObjectArgument,
internal::Matcher<Expr>, InnerMatcher) {
const Expr *ExprNode = Node.getImplicitObjectArgument();
- return (ExprNode != NULL &&
+ return (ExprNode != nullptr &&
InnerMatcher.matches(*ExprNode, Finder, Builder));
}
@@ -1929,7 +2022,7 @@ AST_MATCHER_P_OVERLOAD(CXXMemberCallExpr, thisPointerType,
AST_MATCHER_P(DeclRefExpr, to, internal::Matcher<Decl>,
InnerMatcher) {
const Decl *DeclNode = Node.getDecl();
- return (DeclNode != NULL &&
+ return (DeclNode != nullptr &&
InnerMatcher.matches(*DeclNode, Finder, Builder));
}
@@ -1986,10 +2079,39 @@ AST_MATCHER_P(
VarDecl, hasInitializer, internal::Matcher<Expr>,
InnerMatcher) {
const Expr *Initializer = Node.getAnyInitializer();
- return (Initializer != NULL &&
+ 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 Checks that a call expression or a constructor call expression has
/// a specific number of arguments (including absent default arguments).
///
@@ -2098,7 +2220,7 @@ AST_MATCHER_P(CXXConstructorDecl, hasAnyConstructorInitializer,
AST_MATCHER_P(CXXCtorInitializer, forField,
internal::Matcher<FieldDecl>, InnerMatcher) {
const FieldDecl *NodeAsDecl = Node.getMember();
- return (NodeAsDecl != NULL &&
+ return (NodeAsDecl != nullptr &&
InnerMatcher.matches(*NodeAsDecl, Finder, Builder));
}
@@ -2118,7 +2240,7 @@ AST_MATCHER_P(CXXCtorInitializer, forField,
AST_MATCHER_P(CXXCtorInitializer, withInitializer,
internal::Matcher<Expr>, InnerMatcher) {
const Expr* NodeAsExpr = Node.getInit();
- return (NodeAsExpr != NULL &&
+ return (NodeAsExpr != nullptr &&
InnerMatcher.matches(*NodeAsExpr, Finder, Builder));
}
@@ -2139,12 +2261,6 @@ AST_MATCHER(CXXCtorInitializer, isWritten) {
return Node.isWritten();
}
-/// \brief Matches a constructor declaration that has been implicitly added
-/// by the compiler (eg. implicit default/copy constructors).
-AST_MATCHER(CXXConstructorDecl, isImplicit) {
- return Node.isImplicit();
-}
-
/// \brief Matches any argument of a call expression or a constructor call
/// expression.
///
@@ -2175,6 +2291,11 @@ AST_POLYMORPHIC_MATCHER_P(hasAnyArgument, AST_POLYMORPHIC_SUPPORTED_TYPES_2(
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
@@ -2234,7 +2355,7 @@ AST_MATCHER_P(FunctionDecl, parameterCountIs, unsigned, N) {
/// matches int f() { return 1; }
AST_MATCHER_P(FunctionDecl, returns,
internal::Matcher<QualType>, InnerMatcher) {
- return InnerMatcher.matches(Node.getResultType(), Finder, Builder);
+ return InnerMatcher.matches(Node.getReturnType(), Finder, Builder);
}
/// \brief Matches extern "C" function declarations.
@@ -2263,19 +2384,33 @@ AST_POLYMORPHIC_MATCHER_P(
IfStmt, ForStmt, WhileStmt, DoStmt, ConditionalOperator),
internal::Matcher<Expr>, InnerMatcher) {
const Expr *const Condition = Node.getCond();
- return (Condition != NULL &&
+ return (Condition != nullptr &&
InnerMatcher.matches(*Condition, Finder, Builder));
}
-namespace internal {
-struct NotEqualsBoundNodePredicate {
- bool operator()(const internal::BoundNodesMap &Nodes) const {
- return Nodes.getNode(ID) != Node;
- }
- std::string ID;
- ast_type_traits::DynTypedNode Node;
-};
-} // namespace internal
+/// \brief Matches the then-statement of an if statement.
+///
+/// Examples matches the if statement
+/// (matcher = ifStmt(hasThen(boolLiteral(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(boolLiteral(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.
///
@@ -2325,7 +2460,7 @@ AST_MATCHER_P(IfStmt, hasConditionVariableStatement,
internal::Matcher<DeclStmt>, InnerMatcher) {
const DeclStmt* const DeclarationStatement =
Node.getConditionVariableDeclStmt();
- return DeclarationStatement != NULL &&
+ return DeclarationStatement != nullptr &&
InnerMatcher.matches(*DeclarationStatement, Finder, Builder);
}
@@ -2373,11 +2508,13 @@ AST_MATCHER_P(ArraySubscriptExpr, hasBase,
/// matches 'for (;;) {}'
/// with compoundStmt()
/// matching '{}'
-AST_POLYMORPHIC_MATCHER_P(
- hasBody, AST_POLYMORPHIC_SUPPORTED_TYPES_3(DoStmt, ForStmt, WhileStmt),
- internal::Matcher<Stmt>, InnerMatcher) {
+AST_POLYMORPHIC_MATCHER_P(hasBody,
+ AST_POLYMORPHIC_SUPPORTED_TYPES_4(DoStmt, ForStmt,
+ WhileStmt,
+ CXXForRangeStmt),
+ internal::Matcher<Stmt>, InnerMatcher) {
const Stmt *const Statement = Node.getBody();
- return (Statement != NULL &&
+ return (Statement != nullptr &&
InnerMatcher.matches(*Statement, Finder, Builder));
}
@@ -2451,7 +2588,7 @@ AST_POLYMORPHIC_MATCHER_P(hasOperatorName, AST_POLYMORPHIC_SUPPORTED_TYPES_2(
AST_MATCHER_P(BinaryOperator, hasLHS,
internal::Matcher<Expr>, InnerMatcher) {
Expr *LeftHandSide = Node.getLHS();
- return (LeftHandSide != NULL &&
+ return (LeftHandSide != nullptr &&
InnerMatcher.matches(*LeftHandSide, Finder, Builder));
}
@@ -2464,7 +2601,7 @@ AST_MATCHER_P(BinaryOperator, hasLHS,
AST_MATCHER_P(BinaryOperator, hasRHS,
internal::Matcher<Expr>, InnerMatcher) {
Expr *RightHandSide = Node.getRHS();
- return (RightHandSide != NULL &&
+ return (RightHandSide != nullptr &&
InnerMatcher.matches(*RightHandSide, Finder, Builder));
}
@@ -2484,7 +2621,7 @@ inline internal::Matcher<BinaryOperator> hasEitherOperand(
AST_MATCHER_P(UnaryOperator, hasUnaryOperand,
internal::Matcher<Expr>, InnerMatcher) {
const Expr * const Operand = Node.getSubExpr();
- return (Operand != NULL &&
+ return (Operand != nullptr &&
InnerMatcher.matches(*Operand, Finder, Builder));
}
@@ -2498,7 +2635,7 @@ AST_MATCHER_P(UnaryOperator, hasUnaryOperand,
AST_MATCHER_P(CastExpr, hasSourceExpression,
internal::Matcher<Expr>, InnerMatcher) {
const Expr* const SubExpression = Node.getSubExpr();
- return (SubExpression != NULL &&
+ return (SubExpression != nullptr &&
InnerMatcher.matches(*SubExpression, Finder, Builder));
}
@@ -2530,7 +2667,7 @@ AST_MATCHER_P(ImplicitCastExpr, hasImplicitDestinationType,
AST_MATCHER_P(ConditionalOperator, hasTrueExpression,
internal::Matcher<Expr>, InnerMatcher) {
Expr *Expression = Node.getTrueExpr();
- return (Expression != NULL &&
+ return (Expression != nullptr &&
InnerMatcher.matches(*Expression, Finder, Builder));
}
@@ -2543,7 +2680,7 @@ AST_MATCHER_P(ConditionalOperator, hasTrueExpression,
AST_MATCHER_P(ConditionalOperator, hasFalseExpression,
internal::Matcher<Expr>, InnerMatcher) {
Expr *Expression = Node.getFalseExpr();
- return (Expression != NULL &&
+ return (Expression != nullptr &&
InnerMatcher.matches(*Expression, Finder, Builder));
}
@@ -2585,7 +2722,7 @@ AST_POLYMORPHIC_MATCHER(isDefinition, AST_POLYMORPHIC_SUPPORTED_TYPES_3(
AST_MATCHER_P(CXXMethodDecl, ofClass,
internal::Matcher<CXXRecordDecl>, InnerMatcher) {
const CXXRecordDecl *Parent = Node.getParent();
- return (Parent != NULL &&
+ return (Parent != nullptr &&
InnerMatcher.matches(*Parent, Finder, Builder));
}
@@ -2603,6 +2740,20 @@ AST_MATCHER(CXXMethodDecl, isVirtual) {
return Node.isVirtual();
}
+/// \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
@@ -2822,8 +2973,8 @@ AST_POLYMORPHIC_MATCHER(
/// \brief Matches \c TypeLocs for which the given inner
/// QualType-matcher matches.
-inline internal::BindableMatcher<TypeLoc> loc(
- const internal::Matcher<QualType> &InnerMatcher) {
+AST_MATCHER_FUNCTION_P_OVERLOAD(internal::BindableMatcher<TypeLoc>, loc,
+ internal::Matcher<QualType>, InnerMatcher, 0) {
return internal::BindableMatcher<TypeLoc>(
new internal::TypeLocTypeMatcher(InnerMatcher));
}
@@ -3306,8 +3457,9 @@ const internal::VariadicAllOfMatcher<
/// \brief Matches \c NestedNameSpecifierLocs for which the given inner
/// NestedNameSpecifier-matcher matches.
-inline internal::BindableMatcher<NestedNameSpecifierLoc> loc(
- const internal::Matcher<NestedNameSpecifier> &InnerMatcher) {
+AST_MATCHER_FUNCTION_P_OVERLOAD(
+ internal::BindableMatcher<NestedNameSpecifierLoc>, loc,
+ internal::Matcher<NestedNameSpecifier>, InnerMatcher, 1) {
return internal::BindableMatcher<NestedNameSpecifierLoc>(
new internal::LocMatcher<NestedNameSpecifierLoc, NestedNameSpecifier>(
InnerMatcher));
@@ -3325,7 +3477,7 @@ inline internal::BindableMatcher<NestedNameSpecifierLoc> loc(
/// matches "A::"
AST_MATCHER_P(NestedNameSpecifier, specifiesType,
internal::Matcher<QualType>, InnerMatcher) {
- if (Node.getAsType() == NULL)
+ if (!Node.getAsType())
return false;
return InnerMatcher.matches(QualType(Node.getAsType(), 0), Finder, Builder);
}
@@ -3343,7 +3495,7 @@ AST_MATCHER_P(NestedNameSpecifier, specifiesType,
/// matches "A::"
AST_MATCHER_P(NestedNameSpecifierLoc, specifiesTypeLoc,
internal::Matcher<TypeLoc>, InnerMatcher) {
- return InnerMatcher.matches(Node.getTypeLoc(), Finder, Builder);
+ return Node && InnerMatcher.matches(Node.getTypeLoc(), Finder, Builder);
}
/// \brief Matches on the prefix of a \c NestedNameSpecifier.
@@ -3359,7 +3511,7 @@ AST_MATCHER_P_OVERLOAD(NestedNameSpecifier, hasPrefix,
internal::Matcher<NestedNameSpecifier>, InnerMatcher,
0) {
NestedNameSpecifier *NextNode = Node.getPrefix();
- if (NextNode == NULL)
+ if (!NextNode)
return false;
return InnerMatcher.matches(*NextNode, Finder, Builder);
}
@@ -3394,7 +3546,7 @@ AST_MATCHER_P_OVERLOAD(NestedNameSpecifierLoc, hasPrefix,
/// matches "ns::"
AST_MATCHER_P(NestedNameSpecifier, specifiesNamespace,
internal::Matcher<NamespaceDecl>, InnerMatcher) {
- if (Node.getAsNamespace() == NULL)
+ if (!Node.getAsNamespace())
return false;
return InnerMatcher.matches(*Node.getAsNamespace(), Finder, Builder);
}
@@ -3406,14 +3558,14 @@ AST_MATCHER_P(NestedNameSpecifier, specifiesNamespace,
/// \brief Matches if a node equals another node.
///
/// \c Decl has pointer identity in the AST.
-AST_MATCHER_P_OVERLOAD(Decl, equalsNode, Decl*, Other, 0) {
+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, Stmt*, Other, 1) {
+AST_MATCHER_P_OVERLOAD(Stmt, equalsNode, const Stmt*, Other, 1) {
return &Node == Other;
}
@@ -3463,11 +3615,9 @@ AST_MATCHER_P(CXXConstructorDecl, forEachConstructorInitializer,
internal::Matcher<CXXCtorInitializer>, InnerMatcher) {
BoundNodesTreeBuilder Result;
bool Matched = false;
- for (CXXConstructorDecl::init_const_iterator I = Node.init_begin(),
- E = Node.init_end();
- I != E; ++I) {
+ for (const auto *I : Node.inits()) {
BoundNodesTreeBuilder InitBuilder(*Builder);
- if (InnerMatcher.matches(**I, Finder, &InitBuilder)) {
+ if (InnerMatcher.matches(*I, Finder, &InitBuilder)) {
Matched = true;
Result.addMatch(InitBuilder);
}
diff --git a/include/clang/ASTMatchers/ASTMatchersInternal.h b/include/clang/ASTMatchers/ASTMatchersInternal.h
index 69cee2eb5dfd..94435fd274eb 100644
--- a/include/clang/ASTMatchers/ASTMatchersInternal.h
+++ b/include/clang/ASTMatchers/ASTMatchersInternal.h
@@ -44,7 +44,6 @@
#include "clang/AST/Type.h"
#include "llvm/ADT/Optional.h"
#include "llvm/ADT/VariadicFunction.h"
-#include "llvm/Support/type_traits.h"
#include <map>
#include <string>
#include <vector>
@@ -52,11 +51,6 @@
namespace clang {
namespace ast_matchers {
-/// FIXME: Move into the llvm support library.
-template <bool> struct CompileAssert {};
-#define TOOLING_COMPILE_ASSERT(Expr, Msg) \
- typedef CompileAssert<(bool(Expr))> Msg[bool(Expr) ? 1 : -1]
-
class BoundNodes;
namespace internal {
@@ -80,7 +74,7 @@ public:
const T *getNodeAs(StringRef ID) const {
IDToNodeMap::const_iterator It = NodeMap.find(ID);
if (It == NodeMap.end()) {
- return NULL;
+ return nullptr;
}
return It->second.get<T>();
}
@@ -198,9 +192,9 @@ public:
private:
/// Implements MatcherInterface::Matches.
- virtual bool matches(const T &Node,
- ASTMatchFinder * /* Finder */,
- BoundNodesTreeBuilder * /* Builder */) const {
+ bool matches(const T &Node,
+ ASTMatchFinder * /* Finder */,
+ BoundNodesTreeBuilder * /* Builder */) const override {
return matchesNode(Node);
}
};
@@ -225,9 +219,8 @@ public:
/// Requires \c T to be derived from \c From.
template <typename From>
Matcher(const Matcher<From> &Other,
- typename llvm::enable_if_c<
- llvm::is_base_of<From, T>::value &&
- !llvm::is_same<From, T>::value >::type* = 0)
+ typename std::enable_if<std::is_base_of<From, T>::value &&
+ !std::is_same<From, T>::value>::type * = 0)
: Implementation(new ImplicitCastMatcher<From>(Other)) {}
/// \brief Implicitly converts \c Matcher<Type> to \c Matcher<QualType>.
@@ -235,9 +228,9 @@ public:
/// The resulting matcher is not strict, i.e. ignores qualifiers.
template <typename TypeT>
Matcher(const Matcher<TypeT> &Other,
- typename llvm::enable_if_c<
- llvm::is_same<T, QualType>::value &&
- llvm::is_same<TypeT, Type>::value >::type* = 0)
+ typename std::enable_if<
+ std::is_same<T, QualType>::value &&
+ std::is_same<TypeT, Type>::value>::type* = 0)
: Implementation(new TypeToQualType<TypeT>(Other)) {}
/// \brief Forwards the call to the underlying MatcherInterface<T> pointer.
@@ -257,7 +250,7 @@ public:
uint64_t getID() const {
/// FIXME: Document the requirements this imposes on matcher
/// implementations (no new() implementation_ during a Matches()).
- return reinterpret_cast<uint64_t>(Implementation.getPtr());
+ return reinterpret_cast<uint64_t>(Implementation.get());
}
/// \brief Allows the conversion of a \c Matcher<Type> to a \c
@@ -272,9 +265,8 @@ public:
TypeToQualType(const Matcher<TypeT> &InnerMatcher)
: InnerMatcher(InnerMatcher) {}
- virtual bool matches(const QualType &Node,
- ASTMatchFinder *Finder,
- BoundNodesTreeBuilder *Builder) const {
+ bool matches(const QualType &Node, ASTMatchFinder *Finder,
+ BoundNodesTreeBuilder *Builder) const override {
if (Node.isNull())
return false;
return InnerMatcher.matches(*Node, Finder, Builder);
@@ -292,9 +284,8 @@ private:
explicit ImplicitCastMatcher(const Matcher<Base> &From)
: From(From) {}
- virtual bool matches(const T &Node,
- ASTMatchFinder *Finder,
- BoundNodesTreeBuilder *Builder) const {
+ bool matches(const T &Node, ASTMatchFinder *Finder,
+ BoundNodesTreeBuilder *Builder) const override {
return From.matches(Node, Finder, Builder);
}
@@ -379,9 +370,7 @@ public:
/// 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 {
- return Matcher<T>(new WrappedMatcher<T>(*this));
- }
+ template <typename T> Matcher<T> unconditionalConvertTo() const;
private:
class MatcherStorage : public RefCountedBaseVPTR {
@@ -410,9 +399,6 @@ private:
/// \brief Typed implementation of \c MatcherStorage.
template <typename T> class TypedMatcherStorage;
- /// \brief Simple MatcherInterface<T> wrapper around a DynTypedMatcher.
- template <typename T> class WrappedMatcher;
-
IntrusiveRefCntPtr<const MatcherStorage> Storage;
};
@@ -425,15 +411,15 @@ public:
InnerMatcher(Other), AllowBind(AllowBind) {}
bool matches(const ast_type_traits::DynTypedNode DynNode,
- ASTMatchFinder *Finder, BoundNodesTreeBuilder *Builder) const
- LLVM_OVERRIDE {
+ ASTMatchFinder *Finder,
+ BoundNodesTreeBuilder *Builder) const override {
if (const T *Node = DynNode.get<T>()) {
return InnerMatcher.matches(*Node, Finder, Builder);
}
return false;
}
- llvm::Optional<DynTypedMatcher> tryBind(StringRef ID) const LLVM_OVERRIDE {
+ llvm::Optional<DynTypedMatcher> tryBind(StringRef ID) const override {
if (!AllowBind)
return llvm::Optional<DynTypedMatcher>();
return DynTypedMatcher(BindableMatcher<T>(InnerMatcher).bind(ID));
@@ -452,22 +438,6 @@ template <typename T>
inline DynTypedMatcher::DynTypedMatcher(const BindableMatcher<T> &M)
: Storage(new TypedMatcherStorage<T>(M, true)) {}
-template <typename T>
-class DynTypedMatcher::WrappedMatcher : public MatcherInterface<T> {
-public:
- explicit WrappedMatcher(const DynTypedMatcher &Matcher) : Inner(Matcher) {}
- virtual ~WrappedMatcher() {}
-
- bool matches(const T &Node, ASTMatchFinder *Finder,
- BoundNodesTreeBuilder *Builder) const {
- return Inner.matches(ast_type_traits::DynTypedNode::create(Node), Finder,
- Builder);
- }
-
-private:
- const DynTypedMatcher Inner;
-};
-
/// \brief Specialization of the conversion functions for QualType.
///
/// These specializations provide the Matcher<Type>->Matcher<QualType>
@@ -537,7 +507,7 @@ template <typename T> struct has_getDecl {
static char (&f(CheckT<int Default::*, &C::getDecl>*))[1];
template<typename C> static char (&f(...))[2];
- static bool const value = sizeof(f<Derived>(0)) == 2;
+ static bool const value = sizeof(f<Derived>(nullptr)) == 2;
};
/// \brief Matches overloaded operators with a specific name.
@@ -546,16 +516,17 @@ template <typename T> struct has_getDecl {
/// PolymorphicMatcherWithParam1 and should be StringRef.
template <typename T, typename ArgT>
class HasOverloadedOperatorNameMatcher : public SingleNodeMatcherInterface<T> {
- TOOLING_COMPILE_ASSERT((llvm::is_same<T, CXXOperatorCallExpr>::value ||
- llvm::is_same<T, CXXMethodDecl>::value),
- unsupported_class_for_matcher);
- TOOLING_COMPILE_ASSERT((llvm::is_same<ArgT, StringRef>::value),
- argument_type_must_be_StringRef);
+ 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) {}
- virtual bool matchesNode(const T &Node) const LLVM_OVERRIDE {
+ bool matchesNode(const T &Node) const override {
return matchesSpecialized(Node);
}
@@ -570,7 +541,7 @@ private:
/// \brief Returns true only if CXXMethodDecl represents an overloaded
/// operator and has the given operator name.
- bool matchesSpecialized(const CXXMethodDecl &Node) const {
+ bool matchesSpecialized(const FunctionDecl &Node) const {
return Node.isOverloadedOperator() &&
getOperatorSpelling(Node.getOverloadedOperator()) == Name;
}
@@ -584,16 +555,15 @@ private:
/// not actually used.
template <typename T, typename DeclMatcherT>
class HasDeclarationMatcher : public MatcherInterface<T> {
- TOOLING_COMPILE_ASSERT((llvm::is_same< DeclMatcherT,
- Matcher<Decl> >::value),
- instantiated_with_wrong_types);
+ static_assert(std::is_same<DeclMatcherT, Matcher<Decl>>::value,
+ "instantiated with wrong types");
+
public:
explicit HasDeclarationMatcher(const Matcher<Decl> &InnerMatcher)
: InnerMatcher(InnerMatcher) {}
- virtual bool matches(const T &Node,
- ASTMatchFinder *Finder,
- BoundNodesTreeBuilder *Builder) const {
+ bool matches(const T &Node, ASTMatchFinder *Finder,
+ BoundNodesTreeBuilder *Builder) const override {
return matchesSpecialized(Node, Finder, Builder);
}
@@ -603,7 +573,7 @@ private:
template <typename U>
bool matchesSpecialized(
const U &Node, ASTMatchFinder *Finder, BoundNodesTreeBuilder *Builder,
- typename llvm::enable_if<has_getDecl<U>, int>::type = 0) const {
+ typename std::enable_if<has_getDecl<U>::value, int>::type = 0) const {
return matchesDecl(Node.getDecl(), Finder, Builder);
}
@@ -656,7 +626,7 @@ private:
bool matchesDecl(const Decl *Node,
ASTMatchFinder *Finder,
BoundNodesTreeBuilder *Builder) const {
- return Node != NULL && InnerMatcher.matches(*Node, Finder, Builder);
+ return Node != nullptr && InnerMatcher.matches(*Node, Finder, Builder);
}
const Matcher<Decl> InnerMatcher;
@@ -667,14 +637,14 @@ private:
template <typename T>
struct IsBaseType {
static const bool value =
- (llvm::is_same<T, Decl>::value ||
- llvm::is_same<T, Stmt>::value ||
- llvm::is_same<T, QualType>::value ||
- llvm::is_same<T, Type>::value ||
- llvm::is_same<T, TypeLoc>::value ||
- llvm::is_same<T, NestedNameSpecifier>::value ||
- llvm::is_same<T, NestedNameSpecifierLoc>::value ||
- llvm::is_same<T, CXXCtorInitializer>::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;
@@ -740,14 +710,13 @@ public:
BoundNodesTreeBuilder *Builder,
TraversalKind Traverse,
BindKind Bind) {
- TOOLING_COMPILE_ASSERT(
- (llvm::is_base_of<Decl, T>::value ||
- llvm::is_base_of<Stmt, T>::value ||
- llvm::is_base_of<NestedNameSpecifier, T>::value ||
- llvm::is_base_of<NestedNameSpecifierLoc, T>::value ||
- llvm::is_base_of<TypeLoc, T>::value ||
- llvm::is_base_of<QualType, T>::value),
- unsupported_type_for_recursive_matching);
+ 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);
}
@@ -757,14 +726,13 @@ public:
const DynTypedMatcher &Matcher,
BoundNodesTreeBuilder *Builder,
BindKind Bind) {
- TOOLING_COMPILE_ASSERT(
- (llvm::is_base_of<Decl, T>::value ||
- llvm::is_base_of<Stmt, T>::value ||
- llvm::is_base_of<NestedNameSpecifier, T>::value ||
- llvm::is_base_of<NestedNameSpecifierLoc, T>::value ||
- llvm::is_base_of<TypeLoc, T>::value ||
- llvm::is_base_of<QualType, T>::value),
- unsupported_type_for_recursive_matching);
+ 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);
}
@@ -775,9 +743,9 @@ public:
const DynTypedMatcher &Matcher,
BoundNodesTreeBuilder *Builder,
AncestorMatchMode MatchMode) {
- TOOLING_COMPILE_ASSERT((llvm::is_base_of<Decl, T>::value ||
- llvm::is_base_of<Stmt, T>::value),
- only_Decl_or_Stmt_allowed_for_recursive_matching);
+ static_assert(std::is_base_of<Decl, T>::value ||
+ std::is_base_of<Stmt, T>::value,
+ "only Decl or Stmt allowed for recursive matching");
return matchesAncestorOf(ast_type_traits::DynTypedNode::create(Node),
Matcher, Builder, MatchMode);
}
@@ -820,7 +788,7 @@ struct TypeList {
/// \brief The first type on the list.
typedef T1 head;
- /// \brief A sub list with the tail. ie everything but the 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.
@@ -852,7 +820,7 @@ typedef TypeList<> EmptyTypeList;
template <typename AnyTypeList, typename T>
struct TypeListContainsSuperOf {
static const bool value =
- llvm::is_base_of<typename AnyTypeList::head, T>::value ||
+ std::is_base_of<typename AnyTypeList::head, T>::value ||
TypeListContainsSuperOf<typename AnyTypeList::tail, T>::value;
};
template <typename T>
@@ -952,8 +920,8 @@ public:
typedef typename ExtractFunctionArgMeta<ReturnTypesF>::type ReturnTypes;
template <typename T>
operator Matcher<T>() const {
- TOOLING_COMPILE_ASSERT((TypeListContainsSuperOf<ReturnTypes, T>::value),
- right_polymorphic_conversion);
+ static_assert(TypeListContainsSuperOf<ReturnTypes, T>::value,
+ "right polymorphic conversion");
return Matcher<T>(new MatcherT<T>());
}
};
@@ -970,8 +938,8 @@ public:
template <typename T>
operator Matcher<T>() const {
- TOOLING_COMPILE_ASSERT((TypeListContainsSuperOf<ReturnTypes, T>::value),
- right_polymorphic_conversion);
+ static_assert(TypeListContainsSuperOf<ReturnTypes, T>::value,
+ "right polymorphic conversion");
return Matcher<T>(new MatcherT<T, P1>(Param1));
}
@@ -991,8 +959,8 @@ public:
template <typename T>
operator Matcher<T>() const {
- TOOLING_COMPILE_ASSERT((TypeListContainsSuperOf<ReturnTypes, T>::value),
- right_polymorphic_conversion);
+ static_assert(TypeListContainsSuperOf<ReturnTypes, T>::value,
+ "right polymorphic conversion");
return Matcher<T>(new MatcherT<T, P1, P2>(Param1, Param2));
}
@@ -1018,7 +986,7 @@ private:
template <typename T>
class TrueMatcher : public SingleNodeMatcherInterface<T> {
public:
- virtual bool matchesNode(const T &Node) const {
+ bool matchesNode(const T &Node) const override {
return true;
}
};
@@ -1033,9 +1001,8 @@ public:
IdMatcher(StringRef ID, const Matcher<T> &InnerMatcher)
: ID(ID), InnerMatcher(InnerMatcher) {}
- virtual bool matches(const T &Node,
- ASTMatchFinder *Finder,
- BoundNodesTreeBuilder *Builder) const {
+ bool matches(const T &Node, ASTMatchFinder *Finder,
+ BoundNodesTreeBuilder *Builder) const override {
bool Result = InnerMatcher.matches(Node, Finder, Builder);
if (Result) {
Builder->setBinding(ID, &Node);
@@ -1074,15 +1041,15 @@ public:
/// ChildT must be an AST base type.
template <typename T, typename ChildT>
class HasMatcher : public MatcherInterface<T> {
- TOOLING_COMPILE_ASSERT(IsBaseType<ChildT>::value,
- has_only_accepts_base_type_matcher);
+ static_assert(IsBaseType<ChildT>::value,
+ "has only accepts base type matcher");
+
public:
explicit HasMatcher(const Matcher<ChildT> &ChildMatcher)
: ChildMatcher(ChildMatcher) {}
- virtual bool matches(const T &Node,
- ASTMatchFinder *Finder,
- BoundNodesTreeBuilder *Builder) const {
+ bool matches(const T &Node, ASTMatchFinder *Finder,
+ BoundNodesTreeBuilder *Builder) const override {
return Finder->matchesChildOf(
Node, ChildMatcher, Builder,
ASTMatchFinder::TK_IgnoreImplicitCastsAndParentheses,
@@ -1100,15 +1067,15 @@ public:
/// for each child that matches.
template <typename T, typename ChildT>
class ForEachMatcher : public MatcherInterface<T> {
- TOOLING_COMPILE_ASSERT(IsBaseType<ChildT>::value,
- for_each_only_accepts_base_type_matcher);
+ static_assert(IsBaseType<ChildT>::value,
+ "for each only accepts base type matcher");
+
public:
explicit ForEachMatcher(const Matcher<ChildT> &ChildMatcher)
: ChildMatcher(ChildMatcher) {}
- virtual bool matches(const T& Node,
- ASTMatchFinder* Finder,
- BoundNodesTreeBuilder* Builder) const {
+ bool matches(const T& Node, ASTMatchFinder* Finder,
+ BoundNodesTreeBuilder* Builder) const override {
return Finder->matchesChildOf(
Node, ChildMatcher, Builder,
ASTMatchFinder::TK_IgnoreImplicitCastsAndParentheses,
@@ -1119,38 +1086,6 @@ private:
const Matcher<ChildT> ChildMatcher;
};
-/// \brief Matches nodes of type T if the given Matcher<T> does not match.
-///
-/// Type argument MatcherT is required by PolymorphicMatcherWithParam1
-/// but not actually used. It will always be instantiated with a type
-/// convertible to Matcher<T>.
-template <typename T, typename MatcherT>
-class NotMatcher : public MatcherInterface<T> {
-public:
- explicit NotMatcher(const Matcher<T> &InnerMatcher)
- : InnerMatcher(InnerMatcher) {}
-
- virtual bool matches(const T &Node,
- ASTMatchFinder *Finder,
- BoundNodesTreeBuilder *Builder) const {
- // The 'unless' matcher will always discard the result:
- // If the inner matcher doesn't match, unless returns true,
- // but the inner matcher cannot have bound anything.
- // If the inner matcher matches, the result is false, and
- // any possible binding will be discarded.
- // We still need to hand in all the bound nodes up to this
- // point so the inner matcher can depend on bound nodes,
- // and we need to actively discard the bound nodes, otherwise
- // the inner matcher will reset the bound nodes if it doesn't
- // match, but this would be inversed by 'unless'.
- BoundNodesTreeBuilder Discard(*Builder);
- return !InnerMatcher.matches(Node, Finder, &Discard);
- }
-
-private:
- const Matcher<T> InnerMatcher;
-};
-
/// \brief VariadicOperatorMatcher related types.
/// @{
@@ -1165,22 +1100,18 @@ template <typename T>
class VariadicOperatorMatcherInterface : public MatcherInterface<T> {
public:
VariadicOperatorMatcherInterface(VariadicOperatorFunction Func,
- ArrayRef<const Matcher<T> *> InputMatchers)
- : Func(Func) {
- for (size_t i = 0, e = InputMatchers.size(); i != e; ++i) {
- InnerMatchers.push_back(*InputMatchers[i]);
- }
- }
+ std::vector<DynTypedMatcher> InnerMatchers)
+ : Func(Func), InnerMatchers(std::move(InnerMatchers)) {}
- virtual bool matches(const T &Node, ASTMatchFinder *Finder,
- BoundNodesTreeBuilder *Builder) const {
+ bool matches(const T &Node, ASTMatchFinder *Finder,
+ BoundNodesTreeBuilder *Builder) const override {
return Func(ast_type_traits::DynTypedNode::create(Node), Finder, Builder,
InnerMatchers);
}
private:
const VariadicOperatorFunction Func;
- std::vector<DynTypedMatcher> InnerMatchers;
+ const std::vector<DynTypedMatcher> InnerMatchers;
};
/// \brief "No argument" placeholder to use as template paratemers.
@@ -1192,46 +1123,55 @@ struct VariadicOperatorNoArg {};
/// 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 P1, typename P2,
+template <typename P1, typename P2 = VariadicOperatorNoArg,
typename P3 = VariadicOperatorNoArg,
typename P4 = VariadicOperatorNoArg,
- typename P5 = VariadicOperatorNoArg>
+ typename P5 = VariadicOperatorNoArg,
+ typename P6 = VariadicOperatorNoArg,
+ typename P7 = VariadicOperatorNoArg,
+ typename P8 = VariadicOperatorNoArg,
+ typename P9 = VariadicOperatorNoArg>
class VariadicOperatorMatcher {
public:
VariadicOperatorMatcher(VariadicOperatorFunction Func, const P1 &Param1,
- const P2 &Param2,
+ const P2 &Param2 = VariadicOperatorNoArg(),
const P3 &Param3 = VariadicOperatorNoArg(),
const P4 &Param4 = VariadicOperatorNoArg(),
- const P5 &Param5 = VariadicOperatorNoArg())
+ const P5 &Param5 = VariadicOperatorNoArg(),
+ const P6 &Param6 = VariadicOperatorNoArg(),
+ const P7 &Param7 = VariadicOperatorNoArg(),
+ const P8 &Param8 = VariadicOperatorNoArg(),
+ const P9 &Param9 = VariadicOperatorNoArg())
: Func(Func), Param1(Param1), Param2(Param2), Param3(Param3),
- Param4(Param4), Param5(Param5) {}
+ Param4(Param4), Param5(Param5), Param6(Param6), Param7(Param7),
+ Param8(Param8), Param9(Param9) {}
template <typename T> operator Matcher<T>() const {
- Matcher<T> *Array[5];
- size_t Size = 0;
-
- addMatcher<T>(Param1, Array, Size);
- addMatcher<T>(Param2, Array, Size);
- addMatcher<T>(Param3, Array, Size);
- addMatcher<T>(Param4, Array, Size);
- addMatcher<T>(Param5, Array, Size);
- Matcher<T> Result(new VariadicOperatorMatcherInterface<T>(
- Func, ArrayRef<const Matcher<T> *>(Array, Size)));
- for (size_t i = 0, e = Size; i != e; ++i) delete Array[i];
- return Result;
+ std::vector<DynTypedMatcher> Matchers;
+ addMatcher<T>(Param1, Matchers);
+ addMatcher<T>(Param2, Matchers);
+ addMatcher<T>(Param3, Matchers);
+ addMatcher<T>(Param4, Matchers);
+ addMatcher<T>(Param5, Matchers);
+ addMatcher<T>(Param6, Matchers);
+ addMatcher<T>(Param7, Matchers);
+ addMatcher<T>(Param8, Matchers);
+ addMatcher<T>(Param9, Matchers);
+ return Matcher<T>(
+ new VariadicOperatorMatcherInterface<T>(Func, std::move(Matchers)));
}
private:
template <typename T>
- static void addMatcher(const Matcher<T> &M, Matcher<T> **Array,
- size_t &Size) {
- Array[Size++] = new Matcher<T>(M);
+ static void addMatcher(const Matcher<T> &M,
+ std::vector<DynTypedMatcher> &Matchers) {
+ Matchers.push_back(M);
}
/// \brief Overload to ignore \c VariadicOperatorNoArg arguments.
template <typename T>
- static void addMatcher(VariadicOperatorNoArg, Matcher<T> **Array,
- size_t &Size) {}
+ static void addMatcher(VariadicOperatorNoArg,
+ std::vector<DynTypedMatcher> &Matchers) {}
const VariadicOperatorFunction Func;
const P1 Param1;
@@ -1239,40 +1179,100 @@ private:
const P3 Param3;
const P4 Param4;
const P5 Param5;
+ const P6 Param6;
+ const P7 Param7;
+ const P8 Param8;
+ const P9 Param9;
};
/// \brief Overloaded function object to generate VariadicOperatorMatcher
/// objects from arbitrary matchers.
///
-/// It supports 2-5 argument overloaded operator(). More can be added if needed.
+/// It supports 1-9 argument overloaded operator(). More can be added if needed.
+template <unsigned MinCount, unsigned MaxCount>
struct VariadicOperatorMatcherFunc {
VariadicOperatorFunction Func;
+ template <unsigned Count, typename T>
+ struct EnableIfValidArity
+ : public std::enable_if<MinCount <= Count && Count <= MaxCount, T> {};
+
+ template <typename M1>
+ typename EnableIfValidArity<1, VariadicOperatorMatcher<M1> >::type
+ operator()(const M1 &P1) const {
+ return VariadicOperatorMatcher<M1>(Func, P1);
+ }
template <typename M1, typename M2>
- VariadicOperatorMatcher<M1, M2> operator()(const M1 &P1, const M2 &P2) const {
+ typename EnableIfValidArity<2, VariadicOperatorMatcher<M1, M2> >::type
+ operator()(const M1 &P1, const M2 &P2) const {
return VariadicOperatorMatcher<M1, M2>(Func, P1, P2);
}
template <typename M1, typename M2, typename M3>
- VariadicOperatorMatcher<M1, M2, M3> operator()(const M1 &P1, const M2 &P2,
- const M3 &P3) const {
+ typename EnableIfValidArity<3, VariadicOperatorMatcher<M1, M2, M3> >::type
+ operator()(const M1 &P1, const M2 &P2, const M3 &P3) const {
return VariadicOperatorMatcher<M1, M2, M3>(Func, P1, P2, P3);
}
template <typename M1, typename M2, typename M3, typename M4>
- VariadicOperatorMatcher<M1, M2, M3, M4>
+ typename EnableIfValidArity<4, VariadicOperatorMatcher<M1, M2, M3, M4> >::type
operator()(const M1 &P1, const M2 &P2, const M3 &P3, const M4 &P4) const {
return VariadicOperatorMatcher<M1, M2, M3, M4>(Func, P1, P2, P3, P4);
}
template <typename M1, typename M2, typename M3, typename M4, typename M5>
- VariadicOperatorMatcher<M1, M2, M3, M4, M5>
+ typename EnableIfValidArity<
+ 5, VariadicOperatorMatcher<M1, M2, M3, M4, M5> >::type
operator()(const M1 &P1, const M2 &P2, const M3 &P3, const M4 &P4,
const M5 &P5) const {
return VariadicOperatorMatcher<M1, M2, M3, M4, M5>(Func, P1, P2, P3, P4,
P5);
}
+ template <typename M1, typename M2, typename M3, typename M4, typename M5,
+ typename M6>
+ typename EnableIfValidArity<
+ 6, VariadicOperatorMatcher<M1, M2, M3, M4, M5, M6> >::type
+ operator()(const M1 &P1, const M2 &P2, const M3 &P3, const M4 &P4,
+ const M5 &P5, const M6 &P6) const {
+ return VariadicOperatorMatcher<M1, M2, M3, M4, M5, M6>(
+ Func, P1, P2, P3, P4, P5, P6);
+ }
+ template <typename M1, typename M2, typename M3, typename M4, typename M5,
+ typename M6, typename M7>
+ typename EnableIfValidArity<
+ 7, VariadicOperatorMatcher<M1, M2, M3, M4, M5, M6, M7> >::type
+ operator()(const M1 &P1, const M2 &P2, const M3 &P3, const M4 &P4,
+ const M5 &P5, const M6 &P6, const M7 &P7) const {
+ return VariadicOperatorMatcher<M1, M2, M3, M4, M5, M6, M7>(
+ Func, P1, P2, P3, P4, P5, P6, P7);
+ }
+ template <typename M1, typename M2, typename M3, typename M4, typename M5,
+ typename M6, typename M7, typename M8>
+ typename EnableIfValidArity<
+ 8, VariadicOperatorMatcher<M1, M2, M3, M4, M5, M6, M7, M8> >::type
+ operator()(const M1 &P1, const M2 &P2, const M3 &P3, const M4 &P4,
+ const M5 &P5, const M6 &P6, const M7 &P7, const M8 &P8) const {
+ return VariadicOperatorMatcher<M1, M2, M3, M4, M5, M6, M7, M8>(
+ Func, P1, P2, P3, P4, P5, P6, P7, P8);
+ }
+ template <typename M1, typename M2, typename M3, typename M4, typename M5,
+ typename M6, typename M7, typename M8, typename M9>
+ typename EnableIfValidArity<
+ 9, VariadicOperatorMatcher<M1, M2, M3, M4, M5, M6, M7, M8, M9> >::type
+ operator()(const M1 &P1, const M2 &P2, const M3 &P3, const M4 &P4,
+ const M5 &P5, const M6 &P6, const M7 &P7, const M8 &P8,
+ const M9 &P9) const {
+ return VariadicOperatorMatcher<M1, M2, M3, M4, M5, M6, M7, M8, M9>(
+ Func, P1, P2, P3, P4, P5, P6, P7, P8, P9);
+ }
};
/// @}
+/// \brief Matches nodes that do not match the provided matcher.
+///
+/// Uses the variadic matcher interface, but fails if InnerMatchers.size()!=1.
+bool NotUnaryOperator(const ast_type_traits::DynTypedNode DynNode,
+ ASTMatchFinder *Finder, BoundNodesTreeBuilder *Builder,
+ ArrayRef<DynTypedMatcher> InnerMatchers);
+
/// \brief Matches nodes for which all provided matchers match.
bool AllOfVariadicOperator(const ast_type_traits::DynTypedNode DynNode,
ASTMatchFinder *Finder,
@@ -1293,12 +1293,22 @@ bool AnyOfVariadicOperator(const ast_type_traits::DynTypedNode DynNode,
BoundNodesTreeBuilder *Builder,
ArrayRef<DynTypedMatcher> InnerMatchers);
+template <typename T>
+inline Matcher<T> DynTypedMatcher::unconditionalConvertTo() const {
+ return Matcher<T>(new VariadicOperatorMatcherInterface<T>(
+ AllOfVariadicOperator, llvm::makeArrayRef(*this)));
+}
+
/// \brief Creates a Matcher<T> that matches if all inner matchers match.
template<typename T>
BindableMatcher<T> makeAllOfComposite(
ArrayRef<const Matcher<T> *> InnerMatchers) {
+ std::vector<DynTypedMatcher> DynMatchers;
+ for (size_t i = 0, e = InnerMatchers.size(); i != e; ++i) {
+ DynMatchers.push_back(*InnerMatchers[i]);
+ }
return BindableMatcher<T>(new VariadicOperatorMatcherInterface<T>(
- AllOfVariadicOperator, InnerMatchers));
+ AllOfVariadicOperator, std::move(DynMatchers)));
}
/// \brief Creates a Matcher<T> that matches if
@@ -1320,15 +1330,15 @@ BindableMatcher<T> makeDynCastAllOfComposite(
/// DescendantT must be an AST base type.
template <typename T, typename DescendantT>
class HasDescendantMatcher : public MatcherInterface<T> {
- TOOLING_COMPILE_ASSERT(IsBaseType<DescendantT>::value,
- has_descendant_only_accepts_base_type_matcher);
+ static_assert(IsBaseType<DescendantT>::value,
+ "has descendant only accepts base type matcher");
+
public:
explicit HasDescendantMatcher(const Matcher<DescendantT> &DescendantMatcher)
: DescendantMatcher(DescendantMatcher) {}
- virtual bool matches(const T &Node,
- ASTMatchFinder *Finder,
- BoundNodesTreeBuilder *Builder) const {
+ bool matches(const T &Node, ASTMatchFinder *Finder,
+ BoundNodesTreeBuilder *Builder) const override {
return Finder->matchesDescendantOf(
Node, DescendantMatcher, Builder, ASTMatchFinder::BK_First);
}
@@ -1343,15 +1353,15 @@ public:
/// \c ParentT must be an AST base type.
template <typename T, typename ParentT>
class HasParentMatcher : public MatcherInterface<T> {
- TOOLING_COMPILE_ASSERT(IsBaseType<ParentT>::value,
- has_parent_only_accepts_base_type_matcher);
+ static_assert(IsBaseType<ParentT>::value,
+ "has parent only accepts base type matcher");
+
public:
explicit HasParentMatcher(const Matcher<ParentT> &ParentMatcher)
: ParentMatcher(ParentMatcher) {}
- virtual bool matches(const T &Node,
- ASTMatchFinder *Finder,
- BoundNodesTreeBuilder *Builder) const {
+ bool matches(const T &Node, ASTMatchFinder *Finder,
+ BoundNodesTreeBuilder *Builder) const override {
return Finder->matchesAncestorOf(
Node, ParentMatcher, Builder, ASTMatchFinder::AMM_ParentOnly);
}
@@ -1366,15 +1376,15 @@ public:
/// \c AncestorT must be an AST base type.
template <typename T, typename AncestorT>
class HasAncestorMatcher : public MatcherInterface<T> {
- TOOLING_COMPILE_ASSERT(IsBaseType<AncestorT>::value,
- has_ancestor_only_accepts_base_type_matcher);
+ static_assert(IsBaseType<AncestorT>::value,
+ "has ancestor only accepts base type matcher");
+
public:
explicit HasAncestorMatcher(const Matcher<AncestorT> &AncestorMatcher)
: AncestorMatcher(AncestorMatcher) {}
- virtual bool matches(const T &Node,
- ASTMatchFinder *Finder,
- BoundNodesTreeBuilder *Builder) const {
+ bool matches(const T &Node, ASTMatchFinder *Finder,
+ BoundNodesTreeBuilder *Builder) const override {
return Finder->matchesAncestorOf(
Node, AncestorMatcher, Builder, ASTMatchFinder::AMM_All);
}
@@ -1391,16 +1401,16 @@ public:
/// for each descendant node that matches instead of only for the first.
template <typename T, typename DescendantT>
class ForEachDescendantMatcher : public MatcherInterface<T> {
- TOOLING_COMPILE_ASSERT(IsBaseType<DescendantT>::value,
- for_each_descendant_only_accepts_base_type_matcher);
+ static_assert(IsBaseType<DescendantT>::value,
+ "for each descendant only accepts base type matcher");
+
public:
explicit ForEachDescendantMatcher(
const Matcher<DescendantT>& DescendantMatcher)
: DescendantMatcher(DescendantMatcher) {}
- virtual bool matches(const T& Node,
- ASTMatchFinder* Finder,
- BoundNodesTreeBuilder* Builder) const {
+ bool matches(const T& Node, ASTMatchFinder* Finder,
+ BoundNodesTreeBuilder* Builder) const override {
return Finder->matchesDescendantOf(Node, DescendantMatcher, Builder,
ASTMatchFinder::BK_All);
}
@@ -1413,17 +1423,17 @@ private:
/// the value the ValueEqualsMatcher was constructed with.
template <typename T, typename ValueT>
class ValueEqualsMatcher : public SingleNodeMatcherInterface<T> {
- TOOLING_COMPILE_ASSERT((llvm::is_base_of<CharacterLiteral, T>::value ||
- llvm::is_base_of<CXXBoolLiteralExpr,
- T>::value ||
- llvm::is_base_of<FloatingLiteral, T>::value ||
- llvm::is_base_of<IntegerLiteral, T>::value),
- the_node_must_have_a_getValue_method);
+ 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) {}
- virtual bool matchesNode(const T &Node) const {
+ bool matchesNode(const T &Node) const override {
return Node.getValue() == ExpectedValue;
}
@@ -1478,9 +1488,8 @@ public:
explicit LocMatcher(const Matcher<T> &InnerMatcher)
: InnerMatcher(InnerMatcher) {}
- virtual bool matches(const TLoc &Node,
- ASTMatchFinder *Finder,
- BoundNodesTreeBuilder *Builder) const {
+ bool matches(const TLoc &Node, ASTMatchFinder *Finder,
+ BoundNodesTreeBuilder *Builder) const override {
if (!Node)
return false;
return InnerMatcher.matches(*extract(Node), Finder, Builder);
@@ -1503,9 +1512,8 @@ public:
explicit TypeLocTypeMatcher(const Matcher<QualType> &InnerMatcher)
: InnerMatcher(InnerMatcher) {}
- virtual bool matches(const TypeLoc &Node,
- ASTMatchFinder *Finder,
- BoundNodesTreeBuilder *Builder) const {
+ bool matches(const TypeLoc &Node, ASTMatchFinder *Finder,
+ BoundNodesTreeBuilder *Builder) const override {
if (!Node)
return false;
return InnerMatcher.matches(Node.getType(), Finder, Builder);
@@ -1525,9 +1533,8 @@ public:
QualType (T::*TraverseFunction)() const)
: InnerMatcher(InnerMatcher), TraverseFunction(TraverseFunction) {}
- virtual bool matches(const T &Node,
- ASTMatchFinder *Finder,
- BoundNodesTreeBuilder *Builder) const {
+ bool matches(const T &Node, ASTMatchFinder *Finder,
+ BoundNodesTreeBuilder *Builder) const override {
QualType NextNode = (Node.*TraverseFunction)();
if (NextNode.isNull())
return false;
@@ -1549,9 +1556,8 @@ public:
TypeLoc (T::*TraverseFunction)() const)
: InnerMatcher(InnerMatcher), TraverseFunction(TraverseFunction) {}
- virtual bool matches(const T &Node,
- ASTMatchFinder *Finder,
- BoundNodesTreeBuilder *Builder) const {
+ bool matches(const T &Node, ASTMatchFinder *Finder,
+ BoundNodesTreeBuilder *Builder) const override {
TypeLoc NextNode = (Node.*TraverseFunction)();
if (!NextNode)
return false;
@@ -1612,6 +1618,26 @@ TypeTraversePolymorphicMatcher<
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 ArrayRef<TemplateArgument>(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
diff --git a/include/clang/ASTMatchers/ASTMatchersMacros.h b/include/clang/ASTMatchers/ASTMatchersMacros.h
index b5d530312515..563372a50609 100644
--- a/include/clang/ASTMatchers/ASTMatchersMacros.h
+++ b/include/clang/ASTMatchers/ASTMatchersMacros.h
@@ -37,6 +37,25 @@
#ifndef LLVM_CLANG_AST_MATCHERS_AST_MATCHERS_MACROS_H
#define LLVM_CLANG_AST_MATCHERS_AST_MATCHERS_MACROS_H
+/// \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.
@@ -53,8 +72,8 @@
class matcher_##DefineMatcher##Matcher : public MatcherInterface<Type> { \
public: \
explicit matcher_##DefineMatcher##Matcher() {} \
- virtual bool matches(const Type &Node, ASTMatchFinder *Finder, \
- BoundNodesTreeBuilder *Builder) const; \
+ bool matches(const Type &Node, ASTMatchFinder *Finder, \
+ BoundNodesTreeBuilder *Builder) const override; \
}; \
} \
inline internal::Matcher<Type> DefineMatcher() { \
@@ -88,21 +107,21 @@
: public MatcherInterface<Type> { \
public: \
explicit matcher_##DefineMatcher##OverloadId##Matcher( \
- const ParamType &A##Param) \
+ ParamType const &A##Param) \
: Param(A##Param) {} \
- virtual bool matches(const Type &Node, ASTMatchFinder *Finder, \
- BoundNodesTreeBuilder *Builder) const; \
+ bool matches(const Type &Node, ASTMatchFinder *Finder, \
+ BoundNodesTreeBuilder *Builder) const override; \
\
private: \
- const ParamType Param; \
+ ParamType const Param; \
}; \
} \
- inline internal::Matcher<Type> DefineMatcher(const ParamType &Param) { \
+ inline internal::Matcher<Type> DefineMatcher(ParamType const &Param) { \
return internal::makeMatcher( \
new internal::matcher_##DefineMatcher##OverloadId##Matcher(Param)); \
} \
typedef internal::Matcher<Type>(&DefineMatcher##_Type##OverloadId)( \
- const ParamType &Param); \
+ ParamType const &Param); \
inline bool internal::matcher_##DefineMatcher##OverloadId##Matcher::matches( \
const Type &Node, ASTMatchFinder *Finder, \
BoundNodesTreeBuilder *Builder) const
@@ -132,25 +151,25 @@
class matcher_##DefineMatcher##OverloadId##Matcher \
: public MatcherInterface<Type> { \
public: \
- matcher_##DefineMatcher##OverloadId##Matcher(const ParamType1 &A##Param1, \
- const ParamType2 &A##Param2) \
+ matcher_##DefineMatcher##OverloadId##Matcher(ParamType1 const &A##Param1, \
+ ParamType2 const &A##Param2) \
: Param1(A##Param1), Param2(A##Param2) {} \
- virtual bool matches(const Type &Node, ASTMatchFinder *Finder, \
- BoundNodesTreeBuilder *Builder) const; \
+ bool matches(const Type &Node, ASTMatchFinder *Finder, \
+ BoundNodesTreeBuilder *Builder) const override; \
\
private: \
- const ParamType1 Param1; \
- const ParamType2 Param2; \
+ ParamType1 const Param1; \
+ ParamType2 const Param2; \
}; \
} \
- inline internal::Matcher<Type> DefineMatcher(const ParamType1 &Param1, \
- const ParamType2 &Param2) { \
+ inline internal::Matcher<Type> DefineMatcher(ParamType1 const &Param1, \
+ ParamType2 const &Param2) { \
return internal::makeMatcher( \
new internal::matcher_##DefineMatcher##OverloadId##Matcher(Param1, \
Param2)); \
} \
typedef internal::Matcher<Type>(&DefineMatcher##_Type##OverloadId)( \
- const ParamType1 &Param1, const ParamType2 &Param2); \
+ ParamType1 const &Param1, ParamType2 const &Param2); \
inline bool internal::matcher_##DefineMatcher##OverloadId##Matcher::matches( \
const Type &Node, ASTMatchFinder *Finder, \
BoundNodesTreeBuilder *Builder) const
@@ -184,8 +203,8 @@
template <typename NodeType> \
class matcher_##DefineMatcher##Matcher : public MatcherInterface<NodeType> { \
public: \
- virtual bool matches(const NodeType &Node, ASTMatchFinder *Finder, \
- BoundNodesTreeBuilder *Builder) const; \
+ bool matches(const NodeType &Node, ASTMatchFinder *Finder, \
+ BoundNodesTreeBuilder *Builder) const override; \
}; \
} \
inline internal::PolymorphicMatcherWithParam0< \
@@ -221,18 +240,18 @@
: public MatcherInterface<NodeType> { \
public: \
explicit matcher_##DefineMatcher##OverloadId##Matcher( \
- const ParamType &A##Param) \
+ ParamType const &A##Param) \
: Param(A##Param) {} \
- virtual bool matches(const NodeType &Node, ASTMatchFinder *Finder, \
- BoundNodesTreeBuilder *Builder) const; \
+ bool matches(const NodeType &Node, ASTMatchFinder *Finder, \
+ BoundNodesTreeBuilder *Builder) const override; \
\
private: \
- const ParamType Param; \
+ ParamType const Param; \
}; \
} \
inline internal::PolymorphicMatcherWithParam1< \
internal::matcher_##DefineMatcher##OverloadId##Matcher, ParamType, \
- ReturnTypesF> DefineMatcher(const ParamType &Param) { \
+ ReturnTypesF> DefineMatcher(ParamType const &Param) { \
return internal::PolymorphicMatcherWithParam1< \
internal::matcher_##DefineMatcher##OverloadId##Matcher, ParamType, \
ReturnTypesF>(Param); \
@@ -240,7 +259,7 @@
typedef internal::PolymorphicMatcherWithParam1< \
internal::matcher_##DefineMatcher##OverloadId##Matcher, ParamType, \
ReturnTypesF>(&DefineMatcher##_Type##OverloadId)( \
- const ParamType &Param); \
+ ParamType const &Param); \
template <typename NodeType, typename ParamT> \
bool internal::matcher_##DefineMatcher##OverloadId##Matcher< \
NodeType, ParamT>::matches(const NodeType &Node, ASTMatchFinder *Finder, \
@@ -267,21 +286,21 @@
class matcher_##DefineMatcher##OverloadId##Matcher \
: public MatcherInterface<NodeType> { \
public: \
- matcher_##DefineMatcher##OverloadId##Matcher(const ParamType1 &A##Param1, \
- const ParamType2 &A##Param2) \
+ matcher_##DefineMatcher##OverloadId##Matcher(ParamType1 const &A##Param1, \
+ ParamType2 const &A##Param2) \
: Param1(A##Param1), Param2(A##Param2) {} \
- virtual bool matches(const NodeType &Node, ASTMatchFinder *Finder, \
- BoundNodesTreeBuilder *Builder) const; \
+ bool matches(const NodeType &Node, ASTMatchFinder *Finder, \
+ BoundNodesTreeBuilder *Builder) const override; \
\
private: \
- const ParamType1 Param1; \
- const ParamType2 Param2; \
+ ParamType1 const Param1; \
+ ParamType2 const Param2; \
}; \
} \
inline internal::PolymorphicMatcherWithParam2< \
internal::matcher_##DefineMatcher##OverloadId##Matcher, ParamType1, \
- ParamType2, ReturnTypesF> DefineMatcher(const ParamType1 &Param1, \
- const ParamType2 &Param2) { \
+ ParamType2, ReturnTypesF> DefineMatcher(ParamType1 const &Param1, \
+ ParamType2 const &Param2) { \
return internal::PolymorphicMatcherWithParam2< \
internal::matcher_##DefineMatcher##OverloadId##Matcher, ParamType1, \
ParamType2, ReturnTypesF>(Param1, Param2); \
@@ -289,7 +308,7 @@
typedef internal::PolymorphicMatcherWithParam2< \
internal::matcher_##DefineMatcher##OverloadId##Matcher, ParamType1, \
ParamType2, ReturnTypesF>(&DefineMatcher##_Type##OverloadId)( \
- const ParamType1 &Param1, const ParamType2 &Param2); \
+ ParamType1 const &Param1, ParamType2 const &Param2); \
template <typename NodeType, typename ParamT1, typename ParamT2> \
bool internal::matcher_##DefineMatcher##OverloadId##Matcher< \
NodeType, ParamT1, ParamT2>::matches( \
diff --git a/include/clang/ASTMatchers/Dynamic/Diagnostics.h b/include/clang/ASTMatchers/Dynamic/Diagnostics.h
index aec0c0e31ce2..82a14f1929be 100644
--- a/include/clang/ASTMatchers/Dynamic/Diagnostics.h
+++ b/include/clang/ASTMatchers/Dynamic/Diagnostics.h
@@ -15,15 +15,14 @@
#ifndef LLVM_CLANG_AST_MATCHERS_DYNAMIC_DIAGNOSTICS_H
#define LLVM_CLANG_AST_MATCHERS_DYNAMIC_DIAGNOSTICS_H
-#include <string>
-#include <vector>
-
#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 {
@@ -61,11 +60,12 @@ public:
enum ErrorType {
ET_None = 0,
- ET_RegistryNotFound = 1,
+ ET_RegistryMatcherNotFound = 1,
ET_RegistryWrongArgCount = 2,
ET_RegistryWrongArgType = 3,
ET_RegistryNotBindable = 4,
ET_RegistryAmbiguousOverload = 5,
+ ET_RegistryValueNotFound = 6,
ET_ParserStringError = 100,
ET_ParserNoOpenParen = 101,
diff --git a/include/clang/ASTMatchers/Dynamic/Parser.h b/include/clang/ASTMatchers/Dynamic/Parser.h
index bb6ac76989d0..4045f57d1b36 100644
--- a/include/clang/ASTMatchers/Dynamic/Parser.h
+++ b/include/clang/ASTMatchers/Dynamic/Parser.h
@@ -18,13 +18,14 @@
///
/// \code
/// Grammar for the expressions supported:
-/// <Expression> := <Literal> | <MatcherExpression>
+/// <Expression> := <Literal> | <NamedValue> | <MatcherExpression>
/// <Literal> := <StringLiteral> | <Unsigned>
/// <StringLiteral> := "quoted string"
/// <Unsigned> := [0-9]+
-/// <MatcherExpression> := <MatcherName>(<ArgumentList>) |
-/// <MatcherName>(<ArgumentList>).bind(<StringLiteral>)
-/// <MatcherName> := [a-zA-Z]+
+/// <NamedValue> := <Identifier>
+/// <MatcherExpression> := <Identifier>(<ArgumentList>) |
+/// <Identifier>(<ArgumentList>).bind(<StringLiteral>)
+/// <Identifier> := [a-zA-Z]+
/// <ArgumentList> := <Expression> | <Expression>,<ArgumentList>
/// \endcode
///
@@ -34,6 +35,7 @@
#define LLVM_CLANG_AST_MATCHERS_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"
@@ -61,11 +63,22 @@ public:
public:
virtual ~Sema();
+ /// \brief Lookup a value by name.
+ ///
+ /// This can be used in the Sema layer to declare known constants or to
+ /// allow to split an expression in pieces.
+ ///
+ /// \param Name The name of the value to lookup.
+ ///
+ /// \return The named value. It could be any type that VariantValue
+ /// supports. An empty value means that the name is not recognized.
+ virtual VariantValue getNamedValue(StringRef Name);
+
/// \brief Process a matcher expression.
///
/// All the arguments passed here have already been processed.
///
- /// \param MatcherName The matcher name found by the parser.
+ /// \param Ctor A matcher constructor looked up by lookupMatcherCtor.
///
/// \param NameRange The location of the name in the matcher source.
/// Useful for error reporting.
@@ -78,11 +91,36 @@ public:
/// \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(StringRef MatcherName,
+ virtual VariantMatcher actOnMatcherExpression(MatcherCtor Ctor,
const 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 Sema implementation that uses the matcher registry to process the
+ /// tokens.
+ class RegistrySema : public Parser::Sema {
+ public:
+ virtual ~RegistrySema();
+
+ llvm::Optional<MatcherCtor>
+ lookupMatcherCtor(StringRef MatcherName) override;
+
+ VariantMatcher actOnMatcherExpression(MatcherCtor Ctor,
+ const SourceRange &NameRange,
+ StringRef BindID,
+ ArrayRef<ParserValue> Args,
+ Diagnostics *Error) override;
};
/// \brief Parse a matcher expression, creating matchers from the registry.
@@ -129,19 +167,37 @@ public:
static bool parseExpression(StringRef Code, Sema *S,
VariantValue *Value, Diagnostics *Error);
+ /// \brief Complete an expression at the given offset.
+ ///
+ /// \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);
+
private:
class CodeTokenizer;
+ struct ScopedContextEntry;
struct TokenInfo;
Parser(CodeTokenizer *Tokenizer, Sema *S,
Diagnostics *Error);
bool parseExpressionImpl(VariantValue *Value);
- bool parseMatcherExpressionImpl(VariantValue *Value);
+ bool parseMatcherExpressionImpl(const TokenInfo &NameToken,
+ VariantValue *Value);
+ bool parseIdentifierPrefixImpl(VariantValue *Value);
+
+ void addCompletion(const TokenInfo &CompToken, StringRef TypedText,
+ StringRef Decl);
+ void addExpressionCompletions();
CodeTokenizer *const Tokenizer;
Sema *const S;
Diagnostics *const Error;
+
+ typedef std::vector<std::pair<MatcherCtor, unsigned> > ContextStackTy;
+ ContextStackTy ContextStack;
+ std::vector<MatcherCompletion> Completions;
};
} // namespace dynamic
diff --git a/include/clang/ASTMatchers/Dynamic/Registry.h b/include/clang/ASTMatchers/Dynamic/Registry.h
index c113c1404ef0..faa9254bc2e7 100644
--- a/include/clang/ASTMatchers/Dynamic/Registry.h
+++ b/include/clang/ASTMatchers/Dynamic/Registry.h
@@ -21,20 +21,69 @@
#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)
+ : TypedText(TypedText), MatcherDecl(MatcherDecl) {}
+
+ /// \brief The text to type to select this matcher.
+ std::string TypedText;
+
+ /// \brief The "declaration" of the matcher, with type information.
+ std::string MatcherDecl;
+
+ bool operator==(const MatcherCompletion &Other) const {
+ return TypedText == Other.TypedText && MatcherDecl == Other.MatcherDecl;
+ }
+};
+
class Registry {
public:
- /// \brief Construct a matcher from the registry by name.
+ /// \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 completions for \p Context.
///
- /// Consult the registry of known matchers and construct the appropriate
- /// matcher by name.
+ /// 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.
+ ///
+ /// The completions are ordered first by decreasing relevance, then
+ /// alphabetically. Relevance is determined by how closely the matcher's
+ /// type matches that of the context. For example, if the innermost matcher
+ /// takes a FunctionDecl matcher, the FunctionDecl matchers are returned
+ /// first, followed by the ValueDecl matchers, then NamedDecl, then Decl, then
+ /// polymorphic matchers.
+ ///
+ /// Matchers which are technically convertible to the innermost context but
+ /// which would match either all or no nodes are excluded. For example,
+ /// namedDecl and varDecl are excluded in a FunctionDecl context, because
+ /// those matchers would match respectively all or no nodes in such a context.
+ static std::vector<MatcherCompletion>
+ getCompletions(ArrayRef<std::pair<MatcherCtor, unsigned> > Context);
+
+ /// \brief Construct a matcher from the registry.
///
- /// \param MatcherName The name of the matcher to instantiate.
+ /// \param Ctor The matcher constructor to instantiate.
///
/// \param NameRange The location of the name in the matcher source.
/// Useful for error reporting.
@@ -44,10 +93,10 @@ public:
/// will return an error.
///
/// \return The matcher object constructed if no error was found.
- /// A null matcher if the matcher is not found, or 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(StringRef MatcherName,
+ /// 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,
const SourceRange &NameRange,
ArrayRef<ParserValue> Args,
Diagnostics *Error);
@@ -58,7 +107,7 @@ public:
/// 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(StringRef MatcherName,
+ static VariantMatcher constructBoundMatcher(MatcherCtor Ctor,
const SourceRange &NameRange,
StringRef BindID,
ArrayRef<ParserValue> Args,
diff --git a/include/clang/ASTMatchers/Dynamic/VariantValue.h b/include/clang/ASTMatchers/Dynamic/VariantValue.h
index b9bc017a48c0..b25267b1c54b 100644
--- a/include/clang/ASTMatchers/Dynamic/VariantValue.h
+++ b/include/clang/ASTMatchers/Dynamic/VariantValue.h
@@ -17,14 +17,13 @@
#ifndef LLVM_CLANG_AST_MATCHERS_DYNAMIC_VARIANT_VALUE_H
#define LLVM_CLANG_AST_MATCHERS_DYNAMIC_VARIANT_VALUE_H
-#include <vector>
-
#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 "llvm/Support/type_traits.h"
+#include <memory>
+#include <vector>
namespace clang {
namespace ast_matchers {
@@ -50,7 +49,8 @@ class VariantMatcher {
class MatcherOps {
public:
virtual ~MatcherOps();
- virtual bool canConstructFrom(const DynTypedMatcher &Matcher) const = 0;
+ virtual bool canConstructFrom(const DynTypedMatcher &Matcher,
+ bool &IsExactMatch) const = 0;
virtual void constructFrom(const DynTypedMatcher &Matcher) = 0;
virtual void constructVariadicOperator(
ast_matchers::internal::VariadicOperatorFunction Func,
@@ -78,14 +78,15 @@ public:
/// \brief Clones the provided matchers.
///
/// They should be the result of a polymorphic matcher.
- static VariantMatcher PolymorphicMatcher(ArrayRef<DynTypedMatcher> Matchers);
+ 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(
ast_matchers::internal::VariadicOperatorFunction Func,
- ArrayRef<VariantMatcher> Args);
+ std::vector<VariantMatcher> Args);
/// \brief Makes the matcher the "null" matcher.
void reset();
@@ -145,7 +146,10 @@ private:
public:
typedef ast_matchers::internal::Matcher<T> MatcherT;
- virtual bool canConstructFrom(const DynTypedMatcher &Matcher) const {
+ virtual bool canConstructFrom(const DynTypedMatcher &Matcher,
+ bool &IsExactMatch) const {
+ IsExactMatch = Matcher.getSupportedKind().isSame(
+ ast_type_traits::ASTNodeKind::getFromNodeKind<T>());
return Matcher.canConvertTo<T>();
}
@@ -156,34 +160,25 @@ private:
virtual void constructVariadicOperator(
ast_matchers::internal::VariadicOperatorFunction Func,
ArrayRef<VariantMatcher> InnerMatchers) {
- const size_t NumArgs = InnerMatchers.size();
- MatcherT **InnerArgs = new MatcherT *[NumArgs]();
- bool HasError = false;
- for (size_t i = 0; i != NumArgs; ++i) {
+ std::vector<DynTypedMatcher> DynMatchers;
+ for (size_t i = 0, e = InnerMatchers.size(); i != e; ++i) {
// Abort if any of the inner matchers can't be converted to
// Matcher<T>.
if (!InnerMatchers[i].hasTypedMatcher<T>()) {
- HasError = true;
- break;
+ return;
}
- InnerArgs[i] = new MatcherT(InnerMatchers[i].getTypedMatcher<T>());
+ DynMatchers.push_back(InnerMatchers[i].getTypedMatcher<T>());
}
- if (!HasError) {
- Out.reset(new MatcherT(
- new ast_matchers::internal::VariadicOperatorMatcherInterface<T>(
- Func, ArrayRef<const MatcherT *>(InnerArgs, NumArgs))));
- }
- for (size_t i = 0; i != NumArgs; ++i) {
- delete InnerArgs[i];
- }
- delete[] InnerArgs;
+ Out.reset(new MatcherT(
+ new ast_matchers::internal::VariadicOperatorMatcherInterface<T>(
+ Func, DynMatchers)));
}
- bool hasMatcher() const { return Out.get() != NULL; }
+ bool hasMatcher() const { return Out.get() != nullptr; }
const MatcherT &matcher() const { return *Out; }
private:
- OwningPtr<MatcherT> Out;
+ std::unique_ptr<MatcherT> Out;
};
IntrusiveRefCntPtr<const Payload> Value;
@@ -214,6 +209,10 @@ public:
VariantValue(const std::string &String);
VariantValue(const VariantMatcher &Matchers);
+ /// \brief Returns true iff this is not an empty value.
+ LLVM_EXPLICIT operator bool() const { return hasValue(); }
+ bool hasValue() const { return Type != VT_Nothing; }
+
/// \brief Unsigned value functions.
bool isUnsigned() const;
unsigned getUnsigned() const;
diff --git a/include/clang/Analysis/Analyses/Consumed.h b/include/clang/Analysis/Analyses/Consumed.h
index 23a094a79643..36e07c21907b 100644
--- a/include/clang/Analysis/Analyses/Consumed.h
+++ b/include/clang/Analysis/Analyses/Consumed.h
@@ -18,8 +18,8 @@
#include "clang/AST/DeclCXX.h"
#include "clang/AST/ExprCXX.h"
#include "clang/AST/StmtCXX.h"
-#include "clang/Analysis/AnalysisContext.h"
#include "clang/Analysis/Analyses/PostOrderCFGView.h"
+#include "clang/Analysis/AnalysisContext.h"
#include "clang/Basic/SourceLocation.h"
namespace clang {
@@ -142,7 +142,7 @@ namespace consumed {
TmpMapType TmpMap;
public:
- ConsumedStateMap() : Reachable(true), From(NULL) {}
+ ConsumedStateMap() : Reachable(true), From(nullptr) {}
ConsumedStateMap(const ConsumedStateMap &Other)
: Reachable(Other.Reachable), From(Other.From), VarMap(Other.VarMap),
TmpMap() {}
@@ -185,8 +185,8 @@ namespace consumed {
/// \brief Set the consumed state of a given temporary value.
void setState(const CXXBindTemporaryExpr *Tmp, ConsumedState State);
- /// \brief Remove the variable from our state map.
- void remove(const VarDecl *Var);
+ /// \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.
@@ -201,9 +201,10 @@ namespace consumed {
public:
ConsumedBlockInfo() { }
-
+ ~ConsumedBlockInfo() { llvm::DeleteContainerPointers(StateMapsArray); }
+
ConsumedBlockInfo(unsigned int NumBlocks, PostOrderCFGView *SortedGraph)
- : StateMapsArray(NumBlocks, 0), VisitOrder(NumBlocks, 0) {
+ : StateMapsArray(NumBlocks, nullptr), VisitOrder(NumBlocks, 0) {
unsigned int VisitOrderCounter = 0;
for (PostOrderCFGView::iterator BI = SortedGraph->begin(),
BE = SortedGraph->end(); BI != BE; ++BI) {
diff --git a/include/clang/Analysis/Analyses/Dominators.h b/include/clang/Analysis/Analyses/Dominators.h
index 2a806c8befda..6c6d9238e5a9 100644
--- a/include/clang/Analysis/Analyses/Dominators.h
+++ b/include/clang/Analysis/Analyses/Dominators.h
@@ -17,9 +17,15 @@
#include "clang/Analysis/AnalysisContext.h"
#include "clang/Analysis/CFG.h"
#include "llvm/ADT/GraphTraits.h"
-#include "llvm/Analysis/DominatorInternals.h"
-#include "llvm/Analysis/Dominators.h"
-#include "llvm/IR/Module.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 {
@@ -147,7 +153,7 @@ public:
/// \brief This method converts the dominator tree to human readable form.
///
- virtual void print(raw_ostream &OS, const llvm::Module* M= 0) const {
+ virtual void print(raw_ostream &OS, const llvm::Module* M= nullptr) const {
DT->print(OS);
}
@@ -155,11 +161,6 @@ private:
CFG *cfg;
};
-inline void WriteAsOperand(raw_ostream &OS, const CFGBlock *BB,
- bool t) {
- OS << "BB#" << BB->getBlockID();
-}
-
} // end namespace clang
//===-------------------------------------
diff --git a/include/clang/Analysis/Analyses/FormatString.h b/include/clang/Analysis/Analyses/FormatString.h
index c9516b50cae3..76fe9ddca6f8 100644
--- a/include/clang/Analysis/Analyses/FormatString.h
+++ b/include/clang/Analysis/Analyses/FormatString.h
@@ -83,7 +83,7 @@ public:
};
LengthModifier()
- : Position(0), kind(None) {}
+ : Position(nullptr), kind(None) {}
LengthModifier(const char *pos, Kind k)
: Position(pos), kind(k) {}
@@ -169,10 +169,11 @@ public:
};
ConversionSpecifier(bool isPrintf = true)
- : IsPrintf(isPrintf), Position(0), EndScanList(0), kind(InvalidSpecifier) {}
+ : IsPrintf(isPrintf), Position(nullptr), EndScanList(nullptr),
+ kind(InvalidSpecifier) {}
ConversionSpecifier(bool isPrintf, const char *pos, Kind k)
- : IsPrintf(isPrintf), Position(pos), EndScanList(0), kind(k) {}
+ : IsPrintf(isPrintf), Position(pos), EndScanList(nullptr), kind(k) {}
const char *getStart() const {
return Position;
@@ -226,10 +227,11 @@ private:
const char *Name;
bool Ptr;
public:
- ArgType(Kind k = UnknownTy, const char *n = 0) : K(k), Name(n), Ptr(false) {}
- ArgType(QualType t, const char *n = 0)
+ 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(0), 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; }
@@ -262,7 +264,7 @@ public:
UsesPositionalArg(usesPositionalArg), UsesDotPrefix(0) {}
OptionalAmount(bool valid = true)
- : start(0),length(0), hs(valid ? NotSpecified : Invalid), amt(0),
+ : start(nullptr),length(0), hs(valid ? NotSpecified : Invalid), amt(0),
UsesPositionalArg(0), UsesDotPrefix(0) {}
bool isInvalid() const {
@@ -389,7 +391,7 @@ class PrintfConversionSpecifier :
public analyze_format_string::ConversionSpecifier {
public:
PrintfConversionSpecifier()
- : ConversionSpecifier(true, 0, InvalidSpecifier) {}
+ : ConversionSpecifier(true, nullptr, InvalidSpecifier) {}
PrintfConversionSpecifier(const char *pos, Kind k)
: ConversionSpecifier(true, pos, k) {}
@@ -525,7 +527,7 @@ class ScanfConversionSpecifier :
public analyze_format_string::ConversionSpecifier {
public:
ScanfConversionSpecifier()
- : ConversionSpecifier(false, 0, InvalidSpecifier) {}
+ : ConversionSpecifier(false, nullptr, InvalidSpecifier) {}
ScanfConversionSpecifier(const char *pos, Kind k)
: ConversionSpecifier(false, pos, k) {}
@@ -572,7 +574,8 @@ public:
ArgType getArgType(ASTContext &Ctx) const;
- bool fixType(QualType QT, const LangOptions &LangOpt, ASTContext &Ctx);
+ bool fixType(QualType QT, QualType RawQT, const LangOptions &LangOpt,
+ ASTContext &Ctx);
void toString(raw_ostream &os) const;
diff --git a/include/clang/Analysis/Analyses/LiveVariables.h b/include/clang/Analysis/Analyses/LiveVariables.h
index bbd2b02e8256..784227108ead 100644
--- a/include/clang/Analysis/Analyses/LiveVariables.h
+++ b/include/clang/Analysis/Analyses/LiveVariables.h
@@ -38,7 +38,7 @@ public:
bool equals(const LivenessValues &V) const;
LivenessValues()
- : liveStmts(0), liveDecls(0) {}
+ : liveStmts(nullptr), liveDecls(nullptr) {}
LivenessValues(llvm::ImmutableSet<const Stmt *> LiveStmts,
llvm::ImmutableSet<const VarDecl *> LiveDecls)
diff --git a/include/clang/Analysis/Analyses/PostOrderCFGView.h b/include/clang/Analysis/Analyses/PostOrderCFGView.h
index 4e3244e7b7ca..91bf51cd613f 100644
--- a/include/clang/Analysis/Analyses/PostOrderCFGView.h
+++ b/include/clang/Analysis/Analyses/PostOrderCFGView.h
@@ -52,7 +52,7 @@ public:
// 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 == 0)
+ if (!Block)
return false; // if an edge is trivially false.
if (VisitedBlockIDs.test(Block->getBlockID()))
return false;
@@ -76,14 +76,18 @@ private:
BlockOrderTy BlockOrder;
public:
- typedef std::vector<const CFGBlock*>::reverse_iterator iterator;
+ 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(); }
- bool empty() { return begin() == end(); }
+ 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;
diff --git a/include/clang/Analysis/Analyses/ReachableCode.h b/include/clang/Analysis/Analyses/ReachableCode.h
index 30c5b2d7a5b2..90a6d014f58d 100644
--- a/include/clang/Analysis/Analyses/ReachableCode.h
+++ b/include/clang/Analysis/Analyses/ReachableCode.h
@@ -27,6 +27,7 @@ namespace llvm {
namespace clang {
class AnalysisDeclContext;
class CFGBlock;
+ class Preprocessor;
}
//===----------------------------------------------------------------------===//
@@ -36,11 +37,22 @@ namespace clang {
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(SourceLocation L, SourceRange R1,
+ virtual void HandleUnreachable(UnreachableKind UK,
+ SourceLocation L,
+ SourceRange ConditionVal,
+ SourceRange R1,
SourceRange R2) = 0;
};
@@ -49,7 +61,8 @@ public:
unsigned ScanReachableFromBlock(const CFGBlock *Start,
llvm::BitVector &Reachable);
-void FindUnreachableCode(AnalysisDeclContext &AC, Callback &CB);
+void FindUnreachableCode(AnalysisDeclContext &AC, Preprocessor &PP,
+ Callback &CB);
}} // end namespace clang::reachable_code
diff --git a/include/clang/Analysis/Analyses/ThreadSafety.h b/include/clang/Analysis/Analyses/ThreadSafety.h
index 5def3dd3dfd1..b533c1db492e 100644
--- a/include/clang/Analysis/Analyses/ThreadSafety.h
+++ b/include/clang/Analysis/Analyses/ThreadSafety.h
@@ -39,7 +39,8 @@ enum ProtectedOperationKind {
/// mutex.
enum LockKind {
LK_Shared, ///< Shared/reader lock of a mutex.
- LK_Exclusive ///< Exclusive/writer 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
@@ -72,27 +73,46 @@ public:
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(SourceLocation Loc) {}
+ 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(Name LockName, SourceLocation Loc) {}
+ 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(Name LockName, SourceLocation Loc) {}
+ 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
@@ -100,50 +120,56 @@ public:
/// \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(Name LockName,
+ virtual void handleMutexHeldEndOfScope(StringRef Kind, Name LockName,
SourceLocation LocLocked,
SourceLocation LocEndOfScope,
- LockErrorKind LEK){}
+ 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(Name LockName, SourceLocation Loc1,
+ 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(const NamedDecl *D, ProtectedOperationKind POK,
- AccessKind AK, SourceLocation Loc) {}
+ 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(const NamedDecl *D,
+ virtual void handleMutexNotHeld(StringRef Kind, const NamedDecl *D,
ProtectedOperationKind POK, Name LockName,
LockKind LK, SourceLocation Loc,
- Name *PossibleMatch=0) {}
+ Name *PossibleMatch = nullptr) {}
/// 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(Name FunName, Name LockName,
- SourceLocation Loc) {}
+ virtual void handleFunExcludesLock(StringRef Kind, Name FunName,
+ Name LockName, SourceLocation Loc) {}
bool issueBetaWarnings() { return IssueBetaWarnings; }
void setIssueBetaWarnings(bool b) { IssueBetaWarnings = b; }
diff --git a/include/clang/Analysis/Analyses/ThreadSafetyCommon.h b/include/clang/Analysis/Analyses/ThreadSafetyCommon.h
new file mode 100644
index 000000000000..09c614ca3e36
--- /dev/null
+++ b/include/clang/Analysis/Analyses/ThreadSafetyCommon.h
@@ -0,0 +1,393 @@
+//===- 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_THREAD_SAFETY_COMMON_H
+#define LLVM_CLANG_THREAD_SAFETY_COMMON_H
+
+#include "clang/Analysis/Analyses/PostOrderCFGView.h"
+#include "clang/Analysis/Analyses/ThreadSafetyTIL.h"
+#include "clang/Analysis/AnalysisContext.h"
+#include "clang/Basic/OperatorKinds.h"
+
+#include <memory>
+#include <vector>
+
+
+namespace clang {
+namespace threadSafety {
+
+// 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;
+};
+
+
+// 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 {
+ 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
+ CallingContext *Prev; // The previous context; or 0 if none.
+ bool SelfArrow; // is Self referred to with -> or .?
+
+ CallingContext(const NamedDecl *D = nullptr, const Expr *S = nullptr,
+ unsigned N = 0, const Expr *const *A = nullptr,
+ CallingContext *P = nullptr)
+ : AttrDecl(D), SelfArg(S), NumArgs(N), FunArgs(A), Prev(P),
+ 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 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);
+ 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 *translateConditionalOperator(const ConditionalOperator *C,
+ CallingContext *Ctx);
+ til::SExpr *translateBinaryConditionalOperator(
+ const BinaryConditionalOperator *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 &) LLVM_DELETED_FUNCTION;
+ void operator=(const BlockInfo &) LLVM_DELETED_FUNCTION;
+ };
+
+ // 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:
+ 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.
+ std::unique_ptr<SExprBuilder::CallingContext> CallCtx; // Root calling context
+
+ LVarDefinitionMap CurrentLVarMap;
+ std::vector<til::Variable*> CurrentArguments;
+ std::vector<til::Variable*> CurrentInstructions;
+ std::vector<til::Variable*> 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/include/clang/Analysis/Analyses/ThreadSafetyLogical.h b/include/clang/Analysis/Analyses/ThreadSafetyLogical.h
new file mode 100644
index 000000000000..c4f4b21aab12
--- /dev/null
+++ b/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_THREAD_SAFETY_LOGICAL_H
+#define LLVM_CLANG_THREAD_SAFETY_LOGICAL_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::SExprRef Expr;
+
+public:
+ Terminal(til::SExpr *Expr) : LExpr(LExpr::Terminal), Expr(Expr) {}
+
+ const til::SExpr *expr() const { return Expr.get(); }
+ til::SExpr *expr() { return Expr.get(); }
+
+ 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 // LLVM_CLANG_THREAD_SAFETY_LOGICAL_H
+
diff --git a/include/clang/Analysis/Analyses/ThreadSafetyOps.def b/include/clang/Analysis/Analyses/ThreadSafetyOps.def
new file mode 100644
index 000000000000..6ebc95dbe9a7
--- /dev/null
+++ b/include/clang/Analysis/Analyses/ThreadSafetyOps.def
@@ -0,0 +1,54 @@
+//===- 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)
+TIL_OPCODE_DEF(Goto)
+TIL_OPCODE_DEF(Branch)
+
+// pseudo-terms
+TIL_OPCODE_DEF(Identifier)
+TIL_OPCODE_DEF(IfThenElse)
+TIL_OPCODE_DEF(Let)
+
diff --git a/include/clang/Analysis/Analyses/ThreadSafetyTIL.h b/include/clang/Analysis/Analyses/ThreadSafetyTIL.h
new file mode 100644
index 000000000000..8e4299ea70e8
--- /dev/null
+++ b/include/clang/Analysis/Analyses/ThreadSafetyTIL.h
@@ -0,0 +1,1813 @@
+//===- 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_THREAD_SAFETY_TIL_H
+#define LLVM_CLANG_THREAD_SAFETY_TIL_H
+
+// All clang include dependencies for this file must be put in
+// ThreadSafetyUtil.h.
+#include "ThreadSafetyUtil.h"
+
+#include <stdint.h>
+#include <algorithm>
+#include <cassert>
+#include <cstddef>
+#include <utility>
+
+
+namespace clang {
+namespace threadSafety {
+namespace til {
+
+
+enum TIL_Opcode {
+#define TIL_OPCODE_DEF(X) COP_##X,
+#include "ThreadSafetyOps.def"
+#undef TIL_OPCODE_DEF
+};
+
+enum TIL_UnaryOpcode : unsigned char {
+ UOP_Minus, // -
+ UOP_BitNot, // ~
+ UOP_LogicNot // !
+};
+
+enum TIL_BinaryOpcode : unsigned char {
+ BOP_Mul, // *
+ BOP_Div, // /
+ BOP_Rem, // %
+ BOP_Add, // +
+ BOP_Sub, // -
+ BOP_Shl, // <<
+ BOP_Shr, // >>
+ BOP_BitAnd, // &
+ BOP_BitXor, // ^
+ BOP_BitOr, // |
+ BOP_Eq, // ==
+ BOP_Neq, // !=
+ BOP_Lt, // <
+ BOP_Leq, // <=
+ BOP_LogicAnd, // &&
+ BOP_LogicOr // ||
+};
+
+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
+};
+
+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_Mul;
+const TIL_BinaryOpcode BOP_Max = BOP_LogicOr;
+const TIL_CastOpcode CAST_Min = CAST_none;
+const TIL_CastOpcode CAST_Max = CAST_toInt;
+
+StringRef getUnaryOpcodeString(TIL_UnaryOpcode Op);
+StringRef getBinaryOpcodeString(TIL_BinaryOpcode Op);
+
+
+// ValueTypes are data types that can actually be held in registers.
+// All variables and expressions must have a vBNF_Nonealue 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);
+}
+
+
+
+// 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 *) LLVM_DELETED_FUNCTION;
+
+protected:
+ SExpr(TIL_Opcode Op) : Opcode(Op), Reserved(0), Flags(0) {}
+ SExpr(const SExpr &E) : Opcode(E.Opcode), Reserved(0), Flags(E.Flags) {}
+
+ const unsigned char Opcode;
+ unsigned char Reserved;
+ unsigned short Flags;
+
+private:
+ SExpr() LLVM_DELETED_FUNCTION;
+
+ // SExpr objects must be created in an arena.
+ void *operator new(size_t) LLVM_DELETED_FUNCTION;
+};
+
+
+// Class for owning references to SExprs.
+// Includes attach/detach logic for counting variable references and lazy
+// rewriting strategies.
+class SExprRef {
+public:
+ SExprRef() : Ptr(nullptr) { }
+ SExprRef(std::nullptr_t P) : Ptr(nullptr) { }
+ SExprRef(SExprRef &&R) : Ptr(R.Ptr) { R.Ptr = nullptr; }
+
+ // Defined after Variable and Future, below.
+ inline SExprRef(SExpr *P);
+ inline ~SExprRef();
+
+ SExpr *get() { return Ptr; }
+ const SExpr *get() const { return Ptr; }
+
+ SExpr *operator->() { return get(); }
+ const SExpr *operator->() const { return get(); }
+
+ SExpr &operator*() { return *Ptr; }
+ const SExpr &operator*() const { return *Ptr; }
+
+ bool operator==(const SExprRef &R) const { return Ptr == R.Ptr; }
+ bool operator!=(const SExprRef &R) const { return !operator==(R); }
+ bool operator==(const SExpr *P) const { return Ptr == P; }
+ bool operator!=(const SExpr *P) const { return !operator==(P); }
+ bool operator==(std::nullptr_t) const { return Ptr == nullptr; }
+ bool operator!=(std::nullptr_t) const { return Ptr != nullptr; }
+
+ inline void reset(SExpr *E);
+
+private:
+ inline void attach();
+ inline void detach();
+
+ SExpr *Ptr;
+};
+
+
+// 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 BasicBlock;
+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; }
+
+ // Let-variable, function parameter, or self-variable
+ enum VariableKind {
+ VK_Let,
+ VK_LetBB,
+ VK_Fun,
+ VK_SFun
+ };
+
+ // These are defined after SExprRef contructor, below
+ inline Variable(SExpr *D, const clang::ValueDecl *Cvd = nullptr);
+ inline Variable(StringRef s, SExpr *D = nullptr);
+ inline Variable(const Variable &Vd, SExpr *D);
+
+ VariableKind kind() const { return static_cast<VariableKind>(Flags); }
+
+ const StringRef name() const { return Name; }
+ const clang::ValueDecl *clangDecl() const { return Cvdecl; }
+
+ // Returns the definition (for let vars) or type (for parameter & self vars)
+ SExpr *definition() { return Definition.get(); }
+ const SExpr *definition() const { return Definition.get(); }
+
+ void attachVar() const { ++NumUses; }
+ void detachVar() const { assert(NumUses > 0); --NumUses; }
+
+ unsigned getID() const { return Id; }
+ unsigned getBlockID() const { return BlockID; }
+
+ void setName(StringRef S) { Name = S; }
+ void setID(unsigned Bid, unsigned I) {
+ BlockID = static_cast<unsigned short>(Bid);
+ Id = static_cast<unsigned short>(I);
+ }
+ void setClangDecl(const clang::ValueDecl *VD) { Cvdecl = VD; }
+ void setDefinition(SExpr *E);
+ void setKind(VariableKind K) { Flags = K; }
+
+ 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(Variable* E, C& Cmp) {
+ 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.
+ SExprRef Definition; // The TIL type or definition
+ const clang::ValueDecl *Cvdecl; // The clang declaration for this variable.
+
+ unsigned short BlockID;
+ unsigned short Id;
+ mutable unsigned NumUses;
+};
+
+
+// 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), Location(nullptr)
+ {}
+private:
+ virtual ~Future() LLVM_DELETED_FUNCTION;
+public:
+
+ // Registers the location in the AST where this future is stored.
+ // Forcing the future will automatically update the AST.
+ static inline void registerLocation(SExprRef *Member) {
+ if (Future *F = dyn_cast_or_null<Future>(Member->get()))
+ F->Location = Member;
+ }
+
+ // A lazy rewriting strategy should subclass Future and override this method.
+ virtual SExpr *create() { return nullptr; }
+
+ // Return the result of this future if it exists, otherwise return null.
+ SExpr *maybeGetResult() {
+ return Result;
+ }
+
+ // Return the result of this future; forcing it if necessary.
+ SExpr *result() {
+ switch (Status) {
+ case FS_pending:
+ force();
+ return Result;
+ 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(Future* E, C& Cmp) {
+ if (!Result || !E->Result)
+ return Cmp.comparePointers(this, E);
+ return Cmp.compare(Result, E->Result);
+ }
+
+private:
+ // Force the future.
+ inline void force();
+
+ FutureStatus Status;
+ SExpr *Result;
+ SExprRef *Location;
+};
+
+
+inline void SExprRef::attach() {
+ if (!Ptr)
+ return;
+
+ TIL_Opcode Op = Ptr->opcode();
+ if (Op == COP_Variable) {
+ cast<Variable>(Ptr)->attachVar();
+ } else if (Op == COP_Future) {
+ cast<Future>(Ptr)->registerLocation(this);
+ }
+}
+
+inline void SExprRef::detach() {
+ if (Ptr && Ptr->opcode() == COP_Variable) {
+ cast<Variable>(Ptr)->detachVar();
+ }
+}
+
+inline SExprRef::SExprRef(SExpr *P) : Ptr(P) {
+ attach();
+}
+
+inline SExprRef::~SExprRef() {
+ detach();
+}
+
+inline void SExprRef::reset(SExpr *P) {
+ detach();
+ Ptr = P;
+ attach();
+}
+
+
+inline Variable::Variable(StringRef s, SExpr *D)
+ : SExpr(COP_Variable), Name(s), Definition(D), Cvdecl(nullptr),
+ BlockID(0), Id(0), NumUses(0) {
+ Flags = VK_Let;
+}
+
+inline Variable::Variable(SExpr *D, const clang::ValueDecl *Cvd)
+ : SExpr(COP_Variable), Name(Cvd ? Cvd->getName() : "_x"),
+ Definition(D), Cvdecl(Cvd), BlockID(0), Id(0), NumUses(0) {
+ Flags = VK_Let;
+}
+
+inline Variable::Variable(const Variable &Vd, SExpr *D) // rewrite constructor
+ : SExpr(Vd), Name(Vd.Name), Definition(D), Cvdecl(Vd.Cvdecl),
+ BlockID(0), Id(0), NumUses(0) {
+ Flags = Vd.kind();
+}
+
+inline void Variable::setDefinition(SExpr *E) {
+ Definition.reset(E);
+}
+
+void Future::force() {
+ Status = FS_evaluating;
+ SExpr *R = create();
+ Result = R;
+ if (Location)
+ Location->reset(R);
+ Status = FS_done;
+}
+
+
+// Placeholder for C++ 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(Undefined* E, C& Cmp) {
+ return Cmp.comparePointers(Cstmt, E->Cstmt);
+ }
+
+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(Wildcard* E, C& Cmp) {
+ 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(Literal* E, C& Cmp) {
+ // TODO -- use value, not pointer equality
+ return Cmp.comparePointers(Cexpr, E->Cexpr);
+ }
+
+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);
+}
+
+
+// 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(LiteralPtr* E, C& Cmp) {
+ 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) (add 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.get(); }
+ const SExpr *body() const { return Body.get(); }
+
+ 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(Function* E, C& Cmp) {
+ 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;
+ SExprRef 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.reset(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.reset(this);
+ }
+
+ Variable *variableDecl() { return VarDecl; }
+ const Variable *variableDecl() const { return VarDecl; }
+
+ SExpr *body() { return Body.get(); }
+ const SExpr *body() const { return Body.get(); }
+
+ 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(SFunction* E, C& Cmp) {
+ Cmp.enterScope(variableDecl(), E->variableDecl());
+ typename C::CType Ct = Cmp.compare(body(), E->body());
+ Cmp.leaveScope();
+ return Ct;
+ }
+
+private:
+ Variable *VarDecl;
+ SExprRef 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.get(); }
+ const SExpr *returnType() const { return ReturnType.get(); }
+
+ SExpr *body() { return Body.get(); }
+ const SExpr *body() const { return Body.get(); }
+
+ 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(Code* E, C& Cmp) {
+ typename C::CType Ct = Cmp.compare(returnType(), E->returnType());
+ if (Cmp.notTrue(Ct))
+ return Ct;
+ return Cmp.compare(body(), E->body());
+ }
+
+private:
+ SExprRef ReturnType;
+ SExprRef 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.get(); }
+ const SExpr *range() const { return Range.get(); }
+
+ SExpr *body() { return Body.get(); }
+ const SExpr *body() const { return Body.get(); }
+
+ 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(Field* E, C& Cmp) {
+ typename C::CType Ct = Cmp.compare(range(), E->range());
+ if (Cmp.notTrue(Ct))
+ return Ct;
+ return Cmp.compare(body(), E->body());
+ }
+
+private:
+ SExprRef Range;
+ SExprRef Body;
+};
+
+
+// Apply an argument to a 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.get(); }
+ const SExpr *fun() const { return Fun.get(); }
+
+ SExpr *arg() { return Arg.get(); }
+ const SExpr *arg() const { return Arg.get(); }
+
+ 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(Apply* E, C& Cmp) {
+ typename C::CType Ct = Cmp.compare(fun(), E->fun());
+ if (Cmp.notTrue(Ct))
+ return Ct;
+ return Cmp.compare(arg(), E->arg());
+ }
+
+private:
+ SExprRef Fun;
+ SExprRef 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.get(); }
+ const SExpr *sfun() const { return Sfun.get(); }
+
+ SExpr *arg() { return Arg.get() ? Arg.get() : Sfun.get(); }
+ const SExpr *arg() const { return Arg.get() ? Arg.get() : Sfun.get(); }
+
+ 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.get() ? Vs.traverse(Arg, Vs.subExprCtx(Ctx))
+ : nullptr;
+ return Vs.reduceSApply(*this, Nf, Na);
+ }
+
+ template <class C> typename C::CType compare(SApply* E, C& Cmp) {
+ 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:
+ SExprRef Sfun;
+ SExprRef 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, 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.get(); }
+ const SExpr *record() const { return Rec.get(); }
+
+ const clang::ValueDecl *clangValueDecl() const { return Cvdecl; }
+
+ 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(Project* E, C& Cmp) {
+ typename C::CType Ct = Cmp.compare(record(), E->record());
+ if (Cmp.notTrue(Ct))
+ return Ct;
+ return Cmp.comparePointers(Cvdecl, E->Cvdecl);
+ }
+
+private:
+ SExprRef Rec;
+ StringRef SlotName;
+ 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.get(); }
+ const SExpr *target() const { return Target.get(); }
+
+ 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(Call* E, C& Cmp) {
+ return Cmp.compare(target(), E->target());
+ }
+
+private:
+ SExprRef 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.get(); }
+ const SExpr *dataType() const { return Dtype.get(); }
+
+ 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(Alloc* E, C& Cmp) {
+ typename C::CType Ct = Cmp.compareIntegers(kind(), E->kind());
+ if (Cmp.notTrue(Ct))
+ return Ct;
+ return Cmp.compare(dataType(), E->dataType());
+ }
+
+private:
+ SExprRef 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.get(); }
+ const SExpr *pointer() const { return Ptr.get(); }
+
+ 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(Load* E, C& Cmp) {
+ return Cmp.compare(pointer(), E->pointer());
+ }
+
+private:
+ SExprRef Ptr;
+};
+
+
+// Store a value to memory.
+// Source is a pointer, destination 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.get(); } // Address to store to
+ const SExpr *destination() const { return Dest.get(); }
+
+ SExpr *source() { return Source.get(); } // Value to store
+ const SExpr *source() const { return Source.get(); }
+
+ 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(Store* E, C& Cmp) {
+ typename C::CType Ct = Cmp.compare(destination(), E->destination());
+ if (Cmp.notTrue(Ct))
+ return Ct;
+ return Cmp.compare(source(), E->source());
+ }
+
+private:
+ SExprRef Dest;
+ SExprRef Source;
+};
+
+
+// If p is a reference to an array, then first(p) is a reference to the first
+// element. The usual array notation p[i] becomes first(p + i).
+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.get(); }
+ const SExpr *array() const { return Array.get(); }
+
+ SExpr *index() { return Index.get(); }
+ const SExpr *index() const { return Index.get(); }
+
+ 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(ArrayIndex* E, C& Cmp) {
+ typename C::CType Ct = Cmp.compare(array(), E->array());
+ if (Cmp.notTrue(Ct))
+ return Ct;
+ return Cmp.compare(index(), E->index());
+ }
+
+private:
+ SExprRef Array;
+ SExprRef 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.get(); }
+ const SExpr *array() const { return Array.get(); }
+
+ SExpr *index() { return Index.get(); }
+ const SExpr *index() const { return Index.get(); }
+
+ 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(ArrayAdd* E, C& Cmp) {
+ typename C::CType Ct = Cmp.compare(array(), E->array());
+ if (Cmp.notTrue(Ct))
+ return Ct;
+ return Cmp.compare(index(), E->index());
+ }
+
+private:
+ SExprRef Array;
+ SExprRef Index;
+};
+
+
+// Simple unary operation -- e.g. !, ~, etc.
+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.get(); }
+ const SExpr *expr() const { return Expr0.get(); }
+
+ 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(UnaryOp* E, C& Cmp) {
+ typename C::CType Ct =
+ Cmp.compareIntegers(unaryOpcode(), E->unaryOpcode());
+ if (Cmp.notTrue(Ct))
+ return Ct;
+ return Cmp.compare(expr(), E->expr());
+ }
+
+private:
+ SExprRef Expr0;
+};
+
+
+// Simple binary operation -- e.g. +, -, etc.
+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.get(); }
+ const SExpr *expr0() const { return Expr0.get(); }
+
+ SExpr *expr1() { return Expr1.get(); }
+ const SExpr *expr1() const { return Expr1.get(); }
+
+ 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(BinaryOp* E, C& Cmp) {
+ 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:
+ SExprRef Expr0;
+ SExprRef Expr1;
+};
+
+
+// Cast expression
+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.get(); }
+ const SExpr *expr() const { return Expr0.get(); }
+
+ 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(Cast* E, C& Cmp) {
+ typename C::CType Ct =
+ Cmp.compareIntegers(castOpcode(), E->castOpcode());
+ if (Cmp.notTrue(Ct))
+ return Ct;
+ return Cmp.compare(expr(), E->expr());
+ }
+
+private:
+ SExprRef Expr0;
+};
+
+
+class SCFG;
+
+
+class Phi : public SExpr {
+public:
+ // TODO: change to SExprRef
+ 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) {}
+ Phi(MemRegionRef A, unsigned Nvals) : SExpr(COP_Phi), Values(A, Nvals) {}
+ Phi(const Phi &P, ValArray &&Vs) : SExpr(P), Values(std::move(Vs)) {}
+
+ const ValArray &values() const { return Values; }
+ ValArray &values() { return Values; }
+
+ Status status() const { return static_cast<Status>(Flags); }
+ void setStatus(Status s) { Flags = s; }
+
+ 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(Phi *E, C &Cmp) {
+ // TODO: implement CFG comparisons
+ return Cmp.comparePointers(this, E);
+ }
+
+private:
+ ValArray Values;
+};
+
+
+// A basic block is part of an SCFG, and can be treated as a function in
+// continuation passing style. It consists of a sequence of phi nodes, which
+// are "arguments" to the function, followed by a sequence of instructions.
+// Both arguments and instructions define new variables. It ends with a
+// branch or goto to another basic block in the same SCFG.
+class BasicBlock : public SExpr {
+public:
+ typedef SimpleArray<Variable*> VarArray;
+ typedef SimpleArray<BasicBlock*> BlockArray;
+
+ static bool classof(const SExpr *E) { return E->opcode() == COP_BasicBlock; }
+
+ explicit BasicBlock(MemRegionRef A, BasicBlock* P = nullptr)
+ : SExpr(COP_BasicBlock), Arena(A), CFGPtr(nullptr), BlockID(0),
+ Parent(P), Terminator(nullptr)
+ { }
+ BasicBlock(BasicBlock &B, VarArray &&As, VarArray &&Is, SExpr *T)
+ : SExpr(COP_BasicBlock), Arena(B.Arena), CFGPtr(nullptr), BlockID(0),
+ Parent(nullptr), Args(std::move(As)), Instrs(std::move(Is)),
+ Terminator(T)
+ { }
+
+ unsigned blockID() const { return BlockID; }
+ unsigned numPredecessors() const { return Predecessors.size(); }
+
+ const SCFG* cfg() const { return CFGPtr; }
+ SCFG* cfg() { return CFGPtr; }
+
+ const BasicBlock *parent() const { return Parent; }
+ BasicBlock *parent() { return Parent; }
+
+ const VarArray &arguments() const { return Args; }
+ VarArray &arguments() { return Args; }
+
+ const VarArray &instructions() const { return Instrs; }
+ VarArray &instructions() { return Instrs; }
+
+ const BlockArray &predecessors() const { return Predecessors; }
+ BlockArray &predecessors() { return Predecessors; }
+
+ const SExpr *terminator() const { return Terminator.get(); }
+ SExpr *terminator() { return Terminator.get(); }
+
+ void setBlockID(unsigned i) { BlockID = i; }
+ void setParent(BasicBlock *P) { Parent = P; }
+ void setTerminator(SExpr *E) { Terminator.reset(E); }
+
+ // Add a new argument. V must define a phi-node.
+ void addArgument(Variable *V) {
+ V->setKind(Variable::VK_LetBB);
+ Args.reserveCheck(1, Arena);
+ Args.push_back(V);
+ }
+ // Add a new instruction.
+ void addInstruction(Variable *V) {
+ V->setKind(Variable::VK_LetBB);
+ 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);
+ }
+
+ // Set id numbers for variables.
+ void renumberVars();
+
+ template <class V>
+ typename V::R_BasicBlock traverse(V &Vs, typename V::R_Ctx Ctx) {
+ typename V::template Container<Variable*> Nas(Vs, Args.size());
+ typename V::template Container<Variable*> Nis(Vs, Instrs.size());
+
+ // Entering the basic block should do any scope initialization.
+ Vs.enterBasicBlock(*this);
+
+ for (auto *A : Args) {
+ auto Ne = Vs.traverse(A->Definition, Vs.subExprCtx(Ctx));
+ Variable *Nvd = Vs.enterScope(*A, Ne);
+ Nas.push_back(Nvd);
+ }
+ for (auto *I : Instrs) {
+ auto Ne = Vs.traverse(I->Definition, Vs.subExprCtx(Ctx));
+ Variable *Nvd = Vs.enterScope(*I, Ne);
+ Nis.push_back(Nvd);
+ }
+ auto Nt = Vs.traverse(Terminator, 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(BasicBlock *E, C &Cmp) {
+ // TODO: implement CFG comparisons
+ return Cmp.comparePointers(this, E);
+ }
+
+private:
+ friend class SCFG;
+
+ MemRegionRef Arena;
+
+ SCFG *CFGPtr; // The CFG that contains this block.
+ unsigned BlockID; // unique id for this BB in the containing CFG
+ BasicBlock *Parent; // The parent block is the enclosing lexical scope.
+ // The parent dominates this block.
+ BlockArray Predecessors; // Predecessor blocks in the CFG.
+ VarArray Args; // Phi nodes. One argument per predecessor.
+ VarArray Instrs; // Instructions.
+ SExprRef Terminator; // Branch or Goto
+};
+
+
+// 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) {
+ Entry = new (A) BasicBlock(A, nullptr);
+ Exit = new (A) BasicBlock(A, Entry);
+ auto *V = new (A) Variable(new (A) Phi());
+ Exit->addArgument(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) {
+ // TODO: set entry and exit!
+ }
+
+ 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; }
+
+ inline void add(BasicBlock *BB) {
+ assert(BB->CFGPtr == nullptr || BB->CFGPtr == this);
+ BB->setBlockID(Blocks.size());
+ BB->CFGPtr = this;
+ Blocks.reserveCheck(1, Arena);
+ Blocks.push_back(BB);
+ }
+
+ void setEntry(BasicBlock *BB) { Entry = BB; }
+ void setExit(BasicBlock *BB) { Exit = BB; }
+
+ // Set varable ids in all blocks.
+ void renumberVars();
+
+ 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(SCFG *E, C &Cmp) {
+ // TODO -- implement CFG comparisons
+ return Cmp.comparePointers(this, E);
+ }
+
+private:
+ MemRegionRef Arena;
+ BlockArray Blocks;
+ BasicBlock *Entry;
+ BasicBlock *Exit;
+};
+
+
+class Goto : public SExpr {
+public:
+ static bool classof(const SExpr *E) { return E->opcode() == COP_Goto; }
+
+ Goto(BasicBlock *B, unsigned I)
+ : SExpr(COP_Goto), TargetBlock(B), Index(I) {}
+ Goto(const Goto &G, BasicBlock *B, unsigned I)
+ : SExpr(COP_Goto), TargetBlock(B), Index(I) {}
+
+ const BasicBlock *targetBlock() const { return TargetBlock; }
+ BasicBlock *targetBlock() { return TargetBlock; }
+
+ unsigned index() const { return Index; }
+
+ 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(Goto *E, C &Cmp) {
+ // TODO -- implement CFG comparisons
+ return Cmp.comparePointers(this, E);
+ }
+
+private:
+ BasicBlock *TargetBlock;
+ unsigned Index; // Index into Phi nodes of target block.
+};
+
+
+class Branch : public SExpr {
+public:
+ static bool classof(const SExpr *E) { return E->opcode() == COP_Branch; }
+
+ Branch(SExpr *C, BasicBlock *T, BasicBlock *E, unsigned TI, unsigned EI)
+ : SExpr(COP_Branch), Condition(C), ThenBlock(T), ElseBlock(E),
+ ThenIndex(TI), ElseIndex(EI)
+ {}
+ Branch(const Branch &Br, SExpr *C, BasicBlock *T, BasicBlock *E,
+ unsigned TI, unsigned EI)
+ : SExpr(COP_Branch), Condition(C), ThenBlock(T), ElseBlock(E),
+ ThenIndex(TI), ElseIndex(EI)
+ {}
+
+ const SExpr *condition() const { return Condition; }
+ SExpr *condition() { return Condition; }
+
+ const BasicBlock *thenBlock() const { return ThenBlock; }
+ BasicBlock *thenBlock() { return ThenBlock; }
+
+ const BasicBlock *elseBlock() const { return ElseBlock; }
+ BasicBlock *elseBlock() { return ElseBlock; }
+
+ unsigned thenIndex() const { return ThenIndex; }
+ unsigned elseIndex() const { return ElseIndex; }
+
+ 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(ThenBlock);
+ BasicBlock *Nte = Vs.reduceBasicBlockRef(ElseBlock);
+ return Vs.reduceBranch(*this, Nc, Ntb, Nte);
+ }
+
+ template <class C> typename C::CType compare(Branch *E, C &Cmp) {
+ // TODO -- implement CFG comparisons
+ return Cmp.comparePointers(this, E);
+ }
+
+private:
+ SExpr *Condition;
+ BasicBlock *ThenBlock;
+ BasicBlock *ElseBlock;
+ unsigned ThenIndex;
+ unsigned ElseIndex;
+};
+
+
+// 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(Identifier* E, C& Cmp) {
+ 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.get(); } // Address to store to
+ const SExpr *condition() const { return Condition.get(); }
+
+ SExpr *thenExpr() { return ThenExpr.get(); } // Value to store
+ const SExpr *thenExpr() const { return ThenExpr.get(); }
+
+ SExpr *elseExpr() { return ElseExpr.get(); } // Value to store
+ const SExpr *elseExpr() const { return ElseExpr.get(); }
+
+ 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(IfThenElse* E, C& Cmp) {
+ 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:
+ SExprRef Condition;
+ SExprRef ThenExpr;
+ SExprRef 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.get(); }
+ const SExpr *body() const { return Body.get(); }
+
+ 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(Let* E, C& Cmp) {
+ 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;
+ SExprRef Body;
+};
+
+
+
+SExpr *getCanonicalVal(SExpr *E);
+void simplifyIncompleteArg(Variable *V, til::Phi *Ph);
+
+
+} // end namespace til
+} // end namespace threadSafety
+} // end namespace clang
+
+#endif // LLVM_CLANG_THREAD_SAFETY_TIL_H
diff --git a/include/clang/Analysis/Analyses/ThreadSafetyTraverse.h b/include/clang/Analysis/Analyses/ThreadSafetyTraverse.h
new file mode 100644
index 000000000000..bc1490b4a448
--- /dev/null
+++ b/include/clang/Analysis/Analyses/ThreadSafetyTraverse.h
@@ -0,0 +1,936 @@
+//===- 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_THREAD_SAFETY_TRAVERSE_H
+#define LLVM_CLANG_THREAD_SAFETY_TRAVERSE_H
+
+#include "ThreadSafetyTIL.h"
+
+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.
+ typename R::R_SExpr traverse(SExprRef &E, typename R::R_Ctx Ctx) {
+ return traverse(E.get(), Ctx);
+ }
+
+ typename R::R_SExpr traverse(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
+ }
+ }
+
+// 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,
+ TRV_Decl,
+ TRV_Lazy,
+ TRV_Type
+ };
+
+ // 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;
+};
+
+
+// Implements a traversal that makes a deep copy of an SExpr.
+// The default behavior of reduce##X(...) is to create a copy of the original.
+// Subclasses can override reduce##X to implement non-destructive rewriting
+// passes.
+template<class Self>
+class CopyReducer : public Traversal<Self, CopyReducerBase>,
+ public CopyReducerBase {
+public:
+ CopyReducer(MemRegionRef A) : CopyReducerBase(A) {}
+
+public:
+ R_SExpr reduceNull() {
+ return nullptr;
+ }
+ // R_SExpr reduceFuture(...) is never used.
+
+ R_SExpr reduceUndefined(Undefined &Orig) {
+ return new (Arena) Undefined(Orig);
+ }
+ R_SExpr reduceWildcard(Wildcard &Orig) {
+ return new (Arena) Wildcard(Orig);
+ }
+
+ R_SExpr reduceLiteral(Literal &Orig) {
+ return new (Arena) Literal(Orig);
+ }
+ template<class T>
+ R_SExpr reduceLiteralT(LiteralT<T> &Orig) {
+ return new (Arena) LiteralT<T>(Orig);
+ }
+ R_SExpr reduceLiteralPtr(LiteralPtr &Orig) {
+ return new (Arena) LiteralPtr(Orig);
+ }
+
+ R_SExpr reduceFunction(Function &Orig, Variable *Nvd, R_SExpr E0) {
+ return new (Arena) Function(Orig, Nvd, E0);
+ }
+ R_SExpr reduceSFunction(SFunction &Orig, Variable *Nvd, R_SExpr E0) {
+ return new (Arena) SFunction(Orig, Nvd, E0);
+ }
+ R_SExpr reduceCode(Code &Orig, R_SExpr E0, R_SExpr E1) {
+ return new (Arena) Code(Orig, E0, E1);
+ }
+ R_SExpr reduceField(Field &Orig, R_SExpr E0, R_SExpr E1) {
+ return new (Arena) Field(Orig, E0, E1);
+ }
+
+ R_SExpr reduceApply(Apply &Orig, R_SExpr E0, R_SExpr E1) {
+ return new (Arena) Apply(Orig, E0, E1);
+ }
+ R_SExpr reduceSApply(SApply &Orig, R_SExpr E0, R_SExpr E1) {
+ return new (Arena) SApply(Orig, E0, E1);
+ }
+ R_SExpr reduceProject(Project &Orig, R_SExpr E0) {
+ return new (Arena) Project(Orig, E0);
+ }
+ R_SExpr reduceCall(Call &Orig, R_SExpr E0) {
+ return new (Arena) Call(Orig, E0);
+ }
+
+ R_SExpr reduceAlloc(Alloc &Orig, R_SExpr E0) {
+ return new (Arena) Alloc(Orig, E0);
+ }
+ R_SExpr reduceLoad(Load &Orig, R_SExpr E0) {
+ return new (Arena) Load(Orig, E0);
+ }
+ R_SExpr reduceStore(Store &Orig, R_SExpr E0, R_SExpr E1) {
+ return new (Arena) Store(Orig, E0, E1);
+ }
+ R_SExpr reduceArrayIndex(ArrayIndex &Orig, R_SExpr E0, R_SExpr E1) {
+ return new (Arena) ArrayIndex(Orig, E0, E1);
+ }
+ R_SExpr reduceArrayAdd(ArrayAdd &Orig, R_SExpr E0, R_SExpr E1) {
+ return new (Arena) ArrayAdd(Orig, E0, E1);
+ }
+ R_SExpr reduceUnaryOp(UnaryOp &Orig, R_SExpr E0) {
+ return new (Arena) UnaryOp(Orig, E0);
+ }
+ R_SExpr reduceBinaryOp(BinaryOp &Orig, R_SExpr E0, R_SExpr E1) {
+ return new (Arena) BinaryOp(Orig, E0, E1);
+ }
+ R_SExpr reduceCast(Cast &Orig, R_SExpr E0) {
+ return new (Arena) Cast(Orig, E0);
+ }
+
+ R_SExpr reduceSCFG(SCFG &Orig, Container<BasicBlock *> &Bbs) {
+ return nullptr; // FIXME: implement CFG rewriting
+ }
+ R_BasicBlock reduceBasicBlock(BasicBlock &Orig, Container<Variable *> &As,
+ Container<Variable *> &Is, R_SExpr T) {
+ return nullptr; // FIXME: implement CFG rewriting
+ }
+ R_SExpr reducePhi(Phi &Orig, Container<R_SExpr> &As) {
+ return new (Arena) Phi(Orig, std::move(As.Elems));
+ }
+ R_SExpr reduceGoto(Goto &Orig, BasicBlock *B) {
+ return new (Arena) Goto(Orig, B, 0); // FIXME: set index
+ }
+ R_SExpr reduceBranch(Branch &O, R_SExpr C, BasicBlock *B0, BasicBlock *B1) {
+ return new (Arena) Branch(O, C, B0, B1, 0, 0); // FIXME: set indices
+ }
+
+ R_SExpr reduceIdentifier(Identifier &Orig) {
+ return new (Arena) Identifier(Orig);
+ }
+ R_SExpr reduceIfThenElse(IfThenElse &Orig, R_SExpr C, R_SExpr T, R_SExpr E) {
+ return new (Arena) IfThenElse(Orig, C, T, E);
+ }
+ R_SExpr reduceLet(Let &Orig, Variable *Nvd, R_SExpr B) {
+ return new (Arena) Let(Orig, Nvd, B);
+ }
+
+ // Create a new variable from orig, and push it onto the lexical scope.
+ Variable *enterScope(Variable &Orig, R_SExpr E0) {
+ return new (Arena) Variable(Orig, E0);
+ }
+ // Exit the lexical scope of orig.
+ void exitScope(const Variable &Orig) {}
+
+ void enterCFG(SCFG &Cfg) {}
+ void exitCFG(SCFG &Cfg) {}
+ void enterBasicBlock(BasicBlock &BB) {}
+ void exitBasicBlock(BasicBlock &BB) {}
+
+ // Map Variable references to their rewritten definitions.
+ Variable *reduceVariableRef(Variable *Ovd) { return Ovd; }
+
+ // Map BasicBlock references to their rewritten definitions.
+ BasicBlock *reduceBasicBlockRef(BasicBlock *Obb) { return Obb; }
+};
+
+
+class SExprCopier : public CopyReducer<SExprCopier> {
+public:
+ typedef SExpr *R_SExpr;
+
+ SExprCopier(MemRegionRef A) : CopyReducer(A) { }
+
+ // Create a copy of e in region a.
+ static SExpr *copy(SExpr *E, MemRegionRef A) {
+ SExprCopier Copier(A);
+ return Copier.traverse(E, TRV_Normal);
+ }
+};
+
+
+
+// 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<Variable *> &As,
+ Container<Variable *> &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 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(SExpr *E1, 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
+ }
+ }
+};
+
+
+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(SExpr *E1, SExpr* E2) {
+ if (E1->opcode() != E2->opcode())
+ return false;
+ return compareByCase(E1, E2);
+ }
+
+ // TODO -- handle alpha-renaming of variables
+ void enterScope(Variable* V1, Variable* V2) { }
+ void leaveScope() { }
+
+ bool compareVariableRefs(Variable* V1, Variable* V2) {
+ return V1 == V2;
+ }
+
+ static bool compareExprs(SExpr *E1, SExpr* E2) {
+ EqualsComparator Eq;
+ return Eq.compare(E1, E2);
+ }
+};
+
+
+// Pretty printer for TIL expressions
+template <typename Self, typename StreamType>
+class PrettyPrinter {
+private:
+ bool Verbose; // Print out additional information
+ bool Cleanup; // Omit redundant decls.
+
+public:
+ PrettyPrinter(bool V = false, bool C = true) : Verbose(V), Cleanup(C) { }
+
+ static void print(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(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_Unary;
+
+ 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_Identifier: return Prec_Atom;
+ case COP_IfThenElse: return Prec_Other;
+ case COP_Let: return Prec_Decl;
+ }
+ return Prec_MAX;
+ }
+
+ void printBlockLabel(StreamType & SS, BasicBlock *BB, unsigned index) {
+ if (!BB) {
+ SS << "BB_null";
+ return;
+ }
+ SS << "BB_";
+ SS << BB->blockID();
+ SS << ":";
+ SS << index;
+ }
+
+ void printSExpr(SExpr *E, StreamType &SS, unsigned P) {
+ if (!E) {
+ self()->printNull(SS);
+ 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(Future *E, StreamType &SS) {
+ self()->printSExpr(E->maybeGetResult(), SS, Prec_Atom);
+ }
+
+ void printUndefined(Undefined *E, StreamType &SS) {
+ SS << "#undefined";
+ }
+
+ void printWildcard(Wildcard *E, StreamType &SS) {
+ SS << "_";
+ }
+
+ template<class T>
+ void printLiteralT(LiteralT<T> *E, StreamType &SS) {
+ SS << E->value();
+ }
+
+ void printLiteralT(LiteralT<uint8_t> *E, StreamType &SS) {
+ SS << "'" << E->value() << "'";
+ }
+
+ void printLiteral(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(LiteralPtr *E, StreamType &SS) {
+ SS << E->clangDecl()->getNameAsString();
+ }
+
+ void printVariable(Variable *V, StreamType &SS, bool IsVarDecl = false) {
+ if (!IsVarDecl && Cleanup) {
+ SExpr* E = getCanonicalVal(V);
+ if (E != V) {
+ printSExpr(E, SS, Prec_Atom);
+ return;
+ }
+ }
+ if (V->kind() == Variable::VK_LetBB)
+ SS << V->name() << V->getBlockID() << "_" << V->getID();
+ else
+ SS << V->name() << V->getID();
+ }
+
+ void printFunction(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);
+
+ 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(SFunction *E, StreamType &SS) {
+ SS << "@";
+ self()->printVariable(E->variableDecl(), SS, true);
+ SS << " ";
+ self()->printSExpr(E->body(), SS, Prec_Decl);
+ }
+
+ void printCode(Code *E, StreamType &SS) {
+ SS << ": ";
+ self()->printSExpr(E->returnType(), SS, Prec_Decl-1);
+ SS << " -> ";
+ self()->printSExpr(E->body(), SS, Prec_Decl);
+ }
+
+ void printField(Field *E, StreamType &SS) {
+ SS << ": ";
+ self()->printSExpr(E->range(), SS, Prec_Decl-1);
+ SS << " = ";
+ self()->printSExpr(E->body(), SS, Prec_Decl);
+ }
+
+ void printApply(Apply *E, StreamType &SS, bool sugared = false) {
+ 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(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(Project *E, StreamType &SS) {
+ self()->printSExpr(E->record(), SS, Prec_Postfix);
+ SS << ".";
+ SS << E->slotName();
+ }
+
+ void printCall(Call *E, StreamType &SS) {
+ 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(Alloc *E, StreamType &SS) {
+ SS << "new ";
+ self()->printSExpr(E->dataType(), SS, Prec_Other-1);
+ }
+
+ void printLoad(Load *E, StreamType &SS) {
+ self()->printSExpr(E->pointer(), SS, Prec_Postfix);
+ SS << "^";
+ }
+
+ void printStore(Store *E, StreamType &SS) {
+ self()->printSExpr(E->destination(), SS, Prec_Other-1);
+ SS << " := ";
+ self()->printSExpr(E->source(), SS, Prec_Other-1);
+ }
+
+ void printArrayIndex(ArrayIndex *E, StreamType &SS) {
+ self()->printSExpr(E->array(), SS, Prec_Postfix);
+ SS << "[";
+ self()->printSExpr(E->index(), SS, Prec_MAX);
+ SS << "]";
+ }
+
+ void printArrayAdd(ArrayAdd *E, StreamType &SS) {
+ self()->printSExpr(E->array(), SS, Prec_Postfix);
+ SS << " + ";
+ self()->printSExpr(E->index(), SS, Prec_Atom);
+ }
+
+ void printUnaryOp(UnaryOp *E, StreamType &SS) {
+ SS << getUnaryOpcodeString(E->unaryOpcode());
+ self()->printSExpr(E->expr(), SS, Prec_Unary);
+ }
+
+ void printBinaryOp(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(Cast *E, StreamType &SS) {
+ SS << "%";
+ self()->printSExpr(E->expr(), SS, Prec_Unary);
+ }
+
+ void printSCFG(SCFG *E, StreamType &SS) {
+ SS << "CFG {\n";
+ for (auto BBI : *E) {
+ printBasicBlock(BBI, SS);
+ }
+ SS << "}";
+ newline(SS);
+ }
+
+ void printBasicBlock(BasicBlock *E, StreamType &SS) {
+ SS << "BB_" << E->blockID() << ":";
+ if (E->parent())
+ SS << " BB_" << E->parent()->blockID();
+ newline(SS);
+ for (auto *A : E->arguments()) {
+ SS << "let ";
+ self()->printVariable(A, SS, true);
+ SS << " = ";
+ self()->printSExpr(A->definition(), SS, Prec_MAX);
+ SS << ";";
+ newline(SS);
+ }
+ for (auto *I : E->instructions()) {
+ if (I->definition()->opcode() != COP_Store) {
+ SS << "let ";
+ self()->printVariable(I, SS, true);
+ SS << " = ";
+ }
+ self()->printSExpr(I->definition(), SS, Prec_MAX);
+ SS << ";";
+ newline(SS);
+ }
+ SExpr *T = E->terminator();
+ if (T) {
+ self()->printSExpr(T, SS, Prec_MAX);
+ SS << ";";
+ newline(SS);
+ }
+ newline(SS);
+ }
+
+ void printPhi(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(Goto *E, StreamType &SS) {
+ SS << "goto ";
+ printBlockLabel(SS, E->targetBlock(), E->index());
+ }
+
+ void printBranch(Branch *E, StreamType &SS) {
+ SS << "branch (";
+ self()->printSExpr(E->condition(), SS, Prec_MAX);
+ SS << ") ";
+ printBlockLabel(SS, E->thenBlock(), E->thenIndex());
+ SS << " ";
+ printBlockLabel(SS, E->elseBlock(), E->elseIndex());
+ }
+
+ void printIdentifier(Identifier *E, StreamType &SS) {
+ SS << E->name();
+ }
+
+ void printIfThenElse(IfThenElse *E, StreamType &SS) {
+ 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(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);
+ }
+};
+
+
+} // end namespace til
+} // end namespace threadSafety
+} // end namespace clang
+
+#endif // LLVM_CLANG_THREAD_SAFETY_TRAVERSE_H
diff --git a/include/clang/Analysis/Analyses/ThreadSafetyUtil.h b/include/clang/Analysis/Analyses/ThreadSafetyUtil.h
new file mode 100644
index 000000000000..31200a3a7253
--- /dev/null
+++ b/include/clang/Analysis/Analyses/ThreadSafetyUtil.h
@@ -0,0 +1,316 @@
+//===- 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_THREAD_SAFETY_UTIL_H
+#define LLVM_CLANG_THREAD_SAFETY_UTIL_H
+
+#include "llvm/ADT/StringRef.h"
+#include "llvm/Support/AlignOf.h"
+#include "llvm/Support/Allocator.h"
+#include "llvm/Support/Compiler.h"
+#include "clang/AST/ExprCXX.h"
+
+#include <cassert>
+#include <cstddef>
+#include <vector>
+#include <utility>
+
+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;
+
+ 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];
+ }
+
+ iterator begin() { return Data; }
+ iterator end() { return Data + Size; }
+
+ const_iterator cbegin() const { return Data; }
+ const_iterator cend() const { return Data + Size; }
+
+ void push_back(const T &Elem) {
+ assert(Size < Capacity);
+ Data[Size++] = Elem;
+ }
+
+ 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;
+ }
+
+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) LLVM_DELETED_FUNCTION;
+
+ 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) LLVM_DELETED_FUNCTION;
+ void operator=(const CopyOnWriteVector &V) LLVM_DELETED_FUNCTION;
+
+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;
+};
+
+
+} // end namespace threadSafety
+} // end namespace clang
+
+#endif // LLVM_CLANG_THREAD_SAFETY_UTIL_H
diff --git a/include/clang/Analysis/AnalysisContext.h b/include/clang/Analysis/AnalysisContext.h
index b6f183d21b68..08e335418ab7 100644
--- a/include/clang/Analysis/AnalysisContext.h
+++ b/include/clang/Analysis/AnalysisContext.h
@@ -19,8 +19,8 @@
#include "clang/Analysis/CFG.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/FoldingSet.h"
-#include "llvm/ADT/OwningPtr.h"
#include "llvm/Support/Allocator.h"
+#include <memory>
namespace clang {
@@ -69,16 +69,16 @@ class AnalysisDeclContext {
const Decl * const D;
- OwningPtr<CFG> cfg, completeCFG;
- OwningPtr<CFGStmtMap> cfgStmtMap;
+ std::unique_ptr<CFG> cfg, completeCFG;
+ std::unique_ptr<CFGStmtMap> cfgStmtMap;
CFG::BuildOptions cfgBuildOptions;
CFG::BuildOptions::ForcedBlkExprs *forcedBlkExprs;
bool builtCFG, builtCompleteCFG;
- OwningPtr<ParentMap> PM;
- OwningPtr<PseudoConstantAnalysis> PCA;
- OwningPtr<CFGReverseBlockReachabilityAnalysis> CFA;
+ std::unique_ptr<ParentMap> PM;
+ std::unique_ptr<PseudoConstantAnalysis> PCA;
+ std::unique_ptr<CFGReverseBlockReachabilityAnalysis> CFA;
llvm::BumpPtrAllocator A;
@@ -252,7 +252,7 @@ public:
virtual void Profile(llvm::FoldingSetNodeID &ID) = 0;
void dumpStack(raw_ostream &OS, StringRef Indent = "") const;
- LLVM_ATTRIBUTE_USED void dumpStack() const;
+ void dumpStack() const;
public:
static void ProfileCommon(llvm::FoldingSetNodeID &ID,
@@ -287,11 +287,11 @@ public:
const CFGBlock *getCallSiteBlock() const { return Block; }
/// Return true if the current LocationContext has no caller context.
- virtual bool inTopFrame() const { return getParent() == 0; }
+ bool inTopFrame() const override { return getParent() == nullptr; }
unsigned getIndex() const { return Index; }
- void Profile(llvm::FoldingSetNodeID &ID);
+ void Profile(llvm::FoldingSetNodeID &ID) override;
static void Profile(llvm::FoldingSetNodeID &ID, AnalysisDeclContext *ctx,
const LocationContext *parent, const Stmt *s,
@@ -317,7 +317,7 @@ class ScopeContext : public LocationContext {
public:
~ScopeContext() {}
- void Profile(llvm::FoldingSetNodeID &ID);
+ void Profile(llvm::FoldingSetNodeID &ID) override;
static void Profile(llvm::FoldingSetNodeID &ID, AnalysisDeclContext *ctx,
const LocationContext *parent, const Stmt *s) {
@@ -349,7 +349,7 @@ public:
const void *getContextData() const { return ContextData; }
- void Profile(llvm::FoldingSetNodeID &ID);
+ void Profile(llvm::FoldingSetNodeID &ID) override;
static void Profile(llvm::FoldingSetNodeID &ID, AnalysisDeclContext *ctx,
const LocationContext *parent, const BlockDecl *bd,
@@ -409,7 +409,8 @@ public:
bool addInitializers = false,
bool addTemporaryDtors = false,
bool synthesizeBodies = false,
- bool addStaticInitBranches = false);
+ bool addStaticInitBranches = false,
+ bool addCXXNewAllocator = true);
~AnalysisDeclContextManager();
@@ -437,7 +438,8 @@ public:
// Get the top level stack frame.
const StackFrameContext *getStackFrame(const Decl *D) {
- return LocContexts.getStackFrame(getContext(D), 0, 0, 0, 0);
+ return LocContexts.getStackFrame(getContext(D), nullptr, nullptr, nullptr,
+ 0);
}
// Get a stack frame with parent.
diff --git a/include/clang/Analysis/CFG.h b/include/clang/Analysis/CFG.h
index 14b7ab842675..891fb90691f3 100644
--- a/include/clang/Analysis/CFG.h
+++ b/include/clang/Analysis/CFG.h
@@ -21,13 +21,14 @@
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/GraphTraits.h"
#include "llvm/ADT/Optional.h"
-#include "llvm/ADT/OwningPtr.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;
@@ -45,6 +46,8 @@ namespace clang {
class ASTContext;
class CXXRecordDecl;
class CXXDeleteExpr;
+ class CXXNewExpr;
+ class BinaryOperator;
/// CFGElement - Represents a top-level expression in a basic block.
class CFGElement {
@@ -53,6 +56,7 @@ public:
// main kind
Statement,
Initializer,
+ NewAllocator,
// dtor kind
AutomaticObjectDtor,
DeleteDtor,
@@ -68,9 +72,11 @@ protected:
llvm::PointerIntPair<void *, 2> Data1;
llvm::PointerIntPair<void *, 2> Data2;
- CFGElement(Kind kind, const void *Ptr1, const void *Ptr2 = 0)
+ 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) {}
+ Data2(const_cast<void*>(Ptr2), (((unsigned) kind) >> 2) & 0x3) {
+ assert(getKind() == kind);
+ }
CFGElement() {}
public:
@@ -141,12 +147,31 @@ private:
}
};
+/// 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 = 0)
+ CFGImplicitDtor(Kind kind, const void *data1, const void *data2 = nullptr)
: CFGElement(kind, data1, data2) {
assert(kind >= DTOR_BEGIN && kind <= DTOR_END);
}
@@ -237,7 +262,7 @@ private:
class CFGMemberDtor : public CFGImplicitDtor {
public:
CFGMemberDtor(const FieldDecl *field)
- : CFGImplicitDtor(MemberDtor, field, 0) {}
+ : CFGImplicitDtor(MemberDtor, field, nullptr) {}
const FieldDecl *getFieldDecl() const {
return static_cast<const FieldDecl*>(Data1.getPointer());
@@ -256,7 +281,7 @@ private:
class CFGTemporaryDtor : public CFGImplicitDtor {
public:
CFGTemporaryDtor(CXXBindTemporaryExpr *expr)
- : CFGImplicitDtor(TemporaryDtor, expr, 0) {}
+ : CFGImplicitDtor(TemporaryDtor, expr, nullptr) {}
const CXXBindTemporaryExpr *getBindTemporaryExpr() const {
return static_cast<const CXXBindTemporaryExpr *>(Data1.getPointer());
@@ -388,9 +413,64 @@ class CFGBlock {
/// 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<CFGBlock*> AdjacentBlocks;
+ typedef BumpVector<AdjacentBlock> AdjacentBlocks;
AdjacentBlocks Preds;
AdjacentBlocks Succs;
@@ -410,7 +490,7 @@ class CFGBlock {
public:
explicit CFGBlock(unsigned blockid, BumpVectorContext &C, CFG *parent)
- : Elements(C), Label(NULL), Terminator(NULL), LoopTarget(NULL),
+ : Elements(C), Label(nullptr), Terminator(nullptr), LoopTarget(nullptr),
BlockID(blockid), Preds(C, 1), Succs(C, 1), HasNoReturnElement(false),
Parent(parent) {}
~CFGBlock() {}
@@ -480,9 +560,11 @@ public:
class FilterOptions {
public:
FilterOptions() {
+ IgnoreNullPredecessors = 1;
IgnoreDefaultsWithCoveredEnums = 0;
}
+ unsigned IgnoreNullPredecessors : 1;
unsigned IgnoreDefaultsWithCoveredEnums : 1;
};
@@ -495,11 +577,14 @@ public:
IMPL I, E;
const FilterOptions F;
const CFGBlock *From;
- public:
+ public:
explicit FilteredCFGBlockIterator(const IMPL &i, const IMPL &e,
- const CFGBlock *from,
- const FilterOptions &f)
- : I(i), E(e), F(f), From(from) {}
+ 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; }
@@ -531,7 +616,7 @@ public:
// Manipulation of block contents
- void setTerminator(Stmt *Statement) { Terminator = Statement; }
+ void setTerminator(CFGTerminator Term) { Terminator = Term; }
void setLabel(Stmt *Statement) { Label = Statement; }
void setLoopTarget(const Stmt *loopTarget) { LoopTarget = loopTarget; }
void setHasNoReturnElement() { HasNoReturnElement = true; }
@@ -539,10 +624,10 @@ public:
CFGTerminator getTerminator() { return Terminator; }
const CFGTerminator getTerminator() const { return Terminator; }
- Stmt *getTerminatorCondition();
+ Stmt *getTerminatorCondition(bool StripParens = true);
- const Stmt *getTerminatorCondition() const {
- return const_cast<CFGBlock*>(this)->getTerminatorCondition();
+ const Stmt *getTerminatorCondition(bool StripParens = true) const {
+ return const_cast<CFGBlock*>(this)->getTerminatorCondition(StripParens);
}
const Stmt *getLoopTarget() const { return LoopTarget; }
@@ -556,17 +641,19 @@ public:
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 addSuccessor(CFGBlock *Block, BumpVectorContext &C) {
- if (Block)
- Block->Preds.push_back(this, C);
- Succs.push_back(Block, C);
+ 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);
}
@@ -576,6 +663,11 @@ public:
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);
}
@@ -601,7 +693,8 @@ public:
// 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(0, 0), C));
+ return iterator(Elements.insert(I.base(), Cnt,
+ CFGAutomaticObjDtor(nullptr, 0), C));
}
iterator insertAutomaticObjDtor(iterator I, VarDecl *VD, Stmt *S) {
*I = CFGAutomaticObjDtor(VD, S);
@@ -609,6 +702,17 @@ public:
}
};
+/// \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
@@ -627,13 +731,14 @@ public:
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 alwaysAdd(const Stmt *stmt) const {
return alwaysAddMask[stmt->getStmtClass()];
@@ -650,12 +755,11 @@ public:
}
BuildOptions()
- : forcedBlkExprs(0), PruneTriviallyFalseEdges(true)
- ,AddEHEdges(false)
- ,AddInitializers(false)
- ,AddImplicitDtors(false)
- ,AddTemporaryDtors(false)
- ,AddStaticInitBranches(false) {}
+ : forcedBlkExprs(nullptr), Observer(nullptr),
+ PruneTriviallyFalseEdges(true), AddEHEdges(false),
+ AddInitializers(false), AddImplicitDtors(false),
+ AddTemporaryDtors(false), AddStaticInitBranches(false),
+ AddCXXNewAllocator(false) {}
};
/// \brief Provides a custom implementation of the iterator class to have the
@@ -845,8 +949,9 @@ public:
// Internal: constructors and data.
//===--------------------------------------------------------------------===//
- CFG() : Entry(NULL), Exit(NULL), IndirectGotoBlock(NULL), NumBlockIDs(0),
- Blocks(BlkBVC, 10) {}
+ CFG()
+ : Entry(nullptr), Exit(nullptr), IndirectGotoBlock(nullptr), NumBlockIDs(0),
+ Blocks(BlkBVC, 10) {}
llvm::BumpPtrAllocator& getAllocator() {
return BlkBVC.getAllocator();
diff --git a/include/clang/Analysis/FlowSensitive/DataflowSolver.h b/include/clang/Analysis/FlowSensitive/DataflowSolver.h
deleted file mode 100644
index c611ea2397ec..000000000000
--- a/include/clang/Analysis/FlowSensitive/DataflowSolver.h
+++ /dev/null
@@ -1,342 +0,0 @@
-//===--- DataflowSolver.h - Skeleton Dataflow Analysis Code -----*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This file defines skeleton code for implementing dataflow analyses.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLVM_CLANG_ANALYSES_DATAFLOW_SOLVER
-#define LLVM_CLANG_ANALYSES_DATAFLOW_SOLVER
-
-#include "functional" // STL
-#include "clang/Analysis/CFG.h"
-#include "clang/Analysis/FlowSensitive/DataflowValues.h"
-#include "clang/Analysis/ProgramPoint.h"
-#include "llvm/ADT/DenseMap.h"
-#include "llvm/ADT/SmallVector.h"
-
-namespace clang {
-
-//===----------------------------------------------------------------------===//
-/// DataflowWorkListTy - Data structure representing the worklist used for
-/// dataflow algorithms.
-//===----------------------------------------------------------------------===//
-
-class DataflowWorkListTy {
- llvm::DenseMap<const CFGBlock*, unsigned char> BlockSet;
- SmallVector<const CFGBlock *, 10> BlockQueue;
-public:
- /// enqueue - Add a block to the worklist. Blocks already on the
- /// worklist are not added a second time.
- void enqueue(const CFGBlock *B) {
- unsigned char &x = BlockSet[B];
- if (x == 1)
- return;
- x = 1;
- BlockQueue.push_back(B);
- }
-
- /// dequeue - Remove a block from the worklist.
- const CFGBlock *dequeue() {
- assert(!BlockQueue.empty());
- const CFGBlock *B = BlockQueue.pop_back_val();
- BlockSet[B] = 0;
- return B;
- }
-
- /// isEmpty - Return true if the worklist is empty.
- bool isEmpty() const { return BlockQueue.empty(); }
-};
-
-//===----------------------------------------------------------------------===//
-// BlockItrTraits - Traits classes that allow transparent iteration
-// over successors/predecessors of a block depending on the direction
-// of our dataflow analysis.
-//===----------------------------------------------------------------------===//
-
-namespace dataflow {
-template<typename Tag> struct ItrTraits {};
-
-template <> struct ItrTraits<forward_analysis_tag> {
- typedef CFGBlock::const_pred_iterator PrevBItr;
- typedef CFGBlock::const_succ_iterator NextBItr;
- typedef CFGBlock::const_iterator StmtItr;
-
- static PrevBItr PrevBegin(const CFGBlock *B) { return B->pred_begin(); }
- static PrevBItr PrevEnd(const CFGBlock *B) { return B->pred_end(); }
-
- static NextBItr NextBegin(const CFGBlock *B) { return B->succ_begin(); }
- static NextBItr NextEnd(const CFGBlock *B) { return B->succ_end(); }
-
- static StmtItr StmtBegin(const CFGBlock *B) { return B->begin(); }
- static StmtItr StmtEnd(const CFGBlock *B) { return B->end(); }
-
- static BlockEdge PrevEdge(const CFGBlock *B, const CFGBlock *Prev) {
- return BlockEdge(Prev, B, 0);
- }
-
- static BlockEdge NextEdge(const CFGBlock *B, const CFGBlock *Next) {
- return BlockEdge(B, Next, 0);
- }
-};
-
-template <> struct ItrTraits<backward_analysis_tag> {
- typedef CFGBlock::const_succ_iterator PrevBItr;
- typedef CFGBlock::const_pred_iterator NextBItr;
- typedef CFGBlock::const_reverse_iterator StmtItr;
-
- static PrevBItr PrevBegin(const CFGBlock *B) { return B->succ_begin(); }
- static PrevBItr PrevEnd(const CFGBlock *B) { return B->succ_end(); }
-
- static NextBItr NextBegin(const CFGBlock *B) { return B->pred_begin(); }
- static NextBItr NextEnd(const CFGBlock *B) { return B->pred_end(); }
-
- static StmtItr StmtBegin(const CFGBlock *B) { return B->rbegin(); }
- static StmtItr StmtEnd(const CFGBlock *B) { return B->rend(); }
-
- static BlockEdge PrevEdge(const CFGBlock *B, const CFGBlock *Prev) {
- return BlockEdge(B, Prev, 0);
- }
-
- static BlockEdge NextEdge(const CFGBlock *B, const CFGBlock *Next) {
- return BlockEdge(Next, B, 0);
- }
-};
-} // end namespace dataflow
-
-//===----------------------------------------------------------------------===//
-/// DataflowSolverTy - Generic dataflow solver.
-//===----------------------------------------------------------------------===//
-
-template <typename _DFValuesTy, // Usually a subclass of DataflowValues
- typename _TransferFuncsTy,
- typename _MergeOperatorTy,
- typename _Equal = std::equal_to<typename _DFValuesTy::ValTy> >
-class DataflowSolver {
-
- //===----------------------------------------------------===//
- // Type declarations.
- //===----------------------------------------------------===//
-
-public:
- typedef _DFValuesTy DFValuesTy;
- typedef _TransferFuncsTy TransferFuncsTy;
- typedef _MergeOperatorTy MergeOperatorTy;
-
- typedef typename _DFValuesTy::AnalysisDirTag AnalysisDirTag;
- typedef typename _DFValuesTy::ValTy ValTy;
- typedef typename _DFValuesTy::EdgeDataMapTy EdgeDataMapTy;
- typedef typename _DFValuesTy::BlockDataMapTy BlockDataMapTy;
-
- typedef dataflow::ItrTraits<AnalysisDirTag> ItrTraits;
- typedef typename ItrTraits::NextBItr NextBItr;
- typedef typename ItrTraits::PrevBItr PrevBItr;
- typedef typename ItrTraits::StmtItr StmtItr;
-
- //===----------------------------------------------------===//
- // External interface: constructing and running the solver.
- //===----------------------------------------------------===//
-
-public:
- DataflowSolver(DFValuesTy& d) : D(d), TF(d.getAnalysisData()) {}
- ~DataflowSolver() {}
-
- /// runOnCFG - Computes dataflow values for all blocks in a CFG.
- void runOnCFG(CFG& cfg, bool recordStmtValues = false) {
- // Set initial dataflow values and boundary conditions.
- D.InitializeValues(cfg);
- // Solve the dataflow equations. This will populate D.EdgeDataMap
- // with dataflow values.
- SolveDataflowEquations(cfg, recordStmtValues);
- }
-
- /// runOnBlock - Computes dataflow values for a given block. This
- /// should usually be invoked only after previously computing
- /// dataflow values using runOnCFG, as runOnBlock is intended to
- /// only be used for querying the dataflow values within a block
- /// with and Observer object.
- void runOnBlock(const CFGBlock *B, bool recordStmtValues) {
- BlockDataMapTy& M = D.getBlockDataMap();
- typename BlockDataMapTy::iterator I = M.find(B);
-
- if (I != M.end()) {
- TF.getVal().copyValues(I->second);
- ProcessBlock(B, recordStmtValues, AnalysisDirTag());
- }
- }
-
- void runOnBlock(const CFGBlock &B, bool recordStmtValues) {
- runOnBlock(&B, recordStmtValues);
- }
- void runOnBlock(CFG::iterator &I, bool recordStmtValues) {
- runOnBlock(*I, recordStmtValues);
- }
- void runOnBlock(CFG::const_iterator &I, bool recordStmtValues) {
- runOnBlock(*I, recordStmtValues);
- }
-
- void runOnAllBlocks(const CFG& cfg, bool recordStmtValues = false) {
- for (CFG::const_iterator I=cfg.begin(), E=cfg.end(); I!=E; ++I)
- runOnBlock(I, recordStmtValues);
- }
-
- //===----------------------------------------------------===//
- // Internal solver logic.
- //===----------------------------------------------------===//
-
-private:
-
- /// SolveDataflowEquations - Perform the actual worklist algorithm
- /// to compute dataflow values.
- void SolveDataflowEquations(CFG& cfg, bool recordStmtValues) {
- EnqueueBlocksOnWorklist(cfg, AnalysisDirTag());
-
- while (!WorkList.isEmpty()) {
- const CFGBlock *B = WorkList.dequeue();
- ProcessMerge(cfg, B);
- ProcessBlock(B, recordStmtValues, AnalysisDirTag());
- UpdateEdges(cfg, B, TF.getVal());
- }
- }
-
- void EnqueueBlocksOnWorklist(CFG &cfg, dataflow::forward_analysis_tag) {
- // Enqueue all blocks to ensure the dataflow values are computed
- // for every block. Not all blocks are guaranteed to reach the exit block.
- for (CFG::iterator I=cfg.begin(), E=cfg.end(); I!=E; ++I)
- WorkList.enqueue(&**I);
- }
-
- void EnqueueBlocksOnWorklist(CFG &cfg, dataflow::backward_analysis_tag) {
- // Enqueue all blocks to ensure the dataflow values are computed
- // for every block. Not all blocks are guaranteed to reach the exit block.
- // Enqueue in reverse order since that will more likely match with
- // the order they should ideally processed by the dataflow algorithm.
- for (CFG::reverse_iterator I=cfg.rbegin(), E=cfg.rend(); I!=E; ++I)
- WorkList.enqueue(&**I);
- }
-
- void ProcessMerge(CFG& cfg, const CFGBlock *B) {
- ValTy& V = TF.getVal();
- TF.SetTopValue(V);
-
- // Merge dataflow values from all predecessors of this block.
- MergeOperatorTy Merge;
-
- EdgeDataMapTy& M = D.getEdgeDataMap();
- bool firstMerge = true;
- bool noEdges = true;
- for (PrevBItr I=ItrTraits::PrevBegin(B),E=ItrTraits::PrevEnd(B); I!=E; ++I){
-
- CFGBlock *PrevBlk = *I;
-
- if (!PrevBlk)
- continue;
-
- typename EdgeDataMapTy::iterator EI =
- M.find(ItrTraits::PrevEdge(B, PrevBlk));
-
- if (EI != M.end()) {
- noEdges = false;
- if (firstMerge) {
- firstMerge = false;
- V.copyValues(EI->second);
- }
- else
- Merge(V, EI->second);
- }
- }
-
- bool isInitialized = true;
- typename BlockDataMapTy::iterator BI = D.getBlockDataMap().find(B);
- if(BI == D.getBlockDataMap().end()) {
- isInitialized = false;
- BI = D.getBlockDataMap().insert( std::make_pair(B,ValTy()) ).first;
- }
- // If no edges have been found, it means this is the first time the solver
- // has been called on block B, we copy the initialization values (if any)
- // as current value for V (which will be used as edge data)
- if(noEdges && isInitialized)
- Merge(V, BI->second);
-
- // Set the data for the block.
- BI->second.copyValues(V);
- }
-
- /// ProcessBlock - Process the transfer functions for a given block.
- void ProcessBlock(const CFGBlock *B, bool recordStmtValues,
- dataflow::forward_analysis_tag) {
-
- TF.setCurrentBlock(B);
-
- for (StmtItr I=ItrTraits::StmtBegin(B), E=ItrTraits::StmtEnd(B); I!=E;++I) {
- CFGElement El = *I;
- if (const CFGStmt *S = El.getAs<CFGStmt>())
- ProcessStmt(S->getStmt(), recordStmtValues, AnalysisDirTag());
- }
-
- TF.VisitTerminator(const_cast<CFGBlock*>(B));
- }
-
- void ProcessBlock(const CFGBlock *B, bool recordStmtValues,
- dataflow::backward_analysis_tag) {
-
- TF.setCurrentBlock(B);
-
- TF.VisitTerminator(const_cast<CFGBlock*>(B));
-
- for (StmtItr I=ItrTraits::StmtBegin(B), E=ItrTraits::StmtEnd(B); I!=E;++I) {
- CFGElement El = *I;
- if (const CFGStmt *S = El.getAs<CFGStmt>())
- ProcessStmt(S->getStmt(), recordStmtValues, AnalysisDirTag());
- }
- }
-
- void ProcessStmt(const Stmt *S, bool record, dataflow::forward_analysis_tag) {
- if (record) D.getStmtDataMap()[S] = TF.getVal();
- TF.BlockStmt_Visit(const_cast<Stmt*>(S));
- }
-
- void ProcessStmt(const Stmt *S, bool record, dataflow::backward_analysis_tag){
- TF.BlockStmt_Visit(const_cast<Stmt*>(S));
- if (record) D.getStmtDataMap()[S] = TF.getVal();
- }
-
- /// UpdateEdges - After processing the transfer functions for a
- /// block, update the dataflow value associated with the block's
- /// outgoing/incoming edges (depending on whether we do a
- // forward/backward analysis respectively)
- void UpdateEdges(CFG& cfg, const CFGBlock *B, ValTy& V) {
- for (NextBItr I=ItrTraits::NextBegin(B), E=ItrTraits::NextEnd(B); I!=E; ++I)
- if (CFGBlock *NextBlk = *I)
- UpdateEdgeValue(ItrTraits::NextEdge(B, NextBlk),V, NextBlk);
- }
-
- /// UpdateEdgeValue - Update the value associated with a given edge.
- void UpdateEdgeValue(BlockEdge E, ValTy& V, const CFGBlock *TargetBlock) {
- EdgeDataMapTy& M = D.getEdgeDataMap();
- typename EdgeDataMapTy::iterator I = M.find(E);
-
- if (I == M.end()) { // First computed value for this edge?
- M[E].copyValues(V);
- WorkList.enqueue(TargetBlock);
- }
- else if (!_Equal()(V,I->second)) {
- I->second.copyValues(V);
- WorkList.enqueue(TargetBlock);
- }
- }
-
-private:
- DFValuesTy& D;
- DataflowWorkListTy WorkList;
- TransferFuncsTy TF;
-};
-
-} // end namespace clang
-#endif
diff --git a/include/clang/Analysis/ProgramPoint.h b/include/clang/Analysis/ProgramPoint.h
index 333329d8c30b..57324d042908 100644
--- a/include/clang/Analysis/ProgramPoint.h
+++ b/include/clang/Analysis/ProgramPoint.h
@@ -77,9 +77,9 @@ protected:
ProgramPoint(const void *P,
Kind k,
const LocationContext *l,
- const ProgramPointTag *tag = 0)
+ const ProgramPointTag *tag = nullptr)
: Data1(P),
- Data2(0, (((unsigned) k) >> 0) & 0x3),
+ Data2(nullptr, (((unsigned) k) >> 0) & 0x3),
L(l, (((unsigned) k) >> 2) & 0x3),
Tag(tag, (((unsigned) k) >> 4) & 0x3) {
assert(getKind() == k);
@@ -91,7 +91,7 @@ protected:
const void *P2,
Kind k,
const LocationContext *l,
- const ProgramPointTag *tag = 0)
+ const ProgramPointTag *tag = nullptr)
: Data1(P1),
Data2(P2, (((unsigned) k) >> 0) & 0x3),
L(l, (((unsigned) k) >> 2) & 0x3),
@@ -193,7 +193,7 @@ public:
class BlockEntrance : public ProgramPoint {
public:
BlockEntrance(const CFGBlock *B, const LocationContext *L,
- const ProgramPointTag *tag = 0)
+ const ProgramPointTag *tag = nullptr)
: ProgramPoint(B, BlockEntranceKind, L, tag) {
assert(B && "BlockEntrance requires non-null block");
}
@@ -263,7 +263,7 @@ private:
class PreStmt : public StmtPoint {
public:
PreStmt(const Stmt *S, const LocationContext *L, const ProgramPointTag *tag,
- const Stmt *SubStmt = 0)
+ const Stmt *SubStmt = nullptr)
: StmtPoint(S, SubStmt, PreStmtKind, L, tag) {}
const Stmt *getSubStmt() const { return (const Stmt*) getData2(); }
@@ -280,17 +280,17 @@ class PostStmt : public StmtPoint {
protected:
PostStmt() {}
PostStmt(const Stmt *S, const void *data, Kind k, const LocationContext *L,
- const ProgramPointTag *tag = 0)
+ const ProgramPointTag *tag = nullptr)
: StmtPoint(S, data, k, L, tag) {}
public:
- explicit PostStmt(const Stmt *S, Kind k,
- const LocationContext *L, const ProgramPointTag *tag = 0)
- : StmtPoint(S, NULL, k, L, tag) {}
+ 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 = 0)
- : StmtPoint(S, NULL, PostStmtKind, L, tag) {}
+ const ProgramPointTag *tag = nullptr)
+ : StmtPoint(S, nullptr, PostStmtKind, L, tag) {}
private:
friend class ProgramPoint;
@@ -304,7 +304,7 @@ private:
class PostCondition : public PostStmt {
public:
PostCondition(const Stmt *S, const LocationContext *L,
- const ProgramPointTag *tag = 0)
+ const ProgramPointTag *tag = nullptr)
: PostStmt(S, PostConditionKind, L, tag) {}
private:
@@ -320,7 +320,7 @@ protected:
LocationCheck() {}
LocationCheck(const Stmt *S, const LocationContext *L,
ProgramPoint::Kind K, const ProgramPointTag *tag)
- : StmtPoint(S, NULL, K, L, tag) {}
+ : StmtPoint(S, nullptr, K, L, tag) {}
private:
friend class ProgramPoint;
@@ -333,7 +333,7 @@ private:
class PreLoad : public LocationCheck {
public:
PreLoad(const Stmt *S, const LocationContext *L,
- const ProgramPointTag *tag = 0)
+ const ProgramPointTag *tag = nullptr)
: LocationCheck(S, L, PreLoadKind, tag) {}
private:
@@ -347,7 +347,7 @@ private:
class PreStore : public LocationCheck {
public:
PreStore(const Stmt *S, const LocationContext *L,
- const ProgramPointTag *tag = 0)
+ const ProgramPointTag *tag = nullptr)
: LocationCheck(S, L, PreStoreKind, tag) {}
private:
@@ -361,7 +361,7 @@ private:
class PostLoad : public PostStmt {
public:
PostLoad(const Stmt *S, const LocationContext *L,
- const ProgramPointTag *tag = 0)
+ const ProgramPointTag *tag = nullptr)
: PostStmt(S, PostLoadKind, L, tag) {}
private:
@@ -379,9 +379,9 @@ public:
/// \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 = 0)
+ const ProgramPointTag *tag = nullptr)
: PostStmt(S, PostStoreKind, L, tag) {
- assert(getData2() == 0);
+ assert(getData2() == nullptr);
setData2(Loc);
}
@@ -402,7 +402,7 @@ private:
class PostLValue : public PostStmt {
public:
PostLValue(const Stmt *S, const LocationContext *L,
- const ProgramPointTag *tag = 0)
+ const ProgramPointTag *tag = nullptr)
: PostStmt(S, PostLValueKind, L, tag) {}
private:
@@ -418,8 +418,8 @@ private:
class PreStmtPurgeDeadSymbols : public StmtPoint {
public:
PreStmtPurgeDeadSymbols(const Stmt *S, const LocationContext *L,
- const ProgramPointTag *tag = 0)
- : StmtPoint(S, 0, PreStmtPurgeDeadSymbolsKind, L, tag) { }
+ const ProgramPointTag *tag = nullptr)
+ : StmtPoint(S, nullptr, PreStmtPurgeDeadSymbolsKind, L, tag) { }
private:
friend class ProgramPoint;
@@ -434,8 +434,8 @@ private:
class PostStmtPurgeDeadSymbols : public StmtPoint {
public:
PostStmtPurgeDeadSymbols(const Stmt *S, const LocationContext *L,
- const ProgramPointTag *tag = 0)
- : StmtPoint(S, 0, PostStmtPurgeDeadSymbolsKind, L, tag) { }
+ const ProgramPointTag *tag = nullptr)
+ : StmtPoint(S, nullptr, PostStmtPurgeDeadSymbolsKind, L, tag) { }
private:
friend class ProgramPoint;
@@ -527,8 +527,8 @@ private:
/// 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 = 0)
+ PreImplicitCall(const Decl *D, SourceLocation Loc, const LocationContext *L,
+ const ProgramPointTag *Tag = nullptr)
: ImplicitCallPoint(D, Loc, PreImplicitCallKind, L, Tag) {}
private:
@@ -544,8 +544,8 @@ private:
/// 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 = 0)
+ PostImplicitCall(const Decl *D, SourceLocation Loc, const LocationContext *L,
+ const ProgramPointTag *Tag = nullptr)
: ImplicitCallPoint(D, Loc, PostImplicitCallKind, L, Tag) {}
private:
@@ -562,7 +562,7 @@ class CallEnter : public ProgramPoint {
public:
CallEnter(const Stmt *stmt, const StackFrameContext *calleeCtx,
const LocationContext *callerCtx)
- : ProgramPoint(stmt, calleeCtx, CallEnterKind, callerCtx, 0) {}
+ : ProgramPoint(stmt, calleeCtx, CallEnterKind, callerCtx, nullptr) {}
const Stmt *getCallExpr() const {
return static_cast<const Stmt *>(getData1());
@@ -593,7 +593,7 @@ class CallExitBegin : public ProgramPoint {
public:
// CallExitBegin uses the callee's location context.
CallExitBegin(const StackFrameContext *L)
- : ProgramPoint(0, CallExitBeginKind, L, 0) {}
+ : ProgramPoint(nullptr, CallExitBeginKind, L, nullptr) {}
private:
friend class ProgramPoint;
@@ -610,7 +610,7 @@ public:
// CallExitEnd uses the caller's location context.
CallExitEnd(const StackFrameContext *CalleeCtx,
const LocationContext *CallerCtx)
- : ProgramPoint(CalleeCtx, CallExitEndKind, CallerCtx, 0) {}
+ : ProgramPoint(CalleeCtx, CallExitEndKind, CallerCtx, nullptr) {}
const StackFrameContext *getCalleeContext() const {
return static_cast<const StackFrameContext *>(getData1());
@@ -629,7 +629,8 @@ private:
class EpsilonPoint : public ProgramPoint {
public:
EpsilonPoint(const LocationContext *L, const void *Data1,
- const void *Data2 = 0, const ProgramPointTag *tag = 0)
+ const void *Data2 = nullptr,
+ const ProgramPointTag *tag = nullptr)
: ProgramPoint(Data1, Data2, EpsilonKind, L, tag) {}
const void *getData() const { return getData1(); }
@@ -647,7 +648,7 @@ private:
/// description and potentially other information.
class ProgramPointTag {
public:
- ProgramPointTag(void *tagKind = 0) : TagKind(tagKind) {}
+ ProgramPointTag(void *tagKind = nullptr) : TagKind(tagKind) {}
virtual ~ProgramPointTag();
virtual StringRef getTagDescription() const = 0;
@@ -658,12 +659,12 @@ protected:
private:
const void *TagKind;
};
-
+
class SimpleProgramPointTag : public ProgramPointTag {
- std::string desc;
+ std::string Desc;
public:
- SimpleProgramPointTag(StringRef description);
- StringRef getTagDescription() const;
+ SimpleProgramPointTag(StringRef MsgProvider, StringRef Msg);
+ StringRef getTagDescription() const override;
};
} // end namespace clang
@@ -676,13 +677,13 @@ template <> struct DenseMapInfo<clang::ProgramPoint> {
static inline clang::ProgramPoint getEmptyKey() {
uintptr_t x =
reinterpret_cast<uintptr_t>(DenseMapInfo<void*>::getEmptyKey()) & ~0x7;
- return clang::BlockEntrance(reinterpret_cast<clang::CFGBlock*>(x), 0);
+ 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), 0);
+ return clang::BlockEntrance(reinterpret_cast<clang::CFGBlock*>(x), nullptr);
}
static unsigned getHashValue(const clang::ProgramPoint &Loc) {
diff --git a/include/clang/Analysis/Support/BumpVector.h b/include/clang/Analysis/Support/BumpVector.h
index 387e7792bd38..6d0427ba92b5 100644
--- a/include/clang/Analysis/Support/BumpVector.h
+++ b/include/clang/Analysis/Support/BumpVector.h
@@ -55,12 +55,12 @@ class BumpVector {
public:
// Default ctor - Initialize to empty.
explicit BumpVector(BumpVectorContext &C, unsigned N)
- : Begin(NULL), End(NULL), Capacity(NULL) {
+ : Begin(nullptr), End(nullptr), Capacity(nullptr) {
reserve(C, N);
}
~BumpVector() {
- if (llvm::is_class<T>::value) {
+ if (std::is_class<T>::value) {
// Destroy the constructed elements in the vector.
destroy_range(Begin, End);
}
@@ -130,7 +130,7 @@ public:
}
void clear() {
- if (llvm::is_class<T>::value) {
+ if (std::is_class<T>::value) {
destroy_range(Begin, End);
}
End = Begin;
@@ -223,7 +223,7 @@ void BumpVector<T>::grow(BumpVectorContext &C, size_t MinSize) {
T *NewElts = C.getAllocator().template Allocate<T>(NewCapacity);
// Copy the elements over.
- if (llvm::is_class<T>::value) {
+ if (std::is_class<T>::value) {
std::uninitialized_copy(Begin, End, NewElts);
// Destroy the original elements.
destroy_range(Begin, End);
diff --git a/include/clang/Basic/ABI.h b/include/clang/Basic/ABI.h
index 3b3d59efc015..9e8ef2e3ee8e 100644
--- a/include/clang/Basic/ABI.h
+++ b/include/clang/Basic/ABI.h
@@ -186,10 +186,10 @@ struct ThunkInfo {
/// an ABI-specific comparator.
const CXXMethodDecl *Method;
- ThunkInfo() : Method(0) { }
+ ThunkInfo() : Method(nullptr) { }
ThunkInfo(const ThisAdjustment &This, const ReturnAdjustment &Return,
- const CXXMethodDecl *Method = 0)
+ const CXXMethodDecl *Method = nullptr)
: This(This), Return(Return), Method(Method) {}
friend bool operator==(const ThunkInfo &LHS, const ThunkInfo &RHS) {
@@ -197,7 +197,9 @@ struct ThunkInfo {
LHS.Method == RHS.Method;
}
- bool isEmpty() const { return This.isEmpty() && Return.isEmpty() && Method == 0; }
+ bool isEmpty() const {
+ return This.isEmpty() && Return.isEmpty() && Method == nullptr;
+ }
};
} // end namespace clang
diff --git a/include/clang/Basic/Attr.td b/include/clang/Basic/Attr.td
index 8c3bdba89a8c..704a375ba291 100644
--- a/include/clang/Basic/Attr.td
+++ b/include/clang/Basic/Attr.td
@@ -7,6 +7,54 @@
//
//===----------------------------------------------------------------------===//
+// 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
@@ -19,29 +67,63 @@ include "clang/Basic/StmtNodes.td"
// A subset-subject is an AttrSubject constrained to operate only on some subset
// of that subject.
//
-// The description is used in output messages to specify what the subject
-// represents. FIXME: Deal with translation issues.
-//
// The code fragment is a boolean expression that will confirm that the subject
// meets the requirements; the subject will have the name S, and will have the
// type specified by the base. It should be a simple boolean expression.
-class SubsetSubject<AttrSubject base, string description, code check>
- : AttrSubject {
+class SubsetSubject<AttrSubject base, code check> : AttrSubject {
AttrSubject Base = base;
- string Description = description;
code CheckCode = check;
}
// This is the type of a variable which C++11 allows alignas(...) to appertain
// to.
-def NormalVar : SubsetSubject<Var, "non-register, non-parameter variable",
+def NormalVar : SubsetSubject<Var,
[{S->getStorageClass() != VarDecl::Register &&
S->getKind() != Decl::ImplicitParam &&
S->getKind() != Decl::ParmVar &&
S->getKind() != Decl::NonTypeTemplateParm}]>;
-def NonBitField : SubsetSubject<Field, "non-bit field",
+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) != NULL}]>;
+
+// 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) != NULL &&
+ isa<FunctionProtoType>(S->getFunctionType())) ||
+ isa<ObjCMethodDecl>(S) ||
+ isa<BlockDecl>(S)}]>;
+
// A single argument to an attribute
class Argument<string name, bit optional> {
string Name = name;
@@ -56,7 +138,6 @@ 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 SourceLocArgument<string name, bit opt = 0> : Argument<name, opt>;
class VariadicUnsignedArgument<string name> : Argument<name, 1>;
class VariadicExprArgument<string name> : Argument<name, 1>;
@@ -68,6 +149,11 @@ class VersionArgument<string name, bit opt = 0> : Argument<name, opt>;
// 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;
@@ -95,6 +181,7 @@ class VariadicEnumArgument<string name, string type, list<string> values,
class Spelling<string name, string variety> {
string Name = name;
string Variety = variety;
+ bit KnownToGCC;
}
class GNU<string name> : Spelling<name, "GNU">;
@@ -103,17 +190,62 @@ class CXX11<string namespace, string name> : Spelling<name, "CXX11"> {
string Namespace = namespace;
}
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> {
+ string Name = name;
+}
+def MicrosoftExt : LangOpt<"MicrosoftExt">;
+def Borland : LangOpt<"Borland">;
+def CUDA : LangOpt<"CUDA">;
+
+// 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;
+}
+def TargetARM : TargetArch<["arm", "thumb"]>;
+def TargetMSP430 : TargetArch<["msp430"]>;
+def TargetX86 : TargetArch<["x86"]>;
+def TargetWindows : TargetArch<["x86", "x86_64", "arm", "thumb"]> {
+ let OSes = ["Win32"];
+}
+def TargetMips : TargetArch<["mips", "mipsel"]>;
+
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
- list<AttrSubject> Subjects;
+ SubjectList Subjects;
// The arguments allowed on an attribute
list<Argument> Args = [];
// Accessors which should be generated for the attribute.
@@ -131,28 +263,55 @@ class Attr {
bit SemaHandler = 1;
// Set to true for attributes that are completely ignored.
bit Ignored = 0;
- // Set to true if each of the spellings is a distinct attribute.
- bit DistinctSpellings = 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.
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 that is meant to be processed via
-/// TargetAttributesSema::ProcessDeclAttribute. This class is meant to be used
-/// as a mixin with InheritableAttr or Attr depending on the attribute's needs.
-class TargetSpecificAttr;
+/// 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.
@@ -163,6 +322,7 @@ class IgnoredAttr : Attr {
let Ignored = 1;
let ASTNode = 0;
let SemaHandler = 0;
+ let Documentation = [Undocumented];
}
//
@@ -172,66 +332,77 @@ class IgnoredAttr : Attr {
def AddressSpace : TypeAttr {
let Spellings = [GNU<"address_space">];
let Args = [IntArgument<"AddressSpace">];
+ let Documentation = [Undocumented];
}
def Alias : Attr {
- let Spellings = [GNU<"alias">, CXX11<"gnu", "alias">];
+ let Spellings = [GCC<"alias">];
let Args = [StringArgument<"Aliasee">];
+ let Documentation = [Undocumented];
}
def Aligned : InheritableAttr {
- let Spellings = [GNU<"aligned">, Declspec<"align">, CXX11<"gnu", "aligned">,
- Keyword<"alignas">, Keyword<"_Alignas">];
- let Subjects = [NonBitField, NormalVar, Tag];
+ 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", [GNU<"aligned">, CXX11<"gnu","aligned">]>,
+ let Accessors = [Accessor<"isGNU", [GCC<"aligned">]>,
Accessor<"isC11", [Keyword<"_Alignas">]>,
Accessor<"isAlignas", [Keyword<"alignas">,
Keyword<"_Alignas">]>,
Accessor<"isDeclspec",[Declspec<"align">]>];
+ let Documentation = [Undocumented];
}
def AlignMac68k : InheritableAttr {
+ // This attribute has no spellings as it is only ever created implicitly.
let Spellings = [];
let SemaHandler = 0;
-}
-
-def AllocSize : InheritableAttr {
- let Spellings = [GNU<"alloc_size">, CXX11<"gnu", "alloc_size">];
- let Args = [VariadicUnsignedArgument<"Args">];
+ let Documentation = [Undocumented];
}
def AlwaysInline : InheritableAttr {
- let Spellings = [GNU<"always_inline">, CXX11<"gnu", "always_inline">];
+ let Spellings = [GCC<"always_inline">, Keyword<"__forceinline">];
+ let Subjects = SubjectList<[Function]>;
+ let Documentation = [Undocumented];
}
def TLSModel : InheritableAttr {
- let Spellings = [GNU<"tls_model">, CXX11<"gnu", "tls_model">];
- let Subjects = [Var];
+ 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 {
+def ARMInterrupt : InheritableAttr, TargetSpecificAttr<TargetARM> {
+ // NOTE: If you add any additional spellings, MSP430Interrupt'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 = [];
+ let Spellings = [Keyword<"asm">, Keyword<"__asm__">];
let Args = [StringArgument<"Label">];
let SemaHandler = 0;
+ let Documentation = [Undocumented];
}
def Availability : InheritableAttr {
@@ -247,11 +418,15 @@ def Availability : InheritableAttr {
.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 {
@@ -259,14 +434,15 @@ def Bounded : IgnoredAttr {
}
def CarriesDependency : InheritableParamAttr {
- let Spellings = [GNU<"carries_dependency">, CXX11<"","carries_dependency">,
- CXX11<"std","carries_dependency">];
- let Subjects = [ParmVar, Function];
+ let Spellings = [GNU<"carries_dependency">, CXX11<"","carries_dependency">];
+ let Subjects = SubjectList<[ParmVar, ObjCMethod, Function], ErrorDiag>;
+ let Documentation = [CarriesDependencyDocs];
}
def CDecl : InheritableAttr {
- let Spellings = [GNU<"cdecl">, CXX11<"gnu", "cdecl">, Keyword<"__cdecl">,
- Keyword<"_cdecl">];
+ 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
@@ -275,7 +451,8 @@ def CDecl : InheritableAttr {
// '#pragma clang arc_cf_code_audited' rather than explicitly.
def CFAuditedTransfer : InheritableAttr {
let Spellings = [GNU<"cf_audited_transfer">];
- let Subjects = [Function];
+ let Subjects = SubjectList<[Function], ErrorDiag>;
+ let Documentation = [Undocumented];
}
// cf_unknown_transfer is an explicit opt-out of cf_audited_transfer.
@@ -283,386 +460,623 @@ def CFAuditedTransfer : InheritableAttr {
// transfer semantics.
def CFUnknownTransfer : InheritableAttr {
let Spellings = [GNU<"cf_unknown_transfer">];
- let Subjects = [Function];
+ let Subjects = SubjectList<[Function], ErrorDiag>;
+ let Documentation = [Undocumented];
}
def CFReturnsRetained : InheritableAttr {
let Spellings = [GNU<"cf_returns_retained">];
- let Subjects = [ObjCMethod, Function];
+// let Subjects = SubjectList<[ObjCMethod, ObjCProperty, Function]>;
+ let Documentation = [Undocumented];
}
def CFReturnsNotRetained : InheritableAttr {
let Spellings = [GNU<"cf_returns_not_retained">];
- let Subjects = [ObjCMethod, Function];
+// let Subjects = SubjectList<[ObjCMethod, ObjCProperty, Function]>;
+ let Documentation = [Undocumented];
}
def CFConsumed : InheritableParamAttr {
let Spellings = [GNU<"cf_consumed">];
- let Subjects = [ParmVar];
+ let Subjects = SubjectList<[ParmVar]>;
+ let Documentation = [Undocumented];
}
def Cleanup : InheritableAttr {
- let Spellings = [GNU<"cleanup">, CXX11<"gnu", "cleanup">];
+ let Spellings = [GCC<"cleanup">];
let Args = [FunctionArgument<"FunctionDecl">];
+ let Subjects = SubjectList<[Var]>;
+ let Documentation = [Undocumented];
}
def Cold : InheritableAttr {
- let Spellings = [GNU<"cold">, CXX11<"gnu", "cold">];
+ let Spellings = [GCC<"cold">];
+ let Subjects = SubjectList<[Function]>;
+ let Documentation = [Undocumented];
}
def Common : InheritableAttr {
- let Spellings = [GNU<"common">, CXX11<"gnu", "common">];
+ let Spellings = [GCC<"common">];
+ let Subjects = SubjectList<[Var]>;
+ let Documentation = [Undocumented];
}
def Const : InheritableAttr {
- let Spellings = [GNU<"const">, GNU<"__const">,
- CXX11<"gnu", "const">, CXX11<"gnu", "__const">];
+ let Spellings = [GCC<"const">, GCC<"__const">];
+ let Documentation = [Undocumented];
}
def Constructor : InheritableAttr {
- let Spellings = [GNU<"constructor">, CXX11<"gnu", "constructor">];
- let Args = [IntArgument<"Priority", 1>];
+ 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 CUDADevice : InheritableAttr {
let Spellings = [GNU<"device">];
+ let Subjects = SubjectList<[Function, Var]>;
+ let LangOpts = [CUDA];
+ let Documentation = [Undocumented];
}
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 CUDALaunchBounds : InheritableAttr {
let Spellings = [GNU<"launch_bounds">];
let Args = [IntArgument<"MaxThreads">, DefaultIntArgument<"MinBlocks", 0>];
+ 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 = [Function];
+ let Subjects = SubjectList<[Function], ErrorDiag>;
let SemaHandler = 0;
+ let Documentation = [C11NoReturnDocs];
}
def CXX11NoReturn : InheritableAttr {
- let Spellings = [CXX11<"","noreturn">, CXX11<"std","noreturn">];
- let Subjects = [Function];
+ let Spellings = [CXX11<"","noreturn">];
+ 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 = [GNU<"opencl_image_access">];
- let Args = [IntArgument<"Access">];
+ 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 = [Undocumented];
+}
+
+def OpenCLGlobalAddressSpace : TypeAttr {
+ let Spellings = [Keyword<"__global">, Keyword<"global">];
+ let Documentation = [Undocumented];
+}
+
+def OpenCLLocalAddressSpace : TypeAttr {
+ let Spellings = [Keyword<"__local">, Keyword<"local">];
+ let Documentation = [Undocumented];
+}
+
+def OpenCLConstantAddressSpace : TypeAttr {
+ let Spellings = [Keyword<"__constant">, Keyword<"constant">];
+ let Documentation = [Undocumented];
}
def Deprecated : InheritableAttr {
- let Spellings = [GNU<"deprecated">,
- CXX11<"gnu", "deprecated">, CXX11<"","deprecated">];
+ let Spellings = [GCC<"deprecated">, Declspec<"deprecated">,
+ CXX11<"","deprecated">];
let Args = [StringArgument<"Message", 1>];
+ let Documentation = [Undocumented];
}
def Destructor : InheritableAttr {
- let Spellings = [GNU<"destructor">, CXX11<"gnu", "destructor">];
- let Args = [IntArgument<"Priority", 1>];
+ 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 Subjects = [NullStmt];
+ let Documentation = [FallthroughDocs];
}
def FastCall : InheritableAttr {
- let Spellings = [GNU<"fastcall">, CXX11<"gnu", "fastcall">,
- Keyword<"__fastcall">, Keyword<"_fastcall">];
+ let Spellings = [GCC<"fastcall">, Keyword<"__fastcall">,
+ Keyword<"_fastcall">];
+// let Subjects = [Function, ObjCMethod];
+ let Documentation = [Undocumented];
}
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 = [Function];
+ let Subjects = SubjectList<[Function, ObjCMethod], ErrorDiag>;
+ let Documentation = [Undocumented];
+}
+
+def Flatten : InheritableAttr {
+ let Spellings = [GCC<"flatten">];
+ let Subjects = SubjectList<[Function], ErrorDiag>;
+ let Documentation = [FlattenDocs];
}
def Format : InheritableAttr {
- let Spellings = [GNU<"format">, CXX11<"gnu", "format">];
+ let Spellings = [GCC<"format">];
let Args = [IdentifierArgument<"Type">, IntArgument<"FormatIdx">,
IntArgument<"FirstArg">];
+ let Subjects = SubjectList<[ObjCMethod, Block, HasFunctionProto], WarnDiag,
+ "ExpectedFunction">;
+ let Documentation = [FormatDocs];
}
def FormatArg : InheritableAttr {
- let Spellings = [GNU<"format_arg">, CXX11<"gnu", "format_arg">];
+ let Spellings = [GCC<"format_arg">];
let Args = [IntArgument<"FormatIdx">];
+ let Subjects = SubjectList<[ObjCMethod, HasFunctionProto], WarnDiag,
+ "ExpectedFunction">;
+ let Documentation = [Undocumented];
}
def GNUInline : InheritableAttr {
- let Spellings = [GNU<"gnu_inline">, CXX11<"gnu", "gnu_inline">];
+ let Spellings = [GCC<"gnu_inline">];
+ let Subjects = SubjectList<[Function]>;
+ let Documentation = [Undocumented];
}
def Hot : InheritableAttr {
- let Spellings = [GNU<"hot">, CXX11<"gnu", "hot">];
+ 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 Malloc : InheritableAttr {
- let Spellings = [GNU<"malloc">, CXX11<"gnu", "malloc">];
+ let Spellings = [GCC<"malloc">];
+// let Subjects = [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 {
- let Spellings = [GNU<"may_alias">, CXX11<"gnu", "may_alias">];
+ // 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 = [GNU<"ms_abi">, CXX11<"gnu", "ms_abi">];
+ let Spellings = [GCC<"ms_abi">];
+// let Subjects = [Function, ObjCMethod];
+ let Documentation = [Undocumented];
}
-def MSP430Interrupt : InheritableAttr, TargetSpecificAttr {
- let Spellings = [];
+def MSP430Interrupt : InheritableAttr, TargetSpecificAttr<TargetMSP430> {
+ // NOTE: If you add any additional spellings, ARMInterrupt's spellings must
+ // match.
+ let Spellings = [GNU<"interrupt">];
let Args = [UnsignedArgument<"Number">];
- let SemaHandler = 0;
+ let ParseKind = "Interrupt";
+ let HasCustomParsing = 1;
+ let Documentation = [Undocumented];
}
-def Mips16 : InheritableAttr, TargetSpecificAttr {
- let Spellings = [GNU<"mips16">, CXX11<"gnu", "mips16">];
- let Subjects = [Function];
+def Mips16 : InheritableAttr, TargetSpecificAttr<TargetMips> {
+ let Spellings = [GCC<"mips16">];
+ let Subjects = SubjectList<[Function], ErrorDiag>;
+ let Documentation = [Undocumented];
}
def Mode : Attr {
- let Spellings = [GNU<"mode">, CXX11<"gnu", "mode">];
+ let Spellings = [GCC<"mode">];
let Args = [IdentifierArgument<"Mode">];
+ let Documentation = [Undocumented];
}
def Naked : InheritableAttr {
- let Spellings = [GNU<"naked">, CXX11<"gnu", "naked">];
+ 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 = [GNU<"returns_twice">, CXX11<"gnu", "returns_twice">];
+ let Spellings = [GCC<"returns_twice">];
+ let Subjects = SubjectList<[Function]>;
+ let Documentation = [Undocumented];
}
def NoCommon : InheritableAttr {
- let Spellings = [GNU<"nocommon">, CXX11<"gnu", "nocommon">];
+ let Spellings = [GCC<"nocommon">];
+ let Subjects = SubjectList<[Var]>;
+ let Documentation = [Undocumented];
}
def NoDebug : InheritableAttr {
let Spellings = [GNU<"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 = [GNU<"noinline">, CXX11<"gnu", "noinline">];
+ 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];
}
-def NoMips16 : InheritableAttr, TargetSpecificAttr {
- let Spellings = [GNU<"nomips16">, CXX11<"gnu", "nomips16">];
- let Subjects = [Function];
+def NoSplitStack : InheritableAttr {
+ let Spellings = [GCC<"no_split_stack">];
+ let Subjects = SubjectList<[Function], ErrorDiag>;
+ let Documentation = [NoSplitStackDocs];
}
def NonNull : InheritableAttr {
- let Spellings = [GNU<"nonnull">, CXX11<"gnu", "nonnull">];
+ let Spellings = [GCC<"nonnull">];
+ let Subjects = SubjectList<[ObjCMethod, HasFunctionProto, ParmVar], WarnDiag,
+ "ExpectedFunctionMethodOrParameter">;
let Args = [VariadicUnsignedArgument<"Args">];
let AdditionalMembers =
[{bool isNonNull(unsigned idx) const {
- for (args_iterator i = args_begin(), e = args_end();
- i != e; ++i)
- if (*i == idx)
+ for (const auto &V : args())
+ if (V == idx)
return true;
return false;
} }];
+ let Documentation = [Undocumented];
+}
+
+def ReturnsNonNull : InheritableAttr {
+ let Spellings = [GCC<"returns_nonnull">];
+ let Subjects = SubjectList<[ObjCMethod, Function], WarnDiag,
+ "ExpectedFunctionOrMethod">;
+ let Documentation = [Undocumented];
}
def NoReturn : InheritableAttr {
- let Spellings = [GNU<"noreturn">, CXX11<"gnu", "noreturn">];
+ let Spellings = [GCC<"noreturn">, Declspec<"noreturn">];
// FIXME: Does GCC allow this on the function instead?
- let Subjects = [Function];
+ let Documentation = [Undocumented];
}
def NoInstrumentFunction : InheritableAttr {
- let Spellings = [GNU<"no_instrument_function">,
- CXX11<"gnu", "no_instrument_function">];
- let Subjects = [Function];
+ let Spellings = [GCC<"no_instrument_function">];
+ let Subjects = SubjectList<[Function]>;
+ let Documentation = [Undocumented];
}
def NoThrow : InheritableAttr {
- let Spellings = [GNU<"nothrow">, CXX11<"gnu", "nothrow">];
-}
-
-def NSBridged : InheritableAttr {
- let Spellings = [GNU<"ns_bridged">];
- let Subjects = [Record];
- let Args = [IdentifierArgument<"BridgedType", 1>];
+ let Spellings = [GCC<"nothrow">, Declspec<"nothrow">];
+ let Documentation = [Undocumented];
}
def ObjCBridge : InheritableAttr {
let Spellings = [GNU<"objc_bridge">];
- let Subjects = [Record];
- let Args = [IdentifierArgument<"BridgedType", 1>];
+ let Subjects = SubjectList<[Record], ErrorDiag>;
+ 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">,
+ IdentifierArgument<"InstanceMethod">];
+ let HasCustomParsing = 1;
+ let Documentation = [Undocumented];
}
def NSReturnsRetained : InheritableAttr {
let Spellings = [GNU<"ns_returns_retained">];
- let Subjects = [ObjCMethod, Function];
+// let Subjects = SubjectList<[ObjCMethod, ObjCProperty, Function]>;
+ let Documentation = [Undocumented];
}
def NSReturnsNotRetained : InheritableAttr {
let Spellings = [GNU<"ns_returns_not_retained">];
- let Subjects = [ObjCMethod, Function];
+// let Subjects = SubjectList<[ObjCMethod, ObjCProperty, Function]>;
+ let Documentation = [Undocumented];
}
def NSReturnsAutoreleased : InheritableAttr {
let Spellings = [GNU<"ns_returns_autoreleased">];
- let Subjects = [ObjCMethod, Function];
+// let Subjects = SubjectList<[ObjCMethod, ObjCProperty, Function]>;
+ let Documentation = [Undocumented];
}
def NSConsumesSelf : InheritableAttr {
let Spellings = [GNU<"ns_consumes_self">];
- let Subjects = [ObjCMethod];
+ let Subjects = SubjectList<[ObjCMethod]>;
+ let Documentation = [Undocumented];
}
def NSConsumed : InheritableParamAttr {
let Spellings = [GNU<"ns_consumed">];
- let Subjects = [ParmVar];
+ 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 = [ObjCMethod];
+ 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 ObjCPreciseLifetime : InheritableAttr {
let Spellings = [GNU<"objc_precise_lifetime">];
- let Subjects = [Var];
+ let Subjects = SubjectList<[Var], ErrorDiag>;
+ let Documentation = [Undocumented];
}
def ObjCReturnsInnerPointer : InheritableAttr {
let Spellings = [GNU<"objc_returns_inner_pointer">];
- let Subjects = [ObjCMethod, ObjCProperty];
+ let Subjects = SubjectList<[ObjCMethod, ObjCProperty], ErrorDiag>;
+ let Documentation = [Undocumented];
}
def ObjCRequiresSuper : InheritableAttr {
let Spellings = [GNU<"objc_requires_super">];
- let Subjects = [ObjCMethod];
+ let Subjects = SubjectList<[ObjCMethod], ErrorDiag>;
+ let Documentation = [ObjCRequiresSuperDocs];
}
def ObjCRootClass : InheritableAttr {
let Spellings = [GNU<"objc_root_class">];
- let Subjects = [ObjCInterface];
+ 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 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 = [];
+ 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 DistinctSpellings = 1;
- let Args = [EnumArgument<"OwnKind", "OwnershipKind",
- ["ownership_holds", "ownership_returns", "ownership_takes"],
- ["Holds", "Returns", "Takes"]>,
- StringArgument<"Module">, VariadicUnsignedArgument<"Args">];
- let HasCustomParsing = 1;
+ 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, "ExpectedFunction">;
+ let Documentation = [Undocumented];
}
def Packed : InheritableAttr {
- let Spellings = [GNU<"packed">, CXX11<"gnu", "packed">];
+ let Spellings = [GCC<"packed">];
+// let Subjects = [Tag, Field];
+ let Documentation = [Undocumented];
}
def PnaclCall : InheritableAttr {
let Spellings = [GNU<"pnaclcall">];
+// let Subjects = [Function, ObjCMethod];
+ let Documentation = [Undocumented];
}
def IntelOclBicc : InheritableAttr {
let Spellings = [GNU<"intel_ocl_bicc">];
+// let Subjects = [Function, ObjCMethod];
+ let Documentation = [Undocumented];
}
def Pcs : InheritableAttr {
- let Spellings = [GNU<"pcs">, CXX11<"gnu", "pcs">];
+ 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 = [GNU<"pure">, CXX11<"gnu", "pure">];
+ let Spellings = [GCC<"pure">];
+ let Documentation = [Undocumented];
}
-def Regparm : InheritableAttr {
- let Spellings = [GNU<"regparm">, CXX11<"gnu", "regparm">];
+def Regparm : TypeAttr {
+ let Spellings = [GCC<"regparm">];
let Args = [UnsignedArgument<"NumParams">];
+ let Documentation = [Undocumented];
}
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 {
@@ -670,102 +1084,137 @@ def WorkGroupSizeHint : InheritableAttr {
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 = [GNU<"section">, CXX11<"gnu", "section">];
+ 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 = [GNU<"sentinel">, CXX11<"gnu", "sentinel">];
+ 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 = [GNU<"stdcall">, CXX11<"gnu", "stdcall">,
- Keyword<"__stdcall">, Keyword<"_stdcall">];
+ let Spellings = [GCC<"stdcall">, Keyword<"__stdcall">, Keyword<"_stdcall">];
+// let Subjects = [Function, ObjCMethod];
+ let Documentation = [Undocumented];
}
def SysVABI : InheritableAttr {
- let Spellings = [GNU<"sysv_abi">, CXX11<"gnu", "sysv_abi">];
+ let Spellings = [GCC<"sysv_abi">];
+// let Subjects = [Function, ObjCMethod];
+ let Documentation = [Undocumented];
}
def ThisCall : InheritableAttr {
- let Spellings = [GNU<"thiscall">, CXX11<"gnu", "thiscall">,
- Keyword<"__thiscall">, Keyword<"_thiscall">];
+ let Spellings = [GCC<"thiscall">, Keyword<"__thiscall">,
+ Keyword<"_thiscall">];
+// let Subjects = [Function, ObjCMethod];
+ let Documentation = [Undocumented];
}
def Pascal : InheritableAttr {
let Spellings = [GNU<"pascal">, Keyword<"__pascal">, Keyword<"_pascal">];
+// let Subjects = [Function, ObjCMethod];
+ let Documentation = [Undocumented];
}
def TransparentUnion : InheritableAttr {
- let Spellings = [GNU<"transparent_union">, CXX11<"gnu", "transparent_union">];
+ 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>];
+ let Documentation = [Undocumented];
}
def ArcWeakrefUnavailable : InheritableAttr {
let Spellings = [GNU<"objc_arc_weak_reference_unavailable">];
- let Subjects = [ObjCInterface];
+ 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 = [ObjCInterface];
+ let Subjects = SubjectList<[ObjCInterface], ErrorDiag>;
+ let Documentation = [Undocumented];
}
def Unused : InheritableAttr {
- let Spellings = [GNU<"unused">, CXX11<"gnu", "unused">];
+ let Spellings = [GCC<"unused">];
+ let Subjects = SubjectList<[Var, ObjCIvar, Type, Label, Field, ObjCMethod,
+ FunctionLike], WarnDiag,
+ "ExpectedVariableFunctionOrLabel">;
+ let Documentation = [Undocumented];
}
def Used : InheritableAttr {
- let Spellings = [GNU<"used">, CXX11<"gnu", "used">];
+ let Spellings = [GCC<"used">];
+ let Documentation = [Undocumented];
}
def Uuid : InheritableAttr {
- let Spellings = [GNU<"uuid">];
+ let Spellings = [Declspec<"uuid">];
let Args = [StringArgument<"Guid">];
- let Subjects = [CXXRecord];
+// let Subjects = SubjectList<[CXXRecord]>;
+ let LangOpts = [MicrosoftExt, Borland];
+ let Documentation = [Undocumented];
}
def VectorSize : TypeAttr {
- let Spellings = [GNU<"vector_size">, CXX11<"gnu", "vector_size">];
+ 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 = [GNU<"visibility">, CXX11<"gnu", "visibility">];
+ let Spellings = [GCC<"visibility">];
let Args = [EnumArgument<"Visibility", "VisibilityType",
["default", "hidden", "internal", "protected"],
["Default", "Hidden", "Hidden", "Protected"]>];
+ let Documentation = [Undocumented];
}
def TypeVisibility : InheritableAttr {
@@ -774,80 +1223,227 @@ def TypeVisibility : InheritableAttr {
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 = [CXXRecord];
+ let Subjects = SubjectList<[CXXRecord], ErrorDiag>;
+ let Documentation = [Undocumented];
}
def WarnUnused : InheritableAttr {
let Spellings = [GNU<"warn_unused">];
- let Subjects = [Record];
+ let Subjects = SubjectList<[Record]>;
+ let Documentation = [Undocumented];
}
def WarnUnusedResult : InheritableAttr {
- let Spellings = [GNU<"warn_unused_result">,
- CXX11<"clang", "warn_unused_result">,
- CXX11<"gnu", "warn_unused_result">];
+ 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 = [GNU<"weak">, CXX11<"gnu", "weak">];
+ 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 = [GNU<"weakref">, CXX11<"gnu", "weakref">];
+ 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 {
- let Spellings = [];
+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];
}
// Attribute to disable AddressSanitizer (or equivalent) checks.
def NoSanitizeAddress : InheritableAttr {
- let Spellings = [GNU<"no_address_safety_analysis">,
- GNU<"no_sanitize_address">,
- CXX11<"gnu", "no_address_safety_analysis">,
- CXX11<"gnu", "no_sanitize_address">];
+ let Spellings = [GCC<"no_address_safety_analysis">,
+ GCC<"no_sanitize_address">];
+ let Subjects = SubjectList<[Function], ErrorDiag>;
+ let Documentation = [NoSanitizeAddressDocs];
}
// Attribute to disable ThreadSanitizer checks.
def NoSanitizeThread : InheritableAttr {
let Spellings = [GNU<"no_sanitize_thread">];
+ let Subjects = SubjectList<[Function], ErrorDiag>;
+ let Documentation = [NoSanitizeThreadDocs];
}
// Attribute to disable MemorySanitizer checks.
def NoSanitizeMemory : InheritableAttr {
let Spellings = [GNU<"no_sanitize_memory">];
+ let Subjects = SubjectList<[Function], ErrorDiag>;
+ let Documentation = [NoSanitizeMemoryDocs];
}
// 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<[Struct, TypedefName], ErrorDiag,
+ "ExpectedStructOrTypedef">;
+ 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 {
@@ -855,6 +1451,11 @@ def GuardedBy : InheritableAttr {
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 {
@@ -862,6 +1463,11 @@ def PtGuardedBy : InheritableAttr {
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 {
@@ -869,6 +1475,11 @@ def AcquiredAfter : InheritableAttr {
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 {
@@ -876,20 +1487,11 @@ def AcquiredBefore : InheritableAttr {
let Args = [VariadicExprArgument<"Args">];
let LateParsed = 1;
let TemplateDependent = 1;
-}
-
-def ExclusiveLockFunction : InheritableAttr {
- let Spellings = [GNU<"exclusive_lock_function">];
- let Args = [VariadicExprArgument<"Args">];
- let LateParsed = 1;
- let TemplateDependent = 1;
-}
-
-def SharedLockFunction : InheritableAttr {
- let Spellings = [GNU<"shared_lock_function">];
- 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 {
@@ -897,6 +1499,10 @@ def AssertExclusiveLock : InheritableAttr {
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 {
@@ -904,6 +1510,10 @@ def AssertSharedLock : InheritableAttr {
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
@@ -913,6 +1523,10 @@ def ExclusiveTrylockFunction : InheritableAttr {
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
@@ -922,13 +1536,10 @@ def SharedTrylockFunction : InheritableAttr {
let Args = [ExprArgument<"SuccessValue">, VariadicExprArgument<"Args">];
let LateParsed = 1;
let TemplateDependent = 1;
-}
-
-def UnlockFunction : InheritableAttr {
- let Spellings = [GNU<"unlock_function">];
- let Args = [VariadicExprArgument<"Args">];
- let LateParsed = 1;
- let TemplateDependent = 1;
+ let ParseArgumentsAsUnevaluated = 1;
+ let DuplicatesAllowedWhileMerging = 1;
+ let Subjects = SubjectList<[Function]>;
+ let Documentation = [Undocumented];
}
def LockReturned : InheritableAttr {
@@ -936,6 +1547,9 @@ def LockReturned : InheritableAttr {
let Args = [ExprArgument<"Arg">];
let LateParsed = 1;
let TemplateDependent = 1;
+ let ParseArgumentsAsUnevaluated = 1;
+ let Subjects = SubjectList<[Function]>;
+ let Documentation = [Undocumented];
}
def LocksExcluded : InheritableAttr {
@@ -943,70 +1557,78 @@ def LocksExcluded : InheritableAttr {
let Args = [VariadicExprArgument<"Args">];
let LateParsed = 1;
let TemplateDependent = 1;
-}
-
-def ExclusiveLocksRequired : InheritableAttr {
- let Spellings = [GNU<"exclusive_locks_required">];
- let Args = [VariadicExprArgument<"Args">];
- let LateParsed = 1;
- let TemplateDependent = 1;
-}
-
-def SharedLocksRequired : InheritableAttr {
- let Spellings = [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 Documentation = [Undocumented];
}
// C/C++ consumed attributes.
def Consumable : InheritableAttr {
let Spellings = [GNU<"consumable">];
- let Subjects = [CXXRecord];
+ 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 = [CXXMethod];
- let Args = [VariadicEnumArgument<"CallableState", "ConsumedState",
+ 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 = [ParmVar];
+ 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 = [Function, ParmVar];
+ 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 = [CXXMethod];
+ 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 = [CXXMethod];
+ 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.
@@ -1018,8 +1640,8 @@ def ArgumentWithTypeTag : InheritableAttr {
UnsignedArgument<"ArgumentIdx">,
UnsignedArgument<"TypeTagIdx">,
BoolArgument<"IsPointer">];
- let Subjects = [Function];
let HasCustomParsing = 1;
+ let Documentation = [ArgumentWithTypeTagDocs, PointerWithTypeTagDocs];
}
def TypeTagForDatatype : InheritableAttr {
@@ -1028,8 +1650,9 @@ def TypeTagForDatatype : InheritableAttr {
TypeArgument<"MatchingCType">,
BoolArgument<"LayoutCompatible">,
BoolArgument<"MustBeNull">];
- let Subjects = [Var];
+// let Subjects = SubjectList<[Var], ErrorDiag>;
let HasCustomParsing = 1;
+ let Documentation = [TypeTagForDatatypeDocs];
}
// Microsoft-related attributes
@@ -1039,65 +1662,211 @@ def MsProperty : IgnoredAttr {
}
def MsStruct : InheritableAttr {
- let Spellings = [Declspec<"ms_struct">];
+ let Spellings = [GCC<"ms_struct">];
+ let Subjects = SubjectList<[Record]>;
+ let Documentation = [Undocumented];
}
-def DLLExport : InheritableAttr, TargetSpecificAttr {
- let Spellings = [Declspec<"dllexport">];
+def DLLExport : InheritableAttr, TargetSpecificAttr<TargetWindows> {
+ let Spellings = [Declspec<"dllexport">, GCC<"dllexport">];
+ let Subjects = SubjectList<[Function, Var, CXXRecord]>;
+ let Documentation = [Undocumented];
}
-def DLLImport : InheritableAttr, TargetSpecificAttr {
- let Spellings = [Declspec<"dllimport">];
-}
-
-def ForceInline : InheritableAttr {
- let Spellings = [Keyword<"__forceinline">];
+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 Win64 : InheritableAttr {
+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">];
-}
-
-class MSInheritanceAttr : InheritableAttr;
-
-def SingleInheritance : MSInheritanceAttr {
- let Spellings = [Keyword<"__single_inheritance">];
-}
+ 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;
-def MultipleInheritance : MSInheritanceAttr {
- let Spellings = [Keyword<"__multiple_inheritance">];
-}
+ let AdditionalMembers = [{
+ enum Mode {
+ Never,
+ ForVBaseOverride,
+ ForVFTable
+ };
-def VirtualInheritance : MSInheritanceAttr {
- let Spellings = [Keyword<"__virtual_inheritance">];
+ Mode getVtorDispMode() const { return Mode(vdm); }
+ }];
+ let Documentation = [Undocumented];
}
-// This attribute doesn't have any spellings, but we can apply it implicitly to
-// incomplete types that lack any of the other attributes.
-def UnspecifiedInheritance : MSInheritanceAttr {
- let Spellings = [];
+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 {
+ /// vectorize: vectorizes loop operations if 'value != 0'.
+ /// vectorize_width: vectorize loop operations with width 'value'.
+ /// interleave: interleave multiple loop iterations if 'value != 0'.
+ /// interleave_count: interleaves 'value' loop interations.
+ /// unroll: unroll loop if 'value != 0'.
+ /// unroll_count: unrolls loop 'value' times.
+
+ let Spellings = [Pragma<"clang", "loop">, Pragma<"", "unroll">];
+
+ /// 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"]>,
+ DefaultIntArgument<"Value", 1>];
+
+ let AdditionalMembers = [{
+ static StringRef 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.");
+ }
+
+ static StringRef getValueName(int Value) {
+ if (Value)
+ return "enable";
+ return "disable";
+ }
+
+ void printPrettyPragma(raw_ostream &OS, const PrintingPolicy &Policy) const {
+ unsigned SpellingIndex = getSpellingListIndex();
+ if (SpellingIndex == Pragma_unroll) {
+ // String "unroll" of "#pragma unroll" is already emitted as the
+ // pragma name.
+ if (option == UnrollCount)
+ printArgument(OS);
+ OS << "\n";
+ return;
+ }
+ assert(SpellingIndex == Pragma_clang_loop && "Unexpected spelling");
+ OS << getOptionName(option);
+ printArgument(OS);
+ OS << "\n";
+ }
+
+ // Prints the loop hint argument including the enclosing parentheses to OS.
+ void printArgument(raw_ostream &OS) const {
+ OS << "(";
+ if (option == VectorizeWidth || option == InterleaveCount ||
+ option == UnrollCount)
+ OS << value;
+ else if (value)
+ OS << "enable";
+ else
+ OS << "disable";
+ OS << ")";
+ }
+
+ // Return a string suitable for identifying this attribute in diagnostics.
+ std::string getDiagnosticName() const {
+ std::string DiagnosticName;
+ llvm::raw_string_ostream OS(DiagnosticName);
+ unsigned SpellingIndex = getSpellingListIndex();
+ if (SpellingIndex == Pragma_unroll && option == Unroll)
+ OS << "#pragma unroll";
+ else if (SpellingIndex == Pragma_unroll && option == UnrollCount) {
+ OS << "#pragma unroll";
+ printArgument(OS);
+ } else {
+ assert(SpellingIndex == Pragma_clang_loop && "Unexpected spelling");
+ OS << getOptionName(option);
+ printArgument(OS);
+ }
+ return OS.str();
+ }
+ }];
+
+ let Documentation = [LoopHintDocs, UnrollHintDocs];
+}
diff --git a/include/clang/Basic/AttrDocs.td b/include/clang/Basic/AttrDocs.td
new file mode 100644
index 000000000000..e6d6a33d3b5d
--- /dev/null
+++ b/include/clang/Basic/AttrDocs.td
@@ -0,0 +1,1105 @@
+//==--- 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. Documentation for the Visual C++ attribute is available on MSDN_.
+
+.. _MSDN: 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 EnableIfDocs : Documentation {
+ let Category = DocCatFunction;
+ let Content = [{
+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 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 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.
+
+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 PcsDocs : Documentation {
+ let Category = DocCatFunction;
+ let Content = [{
+On ARM targets, this can attribute can be used to select calling conventions,
+similar to ``stdcall`` on x86. Valid parameter values are "aapcs" and
+"aapcs-vfp".
+ }];
+}
+
+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 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 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 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 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 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`` attribute.
+ }];
+}
+
+def LoopHintDocs : Documentation {
+ let Category = DocCatStmt;
+ 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 Content = [{
+Loop unrolling optimization hints can be specified with ``#pragma unroll``. 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:
+
+.. 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 (...) {
+ ...
+ }
+
+``#pragma unroll`` and ``#pragma unroll _value_`` have identical semantics to
+``#pragma clang loop unroll(enable)`` and ``#pragma clang loop
+unroll_count(_value_)`` respectively. See `language extensions
+<http://clang.llvm.org/docs/LanguageExtensions.html#extensions-for-loop-hint-optimizations>`_
+for further details including limitations of the unroll hints.
+ }];
+}
+
diff --git a/include/clang/Basic/AttrKinds.h b/include/clang/Basic/AttrKinds.h
index 7c4e2c75f04d..150a30e73d3f 100644
--- a/include/clang/Basic/AttrKinds.h
+++ b/include/clang/Basic/AttrKinds.h
@@ -24,7 +24,6 @@ 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,
-#define LAST_MS_INHERITANCE_ATTR(X) X, LAST_MS_INHERITANCE = X,
#include "clang/Basic/AttrList.inc"
NUM_ATTRS
};
diff --git a/include/clang/Basic/Attributes.h b/include/clang/Basic/Attributes.h
new file mode 100644
index 000000000000..5783b3bff510
--- /dev/null
+++ b/include/clang/Basic/Attributes.h
@@ -0,0 +1,41 @@
+//===--- 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 "llvm/ADT/Triple.h"
+#include "clang/Basic/LangOptions.h"
+
+namespace clang {
+
+class IdentifierInfo;
+
+enum class AttrSyntax {
+ /// Is the attribute identifier generally known for any syntax?
+ Generic,
+ /// 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 true if we recognize and implement the attribute specified by
+/// the given information.
+bool hasAttribute(AttrSyntax Syntax, const IdentifierInfo *Scope,
+ const IdentifierInfo *Attr, const llvm::Triple &T,
+ const LangOptions &LangOpts);
+
+} // end namespace clang
+
+#endif // LLVM_CLANG_BASIC_ATTRIBUTES_H
diff --git a/include/clang/Basic/Builtins.def b/include/clang/Basic/Builtins.def
index 55c6ed7deead..e705382e11ca 100644
--- a/include/clang/Basic/Builtins.def
+++ b/include/clang/Basic/Builtins.def
@@ -50,6 +50,7 @@
// 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.
@@ -72,7 +73,7 @@
// 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 compiter-rt or libgcc.
+// '__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
@@ -444,6 +445,7 @@ 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")
@@ -677,8 +679,16 @@ 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(__noop, "v.", "n", ALL_MS_LANGUAGES)
+LANGBUILTIN(__noop, "i.", "n", ALL_MS_LANGUAGES)
LANGBUILTIN(__debugbreak, "v", "n", ALL_MS_LANGUAGES)
+LANGBUILTIN(__va_start, "vc**.", "nt", ALL_MS_LANGUAGES)
+LANGBUILTIN(_InterlockedCompareExchange, "LiLiD*LiLi", "n", ALL_MS_LANGUAGES)
+LANGBUILTIN(_InterlockedCompareExchangePointer, "v*v*D*v*v*", "n", ALL_MS_LANGUAGES)
+LANGBUILTIN(_InterlockedIncrement, "LiLiD*", "n", ALL_MS_LANGUAGES)
+LANGBUILTIN(_InterlockedDecrement, "LiLiD*", "n", ALL_MS_LANGUAGES)
+LANGBUILTIN(_InterlockedExchangeAdd, "LiLiD*Li", "n", ALL_MS_LANGUAGES)
+LANGBUILTIN(_InterlockedExchangePointer, "v*v*D*v*", "n", ALL_MS_LANGUAGES)
+LANGBUILTIN(_InterlockedExchange, "LiLiD*Li", "n", ALL_MS_LANGUAGES)
// C99 library functions
// C99 stdlib.h
@@ -726,11 +736,16 @@ 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)
@@ -749,18 +764,16 @@ 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_GNU_LANGUAGES)
+LIBBUILTIN(vfork, "p", "fj", "unistd.h", ALL_LANGUAGES)
// POSIX setjmp.h
-// In some systems setjmp is a macro that expands to _setjmp. We undefine
-// it here to avoid having two identical LIBBUILTIN entries.
-LIBBUILTIN(_setjmp, "iJ", "fj", "setjmp.h", ALL_GNU_LANGUAGES)
-LIBBUILTIN(__sigsetjmp, "iSJi", "fj", "setjmp.h", ALL_GNU_LANGUAGES)
-LIBBUILTIN(sigsetjmp, "iSJi", "fj", "setjmp.h", ALL_GNU_LANGUAGES)
-LIBBUILTIN(setjmp_syscall, "iJ", "fj", "setjmp.h", ALL_GNU_LANGUAGES)
-LIBBUILTIN(savectx, "iJ", "fj", "setjmp.h", ALL_GNU_LANGUAGES)
-LIBBUILTIN(qsetjmp, "iJ", "fj", "setjmp.h", ALL_GNU_LANGUAGES)
-LIBBUILTIN(getcontext, "iK*", "fj", "setjmp.h", ALL_GNU_LANGUAGES)
+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)
@@ -1137,6 +1150,21 @@ 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)
@@ -1179,6 +1207,8 @@ 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")
#undef BUILTIN
#undef LIBBUILTIN
diff --git a/include/clang/Basic/Builtins.h b/include/clang/Basic/Builtins.h
index 9756f21a1c48..f9d30e40560a 100644
--- a/include/clang/Basic/Builtins.h
+++ b/include/clang/Basic/Builtins.h
@@ -94,53 +94,53 @@ public:
/// \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') != 0;
+ 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') != 0;
+ 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') != 0;
+ 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') != 0;
+ 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') != 0;
+ 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') != 0;
+ 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') != 0;
+ 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') != 0;
+ 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') != 0;
+ return strchr(GetRecord(ID).Attributes, 't') != nullptr;
}
/// \brief Completely forget that the given ID was ever considered a builtin,
@@ -168,7 +168,7 @@ public:
///
/// Such functions can be const when the MathErrno lang option is disabled.
bool isConstWithoutErrno(unsigned ID) const {
- return strchr(GetRecord(ID).Attributes, 'e') != 0;
+ return strchr(GetRecord(ID).Attributes, 'e') != nullptr;
}
private:
@@ -177,6 +177,10 @@ private:
/// \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;
};
}
diff --git a/include/clang/Basic/BuiltinsAArch64.def b/include/clang/Basic/BuiltinsAArch64.def
index aafd202aae11..695ecf9da5f8 100644
--- a/include/clang/Basic/BuiltinsAArch64.def
+++ b/include/clang/Basic/BuiltinsAArch64.def
@@ -1,4 +1,4 @@
-//===-- BuiltinsAArch64.def - AArch64 Builtin function database -*- C++ -*-===//
+//==- BuiltinsAArch64.def - AArch64 Builtin function database ----*- C++ -*-==//
//
// The LLVM Compiler Infrastructure
//
@@ -16,10 +16,38 @@
// In libgcc
BUILTIN(__clear_cache, "vv*v*", "i")
-// NEON
-#define GET_NEON_AARCH64_BUILTINS
-#include "clang/Basic/arm_neon.inc"
-#undef GET_NEON_AARCH64_BUILTINS
-#undef GET_NEON_BUILTINS
+
+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")
#undef BUILTIN
diff --git a/include/clang/Basic/BuiltinsARM.def b/include/clang/Basic/BuiltinsARM.def
index 21bb892a8b9b..2e5eac694fc2 100644
--- a/include/clang/Basic/BuiltinsARM.def
+++ b/include/clang/Basic/BuiltinsARM.def
@@ -14,6 +14,10 @@
// 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*", "")
@@ -24,12 +28,17 @@ 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
@@ -59,15 +68,33 @@ 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", "")
// Data barrier
BUILTIN(__builtin_arm_dmb, "vUi", "nc")
BUILTIN(__builtin_arm_dsb, "vUi", "nc")
+BUILTIN(__builtin_arm_isb, "vUi", "nc")
+
+// MSVC
+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)
-// NEON
-#define GET_NEON_BUILTINS
-#include "clang/Basic/arm_neon.inc"
-#undef GET_NEON_BUILTINS
+LANGBUILTIN(__dmb, "vUi", "nc", ALL_MS_LANGUAGES)
+LANGBUILTIN(__dsb, "vUi", "nc", ALL_MS_LANGUAGES)
+LANGBUILTIN(__isb, "vUi", "nc", ALL_MS_LANGUAGES)
+LANGBUILTIN(__ldrexd, "WiCDWi*", "", ALL_MS_LANGUAGES)
+LANGBUILTIN(_MoveFromCoprocessor, "UiUiUiUiUiUi", "", ALL_MS_LANGUAGES)
+LANGBUILTIN(_MoveFromCoprocessor2, "UiUiUiUiUiUi", "", ALL_MS_LANGUAGES)
+LANGBUILTIN(_MoveToCoprocessor, "vUiUiUiUiUiUi", "", ALL_MS_LANGUAGES)
+LANGBUILTIN(_MoveToCoprocessor2, "vUiUiUiUiUiUi", "", ALL_MS_LANGUAGES)
#undef BUILTIN
+#undef LANGBUILTIN
diff --git a/include/clang/Basic/BuiltinsMips.def b/include/clang/Basic/BuiltinsMips.def
index e435d52ed4f9..2d217f736498 100644
--- a/include/clang/Basic/BuiltinsMips.def
+++ b/include/clang/Basic/BuiltinsMips.def
@@ -783,15 +783,15 @@ 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, "V16cV16cUi", "nc")
-BUILTIN(__builtin_msa_sld_h, "V8sV8sUi", "nc")
-BUILTIN(__builtin_msa_sld_w, "V4iV4iUi", "nc")
-BUILTIN(__builtin_msa_sld_d, "V2LLiV2LLiUi", "nc")
-
-BUILTIN(__builtin_msa_sldi_b, "V16cV16cIUi", "nc")
-BUILTIN(__builtin_msa_sldi_h, "V8sV8sIUi", "nc")
-BUILTIN(__builtin_msa_sldi_w, "V4iV4iIUi", "nc")
-BUILTIN(__builtin_msa_sldi_d, "V2LLiV2LLiIUi", "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")
diff --git a/include/clang/Basic/BuiltinsNEON.def b/include/clang/Basic/BuiltinsNEON.def
new file mode 100644
index 000000000000..7800ae69c4c9
--- /dev/null
+++ b/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/include/clang/Basic/BuiltinsR600.def b/include/clang/Basic/BuiltinsR600.def
new file mode 100644
index 000000000000..49135ccb056d
--- /dev/null
+++ b/include/clang/Basic/BuiltinsR600.def
@@ -0,0 +1,32 @@
+//==- BuiltinsR600.def - R600 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, "dddd", "nc")
+BUILTIN(__builtin_amdgpu_div_fmasf, "ffff", "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")
+
+#undef BUILTIN
diff --git a/include/clang/Basic/BuiltinsX86.def b/include/clang/Basic/BuiltinsX86.def
index 51397fa45df6..1f377a8ab1de 100644
--- a/include/clang/Basic/BuiltinsX86.def
+++ b/include/clang/Basic/BuiltinsX86.def
@@ -59,6 +59,7 @@ BUILTIN(__builtin_ia32_pswapdsi, "V2iV2i", "nc")
// All MMX instructions will be generated via builtins. Any MMX vector
// types (<1 x i64>, <2 x i32>, etc.) that aren't used by these builtins will be
// expanded by the back-end.
+BUILTIN(_mm_prefetch, "vcC*i", "nc")
BUILTIN(__builtin_ia32_emms, "v", "")
BUILTIN(__builtin_ia32_paddb, "V8cV8cV8c", "")
BUILTIN(__builtin_ia32_paddw, "V4sV4sV4s", "")
@@ -452,9 +453,6 @@ BUILTIN(__builtin_ia32_movmskpd256, "iV4d", "")
BUILTIN(__builtin_ia32_movmskps256, "iV8f", "")
BUILTIN(__builtin_ia32_vzeroall, "v", "")
BUILTIN(__builtin_ia32_vzeroupper, "v", "")
-BUILTIN(__builtin_ia32_vbroadcastss, "V4ffC*", "")
-BUILTIN(__builtin_ia32_vbroadcastsd256, "V4ddC*", "")
-BUILTIN(__builtin_ia32_vbroadcastss256, "V8ffC*", "")
BUILTIN(__builtin_ia32_vbroadcastf128_pd256, "V4dV2dC*", "")
BUILTIN(__builtin_ia32_vbroadcastf128_ps256, "V8fV4fC*", "")
BUILTIN(__builtin_ia32_storeupd256, "vd*V4d", "")
@@ -759,5 +757,8 @@ BUILTIN(__builtin_ia32_xbegin, "i", "")
BUILTIN(__builtin_ia32_xend, "v", "")
BUILTIN(__builtin_ia32_xabort, "vIc", "")
BUILTIN(__builtin_ia32_xtest, "i", "")
+BUILTIN(__builtin_ia32_rdpmc, "ULLii", "")
+BUILTIN(__builtin_ia32_rdtsc, "ULLi", "")
+BUILTIN(__builtin_ia32_rdtscp, "ULLiUi*", "")
#undef BUILTIN
diff --git a/include/clang/Basic/CMakeLists.txt b/include/clang/Basic/CMakeLists.txt
index 274b94da8eda..e4929b5b52b9 100644
--- a/include/clang/Basic/CMakeLists.txt
+++ b/include/clang/Basic/CMakeLists.txt
@@ -28,7 +28,14 @@ clang_tablegen(AttrList.inc -gen-clang-attr-list
SOURCE Attr.td
TARGET ClangAttrList)
+clang_tablegen(AttrHasAttributeImpl.inc -gen-clang-attr-has-attribute-impl
+ -I ${CMAKE_CURRENT_SOURCE_DIR}/../../
+ SOURCE Attr.td
+ TARGET ClangAttrHasAttributeImpl
+ )
+
# ARM NEON
clang_tablegen(arm_neon.inc -gen-arm-neon-sema
+ -I ${CMAKE_CURRENT_SOURCE_DIR}/../../
SOURCE arm_neon.td
TARGET ClangARMNeon)
diff --git a/include/clang/Basic/Diagnostic.h b/include/clang/Basic/Diagnostic.h
index c057bdf63436..a7b2ba270d46 100644
--- a/include/clang/Basic/Diagnostic.h
+++ b/include/clang/Basic/Diagnostic.h
@@ -21,20 +21,23 @@
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/IntrusiveRefCntPtr.h"
-#include "llvm/Support/type_traits.h"
+#include "llvm/ADT/iterator_range.h"
#include <list>
#include <vector>
namespace clang {
- class DiagnosticConsumer;
+ class DeclContext;
class DiagnosticBuilder;
+ class DiagnosticConsumer;
+ class DiagnosticErrorTrap;
class DiagnosticOptions;
class IdentifierInfo;
- class DeclContext;
class LangOptions;
class Preprocessor;
- class DiagnosticErrorTrap;
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.
@@ -129,35 +132,34 @@ public:
/// the user. DiagnosticsEngine is tied to one translation unit and one
/// SourceManager.
class DiagnosticsEngine : public RefCountedBase<DiagnosticsEngine> {
+ DiagnosticsEngine(const DiagnosticsEngine &) LLVM_DELETED_FUNCTION;
+ void operator=(const DiagnosticsEngine &) LLVM_DELETED_FUNCTION;
+
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
};
- /// \brief How do we handle otherwise-unmapped extension?
- ///
- /// This is controlled by -pedantic and -pedantic-errors.
- enum ExtensionHandling {
- Ext_Ignore, Ext_Warn, Ext_Error
- };
-
enum ArgumentKind {
ak_std_string, ///< std::string
ak_c_string, ///< const char *
ak_sint, ///< int
ak_uint, ///< unsigned
+ ak_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_qualtype_pair, ///< pair<QualType, QualType>
+ ak_attr ///< Attr *
};
/// \brief Represents on argument value, which is a union discriminated
@@ -181,7 +183,7 @@ private:
// 0 -> no limit.
unsigned ConstexprBacktraceLimit; // Cap on depth of constexpr evaluation
// backtrace stack, 0 -> no limit.
- ExtensionHandling ExtBehavior; // Map extensions onto warnings or errors?
+ diag::Severity ExtBehavior; // Map extensions to warnings or errors?
IntrusiveRefCntPtr<DiagnosticIDs> Diags;
IntrusiveRefCntPtr<DiagnosticOptions> DiagOpts;
DiagnosticConsumer *Client;
@@ -191,7 +193,7 @@ private:
/// \brief Mapping information for diagnostics.
///
/// Mapping info is packed into four bits per diagnostic. The low three
- /// bits are the mapping (an instance of diag::Mapping), or zero if unset.
+ /// 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.
@@ -200,19 +202,18 @@ private:
/// the state so that we know what is the diagnostic state at any given
/// source location.
class DiagState {
- llvm::DenseMap<unsigned, DiagnosticMappingInfo> DiagMap;
+ llvm::DenseMap<unsigned, DiagnosticMapping> DiagMap;
public:
- typedef llvm::DenseMap<unsigned, DiagnosticMappingInfo>::iterator
- iterator;
- typedef llvm::DenseMap<unsigned, DiagnosticMappingInfo>::const_iterator
- const_iterator;
+ typedef llvm::DenseMap<unsigned, DiagnosticMapping>::iterator iterator;
+ typedef llvm::DenseMap<unsigned, DiagnosticMapping>::const_iterator
+ const_iterator;
- void setMappingInfo(diag::kind Diag, DiagnosticMappingInfo Info) {
+ void setMapping(diag::kind Diag, DiagnosticMapping Info) {
DiagMap[Diag] = Info;
}
- DiagnosticMappingInfo &getOrAddMappingInfo(diag::kind Diag);
+ DiagnosticMapping &getOrAddMapping(diag::kind Diag);
const_iterator begin() const { return DiagMap.begin(); }
const_iterator end() const { return DiagMap.end(); }
@@ -308,17 +309,15 @@ private:
///
/// This takes the modifiers and argument that was present in the diagnostic.
///
- /// The PrevArgs array (whose length is NumPrevArgs) indicates the previous
- /// arguments formatted for this diagnostic. Implementations of this function
- /// can use this information to avoid redundancy across arguments.
+ /// 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,
- const char *Modifier, unsigned ModifierLen,
- const char *Argument, unsigned ArgumentLen,
- const ArgumentValue *PrevArgs,
- unsigned NumPrevArgs,
+ StringRef Modifier, StringRef Argument,
+ ArrayRef<ArgumentValue> PrevArgs,
SmallVectorImpl<char> &Output,
void *Cookie,
ArrayRef<intptr_t> QualTypeVals);
@@ -336,11 +335,18 @@ private:
/// \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 = 0,
+ DiagnosticConsumer *client = nullptr,
bool ShouldOwnClient = true);
~DiagnosticsEngine();
@@ -351,6 +357,14 @@ public:
/// \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; }
@@ -364,7 +378,7 @@ public:
return Client;
}
- bool hasSourceManager() const { return SourceMgr != 0; }
+ bool hasSourceManager() const { return SourceMgr != nullptr; }
SourceManager &getSourceManager() const {
assert(SourceMgr && "SourceManager not set!");
return *SourceMgr;
@@ -501,10 +515,8 @@ public:
/// mapped onto ignore/warning/error.
///
/// This corresponds to the GCC -pedantic and -pedantic-errors option.
- void setExtensionHandlingBehavior(ExtensionHandling H) {
- ExtBehavior = H;
- }
- ExtensionHandling getExtensionHandlingBehavior() const { return ExtBehavior; }
+ void setExtensionHandlingBehavior(diag::Severity H) { ExtBehavior = H; }
+ diag::Severity getExtensionHandlingBehavior() const { return ExtBehavior; }
/// \brief Counter bumped when an __extension__ block is/ encountered.
///
@@ -522,8 +534,7 @@ public:
///
/// \param Loc The source location that this change of diagnostic state should
/// take affect. It can be null if we are setting the latest state.
- void setDiagnosticMapping(diag::kind Diag, diag::Mapping Map,
- SourceLocation Loc);
+ 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.
@@ -531,15 +542,14 @@ public:
/// \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 setDiagnosticGroupMapping(StringRef Group, diag::Mapping Map,
- SourceLocation Loc = SourceLocation());
-
- /// \brief Set the warning-as-error flag for the given diagnostic.
- ///
- /// This function always only operates on the current diagnostic state.
- void setDiagnosticWarningAsError(diag::kind Diag, bool Enabled);
+ 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.
///
@@ -548,11 +558,6 @@ public:
/// \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.
- ///
- /// This function always only operates on the current diagnostic state.
- void setDiagnosticErrorAsFatal(diag::kind Diag, bool Enabled);
-
/// \brief Set the error-as-fatal flag for the given diagnostic group.
///
/// This function always only operates on the current diagnostic state.
@@ -560,12 +565,13 @@ public:
/// \returns True if the given group is unknown, false otherwise.
bool setDiagnosticGroupErrorAsFatal(StringRef Group, bool Enabled);
- /// \brief Add the specified mapping to all diagnostics.
+ /// \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 setMappingToAllDiagnostics(diag::Mapping Map,
- SourceLocation Loc = SourceLocation());
+ void setSeverityForAll(diag::Flavor Flavor, diag::Severity Map,
+ SourceLocation Loc = SourceLocation());
bool hasErrorOccurred() const { return ErrorOccurred; }
@@ -587,25 +593,29 @@ public:
this->NumWarnings = NumWarnings;
}
- /// \brief Return an ID for a diagnostic with the specified message and level.
+ /// \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.
- unsigned getCustomDiagID(Level L, StringRef Message) {
- return Diags->getCustomDiagID((DiagnosticIDs::Level)L, Message);
+ ///
+ /// \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,
- const char *Modifier, unsigned ModLen,
- const char *Argument, unsigned ArgLen,
- const ArgumentValue *PrevArgs, unsigned NumPrevArgs,
+ StringRef Modifier, StringRef Argument,
+ ArrayRef<ArgumentValue> PrevArgs,
SmallVectorImpl<char> &Output,
ArrayRef<intptr_t> QualTypeVals) const {
- ArgToStringFn(Kind, Val, Modifier, ModLen, Argument, ArgLen,
- PrevArgs, NumPrevArgs, Output, ArgToStringCookie,
- QualTypeVals);
+ ArgToStringFn(Kind, Val, Modifier, Argument, PrevArgs, Output,
+ ArgToStringCookie, QualTypeVals);
}
void SetArgToStringFn(ArgToStringFnTy Fn, void *Cookie) {
@@ -627,10 +637,27 @@ public:
// 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 {
@@ -680,6 +707,9 @@ public:
/// \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();
@@ -711,20 +741,10 @@ private:
/// diagnostic with more than that almost certainly has to be simplified
/// anyway.
MaxArguments = 10,
-
- /// \brief The maximum number of ranges we can hold.
- MaxRanges = 10,
-
- /// \brief The maximum number of ranges we can hold.
- MaxFixItHints = 10
};
/// \brief The number of entries in Arguments.
signed char NumDiagArgs;
- /// \brief The number of ranges in the DiagRanges array.
- unsigned char NumDiagRanges;
- /// \brief The number of hints in the DiagFixItHints array.
- unsigned char NumDiagFixItHints;
/// \brief Specifies whether an argument is in DiagArgumentsStr or
/// in DiagArguments.
@@ -747,25 +767,25 @@ private:
intptr_t DiagArgumentsVal[MaxArguments];
/// \brief The list of ranges added to this diagnostic.
- CharSourceRange DiagRanges[MaxRanges];
+ SmallVector<CharSourceRange, 8> DiagRanges;
/// \brief If valid, provides a hint with some code to insert, remove,
/// or modify at a particular position.
- FixItHint DiagFixItHints[MaxFixItHints];
+ SmallVector<FixItHint, 8> DiagFixItHints;
- DiagnosticMappingInfo makeMappingInfo(diag::Mapping Map, SourceLocation L) {
+ DiagnosticMapping makeUserMapping(diag::Severity Map, SourceLocation L) {
bool isPragma = L.isValid();
- DiagnosticMappingInfo MappingInfo = DiagnosticMappingInfo::Make(
- Map, /*IsUser=*/true, isPragma);
+ 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) {
- MappingInfo.setNoWarningAsError(true);
- MappingInfo.setNoErrorAsFatal(true);
+ Mapping.setNoWarningAsError(true);
+ Mapping.setNoErrorAsFatal(true);
}
- return MappingInfo;
+ return Mapping;
}
/// \brief Used to report a diagnostic that is finally fully formed.
@@ -848,7 +868,7 @@ public:
/// for example.
class DiagnosticBuilder {
mutable DiagnosticsEngine *DiagObj;
- mutable unsigned NumArgs, NumRanges, NumFixits;
+ mutable unsigned NumArgs;
/// \brief Status variable indicating if this diagnostic is still active.
///
@@ -863,15 +883,15 @@ class DiagnosticBuilder {
void operator=(const DiagnosticBuilder &) LLVM_DELETED_FUNCTION;
friend class DiagnosticsEngine;
-
+
DiagnosticBuilder()
- : DiagObj(0), NumArgs(0), NumRanges(0), NumFixits(0), IsActive(false),
- IsForceEmit(false) { }
+ : DiagObj(nullptr), NumArgs(0), IsActive(false), IsForceEmit(false) {}
explicit DiagnosticBuilder(DiagnosticsEngine *diagObj)
- : DiagObj(diagObj), NumArgs(0), NumRanges(0), NumFixits(0), IsActive(true),
- IsForceEmit(false) {
+ : DiagObj(diagObj), NumArgs(0), IsActive(true), IsForceEmit(false) {
assert(diagObj && "DiagnosticBuilder requires a valid DiagnosticsEngine!");
+ diagObj->DiagRanges.clear();
+ diagObj->DiagFixItHints.clear();
}
friend class PartialDiagnostic;
@@ -879,13 +899,11 @@ class DiagnosticBuilder {
protected:
void FlushCounts() {
DiagObj->NumDiagArgs = NumArgs;
- DiagObj->NumDiagRanges = NumRanges;
- DiagObj->NumDiagFixItHints = NumFixits;
}
/// \brief Clear out the current diagnostic.
void Clear() const {
- DiagObj = 0;
+ DiagObj = nullptr;
IsActive = false;
IsForceEmit = false;
}
@@ -927,8 +945,6 @@ public:
IsForceEmit = D.IsForceEmit;
D.Clear();
NumArgs = D.NumArgs;
- NumRanges = D.NumRanges;
- NumFixits = D.NumFixits;
}
/// \brief Retrieve an empty diagnostic builder.
@@ -974,27 +990,32 @@ public:
void AddSourceRange(const CharSourceRange &R) const {
assert(isActive() && "Clients must not add to cleared diagnostic!");
- assert(NumRanges < DiagnosticsEngine::MaxRanges &&
- "Too many arguments to diagnostic!");
- DiagObj->DiagRanges[NumRanges++] = R;
+ DiagObj->DiagRanges.push_back(R);
}
void AddFixItHint(const FixItHint &Hint) const {
assert(isActive() && "Clients must not add to cleared diagnostic!");
- assert(NumFixits < DiagnosticsEngine::MaxFixItHints &&
- "Too many arguments to diagnostic!");
- DiagObj->DiagFixItHints[NumFixits++] = Hint;
+ DiagObj->DiagFixItHints.push_back(Hint);
}
- bool hasMaxRanges() const {
- return NumRanges == DiagnosticsEngine::MaxRanges;
- }
+ void addFlagValue(StringRef V) const { DiagObj->FlagValue = V; }
+};
- bool hasMaxFixItHints() const {
- return NumFixits == DiagnosticsEngine::MaxFixItHints;
- }
+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);
@@ -1013,7 +1034,13 @@ inline const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB, int I) {
return DB;
}
-inline const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB,bool I) {
+// 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;
}
@@ -1025,6 +1052,12 @@ inline const DiagnosticBuilder &operator<<(const DiagnosticBuilder &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);
@@ -1037,14 +1070,14 @@ inline const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB,
// match.
template<typename T>
inline
-typename llvm::enable_if<llvm::is_same<T, DeclContext>,
- const DiagnosticBuilder &>::type
+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,
const SourceRange &R) {
DB.AddSourceRange(CharSourceRange::getTokenRange(R));
@@ -1052,11 +1085,18 @@ inline const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB,
}
inline const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB,
+ ArrayRef<SourceRange> Ranges) {
+ for (const 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) {
if (!Hint.isNull())
@@ -1065,12 +1105,14 @@ inline const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB,
}
inline DiagnosticBuilder DiagnosticsEngine::Report(SourceLocation Loc,
- unsigned DiagID){
+ 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);
}
@@ -1159,22 +1201,22 @@ public:
/// \brief Return the number of source ranges associated with this diagnostic.
unsigned getNumRanges() const {
- return DiagObj->NumDiagRanges;
+ return DiagObj->DiagRanges.size();
}
/// \pre Idx < getNumRanges()
const CharSourceRange &getRange(unsigned Idx) const {
- assert(Idx < DiagObj->NumDiagRanges && "Invalid diagnostic range index!");
+ 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 llvm::makeArrayRef(DiagObj->DiagRanges, DiagObj->NumDiagRanges);
+ return DiagObj->DiagRanges;
}
unsigned getNumFixItHints() const {
- return DiagObj->NumDiagFixItHints;
+ return DiagObj->DiagFixItHints.size();
}
const FixItHint &getFixItHint(unsigned Idx) const {
@@ -1182,8 +1224,8 @@ public:
return DiagObj->DiagFixItHints[Idx];
}
- const FixItHint *getFixItHints() const {
- return getNumFixItHints()? DiagObj->DiagFixItHints : 0;
+ ArrayRef<FixItHint> getFixItHints() const {
+ return DiagObj->DiagFixItHints;
}
/// \brief Format this diagnostic into a string, substituting the
@@ -1279,7 +1321,7 @@ public:
/// \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 = 0) {}
+ const Preprocessor *PP = nullptr) {}
/// \brief Callback to inform the diagnostic client that processing
/// of a source file has ended.
@@ -1312,7 +1354,7 @@ public:
class IgnoringDiagConsumer : public DiagnosticConsumer {
virtual void anchor();
void HandleDiagnostic(DiagnosticsEngine::Level DiagLevel,
- const Diagnostic &Info) {
+ const Diagnostic &Info) override {
// Just ignore it.
}
};
@@ -1328,11 +1370,11 @@ public:
virtual ~ForwardingDiagnosticConsumer();
- virtual void HandleDiagnostic(DiagnosticsEngine::Level DiagLevel,
- const Diagnostic &Info);
- virtual void clear();
+ void HandleDiagnostic(DiagnosticsEngine::Level DiagLevel,
+ const Diagnostic &Info) override;
+ void clear() override;
- virtual bool IncludeInDiagnosticCounts() const;
+ bool IncludeInDiagnosticCounts() const override;
};
// Struct used for sending info about how a type should be printed.
@@ -1351,6 +1393,13 @@ struct TemplateDiffTypes {
/// 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/include/clang/Basic/Diagnostic.td b/include/clang/Basic/Diagnostic.td
index 2616548bc009..48cbf09419b3 100644
--- a/include/clang/Basic/Diagnostic.td
+++ b/include/clang/Basic/Diagnostic.td
@@ -12,16 +12,20 @@
//
//===----------------------------------------------------------------------===//
-// Define the diagnostic mappings.
-class DiagMapping;
-def MAP_IGNORE : DiagMapping;
-def MAP_WARNING : DiagMapping;
-def MAP_ERROR : DiagMapping;
-def MAP_FATAL : DiagMapping;
+// Define the diagnostic 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;
@@ -57,7 +61,7 @@ include "DiagnosticGroups.td"
// All diagnostics emitted by the compiler are an indirect subclass of this.
-class Diagnostic<string text, DiagClass DC, DiagMapping defaultmapping> {
+class Diagnostic<string text, DiagClass DC, Severity defaultmapping> {
/// Component is specified by the file with a big let directive.
string Component = ?;
string Text = text;
@@ -65,8 +69,8 @@ class Diagnostic<string text, DiagClass DC, DiagMapping defaultmapping> {
SFINAEResponse SFINAE = SFINAE_Suppress;
bit AccessControl = 0;
bit WarningNoWerror = 0;
- bit WarningShowInSystemHeader = 0;
- DiagMapping DefaultMapping = defaultmapping;
+ bit ShowInSystemHeader = 0;
+ Severity DefaultSeverity = defaultmapping;
DiagGroup Group;
string CategoryName = "";
}
@@ -81,24 +85,33 @@ 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, MAP_ERROR>, SFINAEFailure;
-class Warning<string str> : Diagnostic<str, CLASS_WARNING, MAP_WARNING>;
-class Extension<string str> : Diagnostic<str, CLASS_EXTENSION, MAP_IGNORE>;
-class ExtWarn<string str> : Diagnostic<str, CLASS_EXTENSION, MAP_WARNING>;
-class Note<string str> : Diagnostic<str, CLASS_NOTE, MAP_FATAL/*ignored*/>;
+class 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 { DiagMapping DefaultMapping = MAP_IGNORE; }
-class DefaultWarn { DiagMapping DefaultMapping = MAP_WARNING; }
-class DefaultError { DiagMapping DefaultMapping = MAP_ERROR; }
-class DefaultFatal { DiagMapping DefaultMapping = MAP_FATAL; }
+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 DefaultWarnShowInSystemHeader {
- bit WarningShowInSystemHeader = 1;
-}
+class DefaultRemark { Severity DefaultSeverity = SEV_Remark; }
// Definitions for Diagnostics.
include "DiagnosticASTKinds.td"
diff --git a/include/clang/Basic/DiagnosticASTKinds.td b/include/clang/Basic/DiagnosticASTKinds.td
index 113e56490520..8d5a1c77233b 100644
--- a/include/clang/Basic/DiagnosticASTKinds.td
+++ b/include/clang/Basic/DiagnosticASTKinds.td
@@ -89,6 +89,9 @@ 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">;
@@ -138,6 +141,7 @@ 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 warn_integer_constant_overflow : Warning<
"overflow in expression; result is %0 with type %1">,
InGroup<DiagGroup<"integer-overflow">>;
diff --git a/include/clang/Basic/DiagnosticCategories.td b/include/clang/Basic/DiagnosticCategories.td
index a02fbdf93fc3..37b856976d52 100644
--- a/include/clang/Basic/DiagnosticCategories.td
+++ b/include/clang/Basic/DiagnosticCategories.td
@@ -8,3 +8,4 @@
//===----------------------------------------------------------------------===//
class CatInlineAsm : DiagCategory<"Inline Assembly Issue">;
+class CatBackend : DiagCategory<"Backend Issue">;
diff --git a/include/clang/Basic/DiagnosticCommentKinds.td b/include/clang/Basic/DiagnosticCommentKinds.td
index 49781fec9a9c..6dc8b27a2ac9 100644
--- a/include/clang/Basic/DiagnosticCommentKinds.td
+++ b/include/clang/Basic/DiagnosticCommentKinds.td
@@ -11,7 +11,7 @@ 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 he might expect.
+// 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">,
@@ -41,6 +41,10 @@ def warn_doc_html_start_end_mismatch : Warning<
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<
diff --git a/include/clang/Basic/DiagnosticCommonKinds.td b/include/clang/Basic/DiagnosticCommonKinds.td
index c54bafc07fe8..b3c77b8f5f36 100644
--- a/include/clang/Basic/DiagnosticCommonKinds.td
+++ b/include/clang/Basic/DiagnosticCommonKinds.td
@@ -30,7 +30,7 @@ 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_matching : Note<"to match this %0">;
def note_using : Note<"using">;
def note_possibility : Note<"one possibility">;
@@ -40,7 +40,6 @@ def note_also_found : Note<"also found">;
let CategoryName = "Lexical or Preprocessor Issue" in {
-def err_expected_colon : Error<"expected ':'">;
def err_expected_colon_after_setter_name : Error<
"method name referenced in property setter attribute "
"must end with ':'">;
@@ -60,6 +59,10 @@ def err_invalid_numeric_udl : Error<
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">,
@@ -101,8 +104,9 @@ def warn_cxx98_compat_longlong : Warning<
InGroup<CXX98CompatPedantic>, DefaultIgnore;
def err_integer_too_large : Error<
"integer constant is larger than the largest unsigned integer type">;
-def warn_integer_too_large_for_signed : Warning<
- "integer constant is larger than the largest signed integer type">;
+def ext_integer_too_large_for_signed : ExtWarn<
+ "integer constant is larger than the largest signed integer type">,
+ InGroup<DiagGroup<"implicitly-unsigned-literal">>;
// Sema && AST
def note_invalid_subexpr_in_const_expr : Note<
@@ -114,7 +118,6 @@ def err_target_unknown_triple : Error<
"unknown target triple '%0', please use -triple or -arch">;
def err_target_unknown_cpu : Error<"unknown target CPU '%0'">;
def err_target_unknown_abi : Error<"unknown target ABI '%0'">;
-def err_target_unknown_cxxabi : Error<"unknown C++ ABI '%0'">;
def err_target_unknown_fpmath : Error<"unknown FP unit '%0'">;
def err_target_unsupported_fpmath : Error<
"the '%0' unit is not supported with this instruction set">;
@@ -133,4 +136,14 @@ def err_unable_to_make_temp : Error<
// Modules
def err_module_file_conflict : Error<"module '%0' found in both '%1' and '%2'">;
+// 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">;
+
}
diff --git a/include/clang/Basic/DiagnosticDriverKinds.td b/include/clang/Basic/DiagnosticDriverKinds.td
index b48980778c46..cd26a6a4dd70 100644
--- a/include/clang/Basic/DiagnosticDriverKinds.td
+++ b/include/clang/Basic/DiagnosticDriverKinds.td
@@ -17,9 +17,13 @@ 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_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<
@@ -80,6 +84,9 @@ def err_drv_invalid_libcxx_deployment : Error<
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'">;
@@ -109,11 +116,14 @@ 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_unknown_toolchain : Error<
- "cannot recognize the type of the toolchain">;
+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 warn_O4_is_O3 : Warning<"-O4 is equivalent to -O3">, InGroup<Deprecated>;
-def warn_drv_optimization_value : Warning<"optimization level '%0' is unsupported; using '%1%2' instead">,
+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<InvalidCommandLineArgument>;
def warn_c_kext : Warning<
"ignoring -fapple-kext which is valid for C++ and Objective-C++ only">;
@@ -132,12 +142,8 @@ def warn_drv_unused_argument : Warning<
def warn_drv_empty_joined_argument : Warning<
"joined argument expects additional value: '%0'">,
InGroup<UnusedCommandLineArgument>;
-def warn_drv_unused_sanitizer : Warning<"'%0' is ignored in absence of '%1'">,
- InGroup<UnusedSanitizeArgument>;
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<
@@ -154,6 +160,8 @@ 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 note_drv_command_failed_diag_msg : Note<
"diagnostic msg: %0">;
@@ -164,4 +172,11 @@ 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>'">;
+
+def warn_drv_invoking_fallback : Warning<"falling back to %0">,
+ InGroup<Fallback>;
}
diff --git a/include/clang/Basic/DiagnosticFrontendKinds.td b/include/clang/Basic/DiagnosticFrontendKinds.td
index bcf3c41cdb64..ae704c49150b 100644
--- a/include/clang/Basic/DiagnosticFrontendKinds.td
+++ b/include/clang/Basic/DiagnosticFrontendKinds.td
@@ -7,6 +7,8 @@
//
//===----------------------------------------------------------------------===//
+class BackendInfo : CatBackend, ShowInSystemHeader;
+
let Component = "Frontend" in {
def err_fe_error_opening : Error<"error opening '%0': %1">;
@@ -14,13 +16,35 @@ 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;
-// Error generated by the backend.
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 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 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 err_fe_invalid_code_complete_file : Error<
"cannot locate code-completion file %0">, DefaultFatal;
@@ -77,6 +101,8 @@ 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">;
@@ -100,17 +126,8 @@ def err_relocatable_without_isysroot : Error<
"must specify system root with -isysroot when building a relocatable "
"PCH file">;
-def warn_unknown_warning_option : Warning<
- "unknown warning option '%0'">,
- InGroup<UnknownWarningOption>;
-def warn_unknown_negative_warning_option : Warning<
- "unknown warning option '%0'">,
- InGroup<UnknownWarningOption>;
-def warn_unknown_warning_option_suggest : Warning<
- "unknown warning option '%0'; did you mean '%1'?">,
- InGroup<UnknownWarningOption>;
-def warn_unknown_negative_warning_option_suggest : Warning<
- "unknown warning option '%0'; did you mean '%1'?">,
+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'">,
@@ -138,6 +155,10 @@ def warn_missing_submodule : Warning<"missing submodule '%0'">,
InGroup<IncompleteUmbrella>;
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_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 "
@@ -145,4 +166,11 @@ def warn_module_config_macro_undef : Warning<
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<DiagGroup<"module-build">>;
+
+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/include/clang/Basic/DiagnosticGroups.td b/include/clang/Basic/DiagnosticGroups.td
index b0d02164ebc4..58dee482b627 100644
--- a/include/clang/Basic/DiagnosticGroups.td
+++ b/include/clang/Basic/DiagnosticGroups.td
@@ -18,7 +18,7 @@ def Implicit : DiagGroup<"implicit", [
// Empty DiagGroups are recognized by clang but ignored.
def : DiagGroup<"abi">;
-def : DiagGroup<"address">;
+def AbsoluteValue : DiagGroup<"absolute-value">;
def AddressOfTemporary : DiagGroup<"address-of-temporary">;
def : DiagGroup<"aggregate-return">;
def GNUAlignofExpression : DiagGroup<"gnu-alignof-expression">;
@@ -37,14 +37,21 @@ def ConstantConversion :
def LiteralConversion : DiagGroup<"literal-conversion">;
def StringConversion : DiagGroup<"string-conversion">;
def SignConversion : DiagGroup<"sign-conversion">;
-def BoolConversion : DiagGroup<"bool-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 EnumTooLarge : DiagGroup<"enum-too-large">;
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">;
@@ -71,16 +78,17 @@ def CXX11CompatDeprecatedWritableStr :
DiagGroup<"c++11-compat-deprecated-writable-strings">;
def DeprecatedDeclarations : DiagGroup<"deprecated-declarations">;
+def UnavailableDeclarations : DiagGroup<"unavailable-declarations">;
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 are DeprecatedImplementations and DeprecatedWritableStr
-// not in this group?
+// FIXME: Why is DeprecatedImplementations not in this group?
def Deprecated : DiagGroup<"deprecated", [DeprecatedDeclarations,
DeprecatedIncrementBool,
- DeprecatedRegister]>,
+ DeprecatedRegister,
+ DeprecatedWritableStr]>,
DiagCategory<"Deprecations">;
def : DiagGroup<"disabled-optimization">;
@@ -113,6 +121,9 @@ def FormatZeroLength : DiagGroup<"format-zero-length">;
def CXXPre1yCompat : DiagGroup<"c++98-c++11-compat">;
def CXXPre1yCompatPedantic : DiagGroup<"c++98-c++11-compat-pedantic",
[CXXPre1yCompat]>;
+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">;
@@ -125,11 +136,13 @@ def CXX98Compat : DiagGroup<"c++98-compat",
[CXX98CompatBindToTemporaryCopy,
CXX98CompatLocalTypeTemplateArgs,
CXX98CompatUnnamedTypeTemplateArgs,
- CXXPre1yCompat]>;
+ CXXPre1yCompat,
+ CXXPre1zCompat]>;
// Warnings for C++11 features which are Extensions in C++98 mode.
def CXX98CompatPedantic : DiagGroup<"c++98-compat-pedantic",
[CXX98Compat,
- CXXPre1yCompatPedantic]>;
+ CXXPre1yCompatPedantic,
+ CXXPre1zCompatPedantic]>;
def CXX11Narrowing : DiagGroup<"c++11-narrowing">;
@@ -149,10 +162,16 @@ def CXX11Compat : DiagGroup<"c++11-compat",
[CXX11Narrowing,
CXX11CompatReservedUserDefinedLiteral,
CXX11CompatDeprecatedWritableStr,
- CXXPre1yCompat]>;
+ CXXPre1yCompat,
+ CXXPre1zCompat]>;
def : DiagGroup<"c++0x-compat", [CXX11Compat]>;
def CXX11CompatPedantic : DiagGroup<"c++11-compat-pedantic",
- [CXXPre1yCompatPedantic]>;
+ [CXXPre1yCompatPedantic,
+ CXXPre1zCompatPedantic]>;
+
+def CXX14Compat : DiagGroup<"c++14-compat", [CXXPre1zCompat]>;
+def CXX14CompatPedantic : DiagGroup<"c++14-compat-pedantic",
+ [CXXPre1zCompatPedantic]>;
def : DiagGroup<"effc++">;
def DivZero : DiagGroup<"division-by-zero">;
@@ -168,9 +187,11 @@ def OverloadedShiftOpParentheses: DiagGroup<"overloaded-shift-op-parentheses">;
def DanglingElse: DiagGroup<"dangling-else">;
def DanglingField : DiagGroup<"dangling-field">;
def DistributedObjectModifiers : DiagGroup<"distributed-object-modifiers">;
+def InfiniteRecursion : DiagGroup<"infinite-recursion">;
def GNUImaginaryConstant : DiagGroup<"gnu-imaginary-constant">;
def IgnoredQualifiers : DiagGroup<"ignored-qualifiers">;
def : DiagGroup<"import">;
+def IncompatibleMSStruct : DiagGroup<"incompatible-ms-struct">;
def IncompatiblePointerTypesDiscardsQualifiers
: DiagGroup<"incompatible-pointer-types-discards-qualifiers">;
def IncompatiblePointerTypes
@@ -178,6 +199,10 @@ def IncompatiblePointerTypes
[IncompatiblePointerTypesDiscardsQualifiers]>;
def IncompleteUmbrella : DiagGroup<"incomplete-umbrella">;
def IncompleteModule : DiagGroup<"incomplete-module", [IncompleteUmbrella]>;
+def NonModularIncludeInFrameworkModule
+ : DiagGroup<"non-modular-include-in-framework-module">;
+def NonModularIncludeInModule : DiagGroup<"non-modular-include-in-module",
+ [NonModularIncludeInFrameworkModule]>;
def InvalidNoreturn : DiagGroup<"invalid-noreturn">;
def InvalidSourceEncoding : DiagGroup<"invalid-source-encoding">;
def KNRPromotedParameter : DiagGroup<"knr-promoted-parameter">;
@@ -214,24 +239,28 @@ 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 : DiagGroup<"old-style-cast">;
+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">;
+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 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">;
@@ -242,8 +271,7 @@ def DeprecatedObjCIsaUsage : DiagGroup<"deprecated-objc-isa-usage">;
def Packed : DiagGroup<"packed">;
def Padded : DiagGroup<"padded">;
def PointerArith : DiagGroup<"pointer-arith">;
-def PoundWarning : DiagGroup<"#warnings">,
- DiagCategory<"#warning Directive">;
+def PoundWarning : DiagGroup<"#warnings">;
def PoundPragmaMessage : DiagGroup<"#pragma-messages">,
DiagCategory<"#pragma message Directive">;
def : DiagGroup<"pointer-to-int-cast">;
@@ -275,12 +303,19 @@ 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]>;
+ [TautologicalOutOfRangeCompare,
+ TautologicalPointerCompare,
+ TautologicalOverlapCompare,
+ TautologicalUndefinedCompare]>;
def HeaderHygiene : DiagGroup<"header-hygiene">;
def DuplicateDeclSpecifier : DiagGroup<"duplicate-decl-specifier">;
def CompareDistinctPointerType : DiagGroup<"compare-distinct-pointer-types">;
@@ -315,6 +350,7 @@ def : DiagGroup<"strict-prototypes">;
def StrictSelector : DiagGroup<"strict-selector-match">;
def MethodDuplicate : DiagGroup<"duplicate-method-match">;
def CoveredSwitchDefault : DiagGroup<"covered-switch-default">;
+def SwitchBool : DiagGroup<"switch-bool">;
def SwitchEnum : DiagGroup<"switch-enum">;
def Switch : DiagGroup<"switch">;
def ImplicitFallthroughPerFunction :
@@ -334,17 +370,19 @@ 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 UnknownAttributes : DiagGroup<"attributes">;
+def UnknownAttributes : DiagGroup<"unknown-attributes">;
def IgnoredAttributes : DiagGroup<"ignored-attributes">;
+def Attributes : DiagGroup<"attributes", [UnknownAttributes,
+ IgnoredAttributes]>;
def UnnamedTypeTemplateArgs : DiagGroup<"unnamed-type-template-args",
[CXX98CompatUnnamedTypeTemplateArgs]>;
def UnsupportedFriend : DiagGroup<"unsupported-friend">;
def UnusedArgument : DiagGroup<"unused-argument">;
-def UnusedSanitizeArgument : DiagGroup<"unused-sanitize-argument">;
-def UnusedCommandLineArgument : DiagGroup<"unused-command-line-argument",
- [UnusedSanitizeArgument]>;
+def UnusedCommandLineArgument : DiagGroup<"unused-command-line-argument">;
def InvalidCommandLineArgument : DiagGroup<"invalid-command-line-argument">;
def UnusedComparison : DiagGroup<"unused-comparison">;
def UnusedExceptionParameter : DiagGroup<"unused-exception-parameter">;
@@ -364,7 +402,6 @@ def UnusedVariable : DiagGroup<"unused-variable",
def UnusedPropertyIvar : DiagGroup<"unused-property-ivar">;
def UsedButMarkedUnused : DiagGroup<"used-but-marked-unused">;
def UserDefinedLiterals : DiagGroup<"user-defined-literals">;
-def ReadOnlySetterAttrs : DiagGroup<"readonly-setter-attrs">;
def Reorder : DiagGroup<"reorder">;
def UndeclaredSelector : DiagGroup<"undeclared-selector">;
def ImplicitAtomic : DiagGroup<"implicit-atomic-properties">;
@@ -385,6 +422,7 @@ 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">;
@@ -400,16 +438,48 @@ 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.
-def GCCWriteStrings : DiagGroup<"write-strings" , [DeprecatedWritableStr]>;
+//
+// 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
@@ -435,11 +505,13 @@ 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">;
@@ -461,7 +533,7 @@ def Format : DiagGroup<"format",
[FormatExtraArgs, FormatZeroLength, NonNull,
FormatSecurity, FormatY2K, FormatInvalidSpecifier]>,
DiagCategory<"Format String Issue">;
-def FormatNonLiteral : DiagGroup<"format-nonliteral", [FormatSecurity]>;
+def FormatNonLiteral : DiagGroup<"format-nonliteral">;
def Format2 : DiagGroup<"format=2",
[FormatNonLiteral, FormatSecurity, FormatY2K]>;
@@ -502,6 +574,7 @@ def Most : DiagGroup<"most", [
Unused,
VolatileRegisterVar,
ObjCMissingSuperCalls,
+ ObjCDesignatedInit,
OverloadedVirtual,
PrivateExtern,
SelTypeCast,
@@ -524,7 +597,7 @@ 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 : DiagGroup<"all", [Most, Parentheses, Switch]>;
+def : DiagGroup<"all", [Most, Parentheses, Switch, SwitchBool]>;
// Warnings enabled by -pedantic. This is magically filled in by TableGen.
def Pedantic : DiagGroup<"pedantic">;
@@ -555,6 +628,10 @@ def CXX11 : DiagGroup<"c++11-extensions", [CXX11ExtraSemi, CXX11LongLong]>;
// earlier C++ versions.
def CXX1y : DiagGroup<"c++1y-extensions">;
+// 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 DelegatingCtorCycles :
DiagGroup<"delegating-ctor-cycles">;
@@ -608,8 +685,6 @@ def ObjCLiteralComparison : DiagGroup<"objc-literal-compare", [
ObjCStringComparison
]>;
-def ObjCLiteralMissingAtSign : DiagGroup<"objc-literal-missing-atsign">;
-
// Inline ASM warnings.
def ASMOperandWidths : DiagGroup<"asm-operand-widths">;
def ASM : DiagGroup<"asm", [
@@ -618,3 +693,23 @@ def ASM : DiagGroup<"asm", [
// 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">;
+
+// 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">;
diff --git a/include/clang/Basic/DiagnosticIDs.h b/include/clang/Basic/DiagnosticIDs.h
index 56e30fbda7b0..bfb0f0d1ee5d 100644
--- a/include/clang/Basic/DiagnosticIDs.h
+++ b/include/clang/Basic/DiagnosticIDs.h
@@ -56,49 +56,53 @@ namespace clang {
};
/// Enum values that allow the client to map NOTEs, WARNINGs, and EXTENSIONs
- /// to either MAP_IGNORE (nothing), MAP_WARNING (emit a warning), MAP_ERROR
- /// (emit as an error). It allows clients to map errors to
- /// MAP_ERROR/MAP_DEFAULT or MAP_FATAL (stop emitting diagnostics after this
- /// one).
- enum Mapping {
+ /// 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".
- MAP_IGNORE = 1, ///< Map this diagnostic to nothing, ignore it.
- MAP_WARNING = 2, ///< Map this diagnostic to a warning.
- MAP_ERROR = 3, ///< Map this diagnostic to an error.
- MAP_FATAL = 4 ///< Map this diagnostic to a fatal error.
+ 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 DiagnosticMappingInfo {
- unsigned Mapping : 3;
+class DiagnosticMapping {
+ unsigned Severity : 3;
unsigned IsUser : 1;
unsigned IsPragma : 1;
- unsigned HasShowInSystemHeader : 1;
unsigned HasNoWarningAsError : 1;
unsigned HasNoErrorAsFatal : 1;
public:
- static DiagnosticMappingInfo Make(diag::Mapping Mapping, bool IsUser,
- bool IsPragma) {
- DiagnosticMappingInfo Result;
- Result.Mapping = Mapping;
+ static DiagnosticMapping Make(diag::Severity Severity, bool IsUser,
+ bool IsPragma) {
+ DiagnosticMapping Result;
+ Result.Severity = (unsigned)Severity;
Result.IsUser = IsUser;
Result.IsPragma = IsPragma;
- Result.HasShowInSystemHeader = 0;
Result.HasNoWarningAsError = 0;
Result.HasNoErrorAsFatal = 0;
return Result;
}
- diag::Mapping getMapping() const { return diag::Mapping(Mapping); }
- void setMapping(diag::Mapping Value) { Mapping = Value; }
+ 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 hasShowInSystemHeader() const { return HasShowInSystemHeader; }
- void setShowInSystemHeader(bool Value) { HasShowInSystemHeader = Value; }
-
bool hasNoWarningAsError() const { return HasNoWarningAsError; }
void setNoWarningAsError(bool Value) { HasNoWarningAsError = Value; }
@@ -113,7 +117,7 @@ class DiagnosticIDs : public RefCountedBase<DiagnosticIDs> {
public:
/// \brief The level of the diagnostic, after it has been through mapping.
enum Level {
- Ignored, Note, Warning, Error, Fatal
+ Ignored, Note, Remark, Warning, Error, Fatal
};
private:
@@ -124,11 +128,16 @@ public:
DiagnosticIDs();
~DiagnosticIDs();
- /// \brief Return an ID for a diagnostic with the specified message and level.
+ /// \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.
- unsigned getCustomDiagID(Level L, StringRef Message);
+
+ // 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.
@@ -228,15 +237,16 @@ public:
///
/// \param[out] Diags - On return, the diagnostics in the group.
/// \returns \c true if the given group is unknown, \c false otherwise.
- bool getDiagnosticsInGroup(StringRef Group,
+ bool getDiagnosticsInGroup(diag::Flavor Flavor, StringRef Group,
SmallVectorImpl<diag::kind> &Diags) const;
/// \brief Get the set of all diagnostic IDs.
- void getAllDiagnostics(SmallVectorImpl<diag::kind> &Diags) const;
+ void getAllDiagnostics(diag::Flavor Flavor,
+ SmallVectorImpl<diag::kind> &Diags) const;
- /// \brief Get the warning option with the closest edit distance to the given
- /// group name.
- static StringRef getNearestWarningOption(StringRef Group);
+ /// \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
@@ -247,15 +257,13 @@ private:
///
/// \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;
-
- /// \brief An internal implementation helper used when \p DiagClass is
- /// already known.
- DiagnosticIDs::Level getDiagnosticLevel(unsigned DiagID,
- unsigned DiagClass,
- SourceLocation Loc,
- const DiagnosticsEngine &Diag) const;
+ 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.
///
diff --git a/include/clang/Basic/DiagnosticLexKinds.td b/include/clang/Basic/DiagnosticLexKinds.td
index 871f5f65447d..86def878834f 100644
--- a/include/clang/Basic/DiagnosticLexKinds.td
+++ b/include/clang/Basic/DiagnosticLexKinds.td
@@ -151,7 +151,8 @@ def warn_ucn_not_valid_in_c89_literal : ExtWarn<
// Literal
def ext_nonstandard_escape : Extension<
"use of non-standard escape character '\\%0'">;
-def ext_unknown_escape : ExtWarn<"unknown escape sequence '\\%0'">;
+def ext_unknown_escape : ExtWarn<"unknown escape sequence '\\%0'">,
+ InGroup<DiagGroup<"unknown-escape-sequence">>;
def err_invalid_decimal_digit : Error<"invalid digit '%0' in decimal constant">;
def err_invalid_binary_digit : Error<"invalid digit '%0' in binary constant">;
def err_invalid_octal_digit : Error<"invalid digit '%0' in octal constant">;
@@ -244,9 +245,9 @@ def err_invalid_pth_file : Error<
// Preprocessor Diagnostics
//===----------------------------------------------------------------------===//
-let CategoryName = "User Defined Issues" in {
+let CategoryName = "User-Defined Issue" in {
def pp_hash_warning : Warning<"%0">,
- InGroup<PoundWarning>, DefaultWarnShowInSystemHeader;
+ InGroup<PoundWarning>, ShowInSystemHeader;
def err_pp_hash_error : Error<"%0">;
}
@@ -300,6 +301,9 @@ 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 MSVC search rules as: %0">,
+ InGroup<DiagGroup<"msvc-include">>;
def ext_pp_ident_directive : Extension<"#ident is a language extension">;
def ext_pp_include_next_directive : Extension<
@@ -312,7 +316,7 @@ def ext_pp_extra_tokens_at_eol : ExtWarn<
def ext_pp_comma_expr : Extension<"comma operator in operand of #if">;
def ext_pp_bad_vaargs_use : Extension<
"__VA_ARGS__ can only appear in the expansion of a C99 variadic macro">;
-def ext_pp_macro_redef : ExtWarn<"%0 macro redefined">;
+def ext_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<
@@ -349,7 +353,7 @@ def err_pp_error_opening_file : Error<
def err_pp_empty_filename : Error<"empty filename">;
def err_pp_include_too_deep : Error<"#include nested too deeply">;
def err_pp_expects_filename : Error<"expected \"FILENAME\" or <FILENAME>">;
-def err_pp_macro_not_identifier : Error<"macro names must be identifiers">;
+def err_pp_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">;
@@ -375,10 +379,7 @@ 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_defined_requires_identifier : Error<
- "operator 'defined' requires an identifier">;
-def err_pp_missing_lparen : Error<"missing '(' after '%0'">;
-def err_pp_missing_rparen : Error<"missing ')' after '%0'">;
+def err_pp_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">;
@@ -400,6 +401,9 @@ 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>;
@@ -435,7 +439,8 @@ def err_pragma_message_malformed : Error<
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">;
+ "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">;
@@ -470,7 +475,7 @@ def warn_pragma_diagnostic_unknown_warning :
InGroup<UnknownPragmas>;
// - #pragma __debug
def warn_pragma_debug_unexpected_command : Warning<
- "unexpected debug command '%0'">;
+ "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<
@@ -491,11 +496,13 @@ def err_too_few_args_in_macro_invoc : Error<
"too few arguments provided to function-like macro invocation">;
def err_pp_bad_paste : Error<
"pasting formed '%0', an invalid preprocessing token">;
-def err_pp_bad_paste_ms : Warning<
+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' cannot be used as a macro name">;
+ "C++ operator %0 (aka %1) used as a macro name">;
+def ext_pp_operator_used_as_macro_name : Extension<
+ "C++ operator %0 (aka %1) used as a macro name">, InGroup<Microsoft>;
def err_pp_illegal_floating_literal : Error<
"floating point literal in preprocessor expression">;
def err_pp_line_requires_integer : Error<
@@ -535,6 +542,10 @@ def err_pp_include_in_arc_cf_code_audited : Error<
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">;
@@ -551,8 +562,6 @@ 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_header_not_found : Error<
- "%select{|umbrella }0header '%1' not found">;
def err_mmap_umbrella_dir_not_found : Error<
"umbrella directory '%0' not found">;
def err_mmap_umbrella_clash : Error<
@@ -605,7 +614,7 @@ def warn_auto_module_import : Warning<
"import of module '%1'">, InGroup<AutoImport>, DefaultIgnore;
def warn_uncovered_module_header : Warning<
"umbrella header for module '%0' does not include header '%1'">,
- InGroup<IncompleteUmbrella>, DefaultIgnore;
+ InGroup<IncompleteUmbrella>;
def warn_forgotten_module_header : Warning<
"header '%0' is included in module '%1' but not listed in module map">,
InGroup<IncompleteModule>, DefaultIgnore;
@@ -614,7 +623,14 @@ def err_expected_id_building_module : Error<
def error_use_of_private_header_outside_module : Error<
"use of private header from outside its module: '%0'">;
def error_undeclared_use_of_module : Error<
- "use of a module not declared used: '%0'">;
+ "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_header_guard : Warning<
"%0 is used as a header guard here, followed by #define of a different macro">,
diff --git a/include/clang/Basic/DiagnosticOptions.h b/include/clang/Basic/DiagnosticOptions.h
index 2fba3844a09c..3e4d0eefbcf9 100644
--- a/include/clang/Basic/DiagnosticOptions.h
+++ b/include/clang/Basic/DiagnosticOptions.h
@@ -19,7 +19,7 @@ namespace clang {
/// \brief Specifies which overload candidates to display when overload
/// resolution fails.
-enum OverloadsShown {
+enum OverloadsShown : unsigned {
Ovl_All, ///< Show all overloads.
Ovl_Best ///< Show just the "best" overload candidates.
};
@@ -58,6 +58,10 @@ public:
/// 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)
diff --git a/include/clang/Basic/DiagnosticParseKinds.td b/include/clang/Basic/DiagnosticParseKinds.td
index 2feab52ef4d1..b1305e182f0b 100644
--- a/include/clang/Basic/DiagnosticParseKinds.td
+++ b/include/clang/Basic/DiagnosticParseKinds.td
@@ -59,7 +59,8 @@ def ext_integer_complex : Extension<
"complex integer types are a GNU extension">, InGroup<GNUComplexInteger>;
def ext_thread_before : Extension<"'__thread' before '%0'">;
def ext_keyword_as_ident : ExtWarn<
- "keyword '%0' will be treated as an identifier %select{here|for the remainder of the translation unit}1">,
+ "keyword '%0' will be made available as an identifier "
+ "%select{here|for the remainder of the translation unit}1">,
InGroup<KeywordCompat>;
def error_empty_enum : Error<"use of empty enum">;
@@ -68,7 +69,7 @@ def err_invalid_short_spec : Error<"'short %0' is invalid">;
def err_invalid_long_spec : Error<"'long %0' is invalid">;
def err_invalid_longlong_spec : Error<"'long long %0' is invalid">;
def err_invalid_complex_spec : Error<"'_Complex %0' is invalid">;
-def err_friend_storage_spec : Error<"'%0' is invalid in friend declarations">;
+def err_friend_decl_spec : Error<"'%0' is invalid in friend declarations">;
def ext_ident_list_in_param : Extension<
"type-less parameter names in function declaration">;
@@ -148,18 +149,6 @@ 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_ident : Error<"expected identifier">;
-def err_expected_ident_lparen : Error<"expected identifier or '('">;
-def err_expected_ident_lbrace : Error<"expected identifier or '{'">;
-def err_expected_lbrace : Error<"expected '{'">;
-def err_expected_lparen : Error<"expected '('">;
-def err_expected_lparen_or_lbrace : Error<"expected '(' or '{'">;
-def err_expected_rparen : Error<"expected ')'">;
-def err_expected_lsquare : Error<"expected '['">;
-def err_expected_rsquare : Error<"expected ']'">;
-def err_expected_rbrace : Error<"expected '}'">;
-def err_expected_greater : Error<"expected '>'">;
-def err_expected_ggg : Error<"expected '>>>'">;
def err_expected_semi_declaration : Error<
"expected ';' at end of declaration">;
def err_expected_semi_decl_list : Error<
@@ -185,18 +174,16 @@ def err_expected_method_body : Error<"expected method body">;
def err_invalid_token_after_toplevel_declarator : Error<
"expected ';' after top level declarator">;
def err_invalid_token_after_declarator_suggest_equal : Error<
- "invalid '%0' at end of declaration; did you mean '='?">;
+ "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_lparen_after_id : 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_equal_after : Error<"expected '=' after %0">;
-def err_expected_comma : Error<"expected ','">;
def err_expected_lbrace_in_compound_literal : Error<
"expected '{' in compound literal">;
def err_expected_while : Error<"expected 'while' in do/while loop">;
-def err_expected_semi_after : Error<"expected ';' after %0">;
def err_expected_semi_after_stmt : Error<"expected ';' after %0 statement">;
def err_expected_semi_after_expr : Error<"expected ';' after expression">;
def err_extraneous_token_before_semi : Error<"extraneous '%0' before ';'">;
@@ -206,7 +193,7 @@ def err_expected_semi_after_method_proto : Error<
def err_expected_semi_after_namespace_name : Error<
"expected ';' after namespace name">;
def err_unexpected_namespace_attributes_alias : Error<
- "attributes can not be specified on namespace alias">;
+ "attributes cannot be specified on namespace alias">;
def err_inline_namespace_alias : Error<"namespace alias cannot be inline">;
def err_namespace_nonnamespace_scope : Error<
"namespaces can only be defined in global or namespace scope">;
@@ -217,7 +204,8 @@ def err_expected_semi_after_attribute_list : Error<
def err_expected_semi_after_static_assert : Error<
"expected ';' after static_assert">;
def err_expected_semi_for : Error<"expected ';' in 'for' statement specifier">;
-def err_expected_colon_after : Error<"expected ':' after %0">;
+def err_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">,
@@ -238,6 +226,8 @@ def err_expected_selector_for_method : Error<
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">;
@@ -287,6 +277,13 @@ def ext_for_range : ExtWarn<
def warn_cxx98_compat_for_range : Warning<
"range-based for loop is incompatible with C++98">,
InGroup<CXX98Compat>, DefaultIgnore;
+def ext_for_range_identifier : ExtWarn<
+ "range-based for loop with implicit deduced type is a C++1z extension">,
+ InGroup<CXX1z>;
+def warn_cxx1y_compat_for_range_identifier : Warning<
+ "range-based for loop with implicit deduced type is incompatible with "
+ "C++ standards before C++1z">,
+ InGroup<CXXPre1zCompat>, DefaultIgnore;
def err_for_range_expected_decl : Error<
"for range declaration must declare a variable">;
def err_argument_required_after_attribute : Error<
@@ -343,16 +340,16 @@ def warn_vector_long_decl_spec_combination : Warning<
"Use of 'long' with '__vector' is deprecated">, InGroup<Deprecated>;
def err_friend_invalid_in_context : Error<
"'friend' used outside of class">;
-def err_unknown_typename : Error<
- "unknown type name %0">;
def err_use_of_tag_name_without_tag : Error<
"must use '%1' tag to refer to type %0%select{| in this scope}2">;
def err_templated_using_directive : Error<
"cannot template a using directive">;
def err_templated_using_declaration : Error<
"cannot template a using declaration">;
-def err_unexected_colon_in_nested_name_spec : Error<
+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<
@@ -364,6 +361,8 @@ 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">;
/// Objective-C parser diagnostics
def err_expected_minus_or_plus : Error<
@@ -424,7 +423,7 @@ 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 can not be protocol qualified">;
+ "@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<
@@ -449,6 +448,8 @@ 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 go after the %select{identifier|unqualified-id}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">;
@@ -480,9 +481,6 @@ 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_expected_lbrace_or_comma : Error<"expected '{' or ','">;
-def err_expected_rbrace_or_comma : Error<"expected '}' or ','">;
-def err_expected_rsquare_or_comma : Error<"expected ']' or ','">;
def err_using_namespace_in_class : Error<
"'using namespace' is not allowed in classes">;
def err_constructor_bad_name : Error<
@@ -504,8 +502,7 @@ 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 '%select{.|->}0' in function call; perhaps remove the "
- "'%select{.|->}0'?">;
+ "unexpected %0 in function call; perhaps remove the %0?">;
// C++ derived classes
def err_dup_virtual : Error<"duplicate 'virtual' in base specifier">;
@@ -535,10 +532,12 @@ def warn_cxx98_compat_nullptr : Warning<
def warn_cxx98_compat_alignas : Warning<"'alignas' is incompatible with C++98">,
InGroup<CXX98Compat>, DefaultIgnore;
def warn_cxx98_compat_attribute : Warning<
- "attributes are incompatible with C++98">,
+ "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">;
+ "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<
@@ -549,8 +548,6 @@ def err_l_square_l_square_not_attribute : Error<
"introducing an attribute">;
def err_ms_declspec_type : Error<
"__declspec attributes must be an identifier or string literal">;
-def warn_ms_declspec_unknown : Warning<
- "unknown __declspec attribute %0 ignored">, InGroup<UnknownAttributes>;
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<
@@ -576,10 +573,17 @@ 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_cxx1y_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 template template parameter}1">;
+ "%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<
@@ -639,16 +643,13 @@ 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_expected_semi_after_tagdecl : Error<
- "expected ';' after %0">;
def err_typename_refers_to_non_type_template : Error<
- "typename specifier refers to a non-template">;
+ "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 "
- "%select{class|struct|union|interface}1 %2">;
+ "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 "
@@ -744,7 +745,8 @@ 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}0">;
+ "lambda requires '()' before %select{'mutable'|return type|"
+ "attribute specifier}0">;
// Availability attribute
def err_expected_version : Error<
@@ -753,6 +755,13 @@ 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<
@@ -769,35 +778,82 @@ def warn_availability_and_unavailable : Warning<
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">;
+ "missing '(' after '#pragma %0' - ignoring">, InGroup<IgnoredPragmas>;
def warn_pragma_expected_rparen : Warning<
- "missing ')' after '#pragma %0' - ignoring">;
+ "missing ')' after '#pragma %0' - ignoring">, InGroup<IgnoredPragmas>;
def warn_pragma_expected_identifier : Warning<
- "expected identifier in '#pragma %0' - ignored">;
+ "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">;
+ "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">;
+ "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'; expected %1">;
// - #pragma options
def warn_pragma_options_expected_align : Warning<
- "expected 'align' following '#pragma options' - ignored">;
+ "expected 'align' following '#pragma options' - ignored">,
+ InGroup<IgnoredPragmas>;
def warn_pragma_align_expected_equal : Warning<
- "expected '=' following '#pragma %select{align|options align}0' - ignored">;
+ "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">;
+ "invalid alignment option in '#pragma %select{align|options align}0' - ignored">,
+ InGroup<IgnoredPragmas>;
// - #pragma pack
-def warn_pragma_pack_invalid_action : Warning<
- "unknown action for '#pragma pack' - ignored">;
+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">;
+ "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">;
-def warn_pragma_unused_expected_punc : Warning<
- "expected ')' or ',' in '#pragma unused'">;
+ "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 "
@@ -810,6 +866,16 @@ def err_pragma_comment_unknown_kind : Error<"unknown kind of pragma comment">;
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 Section 6.8.g
def err_not_opencl_storage_class_specifier : Error<
@@ -817,11 +883,11 @@ def err_not_opencl_storage_class_specifier : Error<
// OpenCL EXTENSION pragma (OpenCL 1.1 [9.1])
def warn_pragma_expected_colon : Warning<
- "missing ':' after %0 - ignoring">;
+ "missing ':' after %0 - ignoring">, InGroup<IgnoredPragmas>;
def warn_pragma_expected_enable_disable : Warning<
- "expected 'enable' or 'disable' - ignoring">;
+ "expected 'enable' or 'disable' - ignoring">, InGroup<IgnoredPragmas>;
def warn_pragma_unknown_extension : Warning<
- "unknown OpenCL extension %0 - ignoring">;
+ "unknown OpenCL extension %0 - ignoring">, InGroup<IgnoredPragmas>;
def err_seh_expected_handler : Error<
"expected '__except' or '__finally' block">;
@@ -836,21 +902,35 @@ def err_seh___finally_block : Error<
"%0 only allowed in __finally block">;
// OpenMP support.
-def warn_pragma_omp_ignored : Warning <
+def warn_pragma_omp_ignored : Warning<
"unexpected '#pragma omp ...' in program">, InGroup<SourceUsesOpenMP>, DefaultIgnore;
-def warn_omp_extra_tokens_at_eol : Warning <
+def warn_omp_extra_tokens_at_eol : Warning<
"extra tokens at the end of '#pragma omp %0' are ignored">,
InGroup<ExtraTokens>;
-def err_omp_unknown_directive : Error <
+def err_omp_unknown_directive : Error<
"expected an OpenMP directive">;
-def err_omp_unexpected_directive : Error <
+def err_omp_unexpected_directive : Error<
"unexpected OpenMP directive '#pragma omp %0'">;
-def err_omp_expected_punc : Error <
- "expected ',' or ')' in %select{'#pragma omp %1'|'%1' clause}0">;
-def err_omp_unexpected_clause : Error <
+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_more_one_clause : Error <
+def err_omp_more_one_clause : Error<
"directive '#pragma omp %0' cannot contain more than one '%1' clause">;
+def err_omp_immediate_directive : Error<
+ "'#pragma omp %0' cannot be an immediate substatement">;
+def err_omp_expected_identifier_for_critical : Error<
+ "expected identifier specifying the name of the 'omp critical' directive">;
+
+// Pragma loop support.
+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">;
+
+// 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 {
diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td
index 6c7cb001808a..89749edfac44 100644
--- a/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/include/clang/Basic/DiagnosticSemaKinds.td
@@ -14,6 +14,11 @@
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 "
@@ -30,6 +35,25 @@ def warn_duplicate_enum_values : Warning<
"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_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">;
@@ -87,9 +111,9 @@ def err_array_star_in_function_definition : Error<
def err_vla_decl_in_file_scope : Error<
"variable length array declaration not allowed at file scope">;
def err_vla_decl_has_static_storage : Error<
- "variable length array declaration can not have 'static' storage duration">;
+ "variable length array declaration cannot have 'static' storage duration">;
def err_vla_decl_has_extern_linkage : Error<
- "variable length array declaration can not have 'extern' linkage">;
+ "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>;
@@ -142,7 +166,7 @@ def ext_flexible_array_init : Extension<
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">;
+ "%0 cannot be the name of a parameter">;
def err_parameter_name_omitted : Error<"parameter name omitted">;
def warn_unused_parameter : Warning<"unused parameter %0">,
InGroup<UnusedParameter>, DefaultIgnore;
@@ -215,10 +239,13 @@ def ext_implicit_function_decl : ExtWarn<
InGroup<ImplicitFunctionDeclare>;
def note_function_suggestion : Note<"did you mean %0?">;
-def err_ellipsis_first_arg : Error<
- "ISO C requires a named argument before '...'">;
+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_bad_language : Error<"unknown linkage language">;
+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<
@@ -251,9 +278,9 @@ def err_using_decl_nested_name_specifier_is_current_class : Error<
def err_using_decl_nested_name_specifier_is_not_base_class : Error<
"using declaration refers into '%0', which is not a base class of %1">;
def err_using_decl_constructor_not_in_direct_base : Error<
- "%0 is not a direct base of %1, can not inherit constructors">;
+ "%0 is not a direct base of %1, cannot inherit constructors">;
def err_using_decl_constructor_conflict : Error<
- "can not inherit constructor, already inherited constructor with "
+ "cannot inherit constructor, already inherited constructor with "
"the same signature">;
def note_using_decl_constructor_conflict_current_ctor : Note<
"conflicting constructor">;
@@ -267,18 +294,21 @@ def warn_using_decl_constructor_ellipsis : Warning<
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 can not refer to class member">;
+ "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 can not refer to namespace">;
+ "using declaration cannot refer to namespace">;
def err_using_decl_constructor : Error<
- "using declaration can not refer to a constructor">;
+ "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 can not refer to a destructor">;
+ "using declaration cannot refer to a destructor">;
def err_using_decl_template_id : Error<
- "using declaration can not refer to a template specialization">;
+ "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">;
@@ -319,7 +349,7 @@ def err_invalid_thread : Error<
def err_thread_non_global : Error<
"'%0' variables must have global storage">;
def err_thread_unsupported : Error<
- "thread-local storage is unsupported for the current target">;
+ "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">,
@@ -337,40 +367,42 @@ def warn_suggest_noreturn_function : Warning<
def warn_suggest_noreturn_block : Warning<
"block could be declared with attribute 'noreturn'">,
InGroup<MissingNoreturn>, DefaultIgnore;
-def warn_unreachable : Warning<"will never be executed">,
- InGroup<DiagGroup<"unreachable-code">>, 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">;
-def note_please_include_header : Note<
- "please include the header <%0> or explicitly provide a "
- "declaration for '%1'">;
+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_stdio : Warning<
- "declaration of built-in function '%0' requires inclusion of the header "
- "<stdio.h>">,
- InGroup<BuiltinRequiresHeader>;
-def warn_implicit_decl_requires_setjmp : Warning<
- "declaration of built-in function '%0' requires inclusion of the header "
- "<setjmp.h>">,
- InGroup<BuiltinRequiresHeader>;
-def warn_implicit_decl_requires_ucontext : Warning<
- "declaration of built-in function '%0' requires inclusion of the header "
- "<ucontext.h>">,
+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_types_compatible_p_in_cplusplus : Error<
- "__builtin_types_compatible_p is not valid in C++">;
def warn_builtin_unknown : Warning<"use of unknown builtin %0">,
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 dynamic class %2; vtable pointer will be "
- "%select{overwritten|copied|moved|compared}3">,
+ "%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">;
@@ -388,11 +420,18 @@ def warn_sizeof_pointer_type_memaccess : Warning<
"%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">,
+ "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 "
@@ -405,6 +444,10 @@ 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 __assume has side effects that will be discarded">,
+ InGroup<DiagGroup<"assume">>;
+
/// main()
// static main() is not an error in C, just in C++.
def warn_static_main : Warning<"'main' should not be declared static">,
@@ -416,7 +459,8 @@ def ext_noreturn_main : ExtWarn<
def note_main_remove_noreturn : Note<"remove '_Noreturn'">;
def err_constexpr_main : Error<
"'main' is not allowed to be declared constexpr">;
-def err_mainlike_template_decl : Error<"'%0' cannot be a template">;
+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>;
@@ -428,6 +472,8 @@ def warn_main_one_arg : Warning<"only one parameter on 'main' declaration">,
def err_main_arg_wrong : Error<"%select{first|second|third|fourth}0 "
"parameter of 'main' (%select{argument count|argument array|environment|"
"platform-specific data}0) must be of type %1">;
+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">,
@@ -435,6 +481,10 @@ def ext_no_declarators : ExtWarn<"declaration does not declare anything">,
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<
@@ -447,28 +497,37 @@ def err_opencl_half_load_store : Error<
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_argument : Error<
- "declaring function argument of type %0 is not allowed; did you forget * ?">;
+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">;
+ "#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'">;
+ "expected #pragma pack parameter to be '1', '2', '4', '8', or '16'">,
+ InGroup<IgnoredPragmas>;
// Follow the MSVC implementation.
def warn_pragma_pack_show : Warning<"value of #pragma pack(show) == %0">;
def warn_pragma_pack_pop_identifer_and_alignment : Warning<
"specifying both a name and alignment to 'pop' is undefined">;
-def warn_pragma_pack_pop_failed : Warning<"#pragma pack(pop, ...) failed: %0">;
-def warn_pragma_ms_struct_failed : Warning<"#pramga ms_struct can not be used with dynamic classes or structures">, InGroup<IgnoredAttributes>;
+def warn_pragma_pop_failed : Warning<"#pragma %0(pop, ...) failed: %1">,
+ InGroup<IgnoredPragmas>;
+def warn_cxx_ms_struct :
+ Warning<"ms_struct may not produce MSVC-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 warn_pragma_unused_undeclared_var : Warning<
- "undeclared variable %0 used as an argument for '#pragma unused'">;
+ "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'">;
+ "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<
@@ -477,6 +536,14 @@ 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_value : Error<
+ "invalid argument; expected a positive integer value">;
+def err_pragma_loop_invalid_keyword : Error<
+ "invalid argument; expected 'enable' or 'disable'">;
+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<
@@ -547,12 +614,10 @@ def err_conflicting_ivar_bitwidth : Error<
"instance variable %0 has conflicting bit-field width">;
def err_conflicting_ivar_name : Error<
"conflicting instance variable names: %0 vs %1">;
-def err_inconsistant_ivar_count : Error<
+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 note_required_for_protocol_at :
- Note<"required for direct or indirect protocol %0">;
def warn_conflicting_overriding_ret_types : Warning<
"conflicting return type in "
@@ -696,21 +761,21 @@ def note_atomic_property_fixup_suggest : Note<"setter and getter must both be "
def err_atomic_property_nontrivial_assign_op : Error<
"atomic property of reference type %0 cannot have non-trivial assignment"
" operator">;
-def warn_owning_getter_rule : Warning<
- "property's synthesized getter follows Cocoa naming"
+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 warn_auto_synthesizing_protocol_property :Warning<
- "auto property synthesis will not synthesize property"
- " declared in a protocol">,
+ "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">,
+ "%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' "
+ "%0 because it is 'readwrite' but it will be synthesized 'readonly' "
"via another property">,
InGroup<ObjCNoPropertyAutoSynthesis>;
def warn_autosynthesis_property_ivar_match :Warning<
@@ -724,10 +789,10 @@ def warn_property_getter_owning_mismatch : Warning<
"property declared as returning non-retained objects"
"; getter returning retained objects">;
def error_property_setter_ambiguous_use : Error<
- "synthesized properties '%0' and '%1' both claim setter %2 -"
+ "synthesized properties %0 and %1 both claim setter %2 -"
" use of this setter will cause unexpected behavior">;
-def err_ownin_getter_rule : Error<
- "property's synthesized getter follows Cocoa naming"
+def err_cocoa_naming_owned_rule : Error<
+ "property follows Cocoa naming"
" convention for returning 'owned' objects">;
def warn_default_atomic_custom_getter_setter : Warning<
"atomic by default property %0 has a user defined %select{getter|setter}1 "
@@ -778,6 +843,9 @@ def err_arc_perform_selector_retains : Error<
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_receiver_is_weak : Warning <
@@ -818,13 +886,10 @@ def error_weak_property : Error<
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 can not have instance variable specification">;
+ "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_property_attr_mutually_exclusive : Warning<
- "property attributes '%0' and '%1' are mutually exclusive">,
- InGroup<ReadOnlySetterAttrs>, DefaultIgnore;
def warn_objc_missing_super_call : Warning<
"method possibly missing a [super %0] call">,
InGroup<ObjCMissingSuperCalls>;
@@ -841,23 +906,30 @@ def warn_implicit_atomic_property : Warning<
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 "
+ "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<
- "creating selector for nonexistent method %0">, InGroup<Selector>, DefaultIgnore;
-def warning_multiple_selectors: Warning<
- "multiple selectors named %0 found">, InGroup<SelectorTypeMismatch>, DefaultIgnore;
+ "no method with selector %0 is implemented in this translation unit">,
+ InGroup<Selector>, DefaultIgnore;
def warn_unimplemented_protocol_method : Warning<
- "method %0 in protocol not implemented">, InGroup<Protocol>;
-
+ "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;
// C++ declarations
def err_static_assert_expression_is_not_constant : Error<
"static_assert expression is not an integral constant expression">;
-def err_static_assert_failed : Error<"static_assert failed %0">;
+def err_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_cxx1y_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">;
@@ -918,7 +990,11 @@ 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<Microsoft>;
+
def err_invalid_member_in_interface : Error<
"%select{data member |non-public member function |static member function |"
"user-declared constructor|user-declared destructor|operator |"
@@ -937,19 +1013,23 @@ def err_throw_abstract_type : Error<
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 can not be defined in a type specifier">;
+ "%0 cannot be defined in a type specifier">;
def err_type_defined_in_result_type : Error<
- "%0 can not be defined in the result type of a function">;
+ "%0 cannot be defined in the result type of a function">;
def err_type_defined_in_param_type : Error<
- "%0 can not be defined in a parameter type">;
+ "%0 cannot be defined in a parameter type">;
def err_type_defined_in_alias_template : Error<
- "%0 can not be defined in a type alias template">;
+ "%0 cannot be defined in a type alias template">;
def note_pure_virtual_function : Note<
"unimplemented pure virtual method %0 in %1">;
@@ -988,12 +1068,13 @@ 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 warn_mismatched_exception_spec : ExtWarn<
- "exception specification in declaration does not match previous declaration">;
+def ext_mismatched_exception_spec : ExtWarn<
+ "exception specification in declaration does not match previous declaration">,
+ InGroup<Microsoft>;
def err_override_exception_spec : Error<
"exception specification of overriding function is more lax than "
"base version">;
-def warn_override_exception_spec : ExtWarn<
+def ext_override_exception_spec : ExtWarn<
"exception specification of overriding function is more lax than "
"base version">, InGroup<Microsoft>;
def err_incompatible_exception_specs : Error<
@@ -1105,7 +1186,10 @@ def err_incomplete_type : Error<
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 scoped enumeration}1; did you mean ':'?">;
+
// C++ class members
def err_storageclass_invalid_for_member : Error<
"storage class specified for a member declaration">;
@@ -1119,7 +1203,7 @@ def err_virtual_non_function : Error<
def err_virtual_out_of_class : Error<
"'virtual' can only be specified inside the class definition">;
def err_virtual_member_function_template : Error<
- "'virtual' can not be specified on member function templates">;
+ "'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<
@@ -1142,7 +1226,7 @@ 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 warn_pure_function_definition : ExtWarn<
+def ext_pure_function_definition : ExtWarn<
"function definition with pure-specifier is a Microsoft extension">,
InGroup<Microsoft>;
def err_implicit_object_parameter_init : Error<
@@ -1155,10 +1239,9 @@ def warn_call_to_pure_virtual_member_function_from_ctor_dtor : Warning<
"call to pure virtual member function %0; overrides of %0 in subclasses are "
"not available in the %select{constructor|destructor}1 of %2">;
-def note_field_decl : Note<"member is declared here">;
+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_previous_decl : Note<"%0 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 "
@@ -1419,6 +1502,9 @@ def warn_uninit_byref_blockvar_captured_by_block : Warning<
InGroup<Uninitialized>, DefaultIgnore;
def note_block_var_fixit_add_initialization : Note<
"maybe you meant 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_var_fixit_add_initialization : Note<
"initialize the variable %0 to silence this warning">;
def note_uninit_fixit_remove_cond : Note<
@@ -1495,16 +1581,22 @@ 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_requires_parens : Error<
+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 %0 with type %1 from "
+ "parenthesized 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">;
+ "'auto' return without trailing return type; deduced return types are a "
+ "C++1y extension">;
+def err_deduced_return_type : Error<
+ "deduced return types are a C++1y 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<
@@ -1570,7 +1662,7 @@ 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">;
+def err_repeat_attribute : Error<"%0 attribute cannot be repeated">;
// C++11 final
def err_final_function_overridden : Error<
@@ -1597,6 +1689,8 @@ def err_enum_class_reference : Error<
"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<
@@ -1730,6 +1824,8 @@ def err_constexpr_local_var_no_init : Error<
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 warn_cxx11_compat_constexpr_body_no_return : Warning<
@@ -1786,21 +1882,16 @@ def warn_auto_var_is_id : Warning<
// Attributes
def err_nsobject_attribute : Error<
- "__attribute ((NSObject)) is for pointer types only">;
-def err_attribute_can_be_applied_only_to_symbol_declaration : Error<
- "%0 attribute can be applied only to symbol declaration">;
+ "'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<
- "attribute takes no more than %0 argument%s0">;
-def err_suppress_autosynthesis : Error<
- "objc_requires_property_definitions attribute may only be specified on a class"
- "to a class declaration">;
+ "%0 attribute takes no more than %1 argument%s1">;
def err_attribute_too_few_arguments : Error<
- "attribute takes at least %0 argument%s0">;
+ "%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">;
@@ -1809,14 +1900,11 @@ def err_attribute_unsupported : Error<
def err_aligned_attribute_argument_not_int : Error<
"'aligned' attribute requires integer constant">;
def err_alignas_attribute_wrong_decl_type : Error<
- "'%select{alignas|_Alignas}0' attribute cannot be applied to a %select{"
- "function parameter|variable with 'register' storage class|"
- "'catch' variable|bit-field}1">;
+ "%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<
- "'%select{alignas|_Alignas}0' must be specified on definition if it is "
- "specified on any declaration">;
-def note_alignas_on_declaration : Note<
- "declared with '%select{alignas|_Alignas}0' attribute here">;
+ "%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<
@@ -1836,17 +1924,20 @@ def err_init_priority_object_attr : Error<
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">;
+ "%0 attribute parameter %1 is out of bounds">;
def err_attribute_uuid_malformed_guid : Error<
"uuid attribute contains a malformed GUID">;
-def warn_nonnull_pointers_only : Warning<
- "nonnull attribute only applies to pointer arguments">;
-def err_attribute_pointers_only : Error<
- "%0 attribute only applies to pointer arguments">;
+def warn_attribute_pointers_only : Warning<
+ "%0 attribute only applies to 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 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">;
+ "%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_format_strftime_third_parameter : Error<
@@ -1858,8 +1949,6 @@ 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_common_not_supported_cplusplus : Error<
- "common attribute is not supported in C++">;
def err_init_method_bad_return_type : Error<
"init methods must return an object pointer type, not %0">;
def err_attribute_invalid_size : Error<
@@ -1868,8 +1957,8 @@ 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<
"can't convert between vector values of different size (%0 and %1)">;
-def err_typecheck_ext_vector_not_typedef : Error<
- "ext_vector_type only applies to types, not variables">;
+def err_typecheck_vector_not_convertable_non_scalar : Error<
+ "can't convert between vector and non-scalar values (%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<
@@ -1923,8 +2012,8 @@ 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 warn_missing_atsign_prefix : Warning<
- "string literal must be prefixed by '@' ">, InGroup<ObjCLiteralMissingAtSign>;
+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>;
@@ -1934,6 +2023,11 @@ def warn_concatenated_nsarray_literal : Warning<
InGroup<ObjCStringConcatenation>;
def note_objc_literal_comparison_isequal : Note<
"use 'isEqual:' instead">;
+def err_attribute_argument_is_zero : Error<
+ "%0 attribute must be greater than 0">;
+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<
@@ -1948,30 +2042,24 @@ def err_only_annotate_after_access_spec : Error<
def err_attribute_section_invalid_for_target : Error<
"argument to 'section' attribute is not valid for this target: %0">;
-def err_attribute_section_local_variable : Error<
- "'section' attribute is not valid on local variables">;
def 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_getter_for_property : Error<
- "no getter defined for property '%0'">;
-def err_no_setter_for_property : Error<
- "no setter defined for property '%0'">;
-def error_cannot_find_suitable_getter : Error<
- "cannot find suitable getter for property '%0'">;
-def error_cannot_find_suitable_setter : Error<
- "cannot find suitable setter for property '%0'">;
+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_attribute_aligned_not_power_of_two : Error<
"requested alignment is not a power of 2">;
-def err_attribute_aligned_greater_than_8192 : Error<
- "requested alignment must be 8192 bytes or smaller">;
+def err_attribute_aligned_too_great : Error<
+ "requested alignment must be %0 bytes or smaller">;
def warn_redeclaration_without_attribute_prev_attribute_ignored : Warning<
- "'%0' redeclared without %1 attribute: previous %1 ignored">;
+ "%q0 redeclared without %1 attribute: previous %1 ignored">;
def warn_attribute_ignored : Warning<"%0 attribute ignored">,
InGroup<IgnoredAttributes>;
def warn_attribute_after_definition_ignored : Warning<
@@ -2005,8 +2093,8 @@ 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<
- "__attribute ((NSObject)) may be put on a typedef only, "
- "attribute is ignored">, InGroup<NSobjectAttribute>;
+ "'NSObject' attribute may be put on a typedef only; attribute is ignored">,
+ InGroup<NSobjectAttribute>;
def warn_attribute_weak_on_local : Warning<
"__weak attribute cannot be specified on an automatic variable when ARC "
"is not enabled">,
@@ -2017,19 +2105,54 @@ 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 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 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_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 "
+ "%select{without dll attribute|with different dll attribute}1 is not supported">,
+ InGroup<DiagGroup<"unsupported-dll-base-class-template">>;
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">;
+ "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">;
+ "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<
@@ -2042,18 +2165,14 @@ def warn_attribute_wrong_decl_type : Warning<
"variables, functions and labels|fields and global variables|structs|"
"variables, functions and tag types|thread-local variables|"
"variables and fields|variables, data members and tag types|"
- "types and namespaces|Objective-C interfaces}1">,
+ "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 or typedefs|"
+ "interface or protocol declarations}1">,
InGroup<IgnoredAttributes>;
-def err_attribute_wrong_decl_type : Error<
- "%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|variables|methods|"
- "variables, functions and labels|fields and global variables|structs|"
- "variables, functions and tag types|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}1">;
+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">,
@@ -2093,8 +2212,6 @@ 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 err_attribute_can_be_applied_only_to_value_decl : Error<
- "%0 attribute can only be applied to value declarations">;
def warn_attribute_not_on_decl : Warning<
"%0 attribute ignored when parsing type">, InGroup<IgnoredAttributes>;
def err_base_specifier_attribute : Error<
@@ -2121,29 +2238,23 @@ def note_overridden_method : Note<
"overridden 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 'lockable' attribute; type here is '%1'">,
+ "with 'capability' attribute; type here is %1">,
InGroup<ThreadSafetyAttributes>, DefaultIgnore;
-def warn_thread_attribute_argument_not_class : Warning<
- "%0 attribute requires arguments that are class type or point to"
- " class type; 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 'lockable' attribute">,
+ "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">,
+ "%0 only applies to pointer types; type here is %1">,
InGroup<ThreadSafetyAttributes>, DefaultIgnore;
-def warn_thread_attribute_wrong_decl_type : Warning<
- "%0 attribute only applies to %select{"
- "fields and global variables|functions and methods|"
- "classes and structs}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|"
@@ -2151,41 +2262,43 @@ def err_attribute_argument_out_of_range : Error<
":must be between 1 and %2}2">;
// Thread Safety Analysis
-def warn_unlock_but_no_lock : Warning<
- "unlocking '%0' that was not locked">,
+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<
- "locking '%0' that is already locked">,
+def warn_double_lock : Warning<"acquiring %0 '%1' that is already held">,
InGroup<ThreadSafetyAnalysis>, DefaultIgnore;
def warn_no_unlock : Warning<
- "mutex '%0' is still locked at the end of function">,
+ "%0 '%1' is still held at the end of function">,
InGroup<ThreadSafetyAnalysis>, DefaultIgnore;
def warn_expecting_locked : Warning<
- "expecting mutex '%0' to be locked at the end of function">,
+ "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<
- "mutex '%0' is not locked on every path through here">,
+ "%0 '%1' is not held on every path through here">,
InGroup<ThreadSafetyAnalysis>, DefaultIgnore;
def warn_expecting_lock_held_on_loop : Warning<
- "expecting mutex '%0' to be locked at start of each loop">,
+ "expecting %0 '%1' to be held at start of each loop">,
InGroup<ThreadSafetyAnalysis>, DefaultIgnore;
-def note_locked_here : Note<"mutex acquired here">;
+def note_locked_here : Note<"%0 acquired here">;
def warn_lock_exclusive_and_shared : Warning<
- "mutex '%0' is locked exclusively and shared in the same scope">,
+ "%0 '%1' is acquired exclusively and shared in the same scope">,
InGroup<ThreadSafetyAnalysis>, DefaultIgnore;
def note_lock_exclusive_and_shared : Note<
- "the other lock of mutex '%0' is here">;
+ "the other acquisition of %0 '%1' is here">;
def warn_variable_requires_any_lock : Warning<
- "%select{reading|writing}1 variable '%0' requires locking "
+ "%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 locking "
+ "%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 '%0' while mutex '%1' is locked">,
+ "cannot call function '%1' while %0 '%2' is held">,
InGroup<ThreadSafetyAnalysis>, DefaultIgnore;
def warn_cannot_resolve_lock : Warning<
"cannot resolve lock expression">,
@@ -2193,28 +2306,26 @@ def warn_cannot_resolve_lock : Warning<
// Imprecise thread safety warnings
def warn_variable_requires_lock : Warning<
- "%select{reading|writing}2 variable '%0' requires locking "
- "%select{'%1'|'%1' exclusively}2">,
+ "%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}2 the value pointed to by '%0' requires locking "
- "%select{'%1'|'%1' exclusively}2">,
+ "%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 '%0' requires %select{shared|exclusive}2 lock on '%1'">,
+ "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<
- "%select{reading|writing}2 variable '%0' requires locking "
- "%select{'%1'|'%1' exclusively}2">,
+def warn_variable_requires_lock_precise :
+ Warning<warn_variable_requires_lock.Text>,
InGroup<ThreadSafetyPrecise>, DefaultIgnore;
-def warn_var_deref_requires_lock_precise : Warning<
- "%select{reading|writing}2 the value pointed to by '%0' requires locking "
- "%select{'%1'|'%1' exclusively}2">,
+def warn_var_deref_requires_lock_precise :
+ Warning<warn_var_deref_requires_lock.Text>,
InGroup<ThreadSafetyPrecise>, DefaultIgnore;
-def warn_fun_requires_lock_precise : Warning<
- "calling function '%0' requires %select{shared|exclusive}2 lock on '%1'">,
+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'">;
@@ -2259,7 +2370,7 @@ def warn_impcast_float_precision : Warning<
InGroup<Conversion>, DefaultIgnore;
def warn_impcast_float_integer : Warning<
"implicit conversion turns floating-point number into integer: %0 to %1">,
- InGroup<Conversion>, DefaultIgnore;
+ InGroup<FloatConversion>, DefaultIgnore;
def warn_impcast_integer_sign : Warning<
"implicit conversion changes signedness: %0 to %1">,
InGroup<SignConversion>, DefaultIgnore;
@@ -2299,17 +2410,48 @@ def warn_impcast_null_pointer_to_integer : Warning<
def warn_impcast_floating_point_to_bool : Warning<
"implicit conversion turns floating-point number into bool: %0 to %1">,
InGroup<ImplicitConversionFloatingPointToBool>;
-def warn_impcast_function_to_bool : Warning<
- "address of function %q0 will always evaluate to 'true'">,
- InGroup<BoolConversion>;
-def note_function_to_bool_silence : Note<
+
+def warn_impcast_pointer_to_bool : Warning<
+ "address of%select{| function| array}0 '%1' will always evaluate to "
+ "'true'">,
+ 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_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_bool_call : Note<
+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,
@@ -2355,17 +2497,27 @@ def warn_attribute_protected_visibility :
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 err_unknown_machine_mode : Error<"unknown machine mode %0">;
-def err_unsupported_machine_mode : Error<"unsupported machine mode %0">;
+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 err_attr_wrong_decl : Error<
- "'%0' attribute invalid on this declaration, requires typedef or value">;
+ "%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_malloc_pointer_only : Warning<
"'malloc' attribute only applies to functions returning a pointer type">,
InGroup<IgnoredAttributes>;
@@ -2394,15 +2546,14 @@ 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 warn_attribute_ibaction: Warning<
- "ibaction attribute can only be applied to Objective-C instance methods">,
- InGroup<IgnoredAttributes>;
def err_iboutletcollection_type : Error<
"invalid type %0 as argument of iboutletcollection attribute">;
def err_iboutletcollection_builtintype : Error<
@@ -2414,8 +2565,6 @@ def warn_iboutletcollection_property_assign : Warning<
"IBOutletCollection properties should be copy/strong and not assign">,
InGroup<ObjCInvalidIBOutletProperty>;
-def err_attribute_overloadable_not_function : Error<
- "'overloadable' attribute can only be applied to a function">;
def err_attribute_overloadable_missing : Error<
"%select{overloaded function|redeclaration of}0 %1 must have the "
"'overloadable' attribute">;
@@ -2436,15 +2585,36 @@ def warn_objc_requires_super_protocol : Warning<
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>;
-def err_ns_bridged_not_interface : Error<
- "parameter of 'ns_bridged' attribute does not name an Objective-C class">;
-
// objc_bridge attribute diagnostics.
-def err_objc_bridge_not_id : Error<
- "parameter of 'objc_bridge' attribute must be a single name of an Objective-C class">;
+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_cf_bridged_not_interface : Error<
- "CF object of type %0 is bridged to '%1', which is not an Objective-C class">;
+ "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<
@@ -2452,6 +2622,18 @@ def warn_objc_invalid_bridge : Warning<
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<
@@ -2462,14 +2644,12 @@ def err_ident_list_in_fn_declaration : Error<
"a parameter list without types is only allowed in a function definition">;
def ext_param_not_declared : Extension<
"parameter %0 was not declared, defaulting to type 'int'">;
-def err_param_typedef_of_void : Error<
- "empty parameter list defined with a %select{typedef|type alias}0 of 'void' not allowed%select{ in C++|}0">;
def err_param_default_argument : Error<
"C does not support default arguments">;
def err_param_default_argument_redefinition : Error<
"redefinition of default argument">;
-def warn_param_default_argument_redefinition : ExtWarn<
- "redefinition of default argument">;
+def ext_param_default_argument_redefinition : ExtWarn<
+ "redefinition of default argument">, InGroup<Microsoft>;
def err_param_default_argument_missing : Error<
"missing default argument on parameter">;
def err_param_default_argument_missing_name : Error<
@@ -2579,6 +2759,8 @@ 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_disabled_by_enable_if_attr : Note<
+ "candidate disabled: %0">;
def note_ovl_candidate_failed_overload_resolution : Note<
"candidate template ignored: couldn't resolve reference to overloaded "
"function %0">;
@@ -2941,11 +3123,14 @@ def err_template_arg_list_different_arity : Error<
"%select{class template|function template|template template parameter"
"|template}1 %2">;
def note_template_decl_here : Note<"template is declared here">;
-def note_member_of_template_here : Note<"member is declared here">;
def err_template_arg_must_be_type : Error<
"template argument for template type parameter must be a type">;
def err_template_arg_must_be_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<Microsoft>;
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<
@@ -3059,6 +3244,9 @@ def err_pointer_to_member_oper_value_classify: Error<
def ext_ms_deref_template_argument: ExtWarn<
"non-type template argument containing a dereference operation is a "
"Microsoft extension">, InGroup<Microsoft>;
+def ext_ms_delayed_template_argument: ExtWarn<
+ "using the undeclared type %0 as a default template argument is a "
+ "Microsoft extension">, InGroup<Microsoft>;
// C++ template specialization
def err_template_spec_unknown_kind : Error<
@@ -3155,8 +3343,8 @@ 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 (with 'template<>') a member of an unspecialized "
- "template">;
+ "cannot specialize %select{|(with 'template<>') }0a member of an "
+ "unspecialized template">;
// C++ Class Template Partial Specialization
def err_default_arg_in_partial_spec : Error<
@@ -3164,6 +3352,8 @@ def err_default_arg_in_partial_spec : Error<
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">;
@@ -3173,7 +3363,7 @@ def err_partial_spec_args_match_primary_template : Error<
"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 can not be "
+ "%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">;
@@ -3194,6 +3384,9 @@ 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<
@@ -3221,6 +3414,10 @@ 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<
@@ -3273,6 +3470,9 @@ def err_nested_name_spec_non_tag : Error<
// 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<Microsoft>;
def note_previous_explicit_instantiation : Note<
"previous explicit instantiation is here">;
def ext_explicit_instantiation_after_specialization : Extension<
@@ -3368,7 +3568,7 @@ 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 warn_typename_missing : ExtWarn<
+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<
@@ -3383,11 +3583,11 @@ 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">;
+ "%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">;
+ "'%0%1' instantiated to a class template, not a function template">;
def note_referenced_class_template : Error<
- "class template declared here">;
+ "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<
@@ -3397,13 +3597,16 @@ def warn_cxx98_compat_template_outside_of_template : Warning<
InGroup<CXX98Compat>, DefaultIgnore;
def err_non_type_template_in_nested_name_specifier : Error<
- "qualified name refers into a specialization of function template %0">;
+ "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">;
@@ -3479,9 +3682,13 @@ def err_unexpected_typedef : Error<
def err_unexpected_namespace : Error<
"unexpected namespace name %0: expected expression">;
def err_undeclared_var_use : Error<"use of undeclared identifier %0">;
-def warn_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<Microsoft>;
+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<Microsoft>;
+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<Microsoft>;
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 "
@@ -3491,20 +3698,26 @@ def note_not_found_by_two_phase_lookup : Note<"%0 should be declared prior to th
def err_undeclared_use : Error<"use of undeclared %0">;
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_fwdclass_message : Warning<
- "%0 maybe deprecated because receiver type is unknown">,
+ "%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 maybe unavailable because receiver type is unknown">;
-def note_unavailable_here : Note<
- "%select{declaration|function}0 has been explicitly marked "
+ "%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}1 here">;
def note_implicitly_deleted : Note<
"explicitly defaulted function was implicitly deleted here">;
@@ -3528,6 +3741,8 @@ def note_declaration_not_a_prototype : Note<
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">;
@@ -3544,9 +3759,6 @@ def err_definition_of_explicitly_defaulted_member : Error<
def err_redefinition_extern_inline : Error<
"redefinition of a 'extern inline' function %0 is not supported in "
"%select{C99 mode|C++}1">;
-def warn_cxx98_compat_friend_redefinition : Warning<
- "friend function %0 would be implicitly redefined in C++98">,
- InGroup<CXX98Compat>, DefaultIgnore;
def note_deleted_dtor_no_operator_delete : Note<
"virtual destructor requires an unambiguous, accessible 'operator delete'">;
@@ -3584,10 +3796,10 @@ def warn_undefined_inline : Warning<"inline function %q0 is not defined">,
InGroup<DiagGroup<"undefined-inline">>;
def note_used_here : Note<"used here">;
-def warn_internal_in_extern_inline : ExtWarn<
+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 : Extension<
+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<
@@ -3595,15 +3807,15 @@ def warn_static_local_in_extern_inline : Warning<
"in different files">, InGroup<StaticLocalInInline>;
def note_convert_inline_to_static : Note<
"use 'static' to give inline function %0 internal linkage">;
-def note_internal_decl_declared_here : Note<
- "%0 declared here">;
-def warn_redefinition_of_typedef : ExtWarn<
+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<
@@ -3620,8 +3832,8 @@ 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 warn_static_non_static : ExtWarn<
- "static declaration of %0 follows non-static declaration">;
+def ext_static_non_static : Extension<
+ "redeclaring non-static %0 as static is a Microsoft extension">, InGroup<Microsoft>;
def err_non_static_static : Error<
"non-static declaration of %0 follows static declaration">;
def err_extern_non_extern : Error<
@@ -3689,17 +3901,18 @@ def warn_ivars_in_interface : Warning<
def ext_enum_value_not_int : Extension<
"ISO C restricts enumerator values to range of 'int' (%0 is too "
"%select{small|large}1)">;
-def warn_enum_too_large : Warning<
- "enumeration values exceed range of largest integer">;
-def warn_enumerator_too_large : Warning<
- "enumerator value %0 is not representable in the largest integer type">;
+def 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_illegal_constant_array_size : Extension<
"size of static array must be an integer constant expression">;
def err_vm_decl_in_file_scope : Error<
"variably modified type declaration not allowed at file scope">;
def err_vm_decl_has_extern_linkage : Error<
- "variably modified type declaration can not have 'extern' linkage">;
+ "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">;
@@ -3732,6 +3945,9 @@ def warn_typecheck_negative_array_new_size : Warning<"array size is negative">,
InGroup<BadArrayNewLength>;
def warn_typecheck_function_qualifiers : Warning<
"qualifier on function type %0 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<
@@ -3760,22 +3976,22 @@ 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 warn_excess_initializers : ExtWarn<
+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 warn_excess_initializers_in_char_array_initializer : ExtWarn<
+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 warn_initializer_string_for_char_array_too_long : ExtWarn<
+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">,
+ "missing field %0 initializer">,
InGroup<MissingFieldInitializers>, DefaultIgnore;
def warn_braces_around_scalar_init : Warning<
"braces around scalar initializer">;
-def warn_many_braces_around_scalar_init : ExtWarn<
+def ext_many_braces_around_scalar_init : ExtWarn<
"too many braces around scalar initializer">;
def ext_complex_component_init : Extension<
"complex initialization specifying real and imaginary components "
@@ -3816,8 +4032,8 @@ 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_override : Note<
- "override this message by inserting an explicit cast">;
+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<
@@ -3852,7 +4068,7 @@ def warn_unused_label : Warning<"unused label %0">,
InGroup<UnusedLabel>, DefaultIgnore;
def err_goto_into_protected_scope : Error<"goto into protected scope">;
-def warn_goto_into_protected_scope : ExtWarn<"goto into protected scope">,
+def ext_goto_into_protected_scope : ExtWarn<"goto into protected scope">,
InGroup<Microsoft>;
def warn_cxx98_compat_goto_into_protected_scope : Warning<
"goto would jump into protected scope in C++98">,
@@ -3913,6 +4129,9 @@ 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<
@@ -3954,8 +4173,8 @@ def err_flexible_array_virtual_base : Error<
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_nonpod_type : Error<
- "flexible array member %0 of non-POD element type %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>;
@@ -4224,6 +4443,8 @@ def ext_sizeof_alignof_function_type : Extension<
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}0' to a void type">;
def err_sizeof_alignof_incomplete_type : Error<
"invalid application of '%select{sizeof|alignof|vec_step}0' to an "
"incomplete type %1">;
@@ -4244,9 +4465,9 @@ 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 warn_offsetof_non_pod_type : ExtWarn<"offset of on non-POD type %0">,
+def ext_offsetof_non_pod_type : ExtWarn<"offset of on non-POD type %0">,
InGroup<InvalidOffsetof>;
-def warn_offsetof_non_standardlayout_type : ExtWarn<
+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<
@@ -4315,7 +4536,7 @@ def warn_addition_in_bitshift : Warning<
"'%1' will be evaluated first">, InGroup<ShiftOpParentheses>;
def warn_self_assignment : Warning<
- "explicitly assigning a variable of type %0 to itself">,
+ "explicitly assigning value of variable of type %0 to itself">,
InGroup<SelfAssignment>, DefaultIgnore;
def warn_string_plus_int : Warning<
@@ -4439,6 +4660,9 @@ def warn_member_extra_qualification : Warning<
"extra qualification on member %0">, InGroup<Microsoft>;
def err_member_extra_qualification : Error<
"extra qualification on member %0">;
+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">;
@@ -4505,13 +4729,12 @@ def ext_array_init_parens : ExtWarn<
def warn_deprecated_string_literal_conversion : Warning<
"conversion from string literal to %0 is deprecated">,
InGroup<CXX11CompatDeprecatedWritableStr>;
-def warn_deprecated_string_literal_conversion_c : Warning<
- "dummy warning to enable -fconst-strings">, InGroup<DeprecatedWritableStr>, DefaultIgnore;
+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 err_unsupported_global_register : Error<
- "global register variables are not supported">;
def warn_standalone_specifier : Warning<"'%0' ignored on this declaration">,
InGroup<MissingDeclarations>;
def ext_standalone_specifier : ExtWarn<"'%0' is not permitted on a declaration "
@@ -4547,6 +4770,9 @@ 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 : Extension<
+ "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<
@@ -4600,8 +4826,9 @@ 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 constant %0 with expression of type %1 is always "
- "%select{false|true}2">, InGroup<TautologicalOutOfRangeCompare>;
+ "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>;
@@ -4812,7 +5039,7 @@ def warn_register_objc_catch_parm : Warning<
def err_qualified_objc_catch_parm : Error<
"@catch parameter declarator cannot be qualified">;
def warn_objc_pointer_cxx_catch_fragile : Warning<
- "can not catch an exception thrown with @throw in C++ in the non-unified "
+ "cannot catch an exception thrown with @throw in C++ in the non-unified "
"exception model">, InGroup<ObjCNonUnifiedException>;
def err_objc_object_catch : Error<
"can't catch an Objective-C object by value">;
@@ -4925,6 +5152,8 @@ 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<
@@ -5013,7 +5242,7 @@ 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">;
+ "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">;
@@ -5139,6 +5368,9 @@ let CategoryName = "Lambda Issue" in {
"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 %0 from "
+ "parenthesized 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<
@@ -5199,9 +5431,8 @@ 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<"expected a class or namespace">;
-def err_expected_class : Error<"%0 is not a class%select{ or namespace|, "
- "namespace, or scoped enumeration}1">;
+def err_expected_class_or_namespace : Error<"%0 is not a class"
+ "%select{ or namespace|, namespace, or scoped 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<
@@ -5280,6 +5511,8 @@ def err_typecheck_missing_return_type_incompatible : Error<
"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"
@@ -5496,8 +5729,6 @@ def err_call_incomplete_return : Error<
"calling function with incomplete return type %0">;
def err_call_function_incomplete_return : Error<
"calling %0 with incomplete return type %1">;
-def note_function_with_incomplete_return_type_declared_here : Note<
- "%0 declared here">;
def err_call_incomplete_argument : Error<
"argument type %0 is incomplete">;
def err_typecheck_call_too_few_args : Error<
@@ -5553,10 +5784,6 @@ 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 note_callee_decl : Note<
- "%0 declared here">;
-def note_defined_here : Note<"%0 defined here">;
-
def err_builtin_fn_use : Error<"builtin functions must be directly called">;
def warn_call_wrong_number_of_arguments : Warning<
@@ -5590,7 +5817,10 @@ def err_atomic_op_needs_atomic_int_or_ptr : Error<
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_atomic_load_store_uses_lib : Error<
"atomic %select{load|store}0 requires runtime support that is not "
"available for this target">;
@@ -5630,6 +5860,11 @@ 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">;
@@ -5664,6 +5899,10 @@ def err_cast_pointer_from_non_pointer_int : Error<
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;
@@ -5678,10 +5917,10 @@ def ext_typecheck_cond_incompatible_operands_nonstandard : ExtWarn<
"pointer type %2">;
def err_cast_selector_expr : Error<
"cannot type cast @selector expression">;
-def warn_typecheck_cond_incompatible_pointers : ExtWarn<
+def ext_typecheck_cond_incompatible_pointers : ExtWarn<
"pointer type mismatch%diff{ ($ and $)|}0,1">,
InGroup<DiagGroup<"pointer-type-mismatch">>;
-def warn_typecheck_cond_pointer_integer_mismatch : ExtWarn<
+def ext_typecheck_cond_pointer_integer_mismatch : ExtWarn<
"pointer/integer type mismatch in conditional expression"
"%diff{ ($ and $)|}0,1">,
InGroup<DiagGroup<"conditional-type-mismatch">>;
@@ -5709,20 +5948,16 @@ def warn_unused_volatile : Warning<
InGroup<DiagGroup<"unused-volatile-lvalue">>;
def warn_unused_comparison : Warning<
- "%select{equality|inequality}0 comparison result unused">,
+ "%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_type_trait_arity : Error<
- "type trait requires %0%select{| or more}1 argument%select{|s}2; have "
- "%3 argument%s3">;
def err_dimension_expr_not_constant_integer : Error<
"dimension expression does not evaluate to a constant unsigned int">;
-def err_expected_ident_or_lparen : Error<"expected identifier or '('">;
def err_typecheck_cond_incompatible_operands_null : Error<
"non-pointer operand type %0 incompatible with %select{NULL|nullptr}1">;
@@ -5755,6 +5990,7 @@ let CategoryName = "Inline Assembly Issue" in {
"%diff{$ matching output with type $|}0,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_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_invalid_asm_cast_lvalue : Error<
@@ -5782,6 +6018,12 @@ 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">;
@@ -5898,8 +6140,6 @@ def err_reference_to_local_var_in_enclosing_lambda : Error<
def err_reference_to_local_var_in_enclosing_context : Error<
"reference to local variable %0 declared in enclosing context">;
-def note_local_variable_declared_here : Note<
- "%0 declared here">;
def err_static_data_member_not_allowed_in_local_class : Error<
"static data member %0 not allowed in local class %1">;
@@ -5974,6 +6214,9 @@ 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; "
@@ -5990,6 +6233,8 @@ def err_operator_delete_param_type : Error<
// 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
@@ -6120,12 +6365,13 @@ def warn_missing_format_string : Warning<
def warn_scanf_nonzero_width : Warning<
"zero field width in scanf format string is unused">,
InGroup<Format>;
-def warn_printf_conversion_argument_type_mismatch : Warning<
- "format specifies type %0 but the argument has type %1">,
+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_argument_needs_cast : Warning<
- "values of type '%0' should not be used as format arguments; add an explicit "
- "cast to %1 instead">,
+ "%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)">,
@@ -6150,6 +6396,8 @@ 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>;
@@ -6165,12 +6413,12 @@ def warn_printf_nonsensical_flag: Warning<
def warn_format_nonsensical_length: Warning<
"length modifier '%0' results in undefined behavior or no effect with '%1' conversion specifier">,
InGroup<Format>;
-def warn_format_non_standard_positional_arg: ExtWarn<
+def warn_format_non_standard_positional_arg: Warning<
"positional arguments are not supported by ISO C">, InGroup<FormatNonStandard>, DefaultIgnore;
-def warn_format_non_standard: ExtWarn<
+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: ExtWarn<
+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<
@@ -6186,6 +6434,9 @@ def note_printf_c_str: Note<"did you mean to call the %0 method?">;
def warn_null_arg : Warning<
"null passed to a callee which 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 : Warning<
@@ -6230,11 +6481,17 @@ def note_ref_subobject_of_member_declared_here : Note<
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<DiagGroup<"string-compare">>;
+ InGroup<StringCompare>;
def warn_identity_field_assign : Warning<
"assigning %select{field|instance variable}0 to itself">,
@@ -6252,7 +6509,7 @@ 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 "
+ "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>;
@@ -6299,11 +6556,17 @@ 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">;
+ "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>;
@@ -6434,6 +6697,8 @@ def ext_return_has_void_expr : Extension<
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>;
@@ -6484,9 +6749,20 @@ 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_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">;
@@ -6572,9 +6848,6 @@ def error_private_ivar_access : Error<"instance variable %0 is private">,
def error_protected_ivar_access : Error<"instance variable %0 is protected">,
AccessControl;
def warn_maynot_respond : Warning<"%0 may not respond to %1">;
-def warn_attribute_method_def : Warning<
- "attributes on method implementation and its declaration must match">,
- InGroup<DiagGroup<"mismatched-method-attributes">>;
def ext_typecheck_base_super : Warning<
"method parameter type "
"%diff{$ does not match super class method parameter type $|"
@@ -6587,6 +6860,8 @@ 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<
@@ -6644,7 +6919,7 @@ 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 unsupported for this kind of declaration">;
+ "%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<
@@ -6667,6 +6942,8 @@ 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_static_function_scope : Error<
"variables in function scope cannot be declared static">;
def err_opencl_bitfields : Error<
@@ -6696,6 +6973,12 @@ def err_wrong_sampler_addressspace: Error<
def err_opencl_global_invalid_addr_space : Error<
"global variables must have a constant address space qualifier">;
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">;
} // end of sema category
let CategoryName = "OpenMP Issue" in {
@@ -6719,24 +7002,147 @@ 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_unexpected_clause_value : Error <
+def err_omp_lastprivate_incomplete_type : Error<
+ "a lastprivate variable with incomplete type %0">;
+def err_omp_reduction_incomplete_type : Error<
+ "a reduction variable with incomplete type %0">;
+def err_omp_unexpected_clause_value : Error<
"expected %0 in OpenMP clause '%1'">;
-def err_omp_expected_var_name : Error <
+def err_omp_expected_var_name : Error<
"expected variable name">;
-def err_omp_required_method : Error <
+def err_omp_required_method : Error<
"%0 variable must have an accessible, unambiguous %select{default constructor|copy constructor|copy assignment operator|'%2'|destructor}1">;
+def err_omp_task_predetermined_firstprivate_required_method : Error<
+ "predetermined as a firstprivate in a task construct variable must have an accessible, unambiguous %select{copy constructor|destructor}0">;
def err_omp_clause_ref_type_arg : Error<
"arguments of OpenMP clause '%0' cannot be of reference type %1">;
+def err_omp_task_predetermined_firstprivate_ref_type_arg : Error<
+ "predetermined as a firstprivate in a task construct variable cannot be of reference type %0">;
def err_omp_threadprivate_incomplete_type : Error<
"threadprivate variable with incomplete type %0">;
-def err_omp_no_dsa_for_variable : Error <
+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 note_omp_explicit_dsa : Note <
+def note_omp_explicit_dsa : Note<
"defined as %0">;
-def note_omp_predetermined_dsa : Note <
- "predetermined 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_expr : Note<
+ "as specified in 'collapse' clause">;
+def err_omp_negative_expression_in_clause : Error<
+ "argument to '%0' clause must be a positive 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_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 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 must be of the 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_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 err_omp_unknown_reduction_identifier : Error<
+ "incorrect reduction identifier, expected one of '+', '-', '*', '&', '|', '^', '&&', '||', 'min' or 'max'">;
+def err_omp_reduction_type_array : Error<
+ "a reduction variable 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<
+ "variable of type %0 is not valid for specified reduction operation">;
+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?}2">;
+def err_omp_prohibited_region_simd : Error<
+ "OpenMP constructs may not be nested inside a simd 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">;
} // end of OpenMP category
let CategoryName = "Related Result Type Issue" in {
@@ -6778,6 +7184,16 @@ def err_module_private_declaration : Error<
"declaration of %0 must be imported from module '%1' before it is required">;
def err_module_private_definition : Error<
"definition of %0 must be imported from module '%1' before it is required">;
+def err_module_import_in_extern_c : Error<
+ "import of C++ module '%0' appears within extern \"C\" language linkage "
+ "specification">;
+def note_module_import_in_extern_c : Note<
+ "extern \"C\" language linkage specification begins here">;
+def err_module_import_not_at_top_level : Error<
+ "import of module '%0' appears within %1">;
+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'">;
}
let CategoryName = "Documentation Issue" in {
@@ -6785,4 +7201,15 @@ 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
+
} // end of sema component.
diff --git a/include/clang/Basic/DiagnosticSerializationKinds.td b/include/clang/Basic/DiagnosticSerializationKinds.td
index 81509cc18821..be9d2bdbd2de 100644
--- a/include/clang/Basic/DiagnosticSerializationKinds.td
+++ b/include/clang/Basic/DiagnosticSerializationKinds.td
@@ -8,6 +8,7 @@
//===----------------------------------------------------------------------===//
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'">;
@@ -22,6 +23,8 @@ def err_fe_pch_file_modified : Error<
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'">;
@@ -36,16 +39,23 @@ 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 warn_pch_version_too_old : Error<
+def err_pch_version_too_old : Error<
"PCH file uses an older PCH format that is no longer supported">;
-def warn_pch_version_too_new : Error<
+def err_pch_version_too_new : Error<
"PCH file uses a newer PCH format that cannot be read">;
-def warn_pch_different_branch : Error<
+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_imported_module_not_found : Error<
+ "module '%0' imported by AST file '%1' not found">, 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 warn_module_conflict : Warning<
"module '%0' conflicts with already-imported module '%1': %2">,
InGroup<ModuleConflict>;
@@ -75,5 +85,14 @@ 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">;
+
+} // let CategoryName
+} // let Component
-}
diff --git a/include/clang/Basic/FileManager.h b/include/clang/Basic/FileManager.h
index 255eee3084b5..0ad53c4df5ac 100644
--- a/include/clang/Basic/FileManager.h
+++ b/include/clang/Basic/FileManager.h
@@ -17,16 +17,17 @@
#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/OwningPtr.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringMap.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/Support/Allocator.h"
-#include "llvm/Support/FileSystem.h"
+#include <memory>
// FIXME: Enhance libsystem to support inode and other fields in stat.
#include <sys/types.h>
+#include <map>
#ifdef _MSC_VER
typedef unsigned short mode_t;
@@ -48,17 +49,17 @@ class DirectoryEntry {
const char *Name; // Name of the directory.
friend class FileManager;
public:
- DirectoryEntry() : Name(0) {}
+ 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 'FD' member is valid, then this FileEntry has an open file
+/// 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.
+ std::string 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.
@@ -66,33 +67,34 @@ class FileEntry {
llvm::sys::fs::UniqueID UniqueID;
bool IsNamedPipe;
bool InPCH;
+ bool IsValid; // Is this \c FileEntry initialized and valid?
- /// FD - The file descriptor for the file entry if it is opened and owned
- /// by the FileEntry. If not, this is set to -1.
- mutable int FD;
+ /// \brief The open file, if it is owned by the \p FileEntry.
+ mutable std::unique_ptr<vfs::File> File;
friend class FileManager;
-public:
- FileEntry(llvm::sys::fs::UniqueID UniqueID, bool IsNamedPipe, bool InPCH)
- : Name(0), UniqueID(UniqueID), IsNamedPipe(IsNamedPipe), InPCH(InPCH),
- FD(-1) {}
- // Add a default constructor for use with llvm::StringMap
- FileEntry()
- : Name(0), UniqueID(0, 0), IsNamedPipe(false), InPCH(false), FD(-1) {}
-
- FileEntry(const FileEntry &FE) {
- memcpy(this, &FE, sizeof(FE));
- assert(FD == -1 && "Cannot copy a file-owning FileEntry");
+ void closeFile() const {
+ File.reset(); // rely on destructor to close File
}
- void operator=(const FileEntry &FE) {
- memcpy(this, &FE, sizeof(FE));
- assert(FD == -1 && "Cannot assign a file-owning FileEntry");
- }
+ void operator=(const FileEntry &) LLVM_DELETED_FUNCTION;
- ~FileEntry();
+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; }
+ const char *getName() const { return Name.c_str(); }
+ 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; }
@@ -119,16 +121,14 @@ struct FileData;
/// as a single file.
///
class FileManager : public RefCountedBase<FileManager> {
+ IntrusiveRefCntPtr<vfs::FileSystem> FS;
FileSystemOptions FileSystemOpts;
- class UniqueDirContainer;
- class UniqueFileContainer;
-
/// \brief Cache for existing real directories.
- UniqueDirContainer &UniqueRealDirs;
+ std::map<llvm::sys::fs::UniqueID, DirectoryEntry> UniqueRealDirs;
/// \brief Cache for existing real files.
- UniqueFileContainer &UniqueRealFiles;
+ std::map<llvm::sys::fs::UniqueID, FileEntry> UniqueRealFiles;
/// \brief The virtual directories that we have allocated.
///
@@ -169,17 +169,18 @@ class FileManager : public RefCountedBase<FileManager> {
unsigned NumDirCacheMisses, NumFileCacheMisses;
// Caching.
- OwningPtr<FileSystemStatCache> StatCache;
+ std::unique_ptr<FileSystemStatCache> StatCache;
bool getStatValue(const char *Path, FileData &Data, bool isFile,
- int *FileDescriptor);
+ 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);
+ FileManager(const FileSystemOptions &FileSystemOpts,
+ IntrusiveRefCntPtr<vfs::FileSystem> FS = nullptr);
~FileManager();
/// \brief Installs the provided FileSystemStatCache object within
@@ -226,6 +227,10 @@ public:
/// \brief Returns the current file system options
const FileSystemOptions &getFileSystemOptions() { 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.
///
@@ -236,17 +241,20 @@ public:
/// \brief Open the specified file as a MemoryBuffer, returning a new
/// MemoryBuffer if successful, otherwise returning null.
llvm::MemoryBuffer *getBufferForFile(const FileEntry *Entry,
- std::string *ErrorStr = 0,
- bool isVolatile = false);
+ std::string *ErrorStr = nullptr,
+ bool isVolatile = false,
+ bool ShouldCloseOpenFile = true);
llvm::MemoryBuffer *getBufferForFile(StringRef Filename,
- std::string *ErrorStr = 0);
+ std::string *ErrorStr = nullptr);
/// \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,
- llvm::sys::fs::file_status &Result);
+ vfs::Status &Result);
/// \brief Remove the real file \p Entry from the cache.
void invalidateCache(const FileEntry *Entry);
diff --git a/include/clang/Basic/FileSystemStatCache.h b/include/clang/Basic/FileSystemStatCache.h
index 23d82569437f..9be8b1074b2f 100644
--- a/include/clang/Basic/FileSystemStatCache.h
+++ b/include/clang/Basic/FileSystemStatCache.h
@@ -16,21 +16,30 @@
#define LLVM_CLANG_FILESYSTEMSTATCACHE_H
#include "clang/Basic/LLVM.h"
-#include "llvm/ADT/OwningPtr.h"
#include "llvm/ADT/StringMap.h"
#include "llvm/Support/FileSystem.h"
-#include <sys/stat.h>
-#include <sys/types.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'
@@ -39,8 +48,8 @@ struct FileData {
class FileSystemStatCache {
virtual void anchor();
protected:
- OwningPtr<FileSystemStatCache> NextStatCache;
-
+ std::unique_ptr<FileSystemStatCache> NextStatCache;
+
public:
virtual ~FileSystemStatCache() {}
@@ -57,10 +66,11 @@ public:
/// 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 FileDescriptor with a valid
- /// descriptor and the client guarantees that it will close it.
+ /// 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,
- int *FileDescriptor, FileSystemStatCache *Cache);
+ 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.
@@ -74,21 +84,24 @@ public:
/// \brief Retrieve the next stat call cache in the chain, transferring
/// ownership of this cache (and, transitively, all of the remaining caches)
/// to the caller.
- FileSystemStatCache *takeNextStatCache() { return NextStatCache.take(); }
-
+ FileSystemStatCache *takeNextStatCache() { return NextStatCache.release(); }
+
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,
- int *FileDescriptor) = 0;
+ std::unique_ptr<vfs::File> *F,
+ vfs::FileSystem &FS) = 0;
LookupResult statChained(const char *Path, FileData &Data, bool isFile,
- int *FileDescriptor) {
+ std::unique_ptr<vfs::File> *F, vfs::FileSystem &FS) {
if (FileSystemStatCache *Next = getNextStatCache())
- return Next->getStat(Path, Data, isFile, FileDescriptor);
+ 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, FileDescriptor, 0) ? CacheMissing
- : CacheExists;
+ return get(Path, Data, isFile, F, nullptr, FS) ? CacheMissing : CacheExists;
}
};
@@ -106,8 +119,9 @@ public:
iterator begin() const { return StatCalls.begin(); }
iterator end() const { return StatCalls.end(); }
- virtual LookupResult getStat(const char *Path, FileData &Data, bool isFile,
- int *FileDescriptor);
+ LookupResult getStat(const char *Path, FileData &Data, bool isFile,
+ std::unique_ptr<vfs::File> *F,
+ vfs::FileSystem &FS) override;
};
} // end namespace clang
diff --git a/include/clang/Basic/IdentifierTable.h b/include/clang/Basic/IdentifierTable.h
index 304ff364bfc9..0c278a17a32d 100644
--- a/include/clang/Basic/IdentifierTable.h
+++ b/include/clang/Basic/IdentifierTable.h
@@ -17,12 +17,9 @@
#define LLVM_CLANG_BASIC_IDENTIFIERTABLE_H
#include "clang/Basic/LLVM.h"
-#include "clang/Basic/OperatorKinds.h"
#include "clang/Basic/TokenKinds.h"
-#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/StringMap.h"
#include "llvm/ADT/StringRef.h"
-#include "llvm/Support/PointerLikeTypeTraits.h"
#include <cassert>
#include <string>
@@ -428,7 +425,7 @@ 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 = 0);
+ IdentifierInfoLookup* externalLookup = nullptr);
/// \brief Set the external identifier lookup mechanism.
void setExternalIdentifierLookup(IdentifierInfoLookup *IILookup) {
@@ -625,7 +622,7 @@ class Selector {
IdentifierInfo *getAsIdentifierInfo() const {
if (getIdentifierInfoFlag() < MultiArg)
return reinterpret_cast<IdentifierInfo *>(InfoPtr & ~ArgFlags);
- return 0;
+ return nullptr;
}
MultiKeywordSelector *getMultiKeywordSelector() const {
return reinterpret_cast<MultiKeywordSelector *>(InfoPtr & ~ArgFlags);
@@ -697,9 +694,11 @@ public:
/// \brief Derive the full selector name (e.g. "foo:bar:") and return
/// it as an std::string.
- // FIXME: Add a print method that uses a raw_ostream.
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);
@@ -812,6 +811,8 @@ struct DenseMapInfo<clang::Selector> {
template <>
struct isPodLike<clang::Selector> { static const bool value = true; };
+template <typename T> class PointerLikeTypeTraits;
+
template<>
class PointerLikeTypeTraits<clang::Selector> {
public:
diff --git a/include/clang/Basic/LLVM.h b/include/clang/Basic/LLVM.h
index 306c75e57a9f..5a71fa85b3d9 100644
--- a/include/clang/Basic/LLVM.h
+++ b/include/clang/Basic/LLVM.h
@@ -8,7 +8,7 @@
//===----------------------------------------------------------------------===//
//
/// \file
-/// \brief Forward declares and imports various common LLVM datatypes that
+/// \brief Forward-declares and imports various common LLVM datatypes that
/// clang wants to use unqualified.
///
//===----------------------------------------------------------------------===//
@@ -29,7 +29,7 @@ namespace llvm {
class StringRef;
class Twine;
template<typename T> class ArrayRef;
- template<typename T> class OwningPtr;
+ template<typename T> class MutableArrayRef;
template<unsigned InternalLen> class SmallString;
template<typename T, unsigned N> class SmallVector;
template<typename T> class SmallVectorImpl;
@@ -63,7 +63,7 @@ namespace clang {
using llvm::StringRef;
using llvm::Twine;
using llvm::ArrayRef;
- using llvm::OwningPtr;
+ using llvm::MutableArrayRef;
using llvm::SmallString;
using llvm::SmallVector;
using llvm::SmallVectorImpl;
diff --git a/include/clang/Basic/LangOptions.def b/include/clang/Basic/LangOptions.def
index 5a1025cba7ec..a297a4c219cf 100644
--- a/include/clang/Basic/LangOptions.def
+++ b/include/clang/Basic/LangOptions.def
@@ -43,13 +43,14 @@
LANGOPT(C99 , 1, 0, "C99")
LANGOPT(C11 , 1, 0, "C11")
-LANGOPT(MicrosoftExt , 1, 0, "Microsoft extensions")
-LANGOPT(MicrosoftMode , 1, 0, "Microsoft compatibility mode")
+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++0x")
+LANGOPT(CPlusPlus11 , 1, 0, "C++11")
LANGOPT(CPlusPlus1y , 1, 0, "C++1y")
+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,
@@ -61,6 +62,7 @@ BENIGN_LANGOPT(ObjCInferRelatedResultType , 1, 1,
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")
BENIGN_LANGOPT(DollarIdents , 1, 1, "'$' in identifiers")
BENIGN_LANGOPT(AsmPreprocessor, 1, 0, "preprocessor in asm mode")
@@ -82,6 +84,7 @@ 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")
@@ -95,6 +98,9 @@ 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")
LANGOPT(ModulesDeclUse , 1, 0, "require declaration of module uses")
+LANGOPT(ModulesSearchAll , 1, 1, "search even non-imported modules to find unresolved references")
+LANGOPT(ModulesStrictDeclUse, 1, 0, "require declaration of module uses and all headers to be in modules")
+LANGOPT(ModulesErrorRecovery, 1, 1, "automatically import modules as needed when performing error recovery")
LANGOPT(Optimize , 1, 0, "__OPTIMIZE__ predefined macro")
LANGOPT(OptimizeSize , 1, 0, "__OPTIMIZE_SIZE__ predefined macro")
LANGOPT(Static , 1, 0, "__STATIC__ predefined macro (as opposed to __DYNAMIC__)")
@@ -113,6 +119,7 @@ BENIGN_LANGOPT(ObjCGCBitmapPrint , 1, 0, "printing of GC's bitmap layout for __w
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")
@@ -173,12 +180,12 @@ 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(MSCVersion, 32, 0,
- "version of Microsoft Visual C/C++")
+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")
-BENIGN_LANGOPT(RetainCommentsFromSystemHeaders, 1, 0, "retain documentation comments from system headers in the AST")
+LANGOPT(RetainCommentsFromSystemHeaders, 1, 0, "retain documentation comments from system headers in the AST")
#undef LANGOPT
#undef VALUE_LANGOPT
diff --git a/include/clang/Basic/LangOptions.h b/include/clang/Basic/LangOptions.h
index d4e8b4eb5bad..9bffc7cb18cf 100644
--- a/include/clang/Basic/LangOptions.h
+++ b/include/clang/Basic/LangOptions.h
@@ -19,7 +19,6 @@
#include "clang/Basic/LLVM.h"
#include "clang/Basic/ObjCRuntime.h"
#include "clang/Basic/Visibility.h"
-#include "llvm/ADT/IntrusiveRefCntPtr.h"
#include <string>
namespace clang {
@@ -53,12 +52,12 @@ protected:
/// \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 RefCountedBase<LangOptions>, public LangOptionsBase {
+class LangOptions : public LangOptionsBase {
public:
typedef clang::Visibility Visibility;
enum GCMode { NonGC, GCOnly, HybridGC };
- enum StackProtectorMode { SSPOff, SSPOn, SSPReq };
+ enum StackProtectorMode { SSPOff, SSPOn, SSPStrong, SSPReq };
enum SignedOverflowBehaviorTy {
SOB_Undefined, // Default C standard behavior.
@@ -66,6 +65,13 @@ public:
SOB_Trapping // -ftrapv
};
+ enum PragmaMSPointersToMembersKind {
+ PPTMK_BestCase,
+ PPTMK_FullGeneralitySingleInheritance,
+ PPTMK_FullGeneralityMultipleInheritance,
+ PPTMK_FullGeneralityVirtualInheritance
+ };
+
enum AddrSpaceMapMangling { ASMM_Target, ASMM_On, ASMM_Off };
public:
diff --git a/include/clang/Basic/Linkage.h b/include/clang/Basic/Linkage.h
index 699620784ecd..f3b47699cf62 100644
--- a/include/clang/Basic/Linkage.h
+++ b/include/clang/Basic/Linkage.h
@@ -18,7 +18,7 @@ namespace clang {
/// \brief Describes the different kinds of linkage
/// (C++ [basic.link], C99 6.2.2) that an entity may have.
-enum Linkage {
+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,
@@ -59,11 +59,10 @@ enum LanguageLinkage {
/// This is relevant to CodeGen and AST file reading.
enum GVALinkage {
GVA_Internal,
- GVA_C99Inline,
- GVA_CXXInline,
+ GVA_AvailableExternally,
+ GVA_DiscardableODR,
GVA_StrongExternal,
- GVA_TemplateInstantiation,
- GVA_ExplicitTemplateInstantiation
+ GVA_StrongODR
};
inline bool isExternallyVisible(Linkage L) {
diff --git a/include/clang/Basic/Makefile b/include/clang/Basic/Makefile
index 6a3313325216..5579a9990051 100644
--- a/include/clang/Basic/Makefile
+++ b/include/clang/Basic/Makefile
@@ -6,6 +6,7 @@ BUILT_SOURCES = \
DiagnosticFrontendKinds.inc DiagnosticLexKinds.inc \
DiagnosticParseKinds.inc DiagnosticSemaKinds.inc \
DiagnosticSerializationKinds.inc \
+ AttrHasAttributeImpl.inc \
DiagnosticIndexName.inc DiagnosticGroups.inc AttrList.inc arm_neon.inc \
Version.inc
@@ -48,9 +49,16 @@ $(ObjDir)/AttrList.inc.tmp : Attr.td $(CLANG_TBLGEN) $(ObjDir)/.dir
$(Verb) $(ClangTableGen) -gen-clang-attr-list -o $(call SYSPATH, $@) \
-I $(PROJ_SRC_DIR)/../.. $<
+$(ObjDir)/AttrHasAttributeImpl.inc.tmp : Attr.td $(CLANG_TBLGEN) \
+ $(ObjDir)/.dir
+ $(Echo) "Building Clang __has_attribute implementation with tblgen"
+ $(Verb) $(ClangTableGen) -gen-clang-attr-has-attribute-impl -o $(call SYSPATH, $@) \
+ -I $(PROJ_SRC_DIR)/../../ $<
+
$(ObjDir)/arm_neon.inc.tmp : arm_neon.td $(CLANG_TBLGEN) $(ObjDir)/.dir
$(Echo) "Building Clang arm_neon.inc with tblgen"
- $(Verb) $(ClangTableGen) -gen-arm-neon-sema -o $(call SYSPATH, $@) $<
+ $(Verb) $(ClangTableGen) -gen-arm-neon-sema -o $(call SYSPATH, $@) \
+ -I $(PROJ_SRC_DIR)/../.. $<
$(ObjDir)/Version.inc.tmp : Version.inc.in Makefile $(LLVM_OBJ_ROOT)/Makefile.config $(ObjDir)/.dir
$(Echo) "Updating Clang version info."
diff --git a/include/clang/Basic/Module.h b/include/clang/Basic/Module.h
index e8d774e1eb54..9b66840ba412 100644
--- a/include/clang/Basic/Module.h
+++ b/include/clang/Basic/Module.h
@@ -51,10 +51,21 @@ public:
/// \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 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
+ /// \c ModuleMap will be globally unique for top-level modules. In the case of
+ /// inferred modules, \c ModuleMap will contain the module map that allowed
+ /// the inference (e.g. contained 'Module *') rather than the virtual
+ /// inferred module map file.
+ const FileEntry *ModuleMap;
/// \brief The umbrella header or directory.
llvm::PointerUnion<const DirectoryEntry *, const FileEntry *> Umbrella;
@@ -88,7 +99,19 @@ public:
SmallVector<const FileEntry *, 2> ExcludedHeaders;
/// \brief The headers that are private to this module.
- llvm::SmallVector<const FileEntry *, 2> PrivateHeaders;
+ SmallVector<const FileEntry *, 2> PrivateHeaders;
+
+ /// \brief Information about a header directive as found in the module map
+ /// file.
+ struct HeaderDirective {
+ 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<HeaderDirective, 1> MissingHeaders;
/// \brief An individual requirement: a feature name and a flag indicating
/// the required state of that feature.
@@ -100,8 +123,13 @@ public:
/// will be false to indicate that this (sub)module is not available.
SmallVector<Requirement, 2> Requirements;
- /// \brief Whether this module is available in the current
- /// translation unit.
+ /// \brief Whether this module is missing a feature from \c Requirements.
+ unsigned IsMissingRequirement : 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.
@@ -116,7 +144,15 @@ public:
/// \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.
///
@@ -148,11 +184,14 @@ public:
MacrosVisible,
/// \brief All of the names in this module are visible.
AllVisible
- };
-
- ///\ brief The visibility of names within this particular module.
+ };
+
+ /// \brief The visibility of names within this particular module.
NameVisibilityKind NameVisibility;
+ /// \brief The location at which macros within this module became visible.
+ SourceLocation MacroVisibilityLoc;
+
/// \brief The location of the inferred submodule.
SourceLocation InferredSubmoduleLoc;
@@ -243,19 +282,11 @@ public:
/// \brief The list of conflicts.
std::vector<Conflict> Conflicts;
- /// \brief Construct a top-level module.
- explicit Module(StringRef Name, SourceLocation DefinitionLoc,
- bool IsFramework)
- : Name(Name), DefinitionLoc(DefinitionLoc), Parent(0),Umbrella(),ASTFile(0),
- IsAvailable(true), IsFromModuleFile(false), IsFramework(IsFramework),
- IsExplicit(false), IsSystem(false),
- InferSubmodules(false), InferExplicitSubmodules(false),
- InferExportWildcard(false), ConfigMacrosExhaustive(false),
- NameVisibility(Hidden) { }
-
/// \brief Construct a new module or submodule.
- Module(StringRef Name, SourceLocation DefinitionLoc, Module *Parent,
- bool IsFramework, bool IsExplicit);
+ ///
+ /// For an explanation of \p ModuleMap, see Module::ModuleMap.
+ Module(StringRef Name, SourceLocation DefinitionLoc, Module *Parent,
+ const FileEntry *ModuleMap, bool IsFramework, bool IsExplicit);
~Module();
@@ -276,14 +307,15 @@ public:
/// this module.
bool isAvailable(const LangOptions &LangOpts,
const TargetInfo &Target,
- Requirement &Req) const;
+ Requirement &Req,
+ HeaderDirective &MissingHeader) const;
/// \brief Determine whether this module is a submodule.
- bool isSubModule() const { return Parent != 0; }
+ bool isSubModule() const { return Parent != nullptr; }
/// \brief Determine whether this module is a submodule of the given other
/// module.
- bool isSubModuleOf(Module *Other) const;
+ 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
@@ -330,7 +362,8 @@ public:
/// \brief Set the serialized AST file for the top-level module of this module.
void setASTFile(const FileEntry *File) {
- assert((getASTFile() == 0 || getASTFile() == File) && "file path changed");
+ assert((File == nullptr || getASTFile() == nullptr ||
+ getASTFile() == File) && "file path changed");
getTopLevelModule()->ASTFile = File;
}
@@ -382,6 +415,9 @@ public:
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.
@@ -389,6 +425,10 @@ public:
/// \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();
diff --git a/include/clang/Basic/ObjCRuntime.h b/include/clang/Basic/ObjCRuntime.h
index 4c6449750373..fa375f4e183e 100644
--- a/include/clang/Basic/ObjCRuntime.h
+++ b/include/clang/Basic/ObjCRuntime.h
@@ -99,6 +99,11 @@ public:
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;
}
diff --git a/include/clang/Basic/OnDiskHashTable.h b/include/clang/Basic/OnDiskHashTable.h
deleted file mode 100644
index ee301237f91f..000000000000
--- a/include/clang/Basic/OnDiskHashTable.h
+++ /dev/null
@@ -1,485 +0,0 @@
-//===--- OnDiskHashTable.h - On-Disk Hash Table Implementation --*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-///
-/// \file
-/// \brief Defines facilities for reading and writing on-disk hash tables.
-///
-//===----------------------------------------------------------------------===//
-#ifndef LLVM_CLANG_BASIC_ON_DISK_HASH_TABLE_H
-#define LLVM_CLANG_BASIC_ON_DISK_HASH_TABLE_H
-
-#include "clang/Basic/LLVM.h"
-#include "llvm/Support/Allocator.h"
-#include "llvm/Support/DataTypes.h"
-#include "llvm/Support/Host.h"
-#include "llvm/Support/MathExtras.h"
-#include "llvm/Support/raw_ostream.h"
-#include <cassert>
-#include <cstdlib>
-
-namespace clang {
-
-namespace io {
-
-typedef uint32_t Offset;
-
-inline void Emit8(raw_ostream& Out, uint32_t V) {
- Out << (unsigned char)(V);
-}
-
-inline void Emit16(raw_ostream& Out, uint32_t V) {
- Out << (unsigned char)(V);
- Out << (unsigned char)(V >> 8);
- assert((V >> 16) == 0);
-}
-
-inline void Emit24(raw_ostream& Out, uint32_t V) {
- Out << (unsigned char)(V);
- Out << (unsigned char)(V >> 8);
- Out << (unsigned char)(V >> 16);
- assert((V >> 24) == 0);
-}
-
-inline void Emit32(raw_ostream& Out, uint32_t V) {
- Out << (unsigned char)(V);
- Out << (unsigned char)(V >> 8);
- Out << (unsigned char)(V >> 16);
- Out << (unsigned char)(V >> 24);
-}
-
-inline void Emit64(raw_ostream& Out, uint64_t V) {
- Out << (unsigned char)(V);
- Out << (unsigned char)(V >> 8);
- Out << (unsigned char)(V >> 16);
- Out << (unsigned char)(V >> 24);
- Out << (unsigned char)(V >> 32);
- Out << (unsigned char)(V >> 40);
- Out << (unsigned char)(V >> 48);
- Out << (unsigned char)(V >> 56);
-}
-
-inline void Pad(raw_ostream& Out, unsigned A) {
- Offset off = (Offset) Out.tell();
- for (uint32_t n = llvm::OffsetToAlignment(off, A); n; --n)
- Emit8(Out, 0);
-}
-
-inline uint16_t ReadUnalignedLE16(const unsigned char *&Data) {
- uint16_t V = ((uint16_t)Data[0]) |
- ((uint16_t)Data[1] << 8);
- Data += 2;
- return V;
-}
-
-inline uint32_t ReadUnalignedLE32(const unsigned char *&Data) {
- uint32_t V = ((uint32_t)Data[0]) |
- ((uint32_t)Data[1] << 8) |
- ((uint32_t)Data[2] << 16) |
- ((uint32_t)Data[3] << 24);
- Data += 4;
- return V;
-}
-
-inline uint64_t ReadUnalignedLE64(const unsigned char *&Data) {
- uint64_t V = ((uint64_t)Data[0]) |
- ((uint64_t)Data[1] << 8) |
- ((uint64_t)Data[2] << 16) |
- ((uint64_t)Data[3] << 24) |
- ((uint64_t)Data[4] << 32) |
- ((uint64_t)Data[5] << 40) |
- ((uint64_t)Data[6] << 48) |
- ((uint64_t)Data[7] << 56);
- Data += 8;
- return V;
-}
-
-inline uint32_t ReadLE32(const unsigned char *&Data) {
- // Hosts that directly support little-endian 32-bit loads can just
- // use them. Big-endian hosts need a bswap.
- uint32_t V = *((const uint32_t*)Data);
- if (llvm::sys::IsBigEndianHost)
- V = llvm::ByteSwap_32(V);
- Data += 4;
- return V;
-}
-
-} // end namespace io
-
-template<typename Info>
-class OnDiskChainedHashTableGenerator {
- unsigned NumBuckets;
- unsigned NumEntries;
- llvm::BumpPtrAllocator BA;
-
- class Item {
- public:
- typename Info::key_type key;
- typename Info::data_type data;
- Item *next;
- const uint32_t hash;
-
- Item(typename Info::key_type_ref k, typename Info::data_type_ref d,
- Info &InfoObj)
- : key(k), data(d), next(0), hash(InfoObj.ComputeHash(k)) {}
- };
-
- class Bucket {
- public:
- io::Offset off;
- Item* head;
- unsigned length;
-
- Bucket() {}
- };
-
- Bucket* Buckets;
-
-private:
- void insert(Bucket* b, size_t size, Item* E) {
- unsigned idx = E->hash & (size - 1);
- Bucket& B = b[idx];
- E->next = B.head;
- ++B.length;
- B.head = E;
- }
-
- void resize(size_t newsize) {
- Bucket* newBuckets = (Bucket*) std::calloc(newsize, sizeof(Bucket));
- // Populate newBuckets with the old entries.
- for (unsigned i = 0; i < NumBuckets; ++i)
- for (Item* E = Buckets[i].head; E ; ) {
- Item* N = E->next;
- E->next = 0;
- insert(newBuckets, newsize, E);
- E = N;
- }
-
- free(Buckets);
- NumBuckets = newsize;
- Buckets = newBuckets;
- }
-
-public:
-
- void insert(typename Info::key_type_ref key,
- typename Info::data_type_ref data) {
- Info InfoObj;
- insert(key, data, InfoObj);
- }
-
- void insert(typename Info::key_type_ref key,
- typename Info::data_type_ref data, Info &InfoObj) {
-
- ++NumEntries;
- if (4*NumEntries >= 3*NumBuckets) resize(NumBuckets*2);
- insert(Buckets, NumBuckets, new (BA.Allocate<Item>()) Item(key, data,
- InfoObj));
- }
-
- io::Offset Emit(raw_ostream &out) {
- Info InfoObj;
- return Emit(out, InfoObj);
- }
-
- io::Offset Emit(raw_ostream &out, Info &InfoObj) {
- using namespace clang::io;
-
- // Emit the payload of the table.
- for (unsigned i = 0; i < NumBuckets; ++i) {
- Bucket& B = Buckets[i];
- if (!B.head) continue;
-
- // Store the offset for the data of this bucket.
- B.off = out.tell();
- assert(B.off && "Cannot write a bucket at offset 0. Please add padding.");
-
- // Write out the number of items in the bucket.
- Emit16(out, B.length);
- assert(B.length != 0 && "Bucket has a head but zero length?");
-
- // Write out the entries in the bucket.
- for (Item *I = B.head; I ; I = I->next) {
- Emit32(out, I->hash);
- const std::pair<unsigned, unsigned>& Len =
- InfoObj.EmitKeyDataLength(out, I->key, I->data);
- InfoObj.EmitKey(out, I->key, Len.first);
- InfoObj.EmitData(out, I->key, I->data, Len.second);
- }
- }
-
- // Emit the hashtable itself.
- Pad(out, 4);
- io::Offset TableOff = out.tell();
- Emit32(out, NumBuckets);
- Emit32(out, NumEntries);
- for (unsigned i = 0; i < NumBuckets; ++i) Emit32(out, Buckets[i].off);
-
- return TableOff;
- }
-
- OnDiskChainedHashTableGenerator() {
- NumEntries = 0;
- NumBuckets = 64;
- // Note that we do not need to run the constructors of the individual
- // Bucket objects since 'calloc' returns bytes that are all 0.
- Buckets = (Bucket*) std::calloc(NumBuckets, sizeof(Bucket));
- }
-
- ~OnDiskChainedHashTableGenerator() {
- std::free(Buckets);
- }
-};
-
-template<typename Info>
-class OnDiskChainedHashTable {
- const unsigned NumBuckets;
- const unsigned NumEntries;
- const unsigned char* const Buckets;
- const unsigned char* const Base;
- Info InfoObj;
-
-public:
- typedef typename Info::internal_key_type internal_key_type;
- typedef typename Info::external_key_type external_key_type;
- typedef typename Info::data_type data_type;
-
- OnDiskChainedHashTable(unsigned numBuckets, unsigned numEntries,
- const unsigned char* buckets,
- const unsigned char* base,
- const Info &InfoObj = Info())
- : NumBuckets(numBuckets), NumEntries(numEntries),
- Buckets(buckets), Base(base), InfoObj(InfoObj) {
- assert((reinterpret_cast<uintptr_t>(buckets) & 0x3) == 0 &&
- "'buckets' must have a 4-byte alignment");
- }
-
- unsigned getNumBuckets() const { return NumBuckets; }
- unsigned getNumEntries() const { return NumEntries; }
- const unsigned char* getBase() const { return Base; }
- const unsigned char* getBuckets() const { return Buckets; }
-
- bool isEmpty() const { return NumEntries == 0; }
-
- class iterator {
- internal_key_type key;
- const unsigned char* const data;
- const unsigned len;
- Info *InfoObj;
- public:
- iterator() : data(0), len(0) {}
- iterator(const internal_key_type k, const unsigned char* d, unsigned l,
- Info *InfoObj)
- : key(k), data(d), len(l), InfoObj(InfoObj) {}
-
- data_type operator*() const { return InfoObj->ReadData(key, data, len); }
- bool operator==(const iterator& X) const { return X.data == data; }
- bool operator!=(const iterator& X) const { return X.data != data; }
- };
-
- iterator find(const external_key_type& eKey, Info *InfoPtr = 0) {
- if (!InfoPtr)
- InfoPtr = &InfoObj;
-
- using namespace io;
- const internal_key_type& iKey = InfoObj.GetInternalKey(eKey);
- unsigned key_hash = InfoObj.ComputeHash(iKey);
-
- // Each bucket is just a 32-bit offset into the hash table file.
- unsigned idx = key_hash & (NumBuckets - 1);
- const unsigned char* Bucket = Buckets + sizeof(uint32_t)*idx;
-
- unsigned offset = ReadLE32(Bucket);
- if (offset == 0) return iterator(); // Empty bucket.
- const unsigned char* Items = Base + offset;
-
- // 'Items' starts with a 16-bit unsigned integer representing the
- // number of items in this bucket.
- unsigned len = ReadUnalignedLE16(Items);
-
- for (unsigned i = 0; i < len; ++i) {
- // Read the hash.
- uint32_t item_hash = ReadUnalignedLE32(Items);
-
- // Determine the length of the key and the data.
- const std::pair<unsigned, unsigned>& L = Info::ReadKeyDataLength(Items);
- unsigned item_len = L.first + L.second;
-
- // Compare the hashes. If they are not the same, skip the entry entirely.
- if (item_hash != key_hash) {
- Items += item_len;
- continue;
- }
-
- // Read the key.
- const internal_key_type& X =
- InfoPtr->ReadKey((const unsigned char* const) Items, L.first);
-
- // If the key doesn't match just skip reading the value.
- if (!InfoPtr->EqualKey(X, iKey)) {
- Items += item_len;
- continue;
- }
-
- // The key matches!
- return iterator(X, Items + L.first, L.second, InfoPtr);
- }
-
- return iterator();
- }
-
- iterator end() const { return iterator(); }
-
- /// \brief Iterates over all of the keys in the table.
- class key_iterator {
- const unsigned char* Ptr;
- unsigned NumItemsInBucketLeft;
- unsigned NumEntriesLeft;
- Info *InfoObj;
- public:
- typedef external_key_type value_type;
-
- key_iterator(const unsigned char* const Ptr, unsigned NumEntries,
- Info *InfoObj)
- : Ptr(Ptr), NumItemsInBucketLeft(0), NumEntriesLeft(NumEntries),
- InfoObj(InfoObj) { }
- key_iterator()
- : Ptr(0), NumItemsInBucketLeft(0), NumEntriesLeft(0), InfoObj(0) { }
-
- friend bool operator==(const key_iterator &X, const key_iterator &Y) {
- return X.NumEntriesLeft == Y.NumEntriesLeft;
- }
- friend bool operator!=(const key_iterator& X, const key_iterator &Y) {
- return X.NumEntriesLeft != Y.NumEntriesLeft;
- }
-
- key_iterator& operator++() { // Preincrement
- if (!NumItemsInBucketLeft) {
- // 'Items' starts with a 16-bit unsigned integer representing the
- // number of items in this bucket.
- NumItemsInBucketLeft = io::ReadUnalignedLE16(Ptr);
- }
- Ptr += 4; // Skip the hash.
- // Determine the length of the key and the data.
- const std::pair<unsigned, unsigned>& L = Info::ReadKeyDataLength(Ptr);
- Ptr += L.first + L.second;
- assert(NumItemsInBucketLeft);
- --NumItemsInBucketLeft;
- assert(NumEntriesLeft);
- --NumEntriesLeft;
- return *this;
- }
- key_iterator operator++(int) { // Postincrement
- key_iterator tmp = *this; ++*this; return tmp;
- }
-
- value_type operator*() const {
- const unsigned char* LocalPtr = Ptr;
- if (!NumItemsInBucketLeft)
- LocalPtr += 2; // number of items in bucket
- LocalPtr += 4; // Skip the hash.
-
- // Determine the length of the key and the data.
- const std::pair<unsigned, unsigned>& L
- = Info::ReadKeyDataLength(LocalPtr);
-
- // Read the key.
- const internal_key_type& Key = InfoObj->ReadKey(LocalPtr, L.first);
- return InfoObj->GetExternalKey(Key);
- }
- };
-
- key_iterator key_begin() {
- return key_iterator(Base + 4, getNumEntries(), &InfoObj);
- }
- key_iterator key_end() { return key_iterator(); }
-
- /// \brief Iterates over all the entries in the table, returning the data.
- class data_iterator {
- const unsigned char* Ptr;
- unsigned NumItemsInBucketLeft;
- unsigned NumEntriesLeft;
- Info *InfoObj;
- public:
- typedef data_type value_type;
-
- data_iterator(const unsigned char* const Ptr, unsigned NumEntries,
- Info *InfoObj)
- : Ptr(Ptr), NumItemsInBucketLeft(0), NumEntriesLeft(NumEntries),
- InfoObj(InfoObj) { }
- data_iterator()
- : Ptr(0), NumItemsInBucketLeft(0), NumEntriesLeft(0), InfoObj(0) { }
-
- bool operator==(const data_iterator& X) const {
- return X.NumEntriesLeft == NumEntriesLeft;
- }
- bool operator!=(const data_iterator& X) const {
- return X.NumEntriesLeft != NumEntriesLeft;
- }
-
- data_iterator& operator++() { // Preincrement
- if (!NumItemsInBucketLeft) {
- // 'Items' starts with a 16-bit unsigned integer representing the
- // number of items in this bucket.
- NumItemsInBucketLeft = io::ReadUnalignedLE16(Ptr);
- }
- Ptr += 4; // Skip the hash.
- // Determine the length of the key and the data.
- const std::pair<unsigned, unsigned>& L = Info::ReadKeyDataLength(Ptr);
- Ptr += L.first + L.second;
- assert(NumItemsInBucketLeft);
- --NumItemsInBucketLeft;
- assert(NumEntriesLeft);
- --NumEntriesLeft;
- return *this;
- }
- data_iterator operator++(int) { // Postincrement
- data_iterator tmp = *this; ++*this; return tmp;
- }
-
- value_type operator*() const {
- const unsigned char* LocalPtr = Ptr;
- if (!NumItemsInBucketLeft)
- LocalPtr += 2; // number of items in bucket
- LocalPtr += 4; // Skip the hash.
-
- // Determine the length of the key and the data.
- const std::pair<unsigned, unsigned>& L =Info::ReadKeyDataLength(LocalPtr);
-
- // Read the key.
- const internal_key_type& Key =
- InfoObj->ReadKey(LocalPtr, L.first);
- return InfoObj->ReadData(Key, LocalPtr + L.first, L.second);
- }
- };
-
- data_iterator data_begin() {
- return data_iterator(Base + 4, getNumEntries(), &InfoObj);
- }
- data_iterator data_end() { return data_iterator(); }
-
- Info &getInfoObj() { return InfoObj; }
-
- static OnDiskChainedHashTable* Create(const unsigned char* buckets,
- const unsigned char* const base,
- const Info &InfoObj = Info()) {
- using namespace io;
- assert(buckets > base);
- assert((reinterpret_cast<uintptr_t>(buckets) & 0x3) == 0 &&
- "buckets should be 4-byte aligned.");
-
- unsigned numBuckets = ReadLE32(buckets);
- unsigned numEntries = ReadLE32(buckets);
- return new OnDiskChainedHashTable<Info>(numBuckets, numEntries, buckets,
- base, InfoObj);
- }
-};
-
-} // end namespace clang
-
-#endif
diff --git a/include/clang/Basic/OpenCL.h b/include/clang/Basic/OpenCL.h
deleted file mode 100644
index 3b3f259252df..000000000000
--- a/include/clang/Basic/OpenCL.h
+++ /dev/null
@@ -1,29 +0,0 @@
-//===--- OpenCL.h - OpenCL 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 OpenCL-specific enums.
-///
-//===----------------------------------------------------------------------===//
-
-#ifndef LLVM_CLANG_BASIC_OPENCL_H
-#define LLVM_CLANG_BASIC_OPENCL_H
-
-namespace clang {
-
-/// \brief Names for the OpenCL image access qualifiers (OpenCL 1.1 6.6).
-enum OpenCLImageAccess {
- CLIA_read_only = 1,
- CLIA_write_only = 2,
- CLIA_read_write = 3
-};
-
-}
-
-#endif
diff --git a/include/clang/Basic/OpenMPKinds.def b/include/clang/Basic/OpenMPKinds.def
index 6d1a7b27b749..6cfa5ea549f1 100644
--- a/include/clang/Basic/OpenMPKinds.def
+++ b/include/clang/Basic/OpenMPKinds.def
@@ -15,38 +15,196 @@
#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_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_SECTIONS_CLAUSE
+# define OPENMP_PARALLEL_SECTIONS_CLAUSE(Name)
+#endif
+#ifndef OPENMP_TASK_CLAUSE
+# define OPENMP_TASK_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
// 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(flush)
+OPENMP_DIRECTIVE_EXT(parallel_for, "parallel for")
+OPENMP_DIRECTIVE_EXT(parallel_sections, "parallel sections")
// OpenMP clauses.
+OPENMP_CLAUSE(if, OMPIfClause)
+OPENMP_CLAUSE(final, OMPFinalClause)
+OPENMP_CLAUSE(num_threads, OMPNumThreadsClause)
+OPENMP_CLAUSE(safelen, OMPSafelenClause)
+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)
-// Clauses allowed for OpenMP directives.
+// 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(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)
+
+// 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)
// 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)
+
+// 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)
+
+// 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)
+
+#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_SINGLE_CLAUSE
+#undef OPENMP_SECTIONS_CLAUSE
#undef OPENMP_PARALLEL_CLAUSE
+#undef OPENMP_PARALLEL_FOR_CLAUSE
+#undef OPENMP_PARALLEL_SECTIONS_CLAUSE
+#undef OPENMP_TASK_CLAUSE
+#undef OPENMP_SIMD_CLAUSE
+#undef OPENMP_FOR_CLAUSE
+
diff --git a/include/clang/Basic/OpenMPKinds.h b/include/clang/Basic/OpenMPKinds.h
index 5b4573124f21..526cbb26cf15 100644
--- a/include/clang/Basic/OpenMPKinds.h
+++ b/include/clang/Basic/OpenMPKinds.h
@@ -21,30 +21,45 @@ namespace clang {
/// \brief OpenMP directives.
enum OpenMPDirectiveKind {
- OMPD_unknown = 0,
#define OPENMP_DIRECTIVE(Name) \
OMPD_##Name,
+#define OPENMP_DIRECTIVE_EXT(Name, Str) \
+ OMPD_##Name,
#include "clang/Basic/OpenMPKinds.def"
- NUM_OPENMP_DIRECTIVES
+ OMPD_unknown
};
/// \brief OpenMP clauses.
enum OpenMPClauseKind {
- OMPC_unknown = 0,
#define OPENMP_CLAUSE(Name, Class) \
OMPC_##Name,
#include "clang/Basic/OpenMPKinds.def"
OMPC_threadprivate,
- NUM_OPENMP_CLAUSES
+ OMPC_unknown
};
/// \brief OpenMP attributes for 'default' clause.
enum OpenMPDefaultClauseKind {
- OMPC_DEFAULT_unknown = 0,
#define OPENMP_DEFAULT_KIND(Name) \
OMPC_DEFAULT_##Name,
#include "clang/Basic/OpenMPKinds.def"
- NUM_OPENMP_DEFAULT_KINDS
+ 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
};
OpenMPDirectiveKind getOpenMPDirectiveKind(llvm::StringRef Str);
@@ -59,6 +74,43 @@ 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 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 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 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/include/clang/Basic/OperatorKinds.h b/include/clang/Basic/OperatorKinds.h
index 2ceab9cbab9d..d3b70c2f4d22 100644
--- a/include/clang/Basic/OperatorKinds.h
+++ b/include/clang/Basic/OperatorKinds.h
@@ -19,7 +19,7 @@ namespace clang {
/// \brief Enumeration specifying the different kinds of C++ overloaded
/// operators.
-enum OverloadedOperatorKind {
+enum OverloadedOperatorKind : int {
OO_None, ///< Not an overloaded operator
#define OVERLOADED_OPERATOR(Name,Spelling,Token,Unary,Binary,MemberOnly) \
OO_##Name,
diff --git a/include/clang/Basic/PartialDiagnostic.h b/include/clang/Basic/PartialDiagnostic.h
index dd29926fce73..8ae3b22b0cc8 100644
--- a/include/clang/Basic/PartialDiagnostic.h
+++ b/include/clang/Basic/PartialDiagnostic.h
@@ -36,7 +36,7 @@ public:
};
struct Storage {
- Storage() : NumDiagArgs(0), NumDiagRanges(0) { }
+ Storage() : NumDiagArgs(0) { }
enum {
/// \brief The maximum number of arguments we can hold. We
@@ -50,9 +50,6 @@ public:
/// \brief The number of entries in Arguments.
unsigned char NumDiagArgs;
- /// \brief This is the number of ranges in the DiagRanges array.
- unsigned char NumDiagRanges;
-
/// \brief Specifies for each argument whether it is in DiagArgumentsStr
/// or in DiagArguments.
unsigned char DiagArgumentsKind[MaxArguments];
@@ -69,9 +66,7 @@ public:
std::string DiagArgumentsStr[MaxArguments];
/// \brief The list of ranges added to this diagnostic.
- ///
- /// It currently only support 10 ranges, could easily be extended if needed.
- CharSourceRange DiagRanges[10];
+ SmallVector<CharSourceRange, 8> DiagRanges;
/// \brief If valid, provides a hint with some code to insert, remove, or
/// modify at a particular position.
@@ -97,7 +92,7 @@ public:
Storage *Result = FreeList[--NumFreeListEntries];
Result->NumDiagArgs = 0;
- Result->NumDiagRanges = 0;
+ Result->DiagRanges.clear();
Result->FixItHints.clear();
return Result;
}
@@ -159,17 +154,14 @@ private:
Allocator->Deallocate(DiagStorage);
else if (Allocator != reinterpret_cast<StorageAllocator *>(~uintptr_t(0)))
delete DiagStorage;
- DiagStorage = 0;
+ DiagStorage = nullptr;
}
void AddSourceRange(const CharSourceRange &R) const {
if (!DiagStorage)
DiagStorage = getStorage();
- assert(DiagStorage->NumDiagRanges <
- llvm::array_lengthof(DiagStorage->DiagRanges) &&
- "Too many arguments to diagnostic!");
- DiagStorage->DiagRanges[DiagStorage->NumDiagRanges++] = R;
+ DiagStorage->DiagRanges.push_back(R);
}
void AddFixItHint(const FixItHint &Hint) const {
@@ -187,13 +179,13 @@ public:
/// \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(0), Allocator(0) { }
+ : DiagID(0), DiagStorage(nullptr), Allocator(nullptr) { }
PartialDiagnostic(unsigned DiagID, StorageAllocator &Allocator)
- : DiagID(DiagID), DiagStorage(0), Allocator(&Allocator) { }
+ : DiagID(DiagID), DiagStorage(nullptr), Allocator(&Allocator) { }
PartialDiagnostic(const PartialDiagnostic &Other)
- : DiagID(Other.DiagID), DiagStorage(0), Allocator(Other.Allocator)
+ : DiagID(Other.DiagID), DiagStorage(nullptr), Allocator(Other.Allocator)
{
if (Other.DiagStorage) {
DiagStorage = getStorage();
@@ -201,13 +193,11 @@ public:
}
}
-#if LLVM_HAS_RVALUE_REFERENCES
PartialDiagnostic(PartialDiagnostic &&Other)
: DiagID(Other.DiagID), DiagStorage(Other.DiagStorage),
Allocator(Other.Allocator) {
- Other.DiagStorage = 0;
+ Other.DiagStorage = nullptr;
}
-#endif
PartialDiagnostic(const PartialDiagnostic &Other, Storage *DiagStorage)
: DiagID(Other.DiagID), DiagStorage(DiagStorage),
@@ -218,7 +208,7 @@ public:
}
PartialDiagnostic(const Diagnostic &Other, StorageAllocator &Allocator)
- : DiagID(Other.getID()), DiagStorage(0), Allocator(&Allocator)
+ : DiagID(Other.getID()), DiagStorage(nullptr), Allocator(&Allocator)
{
// Copy arguments.
for (unsigned I = 0, N = Other.getNumArgs(); I != N; ++I) {
@@ -251,7 +241,6 @@ public:
return *this;
}
-#if LLVM_HAS_RVALUE_REFERENCES
PartialDiagnostic &operator=(PartialDiagnostic &&Other) {
freeStorage();
@@ -259,10 +248,9 @@ public:
DiagStorage = Other.DiagStorage;
Allocator = Other.Allocator;
- Other.DiagStorage = 0;
+ Other.DiagStorage = nullptr;
return *this;
}
-#endif
~PartialDiagnostic() {
freeStorage();
@@ -312,12 +300,12 @@ public:
}
// Add all ranges.
- for (unsigned i = 0, e = DiagStorage->NumDiagRanges; i != e; ++i)
- DB.AddSourceRange(DiagStorage->DiagRanges[i]);
+ for (const CharSourceRange &Range : DiagStorage->DiagRanges)
+ DB.AddSourceRange(Range);
// Add all fix-its.
- for (unsigned i = 0, e = DiagStorage->FixItHints.size(); i != e; ++i)
- DB.AddFixItHint(DiagStorage->FixItHints[i]);
+ for (const FixItHint &Fix : DiagStorage->FixItHints)
+ DB.AddFixItHint(Fix);
}
void EmitToString(DiagnosticsEngine &Diags,
@@ -339,7 +327,7 @@ public:
freeStorage();
}
- bool hasStorage() const { return DiagStorage != 0; }
+ bool hasStorage() const { return DiagStorage != nullptr; }
friend const PartialDiagnostic &operator<<(const PartialDiagnostic &PD,
unsigned I) {
@@ -380,8 +368,8 @@ public:
// match.
template<typename T>
friend inline
- typename llvm::enable_if<llvm::is_same<T, DeclContext>,
- const PartialDiagnostic &>::type
+ 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);
diff --git a/include/clang/Basic/PlistSupport.h b/include/clang/Basic/PlistSupport.h
new file mode 100644
index 000000000000..b7a938209a1d
--- /dev/null
+++ b/include/clang/Basic/PlistSupport.h
@@ -0,0 +1,122 @@
+//===---------- 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_PLISTSUPPORT_H
+#define LLVM_CLANG_PLISTSUPPORT_H
+
+#include "clang/Basic/FileManager.h"
+#include "clang/Basic/SourceManager.h"
+#include "clang/Lex/Lexer.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,
+ const LangOptions &LangOpts, SourceLocation L,
+ const FIDMap &FM, unsigned indent,
+ bool extend = false) {
+ FullSourceLoc Loc(SM.getExpansionLoc(L), const_cast<SourceManager &>(SM));
+
+ // Add in the length of the token, so that we cover multi-char tokens.
+ unsigned offset =
+ extend ? Lexer::MeasureTokenLength(Loc, SM, LangOpts) - 1 : 0;
+
+ Indent(o, indent) << "<dict>\n";
+ Indent(o, indent) << " <key>line</key>";
+ EmitInteger(o, Loc.getExpansionLineNumber()) << '\n';
+ Indent(o, indent) << " <key>col</key>";
+ EmitInteger(o, Loc.getExpansionColumnNumber() + offset) << '\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,
+ const LangOptions &LangOpts, CharSourceRange R,
+ const FIDMap &FM, unsigned indent) {
+ Indent(o, indent) << "<array>\n";
+ EmitLocation(o, SM, LangOpts, R.getBegin(), FM, indent + 1);
+ EmitLocation(o, SM, LangOpts, R.getEnd(), FM, indent + 1, R.isTokenRange());
+ Indent(o, indent) << "</array>\n";
+}
+}
+}
+
+#endif
diff --git a/include/clang/Basic/PrettyStackTrace.h b/include/clang/Basic/PrettyStackTrace.h
index 967d0d141e5b..0e49295540b4 100644
--- a/include/clang/Basic/PrettyStackTrace.h
+++ b/include/clang/Basic/PrettyStackTrace.h
@@ -31,7 +31,7 @@ namespace clang {
public:
PrettyStackTraceLoc(SourceManager &sm, SourceLocation L, const char *Msg)
: SM(sm), Loc(L), Message(Msg) {}
- virtual void print(raw_ostream &OS) const;
+ void print(raw_ostream &OS) const override;
};
}
diff --git a/include/clang/Basic/Sanitizers.def b/include/clang/Basic/Sanitizers.def
index c9b31a39aa55..0ef39bc710bb 100644
--- a/include/clang/Basic/Sanitizers.def
+++ b/include/clang/Basic/Sanitizers.def
@@ -40,13 +40,6 @@
// AddressSanitizer
SANITIZER("address", Address)
-// More features of AddressSanitizer that should be turned on explicitly.
-SANITIZER("init-order", InitOrder)
-SANITIZER("use-after-return", UseAfterReturn)
-SANITIZER("use-after-scope", UseAfterScope)
-
-SANITIZER_GROUP("address-full", AddressFull,
- Address | InitOrder | UseAfterReturn | UseAfterScope)
// MemorySanitizer
SANITIZER("memory", Memory)
@@ -89,7 +82,7 @@ SANITIZER_GROUP("undefined", Undefined,
ObjectSize | Return | Shift | SignedIntegerOverflow |
Unreachable | VLABound | Vptr)
-// -fsanitize=undefined-trap (and its alias -fcatch-undefined-behavior) includes
+// -fsanitize=undefined-trap includes
// all sanitizers included by -fsanitize=undefined, except those that require
// runtime support. This group is generally used in conjunction with the
// -fsanitize-undefined-trap-on-error flag.
@@ -103,7 +96,6 @@ SANITIZER_GROUP("integer", Integer,
SignedIntegerOverflow | UnsignedIntegerOverflow | Shift |
IntegerDivideByZero)
-// -fbounds-checking
SANITIZER("local-bounds", LocalBounds)
SANITIZER_GROUP("bounds", Bounds, ArrayBounds | LocalBounds)
diff --git a/include/clang/Basic/SourceLocation.h b/include/clang/Basic/SourceLocation.h
index 10ae07b82498..7b637d7e1fb3 100644
--- a/include/clang/Basic/SourceLocation.h
+++ b/include/clang/Basic/SourceLocation.h
@@ -89,7 +89,7 @@ class SourceLocation {
friend class SourceManager;
friend class ASTReader;
friend class ASTWriter;
- enum LLVM_ENUM_INT_TYPE(unsigned) {
+ enum : unsigned {
MacroIDBit = 1U << 31
};
public:
@@ -172,7 +172,7 @@ public:
}
void print(raw_ostream &OS, const SourceManager &SM) const;
- LLVM_ATTRIBUTE_USED std::string printToString(const SourceManager &SM) const;
+ std::string printToString(const SourceManager &SM) const;
void dump(const SourceManager &SM) const;
};
@@ -188,7 +188,7 @@ inline bool operator<(const SourceLocation &LHS, const SourceLocation &RHS) {
return LHS.getRawEncoding() < RHS.getRawEncoding();
}
-/// \brief A trival tuple used to represent a source range.
+/// \brief A trivial tuple used to represent a source range.
class SourceRange {
SourceLocation B;
SourceLocation E;
@@ -268,7 +268,7 @@ class FullSourceLoc : public SourceLocation {
const SourceManager *SrcMgr;
public:
/// \brief Creates a FullSourceLoc where isValid() returns \c false.
- explicit FullSourceLoc() : SrcMgr(0) {}
+ explicit FullSourceLoc() : SrcMgr(nullptr) {}
explicit FullSourceLoc(SourceLocation Loc, const SourceManager &SM)
: SourceLocation(Loc), SrcMgr(&SM) {}
@@ -284,19 +284,19 @@ public:
FullSourceLoc getExpansionLoc() const;
FullSourceLoc getSpellingLoc() const;
- unsigned getExpansionLineNumber(bool *Invalid = 0) const;
- unsigned getExpansionColumnNumber(bool *Invalid = 0) const;
+ unsigned getExpansionLineNumber(bool *Invalid = nullptr) const;
+ unsigned getExpansionColumnNumber(bool *Invalid = nullptr) const;
- unsigned getSpellingLineNumber(bool *Invalid = 0) const;
- unsigned getSpellingColumnNumber(bool *Invalid = 0) const;
+ unsigned getSpellingLineNumber(bool *Invalid = nullptr) const;
+ unsigned getSpellingColumnNumber(bool *Invalid = nullptr) const;
- const char *getCharacterData(bool *Invalid = 0) const;
+ const char *getCharacterData(bool *Invalid = nullptr) const;
- const llvm::MemoryBuffer* getBuffer(bool *Invalid = 0) const;
+ const llvm::MemoryBuffer* getBuffer(bool *Invalid = nullptr) const;
/// \brief Return a StringRef to the source buffer data for the
/// specified FileID.
- StringRef getBufferData(bool *Invalid = 0) const;
+ StringRef getBufferData(bool *Invalid = nullptr) const;
/// \brief Decompose the specified location into a raw FileID + Offset pair.
///
@@ -331,7 +331,7 @@ public:
/// \brief Prints information about this FullSourceLoc to stderr.
///
/// This is useful for debugging.
- LLVM_ATTRIBUTE_USED void dump() const;
+ void dump() const;
friend inline bool
operator==(const FullSourceLoc &LHS, const FullSourceLoc &RHS) {
@@ -358,7 +358,7 @@ class PresumedLoc {
unsigned Line, Col;
SourceLocation IncludeLoc;
public:
- PresumedLoc() : Filename(0) {}
+ PresumedLoc() : Filename(nullptr) {}
PresumedLoc(const char *FN, unsigned Ln, unsigned Co, SourceLocation IL)
: Filename(FN), Line(Ln), Col(Co), IncludeLoc(IL) {
}
@@ -367,8 +367,8 @@ public:
///
/// This occurs when created with invalid source locations or when walking
/// off the top of a \#include stack.
- bool isInvalid() const { return Filename == 0; }
- bool isValid() const { return Filename != 0; }
+ bool isInvalid() const { return Filename == nullptr; }
+ bool isValid() const { return Filename != nullptr; }
/// \brief Return the presumed filename of this location.
///
diff --git a/include/clang/Basic/SourceManager.h b/include/clang/Basic/SourceManager.h
index 6aab998bd898..e567a7a28da5 100644
--- a/include/clang/Basic/SourceManager.h
+++ b/include/clang/Basic/SourceManager.h
@@ -42,14 +42,15 @@
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/DenseSet.h"
#include "llvm/ADT/IntrusiveRefCntPtr.h"
-#include "llvm/ADT/OwningPtr.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 {
@@ -89,12 +90,21 @@ namespace SrcMgr {
DoNotFreeFlag = 0x02
};
+ // Note that the first member of this class is an aligned character buffer
+ // to ensure that this class has an alignment of 8 bytes. This wastes
+ // 8 bytes for every ContentCache object, but each of these corresponds to
+ // a file loaded into memory, so the 8 bytes doesn't seem terribly
+ // important. It is quite awkward to fit this aligner into any other part
+ // of the class due to the lack of portable ways to combine it with other
+ // members.
+ llvm::AlignedCharArray<8, 1> NonceAligner;
+
/// \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<const llvm::MemoryBuffer *, 2> Buffer;
+ mutable llvm::PointerIntPair<llvm::MemoryBuffer *, 2> Buffer;
public:
/// \brief Reference to the file entry representing this ContentCache.
@@ -133,14 +143,16 @@ namespace SrcMgr {
/// file considered as a system one.
unsigned IsSystemFile : 1;
- ContentCache(const FileEntry *Ent = 0)
- : Buffer(0, false), OrigEntry(Ent), ContentsEntry(Ent),
- SourceLineCache(0), NumLines(0), BufferOverridden(false),
- IsSystemFile(false) {}
+ ContentCache(const FileEntry *Ent = nullptr)
+ : Buffer(nullptr, false), OrigEntry(Ent), ContentsEntry(Ent),
+ SourceLineCache(nullptr), NumLines(0), BufferOverridden(false),
+ IsSystemFile(false) {
+ (void)NonceAligner; // Silence warnings about unused member.
+ }
ContentCache(const FileEntry *Ent, const FileEntry *contentEnt)
- : Buffer(0, false), OrigEntry(Ent), ContentsEntry(contentEnt),
- SourceLineCache(0), NumLines(0), BufferOverridden(false),
+ : Buffer(nullptr, false), OrigEntry(Ent), ContentsEntry(contentEnt),
+ SourceLineCache(nullptr), NumLines(0), BufferOverridden(false),
IsSystemFile(false) {}
~ContentCache();
@@ -149,15 +161,15 @@ namespace SrcMgr {
/// a non-NULL Buffer or SourceLineCache. Ownership of allocated memory
/// is not transferred, so this is a logical error.
ContentCache(const ContentCache &RHS)
- : Buffer(0, false), SourceLineCache(0), BufferOverridden(false),
- IsSystemFile(false)
- {
+ : Buffer(nullptr, false), SourceLineCache(nullptr),
+ BufferOverridden(false), IsSystemFile(false) {
OrigEntry = RHS.OrigEntry;
ContentsEntry = RHS.ContentsEntry;
-
- assert (RHS.Buffer.getPointer() == 0 && RHS.SourceLineCache == 0 &&
- "Passed ContentCache object cannot own a buffer.");
-
+
+ assert(RHS.Buffer.getPointer() == nullptr &&
+ RHS.SourceLineCache == nullptr &&
+ "Passed ContentCache object cannot own a buffer.");
+
NumLines = RHS.NumLines;
}
@@ -170,10 +182,10 @@ namespace SrcMgr {
/// will be emitted at.
///
/// \param Invalid If non-NULL, will be set \c true if an error occurred.
- const llvm::MemoryBuffer *getBuffer(DiagnosticsEngine &Diag,
- const SourceManager &SM,
- SourceLocation Loc = SourceLocation(),
- bool *Invalid = 0) const;
+ 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.
@@ -193,7 +205,7 @@ namespace SrcMgr {
/// this content cache. This is used for performance analysis.
llvm::MemoryBuffer::BufferKind getMemoryBufferKind() const;
- void setBuffer(const llvm::MemoryBuffer *B) {
+ void setBuffer(llvm::MemoryBuffer *B) {
assert(!Buffer.getPointer() && "MemoryBuffer already set.");
Buffer.setPointer(B);
Buffer.setInt(false);
@@ -201,13 +213,11 @@ namespace SrcMgr {
/// \brief Get the underlying buffer, returning NULL if the buffer is not
/// yet available.
- const llvm::MemoryBuffer *getRawBuffer() const {
- return Buffer.getPointer();
- }
+ llvm::MemoryBuffer *getRawBuffer() const { return Buffer.getPointer(); }
/// \brief Replace the existing buffer (which will be deleted)
/// with the given buffer.
- void replaceBuffer(const llvm::MemoryBuffer *B, bool DoNotFree = false);
+ void replaceBuffer(llvm::MemoryBuffer *B, bool DoNotFree = false);
/// \brief Determine whether the buffer itself is invalid.
bool isBufferInvalid() const {
@@ -224,6 +234,11 @@ namespace SrcMgr {
ContentCache &operator=(const ContentCache& RHS) LLVM_DELETED_FUNCTION;
};
+ // 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.
///
@@ -551,7 +566,7 @@ class SourceManager : public RefCountedBase<SourceManager> {
/// non-null, FileEntry pointers.
llvm::DenseMap<const FileEntry*, SrcMgr::ContentCache*> FileInfos;
- /// \brief True if the ContentCache for files that are overriden by other
+ /// \brief True if the ContentCache for files that are overridden by other
/// files, should report the original file name. Defaults to true.
bool OverridenFilesKeepOriginalName;
@@ -560,7 +575,7 @@ class SourceManager : public RefCountedBase<SourceManager> {
bool UserFilesAreVolatile;
struct OverriddenFilesInfoTy {
- /// \brief Files that have been overriden with the contents from another
+ /// \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.
@@ -569,7 +584,7 @@ class SourceManager : public RefCountedBase<SourceManager> {
/// \brief Lazily create the object keeping overridden files info, since
/// it is uncommonly used.
- OwningPtr<OverriddenFilesInfoTy> OverriddenFilesInfo;
+ std::unique_ptr<OverriddenFilesInfoTy> OverriddenFilesInfo;
OverriddenFilesInfoTy &getOverriddenFilesInfo() {
if (!OverriddenFilesInfo)
@@ -704,7 +719,8 @@ public:
FileManager &getFileManager() const { return FileMgr; }
/// \brief Set true if the SourceManager should report the original file name
- /// for contents of files that were overriden by other files.Defaults to true.
+ /// for contents of files that were overridden by other files. Defaults to
+ /// true.
void setOverridenFilesKeepOriginalName(bool value) {
OverridenFilesKeepOriginalName = value;
}
@@ -729,18 +745,6 @@ public:
StoredModuleBuildStack.push_back(std::make_pair(moduleName.str(),importLoc));
}
- /// \brief Create the FileID for a memory buffer that will represent the
- /// FileID for the main source.
- ///
- /// One example of when this would be used is when the main source is read
- /// from STDIN.
- FileID createMainFileIDForMemBuffer(const llvm::MemoryBuffer *Buffer,
- SrcMgr::CharacteristicKind Kind = SrcMgr::C_User) {
- assert(MainFileID.isInvalid() && "MainFileID already set!");
- MainFileID = createFileIDForMemBuffer(Buffer, Kind);
- return MainFileID;
- }
-
//===--------------------------------------------------------------------===//
// MainFileID creation and querying methods.
//===--------------------------------------------------------------------===//
@@ -748,14 +752,6 @@ public:
/// \brief Returns the FileID of the main source file.
FileID getMainFileID() const { return MainFileID; }
- /// \brief Create the FileID for the main source file.
- FileID createMainFileID(const FileEntry *SourceFile,
- SrcMgr::CharacteristicKind Kind = SrcMgr::C_User) {
- assert(MainFileID.isInvalid() && "MainFileID already set!");
- MainFileID = createFileID(SourceFile, SourceLocation(), Kind);
- return MainFileID;
- }
-
/// \brief Set the file ID for the main source file.
void setMainFileID(FileID FID) {
assert(MainFileID.isInvalid() && "MainFileID already set!");
@@ -793,10 +789,10 @@ public:
///
/// This does no caching of the buffer and takes ownership of the
/// MemoryBuffer, so only pass a MemoryBuffer to this once.
- FileID createFileIDForMemBuffer(const llvm::MemoryBuffer *Buffer,
+ FileID createFileID(llvm::MemoryBuffer *Buffer,
SrcMgr::CharacteristicKind FileCharacter = SrcMgr::C_User,
- int LoadedID = 0, unsigned LoadedOffset = 0,
- SourceLocation IncludeLoc = SourceLocation()) {
+ int LoadedID = 0, unsigned LoadedOffset = 0,
+ SourceLocation IncludeLoc = SourceLocation()) {
return createFileID(createMemBufferContentCache(Buffer), IncludeLoc,
FileCharacter, LoadedID, LoadedOffset);
}
@@ -823,13 +819,13 @@ public:
///
/// \param Invalid If non-NULL, will be set \c true if an error
/// occurs while retrieving the memory buffer.
- const llvm::MemoryBuffer *getMemoryBufferForFile(const FileEntry *File,
- bool *Invalid = 0);
+ 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 overriden.
+ /// \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.
@@ -837,12 +833,11 @@ public:
/// \param DoNotFree If true, then the buffer will not be freed when the
/// source manager is destroyed.
void overrideFileContents(const FileEntry *SourceFile,
- const llvm::MemoryBuffer *Buffer,
- bool DoNotFree = false);
+ llvm::MemoryBuffer *Buffer, bool DoNotFree = false);
/// \brief Override the given source file with another one.
///
- /// \param SourceFile the source file which will be overriden.
+ /// \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.
@@ -875,8 +870,8 @@ public:
///
/// If there is an error opening this buffer the first time, this
/// manufactures a temporary buffer and returns a non-empty error string.
- const llvm::MemoryBuffer *getBuffer(FileID FID, SourceLocation Loc,
- bool *Invalid = 0) const {
+ 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()) {
@@ -890,7 +885,7 @@ public:
Invalid);
}
- const llvm::MemoryBuffer *getBuffer(FileID FID, bool *Invalid = 0) const {
+ llvm::MemoryBuffer *getBuffer(FileID FID, bool *Invalid = nullptr) const {
bool MyInvalid = false;
const SrcMgr::SLocEntry &Entry = getSLocEntry(FID, &MyInvalid);
if (MyInvalid || !Entry.isFile()) {
@@ -910,11 +905,11 @@ public:
bool MyInvalid = false;
const SrcMgr::SLocEntry &Entry = getSLocEntry(FID, &MyInvalid);
if (MyInvalid || !Entry.isFile())
- return 0;
+ return nullptr;
const SrcMgr::ContentCache *Content = Entry.getFile().getContentCache();
if (!Content)
- return 0;
+ return nullptr;
return Content->OrigEntry;
}
@@ -923,7 +918,7 @@ public:
{
const SrcMgr::ContentCache *Content = sloc.getFile().getContentCache();
if (!Content)
- return 0;
+ return nullptr;
return Content->OrigEntry;
}
@@ -932,7 +927,7 @@ public:
///
/// \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 = 0) const;
+ 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.
@@ -1167,15 +1162,16 @@ public:
/// \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 = 0) const;
+ 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 = 0) const;
+ 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.
@@ -1184,7 +1180,7 @@ public:
/// relative offset of \p Loc inside the chunk.
bool isInSLocAddrSpace(SourceLocation Loc,
SourceLocation Start, unsigned Length,
- unsigned *RelativeOffset = 0) const {
+ unsigned *RelativeOffset = nullptr) const {
assert(((Start.getOffset() < NextLocalOffset &&
Start.getOffset()+Length <= NextLocalOffset) ||
(Start.getOffset() >= CurrentLoadedOffset &&
@@ -1230,7 +1226,8 @@ public:
/// in the appropriate spelling MemoryBuffer.
///
/// \param Invalid If non-NULL, will be set \c true if an error occurs.
- const char *getCharacterData(SourceLocation SL, bool *Invalid = 0) const;
+ const char *getCharacterData(SourceLocation SL,
+ bool *Invalid = nullptr) const;
/// \brief Return the column # for the specified file position.
///
@@ -1239,12 +1236,13 @@ public:
/// 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 = 0) const;
- unsigned getSpellingColumnNumber(SourceLocation Loc, bool *Invalid = 0) const;
+ bool *Invalid = nullptr) const;
+ unsigned getSpellingColumnNumber(SourceLocation Loc,
+ bool *Invalid = nullptr) const;
unsigned getExpansionColumnNumber(SourceLocation Loc,
- bool *Invalid = 0) const;
- unsigned getPresumedColumnNumber(SourceLocation Loc, bool *Invalid = 0) const;
-
+ 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.
@@ -1252,17 +1250,17 @@ public:
/// This requires building and caching a table of line offsets for the
/// MemoryBuffer, so this is not cheap: use only when about to emit a
/// diagnostic.
- unsigned getLineNumber(FileID FID, unsigned FilePos, bool *Invalid = 0) const;
- unsigned getSpellingLineNumber(SourceLocation Loc, bool *Invalid = 0) const;
- unsigned getExpansionLineNumber(SourceLocation Loc, bool *Invalid = 0) const;
- unsigned getPresumedLineNumber(SourceLocation Loc, bool *Invalid = 0) const;
+ 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 = 0) const;
+ 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
@@ -1286,7 +1284,7 @@ public:
/// an expansion location, not at the spelling location.
///
/// \returns The presumed location of the specified SourceLocation. If the
- /// presumed location cannot be calculate (e.g., because \p Loc is invalid
+ /// 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,
@@ -1332,14 +1330,14 @@ public:
return loc.isMacroID() && isInSystemHeader(getSpellingLoc(loc));
}
- /// \brief The size of the SLocEnty that \p FID represents.
+ /// \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 = 0) const {
+ unsigned *RelativeOffset = nullptr) const {
unsigned Offs = Loc.getOffset();
if (isOffsetInFileID(FID, Offs)) {
if (RelativeOffset)
@@ -1368,7 +1366,7 @@ public:
bool IsSystemHeader, bool IsExternCHeader);
/// \brief Determine if the source manager has a line table.
- bool hasLineTable() const { return LineTable != 0; }
+ bool hasLineTable() const { return LineTable != nullptr; }
/// \brief Retrieve the stored line table.
LineTableInfo &getLineTable();
@@ -1475,7 +1473,7 @@ public:
/// \brief Get a local SLocEntry. This is exposed for indexing.
const SrcMgr::SLocEntry &getLocalSLocEntry(unsigned Index,
- bool *Invalid = 0) const {
+ bool *Invalid = nullptr) const {
assert(Index < LocalSLocEntryTable.size() && "Invalid index");
return LocalSLocEntryTable[Index];
}
@@ -1485,14 +1483,15 @@ public:
/// \brief Get a loaded SLocEntry. This is exposed for indexing.
const SrcMgr::SLocEntry &getLoadedSLocEntry(unsigned Index,
- bool *Invalid = 0) const {
+ 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 = 0) const {
+ const SrcMgr::SLocEntry &getSLocEntry(FileID FID,
+ bool *Invalid = nullptr) const {
if (FID.ID == 0 || FID.ID == -1) {
if (Invalid) *Invalid = true;
return LocalSLocEntryTable[0];
@@ -1555,21 +1554,22 @@ public:
}
private:
- const llvm::MemoryBuffer *getFakeBufferForRecovery() const;
+ 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 = 0) const {
+ 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 = 0) const {
+ const SrcMgr::SLocEntry &
+ getLoadedSLocEntryByID(int ID, bool *Invalid = nullptr) const {
return getLoadedSLocEntry(static_cast<unsigned>(-ID - 2), Invalid);
}
@@ -1623,8 +1623,8 @@ private:
bool isSystemFile = false);
/// \brief Create a new ContentCache for the specified memory buffer.
- const SrcMgr::ContentCache*
- createMemBufferContentCache(const llvm::MemoryBuffer *Buf);
+ const SrcMgr::ContentCache *
+ createMemBufferContentCache(llvm::MemoryBuffer *Buf);
FileID getFileIDSlow(unsigned SLocOffset) const;
FileID getFileIDLocal(unsigned SLocOffset) const;
diff --git a/include/clang/Basic/Specifiers.h b/include/clang/Basic/Specifiers.h
index 0b8093969ae3..f89567356be5 100644
--- a/include/clang/Basic/Specifiers.h
+++ b/include/clang/Basic/Specifiers.h
@@ -63,21 +63,13 @@ namespace clang {
TST_decltype_auto, // C++1y decltype(auto)
TST_unknown_anytype, // __unknown_anytype extension
TST_atomic, // C11 _Atomic
- TST_image1d_t, // OpenCL image1d_t
- TST_image1d_array_t, // OpenCL image1d_array_t
- TST_image1d_buffer_t, // OpenCL image1d_buffer_t
- TST_image2d_t, // OpenCL image2d_t
- TST_image2d_array_t, // OpenCL image2d_array_t
- TST_image3d_t, // OpenCL image3d_t
- TST_sampler_t, // OpenCL sampler_t
- TST_event_t, // OpenCL event_t
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 : 6;
+ /*DeclSpec::TST*/ unsigned Type : 5;
/*DeclSpec::TSS*/ unsigned Sign : 2;
/*DeclSpec::TSW*/ unsigned Width : 2;
bool ModeAttr : 1;
diff --git a/include/clang/Basic/StmtNodes.td b/include/clang/Basic/StmtNodes.td
index 69851a9d5283..d9806486497d 100644
--- a/include/clang/Basic/StmtNodes.td
+++ b/include/clang/Basic/StmtNodes.td
@@ -115,8 +115,6 @@ def CXXNewExpr : DStmt<Expr>;
def CXXDeleteExpr : DStmt<Expr>;
def CXXPseudoDestructorExpr : DStmt<Expr>;
def TypeTraitExpr : DStmt<Expr>;
-def UnaryTypeTraitExpr : DStmt<Expr>;
-def BinaryTypeTraitExpr : DStmt<Expr>;
def ArrayTypeTraitExpr : DStmt<Expr>;
def ExpressionTraitExpr : DStmt<Expr>;
def DependentScopeDeclRefExpr : DStmt<Expr>;
@@ -172,6 +170,7 @@ def CXXUuidofExpr : DStmt<Expr>;
def SEHTryStmt : Stmt;
def SEHExceptStmt : Stmt;
def SEHFinallyStmt : Stmt;
+def SEHLeaveStmt : Stmt;
def MSDependentExistsStmt : Stmt;
// OpenCL Extensions.
@@ -180,3 +179,17 @@ def AsTypeExpr : DStmt<Expr>;
// OpenMP Directives.
def OMPExecutableDirective : Stmt<1>;
def OMPParallelDirective : DStmt<OMPExecutableDirective>;
+def OMPSimdDirective : DStmt<OMPExecutableDirective>;
+def OMPForDirective : DStmt<OMPExecutableDirective>;
+def OMPSectionsDirective : DStmt<OMPExecutableDirective>;
+def OMPSectionDirective : DStmt<OMPExecutableDirective>;
+def OMPSingleDirective : DStmt<OMPExecutableDirective>;
+def OMPMasterDirective : DStmt<OMPExecutableDirective>;
+def OMPCriticalDirective : DStmt<OMPExecutableDirective>;
+def OMPParallelForDirective : DStmt<OMPExecutableDirective>;
+def OMPParallelSectionsDirective : DStmt<OMPExecutableDirective>;
+def OMPTaskDirective : DStmt<OMPExecutableDirective>;
+def OMPTaskyieldDirective : DStmt<OMPExecutableDirective>;
+def OMPBarrierDirective : DStmt<OMPExecutableDirective>;
+def OMPTaskwaitDirective : DStmt<OMPExecutableDirective>;
+def OMPFlushDirective : DStmt<OMPExecutableDirective>;
diff --git a/include/clang/Basic/TargetBuiltins.h b/include/clang/Basic/TargetBuiltins.h
index ed3cc49fedb9..b1652bed07f2 100644
--- a/include/clang/Basic/TargetBuiltins.h
+++ b/include/clang/Basic/TargetBuiltins.h
@@ -1,4 +1,4 @@
-//===--- TargetBuiltins.h - Target specific builtin IDs -------------------===//
+//===--- TargetBuiltins.h - Target specific builtin IDs ---------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -21,25 +21,37 @@
namespace clang {
- /// \brief AArch64 builtins
- namespace AArch64 {
- enum {
- LastTIBuiltin = clang::Builtin::FirstTSBuiltin-1,
+ namespace NEON {
+ enum {
+ LastTIBuiltin = clang::Builtin::FirstTSBuiltin - 1,
#define BUILTIN(ID, TYPE, ATTRS) BI##ID,
-#include "clang/Basic/BuiltinsAArch64.def"
- LastTSBuiltin
- };
+#include "clang/Basic/BuiltinsNEON.def"
+ FirstTSBuiltin
+ };
}
+
/// \brief ARM builtins
namespace ARM {
enum {
- LastTIBuiltin = clang::Builtin::FirstTSBuiltin-1,
+ LastTIBuiltin = clang::Builtin::FirstTSBuiltin-1,
+ LastNEONBuiltin = NEON::FirstTSBuiltin - 1,
#define BUILTIN(ID, TYPE, ATTRS) BI##ID,
#include "clang/Basic/BuiltinsARM.def"
- LastTSBuiltin
+ 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 {
@@ -60,6 +72,15 @@ namespace clang {
};
}
+ /// \brief R600 builtins
+ namespace R600 {
+ enum {
+ LastTIBuiltin = clang::Builtin::FirstTSBuiltin - 1,
+ #define BUILTIN(ID, TYPE, ATTRS) BI##ID,
+ #include "clang/Basic/BuiltinsR600.def"
+ LastTSBuiltin
+ };
+ }
/// \brief X86 builtins
namespace X86 {
@@ -91,6 +112,7 @@ namespace clang {
Poly8,
Poly16,
Poly64,
+ Poly128,
Float16,
Float32,
Float64
diff --git a/include/clang/Basic/TargetCXXABI.h b/include/clang/Basic/TargetCXXABI.h
index 1590cca62337..f9e37c360b4f 100644
--- a/include/clang/Basic/TargetCXXABI.h
+++ b/include/clang/Basic/TargetCXXABI.h
@@ -63,6 +63,14 @@ public:
/// - 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,
+
/// The generic AArch64 ABI is also a modified version of the Itanium ABI,
/// but it has fewer divergences than the 32-bit ARM ABI.
///
@@ -105,6 +113,7 @@ public:
case GenericItanium:
case GenericARM:
case iOS:
+ case iOS64:
return true;
case Microsoft:
@@ -120,6 +129,7 @@ public:
case GenericItanium:
case GenericARM:
case iOS:
+ case iOS64:
return false;
case Microsoft:
@@ -135,14 +145,14 @@ public:
return !isMicrosoft();
}
- /// Are temporary objects passed by value to a call destroyed by the callee?
+ /// 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 isArgumentDestroyedByCallee() const {
+ bool areArgsDestroyedLeftToRightInCallee() const {
return isMicrosoft();
}
@@ -195,6 +205,7 @@ public:
bool canKeyFunctionBeInline() const {
switch (getKind()) {
case GenericARM:
+ case iOS64:
return false;
case GenericAArch64:
@@ -230,7 +241,7 @@ public:
/// 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.
+ /// This is non-strictly conforming in C++11 mode.
UseTailPaddingUnlessPOD03,
/// Only allocate objects in the tail padding of a base class if
@@ -248,6 +259,11 @@ public:
case iOS:
return UseTailPaddingUnlessPOD03;
+ // iOS on ARM64 uses the C++11 POD rules. It does not honor the
+ // Itanium exception about classes with over-large bitfields.
+ case iOS64:
+ return UseTailPaddingUnlessPOD11;
+
// MSVC always allocates fields in the tail-padding of a base class
// subobject, even if they're POD.
case Microsoft:
diff --git a/include/clang/Basic/TargetInfo.h b/include/clang/Basic/TargetInfo.h
index 047872dd4017..edef7c0377f2 100644
--- a/include/clang/Basic/TargetInfo.h
+++ b/include/clang/Basic/TargetInfo.h
@@ -16,9 +16,9 @@
#define LLVM_CLANG_BASIC_TARGETINFO_H
#include "clang/Basic/AddressSpaces.h"
-#include "clang/Basic/TargetCXXABI.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"
@@ -47,7 +47,7 @@ namespace Builtin { struct Info; }
/// \brief Exposes information about the current target.
///
class TargetInfo : public RefCountedBase<TargetInfo> {
- IntrusiveRefCntPtr<TargetOptions> TargetOpts;
+ std::shared_ptr<TargetOptions> TargetOpts;
llvm::Triple Triple;
protected:
// Target values set by the ctor of the actual target implementation. Default
@@ -94,8 +94,9 @@ public:
/// \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,
- TargetOptions *Opts);
+ static TargetInfo *
+ CreateTargetInfo(DiagnosticsEngine &Diags,
+ const std::shared_ptr<TargetOptions> &Opts);
virtual ~TargetInfo();
@@ -105,10 +106,6 @@ public:
return *TargetOpts;
}
- void setTargetOpts(TargetOptions *TargetOpts) {
- this->TargetOpts = TargetOpts;
- }
-
///===---- Target Data Type Query Methods -------------------------------===//
enum IntType {
NoInt = 0,
@@ -173,7 +170,7 @@ public:
};
protected:
- IntType SizeType, IntMaxType, UIntMaxType, PtrDiffType, IntPtrType, WCharType,
+ IntType SizeType, IntMaxType, PtrDiffType, IntPtrType, WCharType,
WIntType, Char16Type, Char32Type, Int64Type, SigAtomicType,
ProcessIDType;
@@ -209,19 +206,44 @@ protected:
public:
IntType getSizeType() const { return SizeType; }
IntType getIntMaxType() const { return IntMaxType; }
- IntType getUIntMaxType() const { return UIntMaxType; }
+ 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().
@@ -230,6 +252,9 @@ public:
/// \brief Return integer type with specified width.
IntType getIntTypeByWidth(unsigned BitWidth, bool IsSigned) const;
+ /// \brief Return the smallest integer type with at least the specified width.
+ IntType getLeastIntTypeByWidth(unsigned BitWidth, bool IsSigned) const;
+
/// \brief Return floating point type with specified width.
RealType getRealTypeByWidth(unsigned BitWidth) const;
@@ -283,7 +308,7 @@ public:
unsigned getLongLongAlign() const { return LongLongAlign; }
/// \brief Determine whether the __int128 type is supported on this target.
- bool hasInt128Type() const { return getPointerWidth(0) >= 64; } // FIXME
+ 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.
@@ -421,7 +446,13 @@ public:
/// \brief Return the constant suffix for the specified integer type enum.
///
/// For example, SignedLong -> "L".
- static const char *getTypeConstantSuffix(IntType T);
+ 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.
@@ -579,6 +610,7 @@ public:
}
const char *getTargetDescription() const {
+ assert(DescriptionString);
return DescriptionString;
}
@@ -604,24 +636,6 @@ public:
/// either; the entire thing is pretty badly mangled.
virtual bool hasProtectedVisibility() const { return true; }
- /// \brief Return the section to use for CFString literals, or 0 if no
- /// special section is used.
- virtual const char *getCFStringSection() const {
- return "__DATA,__cfstring";
- }
-
- /// \brief Return the section to use for NSString literals, or 0 if no
- /// special section is used.
- virtual const char *getNSStringSection() const {
- return "__OBJC,__cstring_object,regular,no_dead_strip";
- }
-
- /// \brief Return the section to use for NSString literals, or 0 if no
- /// special section is used (NonFragile ABI).
- virtual const char *getNSStringNonFragileABISection() const {
- return "__DATA, __objc_stringobj, regular, no_dead_strip";
- }
-
/// \brief An optional hook that targets can implement to perform semantic
/// checking on attribute((section("foo"))) specifiers.
///
@@ -641,7 +655,7 @@ public:
///
/// Apply changes to the target information with respect to certain
/// language options which change the target configuration.
- virtual void setForcedLangOptions(LangOptions &Opts);
+ virtual void adjust(const LangOptions &Opts);
/// \brief Get the default set of target features for the CPU;
/// this should include all legal feature strings on the target.
@@ -649,9 +663,7 @@ public:
}
/// \brief Get the ABI currently in use.
- virtual const char *getABI() const {
- return "";
- }
+ virtual StringRef getABI() const { return StringRef(); }
/// \brief Get the C++ ABI currently in use.
TargetCXXABI getCXXABI() const {
@@ -752,7 +764,7 @@ public:
/// \brief Return the section to use for C++ static initialization functions.
virtual const char *getStaticInitSectionSpecifier() const {
- return 0;
+ return nullptr;
}
const LangAS::Map &getAddressSpaceMap() const {
@@ -818,7 +830,7 @@ protected:
unsigned &NumAliases) const = 0;
virtual void getGCCAddlRegNames(const AddlRegName *&Addl,
unsigned &NumAddl) const {
- Addl = 0;
+ Addl = nullptr;
NumAddl = 0;
}
virtual bool validateAsmConstraint(const char *&Name,
diff --git a/include/clang/Basic/TargetOptions.h b/include/clang/Basic/TargetOptions.h
index 9909182ab6dd..2c86c31c2391 100644
--- a/include/clang/Basic/TargetOptions.h
+++ b/include/clang/Basic/TargetOptions.h
@@ -15,15 +15,13 @@
#ifndef LLVM_CLANG_FRONTEND_TARGETOPTIONS_H
#define LLVM_CLANG_FRONTEND_TARGETOPTIONS_H
-#include "clang/Basic/LLVM.h"
-#include "llvm/ADT/IntrusiveRefCntPtr.h"
#include <string>
#include <vector>
namespace clang {
/// \brief Options for controlling the target.
-class TargetOptions : public RefCountedBase<TargetOptions> {
+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.
@@ -38,10 +36,6 @@ public:
/// If given, the name of the target ABI to use.
std::string ABI;
- /// If given, the name of the target C++ ABI to use. If not given, defaults
- /// to "itanium".
- std::string CXXABI;
-
/// If given, the version string of the linker in use.
std::string LinkerVersion;
diff --git a/include/clang/Basic/TemplateKinds.h b/include/clang/Basic/TemplateKinds.h
index c5218933a226..b730143b6391 100644
--- a/include/clang/Basic/TemplateKinds.h
+++ b/include/clang/Basic/TemplateKinds.h
@@ -17,6 +17,7 @@
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,
diff --git a/include/clang/Basic/TokenKinds.def b/include/clang/Basic/TokenKinds.def
index 6812cce2dbea..5d088336dfe2 100644
--- a/include/clang/Basic/TokenKinds.def
+++ b/include/clang/Basic/TokenKinds.def
@@ -23,6 +23,18 @@
#ifndef KEYWORD
#define KEYWORD(X,Y) TOK(kw_ ## X)
#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
@@ -217,6 +229,7 @@ PUNCTUATOR(greatergreatergreater, ">>>")
// KEYALTIVEC - This is a keyword in AltiVec
// KEYBORLAND - This is a keyword if Borland extensions are 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)
@@ -255,7 +268,7 @@ KEYWORD(volatile , KEYALL)
KEYWORD(while , KEYALL)
KEYWORD(_Alignas , KEYALL)
KEYWORD(_Alignof , KEYALL)
-KEYWORD(_Atomic , KEYALL)
+KEYWORD(_Atomic , KEYALL|KEYNOMS)
KEYWORD(_Bool , KEYNOCXX)
KEYWORD(_Complex , KEYALL)
KEYWORD(_Generic , KEYALL)
@@ -284,7 +297,7 @@ KEYWORD(mutable , KEYCXX)
KEYWORD(namespace , KEYCXX)
KEYWORD(new , KEYCXX)
KEYWORD(operator , KEYCXX)
-KEYWORD(private , KEYCXX|KEYOPENCL)
+KEYWORD(private , KEYCXX)
KEYWORD(protected , KEYCXX)
KEYWORD(public , KEYCXX)
KEYWORD(reinterpret_cast , KEYCXX)
@@ -334,7 +347,9 @@ KEYWORD(__alignof , KEYALL)
KEYWORD(__attribute , KEYALL)
KEYWORD(__builtin_choose_expr , KEYALL)
KEYWORD(__builtin_offsetof , KEYALL)
-KEYWORD(__builtin_types_compatible_p, 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)
@@ -350,43 +365,51 @@ KEYWORD(typeof , KEYGNU)
// MS Extensions
KEYWORD(__FUNCDNAME__ , KEYMS)
+KEYWORD(__FUNCSIG__ , KEYMS)
KEYWORD(L__FUNCTION__ , KEYMS)
-KEYWORD(__is_interface_class , KEYMS)
-KEYWORD(__is_sealed , 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
-KEYWORD(__has_nothrow_assign , KEYCXX)
-KEYWORD(__has_nothrow_move_assign , KEYCXX)
-KEYWORD(__has_nothrow_copy , KEYCXX)
-KEYWORD(__has_nothrow_constructor , KEYCXX)
-KEYWORD(__has_trivial_assign , KEYCXX)
-KEYWORD(__has_trivial_move_assign , KEYCXX)
-KEYWORD(__has_trivial_copy , KEYCXX)
-KEYWORD(__has_trivial_constructor , KEYCXX)
-KEYWORD(__has_trivial_move_constructor, KEYCXX)
-KEYWORD(__has_trivial_destructor , KEYCXX)
-KEYWORD(__has_virtual_destructor , KEYCXX)
-KEYWORD(__is_abstract , KEYCXX)
-KEYWORD(__is_base_of , KEYCXX)
-KEYWORD(__is_class , KEYCXX)
-KEYWORD(__is_convertible_to , KEYCXX)
-KEYWORD(__is_empty , KEYCXX)
-KEYWORD(__is_enum , KEYCXX)
-KEYWORD(__is_final , KEYCXX)
+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.
-KEYWORD(__is_literal , KEYCXX)
+TYPE_TRAIT_1(__is_literal, IsLiteral, KEYCXX)
// Name for GCC 4.6 compatibility - people have already written libraries using
// this name unfortunately.
-KEYWORD(__is_literal_type , KEYCXX)
-KEYWORD(__is_pod , KEYCXX)
-KEYWORD(__is_polymorphic , KEYCXX)
-KEYWORD(__is_trivial , KEYCXX)
-KEYWORD(__is_union , KEYCXX)
+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
-KEYWORD(__is_trivially_constructible, KEYCXX)
-KEYWORD(__is_trivially_copyable , KEYCXX)
-KEYWORD(__is_trivially_assignable , KEYCXX)
+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
@@ -394,33 +417,33 @@ KEYWORD(__is_lvalue_expr , KEYCXX)
KEYWORD(__is_rvalue_expr , KEYCXX)
// Embarcadero Unary Type Traits
-KEYWORD(__is_arithmetic , KEYCXX)
-KEYWORD(__is_floating_point , KEYCXX)
-KEYWORD(__is_integral , KEYCXX)
-KEYWORD(__is_complete_type , KEYCXX)
-KEYWORD(__is_void , KEYCXX)
-KEYWORD(__is_array , KEYCXX)
-KEYWORD(__is_function , KEYCXX)
-KEYWORD(__is_reference , KEYCXX)
-KEYWORD(__is_lvalue_reference , KEYCXX)
-KEYWORD(__is_rvalue_reference , KEYCXX)
-KEYWORD(__is_fundamental , KEYCXX)
-KEYWORD(__is_object , KEYCXX)
-KEYWORD(__is_scalar , KEYCXX)
-KEYWORD(__is_compound , KEYCXX)
-KEYWORD(__is_pointer , KEYCXX)
-KEYWORD(__is_member_object_pointer , KEYCXX)
-KEYWORD(__is_member_function_pointer, KEYCXX)
-KEYWORD(__is_member_pointer , KEYCXX)
-KEYWORD(__is_const , KEYCXX)
-KEYWORD(__is_volatile , KEYCXX)
-KEYWORD(__is_standard_layout , KEYCXX)
-KEYWORD(__is_signed , KEYCXX)
-KEYWORD(__is_unsigned , KEYCXX)
+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
-KEYWORD(__is_same , KEYCXX)
-KEYWORD(__is_convertible , KEYCXX)
+TYPE_TRAIT_2(__is_same, IsSame, KEYCXX)
+TYPE_TRAIT_2(__is_convertible, IsConvertible, KEYCXX)
KEYWORD(__array_rank , KEYCXX)
KEYWORD(__array_extent , KEYCXX)
@@ -434,35 +457,31 @@ KEYWORD(__cdecl , KEYALL)
KEYWORD(__stdcall , KEYALL)
KEYWORD(__fastcall , KEYALL)
KEYWORD(__thiscall , KEYALL)
-KEYWORD(__forceinline , KEYALL)
+KEYWORD(__forceinline , KEYMS)
KEYWORD(__unaligned , KEYMS)
-// OpenCL-specific keywords
-KEYWORD(__kernel , KEYOPENCL)
-ALIAS("kernel", __kernel , KEYOPENCL)
-KEYWORD(vec_step , KEYOPENCL|KEYALTIVEC)
-KEYWORD(__private , KEYOPENCL)
+// OpenCL address space qualifiers
KEYWORD(__global , KEYOPENCL)
KEYWORD(__local , KEYOPENCL)
KEYWORD(__constant , KEYOPENCL)
+KEYWORD(__private , KEYOPENCL)
ALIAS("global", __global , KEYOPENCL)
ALIAS("local", __local , KEYOPENCL)
ALIAS("constant", __constant , KEYOPENCL)
+ALIAS("private", __private , 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(image1d_t , KEYOPENCL)
-KEYWORD(image1d_array_t , KEYOPENCL)
-KEYWORD(image1d_buffer_t , KEYOPENCL)
-KEYWORD(image2d_t , KEYOPENCL)
-KEYWORD(image2d_array_t , KEYOPENCL)
-KEYWORD(image3d_t , KEYOPENCL)
-KEYWORD(sampler_t , KEYOPENCL)
-KEYWORD(event_t , KEYOPENCL)
+KEYWORD(vec_step , KEYOPENCL|KEYALTIVEC)
// Borland Extensions.
KEYWORD(__pascal , KEYALL)
@@ -475,7 +494,7 @@ KEYWORD(__pixel , KEYALTIVEC)
ALIAS("__fp16", half , KEYALL)
// OpenCL Extension.
-KEYWORD(half , KEYOPENCL)
+KEYWORD(half , HALFSUPPORT)
// Objective-C ARC keywords.
KEYWORD(__bridge , KEYARC)
@@ -656,6 +675,21 @@ ANNOTATION(pragma_redefine_extname)
// 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.
@@ -667,8 +701,15 @@ ANNOTATION(pragma_opencl_extension)
ANNOTATION(pragma_openmp)
ANNOTATION(pragma_openmp_end)
-// Annotation for module import translated from #include etc.
+// 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
@@ -677,6 +718,10 @@ ANNOTATION(module_include)
#undef CXX_KEYWORD_OPERATOR
#undef PPKEYWORD
#undef ALIAS
+#undef TYPE_TRAIT_N
+#undef TYPE_TRAIT_2
+#undef TYPE_TRAIT_1
+#undef TYPE_TRAIT
#undef KEYWORD
#undef PUNCTUATOR
#undef TOK
diff --git a/include/clang/Basic/TokenKinds.h b/include/clang/Basic/TokenKinds.h
index dcbe1da1115d..794625ca91e3 100644
--- a/include/clang/Basic/TokenKinds.h
+++ b/include/clang/Basic/TokenKinds.h
@@ -15,12 +15,14 @@
#ifndef LLVM_CLANG_TOKENKINDS_H
#define LLVM_CLANG_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 {
+enum TokenKind : unsigned short {
#define TOK(X) X,
#include "clang/Basic/TokenKinds.def"
NUM_TOKENS
@@ -52,7 +54,7 @@ enum OnOffSwitch {
///
/// The name of a token will be an internal name (such as "l_square")
/// and should not be used as part of diagnostic messages.
-const char *getTokenName(enum TokenKind Kind);
+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.
@@ -61,7 +63,11 @@ const char *getTokenName(enum TokenKind Kind);
/// and will not produce any alternative spellings (e.g., a
/// digraph). For the actual spelling of a given Token, use
/// Preprocessor::getSpelling().
-const char *getTokenSimpleSpelling(enum TokenKind Kind);
+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) {
diff --git a/include/clang/Basic/TypeTraits.h b/include/clang/Basic/TypeTraits.h
index fc53527188bb..d7d2b18f3101 100644
--- a/include/clang/Basic/TypeTraits.h
+++ b/include/clang/Basic/TypeTraits.h
@@ -17,8 +17,8 @@
namespace clang {
- /// \brief Names for the unary type traits.
- enum UnaryTypeTrait {
+ /// \brief Names for traits that operate specifically on types.
+ enum TypeTrait {
UTT_HasNothrowAssign,
UTT_HasNothrowMoveAssign,
UTT_HasNothrowCopy,
@@ -37,6 +37,7 @@ namespace clang {
UTT_IsCompleteType,
UTT_IsCompound,
UTT_IsConst,
+ UTT_IsDestructible,
UTT_IsEmpty,
UTT_IsEnum,
UTT_IsFinal,
@@ -50,6 +51,7 @@ namespace clang {
UTT_IsMemberFunctionPointer,
UTT_IsMemberObjectPointer,
UTT_IsMemberPointer,
+ UTT_IsNothrowDestructible,
UTT_IsObject,
UTT_IsPOD,
UTT_IsPointer,
@@ -65,17 +67,19 @@ namespace clang {
UTT_IsUnion,
UTT_IsUnsigned,
UTT_IsVoid,
- UTT_IsVolatile
- };
-
- /// \brief Names for the binary type traits.
- enum BinaryTypeTrait {
+ UTT_IsVolatile,
+ UTT_Last = UTT_IsVolatile,
BTT_IsBaseOf,
BTT_IsConvertible,
BTT_IsConvertibleTo,
BTT_IsSame,
BTT_TypeCompatible,
- BTT_IsTriviallyAssignable
+ BTT_IsNothrowAssignable,
+ BTT_IsTriviallyAssignable,
+ BTT_Last = BTT_IsTriviallyAssignable,
+ TT_IsConstructible,
+ TT_IsNothrowConstructible,
+ TT_IsTriviallyConstructible
};
/// \brief Names for the array type traits.
@@ -90,12 +94,6 @@ namespace clang {
UETT_AlignOf,
UETT_VecStep
};
-
- /// \brief Names for type traits that operate specifically on types.
- enum TypeTrait {
- TT_IsTriviallyConstructible
- };
-
}
#endif
diff --git a/include/clang/Basic/Version.h b/include/clang/Basic/Version.h
index 7db8a2ebf682..02da432a40db 100644
--- a/include/clang/Basic/Version.h
+++ b/include/clang/Basic/Version.h
@@ -70,6 +70,9 @@ namespace clang {
/// 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.
diff --git a/include/clang/Basic/VersionTuple.h b/include/clang/Basic/VersionTuple.h
index ff06a5c23d82..54d06e07396a 100644
--- a/include/clang/Basic/VersionTuple.h
+++ b/include/clang/Basic/VersionTuple.h
@@ -18,6 +18,7 @@
#include "clang/Basic/LLVM.h"
#include "llvm/ADT/Optional.h"
#include <string>
+#include <tuple>
namespace clang {
@@ -87,13 +88,8 @@ public:
/// If not provided, minor and subminor version numbers are considered to be
/// zero.
friend bool operator<(const VersionTuple &X, const VersionTuple &Y) {
- if (X.Major != Y.Major)
- return X.Major < Y.Major;
-
- if (X.Minor != Y.Minor)
- return X.Minor < Y.Minor;
-
- return X.Subminor < Y.Subminor;
+ return std::tie(X.Major, X.Minor, X.Subminor) <
+ std::tie(Y.Major, Y.Minor, Y.Subminor);
}
/// \brief Determine whether one version number follows another.
diff --git a/include/clang/Basic/VirtualFileSystem.h b/include/clang/Basic/VirtualFileSystem.h
new file mode 100644
index 000000000000..36f78fd8725f
--- /dev/null
+++ b/include/clang/Basic/VirtualFileSystem.h
@@ -0,0 +1,283 @@
+//===- 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_VIRTUAL_FILE_SYSTEM_H
+#define LLVM_CLANG_BASIC_VIRTUAL_FILE_SYSTEM_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/raw_ostream.h"
+#include "llvm/Support/SourceMgr.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, StringRef RealName, 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);
+
+ /// \brief Returns the name that should be used for this file or directory.
+ StringRef getName() const { return Name; }
+ void setName(StringRef N) { Name = N; }
+
+ /// @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; }
+ void setType(llvm::sys::fs::file_type v) { Type = v; }
+ void setPermissions(llvm::sys::fs::perms p) { Perms = p; }
+ /// @}
+ /// @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 std::error_code getBuffer(const Twine &Name,
+ std::unique_ptr<llvm::MemoryBuffer> &Result,
+ int64_t FileSize = -1,
+ bool RequiresNullTerminator = true,
+ bool IsVolatile = false) = 0;
+ /// \brief Closes the file.
+ virtual std::error_code close() = 0;
+ /// \brief Sets the name to use for this file.
+ virtual void setName(StringRef Name) = 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 std::error_code openFileForRead(const Twine &Path,
+ std::unique_ptr<File> &Result) = 0;
+
+ /// This is a convenience method that opens a file, gets its content and then
+ /// closes the file.
+ std::error_code getBufferForFile(const Twine &Name,
+ std::unique_ptr<llvm::MemoryBuffer> &Result,
+ 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;
+};
+
+/// \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;
+ std::error_code openFileForRead(const Twine &Path,
+ std::unique_ptr<File> &Result) override;
+ directory_iterator dir_begin(const Twine &Dir, std::error_code &EC) 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(); }
+};
+
+/// \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.
+///
+/// Takes ownership of \p Buffer.
+IntrusiveRefCntPtr<FileSystem>
+getVFSFromYAML(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 // LLVM_CLANG_BASIC_VIRTUAL_FILE_SYSTEM_H
diff --git a/include/clang/Basic/arm_neon.td b/include/clang/Basic/arm_neon.td
index b918459f4e4a..0247bb5dd0d7 100644
--- a/include/clang/Basic/arm_neon.td
+++ b/include/clang/Basic/arm_neon.td
@@ -11,142 +11,265 @@
// 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
+//===----------------------------------------------------------------------===//
-class Op;
-
-def OP_NONE : Op;
-def OP_UNAVAILABLE : Op;
-def OP_ADD : Op;
-def OP_ADDL : Op;
-def OP_ADDLHi : Op;
-def OP_ADDW : Op;
-def OP_ADDWHi : Op;
-def OP_SUB : Op;
-def OP_SUBL : Op;
-def OP_SUBLHi : Op;
-def OP_SUBW : Op;
-def OP_SUBWHi : Op;
-def OP_MUL : Op;
-def OP_MLA : Op;
-def OP_MLAL : Op;
-def OP_MULLHi : Op;
-def OP_MULLHi_N : Op;
-def OP_MLALHi : Op;
-def OP_MLALHi_N : Op;
-def OP_MLS : Op;
-def OP_MLSL : Op;
-def OP_MLSLHi : Op;
-def OP_MLSLHi_N : Op;
-def OP_MUL_N : Op;
-def OP_MLA_N : Op;
-def OP_MLS_N : Op;
-def OP_FMLA_N : Op;
-def OP_FMLS_N : Op;
-def OP_MLAL_N : Op;
-def OP_MLSL_N : Op;
-def OP_MUL_LN: Op;
-def OP_MULX_LN: Op;
-def OP_MULL_LN : Op;
-def OP_MULLHi_LN : Op;
-def OP_MLA_LN: Op;
-def OP_MLS_LN: Op;
-def OP_MLAL_LN : Op;
-def OP_MLALHi_LN : Op;
-def OP_MLSL_LN : Op;
-def OP_MLSLHi_LN : Op;
-def OP_QDMULL_LN : Op;
-def OP_QDMULLHi_LN : Op;
-def OP_QDMLAL_LN : Op;
-def OP_QDMLALHi_LN : Op;
-def OP_QDMLSL_LN : Op;
-def OP_QDMLSLHi_LN : Op;
-def OP_QDMULH_LN : Op;
-def OP_QRDMULH_LN : Op;
-def OP_FMS_LN : Op;
-def OP_FMS_LNQ : Op;
-def OP_TRN1 : Op;
-def OP_ZIP1 : Op;
-def OP_UZP1 : Op;
-def OP_TRN2 : Op;
-def OP_ZIP2 : Op;
-def OP_UZP2 : Op;
-def OP_EQ : Op;
-def OP_GE : Op;
-def OP_LE : Op;
-def OP_GT : Op;
-def OP_LT : Op;
-def OP_NEG : Op;
-def OP_NOT : Op;
-def OP_AND : Op;
-def OP_OR : Op;
-def OP_XOR : Op;
-def OP_ANDN : Op;
-def OP_ORN : Op;
-def OP_CAST : Op;
-def OP_HI : Op;
-def OP_LO : Op;
-def OP_CONC : Op;
-def OP_DUP : Op;
-def OP_DUP_LN: Op;
-def OP_SEL : Op;
-def OP_REV64 : Op;
-def OP_REV32 : Op;
-def OP_REV16 : Op;
-def OP_XTN : Op;
-def OP_SQXTUN : Op;
-def OP_QXTN : Op;
-def OP_VCVT_NA_HI : Op;
-def OP_VCVT_EX_HI : Op;
-def OP_VCVTX_HI : Op;
-def OP_REINT : Op;
-def OP_ADDHNHi : Op;
-def OP_RADDHNHi : Op;
-def OP_SUBHNHi : Op;
-def OP_RSUBHNHi : Op;
-def OP_ABDL : Op;
-def OP_ABDLHi : Op;
-def OP_ABA : Op;
-def OP_ABAL : Op;
-def OP_ABALHi : Op;
-def OP_QDMULLHi : Op;
-def OP_QDMULLHi_N : Op;
-def OP_QDMLALHi : Op;
-def OP_QDMLALHi_N : Op;
-def OP_QDMLSLHi : Op;
-def OP_QDMLSLHi_N : Op;
-def OP_DIV : Op;
-def OP_LONG_HI : Op;
-def OP_NARROW_HI : Op;
-def OP_MOVL_HI : Op;
-def OP_COPY_LN : Op;
-def OP_COPYQ_LN : Op;
-def OP_COPY_LNQ : Op;
-def OP_SCALAR_MUL_LN : Op;
-def OP_SCALAR_MUL_LNQ : Op;
-def OP_SCALAR_MULX_LN : Op;
-def OP_SCALAR_MULX_LNQ : Op;
-def OP_SCALAR_VMULX_LN : Op;
-def OP_SCALAR_VMULX_LNQ : Op;
-def OP_SCALAR_QDMULL_LN : Op;
-def OP_SCALAR_QDMULL_LNQ : Op;
-def OP_SCALAR_QDMULH_LN : Op;
-def OP_SCALAR_QDMULH_LNQ : Op;
-def OP_SCALAR_QRDMULH_LN : Op;
-def OP_SCALAR_QRDMULH_LNQ : Op;
-def OP_SCALAR_GET_LN : Op;
-def OP_SCALAR_SET_LN : Op;
-
-class Inst <string n, string p, string t, Op o> {
+// 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;
- Op Operand = o;
+ string ArchGuard = "";
+
+ Operation Operation = o;
+ bit CartesianProductOfTypes = 0;
+ bit BigEndianSafe = 0;
bit isShift = 0;
bit isScalarShift = 0;
bit isScalarNarrowShift = 0;
bit isVCVT_N = 0;
- bit isA64 = 0;
- bit isCrypto = 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
@@ -181,59 +304,193 @@ class WInst<string n, string p, string t> : Inst<n, p, t, OP_NONE> {}
// 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, Op o> : Inst<n, p, t, o> {}
-class IOpInst<string n, string p, string t, Op o> : Inst<n, p, t, o> {}
-class WOpInst<string n, string p, string t, Op o> : Inst<n, p, t, o> {}
-class LOpInst<string n, string p, string t, Op o> : Inst<n, p, t, o> {}
-class NoTestOpInst<string n, string p, string t, Op o> : Inst<n, p, t, o> {}
+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> {}
-// 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
+//===----------------------------------------------------------------------===//
+// Operations
+//===----------------------------------------------------------------------===//
-// sizes:
-// c: char
-// s: short
-// i: int
-// l: long
-// f: float
-// h: half-float
-// d: double
+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_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", $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_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))>;
-// size modifiers:
-// S: scalar, only used for function mangling.
-// U: unsigned
-// Q: 128b
-// H: 128b without mangling 'q'
-// P: polynomial
+//===----------------------------------------------------------------------===//
+// Instructions
+//===----------------------------------------------------------------------===//
////////////////////////////////////////////////////////////////////////////////
// E.3.1 Addition
@@ -398,15 +655,19 @@ def VSET_LANE : IInst<"vset_lane", "dsdi",
////////////////////////////////////////////////////////////////////////////////
// E.3.18 Initialize a vector from bit pattern
-def VCREATE : NoTestOpInst<"vcreate", "dl", "csihfUcUsUiUlPcPsl", OP_CAST>;
+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",
- "UcUsUicsiPcPsfQUcQUsQUiQcQsQiQPcQPsQflUlQlQUl", OP_DUP>;
+ "UcUsUicsiPcPshfQUcQUsQUiQcQsQiQPcQPsQhQflUlQlQUl",
+ OP_DUP>;
def VMOV_N : WOpInst<"vmov_n", "ds",
- "UcUsUicsiPcPsfQUcQUsQUiQcQsQiQPcQPsQflUlQlQUl", OP_DUP>;
+ "UcUsUicsiPcPshfQUcQUsQUiQcQsQiQPcQPsQhQflUlQlQUl",
+ OP_DUP>;
}
let InstName = "" in
def VDUP_LANE: WOpInst<"vdup_lane", "dgi",
@@ -530,7 +791,11 @@ def VUZP : WInst<"vuzp", "2dd", "csiUcUsUifPcPsQcQsQiQUcQUsQUiQfQPcQPs">;
// E.3.31 Vector reinterpret cast operations
def VREINTERPRET
: NoTestOpInst<"vreinterpret", "dd",
- "csilUcUsUiUlhfPcPsQcQsQiQlQUcQUsQUiQUlQhQfQPcQPs", OP_REINT>;
+ "csilUcUsUiUlhfPcPsQcQsQiQlQUcQUsQUiQUlQhQfQPcQPs", OP_REINT> {
+ let CartesianProductOfTypes = 1;
+ let ArchGuard = "!defined(__aarch64__)";
+ let BigEndianSafe = 1;
+}
////////////////////////////////////////////////////////////////////////////////
// Vector fused multiply-add operations
@@ -540,87 +805,66 @@ def VFMA : SInst<"vfma", "dddd", "fQf">;
////////////////////////////////////////////////////////////////////////////////
// AArch64 Intrinsics
-let isA64 = 1 in {
+let ArchGuard = "defined(__aarch64__)" in {
////////////////////////////////////////////////////////////////////////////////
// Load/Store
-// With additional QUl, Ql, d, Qd, Pl, QPl type.
-def LD1 : WInst<"vld1", "dc",
- "QUcQUsQUiQUlQcQsQiQlQhQfQdQPcQPsUcUsUiUlcsilhfdPcPsPlQPl">;
-def LD2 : WInst<"vld2", "2c",
- "QUcQUsQUiQUlQcQsQiQlQhQfQdQPcQPsUcUsUiUlcsilhfdPcPsPlQPl">;
-def LD3 : WInst<"vld3", "3c",
- "QUcQUsQUiQUlQcQsQiQlQhQfQdQPcQPsUcUsUiUlcsilhfdPcPsPlQPl">;
-def LD4 : WInst<"vld4", "4c",
- "QUcQUsQUiQUlQcQsQiQlQhQfQdQPcQPsUcUsUiUlcsilhfdPcPsPlQPl">;
-def ST1 : WInst<"vst1", "vpd",
- "QUcQUsQUiQUlQcQsQiQlQhQfQdQPcQPsUcUsUiUlcsilhfdPcPsPlQPl">;
-def ST2 : WInst<"vst2", "vp2",
- "QUcQUsQUiQUlQcQsQiQlQhQfQdQPcQPsUcUsUiUlcsilhfdPcPsPlQPl">;
-def ST3 : WInst<"vst3", "vp3",
- "QUcQUsQUiQUlQcQsQiQlQhQfQdQPcQPsUcUsUiUlcsilhfdPcPsPlQPl">;
-def ST4 : WInst<"vst4", "vp4",
- "QUcQUsQUiQUlQcQsQiQlQhQfQdQPcQPsUcUsUiUlcsilhfdPcPsPlQPl">;
+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",
- "QUcQUsQUiQUlQcQsQiQlQhQfQdQPcQPsQPlUcUsUiUlcsilhfdPcPsPl">;
+ "QUcQUsQUiQcQsQiQhQfQPcQPsUcUsUiUlcsilhfPcPsQUlQldQdPlQPl">;
def LD3_x3 : WInst<"vld1_x3", "3c",
- "QUcQUsQUiQUlQcQsQiQlQhQfQdQPcQPsQPlUcUsUiUlcsilhfdPcPsPl">;
+ "QUcQUsQUiQcQsQiQhQfQPcQPsUcUsUiUlcsilhfPcPsQUlQldQdPlQPl">;
def LD4_x4 : WInst<"vld1_x4", "4c",
- "QUcQUsQUiQUlQcQsQiQlQhQfQdQPcQPsQPlUcUsUiUlcsilhfdPcPsPl">;
+ "QUcQUsQUiQcQsQiQhQfQPcQPsUcUsUiUlcsilhfPcPsQUlQldQdPlQPl">;
def ST1_X2 : WInst<"vst1_x2", "vp2",
- "QUcQUsQUiQUlQcQsQiQlQhQfQdQPcQPsQPlUcUsUiUlcsilhfdPcPsPl">;
+ "QUcQUsQUiQcQsQiQhQfQPcQPsUcUsUiUlcsilhfPcPsQUlQldQdPlQPl">;
def ST1_X3 : WInst<"vst1_x3", "vp3",
- "QUcQUsQUiQUlQcQsQiQlQhQfQdQPcQPsQPlUcUsUiUlcsilhfdPcPsPl">;
+ "QUcQUsQUiQcQsQiQhQfQPcQPsUcUsUiUlcsilhfPcPsQUlQldQdPlQPl">;
def ST1_X4 : WInst<"vst1_x4", "vp4",
- "QUcQUsQUiQUlQcQsQiQlQhQfQdQPcQPsQPlUcUsUiUlcsilhfdPcPsPl">;
-
-// With additional QUl, Ql, d, Qd, Pl, QPl type.
-def LD1_LANE : WInst<"vld1_lane", "dcdi",
- "QUcQUsQUiQUlQcQsQiQlQhQfQdQPcQPsQPlUcUsUiUlcsilhfdPcPsPl">;
-def LD2_LANE : WInst<"vld2_lane", "2c2i",
- "QUcQUsQUiQUlQcQsQiQlQhQfQdQPcQPsQPlUcUsUiUlcsilhfdPcPsPl">;
-def LD3_LANE : WInst<"vld3_lane", "3c3i",
- "QUcQUsQUiQUlQcQsQiQlQhQfQdQPcQPsQPlUcUsUiUlcsilhfdPcPsPl">;
-def LD4_LANE : WInst<"vld4_lane", "4c4i",
- "QUcQUsQUiQUlQcQsQiQlQhQfQdQPcQPsQPlUcUsUiUlcsilhfdPcPsPl">;
-def ST1_LANE : WInst<"vst1_lane", "vpdi",
- "QUcQUsQUiQUlQcQsQiQlQhQfQdQPcQPsQPlUcUsUiUlcsilhfdPcPsPl">;
-def ST2_LANE : WInst<"vst2_lane", "vp2i",
- "QUcQUsQUiQUlQcQsQiQlQhQfQdQPcQPsQPlUcUsUiUlcsilhfdPcPsPl">;
-def ST3_LANE : WInst<"vst3_lane", "vp3i",
- "QUcQUsQUiQUlQcQsQiQlQhQfQdQPcQPsQPlUcUsUiUlcsilhfdPcPsPl">;
-def ST4_LANE : WInst<"vst4_lane", "vp4i",
- "QUcQUsQUiQUlQcQsQiQlQhQfQdQPcQPsQPlUcUsUiUlcsilhfdPcPsPl">;
-
-def LD1_DUP : WInst<"vld1_dup", "dc",
- "QUcQUsQUiQUlQcQsQiQlQhQfQdQPcQPsQPlUcUsUiUlcsilhfdPcPsPl">;
+ "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",
- "QUcQUsQUiQUlQcQsQiQlQhQfQdQPcQPsQPlUcUsUiUlcsilhfdPcPsPl">;
+ "QUcQUsQUiQUlQcQsQiQlQhQfQdQPcQPsQPldPl">;
def LD3_DUP : WInst<"vld3_dup", "3c",
- "QUcQUsQUiQUlQcQsQiQlQhQfQdQPcQPsQPlUcUsUiUlcsilhfdPcPsPl">;
+ "QUcQUsQUiQUlQcQsQiQlQhQfQdQPcQPsQPldPl">;
def LD4_DUP : WInst<"vld4_dup", "4c",
- "QUcQUsQUiQUlQcQsQiQlQhQfQdQPcQPsQPlUcUsUiUlcsilhfdPcPsPl">;
+ "QUcQUsQUiQUlQcQsQiQlQhQfQdQPcQPsQPldPl">;
+
+def VLDRQ : WInst<"vldrq", "sc", "Pk">;
+def VSTRQ : WInst<"vstrq", "vps", "Pk">;
////////////////////////////////////////////////////////////////////////////////
// Addition
-// With additional d, Qd type.
-def ADD : IOpInst<"vadd", "ddd", "csilfdUcUsUiUlQcQsQiQlQfQUcQUsQUiQUlQd",
- OP_ADD>;
+def ADD : IOpInst<"vadd", "ddd", "dQd", OP_ADD>;
////////////////////////////////////////////////////////////////////////////////
// Subtraction
-// With additional Qd type.
-def SUB : IOpInst<"vsub", "ddd", "csildfUcUsUiUlQcQsQiQlQfQUcQUsQUiQUlQd",
- OP_SUB>;
+def SUB : IOpInst<"vsub", "ddd", "dQd", OP_SUB>;
////////////////////////////////////////////////////////////////////////////////
// Multiplication
-// With additional Qd type.
-def MUL : IOpInst<"vmul", "ddd", "csifdUcUsUiQcQsQiQfQUcQUsQUiQd", OP_MUL>;
-def MLA : IOpInst<"vmla", "dddd", "csifdUcUsUiQcQsQiQfQUcQUsQUiQd", OP_MLA>;
-def MLS : IOpInst<"vmls", "dddd", "csifdUcUsUiQcQsQiQfQUcQUsQUiQd", OP_MLS>;
+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
@@ -632,34 +876,33 @@ def FDIV : IOpInst<"vdiv", "ddd", "fdQfQd", OP_DIV>;
////////////////////////////////////////////////////////////////////////////////
// Vector fused multiply-add operations
-// With additional d, Qd type.
-def FMLA : SInst<"vfma", "dddd", "fdQfQd">;
+def FMLA : SInst<"vfma", "dddd", "dQd">;
def FMLS : SInst<"vfms", "dddd", "fdQfQd">;
////////////////////////////////////////////////////////////////////////////////
-// MUL, FMA, FMS definitions with scalar argument
+// 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", "fQf", OP_FMLA_N>;
-def FMLS_N : SOpInst<"vfms_n", "ddds", "fQf", OP_FMLS_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
-// With additional Qd, Ql, QPl type.
-def BSL : SInst<"vbsl", "dudd",
- "csilUcUsUiUlfdPcPsQcQsQiQlQUcQUsQUiQUlQfQPcQPsQdPlQPl">;
+def BSL : SInst<"vbsl", "dudd", "dPlQdQPl">;
////////////////////////////////////////////////////////////////////////////////
// Absolute Difference
-// With additional Qd type.
-def ABD : SInst<"vabd", "ddd", "csiUcUsUifdQcQsQiQUcQUsQUiQfQd">;
+def ABD : SInst<"vabd", "ddd", "dQd">;
////////////////////////////////////////////////////////////////////////////////
// saturating absolute/negate
-// With additional Qd/Ql type.
-def ABS : SInst<"vabs", "dd", "csilfdQcQsQiQfQlQd">;
-def QABS : SInst<"vqabs", "dd", "csilQcQsQiQl">;
-def NEG : SOpInst<"vneg", "dd", "csilfdQcQsQiQfQdQl", OP_NEG>;
-def QNEG : SInst<"vqneg", "dd", "csilQcQsQiQl">;
+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
@@ -671,9 +914,8 @@ def USQADD : SInst<"vsqadd", "ddd", "UcUsUiUlQUcQUsQUiQUl">;
////////////////////////////////////////////////////////////////////////////////
// Reciprocal/Sqrt
-// With additional d, Qd type.
-def FRECPS : IInst<"vrecps", "ddd", "fdQfQd">;
-def FRSQRTS : IInst<"vrsqrts", "ddd", "fdQfQd">;
+def FRECPS : IInst<"vrecps", "ddd", "dQd">;
+def FRSQRTS : IInst<"vrsqrts", "ddd", "dQd">;
////////////////////////////////////////////////////////////////////////////////
// bitwise reverse
@@ -693,13 +935,13 @@ def QXTN2 : SOpInst<"vqmovn_high", "qhk", "silUsUiUl", OP_QXTN>;
////////////////////////////////////////////////////////////////////////////////
// Converting vectors
-def VCVT_HIGH_F16 : SOpInst<"vcvt_high_f16", "qhj", "f", OP_VCVT_NA_HI>;
-def VCVT_HIGH_F32_F16 : SOpInst<"vcvt_high_f32", "wk", "h", OP_VCVT_EX_HI>;
-def VCVT_F32_F64 : SInst<"vcvt_f32_f64", "fj", "d">;
-def VCVT_HIGH_F32_F64 : SOpInst<"vcvt_high_f32", "qfj", "d", OP_VCVT_NA_HI>;
+def VCVT_HIGH_F16 : SOpInst<"vcvt_high_f16", "qhj", "f", OP_VCVT_NA_HI_F16>;
+def VCVT_HIGH_F32_F16 : SOpInst<"vcvt_high_f32", "wk", "h", OP_VCVT_EX_HI_F32>;
+def VCVT_F32_F64 : SInst<"vcvt_f32_f64", "md", "Qd">;
+def VCVT_HIGH_F32_F64 : SOpInst<"vcvt_high_f32", "qfj", "d", OP_VCVT_NA_HI_F32>;
def VCVT_F64_F32 : SInst<"vcvt_f64_f32", "wd", "f">;
def VCVT_F64 : SInst<"vcvt_f64", "Fd", "lUlQlQUl">;
-def VCVT_HIGH_F64_F32 : SOpInst<"vcvt_high_f64", "wj", "f", OP_VCVT_EX_HI>;
+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>;
def FRINTN : SInst<"vrndn", "dd", "fdQfQd">;
@@ -711,47 +953,22 @@ def FRINTZ : SInst<"vrnd", "dd", "fdQfQd">;
def FRINTI : SInst<"vrndi", "dd", "fdQfQd">;
def VCVT_S64 : SInst<"vcvt_s64", "xd", "dQd">;
def VCVT_U64 : SInst<"vcvt_u64", "ud", "dQd">;
-def FCVTNS_S32 : SInst<"vcvtn_s32", "xd", "fQf">;
-def FCVTNS_S64 : SInst<"vcvtn_s64", "xd", "dQd">;
-def FCVTNU_S32 : SInst<"vcvtn_u32", "ud", "fQf">;
-def FCVTNU_S64 : SInst<"vcvtn_u64", "ud", "dQd">;
-def FCVTPS_S32 : SInst<"vcvtp_s32", "xd", "fQf">;
-def FCVTPS_S64 : SInst<"vcvtp_s64", "xd", "dQd">;
-def FCVTPU_S32 : SInst<"vcvtp_u32", "ud", "fQf">;
-def FCVTPU_S64 : SInst<"vcvtp_u64", "ud", "dQd">;
-def FCVTMS_S32 : SInst<"vcvtm_s32", "xd", "fQf">;
-def FCVTMS_S64 : SInst<"vcvtm_s64", "xd", "dQd">;
-def FCVTMU_S32 : SInst<"vcvtm_u32", "ud", "fQf">;
-def FCVTMU_S64 : SInst<"vcvtm_u64", "ud", "dQd">;
-def FCVTAS_S32 : SInst<"vcvta_s32", "xd", "fQf">;
-def FCVTAS_S64 : SInst<"vcvta_s64", "xd", "dQd">;
-def FCVTAU_S32 : SInst<"vcvta_u32", "ud", "fQf">;
-def FCVTAU_S64 : SInst<"vcvta_u64", "ud", "dQd">;
-def FRECPE : SInst<"vrecpe", "dd", "fdUiQfQUiQd">;
-def FRSQRTE : SInst<"vrsqrte", "dd", "fdUiQfQUiQd">;
+def FRECPE : SInst<"vrecpe", "dd", "dQd">;
+def FRSQRTE : SInst<"vrsqrte", "dd", "dQd">;
def FSQRT : SInst<"vsqrt", "dd", "fdQfQd">;
////////////////////////////////////////////////////////////////////////////////
// Comparison
-// With additional Qd, Ql, QPl type.
-def FCAGE : IInst<"vcage", "udd", "fdQfQd">;
-def FCAGT : IInst<"vcagt", "udd", "fdQfQd">;
-def FCALE : IInst<"vcale", "udd", "fdQfQd">;
-def FCALT : IInst<"vcalt", "udd", "fdQfQd">;
-// With additional Ql, QUl, Qd types.
-def CMTST : WInst<"vtst", "udd",
- "csiUcUsUiPcPsQcQsQiQUcQUsQUiQPcQPslUlQlQUlPlQPl">;
-// With additional l, Ul,d, Qd, Ql, QUl, Qd types.
-def CFMEQ : SOpInst<"vceq", "udd",
- "csilfUcUsUiUlPcQcdQdQsQiQfQUcQUsQUiQUlQlQPcPlQPl", OP_EQ>;
-def CFMGE : SOpInst<"vcge", "udd",
- "csilfUcUsUiUlQcQsQiQlQfQUcQUsQUiQUldQd", OP_GE>;
-def CFMLE : SOpInst<"vcle", "udd",
- "csilfUcUsUiUlQcQsQiQlQfQUcQUsQUiQUldQd", OP_LE>;
-def CFMGT : SOpInst<"vcgt", "udd",
- "csilfUcUsUiUlQcQsQiQlQfQUcQUsQUiQUldQd", OP_GT>;
-def CFMLT : SOpInst<"vclt", "udd",
- "csilfUcUsUiUlQcQsQiQlQfQUcQUsQUiQUldQd", OP_LT>;
+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">;
@@ -762,9 +979,8 @@ def CMLT : SInst<"vcltz", "ud", "csilfdQcQsQiQlQfQd">;
////////////////////////////////////////////////////////////////////////////////
// Max/Min Integer
-// With additional Qd type.
-def MAX : SInst<"vmax", "ddd", "csiUcUsUifdQcQsQiQUcQUsQUiQfQd">;
-def MIN : SInst<"vmin", "ddd", "csiUcUsUifdQcQsQiQUcQUsQUiQfQd">;
+def MAX : SInst<"vmax", "ddd", "dQd">;
+def MIN : SInst<"vmin", "ddd", "dQd">;
////////////////////////////////////////////////////////////////////////////////
// MaxNum/MinNum Floating Point
@@ -773,9 +989,8 @@ def FMINNM : SInst<"vminnm", "ddd", "fdQfQd">;
////////////////////////////////////////////////////////////////////////////////
// Pairwise Max/Min
-// With additional Qc Qs Qi QUc QUs QUi Qf Qd types.
-def MAXP : SInst<"vpmax", "ddd", "csiUcUsUifQcQsQiQUcQUsQUiQfQd">;
-def MINP : SInst<"vpmin", "ddd", "csiUcUsUifQcQsQiQUcQUsQUiQfQd">;
+def MAXP : SInst<"vpmax", "ddd", "QcQsQiQUcQUsQUiQfQd">;
+def MINP : SInst<"vpmin", "ddd", "QcQsQiQUcQUsQUiQfQd">;
////////////////////////////////////////////////////////////////////////////////
// Pairwise MaxNum/MinNum Floating Point
@@ -784,8 +999,7 @@ def FMINNMP : SInst<"vpminnm", "ddd", "fQfQd">;
////////////////////////////////////////////////////////////////////////////////
// Pairwise Addition
-// With additional Qc Qs Qi QUc QUs QUi Qf Qd types.
-def ADDP : IInst<"vpadd", "ddd", "csiUcUsUifQcQsQiQlQUcQUsQUiQUlQfQd">;
+def ADDP : IInst<"vpadd", "ddd", "QcQsQiQlQUcQUsQUiQUlQfQd">;
////////////////////////////////////////////////////////////////////////////////
// Shifts by constant
@@ -795,11 +1009,8 @@ def SHLL_HIGH_N : SOpInst<"vshll_high_n", "ndi", "HcHsHiHUcHUsHUi",
OP_LONG_HI>;
////////////////////////////////////////////////////////////////////////////////
-// Shifts with insert, with additional Ql, QPl type.
-def SRI_N : WInst<"vsri_n", "dddi",
- "csilUcUsUiUlPcPsQcQsQiQlQUcQUsQUiQUlQPcQPsPlQPl">;
-def SLI_N : WInst<"vsli_n", "dddi",
- "csilUcUsUiUlPcPsQcQsQiQlQUcQUsQUiQUlQPcQPsPlQPl">;
+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",
@@ -854,44 +1065,40 @@ 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",
- "csilPcPsUcUsUiUlQcQsQiQlQUcQUsQUiQUlPcPsQPcQPsfdQfQdPlQPl">;
-def SET_LANE : IInst<"vset_lane", "dsdi",
- "csilPcPsUcUsUiUlQcQsQiQlQUcQUsQUiQUlPcPsQPcQPsfdQfQdPlQPl">;
+def GET_LANE : IInst<"vget_lane", "sdi", "dQdPlQPl">;
+def SET_LANE : IInst<"vset_lane", "dsdi", "dQdPlQPl">;
def COPY_LANE : IOpInst<"vcopy_lane", "ddidi",
- "csilPcPsUcUsUiUlPcPsPlfd", OP_COPY_LN>;
+ "csilUcUsUiUlPcPsPlfd", OP_COPY_LN>;
def COPYQ_LANE : IOpInst<"vcopy_lane", "ddigi",
- "QcQsQiQlQUcQUsQUiQUlQPcQPsQfQdQPl", OP_COPYQ_LN>;
+ "QcQsQiQlQUcQUsQUiQUlQPcQPsQfQdQPl", OP_COPY_LN>;
def COPY_LANEQ : IOpInst<"vcopy_laneq", "ddiki",
- "csilPcPsPlUcUsUiUlfd", OP_COPY_LNQ>;
+ "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",
- "csilPcPsUcUsUiUlhfdQcQsQiQlQPcQPsQUcQUsQUiQUlQhQfQdPlQPl",
- OP_DUP_LN>;
-def VDUP_LANE2: WOpInst<"vdup_laneq", "dki",
- "csilPcPsUcUsUiUlhfdQcQsQiQlQPcQPsQUcQUsQUiQUlQhQfQdPlQPl",
+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",
- "UcUsUicsiPcPsfQUcQUsQUiQcQsQiQPcQPsQflUlQlQUldQdPlQPl",
- OP_DUP>;
-def MOV_N : WOpInst<"vmov_n", "ds",
- "UcUsUicsiPcPsfQUcQUsQUiQcQsQiQPcQPsQflUlQlQUldQd",
- OP_DUP>;
+def DUP_N : WOpInst<"vdup_n", "ds", "dQdPlQPl", OP_DUP>;
+def MOV_N : WOpInst<"vmov_n", "ds", "dQd", OP_DUP>;
////////////////////////////////////////////////////////////////////////////////
-// Combining vectors, with additional Pl
-def COMBINE : NoTestOpInst<"vcombine", "kdd", "csilhfdUcUsUiUlPcPsPl", OP_CONC>;
+def COMBINE : NoTestOpInst<"vcombine", "kdd", "dPl", OP_CONC>;
////////////////////////////////////////////////////////////////////////////////
-//Initialize a vector from bit pattern, with additional Pl
-def CREATE : NoTestOpInst<"vcreate", "dl", "csihfdUcUsUiUlPcPslPl", OP_CAST>;
+//Initialize a vector from bit pattern
+def CREATE : NoTestOpInst<"vcreate", "dl", "dPl", OP_CAST> {
+ let BigEndianSafe = 1;
+}
////////////////////////////////////////////////////////////////////////////////
@@ -901,7 +1108,9 @@ 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">;
+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>;
@@ -933,7 +1142,7 @@ 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",
- "sifUsUiQsQiQfQUsQUiQfQd", OP_MUL_LN>;
+ "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>;
@@ -965,12 +1174,11 @@ def FMINNMV : SInst<"vminnmv", "sd", "fQfQd">;
////////////////////////////////////////////////////////////////////////////////
// Newly added Vector Extract for f64
-def VEXT_A64 : WInst<"vext", "dddi",
- "cUcPcsUsPsiUilUlfdQcQUcQPcQsQUsQPsQiQUiQlQUlQfQdPlQPl">;
+def VEXT_A64 : WInst<"vext", "dddi", "dQdPlQPl">;
////////////////////////////////////////////////////////////////////////////////
// Crypto
-let isCrypto = 1 in {
+let ArchGuard = "__ARM_FEATURE_CRYPTO" in {
def AESE : SInst<"vaese", "ddd", "QUc">;
def AESD : SInst<"vaesd", "ddd", "QUc">;
def AESMC : SInst<"vaesmc", "dd", "QUc">;
@@ -990,6 +1198,31 @@ 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">;
+}
+
+////////////////////////////////////////////////////////////////////////////////
// Permutation
def VTRN1 : SOpInst<"vtrn1", "ddd",
"csiUcUsUifPcPsQcQsQiQlQUcQUsQUiQUlQfQdQPcQPsQPl", OP_TRN1>;
@@ -1021,11 +1254,17 @@ def VQTBX4_A64 : WInst<"vqtbx4", "ddDt", "UccPcQUcQcQPc">;
////////////////////////////////////////////////////////////////////////////////
// Vector reinterpret cast operations
-// With additional d, Qd, pl, Qpl types
-def REINTERPRET
- : NoTestOpInst<"vreinterpret", "dd",
- "csilUcUsUiUlhfdPcPsPlQcQsQiQlQUcQUsQUiQUlQhQfQdQPcQPsQPl", OP_REINT>;
+// 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
@@ -1042,10 +1281,8 @@ def SCALAR_SUB : SInst<"vsub", "sss", "SlSUl">;
def SCALAR_QSUB : SInst<"vqsub", "sss", "ScSsSiSlSUcSUsSUiSUl">;
let InstName = "vmov" in {
-def VGET_HIGH_A64 : NoTestOpInst<"vget_high", "dk", "csilhfdUcUsUiUlPcPsPl",
- OP_HI>;
-def VGET_LOW_A64 : NoTestOpInst<"vget_low", "dk", "csilhfdUcUsUiUlPcPsPl",
- OP_LO>;
+def VGET_HIGH_A64 : NoTestOpInst<"vget_high", "dk", "dPl", OP_HI>;
+def VGET_LOW_A64 : NoTestOpInst<"vget_low", "dk", "dPl", OP_LO>;
}
////////////////////////////////////////////////////////////////////////////////
@@ -1282,11 +1519,11 @@ 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_LNQ>;
+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_LNQ>;
+def SCALAR_FMULX_LANEQ : IOpInst<"vmulx_laneq", "ssji", "SfSd", OP_SCALAR_MULX_LN>;
def SCALAR_VMUL_N : IInst<"vmul_n", "dds", "d">;
@@ -1294,7 +1531,9 @@ def SCALAR_VMUL_N : IInst<"vmul_n", "dds", "d">;
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">;
+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>;
@@ -1312,7 +1551,7 @@ 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_LNQ>;
+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">;
@@ -1324,15 +1563,18 @@ 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_LNQ>;
+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_LNQ>;
+def SCALAR_SQRDMULH_LANEQ : SOpInst<"vqrdmulh_laneq", "ssji", "SsSi", OP_SCALAR_QRDMULH_LN>;
def SCALAR_VDUP_LANE : IInst<"vdup_lane", "sdi", "ScSsSiSlSfSdSUcSUsSUiSUlSPcSPs">;
def SCALAR_VDUP_LANEQ : IInst<"vdup_laneq", "sji", "ScSsSiSlSfSdSUcSUsSUiSUlSPcSPs">;
-def SCALAR_GET_LANE : IOpInst<"vget_lane", "sdi", "hQh", OP_SCALAR_GET_LN>;
-def SCALAR_SET_LANE : IOpInst<"vset_lane", "dsdi", "hQh", OP_SCALAR_SET_LN>;
+// FIXME: Rename so it is obvious this only applies to halfs.
+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>;
}
diff --git a/include/clang/CMakeLists.txt b/include/clang/CMakeLists.txt
index 71c37fda7891..1d8aecd3b24e 100644
--- a/include/clang/CMakeLists.txt
+++ b/include/clang/CMakeLists.txt
@@ -1,7 +1,6 @@
add_subdirectory(AST)
add_subdirectory(Basic)
add_subdirectory(Driver)
-add_subdirectory(Lex)
add_subdirectory(Parse)
add_subdirectory(Sema)
add_subdirectory(Serialization)
diff --git a/include/clang/CodeGen/BackendUtil.h b/include/clang/CodeGen/BackendUtil.h
index 135b6a927f9a..f8b90b34eeec 100644
--- a/include/clang/CodeGen/BackendUtil.h
+++ b/include/clang/CodeGen/BackendUtil.h
@@ -21,7 +21,7 @@ namespace clang {
class CodeGenOptions;
class TargetOptions;
class LangOptions;
-
+
enum BackendAction {
Backend_EmitAssembly, ///< Emit native assembly files
Backend_EmitBC, ///< Emit LLVM bitcode files
@@ -30,11 +30,11 @@ namespace clang {
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,
- llvm::Module *M,
- BackendAction Action, raw_ostream *OS);
+ StringRef TDesc, llvm::Module *M, BackendAction Action,
+ raw_ostream *OS);
}
#endif
diff --git a/include/clang/CodeGen/CGFunctionInfo.h b/include/clang/CodeGen/CGFunctionInfo.h
index 96da0e9de1ad..449827e02891 100644
--- a/include/clang/CodeGen/CGFunctionInfo.h
+++ b/include/clang/CodeGen/CGFunctionInfo.h
@@ -19,21 +19,23 @@
#include "clang/AST/CanonicalType.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 {
+ 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
@@ -60,86 +62,130 @@ public:
/// are all scalar types or are themselves expandable types.
Expand,
- KindFirst=Direct, KindLast=Expand
+ /// InAlloca - Pass the argument directly using the LLVM inalloca attribute.
+ /// This is similar to 'direct', 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:
- Kind TheKind;
- llvm::Type *TypeData;
+ llvm::Type *TypeData; // isDirect() || isExtend()
llvm::Type *PaddingType;
- unsigned UIntData;
- bool BoolData0;
- bool BoolData1;
- bool InReg;
- bool PaddingInReg;
+ 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()
- ABIArgInfo(Kind K, llvm::Type *TD, unsigned UI, bool B0, bool B1, bool IR,
- bool PIR, llvm::Type* P)
- : TheKind(K), TypeData(TD), PaddingType(P), UIntData(UI), BoolData0(B0),
- BoolData1(B1), InReg(IR), PaddingInReg(PIR) {}
+ ABIArgInfo(Kind K)
+ : PaddingType(nullptr), TheKind(K), PaddingInReg(false), InReg(false) {}
public:
- ABIArgInfo() : TheKind(Direct), TypeData(0), UIntData(0) {}
-
- static ABIArgInfo getDirect(llvm::Type *T = 0, unsigned Offset = 0,
- llvm::Type *Padding = 0) {
- return ABIArgInfo(Direct, T, Offset, false, false, false, false, Padding);
- }
- static ABIArgInfo getDirectInReg(llvm::Type *T = 0) {
- return ABIArgInfo(Direct, T, 0, false, false, true, false, 0);
- }
- static ABIArgInfo getExtend(llvm::Type *T = 0) {
- return ABIArgInfo(Extend, T, 0, false, false, false, false, 0);
- }
- static ABIArgInfo getExtendInReg(llvm::Type *T = 0) {
- return ABIArgInfo(Extend, T, 0, false, false, true, false, 0);
+ 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) {
+ auto AI = ABIArgInfo(Direct);
+ AI.setCoerceToType(T);
+ AI.setDirectOffset(Offset);
+ AI.setPaddingType(Padding);
+ 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, 0, 0, false, false, false, false, 0);
- }
- static ABIArgInfo getIndirect(unsigned Alignment, bool ByVal = true
- , bool Realign = false
- , llvm::Type *Padding = 0) {
- return ABIArgInfo(Indirect, 0, Alignment, ByVal, Realign, false, false,
- Padding);
- }
- static ABIArgInfo getIndirectInReg(unsigned Alignment, bool ByVal = true
- , bool Realign = false) {
- return ABIArgInfo(Indirect, 0, Alignment, ByVal, Realign, true, false, 0);
+ return ABIArgInfo(Ignore);
+ }
+ static ABIArgInfo getIndirect(unsigned 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(unsigned 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, 0, 0, false, false, false, false, 0);
+ return ABIArgInfo(Expand);
}
static ABIArgInfo getExpandWithPadding(bool PaddingInReg,
llvm::Type *Padding) {
- return ABIArgInfo(Expand, 0, 0, false, false, false, PaddingInReg,
- 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 TheKind == Direct || TheKind == Extend;
- }
+ bool canHaveCoerceToType() const { return isDirect() || isExtend(); }
// Direct/Extend accessors
unsigned getDirectOffset() const {
assert((isDirect() || isExtend()) && "Not a direct or extend kind");
- return UIntData;
+ return DirectOffset;
}
-
- llvm::Type *getPaddingType() const {
- return PaddingType;
+ 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!");
@@ -156,20 +202,67 @@ public:
return InReg;
}
+ void setInReg(bool IR) {
+ assert((isDirect() || isExtend() || isIndirect()) && "Invalid kind!");
+ InReg = IR;
+ }
+
// Indirect accessors
unsigned getIndirectAlign() const {
- assert(TheKind == Indirect && "Invalid kind!");
- return UIntData;
+ assert(isIndirect() && "Invalid kind!");
+ return IndirectAlign;
+ }
+ void setIndirectAlign(unsigned IA) {
+ assert(isIndirect() && "Invalid kind!");
+ IndirectAlign = IA;
}
bool getIndirectByVal() const {
- assert(TheKind == Indirect && "Invalid kind!");
- return BoolData0;
+ assert(isIndirect() && "Invalid kind!");
+ return IndirectByVal;
+ }
+ void setIndirectByVal(unsigned IBV) {
+ assert(isIndirect() && "Invalid kind!");
+ IndirectByVal = IBV;
}
bool getIndirectRealign() const {
- assert(TheKind == Indirect && "Invalid kind!");
- return BoolData1;
+ 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;
}
void dump() const;
@@ -195,7 +288,7 @@ public:
static RequiredArgs forPrototypePlus(const FunctionProtoType *prototype,
unsigned additional) {
if (!prototype->isVariadic()) return All;
- return RequiredArgs(prototype->getNumArgs() + additional);
+ return RequiredArgs(prototype->getNumParams() + additional);
}
static RequiredArgs forPrototype(const FunctionProtoType *prototype) {
@@ -243,6 +336,9 @@ class CGFunctionInfo : public llvm::FoldingSetNode {
/// The clang::CallingConv that this was originally created with.
unsigned ASTCallingConvention : 8;
+ /// Whether this is an instance method.
+ unsigned InstanceMethod : 1;
+
/// Whether this function is noreturn.
unsigned NoReturn : 1;
@@ -255,6 +351,10 @@ class CGFunctionInfo : public llvm::FoldingSetNode {
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 NumArgs;
ArgInfo *getArgsBuffer() {
return reinterpret_cast<ArgInfo*>(this+1);
@@ -267,6 +367,7 @@ class CGFunctionInfo : public llvm::FoldingSetNode {
public:
static CGFunctionInfo *create(unsigned llvmCC,
+ bool InstanceMethod,
const FunctionType::ExtInfo &extInfo,
CanQualType resultType,
ArrayRef<CanQualType> argTypes,
@@ -275,6 +376,14 @@ public:
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; }
@@ -285,6 +394,8 @@ public:
bool isVariadic() const { return Required.allowsOptionalArgs(); }
RequiredArgs getRequiredArgs() const { return Required; }
+ bool isInstanceMethod() const { return InstanceMethod; }
+
bool isNoReturn() const { return NoReturn; }
/// In ARC, whether this function retains its return value. This
@@ -325,23 +436,33 @@ public:
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; }
+ void setArgStruct(llvm::StructType *Ty) { ArgStruct = Ty; }
+
void Profile(llvm::FoldingSetNodeID &ID) {
ID.AddInteger(getASTCallingConvention());
+ ID.AddBoolean(InstanceMethod);
ID.AddBoolean(NoReturn);
ID.AddBoolean(ReturnsRetained);
ID.AddBoolean(HasRegParm);
ID.AddInteger(RegParm);
ID.AddInteger(Required.getOpaqueData());
getReturnType().Profile(ID);
- for (arg_iterator it = arg_begin(), ie = arg_end(); it != ie; ++it)
- it->type.Profile(ID);
+ for (const auto &I : arguments())
+ I.type.Profile(ID);
}
static void Profile(llvm::FoldingSetNodeID &ID,
+ bool InstanceMethod,
const FunctionType::ExtInfo &info,
RequiredArgs required,
CanQualType resultType,
ArrayRef<CanQualType> argTypes) {
ID.AddInteger(info.getCC());
+ ID.AddBoolean(InstanceMethod);
ID.AddBoolean(info.getNoReturn());
ID.AddBoolean(info.getProducesResult());
ID.AddBoolean(info.getHasRegParm());
diff --git a/include/clang/CodeGen/CodeGenABITypes.h b/include/clang/CodeGen/CodeGenABITypes.h
index 81e2cdc1901b..2502982b23fb 100644
--- a/include/clang/CodeGen/CodeGenABITypes.h
+++ b/include/clang/CodeGen/CodeGenABITypes.h
@@ -47,10 +47,7 @@ class CodeGenModule;
class CodeGenABITypes
{
public:
- CodeGenABITypes(ASTContext &C, const CodeGenOptions &CodeGenOpts,
- llvm::Module &M, const llvm::DataLayout &TD,
- DiagnosticsEngine &Diags);
-
+ CodeGenABITypes(ASTContext &C, llvm::Module &M, const llvm::DataLayout &TD);
~CodeGenABITypes();
/// These methods all forward to methods in the private implementation class
@@ -65,12 +62,18 @@ public:
CanQual<FunctionNoProtoType> Ty);
const CGFunctionInfo &arrangeCXXMethodType(const CXXRecordDecl *RD,
const FunctionProtoType *FTP);
- const CGFunctionInfo &arrangeLLVMFunctionInfo(CanQualType returnType,
- llvm::ArrayRef<CanQualType> argTypes,
- FunctionType::ExtInfo info,
- RequiredArgs args);
+ 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.
+ CodeGenOptions *CGO;
+
+ /// The CodeGenModule we use get to the CodeGenTypes object.
CodeGen::CodeGenModule *CGM;
};
diff --git a/include/clang/CodeGen/CodeGenAction.h b/include/clang/CodeGen/CodeGenAction.h
index 912ef01a018c..37819c780d5d 100644
--- a/include/clang/CodeGen/CodeGenAction.h
+++ b/include/clang/CodeGen/CodeGenAction.h
@@ -11,7 +11,7 @@
#define LLVM_CLANG_CODEGEN_CODE_GEN_ACTION_H
#include "clang/Frontend/FrontendAction.h"
-#include "llvm/ADT/OwningPtr.h"
+#include <memory>
namespace llvm {
class LLVMContext;
@@ -24,7 +24,7 @@ class BackendConsumer;
class CodeGenAction : public ASTFrontendAction {
private:
unsigned Act;
- OwningPtr<llvm::Module> TheModule;
+ std::unique_ptr<llvm::Module> TheModule;
llvm::Module *LinkModule;
llvm::LLVMContext *VMContext;
bool OwnsVMContext;
@@ -33,16 +33,16 @@ 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 = 0);
+ CodeGenAction(unsigned _Act, llvm::LLVMContext *_VMContext = nullptr);
- virtual bool hasIRSupport() const;
+ bool hasIRSupport() const override;
- virtual ASTConsumer *CreateASTConsumer(CompilerInstance &CI,
- StringRef InFile);
+ ASTConsumer *CreateASTConsumer(CompilerInstance &CI,
+ StringRef InFile) override;
- virtual void ExecuteAction();
+ void ExecuteAction() override;
- virtual void EndSourceFileAction();
+ void EndSourceFileAction() override;
public:
~CodeGenAction();
@@ -65,37 +65,37 @@ public:
class EmitAssemblyAction : public CodeGenAction {
virtual void anchor();
public:
- EmitAssemblyAction(llvm::LLVMContext *_VMContext = 0);
+ EmitAssemblyAction(llvm::LLVMContext *_VMContext = nullptr);
};
class EmitBCAction : public CodeGenAction {
virtual void anchor();
public:
- EmitBCAction(llvm::LLVMContext *_VMContext = 0);
+ EmitBCAction(llvm::LLVMContext *_VMContext = nullptr);
};
class EmitLLVMAction : public CodeGenAction {
virtual void anchor();
public:
- EmitLLVMAction(llvm::LLVMContext *_VMContext = 0);
+ EmitLLVMAction(llvm::LLVMContext *_VMContext = nullptr);
};
class EmitLLVMOnlyAction : public CodeGenAction {
virtual void anchor();
public:
- EmitLLVMOnlyAction(llvm::LLVMContext *_VMContext = 0);
+ EmitLLVMOnlyAction(llvm::LLVMContext *_VMContext = nullptr);
};
class EmitCodeGenOnlyAction : public CodeGenAction {
virtual void anchor();
public:
- EmitCodeGenOnlyAction(llvm::LLVMContext *_VMContext = 0);
+ EmitCodeGenOnlyAction(llvm::LLVMContext *_VMContext = nullptr);
};
class EmitObjAction : public CodeGenAction {
virtual void anchor();
public:
- EmitObjAction(llvm::LLVMContext *_VMContext = 0);
+ EmitObjAction(llvm::LLVMContext *_VMContext = nullptr);
};
}
diff --git a/include/clang/CodeGen/ModuleBuilder.h b/include/clang/CodeGen/ModuleBuilder.h
index cda7863445cf..4b7236bfd03b 100644
--- a/include/clang/CodeGen/ModuleBuilder.h
+++ b/include/clang/CodeGen/ModuleBuilder.h
@@ -27,12 +27,14 @@ namespace clang {
class LangOptions;
class CodeGenOptions;
class TargetOptions;
+ 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.
diff --git a/include/clang/Config/config.h.cmake b/include/clang/Config/config.h.cmake
index c18c4cc86f76..7629ef9129b1 100644
--- a/include/clang/Config/config.h.cmake
+++ b/include/clang/Config/config.h.cmake
@@ -1,3 +1,10 @@
+/* This generated file is for internal use. Do not include it from headers. */
+
+#ifdef CONFIG_H
+#error config.h can only be included once
+#else
+#define CONFIG_H
+
/* Bug report URL. */
#define BUG_REPORT_URL "${BUG_REPORT_URL}"
@@ -12,3 +19,11 @@
/* Directory where gcc is installed. */
#define GCC_INSTALL_PREFIX "${GCC_INSTALL_PREFIX}"
+
+/* Define if we have libxml2 */
+#cmakedefine CLANG_HAVE_LIBXML ${CLANG_HAVE_LIBXML}
+
+/* The LLVM product name and version */
+#define BACKEND_PACKAGE_STRING "${BACKEND_PACKAGE_STRING}"
+
+#endif
diff --git a/include/clang/Config/config.h.in b/include/clang/Config/config.h.in
index 8ff94178e27e..1530fefaa53d 100644
--- a/include/clang/Config/config.h.in
+++ b/include/clang/Config/config.h.in
@@ -1,6 +1,8 @@
-/* include/clang/Config/config.h.in. */
+/* This generated file is for internal use. Do not include it from headers. */
-#ifndef CONFIG_H
+#ifdef CONFIG_H
+#error config.h can only be included once
+#else
#define CONFIG_H
/* Bug report URL. */
@@ -21,4 +23,12 @@
/* Directory where gcc is installed. */
#undef GCC_INSTALL_PREFIX
+/* Define if we have libxml2 */
+#undef CLANG_HAVE_LIBXML
+
+#undef PACKAGE_STRING
+
+/* The LLVM product name and version */
+#define BACKEND_PACKAGE_STRING PACKAGE_STRING
+
#endif
diff --git a/include/clang/Driver/Action.h b/include/clang/Driver/Action.h
index 289dbe3ee4f8..2cdb581b85c3 100644
--- a/include/clang/Driver/Action.h
+++ b/include/clang/Driver/Action.h
@@ -50,10 +50,11 @@ public:
LinkJobClass,
LipoJobClass,
DsymutilJobClass,
- VerifyJobClass,
+ VerifyDebugInfoJobClass,
+ VerifyPCHJobClass,
JobClassFirst=PreprocessJobClass,
- JobClassLast=VerifyJobClass
+ JobClassLast=VerifyPCHJobClass
};
static const char *getClassName(ActionClass AC);
@@ -141,7 +142,7 @@ public:
};
class PreprocessJobAction : public JobAction {
- virtual void anchor();
+ void anchor() override;
public:
PreprocessJobAction(Action *Input, types::ID OutputType);
@@ -151,7 +152,7 @@ public:
};
class PrecompileJobAction : public JobAction {
- virtual void anchor();
+ void anchor() override;
public:
PrecompileJobAction(Action *Input, types::ID OutputType);
@@ -161,7 +162,7 @@ public:
};
class AnalyzeJobAction : public JobAction {
- virtual void anchor();
+ void anchor() override;
public:
AnalyzeJobAction(Action *Input, types::ID OutputType);
@@ -171,7 +172,7 @@ public:
};
class MigrateJobAction : public JobAction {
- virtual void anchor();
+ void anchor() override;
public:
MigrateJobAction(Action *Input, types::ID OutputType);
@@ -181,7 +182,7 @@ public:
};
class CompileJobAction : public JobAction {
- virtual void anchor();
+ void anchor() override;
public:
CompileJobAction(Action *Input, types::ID OutputType);
@@ -191,7 +192,7 @@ public:
};
class AssembleJobAction : public JobAction {
- virtual void anchor();
+ void anchor() override;
public:
AssembleJobAction(Action *Input, types::ID OutputType);
@@ -201,7 +202,7 @@ public:
};
class LinkJobAction : public JobAction {
- virtual void anchor();
+ void anchor() override;
public:
LinkJobAction(ActionList &Inputs, types::ID Type);
@@ -211,7 +212,7 @@ public:
};
class LipoJobAction : public JobAction {
- virtual void anchor();
+ void anchor() override;
public:
LipoJobAction(ActionList &Inputs, types::ID Type);
@@ -221,7 +222,7 @@ public:
};
class DsymutilJobAction : public JobAction {
- virtual void anchor();
+ void anchor() override;
public:
DsymutilJobAction(ActionList &Inputs, types::ID Type);
@@ -231,11 +232,31 @@ public:
};
class VerifyJobAction : public JobAction {
- virtual void anchor();
+ void anchor() override;
+public:
+ VerifyJobAction(ActionClass Kind, Action *Input, types::ID Type);
+ VerifyJobAction(ActionClass Kind, ActionList &Inputs, 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(Action *Input, types::ID Type);
+ static bool classof(const Action *A) {
+ return A->getKind() == VerifyDebugInfoJobClass;
+ }
+};
+
+class VerifyPCHJobAction : public VerifyJobAction {
+ void anchor() override;
public:
- VerifyJobAction(ActionList &Inputs, types::ID Type);
+ VerifyPCHJobAction(Action *Input, types::ID Type);
static bool classof(const Action *A) {
- return A->getKind() == VerifyJobClass;
+ return A->getKind() == VerifyPCHJobClass;
}
};
diff --git a/include/clang/Driver/CC1AsOptions.h b/include/clang/Driver/CC1AsOptions.h
deleted file mode 100644
index 345f50a57d5f..000000000000
--- a/include/clang/Driver/CC1AsOptions.h
+++ /dev/null
@@ -1,37 +0,0 @@
-//===--- CC1AsOptions.h - Clang Assembler Options Table ---------*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef CLANG_DRIVER_CC1ASOPTIONS_H
-#define CLANG_DRIVER_CC1ASOPTIONS_H
-
-namespace llvm {
-namespace opt {
- class OptTable;
-}
-}
-
-namespace clang {
-namespace driver {
-
-namespace cc1asoptions {
- 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/CC1AsOptions.inc"
- LastOption
-#undef OPTION
- };
-}
-
-llvm::opt::OptTable *createCC1AsOptTable();
-}
-}
-
-#endif
diff --git a/include/clang/Driver/CC1AsOptions.td b/include/clang/Driver/CC1AsOptions.td
deleted file mode 100644
index b536724f2425..000000000000
--- a/include/clang/Driver/CC1AsOptions.td
+++ /dev/null
@@ -1,95 +0,0 @@
-//===--- CC1AsOptions.td - Options for clang -cc1as -----------------------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This file defines the options accepted by clang -cc1as.
-//
-//===----------------------------------------------------------------------===//
-
-// Include the common option parsing interfaces.
-include "llvm/Option/OptParser.td"
-
-//===----------------------------------------------------------------------===//
-// Target Options
-//===----------------------------------------------------------------------===//
-
-def triple : Separate<["-"], "triple">,
- HelpText<"Specify target triple (e.g. x86_64-pc-linux-gnu)">;
-def target_cpu : Separate<["-"], "target-cpu">,
- HelpText<"Target a specific cpu type">;
-def target_feature : Separate<["-"], "target-feature">,
- HelpText<"Target specific attributes">;
-
-//===----------------------------------------------------------------------===//
-// Language Options
-//===----------------------------------------------------------------------===//
-
-def I : JoinedOrSeparate<["-"], "I">, MetaVarName<"<directory>">,
- HelpText<"Add directory to include search path">;
-def n : Flag<["-"], "n">,
- HelpText<"Don't automatically start assembly file with a text section">;
-def msave_temp_labels : Flag<["-"], "msave-temp-labels">,
- HelpText<"Save temporary labels in the symbol table. "
- "Note this may change .s semantics, it should almost never be used "
- "on compiler generated code!">;
-def main_file_name : Separate<["-"], "main-file-name">,
- HelpText<"Main file name to use for debug info">;
-
-//===----------------------------------------------------------------------===//
-// Frontend Options
-//===----------------------------------------------------------------------===//
-
-def o : Separate<["-"], "o">, MetaVarName<"<path>">,
- HelpText<"Specify output file">;
-
-def filetype : Separate<["-"], "filetype">,
- HelpText<"Specify the output file type ('asm', 'null', or 'obj')">;
-
-def help : Flag<["-", "--"], "help">,
- HelpText<"Print this help text">;
-
-def version : Flag<["-", "--"], "version">,
- HelpText<"Print the assembler version">;
-def v : Flag<["-"], "v">, Alias<version>;
-
-// Generic forwarding to LLVM options. This should only be used for debugging
-// and experimental features.
-def mllvm : Separate<["-"], "mllvm">,
- HelpText<"Additional arguments to forward to LLVM's option processing">;
-
-//===----------------------------------------------------------------------===//
-// Transliterate Options
-//===----------------------------------------------------------------------===//
-
-def output_asm_variant : Separate<["-"], "output-asm-variant">,
- HelpText<"Select the asm variant index to use for output">;
-def show_encoding : Flag<["-"], "show-encoding">,
- HelpText<"Show instruction encoding information in transliterate mode">;
-def show_inst : Flag<["-"], "show-inst">,
- HelpText<"Show internal instruction representation in transliterate mode">;
-
-//===----------------------------------------------------------------------===//
-// Assemble Options
-//===----------------------------------------------------------------------===//
-
-def mrelax_all : Flag<["-"], "mrelax-all">,
- HelpText<"Relax all fixups (for performance testing)">;
-
-def mno_exec_stack : Flag<["-"], "mnoexecstack">,
- HelpText<"Mark the file as not needing an executable stack">;
-
-def g : Flag<["-"], "g">, HelpText<"Generate source level debug information">;
-
-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 dwarf_debug_producer : Separate<["-"], "dwarf-debug-producer">,
- HelpText<"The string to embed in the Dwarf debug AT_producer record.">;
diff --git a/include/clang/Driver/CC1Options.h b/include/clang/Driver/CC1Options.h
deleted file mode 100644
index e69de29bb2d1..000000000000
--- a/include/clang/Driver/CC1Options.h
+++ /dev/null
diff --git a/include/clang/Driver/CC1Options.td b/include/clang/Driver/CC1Options.td
index 85cfdcf3946b..d25560c9f3ac 100644
--- a/include/clang/Driver/CC1Options.td
+++ b/include/clang/Driver/CC1Options.td
@@ -7,7 +7,7 @@
//
//===----------------------------------------------------------------------===//
//
-// This file defines the options accepted by clang -cc1.
+// This file defines the options accepted by clang -cc1 and clang -cc1as.
//
//===----------------------------------------------------------------------===//
@@ -17,21 +17,24 @@ let Flags = [CC1Option, NoDriverOption] in {
// Target Options
//===----------------------------------------------------------------------===//
-def cxx_abi : Separate<["-"], "cxx-abi">,
- HelpText<"Target a particular C++ ABI type">;
-def target_abi : Separate<["-"], "target-abi">,
- HelpText<"Target a particular ABI type">;
+let Flags = [CC1Option, CC1AsOption, NoDriverOption] in {
+
def target_cpu : Separate<["-"], "target-cpu">,
HelpText<"Target a specific cpu type">;
-def mfpmath : Separate<["-"], "mfpmath">,
- HelpText<"Which unit to use for fp math">;
def target_feature : Separate<["-"], "target-feature">,
HelpText<"Target specific attributes">;
-def target_linker_version : Separate<["-"], "target-linker-version">,
- HelpText<"Target linker version">;
def triple : Separate<["-"], "triple">,
HelpText<"Specify target triple (e.g. i686-apple-darwin9)">;
+
+}
+
+def 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
@@ -124,22 +127,37 @@ def migrator_no_finalize_removal : Flag<["-"], "no-finalize-removal">,
// CodeGen Options
//===----------------------------------------------------------------------===//
+let Flags = [CC1Option, CC1AsOption, NoDriverOption] in {
+
+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 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 disable_llvm_optzns : Flag<["-"], "disable-llvm-optzns">,
HelpText<"Don't run LLVM optimization passes">;
def disable_llvm_verifier : Flag<["-"], "disable-llvm-verifier">,
HelpText<"Don't run the LLVM IR verifier pass">;
def disable_red_zone : Flag<["-"], "disable-red-zone">,
HelpText<"Do not emit code that uses the red zone.">;
-def 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 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 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">,
@@ -188,8 +206,6 @@ def mfloat_abi : Separate<["-"], "mfloat-abi">,
HelpText<"The float ABI to use">;
def mlimit_float_precision : Separate<["-"], "mlimit-float-precision">,
HelpText<"Limit float precision to the given value">;
-def mno_exec_stack : Flag<["-"], "mnoexecstack">,
- HelpText<"Mark the file as not needing an executable stack">;
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">,
@@ -198,8 +214,6 @@ 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 msave_temp_labels : Flag<["-"], "msave-temp-labels">,
- HelpText<"(integrated-as) Save temporary labels">;
def mrelocation_model : Separate<["-"], "mrelocation-model">,
HelpText<"The relocation model to use">;
def munwind_tables : Flag<["-"], "munwind-tables">,
@@ -223,10 +237,12 @@ def dependent_lib : Joined<["--"], "dependent-lib=">,
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 stderr">;
+ HelpText<"Print cl.exe style /showIncludes to stdout">;
//===----------------------------------------------------------------------===//
// Diagnostic Options
@@ -256,6 +272,8 @@ def fconstexpr_backtrace_limit : Separate<["-"], "fconstexpr-backtrace-limit">,
HelpText<"Set the maximum number of entries to print in a constexpr evaluation backtrace (0 = no limit).">;
def fmessage_length : Separate<["-"], "fmessage-length">, MetaVarName<"<N>">,
HelpText<"Format message diagnostics so that they fit within N columns or fewer, when possible.">;
+def verify : Flag<["-"], "verify">,
+ HelpText<"Verify diagnostic output using comment directives">;
def Wno_rewrite_macros : Flag<["-"], "Wno-rewrite-macros">,
HelpText<"Silence ObjC rewriting warnings">;
@@ -266,6 +284,7 @@ def Wno_rewrite_macros : Flag<["-"], "Wno-rewrite-macros">,
// 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>">,
@@ -297,8 +316,6 @@ def plugin_arg : JoinedAndSeparate<["-"], "plugin-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 version : Flag<["-"], "version">,
- HelpText<"Print the compiler version">;
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"
@@ -308,6 +325,8 @@ def ast_dump_lookups : Flag<["-"], "ast-dump-lookups">,
HelpText<"Include name lookup table dumps in AST dumps">;
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">;
let Group = Action_Group in {
@@ -393,14 +412,19 @@ def foverride_record_layout_EQ : Joined<["-"], "foverride-record-layout=">,
// 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 fhidden_weak_vtables : Flag<["-"], "fhidden-weak-vtables">,
- HelpText<"Generate weak vtables and RTTI with hidden visibility">;
-def main_file_name : Separate<["-"], "main-file-name">,
- HelpText<"Main file name to use for debug info">;
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">,
@@ -476,6 +500,10 @@ def fsized_deallocation : Flag<["-"], "fsized-deallocation">,
HelpText<"Enable C++1y sized global deallocation functions">;
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">;
//===----------------------------------------------------------------------===//
// Header Search Options
@@ -504,14 +532,6 @@ def internal_externc_isystem : JoinedOrSeparate<["-"], "internal-externc-isystem
"implicit extern \"C\" semantics; these are assumed to not be "
"user-provided and are used to model system and standard headers' "
"paths.">;
-def isystem_prefix : JoinedOrSeparate<["-"], "isystem-prefix">,
- MetaVarName<"<prefix>">,
- HelpText<"Treat all #include paths starting with <prefix> as including a "
- "system header.">;
-def ino_system_prefix : JoinedOrSeparate<["-"], "ino-system-prefix">,
- MetaVarName<"<prefix>">,
- HelpText<"Treat all #include paths starting with <prefix> as not including a "
- "system header.">;
//===----------------------------------------------------------------------===//
// Preprocessor Options
@@ -539,6 +559,8 @@ 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">,
@@ -556,3 +578,32 @@ def fcuda_is_device : Flag<["-"], "fcuda-is-device">,
HelpText<"Generate code for CUDA device">;
} // 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/include/clang/Driver/CLCompatOptions.td b/include/clang/Driver/CLCompatOptions.td
index d17a63c62c92..7278bf868355 100644
--- a/include/clang/Driver/CLCompatOptions.td
+++ b/include/clang/Driver/CLCompatOptions.td
@@ -57,10 +57,19 @@ def _SLASH_C : CLFlag<"C">, HelpText<"Don't discard comments when preprocessing"
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_GR : CLFlag<"GR">, HelpText<"Enable RTTI">, Alias<frtti>;
-def _SLASH_GR_ : CLFlag<"GR-">, HelpText<"Disable RTTI">, Alias<fno_rtti>;
+def _SLASH_E : CLFlag<"E">, HelpText<"Preprocess to stdout">, Alias<E>;
+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_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>;
@@ -88,7 +97,6 @@ def _SLASH_Oy : CLFlag<"Oy">, HelpText<"Enable frame pointer omission">,
Alias<fomit_frame_pointer>;
def _SLASH_Oy_ : CLFlag<"Oy-">, HelpText<"Disable frame pointer omission">,
Alias<fno_omit_frame_pointer>;
-def _SLASH_P : CLFlag<"P">, HelpText<"Only run the preprocessor">, Alias<E>;
def _SLASH_QUESTION : CLFlag<"?">, Alias<help>,
HelpText<"Display available options">;
def _SLASH_showIncludes : CLFlag<"showIncludes">,
@@ -96,6 +104,16 @@ def _SLASH_showIncludes : CLFlag<"showIncludes">,
Alias<show_includes>;
def _SLASH_U : CLJoinedOrSeparate<"U">, HelpText<"Undefine macro">,
MetaVarName<"<macro>">, Alias<U>;
+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_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>;
@@ -107,14 +125,27 @@ def _SLASH_WX : CLFlag<"WX">, HelpText<"Treat warnings as errors">,
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_vd : CLJoined<"vd">, HelpText<"Control vtordisp placement">,
+ Alias<vtordisp_mode_EQ>;
+def _SLASH_Z7 : CLFlag<"Z7">, Alias<gline_tables_only>;
+def _SLASH_Zi : CLFlag<"Zi">, HelpText<"Enable debug information">,
+ Alias<gline_tables_only>;
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_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">,
@@ -127,6 +158,9 @@ def _SLASH_FI : CLJoinedOrSeparate<"FI">,
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">,
+ MetaVarName<"<file>">;
def _SLASH_Fo : CLCompileJoined<"Fo">,
HelpText<"Set output object file, or directory (ends in / or \\)">,
MetaVarName<"<file or directory>">;
@@ -142,6 +176,7 @@ 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_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">;
@@ -164,9 +199,10 @@ def _SLASH_Ob2 : CLIgnoredFlag<"Ob2">;
def _SLASH_RTC : CLIgnoredJoined<"RTC">;
def _SLASH_sdl : CLIgnoredFlag<"sdl">;
def _SLASH_sdl_ : CLIgnoredFlag<"sdl-">;
-def _SLASH_vmg : CLIgnoredFlag<"vmg">;
def _SLASH_w : CLIgnoredJoined<"w">;
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">;
@@ -174,19 +210,15 @@ def _SLASH_Zm : CLIgnoredJoined<"Zm">;
// Unsupported:
def _SLASH_AI : CLJoined<"AI">;
-def _SLASH_arch : CLJoined<"arch:">;
def _SLASH_bigobj : CLFlag<"bigobj">;
def _SLASH_clr : CLJoined<"clr">;
+def _SLASH_d2Zi_PLUS : CLFlag<"d2Zi+">;
def _SLASH_doc : CLJoined<"doc">;
-def _SLASH_E : CLFlag<"E">;
-def _SLASH_EH : CLJoined<"EH">;
-def _SLASH_EP : CLFlag<"EP">;
def _SLASH_FA_joined : CLJoined<"FA">;
def _SLASH_favor : CLJoined<"favor">;
def _SLASH_FC : CLFlag<"FC">;
def _SLASH_F : CLFlag<"F">;
def _SLASH_Fd : CLJoined<"Fd">;
-def _SLASH_Fi : CLJoined<"Fi">;
def _SLASH_Fm : CLJoined<"Fm">;
def _SLASH_fp : CLJoined<"fp">;
def _SLASH_Fp : CLJoined<"Fp">;
@@ -210,8 +242,6 @@ def _SLASH_GS : CLFlag<"GS">;
def _SLASH_Gs : CLJoined<"Gs">;
def _SLASH_GT : CLFlag<"GT">;
def _SLASH_GX : CLFlag<"GX">;
-def _SLASH_Gy : CLFlag<"Gy">;
-def _SLASH_Gy_ : CLFlag<"Gy-">;
def _SLASH_Gz : CLFlag<"Gz">;
def _SLASH_GZ : CLFlag<"GZ">;
def _SLASH_H : CLFlag<"H">;
@@ -229,11 +259,6 @@ def _SLASH_Qpar : CLFlag<"Qpar">;
def _SLASH_Qvec_report : CLJoined<"Qvec-report">;
def _SLASH_u : CLFlag<"u">;
def _SLASH_V : CLFlag<"V">;
-def _SLASH_vd : CLJoined<"vd">;
-def _SLASH_vmb : CLFlag<"vmb">;
-def _SLASH_vmm : CLFlag<"vmm">;
-def _SLASH_vms : CLFlag<"vms">;
-def _SLASH_vmv : CLFlag<"vmv">;
def _SLASH_volatile : CLFlag<"volatile">;
def _SLASH_WL : CLFlag<"WL">;
def _SLASH_Wp64 : CLFlag<"Wp64">;
@@ -243,13 +268,11 @@ def _SLASH_Y_ : CLFlag<"Y-">;
def _SLASH_Yd : CLFlag<"Yd">;
def _SLASH_Yl : CLJoined<"Yl">;
def _SLASH_Yu : CLJoined<"Yu">;
-def _SLASH_Z7 : CLFlag<"Z7">;
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_ZI : CLFlag<"ZI">;
def _SLASH_Zl : CLFlag<"Zl">;
-def _SLASH_Zp : CLFlag<"Zp">;
+def _SLASH_Zp : CLJoined<"Zp">;
def _SLASH_ZW : CLJoined<"ZW">;
diff --git a/include/clang/Driver/CMakeLists.txt b/include/clang/Driver/CMakeLists.txt
index 5961cac20ccf..a9d988047920 100644
--- a/include/clang/Driver/CMakeLists.txt
+++ b/include/clang/Driver/CMakeLists.txt
@@ -1,7 +1,3 @@
set(LLVM_TARGET_DEFINITIONS Options.td)
tablegen(LLVM Options.inc -gen-opt-parser-defs)
add_public_tablegen_target(ClangDriverOptions)
-
-set(LLVM_TARGET_DEFINITIONS CC1AsOptions.td)
-tablegen(LLVM CC1AsOptions.inc -gen-opt-parser-defs)
-add_public_tablegen_target(ClangCC1AsOptions)
diff --git a/include/clang/Driver/Compilation.h b/include/clang/Driver/Compilation.h
index 3493e4f1509b..c1c0f4326d76 100644
--- a/include/clang/Driver/Compilation.h
+++ b/include/clang/Driver/Compilation.h
@@ -69,6 +69,9 @@ class Compilation {
/// 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,
@@ -173,6 +176,9 @@ public:
/// 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() { return ForDiagnostics; }
};
} // end namespace driver
diff --git a/include/clang/Driver/Driver.h b/include/clang/Driver/Driver.h
index 73c808609355..df974ad1d760 100644
--- a/include/clang/Driver/Driver.h
+++ b/include/clang/Driver/Driver.h
@@ -15,11 +15,11 @@
#include "clang/Driver/Phases.h"
#include "clang/Driver/Types.h"
#include "clang/Driver/Util.h"
-#include "llvm/ADT/OwningPtr.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>
@@ -188,12 +188,11 @@ private:
// 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 = 0) const;
+ llvm::opt::Arg **FinalPhaseArg = nullptr) const;
public:
Driver(StringRef _ClangExecutable,
StringRef _DefaultTargetTriple,
- StringRef _DefaultImageName,
DiagnosticsEngine &_Diags);
~Driver();
@@ -259,7 +258,7 @@ public:
/// \param Args - The input arguments.
/// \param Inputs - The list to store the resulting compilation
/// inputs onto.
- void BuildInputs(const ToolChain &TC, const llvm::opt::DerivedArgList &Args,
+ void BuildInputs(const ToolChain &TC, llvm::opt::DerivedArgList &Args,
InputList &Inputs) const;
/// BuildActions - Construct the list of actions to perform for the
diff --git a/include/clang/Driver/Job.h b/include/clang/Driver/Job.h
index 1dd49a792356..5b19efeddeea 100644
--- a/include/clang/Driver/Job.h
+++ b/include/clang/Driver/Job.h
@@ -11,9 +11,9 @@
#define CLANG_DRIVER_JOB_H_
#include "clang/Basic/LLVM.h"
-#include "llvm/ADT/OwningPtr.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/Option/Option.h"
+#include <memory>
namespace llvm {
class raw_ostream;
@@ -76,8 +76,8 @@ public:
Command(const Action &_Source, const Tool &_Creator, const char *_Executable,
const llvm::opt::ArgStringList &_Arguments);
- virtual void Print(llvm::raw_ostream &OS, const char *Terminator,
- bool Quote, bool CrashReport = false) const;
+ void Print(llvm::raw_ostream &OS, const char *Terminator, bool Quote,
+ bool CrashReport = false) const override;
virtual int Execute(const StringRef **Redirects, std::string *ErrMsg,
bool *ExecutionFailed) const;
@@ -88,6 +88,8 @@ public:
/// getCreator - Return the Tool which caused the creation of this job.
const Tool &getCreator() const { return Creator; }
+ const char *getExecutable() const { return Executable; }
+
const llvm::opt::ArgStringList &getArguments() const { return Arguments; }
static bool classof(const Job *J) {
@@ -104,18 +106,18 @@ public:
const char *Executable_, const ArgStringList &Arguments_,
Command *Fallback_);
- virtual void Print(llvm::raw_ostream &OS, const char *Terminator,
- bool Quote, bool CrashReport = false) const;
+ void Print(llvm::raw_ostream &OS, const char *Terminator, bool Quote,
+ bool CrashReport = false) const override;
- virtual int Execute(const StringRef **Redirects, std::string *ErrMsg,
- bool *ExecutionFailed) const;
+ int Execute(const StringRef **Redirects, std::string *ErrMsg,
+ bool *ExecutionFailed) const override;
static bool classof(const Job *J) {
return J->getKind() == FallbackCommandClass;
}
private:
- OwningPtr<Command> Fallback;
+ std::unique_ptr<Command> Fallback;
};
/// JobList - A sequence of jobs to perform.
@@ -133,8 +135,8 @@ public:
JobList();
virtual ~JobList();
- virtual void Print(llvm::raw_ostream &OS, const char *Terminator,
- bool Quote, bool CrashReport = false) const;
+ void Print(llvm::raw_ostream &OS, const char *Terminator,
+ bool Quote, bool CrashReport = false) const override;
/// Add a job to the list (taking ownership).
void addJob(Job *J) { Jobs.push_back(J); }
diff --git a/include/clang/Driver/Makefile b/include/clang/Driver/Makefile
index 77cf6ff8d938..8309330d8bd5 100644
--- a/include/clang/Driver/Makefile
+++ b/include/clang/Driver/Makefile
@@ -1,5 +1,5 @@
CLANG_LEVEL := ../../..
-BUILT_SOURCES = Options.inc CC1AsOptions.inc
+BUILT_SOURCES = Options.inc
TABLEGEN_INC_FILES_COMMON = 1
@@ -8,7 +8,3 @@ include $(CLANG_LEVEL)/Makefile
$(ObjDir)/Options.inc.tmp : Options.td CC1Options.td CLCompatOptions.td $(LLVM_TBLGEN) $(ObjDir)/.dir
$(Echo) "Building Clang Driver Option tables with tblgen"
$(Verb) $(LLVMTableGen) -gen-opt-parser-defs -o $(call SYSPATH, $@) $<
-
-$(ObjDir)/CC1AsOptions.inc.tmp : CC1AsOptions.td $(LLVM_TBLGEN) $(ObjDir)/.dir
- $(Echo) "Building Clang CC1 Assembler Option tables with tblgen"
- $(Verb) $(LLVMTableGen) -gen-opt-parser-defs -o $(call SYSPATH, $@) $<
diff --git a/include/clang/Driver/Multilib.h b/include/clang/Driver/Multilib.h
new file mode 100644
index 000000000000..6c3738a9cc03
--- /dev/null
+++ b/include/clang/Driver/Multilib.h
@@ -0,0 +1,167 @@
+//===--- 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 CLANG_LIB_DRIVER_MULTILIB_H_
+#define CLANG_LIB_DRIVER_MULTILIB_H_
+
+#include "clang/Basic/LLVM.h"
+#include "llvm/ADT/Triple.h"
+#include "llvm/Option/Option.h"
+#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;
+
+ struct FilterCallback {
+ virtual ~FilterCallback() {};
+ /// \return true iff the filter should remove the Multilib from the set
+ virtual bool operator()(const Multilib &M) const = 0;
+ };
+
+private:
+ multilib_list Multilibs;
+
+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(const std::vector<Multilib> &Ms);
+
+ /// Filter out some subset of the Multilibs using a user defined callback
+ MultilibSet &FilterOut(const FilterCallback &F);
+ /// Filter out those Multilibs whose gccSuffix matches the given expression
+ MultilibSet &FilterOut(std::string 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;
+
+private:
+ /// Apply the filter to Multilibs and return the subset that remains
+ static multilib_list filterCopy(const FilterCallback &F,
+ const multilib_list &Ms);
+
+ /// Apply the filter to the multilib_list, removing those that don't match
+ static void filterInPlace(const FilterCallback &F, multilib_list &Ms);
+};
+
+raw_ostream &operator<<(raw_ostream &OS, const MultilibSet &MS);
+}
+}
+
+#endif
+
diff --git a/include/clang/Driver/Options.h b/include/clang/Driver/Options.h
index 28948be96dec..cee705deac63 100644
--- a/include/clang/Driver/Options.h
+++ b/include/clang/Driver/Options.h
@@ -30,7 +30,8 @@ enum ClangFlags {
CoreOption = (1 << 8),
CLOption = (1 << 9),
CC1Option = (1 << 10),
- NoDriverOption = (1 << 11)
+ CC1AsOption = (1 << 11),
+ NoDriverOption = (1 << 12)
};
enum ID {
diff --git a/include/clang/Driver/Options.td b/include/clang/Driver/Options.td
index 9e7dc78d63cf..9d4fdad46ade 100644
--- a/include/clang/Driver/Options.td
+++ b/include/clang/Driver/Options.td
@@ -44,6 +44,9 @@ 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;
@@ -60,7 +63,10 @@ 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>;
@@ -69,11 +75,11 @@ 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>;
-def m_x86_Features_Group : OptionGroup<"<m x86 features group>">, Group<m_Group>;
+def m_x86_Features_Group : OptionGroup<"<m x86 features group>">, Group<m_Group>, Flags<[CoreOption]>;
def m_hexagon_Features_Group : OptionGroup<"<m hexagon features group>">, Group<m_Group>;
def m_arm_Features_Group : OptionGroup<"<m arm features group>">, Group<m_Group>;
+def m_aarch64_Features_Group : OptionGroup<"<m aarch64 features group>">, Group<m_Group>;
def m_ppc_Features_Group : OptionGroup<"<m ppc features group>">, Group<m_Group>;
-def opencl_Group : OptionGroup<"<opencl group>">;
def u_Group : OptionGroup<"<u group>">;
def pedantic_Group : OptionGroup<"<pedantic group>">,
@@ -87,6 +93,10 @@ def clang_ignored_f_Group : OptionGroup<"<clang ignored 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
@@ -184,8 +194,13 @@ def objcmt_returns_innerpointer_property : Flag<["-"], "objcmt-returns-innerpoin
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_white_list_dir_path: Joined<["-"], "objcmt-white-list-dir-path=">, Flags<[CC1Option]>,
+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]>;
@@ -193,7 +208,7 @@ def ccc_ : Joined<["-"], "ccc-">, Group<internal_Group>, Flags<[Unsupported]>;
// Standard Options
def _HASH_HASH_HASH : Flag<["-"], "###">, Flags<[DriverOption, CoreOption]>,
- HelpText<"Print the commands to run for this compilation">;
+ 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]>;
@@ -210,23 +225,29 @@ 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]>,
+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>;
-def MF : JoinedOrSeparate<["-"], "MF">, Group<M_Group>;
+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 dependency list">;
-def MMD : Flag<["-"], "MMD">, Group<M_Group>;
-def MM : Flag<["-"], "MM">, Group<M_Group>;
+ 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 target to quote for dependency">;
+ HelpText<"Specify name of main file output to quote in depfile">;
def MT : JoinedOrSeparate<["-"], "MT">, Group<M_Group>, Flags<[CC1Option]>,
- HelpText<"Specify target for dependency">;
+ HelpText<"Specify name of main file output in depfile">;
def Mach : Flag<["-"], "Mach">;
-def M : Flag<["-"], "M">, Group<M_Group>;
def O0 : Flag<["-"], "O0">, Group<O_Group>, Flags<[CC1Option]>;
def O4 : Flag<["-"], "O4">, Group<O_Group>, Flags<[CC1Option]>;
def ObjCXX : Flag<["-"], "ObjC++">, Flags<[DriverOption]>,
@@ -242,7 +263,19 @@ 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 R : Flag<["-"], "R">;
+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>;
@@ -261,6 +294,7 @@ 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>,
@@ -268,6 +302,8 @@ def Wnonportable_cfstrings : Joined<["-"], "Wnonportable-cfstrings">, Group<W_Gr
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">,
@@ -278,6 +314,8 @@ def Xassembler : Separate<["-"], "Xassembler">,
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">,
@@ -297,8 +335,6 @@ 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 cl_kernel_arg_info : Flag<["-"], "cl-kernel-arg-info">, Flags<[CC1Option]>, Group<opencl_Group>,
-HelpText<"OpenCL only. This option allows the compiler to store information about the arguments of a kernel(s)"> ;
def client__name : JoinedOrSeparate<["-"], "client_name">;
def combine : Flag<["-", "--"], "combine">, Flags<[DriverOption, Unsupported]>;
def compatibility__version : JoinedOrSeparate<["-"], "compatibility_version">;
@@ -320,6 +356,8 @@ 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">;
@@ -346,10 +384,7 @@ 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 faddress_sanitizer : Flag<["-"], "faddress-sanitizer">, Group<f_Group>;
-def fno_address_sanitizer : Flag<["-"], "fno-address-sanitizer">, Group<f_Group>;
-def fthread_sanitizer : Flag<["-"], "fthread-sanitizer">, Group<f_Group>;
-def fno_thread_sanitizer : Flag<["-"], "fno-thread-sanitizer">, Group<f_Group>;
+def shared_libasan : Flag<["-"], "shared-libasan">;
def fasm : Flag<["-"], "fasm">, Group<f_Group>;
def fasm_blocks : Flag<["-"], "fasm-blocks">, Group<f_Group>, Flags<[CC1Option]>;
@@ -369,19 +404,23 @@ def fno_autolink : Flag <["-"], "fno-autolink">, Group<f_Group>,
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">;
+def fprofile_instr_use : Flag<["-"], "fprofile-instr-use">, Group<f_Group>;
+def fprofile_instr_use_EQ : Joined<["-"], "fprofile-instr-use=">,
+ Group<f_Group>, Flags<[CC1Option]>,
+ HelpText<"Use instrumentation data for profile-guided optimization">;
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 fbounds_checking : Flag<["-"], "fbounds-checking">, Group<f_Group>,
- HelpText<"Enable run-time bounds checks">;
-def fbounds_checking_EQ : Joined<["-"], "fbounds-checking=">, Flags<[CC1Option]>,
- Group<f_Group>;
def fbuiltin : Flag<["-"], "fbuiltin">, Group<f_Group>;
def fcaret_diagnostics : Flag<["-"], "fcaret-diagnostics">, Group<f_Group>;
-def fcatch_undefined_behavior : Flag<["-"], "fcatch-undefined-behavior">, Group<f_Group>;
def fclasspath_EQ : Joined<["-"], "fclasspath=">, Group<f_Group>;
def fcolor_diagnostics : Flag<["-"], "fcolor-diagnostics">, Group<f_Group>, Flags<[CC1Option]>,
HelpText<"Use colors in diagnostics">;
@@ -417,8 +456,6 @@ def fdiagnostics_print_source_range_info : Flag<["-"], "fdiagnostics-print-sourc
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_name : Flag<["-"], "fdiagnostics-show-name">, Group<f_Group>,
- Flags<[CC1Option]>, HelpText<"Print diagnostic name">;
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>;
@@ -428,8 +465,8 @@ def fdiagnostics_show_template_tree : Flag<["-"], "fdiagnostics-show-template-tr
HelpText<"Print a template comparison tree for differing templates">;
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<f_Group>;
-def fno_dwarf2_cfi_asm : Flag<["-"], "fno-dwarf2-cfi-asm">, Group<f_Group>, 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>;
@@ -440,18 +477,16 @@ def feliminate_unused_debug_symbols : Flag<["-"], "feliminate-unused-debug-symbo
def femit_all_decls : Flag<["-"], "femit-all-decls">, Group<f_Group>, Flags<[CC1Option]>,
HelpText<"Emit all declarations, even if unused">;
def fencoding_EQ : Joined<["-"], "fencoding=">, Group<f_Group>;
-def ferror_limit_EQ : Joined<["-"], "ferror-limit=">, 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 fexpensive_optimizations : Flag<["-"], "fexpensive-optimizations">,
- Group<clang_ignored_f_Group>;
-def fno_expensive_optimizations : Flag<["-"], "fno-expensive-optimizations">,
- Group<clang_ignored_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 fextended_identifiers : Flag<["-"], "fextended-identifiers">,
- Group<clang_ignored_f_Group>;
-def fno_extended_identifiers : Flag<["-"], "fno-extended-identifiers">,
- Group<f_Group>, Flags<[Unsupported]>;
+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 "
@@ -470,23 +505,21 @@ def fsanitize_EQ : CommaJoined<["-"], "fsanitize=">, Group<f_clang_Group>,
"address (memory errors) | thread (race detection) | "
"undefined (miscellaneous undefined behavior)">;
def fno_sanitize_EQ : CommaJoined<["-"], "fno-sanitize=">, Group<f_clang_Group>;
-def fsanitize_address_zero_base_shadow : Flag<["-"], "fsanitize-address-zero-base-shadow">,
- Group<f_clang_Group>, Flags<[CC1Option]>,
- HelpText<"Make AddressSanitizer map shadow memory "
- "at zero offset">;
-def fno_sanitize_address_zero_base_shadow : Flag<["-"], "fno-sanitize-address-zero-base-shadow">,
- Group<f_clang_Group>;
def fsanitize_blacklist : Joined<["-"], "fsanitize-blacklist=">,
- Group<f_clang_Group>, Flags<[CC1Option]>,
+ 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_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>;
+ Group<f_clang_Group>, Flags<[CC1Option]>,
+ HelpText<"Disable origins tracking in MemorySanitizer">;
def fsanitize_recover : Flag<["-"], "fsanitize-recover">,
Group<f_clang_Group>;
def fno_sanitize_recover : Flag<["-"], "fno-sanitize-recover">,
@@ -512,9 +545,9 @@ 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>;
-// Sic. This option was misspelled originally.
-def fhonor_infinites : Flag<["-"], "fhonor-infinites">, Alias<fhonor_infinities>;
-def fno_honor_infinites : Flag<["-"], "fno-honor-infinites">, Alias<fno_honor_infinities>;
+// 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>,
@@ -539,16 +572,14 @@ 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 findirect_virtual_calls : Flag<["-"], "findirect-virtual-calls">, Alias<fapple_kext>;
-def finline_functions : Flag<["-"], "finline-functions">, Group<clang_ignored_f_Group>;
+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 finstrument_functions : Flag<["-"], "finstrument-functions">, Group<f_Group>, Flags<[CC1Option]>,
HelpText<"Generate calls to instrument function entry and exit">;
-def fkeep_inline_functions : Flag<["-"], "fkeep-inline-functions">, Group<clang_ignored_f_Group>;
def flat__namespace : Flag<["-"], "flat_namespace">;
def flax_vector_conversions : Flag<["-"], "flax-vector-conversions">, Group<f_Group>;
-def flimit_debug_info : Flag<["-"], "flimit-debug-info">, Group<f_Group>, Flags<[CC1Option]>,
- HelpText<"Limit debug information produced to reduce size of debug binary">;
def flimited_precision_EQ : Joined<["-"], "flimited-precision=">, Group<f_Group>;
def flto : Flag<["-"], "flto">, Group<f_Group>;
def fno_lto : Flag<["-"], "fno-lto">, Group<f_Group>;
@@ -559,21 +590,45 @@ def fmessage_length_EQ : Joined<["-"], "fmessage-length=">, Group<f_Group>;
def fms_extensions : Flag<["-"], "fms-extensions">, Group<f_Group>, Flags<[CC1Option]>,
HelpText<"Accept some non-standard constructs supported by the Microsoft compiler">;
def fms_compatibility : Flag<["-"], "fms-compatibility">, Group<f_Group>, Flags<[CC1Option]>,
- HelpText<"Enable Microsoft compatibility mode">;
-def fmsc_version : Joined<["-"], "fmsc-version=">, Group<f_Group>, Flags<[CC1Option, CoreOption]>,
- HelpText<"Version of the Microsoft C/C++ compiler to report in _MSC_VER (0 = don't define it (default))">;
+ HelpText<"Enable full Microsoft Visual C++ compatibility">;
+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]>;
+ "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 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 validate 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">;
@@ -591,6 +646,11 @@ def fmodules_ignore_macro : Joined<["-"], "fmodules-ignore-macro=">, Group<f_Gro
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 fretain_comments_from_system_headers : Flag<["-"], "fretain-comments-from-system-headers">, Group<f_Group>, Flags<[CC1Option]>;
def fmudflapth : Flag<["-"], "fmudflapth">, Group<f_Group>;
@@ -627,7 +687,6 @@ 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_name : Flag<["-"], "fno-diagnostics-show-name">, Group<f_Group>;
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>;
@@ -640,11 +699,8 @@ 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 fno_keep_inline_functions : Flag<["-"], "fno-keep-inline-functions">, Group<clang_ignored_f_Group>;
def fno_lax_vector_conversions : Flag<["-"], "fno-lax-vector-conversions">, Group<f_Group>,
HelpText<"Disallow implicit conversions between vectors with a different number of elements or different element types">, Flags<[CC1Option]>;
-def fno_limit_debug_info : Flag<["-"], "fno-limit-debug-info">, Group<f_Group>, Flags<[CC1Option]>,
- HelpText<"Do not limit debug information produced to reduce size of debug binary">;
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>,
@@ -653,6 +709,8 @@ def fno_module_maps : Flag <["-"], "fno-module-maps">, Group<f_Group>,
Flags<[DriverOption]>;
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 fno_ms_extensions : Flag<["-"], "fno-ms-extensions">, Group<f_Group>;
def fno_ms_compatibility : Flag<["-"], "fno-ms-compatibility">, Group<f_Group>;
def fno_delayed_template_parsing : Flag<["-"], "fno-delayed-template-parsing">, Group<f_Group>;
@@ -672,8 +730,10 @@ def fno_show_source_location : Flag<["-"], "fno-show-source-location">, Group<f_
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>;
-def fno_strict_aliasing : Flag<["-"], "fno-strict-aliasing">, Group<f_Group>;
+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>;
@@ -726,7 +786,8 @@ def fno_objc_nonfragile_abi : Flag<["-"], "fno-objc-nonfragile-abi">, Group<f_Gr
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]>;
+def fopenmp : Flag<["-"], "fopenmp">, Group<f_Group>, Flags<[CC1Option, NoArgumentUnused]>;
+def fopenmp_EQ : Joined<["-"], "fopenmp=">, Group<f_Group>, Flags<[CC1Option]>;
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">;
@@ -753,12 +814,14 @@ def frandom_seed_EQ : Joined<["-"], "frandom-seed=">, Group<clang_ignored_f_Grou
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 fsched_interblock : Flag<["-"], "fsched-interblock">, Group<clang_ignored_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 freorder_blocks : Flag<["-"], "freorder-blocks">, Group<clang_ignored_f_Group>;
+def : Flag<["-"], "freorder-blocks">, Group<clang_ignored_gcc_optimization_f_Group>;
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">;
@@ -770,9 +833,20 @@ def fsigned_char : Flag<["-"], "fsigned-char">, Group<f_Group>;
def fno_signed_char : Flag<["-"], "fno-signed-char">, Flags<[CC1Option]>,
Group<clang_ignored_f_Group>, HelpText<"Char is unsigned">;
def fsplit_stack : Flag<["-"], "fsplit-stack">, Group<f_Group>;
-def fstack_protector_all : Flag<["-"], "fstack-protector-all">, Group<f_Group>;
-def fstack_protector : Flag<["-"], "fstack-protector">, Group<f_Group>;
-def fstrict_aliasing : Flag<["-"], "fstrict-aliasing">, Group<f_Group>;
+def 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>, Flags<[CC1Option]>,
+ HelpText<"Emit full debug info for all types used by the program">;
+def fno_standalone_debug : Flag<["-"], "fno-standalone-debug">, Group<f_Group>, Flags<[CC1Option]>,
+ 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">;
@@ -789,29 +863,28 @@ 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 ftree_vectorize : Flag<["-"], "ftree-vectorize">, Alias<fvectorize>;
-def fno_tree_vectorize : Flag<["-"], "fno-tree-vectorize">, Alias<fno_vectorize>;
+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 ftree_slp_vectorize : Flag<["-"], "ftree-slp-vectorize">, Alias<fslp_vectorize>;
-def fno_tree_slp_vectorize : Flag<["-"], "fno-tree-slp-vectorize">, Alias<fno_slp_vectorize>;
+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]>;
-// Just silence warnings about -Wlarger-than, -Wframe-larger-than for now.
-def Wlarger_than : Separate<["-"], "Wlarger-than">, Group<clang_ignored_f_Group>;
-def Wlarger_than_EQ : Joined<["-"], "Wlarger-than=">, Alias<Wlarger_than>;
-def Wlarger_than_ : Joined<["-"], "Wlarger-than-">, Alias<Wlarger_than>;
-def Wframe_larger_than : Separate<["-"], "Wframe-larger-than">, Group<clang_ignored_f_Group>;
-def Wframe_larger_than_EQ : Joined<["-"], "Wframe-larger-than=">, Alias<Wframe_larger_than>;
+// 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 fterminated_vtables : Flag<["-"], "fterminated-vtables">, Alias<fapple_kext>;
+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]>;
@@ -866,10 +939,13 @@ def fno_data_sections : Flag <["-"], "fno-data-sections">, 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 g_Flag : Flag<["-"], "g">, Group<g_Group>,
- HelpText<"Generate source level debug information">, Flags<[CC1Option]>;
+ HelpText<"Generate source-level debug information">, Flags<[CC1Option,CC1AsOption]>;
def gline_tables_only : Flag<["-"], "gline-tables-only">, Group<g_Group>,
HelpText<"Emit debug line number tables only">, Flags<[CC1Option]>;
+def gmlt : Flag<["-"], "gmlt">, Alias<gline_tables_only>;
def g0 : Flag<["-"], "g0">, Group<g_Group>;
def g1 : Flag<["-"], "g1">, Group<g_Group>;
def g2 : Flag<["-"], "g2">, Group<g_Group>;
@@ -880,11 +956,11 @@ def ggdb1 : Flag<["-"], "ggdb1">, Group<g_Group>;
def ggdb2 : Flag<["-"], "ggdb2">, Group<g_Group>;
def ggdb3 : Flag<["-"], "ggdb3">, Group<g_Group>;
def gdwarf_2 : Flag<["-"], "gdwarf-2">, Group<g_Group>,
- HelpText<"Generate source level debug information with dwarf version 2">, Flags<[CC1Option]>;
+ HelpText<"Generate source-level debug information with dwarf version 2">, Flags<[CC1Option,CC1AsOption]>;
def gdwarf_3 : Flag<["-"], "gdwarf-3">, Group<g_Group>,
- HelpText<"Generate source level debug information with dwarf version 3">, Flags<[CC1Option]>;
+ HelpText<"Generate source-level debug information with dwarf version 3">, Flags<[CC1Option,CC1AsOption]>;
def gdwarf_4 : Flag<["-"], "gdwarf-4">, Group<g_Group>,
- HelpText<"Generate source level debug information with dwarf version 4">, Flags<[CC1Option]>;
+ HelpText<"Generate source-level debug information with dwarf version 4">, Flags<[CC1Option,CC1AsOption]>;
def gfull : Flag<["-"], "gfull">, Group<g_Group>;
def gused : Flag<["-"], "gused">, Group<g_Group>;
def gstabs : Joined<["-"], "gstabs">, Group<g_Group>, Flags<[Unsupported]>;
@@ -898,10 +974,12 @@ def gno_record_gcc_switches : Flag<["-"], "gno-record-gcc-switches">,
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 headerpad__max__install__names : Joined<["-"], "headerpad_max_install_names">;
-def help : Flag<["-", "--"], "help">, Flags<[CC1Option]>,
+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">;
@@ -918,9 +996,10 @@ def include_pch : Separate<["-"], "include-pch">, Group<clang_i_Group>, Flags<[C
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 integrated_as : Flag<["-"], "integrated-as">, Flags<[DriverOption]>;
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]>,
@@ -938,21 +1017,28 @@ 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 EL : Flag<["-"], "EL">, Flags<[DriverOption]>;
-def EB : Flag<["-"], "EB">, Flags<[DriverOption]>;
+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 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 mcpu_EQ : Joined<["-"], "mcpu=">, Group<m_Group>;
@@ -973,7 +1059,7 @@ def mios_simulator_version_min_EQ : Joined<["-"], "mios-simulator-version-min=">
def mkernel : Flag<["-"], "mkernel">, Group<m_Group>;
def mlinker_version_EQ : Joined<["-"], "mlinker-version=">,
Flags<[DriverOption]>;
-def mllvm : Separate<["-"], "mllvm">, Flags<[CC1Option]>,
+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>;
def mms_bitfields : Flag<["-"], "mms-bitfields">, Group<m_Group>, Flags<[CC1Option]>,
@@ -1028,11 +1114,11 @@ def mno_rdseed : Flag<["-"], "mno-rdseed">, Group<m_x86_Features_Group>;
def mno_sha : Flag<["-"], "mno-sha">, Group<m_x86_Features_Group>;
def munaligned_access : Flag<["-"], "munaligned-access">, Group<m_arm_Features_Group>,
- HelpText<"Allow memory accesses to be unaligned (ARM only)">;
+ 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 (ARM only)">;
+ 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 (ARM only, same as mno-unaligned-access)">;
+ HelpText<"Force all memory accesses to be aligned (AArch64 only, 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.">;
@@ -1045,6 +1131,13 @@ 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 mvsx : Flag<["-"], "mvsx">, Group<m_ppc_Features_Group>;
def mno_vsx : Flag<["-"], "mno-vsx">, Group<m_ppc_Features_Group>;
@@ -1056,6 +1149,8 @@ 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 faltivec : Flag<["-"], "faltivec">, Group<f_Group>, Flags<[CC1Option]>,
HelpText<"Enable AltiVec vector initializer syntax">;
@@ -1071,7 +1166,7 @@ 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]>,
+def mrelax_all : Flag<["-"], "mrelax-all">, Group<m_Group>, Flags<[CC1Option,CC1AsOption]>,
HelpText<"(integrated-as) Relax all machine instructions">;
def mrtd : Flag<["-"], "mrtd">, Group<m_Group>, Flags<[CC1Option]>,
HelpText<"Make StdCall calling convention the default">;
@@ -1138,18 +1233,48 @@ def mfp64 : Flag<["-"], "mfp64">, Group<m_Group>,
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 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 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 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 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>;
@@ -1160,7 +1285,6 @@ def mwarn_nonportable_cfstrings : Flag<["-"], "mwarn-nonportable-cfstrings">, Gr
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_as : Flag<["-"], "no-integrated-as">, Flags<[DriverOption]>;
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">;
@@ -1180,7 +1304,7 @@ 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]>,
+def o : JoinedOrSeparate<["-"], "o">, Flags<[DriverOption, RenderAsInput, CC1Option, CC1AsOption]>,
HelpText<"Write output to <file>">, MetaVarName<"<file>">;
def pagezero__size : JoinedOrSeparate<["-"], "pagezero_size">;
def pass_exit_codes : Flag<["-", "--"], "pass-exit-codes">, Flags<[Unsupported]>;
@@ -1228,6 +1352,8 @@ def rtlib_EQ : Joined<["-", "--"], "rtlib=">;
def r : Flag<["-"], "r">;
def save_temps : Flag<["-", "--"], "save-temps">, Flags<[DriverOption]>,
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>;
@@ -1257,8 +1383,18 @@ 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]>,
+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">;
@@ -1278,10 +1414,10 @@ 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]>,
+def v : Flag<["-"], "v">, Flags<[CC1Option, CoreOption]>,
HelpText<"Show commands to run and use verbose output">;
-def verify : Flag<["-"], "verify">, Flags<[DriverOption,CC1Option]>,
- HelpText<"Verify output using a verifier">;
+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]>;
@@ -1294,6 +1430,15 @@ def x : JoinedOrSeparate<["-"], "x">, Flags<[DriverOption,CC1Option]>,
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]>,
@@ -1302,7 +1447,8 @@ def working_directory_EQ : Joined<["-"], "working-directory=">, Flags<[CC1Option
// Double dash options, which are usually an alias for one of the previous
// options.
-def _mhwdiv_EQ : Separate<["--"], "mhwdiv">, Alias<mhwdiv_EQ>;
+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>;
@@ -1445,52 +1591,55 @@ multiclass BooleanFFlag<string name> {
def _fno : Flag<["-"], "fno-"#name>;
}
-def fprofile_dir : Joined<["-"], "fprofile-dir=">, Group<clang_ignored_f_Group>;
+defm : BooleanFFlag<"no-keep-inline-functions">, Group<clang_ignored_gcc_optimization_f_Group>;
+
+def fprofile_dir : Joined<["-"], "fprofile-dir=">, Group<clang_ignored_gcc_optimization_f_Group>;
-defm profile_use : BooleanFFlag<"profile-use">, Group<clang_ignored_f_Group>;
-def fprofile_use_EQ : Joined<["-"], "fprofile-use=">, Group<clang_ignored_f_Group>;
-def fuse_ld_EQ : Joined<["-"], "fuse-ld=">, Group<clang_ignored_f_Group>;
+defm profile_use : BooleanFFlag<"profile-use">, Group<clang_ignored_gcc_optimization_f_Group>;
+def fprofile_use_EQ : Joined<["-"], "fprofile-use=">, 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_f_Group>;
-def falign_functions_EQ : Joined<["-"], "falign-functions=">, Group<clang_ignored_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>;
// 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 eliminate_unused_debug_types : BooleanFFlag<"eliminate-unused-debug-types">, Group<clang_ignored_f_Group>;
-defm float_store : BooleanFFlag<"float-store">, Group<clang_ignored_f_Group>;
+defm float_store : BooleanFFlag<"float-store">, Group<clang_ignored_gcc_optimization_f_Group>;
defm function_attribute_list : BooleanFFlag<"function-attribute-list">, Group<clang_ignored_f_Group>;
-defm gcse : BooleanFFlag<"gcse">, Group<clang_ignored_f_Group>;
+defm gcse : BooleanFFlag<"gcse">, 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 inline_limit : BooleanFFlag<"inline-limit">, Group<clang_ignored_f_Group>;
-defm ivopts : BooleanFFlag<"ivopts">, Group<clang_ignored_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 ivopts : BooleanFFlag<"ivopts">, Group<clang_ignored_gcc_optimization_f_Group>;
defm non_call_exceptions : BooleanFFlag<"non-call-exceptions">, Group<clang_ignored_f_Group>;
defm permissive : BooleanFFlag<"permissive">, Group<clang_ignored_f_Group>;
-defm prefetch_loop_arrays : BooleanFFlag<"prefetch-loop-arrays">, 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_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_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 ripa : BooleanFFlag<"ripa">, Group<clang_ignored_f_Group>;
-defm rounding_math : BooleanFFlag<"rounding-math">, Group<clang_ignored_f_Group>;
-defm schedule_insns : BooleanFFlag<"schedule-insns">, 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 see : BooleanFFlag<"see">, Group<clang_ignored_f_Group>;
-defm signaling_nans : BooleanFFlag<"signaling-nans">, Group<clang_ignored_f_Group>;
+defm signaling_nans : BooleanFFlag<"signaling-nans">, Group<clang_ignored_gcc_optimization_f_Group>;
defm spec_constr_count : BooleanFFlag<"spec-constr-count">, Group<clang_ignored_f_Group>;
defm strength_reduce :
- BooleanFFlag<"strength-reduce">, Group<clang_ignored_f_Group>;
+ 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_f_Group>;
+defm tracer : BooleanFFlag<"tracer">, Group<clang_ignored_gcc_optimization_f_Group>;
defm tree_salias : BooleanFFlag<"tree-salias">, Group<clang_ignored_f_Group>;
defm tree_vectorizer_verbose : BooleanFFlag<"tree-vectorizer-verbose">, Group<clang_ignored_f_Group>;
-defm unroll_all_loops : BooleanFFlag<"unroll-all-loops">, Group<clang_ignored_f_Group>;
-defm unswitch_loops : BooleanFFlag<"unswitch-loops">, Group<clang_ignored_f_Group>;
+defm unroll_all_loops : BooleanFFlag<"unroll-all-loops">, Group<clang_ignored_gcc_optimization_f_Group>;
+defm unswitch_loops : BooleanFFlag<"unswitch-loops">, Group<clang_ignored_gcc_optimization_f_Group>;
// gfortran options that we recognize in the driver and pass along when
diff --git a/include/clang/Driver/SanitizerArgs.h b/include/clang/Driver/SanitizerArgs.h
index 35b8f89a88a7..c79c4714f4f9 100644
--- a/include/clang/Driver/SanitizerArgs.h
+++ b/include/clang/Driver/SanitizerArgs.h
@@ -9,10 +9,9 @@
#ifndef CLANG_LIB_DRIVER_SANITIZERARGS_H_
#define CLANG_LIB_DRIVER_SANITIZERARGS_H_
-#include <string>
-
#include "llvm/Option/Arg.h"
#include "llvm/Option/ArgList.h"
+#include <string>
namespace clang {
namespace driver {
@@ -43,14 +42,16 @@ class SanitizerArgs {
NeedsLeakDetection = Leak,
NeedsUbsanRt = Undefined | Integer,
NotAllowedWithTrap = Vptr,
- HasZeroBaseShadow = Thread | Memory | DataFlow
+ HasZeroBaseShadow = Thread | Memory | DataFlow,
+ NeedsUnwindTables = Address | Thread | Memory | DataFlow
};
unsigned Kind;
std::string BlacklistFile;
- bool MsanTrackOrigins;
+ int MsanTrackOrigins;
bool AsanZeroBaseShadow;
bool UbsanTrapOnError;
+ bool AsanSharedRuntime;
public:
SanitizerArgs();
@@ -58,6 +59,7 @@ class SanitizerArgs {
SanitizerArgs(const ToolChain &TC, const llvm::opt::ArgList &Args);
bool needsAsanRt() const { return Kind & NeedsAsanRt; }
+ bool needsSharedAsanRt() const { return AsanSharedRuntime; }
bool needsTsanRt() const { return Kind & NeedsTsanRt; }
bool needsMsanRt() const { return Kind & NeedsMsanRt; }
bool needsLeakDetection() const { return Kind & NeedsLeakDetection; }
@@ -74,6 +76,7 @@ class SanitizerArgs {
bool hasZeroBaseShadow() const {
return (Kind & HasZeroBaseShadow) || AsanZeroBaseShadow;
}
+ bool needsUnwindTables() const { return Kind & NeedsUnwindTables; }
void addArgs(const llvm::opt::ArgList &Args,
llvm::opt::ArgStringList &CmdArgs) const;
@@ -99,7 +102,7 @@ class SanitizerArgs {
/// Produce an argument string from ArgList \p Args, which shows how it
/// provides a sanitizer kind in \p Mask. For example, the argument list
- /// "-fsanitize=thread,vptr -faddress-sanitizer" with mask \c NeedsUbsanRt
+ /// "-fsanitize=thread,vptr -fsanitize=address" with mask \c NeedsUbsanRt
/// would produce "-fsanitize=vptr".
static std::string lastArgumentForKind(const Driver &D,
const llvm::opt::ArgList &Args,
diff --git a/include/clang/Driver/ToolChain.h b/include/clang/Driver/ToolChain.h
index c212a833224f..550e4dfc60c3 100644
--- a/include/clang/Driver/ToolChain.h
+++ b/include/clang/Driver/ToolChain.h
@@ -11,12 +11,13 @@
#define CLANG_DRIVER_TOOLCHAIN_H_
#include "clang/Driver/Action.h"
+#include "clang/Driver/Multilib.h"
#include "clang/Driver/Types.h"
#include "clang/Driver/Util.h"
-#include "llvm/ADT/OwningPtr.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/Triple.h"
#include "llvm/Support/Path.h"
+#include <memory>
#include <string>
namespace llvm {
@@ -65,17 +66,19 @@ private:
/// programs.
path_list ProgramPaths;
- mutable OwningPtr<Tool> Clang;
- mutable OwningPtr<Tool> Assemble;
- mutable OwningPtr<Tool> Link;
+ 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 OwningPtr<SanitizerArgs> SanitizerArguments;
+ mutable std::unique_ptr<SanitizerArgs> SanitizerArguments;
protected:
+ MultilibSet Multilibs;
+
ToolChain(const Driver &D, const llvm::Triple &T,
const llvm::opt::ArgList &Args);
@@ -127,6 +130,8 @@ public:
path_list &getProgramPaths() { return ProgramPaths; }
const path_list &getProgramPaths() const { return ProgramPaths; }
+ const MultilibSet &getMultilibs() const { return Multilibs; }
+
const SanitizerArgs& getSanitizerArgs() const;
// Tool access.
@@ -139,7 +144,7 @@ public:
virtual llvm::opt::DerivedArgList *
TranslateArgs(const llvm::opt::DerivedArgList &Args,
const char *BoundArch) const {
- return 0;
+ return nullptr;
}
/// Choose a tool to use to handle the action \p JA.
@@ -150,6 +155,10 @@ public:
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,
@@ -159,6 +168,10 @@ public:
// 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;
@@ -193,7 +206,7 @@ public:
virtual bool UseObjCMixedDispatch() const { return false; }
/// GetDefaultStackProtectorLevel - Get the default stack protector level for
- /// this tool chain (0=off, 1=on, 2=all).
+ /// this tool chain (0=off, 1=on, 2=strong, 3=all).
virtual unsigned GetDefaultStackProtectorLevel(bool KernelOrKext) const {
return 0;
}
@@ -275,6 +288,9 @@ public:
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
diff --git a/include/clang/Driver/Types.def b/include/clang/Driver/Types.def
index d4f52d3220c8..32096792cadc 100644
--- a/include/clang/Driver/Types.def
+++ b/include/clang/Driver/Types.def
@@ -54,22 +54,22 @@ 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, 0, "pu")
-TYPE("cl-header", CLHeader, PP_CHeader, 0, "pu")
+TYPE("c-header", CHeader, PP_CHeader, nullptr, "pu")
+TYPE("cl-header", CLHeader, PP_CHeader, nullptr, "pu")
TYPE("objective-c-header-cpp-output", PP_ObjCHeader, INVALID, "mi", "p")
-TYPE("objective-c-header", ObjCHeader, PP_ObjCHeader, 0, "pu")
+TYPE("objective-c-header", ObjCHeader, PP_ObjCHeader, nullptr, "pu")
TYPE("c++-header-cpp-output", PP_CXXHeader, INVALID, "ii", "p")
-TYPE("c++-header", CXXHeader, PP_CXXHeader, 0, "pu")
+TYPE("c++-header", CXXHeader, PP_CXXHeader, nullptr, "pu")
TYPE("objective-c++-header-cpp-output", PP_ObjCXXHeader, INVALID, "mii", "p")
-TYPE("objective-c++-header", ObjCXXHeader, PP_ObjCXXHeader, 0, "pu")
+TYPE("objective-c++-header", ObjCXXHeader, PP_ObjCXXHeader, nullptr, "pu")
// Other languages.
-TYPE("ada", Ada, INVALID, 0, "u")
+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, 0, "u")
-TYPE("f95-cpp-input", Fortran, PP_Fortran, 0, "u")
-TYPE("java", Java, INVALID, 0, "u")
+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.
@@ -87,8 +87,8 @@ 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, 0, "u")
+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, 0, "u")
+TYPE("none", Nothing, INVALID, nullptr, "u")
diff --git a/include/clang/Edit/Commit.h b/include/clang/Edit/Commit.h
index 626b1dd6305e..5cc5b9c6ff8b 100644
--- a/include/clang/Edit/Commit.h
+++ b/include/clang/Edit/Commit.h
@@ -49,8 +49,7 @@ private:
const LangOptions &LangOpts;
const PPConditionalDirectiveRecord *PPRec;
EditedSource *Editor;
-
- const bool ForceCommitInSystemHeader;
+
bool IsCommitable;
SmallVector<Edit, 8> CachedEdits;
@@ -59,9 +58,9 @@ private:
public:
explicit Commit(EditedSource &Editor);
Commit(const SourceManager &SM, const LangOptions &LangOpts,
- const PPConditionalDirectiveRecord *PPRec = 0)
- : SourceMgr(SM), LangOpts(LangOpts), PPRec(PPRec), Editor(0),
- ForceCommitInSystemHeader(true), IsCommitable(true) { }
+ const PPConditionalDirectiveRecord *PPRec = nullptr)
+ : SourceMgr(SM), LangOpts(LangOpts), PPRec(PPRec), Editor(nullptr),
+ IsCommitable(true) { }
bool isCommitable() const { return IsCommitable; }
@@ -132,9 +131,9 @@ private:
void commitRemove(FileOffset offset, unsigned length);
bool isAtStartOfMacroExpansion(SourceLocation loc,
- SourceLocation *MacroBegin = 0) const;
+ SourceLocation *MacroBegin = nullptr) const;
bool isAtEndOfMacroExpansion(SourceLocation loc,
- SourceLocation *MacroEnd = 0) const;
+ SourceLocation *MacroEnd = nullptr) const;
StringRef copyString(StringRef str) {
char *buf = StrAlloc.Allocate<char>(str.size());
diff --git a/include/clang/Edit/EditedSource.h b/include/clang/Edit/EditedSource.h
index 3ad5a6be1464..150a5b41b5a4 100644
--- a/include/clang/Edit/EditedSource.h
+++ b/include/clang/Edit/EditedSource.h
@@ -28,7 +28,6 @@ class EditedSource {
const SourceManager &SourceMgr;
const LangOptions &LangOpts;
const PPConditionalDirectiveRecord *PPRec;
- const bool ForceCommitInSystemHeader;
struct FileEdit {
StringRef Text;
@@ -46,21 +45,15 @@ class EditedSource {
public:
EditedSource(const SourceManager &SM, const LangOptions &LangOpts,
- const PPConditionalDirectiveRecord *PPRec = 0,
- const bool FCommitInSystemHeader = true)
+ const PPConditionalDirectiveRecord *PPRec = nullptr)
: SourceMgr(SM), LangOpts(LangOpts), PPRec(PPRec),
- ForceCommitInSystemHeader(FCommitInSystemHeader),
- StrAlloc(/*size=*/512) { }
+ StrAlloc() { }
const SourceManager &getSourceManager() const { return SourceMgr; }
const LangOptions &getLangOpts() const { return LangOpts; }
const PPConditionalDirectiveRecord *getPPCondDirectiveRecord() const {
return PPRec;
}
-
- bool getForceCommitInSystemHeader() const {
- return ForceCommitInSystemHeader;
- }
bool canInsertInOffset(SourceLocation OrigLoc, FileOffset Offs);
diff --git a/include/clang/Edit/FileOffset.h b/include/clang/Edit/FileOffset.h
index 675ad18fcd39..0c1e72b84e51 100644
--- a/include/clang/Edit/FileOffset.h
+++ b/include/clang/Edit/FileOffset.h
@@ -41,20 +41,16 @@ public:
return !(LHS == RHS);
}
friend bool operator<(FileOffset LHS, FileOffset RHS) {
- if (LHS.FID != RHS.FID)
- return LHS.FID < RHS.FID;
- return LHS.Offs < RHS.Offs;
+ return std::tie(LHS.FID, LHS.Offs) < std::tie(RHS.FID, RHS.Offs);
}
friend bool operator>(FileOffset LHS, FileOffset RHS) {
- if (LHS.FID != RHS.FID)
- return LHS.FID > RHS.FID;
- return LHS.Offs > RHS.Offs;
+ return RHS < LHS;
}
friend bool operator>=(FileOffset LHS, FileOffset RHS) {
- return LHS > RHS || LHS == RHS;
+ return !(LHS < RHS);
}
friend bool operator<=(FileOffset LHS, FileOffset RHS) {
- return LHS < RHS || LHS == RHS;
+ return !(RHS < LHS);
}
};
diff --git a/include/clang/Format/Format.h b/include/clang/Format/Format.h
index 0f2746712a69..45cccaacd569 100644
--- a/include/clang/Format/Format.h
+++ b/include/clang/Format/Format.h
@@ -17,7 +17,7 @@
#include "clang/Frontend/FrontendAction.h"
#include "clang/Tooling/Refactoring.h"
-#include "llvm/Support/system_error.h"
+#include <system_error>
namespace clang {
@@ -27,19 +27,49 @@ 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 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 JavaScript.
+ LK_JavaScript,
+ /// Should be used for Protocol Buffers
+ /// (https://developers.google.com/protocol-buffers/).
+ LK_Proto
+ };
+
+ /// \brief Language, this format style is targeted at.
+ LanguageKind Language;
+
/// \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.
+ /// statements unless they contradict other rules.
unsigned ColumnLimit;
/// \brief The maximum number of consecutive empty lines to keep.
unsigned MaxEmptyLinesToKeep;
+ /// \brief If true, empty lines at the start of blocks are kept.
+ bool KeepEmptyLinesAtTheStartOfBlocks;
+
/// \brief The penalty for each line break introduced inside a comment.
unsigned PenaltyBreakComment;
@@ -55,11 +85,22 @@ struct FormatStyle {
/// \brief The penalty for breaking a function call after "call(".
unsigned PenaltyBreakBeforeFirstCallParameter;
- /// \brief Set whether & and * bind to the type as opposed to the variable.
- bool PointerBindsToType;
+ /// \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
+ };
+
+ /// Pointer and reference alignment style.
+ PointerAlignmentStyle PointerAlignment;
- /// \brief If \c true, analyze the formatted file for the most common binding.
- bool DerivePointerBinding;
+ /// \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 The extra indent or outdent of access modifiers, e.g. \c public:.
int AccessModifierOffset;
@@ -85,6 +126,10 @@ struct FormatStyle {
/// Switch statement body is always indented one level more than case labels.
bool IndentCaseLabels;
+ /// \brief Indent if a function definition or declaration is wrapped after the
+ /// type.
+ bool IndentWrappedFunctionNames;
+
/// \brief Different ways to indent namespace contents.
enum NamespaceIndentationKind {
/// Don't indent in namespaces.
@@ -98,7 +143,11 @@ struct FormatStyle {
/// \brief The indentation used for namespaces.
NamespaceIndentationKind NamespaceIndentation;
- /// \brief The number of spaces to before trailing line comments.
+ /// \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 false, a function call's or function definition's parameters
@@ -133,6 +182,11 @@ struct FormatStyle {
/// the commas with the colon.
bool BreakConstructorInitializersBeforeComma;
+ /// \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, <tt>if (a) return;</tt> can be put on a single
/// line.
bool AllowShortIfStatementsOnASingleLine;
@@ -141,6 +195,25 @@ struct FormatStyle {
/// single line.
bool AllowShortLoopsOnASingleLine;
+ /// \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 functions defined inside a class.
+ 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 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;
@@ -199,7 +272,11 @@ struct FormatStyle {
/// Like \c Attach, but break before function definitions.
BS_Stroustrup,
/// Always break before braces.
- BS_Allman
+ 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
};
/// \brief The brace breaking style to use.
@@ -220,10 +297,6 @@ struct FormatStyle {
/// a zero-length name is assumed.
bool Cpp11BracedListStyle;
- /// \brief If \c true, indent when breaking function declarations which
- /// are not also definitions after the type.
- bool IndentFunctionDeclarationAfterType;
-
/// \brief If \c true, spaces will be inserted after '(' and before ')'.
bool SpacesInParentheses;
@@ -231,15 +304,32 @@ struct FormatStyle {
/// template argument lists
bool SpacesInAngles;
- /// \brief If \c false, spaces may be inserted into '()'.
+ /// \brief If \c true, spaces may be inserted into '()'.
bool SpaceInEmptyParentheses;
- /// \brief If \c false, spaces may be inserted into C style casts.
+ /// \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 between 'for'/'if'/'while'/...
- /// and '('.
- bool SpaceAfterControlStatementKeyword;
+ /// \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 false, spaces will be removed before assignment operators.
bool SpaceBeforeAssignmentOperators;
@@ -247,6 +337,25 @@ struct FormatStyle {
/// \brief Indent width for line continuations.
unsigned ContinuationIndentWidth;
+ /// \brief A regular expression that describes comments with special meaning,
+ /// which should not be split into lines or otherwise changed.
+ std::string CommentPragmas;
+
+ /// \brief Disables formatting at all.
+ bool DisableFormat;
+
+ /// \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
+ ///
+ /// For example: BOOST_FOREACH.
+ std::vector<std::string> ForEachMacros;
+
bool operator==(const FormatStyle &R) const {
return AccessModifierOffset == R.AccessModifierOffset &&
ConstructorInitializerIndentWidth ==
@@ -255,6 +364,9 @@ struct FormatStyle {
AlignTrailingComments == R.AlignTrailingComments &&
AllowAllParametersOfDeclarationOnNextLine ==
R.AllowAllParametersOfDeclarationOnNextLine &&
+ AllowShortFunctionsOnASingleLine ==
+ R.AllowShortFunctionsOnASingleLine &&
+ AllowShortBlocksOnASingleLine == R.AllowShortBlocksOnASingleLine &&
AllowShortIfStatementsOnASingleLine ==
R.AllowShortIfStatementsOnASingleLine &&
AllowShortLoopsOnASingleLine == R.AllowShortLoopsOnASingleLine &&
@@ -271,33 +383,37 @@ struct FormatStyle {
ColumnLimit == R.ColumnLimit &&
ConstructorInitializerAllOnOneLineOrOnePerLine ==
R.ConstructorInitializerAllOnOneLineOrOnePerLine &&
- DerivePointerBinding == R.DerivePointerBinding &&
+ DerivePointerAlignment == R.DerivePointerAlignment &&
ExperimentalAutoDetectBinPacking ==
R.ExperimentalAutoDetectBinPacking &&
IndentCaseLabels == R.IndentCaseLabels &&
- IndentFunctionDeclarationAfterType ==
- R.IndentFunctionDeclarationAfterType &&
- IndentWidth == R.IndentWidth &&
+ IndentWrappedFunctionNames == R.IndentWrappedFunctionNames &&
+ IndentWidth == R.IndentWidth && Language == R.Language &&
MaxEmptyLinesToKeep == R.MaxEmptyLinesToKeep &&
+ KeepEmptyLinesAtTheStartOfBlocks ==
+ R.KeepEmptyLinesAtTheStartOfBlocks &&
NamespaceIndentation == R.NamespaceIndentation &&
+ ObjCSpaceAfterProperty == R.ObjCSpaceAfterProperty &&
ObjCSpaceBeforeProtocolList == R.ObjCSpaceBeforeProtocolList &&
PenaltyBreakComment == R.PenaltyBreakComment &&
PenaltyBreakFirstLessLess == R.PenaltyBreakFirstLessLess &&
PenaltyBreakString == R.PenaltyBreakString &&
PenaltyExcessCharacter == R.PenaltyExcessCharacter &&
PenaltyReturnTypeOnItsOwnLine == R.PenaltyReturnTypeOnItsOwnLine &&
- PointerBindsToType == R.PointerBindsToType &&
+ PointerAlignment == R.PointerAlignment &&
SpacesBeforeTrailingComments == R.SpacesBeforeTrailingComments &&
Cpp11BracedListStyle == R.Cpp11BracedListStyle &&
Standard == R.Standard && TabWidth == R.TabWidth &&
UseTab == R.UseTab && SpacesInParentheses == R.SpacesInParentheses &&
SpacesInAngles == R.SpacesInAngles &&
SpaceInEmptyParentheses == R.SpaceInEmptyParentheses &&
+ SpacesInContainerLiterals == R.SpacesInContainerLiterals &&
SpacesInCStyleCastParentheses == R.SpacesInCStyleCastParentheses &&
- SpaceAfterControlStatementKeyword ==
- R.SpaceAfterControlStatementKeyword &&
+ SpaceBeforeParens == R.SpaceBeforeParens &&
SpaceBeforeAssignmentOperators == R.SpaceBeforeAssignmentOperators &&
- ContinuationIndentWidth == R.ContinuationIndentWidth;
+ ContinuationIndentWidth == R.ContinuationIndentWidth &&
+ CommentPragmas == R.CommentPragmas &&
+ ForEachMacros == R.ForEachMacros;
}
};
@@ -305,13 +421,15 @@ struct FormatStyle {
/// http://llvm.org/docs/CodingStandards.html.
FormatStyle getLLVMStyle();
-/// \brief Returns a format style complying with Google's C++ style guide:
+/// \brief Returns a format style complying with one of Google's style guides:
/// http://google-styleguide.googlecode.com/svn/trunk/cppguide.xml.
-FormatStyle getGoogleStyle();
+/// 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 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.
@@ -321,16 +439,30 @@ FormatStyle getMozillaStyle();
/// http://www.webkit.org/coding/coding-style.html
FormatStyle getWebKitStyle();
-/// \brief Gets a predefined style by name.
+/// \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 *Style);
+bool getPredefinedStyle(StringRef Name, FormatStyle::LanguageKind Language,
+ FormatStyle *Style);
/// \brief Parse configuration from YAML-formatted text.
-llvm::error_code parseConfiguration(StringRef Text, FormatStyle *Style);
+///
+/// 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);
@@ -359,8 +491,8 @@ tooling::Replacements reformat(const FormatStyle &Style, StringRef Code,
///
/// \param Standard determines lexing mode: LC_Cpp11 and LS_Auto turn on C++11
/// lexing mode, LS_Cpp03 - C++03 mode.
-LangOptions getFormattingLangOpts(FormatStyle::LanguageStandard Standard =
- FormatStyle::LS_Cpp11);
+LangOptions getFormattingLangOpts(
+ FormatStyle::LanguageStandard Standard = FormatStyle::LS_Cpp11);
/// \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
@@ -381,12 +513,20 @@ extern const char *StyleOptionHelpDescription;
/// 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);
+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/include/clang/Frontend/ASTUnit.h b/include/clang/Frontend/ASTUnit.h
index 43d77f0171e9..42dc69ab4a15 100644
--- a/include/clang/Frontend/ASTUnit.h
+++ b/include/clang/Frontend/ASTUnit.h
@@ -27,12 +27,13 @@
#include "clang/Sema/CodeCompleteConsumer.h"
#include "clang/Serialization/ASTBitCodes.h"
#include "llvm/ADT/IntrusiveRefCntPtr.h"
-#include "llvm/ADT/OwningPtr.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>
@@ -63,33 +64,51 @@ 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:
- IntrusiveRefCntPtr<LangOptions> LangOpts;
+ std::shared_ptr<LangOptions> LangOpts;
IntrusiveRefCntPtr<DiagnosticsEngine> Diagnostics;
IntrusiveRefCntPtr<FileManager> FileMgr;
IntrusiveRefCntPtr<SourceManager> SourceMgr;
- OwningPtr<HeaderSearch> HeaderInfo;
+ std::unique_ptr<HeaderSearch> HeaderInfo;
IntrusiveRefCntPtr<TargetInfo> Target;
IntrusiveRefCntPtr<Preprocessor> PP;
IntrusiveRefCntPtr<ASTContext> Ctx;
- IntrusiveRefCntPtr<TargetOptions> TargetOpts;
+ std::shared_ptr<TargetOptions> TargetOpts;
IntrusiveRefCntPtr<HeaderSearchOptions> HSOpts;
- ASTReader *Reader;
+ IntrusiveRefCntPtr<ASTReader> Reader;
bool HadModuleLoaderFatalFailure;
struct ASTWriterData;
- OwningPtr<ASTWriterData> WriterData;
+ std::unique_ptr<ASTWriterData> WriterData;
FileSystemOptions FileSystemOpts;
/// \brief The AST consumer that received information about the translation
/// unit as it was parsed or loaded.
- OwningPtr<ASTConsumer> Consumer;
-
+ std::unique_ptr<ASTConsumer> Consumer;
+
/// \brief The semantic analysis object used to type-check the translation
/// unit.
- OwningPtr<Sema> TheSema;
-
+ std::unique_ptr<Sema> TheSema;
+
/// Optional owned invocation, just used to make the invocation used in
/// LoadFromCommandLine available.
IntrusiveRefCntPtr<CompilerInvocation> Invocation;
@@ -135,7 +154,7 @@ private:
std::string OriginalSourceFile;
/// \brief The set of diagnostics produced when creating the preamble.
- SmallVector<StoredDiagnostic, 4> PreambleDiagnostics;
+ SmallVector<StandaloneDiagnostic, 4> PreambleDiagnostics;
/// \brief The set of diagnostics produced when creating this
/// translation unit.
@@ -170,7 +189,7 @@ public:
mutable unsigned NumLines;
public:
- PreambleData() : File(0), NumLines(0) { }
+ PreambleData() : File(nullptr), NumLines(0) { }
void assign(const FileEntry *F, const char *begin, const char *end) {
File = F;
@@ -178,7 +197,7 @@ public:
NumLines = 0;
}
- void clear() { Buffer.clear(); File = 0; NumLines = 0; }
+ void clear() { Buffer.clear(); File = nullptr; NumLines = 0; }
size_t size() const { return Buffer.size(); }
bool empty() const { return Buffer.empty(); }
@@ -205,8 +224,34 @@ public:
return Preamble;
}
-private:
+ /// 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;
@@ -216,17 +261,13 @@ private:
/// Used to inform the lexer as to whether it's starting at the beginning of
/// a line after skipping the preamble.
bool PreambleEndsAtStartOfLine;
-
- /// \brief The size of the source buffer that we've reserved for the main
- /// file within the precompiled preamble.
- unsigned PreambleReservedSize;
/// \brief Keeps track of the files that were used when computing the
/// preamble, with both their buffer size and their modification time.
///
/// If any of the files have changed from one compile to the next,
/// the preamble must be thrown away.
- llvm::StringMap<std::pair<off_t, time_t> > FilesInPreamble;
+ 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
@@ -268,9 +309,9 @@ private:
const char **ArgBegin, const char **ArgEnd,
ASTUnit &AST, bool CaptureDiagnostics);
- void TranslateStoredDiagnostics(ASTReader *MMan, StringRef ModName,
+ void TranslateStoredDiagnostics(FileManager &FileMgr,
SourceManager &SrcMan,
- const SmallVectorImpl<StoredDiagnostic> &Diags,
+ const SmallVectorImpl<StandaloneDiagnostic> &Diags,
SmallVectorImpl<StoredDiagnostic> &Out);
void clearFileLevelDecls();
@@ -337,8 +378,8 @@ private:
/// \brief Allocator used to store cached code completions.
IntrusiveRefCntPtr<GlobalCodeCompletionAllocator>
CachedCompletionAllocator;
-
- OwningPtr<CodeCompletionTUInfo> CCTUInfo;
+
+ std::unique_ptr<CodeCompletionTUInfo> CCTUInfo;
/// \brief The set of cached code-completion results.
std::vector<CachedCodeCompletionResult> CachedCompletionResults;
@@ -406,9 +447,7 @@ private:
/// just about any usage.
/// Becomes a noop in release mode; only useful for debug mode checking.
class ConcurrencyState {
-#ifndef NDEBUG
void *Mutex; // a llvm::sys::MutexImpl in debug;
-#endif
public:
ConcurrencyState();
@@ -457,10 +496,15 @@ public:
void setASTContext(ASTContext *ctx) { Ctx = ctx; }
void setPreprocessor(Preprocessor *pp);
- bool hasSema() const { return TheSema.isValid(); }
+ bool hasSema() const { return (bool)TheSema; }
Sema &getSema() const {
assert(TheSema && "ASTUnit does not have a Sema object!");
- return *TheSema;
+ return *TheSema;
+ }
+
+ const LangOptions &getLangOpts() const {
+ assert(LangOpts && " ASTUnit does not have language options");
+ return *LangOpts;
}
const FileManager &getFileManager() const { return *FileMgr; }
@@ -641,16 +685,14 @@ public:
bool isModuleFile();
llvm::MemoryBuffer *getBufferForFile(StringRef Filename,
- std::string *ErrorStr = 0);
+ std::string *ErrorStr = nullptr);
/// \brief Determine what kind of translation unit this AST represents.
TranslationUnitKind getTranslationUnitKind() const { return TUKind; }
- typedef llvm::PointerUnion<const char *, const llvm::MemoryBuffer *>
- FilenameOrMemBuf;
/// \brief A mapping from a file name to the memory buffer that stores the
/// remapped contents of that file.
- typedef std::pair<std::string, FilenameOrMemBuf> RemappedFile;
+ typedef std::pair<std::string, llvm::MemoryBuffer *> RemappedFile;
/// \brief Create a ASTUnit. Gets ownership of the passed CompilerInvocation.
static ASTUnit *create(CompilerInvocation *CI,
@@ -670,8 +712,7 @@ public:
IntrusiveRefCntPtr<DiagnosticsEngine> Diags,
const FileSystemOptions &FileSystemOpts,
bool OnlyLocalDecls = false,
- RemappedFile *RemappedFiles = 0,
- unsigned NumRemappedFiles = 0,
+ ArrayRef<RemappedFile> RemappedFiles = None,
bool CaptureDiagnostics = false,
bool AllowPCHWithCompilerErrors = false,
bool UserFilesAreVolatile = false);
@@ -714,19 +755,15 @@ public:
/// 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,
- IntrusiveRefCntPtr<DiagnosticsEngine> Diags,
- ASTFrontendAction *Action = 0,
- ASTUnit *Unit = 0,
- bool Persistent = true,
- StringRef ResourceFilesPath = StringRef(),
- bool OnlyLocalDecls = false,
- bool CaptureDiagnostics = false,
- bool PrecompilePreamble = false,
- bool CacheCodeCompletionResults = false,
- bool IncludeBriefCommentsInCodeCompletion = false,
- bool UserFilesAreVolatile = false,
- OwningPtr<ASTUnit> *ErrAST = 0);
+ static ASTUnit *LoadFromCompilerInvocationAction(
+ CompilerInvocation *CI, IntrusiveRefCntPtr<DiagnosticsEngine> Diags,
+ ASTFrontendAction *Action = nullptr, ASTUnit *Unit = nullptr,
+ bool Persistent = true, StringRef ResourceFilesPath = StringRef(),
+ bool OnlyLocalDecls = false, bool CaptureDiagnostics = false,
+ bool PrecompilePreamble = false, 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.
@@ -739,15 +776,13 @@ public:
//
// FIXME: Move OnlyLocalDecls, UseBumpAllocator to setters on the ASTUnit, we
// shouldn't need to specify them at construction time.
- static ASTUnit *LoadFromCompilerInvocation(CompilerInvocation *CI,
- IntrusiveRefCntPtr<DiagnosticsEngine> Diags,
- bool OnlyLocalDecls = false,
- bool CaptureDiagnostics = false,
- bool PrecompilePreamble = false,
- TranslationUnitKind TUKind = TU_Complete,
- bool CacheCodeCompletionResults = false,
- bool IncludeBriefCommentsInCodeCompletion = false,
- bool UserFilesAreVolatile = false);
+ static std::unique_ptr<ASTUnit> LoadFromCompilerInvocation(
+ CompilerInvocation *CI, IntrusiveRefCntPtr<DiagnosticsEngine> Diags,
+ bool OnlyLocalDecls = false, bool CaptureDiagnostics = false,
+ bool PrecompilePreamble = false, 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.
@@ -767,32 +802,25 @@ public:
///
// 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,
- IntrusiveRefCntPtr<DiagnosticsEngine> Diags,
- StringRef ResourceFilesPath,
- bool OnlyLocalDecls = false,
- bool CaptureDiagnostics = false,
- RemappedFile *RemappedFiles = 0,
- unsigned NumRemappedFiles = 0,
- bool RemappedFilesKeepOriginalName = true,
- bool PrecompilePreamble = false,
- TranslationUnitKind TUKind = TU_Complete,
- bool CacheCodeCompletionResults = false,
- bool IncludeBriefCommentsInCodeCompletion = false,
- bool AllowPCHWithCompilerErrors = false,
- bool SkipFunctionBodies = false,
- bool UserFilesAreVolatile = false,
- bool ForSerialization = false,
- OwningPtr<ASTUnit> *ErrAST = 0);
-
+ static ASTUnit *LoadFromCommandLine(
+ const char **ArgBegin, const char **ArgEnd,
+ IntrusiveRefCntPtr<DiagnosticsEngine> Diags, StringRef ResourceFilesPath,
+ bool OnlyLocalDecls = false, bool CaptureDiagnostics = false,
+ ArrayRef<RemappedFile> RemappedFiles = None,
+ bool RemappedFilesKeepOriginalName = true,
+ bool PrecompilePreamble = false, TranslationUnitKind TUKind = TU_Complete,
+ bool CacheCodeCompletionResults = false,
+ bool IncludeBriefCommentsInCodeCompletion = false,
+ bool AllowPCHWithCompilerErrors = false, bool SkipFunctionBodies = false,
+ bool UserFilesAreVolatile = false, bool ForSerialization = false,
+ 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(RemappedFile *RemappedFiles = 0,
- unsigned NumRemappedFiles = 0);
+ bool Reparse(ArrayRef<RemappedFile> RemappedFiles = None);
/// \brief Perform code completion at the given file, line, and
/// column within this translation unit.
@@ -815,7 +843,7 @@ public:
/// 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,
- RemappedFile *RemappedFiles, unsigned NumRemappedFiles,
+ ArrayRef<RemappedFile> RemappedFiles,
bool IncludeMacros, bool IncludeCodePatterns,
bool IncludeBriefComments,
CodeCompleteConsumer &Consumer,
@@ -834,20 +862,21 @@ public:
///
/// \returns True if an error occurred, false otherwise.
bool serialize(raw_ostream &OS);
-
- virtual ModuleLoadResult loadModule(SourceLocation ImportLoc,
- ModuleIdPath Path,
- Module::NameVisibilityKind Visibility,
- bool IsInclusionDirective) {
+
+ 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();
}
- virtual void makeModuleVisible(Module *Mod,
- Module::NameVisibilityKind Visibility,
- SourceLocation ImportLoc,
- bool Complain) { }
+ void makeModuleVisible(Module *Mod, Module::NameVisibilityKind Visibility,
+ SourceLocation ImportLoc, bool Complain) override {}
+ GlobalModuleIndex *loadGlobalModuleIndex(SourceLocation TriggerLoc) override
+ { return nullptr; }
+ bool lookupMissingImports(StringRef Name, SourceLocation TriggerLoc) override
+ { return 0; };
};
} // namespace clang
diff --git a/include/clang/Frontend/ChainedDiagnosticConsumer.h b/include/clang/Frontend/ChainedDiagnosticConsumer.h
index b7dc7c7b5291..11762a97cfc4 100644
--- a/include/clang/Frontend/ChainedDiagnosticConsumer.h
+++ b/include/clang/Frontend/ChainedDiagnosticConsumer.h
@@ -11,7 +11,7 @@
#define LLVM_CLANG_FRONTEND_CHAINEDDIAGNOSTICCONSUMER_H
#include "clang/Basic/Diagnostic.h"
-#include "llvm/ADT/OwningPtr.h"
+#include <memory>
namespace clang {
class LangOptions;
@@ -22,8 +22,8 @@ class LangOptions;
/// diagnostics should be included in counts.
class ChainedDiagnosticConsumer : public DiagnosticConsumer {
virtual void anchor();
- OwningPtr<DiagnosticConsumer> Primary;
- OwningPtr<DiagnosticConsumer> Secondary;
+ std::unique_ptr<DiagnosticConsumer> Primary;
+ std::unique_ptr<DiagnosticConsumer> Secondary;
public:
ChainedDiagnosticConsumer(DiagnosticConsumer *_Primary,
@@ -32,28 +32,28 @@ public:
Secondary.reset(_Secondary);
}
- virtual void BeginSourceFile(const LangOptions &LO,
- const Preprocessor *PP) {
+ void BeginSourceFile(const LangOptions &LO,
+ const Preprocessor *PP) override {
Primary->BeginSourceFile(LO, PP);
Secondary->BeginSourceFile(LO, PP);
}
- virtual void EndSourceFile() {
+ void EndSourceFile() override {
Secondary->EndSourceFile();
Primary->EndSourceFile();
}
- virtual void finish() {
+ void finish() override {
Secondary->finish();
Primary->finish();
}
- virtual bool IncludeInDiagnosticCounts() const {
+ bool IncludeInDiagnosticCounts() const override {
return Primary->IncludeInDiagnosticCounts();
}
- virtual void HandleDiagnostic(DiagnosticsEngine::Level DiagLevel,
- const Diagnostic &Info) {
+ void HandleDiagnostic(DiagnosticsEngine::Level DiagLevel,
+ const Diagnostic &Info) override {
// Default implementation (Warnings/errors count).
DiagnosticConsumer::HandleDiagnostic(DiagLevel, Info);
diff --git a/include/clang/Frontend/ChainedIncludesSource.h b/include/clang/Frontend/ChainedIncludesSource.h
deleted file mode 100644
index aa30460040a5..000000000000
--- a/include/clang/Frontend/ChainedIncludesSource.h
+++ /dev/null
@@ -1,75 +0,0 @@
-//===- ChainedIncludesSource.h - Chained PCHs in Memory ---------*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This file defines the ChainedIncludesSource class, which converts headers
-// to chained PCHs in memory, mainly used for testing.
-//
-//===----------------------------------------------------------------------===//
-#ifndef LLVM_CLANG_SERIALIZATION_CHAINEDINCLUDESSOURCE_H
-#define LLVM_CLANG_SERIALIZATION_CHAINEDINCLUDESSOURCE_H
-
-#include "clang/Sema/ExternalSemaSource.h"
-#include <vector>
-
-namespace clang {
- class CompilerInstance;
-
-class ChainedIncludesSource : public ExternalSemaSource {
-public:
- virtual ~ChainedIncludesSource();
-
- static ChainedIncludesSource *create(CompilerInstance &CI);
-
- ExternalSemaSource &getFinalReader() const { return *FinalReader; }
-
-private:
- std::vector<CompilerInstance *> CIs;
- OwningPtr<ExternalSemaSource> FinalReader;
-
-
-protected:
-
-//===----------------------------------------------------------------------===//
-// ExternalASTSource interface.
-//===----------------------------------------------------------------------===//
-
- virtual Decl *GetExternalDecl(uint32_t ID);
- virtual Selector GetExternalSelector(uint32_t ID);
- virtual uint32_t GetNumExternalSelectors();
- virtual Stmt *GetExternalDeclStmt(uint64_t Offset);
- virtual CXXBaseSpecifier *GetExternalCXXBaseSpecifiers(uint64_t Offset);
- virtual bool FindExternalVisibleDeclsByName(const DeclContext *DC,
- DeclarationName Name);
- virtual ExternalLoadResult FindExternalLexicalDecls(const DeclContext *DC,
- bool (*isKindWeWant)(Decl::Kind),
- SmallVectorImpl<Decl*> &Result);
- virtual void CompleteType(TagDecl *Tag);
- virtual void CompleteType(ObjCInterfaceDecl *Class);
- virtual void StartedDeserializing();
- virtual void FinishedDeserializing();
- virtual void StartTranslationUnit(ASTConsumer *Consumer);
- virtual void PrintStats();
-
- /// Return the amount of memory used by memory buffers, breaking down
- /// by heap-backed versus mmap'ed memory.
- virtual void getMemoryBufferSizes(MemoryBufferSizes &sizes) const;
-
-//===----------------------------------------------------------------------===//
-// ExternalSemaSource interface.
-//===----------------------------------------------------------------------===//
-
- virtual void InitializeSema(Sema &S);
- virtual void ForgetSema();
- virtual void ReadMethodPool(Selector Sel);
- virtual bool LookupUnqualified(LookupResult &R, Scope *S);
-};
-
-}
-
-#endif
diff --git a/include/clang/Frontend/CodeGenOptions.def b/include/clang/Frontend/CodeGenOptions.def
index 78b825dc14ff..1d92efeda258 100644
--- a/include/clang/Frontend/CodeGenOptions.def
+++ b/include/clang/Frontend/CodeGenOptions.def
@@ -28,6 +28,8 @@ CODEGENOPT(Name, 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.
@@ -59,8 +61,6 @@ 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(HiddenWeakVTables , 1, 0) ///< Emit weak vtables, RTTI, and thunks with
- ///< hidden visibility.
CODEGENOPT(InstrumentFunctions , 1, 0) ///< Set when -finstrument-functions is
///< enabled.
CODEGENOPT(InstrumentForProfiling , 1, 0) ///< Set when -pg is enabled.
@@ -68,7 +68,6 @@ CODEGENOPT(LessPreciseFPMAD , 1, 0) ///< Enable less precise MAD instructions t
///< be generated.
CODEGENOPT(MergeAllConstants , 1, 1) ///< Merge identical constants.
CODEGENOPT(NoCommon , 1, 0) ///< Set when -fno-common or C++ is enabled.
-CODEGENOPT(NoDwarf2CFIAsm , 1, 0) ///< Set when -fno-dwarf2-cfi-asm is enabled.
CODEGENOPT(NoDwarfDirectoryAsm , 1, 0) ///< Set when -fno-dwarf-directory-asm is
///< enabled.
CODEGENOPT(NoExecStack , 1, 0) ///< Set when -Wa,--noexecstack is enabled.
@@ -87,6 +86,9 @@ CODEGENOPT(OmitLeafFramePointer , 1, 0) ///< Set when -momit-leaf-frame-pointer
VALUE_CODEGENOPT(OptimizationLevel, 3, 0) ///< The -O[0-4] 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.
+
/// If -fpcc-struct-return or -freg-struct-return is specified.
ENUM_CODEGENOPT(StructReturnConvention, StructReturnConventionKind, 2, SRCK_Default)
@@ -96,7 +98,7 @@ 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, 1, 0) ///< Enable tracking origins in
+CODEGENOPT(SanitizeMemoryTrackOrigins, 2, 0) ///< Enable tracking origins in
///< MemorySanitizer
CODEGENOPT(SanitizeUndefinedTrapOnError, 1, 0) ///< Set on
/// -fsanitize-undefined-trap-on-error
@@ -138,7 +140,7 @@ VALUE_CODEGENOPT(NumRegisterParameters, 32, 0)
VALUE_CODEGENOPT(SSPBufferSize, 32, 0)
/// The kind of generated debug info.
-ENUM_CODEGENOPT(DebugInfo, DebugInfoKind, 2, NoDebugInfo)
+ENUM_CODEGENOPT(DebugInfo, DebugInfoKind, 3, NoDebugInfo)
/// Dwarf version.
VALUE_CODEGENOPT(DwarfVersion, 3, 0)
diff --git a/include/clang/Frontend/CodeGenOptions.h b/include/clang/Frontend/CodeGenOptions.h
index 86aabf7b95ec..3d532cea3431 100644
--- a/include/clang/Frontend/CodeGenOptions.h
+++ b/include/clang/Frontend/CodeGenOptions.h
@@ -16,6 +16,7 @@
#include <string>
#include <vector>
+#include "llvm/Support/Regex.h"
namespace clang {
@@ -50,12 +51,27 @@ public:
};
enum DebugInfoKind {
- NoDebugInfo, // Don't generate debug info.
- DebugLineTablesOnly, // Emit only debug info necessary for generating
- // line number tables (-gline-tables-only).
- LimitedDebugInfo, // Limit generated debug info to reduce size
- // (-flimit-debug-info).
- FullDebugInfo // Generate complete debug info.
+ 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 TLSModel {
@@ -134,6 +150,31 @@ public:
/// 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;
+
+ /// 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;
+
public:
// Define accessors/mutators for code generation options of enumeration type.
#define CODEGENOPT(Name, Bits, Default)
diff --git a/include/clang/Frontend/CompilerInstance.h b/include/clang/Frontend/CompilerInstance.h
index 5673c5908d78..44e91026acb5 100644
--- a/include/clang/Frontend/CompilerInstance.h
+++ b/include/clang/Frontend/CompilerInstance.h
@@ -13,14 +13,15 @@
#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/OwningPtr.h"
#include "llvm/ADT/StringRef.h"
#include <cassert>
#include <list>
+#include <memory>
#include <string>
#include <utility>
@@ -74,6 +75,9 @@ class CompilerInstance : public ModuleLoader {
/// The target being compiled for.
IntrusiveRefCntPtr<TargetInfo> Target;
+ /// The virtual file system.
+ IntrusiveRefCntPtr<vfs::FileSystem> VirtualFileSystem;
+
/// The file manager.
IntrusiveRefCntPtr<FileManager> FileMgr;
@@ -87,19 +91,27 @@ class CompilerInstance : public ModuleLoader {
IntrusiveRefCntPtr<ASTContext> Context;
/// The AST consumer.
- OwningPtr<ASTConsumer> Consumer;
+ std::unique_ptr<ASTConsumer> Consumer;
/// The code completion consumer.
- OwningPtr<CodeCompleteConsumer> CompletionConsumer;
+ std::unique_ptr<CodeCompleteConsumer> CompletionConsumer;
/// \brief The semantic analysis object.
- OwningPtr<Sema> TheSema;
+ std::unique_ptr<Sema> TheSema;
/// \brief The frontend timer
- OwningPtr<llvm::Timer> FrontendTimer;
+ 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 dependency file generator.
+ std::unique_ptr<DependencyFileGenerator> TheDependencyFileGenerator;
- /// \brief Non-owning reference to the ASTReader, if one exists.
- ASTReader *ModuleManager;
+ std::vector<std::shared_ptr<DependencyCollector>> DependencyCollectors;
/// \brief The set of top-level modules that has already been loaded,
/// along with the module map
@@ -117,13 +129,16 @@ class CompilerInstance : public ModuleLoader {
/// 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
+ /// TempFilename may be empty and Filename non-empty if creating the temporary
/// failed.
struct OutputFile {
std::string Filename;
@@ -141,7 +156,7 @@ class CompilerInstance : public ModuleLoader {
CompilerInstance(const CompilerInstance &) LLVM_DELETED_FUNCTION;
void operator=(const CompilerInstance &) LLVM_DELETED_FUNCTION;
public:
- CompilerInstance();
+ explicit CompilerInstance(bool BuildingModule = false);
~CompilerInstance();
/// @name High-Level Operations
@@ -183,7 +198,7 @@ public:
/// @name Compiler Invocation and Options
/// {
- bool hasInvocation() const { return Invocation != 0; }
+ bool hasInvocation() const { return Invocation != nullptr; }
CompilerInvocation &getInvocation() {
assert(Invocation && "Compiler instance has no invocation!");
@@ -281,7 +296,7 @@ public:
/// @name Diagnostics Engine
/// {
- bool hasDiagnostics() const { return Diagnostics != 0; }
+ bool hasDiagnostics() const { return Diagnostics != nullptr; }
/// Get the current diagnostics engine.
DiagnosticsEngine &getDiagnostics() const {
@@ -302,7 +317,7 @@ public:
/// @name Target Info
/// {
- bool hasTarget() const { return Target != 0; }
+ bool hasTarget() const { return Target != nullptr; }
TargetInfo &getTarget() const {
assert(Target && "Compiler instance has no target!");
@@ -313,10 +328,30 @@ public:
void setTarget(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 != 0; }
+ bool hasFileManager() const { return FileMgr != nullptr; }
/// Return the current file manager to the caller.
FileManager &getFileManager() const {
@@ -325,17 +360,18 @@ public:
}
void resetAndLeakFileManager() {
+ BuryPointer(FileMgr.get());
FileMgr.resetWithoutRelease();
}
- /// setFileManager - Replace the current file manager.
+ /// \brief Replace the current file manager and virtual file system.
void setFileManager(FileManager *Value);
/// }
/// @name Source Manager
/// {
- bool hasSourceManager() const { return SourceMgr != 0; }
+ bool hasSourceManager() const { return SourceMgr != nullptr; }
/// Return the current source manager.
SourceManager &getSourceManager() const {
@@ -344,6 +380,7 @@ public:
}
void resetAndLeakSourceManager() {
+ BuryPointer(SourceMgr.get());
SourceMgr.resetWithoutRelease();
}
@@ -354,7 +391,7 @@ public:
/// @name Preprocessor
/// {
- bool hasPreprocessor() const { return PP != 0; }
+ bool hasPreprocessor() const { return PP != nullptr; }
/// Return the current preprocessor.
Preprocessor &getPreprocessor() const {
@@ -363,6 +400,7 @@ public:
}
void resetAndLeakPreprocessor() {
+ BuryPointer(PP.get());
PP.resetWithoutRelease();
}
@@ -373,7 +411,7 @@ public:
/// @name ASTContext
/// {
- bool hasASTContext() const { return Context != 0; }
+ bool hasASTContext() const { return Context != nullptr; }
ASTContext &getASTContext() const {
assert(Context && "Compiler instance has no AST context!");
@@ -381,6 +419,7 @@ public:
}
void resetAndLeakASTContext() {
+ BuryPointer(Context.get());
Context.resetWithoutRelease();
}
@@ -395,7 +434,7 @@ public:
/// @name ASTConsumer
/// {
- bool hasASTConsumer() const { return Consumer.isValid(); }
+ bool hasASTConsumer() const { return (bool)Consumer; }
ASTConsumer &getASTConsumer() const {
assert(Consumer && "Compiler instance has no AST consumer!");
@@ -404,7 +443,7 @@ public:
/// takeASTConsumer - Remove the current AST consumer and give ownership to
/// the caller.
- ASTConsumer *takeASTConsumer() { return Consumer.take(); }
+ ASTConsumer *takeASTConsumer() { return Consumer.release(); }
/// setASTConsumer - Replace the current AST consumer; the compiler instance
/// takes ownership of \p Value.
@@ -413,29 +452,32 @@ public:
/// }
/// @name Semantic analysis
/// {
- bool hasSema() const { return TheSema.isValid(); }
-
+ bool hasSema() const { return (bool)TheSema; }
+
Sema &getSema() const {
assert(TheSema && "Compiler instance has no Sema object!");
return *TheSema;
}
-
- Sema *takeSema() { return TheSema.take(); }
-
+
+ Sema *takeSema() { return TheSema.release(); }
+ void resetAndLeakSema() { BuryPointer(TheSema.release()); }
+
/// }
/// @name Module Management
/// {
- ASTReader *getModuleManager() const { return ModuleManager; }
- void setModuleManager(ASTReader *Reader) { ModuleManager = Reader; }
+ IntrusiveRefCntPtr<ASTReader> getModuleManager() const;
+ void setModuleManager(IntrusiveRefCntPtr<ASTReader> Reader);
+
+ std::shared_ptr<ModuleDependencyCollector> getModuleDepCollector() const;
+ void setModuleDepCollector(
+ std::shared_ptr<ModuleDependencyCollector> Collector);
/// }
/// @name Code Completion
/// {
- bool hasCodeCompletionConsumer() const {
- return CompletionConsumer.isValid();
- }
+ bool hasCodeCompletionConsumer() const { return (bool)CompletionConsumer; }
CodeCompleteConsumer &getCodeCompletionConsumer() const {
assert(CompletionConsumer &&
@@ -446,7 +488,7 @@ public:
/// takeCodeCompletionConsumer - Remove the current code completion consumer
/// and give ownership to the caller.
CodeCompleteConsumer *takeCodeCompletionConsumer() {
- return CompletionConsumer.take();
+ return CompletionConsumer.release();
}
/// setCodeCompletionConsumer - Replace the current code completion consumer;
@@ -457,7 +499,7 @@ public:
/// @name Frontend timer
/// {
- bool hasFrontendTimer() const { return FrontendTimer.isValid(); }
+ bool hasFrontendTimer() const { return (bool)FrontendTimer; }
llvm::Timer &getFrontendTimer() const {
assert(FrontendTimer && "Compiler instance has no frontend timer!");
@@ -495,7 +537,7 @@ public:
///
/// \param ShouldOwnClient If Client is non-NULL, specifies whether
/// the diagnostic object should take ownership of the client.
- void createDiagnostics(DiagnosticConsumer *Client = 0,
+ void createDiagnostics(DiagnosticConsumer *Client = nullptr,
bool ShouldOwnClient = true);
/// Create a DiagnosticsEngine object with a the TextDiagnosticPrinter.
@@ -518,9 +560,9 @@ public:
/// \return The new object on success, or null on failure.
static IntrusiveRefCntPtr<DiagnosticsEngine>
createDiagnostics(DiagnosticOptions *Opts,
- DiagnosticConsumer *Client = 0,
+ DiagnosticConsumer *Client = nullptr,
bool ShouldOwnClient = true,
- const CodeGenOptions *CodeGenOpts = 0);
+ const CodeGenOptions *CodeGenOpts = nullptr);
/// Create the file manager and replace any existing one with it.
void createFileManager();
@@ -530,28 +572,26 @@ public:
/// Create the preprocessor, using the invocation, file, and source managers,
/// and replace any existing one with it.
- void createPreprocessor();
+ void createPreprocessor(TranslationUnitKind TUKind);
/// 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,
+ void createPCHExternalASTSource(StringRef Path, bool DisablePCHValidation,
bool AllowPCHWithCompilerErrors,
- void *DeserializationListener);
+ 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 ExternalASTSource *
- createPCHExternalASTSource(StringRef Path, const std::string &Sysroot,
- bool DisablePCHValidation,
- bool AllowPCHWithCompilerErrors,
- Preprocessor &PP, ASTContext &Context,
- void *DeserializationListener, bool Preamble,
- bool UseGlobalModuleIndex);
+ static ExternalASTSource *createPCHExternalASTSource(
+ StringRef Path, const std::string &Sysroot, bool DisablePCHValidation,
+ bool AllowPCHWithCompilerErrors, Preprocessor &PP, ASTContext &Context,
+ 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
@@ -632,6 +672,8 @@ public:
std::string *ResultPathName,
std::string *TempPathName);
+ llvm::raw_null_ostream *createNullOutputFile();
+
/// }
/// @name Initialization Utility Methods
/// {
@@ -653,21 +695,28 @@ public:
const FrontendOptions &Opts);
/// }
-
- virtual ModuleLoadResult loadModule(SourceLocation ImportLoc,
- ModuleIdPath Path,
- Module::NameVisibilityKind Visibility,
- bool IsInclusionDirective);
- virtual void makeModuleVisible(Module *Mod,
- Module::NameVisibilityKind Visibility,
- SourceLocation ImportLoc,
- bool Complain);
+ // Create module manager.
+ void createModuleManager();
+
+ ModuleLoadResult loadModule(SourceLocation ImportLoc, ModuleIdPath Path,
+ Module::NameVisibilityKind Visibility,
+ bool IsInclusionDirective) override;
+
+ void makeModuleVisible(Module *Mod, Module::NameVisibilityKind Visibility,
+ SourceLocation ImportLoc, bool Complain) 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
diff --git a/include/clang/Frontend/CompilerInvocation.h b/include/clang/Frontend/CompilerInvocation.h
index f64773c2c4bd..f05ab80c8d55 100644
--- a/include/clang/Frontend/CompilerInvocation.h
+++ b/include/clang/Frontend/CompilerInvocation.h
@@ -47,15 +47,17 @@ class DiagnosticsEngine;
/// 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 = 0);
+ DiagnosticsEngine *Diags = nullptr);
class CompilerInvocationBase : public RefCountedBase<CompilerInvocation> {
-protected:
+ void operator=(const CompilerInvocationBase &) LLVM_DELETED_FUNCTION;
+
+public:
/// Options controlling the language variant.
- IntrusiveRefCntPtr<LangOptions> LangOpts;
+ std::shared_ptr<LangOptions> LangOpts;
/// Options controlling the target.
- IntrusiveRefCntPtr<TargetOptions> TargetOpts;
+ std::shared_ptr<TargetOptions> TargetOpts;
/// Options controlling the diagnostic engine.
IntrusiveRefCntPtr<DiagnosticOptions> DiagnosticOpts;
@@ -66,17 +68,17 @@ protected:
/// Options controlling the preprocessor (aside from \#include handling).
IntrusiveRefCntPtr<PreprocessorOptions> PreprocessorOpts;
-public:
CompilerInvocationBase();
+ ~CompilerInvocationBase();
CompilerInvocationBase(const CompilerInvocationBase &X);
- LangOptions *getLangOpts() { return LangOpts.getPtr(); }
- const LangOptions *getLangOpts() const { return LangOpts.getPtr(); }
+ LangOptions *getLangOpts() { return LangOpts.get(); }
+ const LangOptions *getLangOpts() const { return LangOpts.get(); }
- TargetOptions &getTargetOpts() { return *TargetOpts.getPtr(); }
+ TargetOptions &getTargetOpts() { return *TargetOpts.get(); }
const TargetOptions &getTargetOpts() const {
- return *TargetOpts.getPtr();
+ return *TargetOpts.get();
}
DiagnosticOptions &getDiagnosticOpts() const { return *DiagnosticOpts; }
@@ -204,6 +206,14 @@ public:
/// @}
};
+namespace vfs {
+ class FileSystem;
+}
+
+IntrusiveRefCntPtr<vfs::FileSystem>
+createVFSFromCompilerInvocation(const CompilerInvocation &CI,
+ DiagnosticsEngine &Diags);
+
} // end namespace clang
#endif
diff --git a/include/clang/Frontend/DependencyOutputOptions.h b/include/clang/Frontend/DependencyOutputOptions.h
index fefb6f3eda84..5da14597b646 100644
--- a/include/clang/Frontend/DependencyOutputOptions.h
+++ b/include/clang/Frontend/DependencyOutputOptions.h
@@ -26,6 +26,7 @@ public:
/// 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 file to write dependency output to.
std::string OutputFile;
@@ -42,7 +43,10 @@ public:
/// \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;
@@ -50,6 +54,7 @@ public:
UsePhonyTargets = 0;
AddMissingHeaderDeps = 0;
PrintShowIncludes = 0;
+ IncludeModuleFiles = 0;
}
};
diff --git a/include/clang/Frontend/DiagnosticRenderer.h b/include/clang/Frontend/DiagnosticRenderer.h
index f3cd054045e3..ce1dc9046557 100644
--- a/include/clang/Frontend/DiagnosticRenderer.h
+++ b/include/clang/Frontend/DiagnosticRenderer.h
@@ -83,9 +83,7 @@ protected:
DiagnosticsEngine::Level Level,
ArrayRef<CharSourceRange> Ranges,
const SourceManager &SM) = 0;
-
- virtual void emitBasicNote(StringRef Message) = 0;
-
+
virtual void emitCodeContext(SourceLocation Loc,
DiagnosticsEngine::Level Level,
SmallVectorImpl<CharSourceRange>& Ranges,
@@ -108,6 +106,7 @@ protected:
private:
+ void emitBasicNote(StringRef Message);
void emitIncludeStack(SourceLocation Loc, PresumedLoc PLoc,
DiagnosticsEngine::Level Level, const SourceManager &SM);
void emitIncludeStackRecursively(SourceLocation Loc, const SourceManager &SM);
@@ -144,7 +143,7 @@ public:
StringRef Message, ArrayRef<CharSourceRange> Ranges,
ArrayRef<FixItHint> FixItHints,
const SourceManager *SM,
- DiagOrStoredDiag D = (Diagnostic *)0);
+ DiagOrStoredDiag D = (Diagnostic *)nullptr);
void emitStoredDiagnostic(StoredDiagnostic &Diag);
};
@@ -158,20 +157,17 @@ public:
: DiagnosticRenderer(LangOpts, DiagOpts) {}
virtual ~DiagnosticNoteRenderer();
-
- virtual void emitBasicNote(StringRef Message);
-
- virtual void emitIncludeLocation(SourceLocation Loc,
- PresumedLoc PLoc,
- const SourceManager &SM);
- virtual void emitImportLocation(SourceLocation Loc, PresumedLoc PLoc,
- StringRef ModuleName,
- const SourceManager &SM);
+ void emitIncludeLocation(SourceLocation Loc, PresumedLoc PLoc,
+ const SourceManager &SM) override;
- virtual void emitBuildingModuleLocation(SourceLocation Loc, PresumedLoc PLoc,
- StringRef ModuleName,
- const SourceManager &SM);
+ 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;
diff --git a/include/clang/Frontend/FrontendAction.h b/include/clang/Frontend/FrontendAction.h
index a568ba02d2a0..9ac9d2828f6a 100644
--- a/include/clang/Frontend/FrontendAction.h
+++ b/include/clang/Frontend/FrontendAction.h
@@ -21,8 +21,8 @@
#include "clang/Basic/LLVM.h"
#include "clang/Basic/LangOptions.h"
#include "clang/Frontend/FrontendOptions.h"
-#include "llvm/ADT/OwningPtr.h"
#include "llvm/ADT/StringRef.h"
+#include <memory>
#include <string>
#include <vector>
@@ -35,7 +35,7 @@ class CompilerInstance;
/// Abstract base class for actions which can be performed by the frontend.
class FrontendAction {
FrontendInputFile CurrentInput;
- OwningPtr<ASTUnit> CurrentASTUnit;
+ std::unique_ptr<ASTUnit> CurrentASTUnit;
CompilerInstance *Instance;
friend class ASTMergeAction;
friend class WrapperFrontendAction;
@@ -124,7 +124,7 @@ public:
bool isCurrentFileAST() const {
assert(!CurrentInput.isEmpty() && "No current file!");
- return CurrentASTUnit.isValid();
+ return (bool)CurrentASTUnit;
}
const FrontendInputFile &getCurrentInput() const {
@@ -146,11 +146,10 @@ public:
return *CurrentASTUnit;
}
- ASTUnit *takeCurrentASTUnit() {
- return CurrentASTUnit.take();
- }
+ ASTUnit *takeCurrentASTUnit() { return CurrentASTUnit.release(); }
- void setCurrentInput(const FrontendInputFile &CurrentInput, ASTUnit *AST = 0);
+ void setCurrentInput(const FrontendInputFile &CurrentInput,
+ ASTUnit *AST = nullptr);
/// @}
/// @name Supported Modes
@@ -220,17 +219,17 @@ protected:
///
/// This will also take care of instantiating a code completion consumer if
/// the user requested it and the action supports it.
- virtual void ExecuteAction();
+ void ExecuteAction() override;
public:
- virtual bool usesPreprocessorOnly() const { return false; }
+ bool usesPreprocessorOnly() const override { return false; }
};
class PluginASTAction : public ASTFrontendAction {
virtual void anchor();
protected:
- virtual ASTConsumer *CreateASTConsumer(CompilerInstance &CI,
- StringRef InFile) = 0;
+ ASTConsumer *CreateASTConsumer(CompilerInstance &CI,
+ StringRef InFile) override = 0;
public:
/// \brief Parse the given plugin command line arguments.
@@ -248,11 +247,11 @@ class PreprocessorFrontendAction : public FrontendAction {
protected:
/// \brief Provide a default implementation which returns aborts;
/// this method should never be called by FrontendAction clients.
- virtual ASTConsumer *CreateASTConsumer(CompilerInstance &CI,
- StringRef InFile);
+ ASTConsumer *CreateASTConsumer(CompilerInstance &CI,
+ StringRef InFile) override;
public:
- virtual bool usesPreprocessorOnly() const { return true; }
+ bool usesPreprocessorOnly() const override { return true; }
};
/// \brief A frontend action which simply wraps some other runtime-specified
@@ -262,28 +261,27 @@ public:
/// some existing action's behavior. It implements every virtual method in
/// the FrontendAction interface by forwarding to the wrapped action.
class WrapperFrontendAction : public FrontendAction {
- OwningPtr<FrontendAction> WrappedAction;
+ std::unique_ptr<FrontendAction> WrappedAction;
protected:
- virtual ASTConsumer *CreateASTConsumer(CompilerInstance &CI,
- StringRef InFile);
- virtual bool BeginInvocation(CompilerInstance &CI);
- virtual bool BeginSourceFileAction(CompilerInstance &CI,
- StringRef Filename);
- virtual void ExecuteAction();
- virtual void EndSourceFileAction();
+ 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);
- virtual bool usesPreprocessorOnly() const;
- virtual TranslationUnitKind getTranslationUnitKind();
- virtual bool hasPCHSupport() const;
- virtual bool hasASTFileSupport() const;
- virtual bool hasIRSupport() const;
- virtual bool hasCodeCompletionSupport() const;
+ 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
diff --git a/include/clang/Frontend/FrontendActions.h b/include/clang/Frontend/FrontendActions.h
index f3d12769f143..84cc82cfbe2f 100644
--- a/include/clang/Frontend/FrontendActions.h
+++ b/include/clang/Frontend/FrontendActions.h
@@ -17,21 +17,22 @@
namespace clang {
class Module;
+class FileEntry;
//===----------------------------------------------------------------------===//
// Custom Consumer Actions
//===----------------------------------------------------------------------===//
class InitOnlyAction : public FrontendAction {
- virtual void ExecuteAction();
+ void ExecuteAction() override;
- virtual ASTConsumer *CreateASTConsumer(CompilerInstance &CI,
- StringRef InFile);
+ 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.
- virtual bool usesPreprocessorOnly() const { return false; }
+ bool usesPreprocessorOnly() const override { return false; }
};
//===----------------------------------------------------------------------===//
@@ -40,44 +41,44 @@ public:
class ASTPrintAction : public ASTFrontendAction {
protected:
- virtual ASTConsumer *CreateASTConsumer(CompilerInstance &CI,
- StringRef InFile);
+ ASTConsumer *CreateASTConsumer(CompilerInstance &CI,
+ StringRef InFile) override;
};
class ASTDumpAction : public ASTFrontendAction {
protected:
- virtual ASTConsumer *CreateASTConsumer(CompilerInstance &CI,
- StringRef InFile);
+ ASTConsumer *CreateASTConsumer(CompilerInstance &CI,
+ StringRef InFile) override;
};
class ASTDeclListAction : public ASTFrontendAction {
protected:
- virtual ASTConsumer *CreateASTConsumer(CompilerInstance &CI,
- StringRef InFile);
+ ASTConsumer *CreateASTConsumer(CompilerInstance &CI,
+ StringRef InFile) override;
};
class ASTViewAction : public ASTFrontendAction {
protected:
- virtual ASTConsumer *CreateASTConsumer(CompilerInstance &CI,
- StringRef InFile);
+ ASTConsumer *CreateASTConsumer(CompilerInstance &CI,
+ StringRef InFile) override;
};
class DeclContextPrintAction : public ASTFrontendAction {
protected:
- virtual ASTConsumer *CreateASTConsumer(CompilerInstance &CI,
- StringRef InFile);
+ ASTConsumer *CreateASTConsumer(CompilerInstance &CI,
+ StringRef InFile) override;
};
class GeneratePCHAction : public ASTFrontendAction {
protected:
- virtual ASTConsumer *CreateASTConsumer(CompilerInstance &CI,
- StringRef InFile);
+ ASTConsumer *CreateASTConsumer(CompilerInstance &CI,
+ StringRef InFile) override;
- virtual TranslationUnitKind getTranslationUnitKind() {
+ TranslationUnitKind getTranslationUnitKind() override {
return TU_Prefix;
}
- virtual bool hasASTFileSupport() const { return false; }
+ bool hasASTFileSupport() const override { return false; }
public:
/// \brief Compute the AST consumer arguments that will be used to
@@ -93,57 +94,71 @@ public:
class GenerateModuleAction : public ASTFrontendAction {
clang::Module *Module;
+ const FileEntry *ModuleMapForUniquing;
bool IsSystem;
protected:
- virtual ASTConsumer *CreateASTConsumer(CompilerInstance &CI,
- StringRef InFile);
-
- virtual TranslationUnitKind getTranslationUnitKind() {
+ ASTConsumer *CreateASTConsumer(CompilerInstance &CI,
+ StringRef InFile) override;
+
+ TranslationUnitKind getTranslationUnitKind() override {
return TU_Module;
}
-
- virtual bool hasASTFileSupport() const { return false; }
-
+
+ bool hasASTFileSupport() const override { return false; }
+
public:
- explicit GenerateModuleAction(bool IsSystem = false)
- : ASTFrontendAction(), IsSystem(IsSystem) { }
+ GenerateModuleAction(const FileEntry *ModuleMap = nullptr,
+ bool IsSystem = false)
+ : ASTFrontendAction(), ModuleMapForUniquing(ModuleMap), IsSystem(IsSystem)
+ { }
+
+ bool BeginSourceFileAction(CompilerInstance &CI, StringRef Filename) override;
- virtual bool BeginSourceFileAction(CompilerInstance &CI, StringRef Filename);
-
/// \brief Compute the AST consumer arguments that will be used to
/// create the PCHGenerator instance returned by CreateASTConsumer.
///
/// \returns true if an error occurred, false otherwise.
- static bool ComputeASTConsumerArguments(CompilerInstance &CI,
- StringRef InFile,
- std::string &Sysroot,
- std::string &OutputFile,
- raw_ostream *&OS);
+ bool ComputeASTConsumerArguments(CompilerInstance &CI,
+ StringRef InFile,
+ std::string &Sysroot,
+ std::string &OutputFile,
+ raw_ostream *&OS);
};
class SyntaxOnlyAction : public ASTFrontendAction {
protected:
- virtual ASTConsumer *CreateASTConsumer(CompilerInstance &CI,
- StringRef InFile);
+ ASTConsumer *CreateASTConsumer(CompilerInstance &CI,
+ StringRef InFile) override;
public:
- virtual bool hasCodeCompletionSupport() const { return true; }
+ 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:
- virtual ASTConsumer *CreateASTConsumer(CompilerInstance &CI,
- StringRef InFile);
- virtual void ExecuteAction();
-
+ ASTConsumer *CreateASTConsumer(CompilerInstance &CI,
+ StringRef InFile) override;
+ void ExecuteAction() override;
+
public:
- virtual bool hasPCHSupport() const { return false; }
- virtual bool hasASTFileSupport() const { return true; }
- virtual bool hasIRSupport() const { return false; }
- virtual bool hasCodeCompletionSupport() const { return false; }
+ 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:
+ ASTConsumer *CreateASTConsumer(CompilerInstance &CI,
+ StringRef InFile) override;
+
+ void ExecuteAction() override;
+
+public:
+ bool hasCodeCompletionSupport() const override { return false; }
};
/**
@@ -162,34 +177,34 @@ class ASTMergeAction : public FrontendAction {
std::vector<std::string> ASTFiles;
protected:
- virtual ASTConsumer *CreateASTConsumer(CompilerInstance &CI,
- StringRef InFile);
+ ASTConsumer *CreateASTConsumer(CompilerInstance &CI,
+ StringRef InFile) override;
- virtual bool BeginSourceFileAction(CompilerInstance &CI,
- StringRef Filename);
+ bool BeginSourceFileAction(CompilerInstance &CI,
+ StringRef Filename) override;
- virtual void ExecuteAction();
- virtual void EndSourceFileAction();
+ void ExecuteAction() override;
+ void EndSourceFileAction() override;
public:
ASTMergeAction(FrontendAction *AdaptedAction, ArrayRef<std::string> ASTFiles);
virtual ~ASTMergeAction();
- virtual bool usesPreprocessorOnly() const;
- virtual TranslationUnitKind getTranslationUnitKind();
- virtual bool hasPCHSupport() const;
- virtual bool hasASTFileSupport() const;
- virtual bool hasCodeCompletionSupport() const;
+ 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();
- virtual ASTConsumer *CreateASTConsumer(CompilerInstance &, StringRef) {
- return 0;
+ void ExecuteAction() override;
+ ASTConsumer *CreateASTConsumer(CompilerInstance &, StringRef) override {
+ return nullptr;
}
-
- virtual bool usesPreprocessorOnly() const { return true; }
+
+ bool usesPreprocessorOnly() const override { return true; }
};
//===----------------------------------------------------------------------===//
@@ -198,29 +213,29 @@ protected:
class DumpRawTokensAction : public PreprocessorFrontendAction {
protected:
- void ExecuteAction();
+ void ExecuteAction() override;
};
class DumpTokensAction : public PreprocessorFrontendAction {
protected:
- void ExecuteAction();
+ void ExecuteAction() override;
};
class GeneratePTHAction : public PreprocessorFrontendAction {
protected:
- void ExecuteAction();
+ void ExecuteAction() override;
};
class PreprocessOnlyAction : public PreprocessorFrontendAction {
protected:
- void ExecuteAction();
+ void ExecuteAction() override;
};
class PrintPreprocessedAction : public PreprocessorFrontendAction {
protected:
- void ExecuteAction();
+ void ExecuteAction() override;
- virtual bool hasPCHSupport() const { return true; }
+ bool hasPCHSupport() const override { return true; }
};
} // end namespace clang
diff --git a/include/clang/Frontend/FrontendOptions.h b/include/clang/Frontend/FrontendOptions.h
index 4b321e86d29c..e87da8de1cfa 100644
--- a/include/clang/Frontend/FrontendOptions.h
+++ b/include/clang/Frontend/FrontendOptions.h
@@ -43,6 +43,7 @@ namespace frontend {
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.
@@ -89,9 +90,9 @@ class FrontendInputFile {
bool IsSystem;
public:
- FrontendInputFile() : Buffer(0), Kind(IK_None) { }
+ FrontendInputFile() : Buffer(nullptr), Kind(IK_None) { }
FrontendInputFile(StringRef File, InputKind Kind, bool IsSystem = false)
- : File(File.str()), Buffer(0), Kind(Kind), IsSystem(IsSystem) { }
+ : File(File.str()), Buffer(nullptr), Kind(Kind), IsSystem(IsSystem) { }
FrontendInputFile(llvm::MemoryBuffer *buffer, InputKind Kind,
bool IsSystem = false)
: Buffer(buffer), Kind(Kind), IsSystem(IsSystem) { }
@@ -99,9 +100,9 @@ public:
InputKind getKind() const { return Kind; }
bool isSystem() const { return IsSystem; }
- bool isEmpty() const { return File.empty() && Buffer == 0; }
+ bool isEmpty() const { return File.empty() && Buffer == nullptr; }
bool isFile() const { return !isBuffer(); }
- bool isBuffer() const { return Buffer != 0; }
+ bool isBuffer() const { return Buffer != nullptr; }
StringRef getFile() const {
assert(isFile());
@@ -179,10 +180,13 @@ public:
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,
ObjCMT_MigrateDecls = (ObjCMT_ReadonlyProperty | ObjCMT_ReadwriteProperty |
ObjCMT_Annotation | ObjCMT_Instancetype |
ObjCMT_NsMacros | ObjCMT_ProtocolConformance |
- ObjCMT_NsAtomicIOSOnlyProperty),
+ ObjCMT_NsAtomicIOSOnlyProperty |
+ ObjCMT_DesignatedInitializer),
ObjCMT_MigrateAll = (ObjCMT_Literals | ObjCMT_Subscripting | ObjCMT_MigrateDecls)
};
unsigned ObjCMTAction;
diff --git a/include/clang/Frontend/FrontendPluginRegistry.h b/include/clang/Frontend/FrontendPluginRegistry.h
index ec925adb0186..49be495daa37 100644
--- a/include/clang/Frontend/FrontendPluginRegistry.h
+++ b/include/clang/Frontend/FrontendPluginRegistry.h
@@ -13,6 +13,9 @@
#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.
diff --git a/include/clang/Frontend/LangStandard.h b/include/clang/Frontend/LangStandard.h
index 1124d53eafd5..9680e1f2e04c 100644
--- a/include/clang/Frontend/LangStandard.h
+++ b/include/clang/Frontend/LangStandard.h
@@ -25,10 +25,11 @@ enum LangFeatures {
CPlusPlus = (1 << 4),
CPlusPlus11 = (1 << 5),
CPlusPlus1y = (1 << 6),
- Digraphs = (1 << 7),
- GNUMode = (1 << 8),
- HexFloat = (1 << 9),
- ImplicitInt = (1 << 10)
+ CPlusPlus1z = (1 << 7),
+ Digraphs = (1 << 8),
+ GNUMode = (1 << 9),
+ HexFloat = (1 << 10),
+ ImplicitInt = (1 << 11)
};
}
@@ -69,12 +70,15 @@ public:
/// isCPlusPlus - Language is a C++ variant.
bool isCPlusPlus() const { return Flags & frontend::CPlusPlus; }
- /// isCPlusPlus11 - Language is a C++0x variant.
+ /// isCPlusPlus11 - Language is a C++11 variant (or later).
bool isCPlusPlus11() const { return Flags & frontend::CPlusPlus11; }
- /// isCPlusPlus1y - Language is a C++1y variant.
+ /// isCPlusPlus1y - Language is a C++14 variant (or later).
bool isCPlusPlus1y() const { return Flags & frontend::CPlusPlus1y; }
+ /// 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; }
diff --git a/include/clang/Frontend/LangStandards.def b/include/clang/Frontend/LangStandards.def
index 7b2516b0e3ef..90a27b5b9982 100644
--- a/include/clang/Frontend/LangStandards.def
+++ b/include/clang/Frontend/LangStandards.def
@@ -108,13 +108,29 @@ LANGSTANDARD(gnucxx11, "gnu++11",
LineComment | CPlusPlus | CPlusPlus11 | Digraphs | GNUMode)
LANGSTANDARD(cxx1y, "c++1y",
- "Working draft for ISO C++ 2014",
+ "ISO C++ 2014 with amendments",
+ LineComment | CPlusPlus | CPlusPlus11 | CPlusPlus1y | Digraphs)
+LANGSTANDARD(cxx14, "c++14",
+ "ISO C++ 2014 with amendments",
LineComment | CPlusPlus | CPlusPlus11 | CPlusPlus1y | Digraphs)
LANGSTANDARD(gnucxx1y, "gnu++1y",
- "Working draft for ISO C++ 2014 with GNU extensions",
+ "ISO C++ 2014 with amendments and GNU extensions",
+ LineComment | CPlusPlus | CPlusPlus11 | CPlusPlus1y | Digraphs |
+ GNUMode)
+LANGSTANDARD(gnucxx14, "gnu++14",
+ "ISO C++ 2014 with amendments and GNU extensions",
LineComment | CPlusPlus | CPlusPlus11 | CPlusPlus1y | Digraphs |
GNUMode)
+LANGSTANDARD(cxx1z, "c++1z",
+ "Working draft for ISO C++ 2017",
+ LineComment | CPlusPlus | CPlusPlus11 | CPlusPlus1y | CPlusPlus1z |
+ Digraphs)
+LANGSTANDARD(gnucxx1z, "gnu++1z",
+ "Working draft for ISO C++ 2017 with GNU extensions",
+ LineComment | CPlusPlus | CPlusPlus11 | CPlusPlus1y | CPlusPlus1z |
+ Digraphs | GNUMode)
+
// OpenCL
LANGSTANDARD(opencl, "cl",
"OpenCL 1.0",
diff --git a/include/clang/Frontend/LayoutOverrideSource.h b/include/clang/Frontend/LayoutOverrideSource.h
index ec34e147650e..16d032b7dd72 100644
--- a/include/clang/Frontend/LayoutOverrideSource.h
+++ b/include/clang/Frontend/LayoutOverrideSource.h
@@ -47,12 +47,13 @@ namespace clang {
/// \brief If this particular record type has an overridden layout,
/// return that layout.
- virtual bool
+ 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);
+ llvm::DenseMap<const CXXRecordDecl *,
+ CharUnits> &VirtualBaseOffsets) override;
/// \brief Dump the overridden layouts.
void dump();
diff --git a/include/clang/Frontend/LogDiagnosticPrinter.h b/include/clang/Frontend/LogDiagnosticPrinter.h
index e8a6bb357cab..013031987045 100644
--- a/include/clang/Frontend/LogDiagnosticPrinter.h
+++ b/include/clang/Frontend/LogDiagnosticPrinter.h
@@ -39,7 +39,10 @@ class LogDiagnosticPrinter : public DiagnosticConsumer {
/// The level of the diagnostic.
DiagnosticsEngine::Level DiagnosticLevel;
};
-
+
+ void EmitDiagEntry(llvm::raw_ostream &OS,
+ const LogDiagnosticPrinter::DiagEntry &DE);
+
raw_ostream &OS;
const LangOptions *LangOpts;
IntrusiveRefCntPtr<DiagnosticOptions> DiagOpts;
@@ -62,14 +65,14 @@ public:
DwarfDebugFlags = Value;
}
- void BeginSourceFile(const LangOptions &LO, const Preprocessor *PP) {
+ void BeginSourceFile(const LangOptions &LO, const Preprocessor *PP) override {
LangOpts = &LO;
}
- void EndSourceFile();
+ void EndSourceFile() override;
- virtual void HandleDiagnostic(DiagnosticsEngine::Level DiagLevel,
- const Diagnostic &Info);
+ void HandleDiagnostic(DiagnosticsEngine::Level DiagLevel,
+ const Diagnostic &Info) override;
};
} // end namespace clang
diff --git a/include/clang/Frontend/MultiplexConsumer.h b/include/clang/Frontend/MultiplexConsumer.h
index 6ea7547c7140..4d31104cce18 100644
--- a/include/clang/Frontend/MultiplexConsumer.h
+++ b/include/clang/Frontend/MultiplexConsumer.h
@@ -17,7 +17,7 @@
#include "clang/Basic/LLVM.h"
#include "clang/Sema/SemaConsumer.h"
-#include "llvm/ADT/OwningPtr.h"
+#include <memory>
#include <vector>
namespace clang {
@@ -33,28 +33,35 @@ public:
~MultiplexConsumer();
// ASTConsumer
- virtual void Initialize(ASTContext &Context);
- virtual void HandleCXXStaticMemberVarInstantiation(VarDecl *VD);
- virtual bool HandleTopLevelDecl(DeclGroupRef D);
- virtual void HandleInterestingDecl(DeclGroupRef D);
- virtual void HandleTranslationUnit(ASTContext &Ctx);
- virtual void HandleTagDeclDefinition(TagDecl *D);
- virtual void HandleCXXImplicitFunctionInstantiation(FunctionDecl *D);
- virtual void HandleTopLevelDeclInObjCContainer(DeclGroupRef D);
- virtual void CompleteTentativeDefinition(VarDecl *D);
- virtual void HandleVTable(CXXRecordDecl *RD, bool DefinitionRequired);
- virtual ASTMutationListener *GetASTMutationListener();
- virtual ASTDeserializationListener *GetASTDeserializationListener();
- virtual void PrintStats();
+ 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, bool DefinitionRequired) override;
+ ASTMutationListener *GetASTMutationListener() override;
+ ASTDeserializationListener *GetASTDeserializationListener() override;
+ void PrintStats() override;
// SemaConsumer
- virtual void InitializeSema(Sema &S);
- virtual void ForgetSema();
+ void InitializeSema(Sema &S) override;
+ void ForgetSema() override;
private:
std::vector<ASTConsumer*> Consumers; // Owns these.
- OwningPtr<MultiplexASTMutationListener> MutationListener;
- OwningPtr<MultiplexASTDeserializationListener> DeserializationListener;
+ std::unique_ptr<MultiplexASTMutationListener> MutationListener;
+ std::unique_ptr<MultiplexASTDeserializationListener> DeserializationListener;
};
} // end namespace clang
diff --git a/include/clang/Frontend/SerializedDiagnosticPrinter.h b/include/clang/Frontend/SerializedDiagnosticPrinter.h
index 117771d15791..4dda1fa4b655 100644
--- a/include/clang/Frontend/SerializedDiagnosticPrinter.h
+++ b/include/clang/Frontend/SerializedDiagnosticPrinter.h
@@ -46,6 +46,19 @@ enum RecordIDs {
RECORD_LAST = RECORD_FIXIT
};
+/// 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 Returns a DiagnosticConsumer that serializes diagnostics to
/// a bitcode file.
///
diff --git a/include/clang/Frontend/TextDiagnostic.h b/include/clang/Frontend/TextDiagnostic.h
index c8d01b0b15eb..acebb90b7076 100644
--- a/include/clang/Frontend/TextDiagnostic.h
+++ b/include/clang/Frontend/TextDiagnostic.h
@@ -63,52 +63,48 @@ public:
/// formatting of their diagnostic messages.
///
/// \param OS Where the message is printed
- /// \param Level Used to colorizing the message
+ /// \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,
- DiagnosticsEngine::Level Level,
- StringRef Message,
- unsigned CurrentColumn, unsigned Columns,
- bool ShowColors);
+ static void printDiagnosticMessage(raw_ostream &OS, bool IsSupplemental,
+ StringRef Message, unsigned CurrentColumn,
+ unsigned Columns, bool ShowColors);
protected:
- virtual void emitDiagnosticMessage(SourceLocation Loc,PresumedLoc PLoc,
- DiagnosticsEngine::Level Level,
- StringRef Message,
- ArrayRef<CharSourceRange> Ranges,
- const SourceManager *SM,
- DiagOrStoredDiag D);
-
- virtual void emitDiagnosticLoc(SourceLocation Loc, PresumedLoc PLoc,
- DiagnosticsEngine::Level Level,
- ArrayRef<CharSourceRange> Ranges,
- const SourceManager &SM);
-
- virtual void emitCodeContext(SourceLocation Loc,
- DiagnosticsEngine::Level Level,
- SmallVectorImpl<CharSourceRange>& Ranges,
- ArrayRef<FixItHint> Hints,
- const SourceManager &SM) {
+ 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);
}
-
- virtual void emitBasicNote(StringRef Message);
-
- virtual void emitIncludeLocation(SourceLocation Loc, PresumedLoc PLoc,
- const SourceManager &SM);
- virtual void emitImportLocation(SourceLocation Loc, PresumedLoc PLoc,
- StringRef ModuleName,
- const SourceManager &SM);
+ void emitIncludeLocation(SourceLocation Loc, PresumedLoc PLoc,
+ const SourceManager &SM) override;
+
+ void emitImportLocation(SourceLocation Loc, PresumedLoc PLoc,
+ StringRef ModuleName,
+ const SourceManager &SM) override;
- virtual void emitBuildingModuleLocation(SourceLocation Loc, PresumedLoc PLoc,
- StringRef ModuleName,
- const SourceManager &SM);
+ void emitBuildingModuleLocation(SourceLocation Loc, PresumedLoc PLoc,
+ StringRef ModuleName,
+ const SourceManager &SM) override;
private:
void emitSnippetAndCaret(SourceLocation Loc, DiagnosticsEngine::Level Level,
diff --git a/include/clang/Frontend/TextDiagnosticBuffer.h b/include/clang/Frontend/TextDiagnosticBuffer.h
index 93ac299da30e..fe5aa3e91d7f 100644
--- a/include/clang/Frontend/TextDiagnosticBuffer.h
+++ b/include/clang/Frontend/TextDiagnosticBuffer.h
@@ -28,7 +28,7 @@ public:
typedef DiagList::iterator iterator;
typedef DiagList::const_iterator const_iterator;
private:
- DiagList Errors, Warnings, Notes;
+ DiagList Errors, Warnings, Remarks, Notes;
public:
const_iterator err_begin() const { return Errors.begin(); }
const_iterator err_end() const { return Errors.end(); }
@@ -36,11 +36,14 @@ public:
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(); }
- virtual void HandleDiagnostic(DiagnosticsEngine::Level DiagLevel,
- const Diagnostic &Info);
+ void HandleDiagnostic(DiagnosticsEngine::Level DiagLevel,
+ const Diagnostic &Info) override;
/// FlushDiagnostics - Flush the buffered diagnostics to an given
/// diagnostic engine.
diff --git a/include/clang/Frontend/TextDiagnosticPrinter.h b/include/clang/Frontend/TextDiagnosticPrinter.h
index dc8047066c1d..9f6d5ff9dd17 100644
--- a/include/clang/Frontend/TextDiagnosticPrinter.h
+++ b/include/clang/Frontend/TextDiagnosticPrinter.h
@@ -18,7 +18,7 @@
#include "clang/Basic/Diagnostic.h"
#include "clang/Basic/LLVM.h"
#include "llvm/ADT/IntrusiveRefCntPtr.h"
-#include "llvm/ADT/OwningPtr.h"
+#include <memory>
namespace clang {
class DiagnosticOptions;
@@ -30,7 +30,7 @@ class TextDiagnosticPrinter : public DiagnosticConsumer {
IntrusiveRefCntPtr<DiagnosticOptions> DiagOpts;
/// \brief Handle to the currently active text diagnostic emitter.
- OwningPtr<TextDiagnostic> TextDiag;
+ std::unique_ptr<TextDiagnostic> TextDiag;
/// A string to prefix to error messages.
std::string Prefix;
@@ -47,9 +47,10 @@ public:
/// used.
void setPrefix(std::string Value) { Prefix = Value; }
- void BeginSourceFile(const LangOptions &LO, const Preprocessor *PP);
- void EndSourceFile();
- void HandleDiagnostic(DiagnosticsEngine::Level Level, const Diagnostic &Info);
+ void BeginSourceFile(const LangOptions &LO, const Preprocessor *PP) override;
+ void EndSourceFile() override;
+ void HandleDiagnostic(DiagnosticsEngine::Level Level,
+ const Diagnostic &Info) override;
};
} // end namespace clang
diff --git a/include/clang/Frontend/Utils.h b/include/clang/Frontend/Utils.h
index dff56c3a8a4e..4c0a7b7a9c66 100644
--- a/include/clang/Frontend/Utils.h
+++ b/include/clang/Frontend/Utils.h
@@ -15,8 +15,10 @@
#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 {
@@ -30,12 +32,14 @@ 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;
@@ -59,23 +63,81 @@ void ApplyHeaderSearchOptions(HeaderSearch &HS,
/// environment ready to process a single file.
void InitializePreprocessor(Preprocessor &PP,
const PreprocessorOptions &PPOpts,
- const HeaderSearchOptions &HSOpts,
const FrontendOptions &FEOpts);
-/// ProcessWarningOptions - Initialize the diagnostic client and process the
-/// warning options specified on the command line.
-void ProcessWarningOptions(DiagnosticsEngine &Diags,
- const DiagnosticOptions &Opts,
- bool ReportDiags = true);
-
/// DoPrintPreprocessedInput - Implement -E mode.
void DoPrintPreprocessedInput(Preprocessor &PP, raw_ostream* OS,
const PreprocessorOutputOptions &Opts);
-/// AttachDependencyFileGen - Create a dependency file generator, and attach
-/// it to the given preprocessor. This takes ownership of the output stream.
-void AttachDependencyFileGen(Preprocessor &PP,
- const DependencyOutputOptions &Opts);
+/// 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); }
+ 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.
@@ -101,6 +163,12 @@ void AttachHeaderIncludeGen(Preprocessor &PP, bool ShowAllHeaders = false,
/// a seekable stream.
void CacheTokens(Preprocessor &PP, llvm::raw_fd_ostream* 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.
///
@@ -115,7 +183,7 @@ createInvocationFromCommandLine(ArrayRef<const char *> Args,
/// 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 = 0);
+ DiagnosticsEngine *Diags = nullptr);
inline int getLastArgIntValue(const llvm::opt::ArgList &Args,
llvm::opt::OptSpecifier Id, int Default,
@@ -123,6 +191,22 @@ inline int getLastArgIntValue(const llvm::opt::ArgList &Args,
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);
+
} // end namespace clang
#endif
diff --git a/include/clang/Frontend/VerifyDiagnosticConsumer.h b/include/clang/Frontend/VerifyDiagnosticConsumer.h
index 95d7752517d8..9273fac50910 100644
--- a/include/clang/Frontend/VerifyDiagnosticConsumer.h
+++ b/include/clang/Frontend/VerifyDiagnosticConsumer.h
@@ -13,10 +13,10 @@
#include "clang/Basic/Diagnostic.h"
#include "clang/Lex/Preprocessor.h"
#include "llvm/ADT/DenseMap.h"
-#include "llvm/ADT/OwningPtr.h"
#include "llvm/ADT/PointerIntPair.h"
#include "llvm/ADT/STLExtras.h"
#include <climits>
+#include <memory>
namespace clang {
@@ -34,12 +34,12 @@ class FileEntry;
/// comment on the line that has the diagnostic, use:
///
/// \code
-/// expected-{error,warning,note}
+/// expected-{error,warning,remark,note}
/// \endcode
///
-/// to tag if it's an expected error or warning, and place the expected text
-/// between {{ and }} markers. The full text doesn't have to be included, only
-/// enough to ensure that the correct diagnostic was emitted.
+/// 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:
///
@@ -71,7 +71,10 @@ class FileEntry;
/// \endcode
///
/// The path can be absolute or relative and the same search paths will be used
-/// as for #include directives.
+/// 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
@@ -108,10 +111,11 @@ class FileEntry;
///
/// In this example, the diagnostic may appear only once, if at all.
///
-/// Regex matching mode may be selected by appending '-re' to type, such as:
+/// 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
+/// expected-error-re {{format specifies type 'wchar_t **' (aka '{{.+}}')}}
/// \endcode
///
/// Examples matching error: "variable has incomplete type 'struct s'"
@@ -120,10 +124,10 @@ class FileEntry;
/// // expected-error {{variable has incomplete type 'struct s'}}
/// // expected-error {{variable has incomplete type}}
///
-/// // expected-error-re {{variable has has type 'struct .'}}
-/// // expected-error-re {{variable has has type 'struct .*'}}
-/// // expected-error-re {{variable has has type 'struct (.*)'}}
-/// // expected-error-re {{variable has has type 'struct[[:space:]](.*)'}}
+/// // 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
@@ -142,7 +146,7 @@ public:
class Directive {
public:
static Directive *create(bool RegexKind, SourceLocation DirectiveLoc,
- SourceLocation DiagnosticLoc,
+ SourceLocation DiagnosticLoc, bool MatchAnyLine,
StringRef Text, unsigned Min, unsigned Max);
public:
/// Constant representing n or more matches.
@@ -152,6 +156,7 @@ public:
SourceLocation DiagnosticLoc;
const std::string Text;
unsigned Min, Max;
+ bool MatchAnyLine;
virtual ~Directive() { }
@@ -164,9 +169,9 @@ public:
protected:
Directive(SourceLocation DirectiveLoc, SourceLocation DiagnosticLoc,
- StringRef Text, unsigned Min, unsigned Max)
+ bool MatchAnyLine, StringRef Text, unsigned Min, unsigned Max)
: DirectiveLoc(DirectiveLoc), DiagnosticLoc(DiagnosticLoc),
- Text(Text), Min(Min), Max(Max) {
+ Text(Text), Min(Min), Max(Max), MatchAnyLine(MatchAnyLine) {
assert(!DirectiveLoc.isInvalid() && "DirectiveLoc is invalid!");
assert(!DiagnosticLoc.isInvalid() && "DiagnosticLoc is invalid!");
}
@@ -183,13 +188,17 @@ public:
struct ExpectedData {
DirectiveList Errors;
DirectiveList Warnings;
+ DirectiveList Remarks;
DirectiveList Notes;
- ~ExpectedData() {
+ void Reset() {
llvm::DeleteContainerPointers(Errors);
llvm::DeleteContainerPointers(Warnings);
+ llvm::DeleteContainerPointers(Remarks);
llvm::DeleteContainerPointers(Notes);
}
+
+ ~ExpectedData() { Reset(); }
};
enum DirectiveStatus {
@@ -203,7 +212,7 @@ private:
DiagnosticsEngine &Diags;
DiagnosticConsumer *PrimaryClient;
bool OwnsPrimaryClient;
- OwningPtr<TextDiagnosticBuffer> Buffer;
+ std::unique_ptr<TextDiagnosticBuffer> Buffer;
const Preprocessor *CurrentPreprocessor;
const LangOptions *LangOpts;
SourceManager *SrcManager;
@@ -217,24 +226,19 @@ private:
SrcManager = &SM;
}
-#ifndef NDEBUG
+ // 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;
-#endif
public:
/// Create a new verifying diagnostic client, which will issue errors to
@@ -243,10 +247,10 @@ public:
VerifyDiagnosticConsumer(DiagnosticsEngine &Diags);
~VerifyDiagnosticConsumer();
- virtual void BeginSourceFile(const LangOptions &LangOpts,
- const Preprocessor *PP);
+ void BeginSourceFile(const LangOptions &LangOpts,
+ const Preprocessor *PP) override;
- virtual void EndSourceFile();
+ void EndSourceFile() override;
enum ParsedStatus {
/// File has been processed via HandleComment.
@@ -262,10 +266,10 @@ public:
/// \brief Update lists of parsed and unparsed files.
void UpdateParsedFileStatus(SourceManager &SM, FileID FID, ParsedStatus PS);
- virtual bool HandleComment(Preprocessor &PP, SourceRange Comment);
+ bool HandleComment(Preprocessor &PP, SourceRange Comment) override;
- virtual void HandleDiagnostic(DiagnosticsEngine::Level DiagLevel,
- const Diagnostic &Info);
+ void HandleDiagnostic(DiagnosticsEngine::Level DiagLevel,
+ const Diagnostic &Info) override;
};
} // end namspace clang
diff --git a/include/clang/Index/CommentToXML.h b/include/clang/Index/CommentToXML.h
index 8444b145343f..bb7b71ad411b 100644
--- a/include/clang/Index/CommentToXML.h
+++ b/include/clang/Index/CommentToXML.h
@@ -11,6 +11,7 @@
#define LLVM_CLANG_INDEX_COMMENTTOXML_H
#include "clang/Basic/LLVM.h"
+#include <memory>
namespace clang {
class ASTContext;
@@ -24,11 +25,12 @@ namespace index {
class SimpleFormatContext;
class CommentToXMLConverter {
- SimpleFormatContext *FormatContext;
+ std::unique_ptr<SimpleFormatContext> FormatContext;
unsigned FormatInMemoryUniqueId;
public:
- CommentToXMLConverter() : FormatContext(0), FormatInMemoryUniqueId(0) {}
+ CommentToXMLConverter();
+ ~CommentToXMLConverter();
void convertCommentToHTML(const comments::FullComment *FC,
SmallVectorImpl<char> &HTML,
diff --git a/include/clang/Index/USRGeneration.h b/include/clang/Index/USRGeneration.h
index 7b0fd5063ac6..3195dee7506c 100644
--- a/include/clang/Index/USRGeneration.h
+++ b/include/clang/Index/USRGeneration.h
@@ -14,7 +14,9 @@
#include "llvm/ADT/StringRef.h"
namespace clang {
- class Decl;
+class Decl;
+class MacroDefinition;
+class SourceManager;
namespace index {
@@ -22,7 +24,7 @@ static inline StringRef getUSRSpacePrefix() {
return "c:";
}
-/// \brief Generate a USR for a Decl, including the prefix.
+/// \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);
@@ -47,6 +49,12 @@ 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 MacroDefinition *MD, const SourceManager &SM,
+ SmallVectorImpl<char> &Buf);
+
} // namespace index
} // namespace clang
diff --git a/include/clang/Lex/CMakeLists.txt b/include/clang/Lex/CMakeLists.txt
deleted file mode 100644
index 38055ebb64dd..000000000000
--- a/include/clang/Lex/CMakeLists.txt
+++ /dev/null
@@ -1,5 +0,0 @@
-clang_tablegen(AttrSpellings.inc -gen-clang-attr-spelling-list
- -I ${CMAKE_CURRENT_SOURCE_DIR}/../../
- SOURCE ../Basic/Attr.td
- TARGET ClangAttrSpellings
- DEPENDS AttrSpellings.inc)
diff --git a/include/clang/Lex/DirectoryLookup.h b/include/clang/Lex/DirectoryLookup.h
index dff3e8c3608d..9edf11966091 100644
--- a/include/clang/Lex/DirectoryLookup.h
+++ b/include/clang/Lex/DirectoryLookup.h
@@ -92,17 +92,21 @@ public:
/// getDir - Return the directory that this entry refers to.
///
- const DirectoryEntry *getDir() const { return isNormalDir() ? u.Dir : 0; }
+ 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 : 0;
+ return isFramework() ? u.Dir : nullptr;
}
/// getHeaderMap - Return the directory that this entry refers to.
///
- const HeaderMap *getHeaderMap() const { return isHeaderMap() ? u.Map : 0; }
+ 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; }
@@ -161,11 +165,17 @@ public:
/// \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.
- const FileEntry *LookupFile(StringRef Filename, HeaderSearch &HS,
+ ///
+ /// \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,
ModuleMap::KnownHeader *SuggestedModule,
- bool &InUserSpecifiedSystemFramework) const;
+ bool &InUserSpecifiedSystemFramework,
+ bool &HasBeenMapped,
+ SmallVectorImpl<char> &MappedName) const;
private:
const FileEntry *DoFrameworkLookup(
diff --git a/include/clang/Lex/HeaderMap.h b/include/clang/Lex/HeaderMap.h
index 8473a6a4e752..8e78b5ac9884 100644
--- a/include/clang/Lex/HeaderMap.h
+++ b/include/clang/Lex/HeaderMap.h
@@ -55,6 +55,11 @@ public:
/// "../../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;
diff --git a/include/clang/Lex/HeaderSearch.h b/include/clang/Lex/HeaderSearch.h
index fb1a86206354..034262982770 100644
--- a/include/clang/Lex/HeaderSearch.h
+++ b/include/clang/Lex/HeaderSearch.h
@@ -18,10 +18,10 @@
#include "clang/Lex/ModuleMap.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/IntrusiveRefCntPtr.h"
-#include "llvm/ADT/OwningPtr.h"
#include "llvm/ADT/StringMap.h"
#include "llvm/ADT/StringSet.h"
#include "llvm/Support/Allocator.h"
+#include <memory>
#include <vector>
namespace clang {
@@ -73,6 +73,9 @@ struct HeaderFileInfo {
/// provided via a header map. This bit indicates when this is one of
/// those framework headers.
unsigned IndexHeaderMapHeader : 1;
+
+ /// \brief Whether this file had been looked up as a header.
+ unsigned IsValid : 1;
/// \brief The number of times the file has been included already.
unsigned short NumIncludes;
@@ -102,8 +105,8 @@ struct HeaderFileInfo {
: isImport(false), isPragmaOnce(false), DirInfo(SrcMgr::C_User),
External(false), isModuleHeader(false), isCompilingModuleHeader(false),
HeaderRole(ModuleMap::NormalHeader),
- Resolved(false), IndexHeaderMapHeader(false),
- NumIncludes(0), ControllingMacroID(0), ControllingMacro(0) {}
+ Resolved(false), IndexHeaderMapHeader(false), IsValid(0),
+ NumIncludes(0), ControllingMacroID(0), ControllingMacro(nullptr) {}
/// \brief Retrieve the controlling macro for this header file, if
/// any.
@@ -158,6 +161,7 @@ class HeaderSearch {
/// \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
@@ -185,15 +189,27 @@ class HeaderSearch {
/// included, indexed by the FileEntry's UID.
std::vector<HeaderFileInfo> FileInfo;
- /// \brief Keeps track of each lookup performed by LookupFile.
- ///
- /// The first part of the value is the starting index in SearchDirs
- /// that the cached search was performed from. If there is a hit and
- /// this value doesn't match the current query, the cache has to be
- /// ignored. The second value is the entry in SearchDirs that satisfied
- /// the query.
- llvm::StringMap<std::pair<unsigned, unsigned>, llvm::BumpPtrAllocator>
- LookupFileCache;
+ /// 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.
@@ -204,7 +220,7 @@ class HeaderSearch {
/// include_alias pragma for Microsoft compatibility.
typedef llvm::StringMap<std::string, llvm::BumpPtrAllocator>
IncludeAliasMap;
- OwningPtr<IncludeAliasMap> IncludeAliases;
+ std::unique_ptr<IncludeAliasMap> IncludeAliases;
/// HeaderMaps - This is a mapping from FileEntry -> HeaderMap, uniquing
/// headermaps. This vector owns the headermap.
@@ -232,6 +248,8 @@ class HeaderSearch {
unsigned NumMultiIncludeFileOptzn;
unsigned NumFrameworkLookups, NumSubFrameworkLookups;
+ bool EnabledModules;
+
// HeaderSearch doesn't support default or copy construction.
HeaderSearch(const HeaderSearch&) LLVM_DELETED_FUNCTION;
void operator=(const HeaderSearch&) LLVM_DELETED_FUNCTION;
@@ -278,9 +296,7 @@ public:
}
/// \brief Checks whether the map exists or not.
- bool HasIncludeAliasMap() const {
- return IncludeAliases.isValid();
- }
+ bool HasIncludeAliasMap() const { return (bool)IncludeAliases; }
/// \brief Map the source include name to the dest include name.
///
@@ -347,13 +363,15 @@ public:
/// \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 CurFileEnt If non-null, indicates where the \#including file is, in
- /// case a relative search is needed.
+ /// \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
@@ -366,10 +384,10 @@ public:
/// \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, bool isAngled,
- const DirectoryLookup *FromDir,
+ const FileEntry *LookupFile(StringRef Filename, SourceLocation IncludeLoc,
+ bool isAngled, const DirectoryLookup *FromDir,
const DirectoryLookup *&CurDir,
- const FileEntry *CurFileEnt,
+ ArrayRef<const FileEntry *> Includers,
SmallVectorImpl<char> *SearchPath,
SmallVectorImpl<char> *RelativePath,
ModuleMap::KnownHeader *SuggestedModule,
@@ -458,6 +476,9 @@ public:
/// FileEntry, uniquing them through the 'HeaderMaps' datastructure.
const HeaderMap *CreateHeaderMap(const FileEntry *FE);
+ /// Returns true if modules are enabled.
+ bool enabledModules() const { return EnabledModules; }
+
/// \brief Retrieve the name of the module file that should be used to
/// load the given module.
///
@@ -472,9 +493,12 @@ public:
///
/// \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);
+ std::string getModuleFileName(StringRef ModuleName, StringRef ModuleMapPath);
/// \brief Lookup a module Search for a module with the given name.
///
@@ -486,11 +510,17 @@ public:
///
/// \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.
///
@@ -543,16 +573,20 @@ private:
/// of the given search directory.
void loadSubdirectoryModuleMaps(DirectoryLookup &SearchDir);
+ /// \brief Return the HeaderFileInfo structure for the specified FileEntry.
+ const HeaderFileInfo &getFileInfo(const FileEntry *FE) const {
+ return const_cast<HeaderSearch*>(this)->getFileInfo(FE);
+ }
+
public:
/// \brief Retrieve the module map.
ModuleMap &getModuleMap() { return ModMap; }
unsigned header_file_size() const { return FileInfo.size(); }
- /// \brief Return the HeaderFileInfo structure for the specified FileEntry.
- const HeaderFileInfo &getFileInfo(const FileEntry *FE) const {
- return const_cast<HeaderSearch*>(this)->getFileInfo(FE);
- }
+ /// \brief Get a \c HeaderFileInfo structure for the specified \c FileEntry,
+ /// if one exists.
+ bool tryGetFileInfo(const FileEntry *FE, HeaderFileInfo &Result) const;
// Used by external tools
typedef std::vector<DirectoryLookup>::const_iterator search_dir_iterator;
@@ -602,26 +636,32 @@ private:
/// invalid.
LMM_InvalidModuleMap
};
-
+
+ LoadModuleMapResult loadModuleMapFileImpl(const FileEntry *File,
+ bool IsSystem);
+
/// \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);
+ 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 IsSystem, bool IsFramework);
/// \brief Return the HeaderFileInfo structure for the specified FileEntry.
HeaderFileInfo &getFileInfo(const FileEntry *FE);
diff --git a/include/clang/Lex/HeaderSearchOptions.h b/include/clang/Lex/HeaderSearchOptions.h
index 0b21c0dd3492..06024b2e90f2 100644
--- a/include/clang/Lex/HeaderSearchOptions.h
+++ b/include/clang/Lex/HeaderSearchOptions.h
@@ -89,6 +89,9 @@ public:
/// \brief The directory used for the module cache.
std::string ModuleCachePath;
+ /// \brief The directory used for a user build.
+ std::string ModuleUserBuildPath;
+
/// \brief Whether we should disable the use of the hash string within the
/// module cache.
///
@@ -116,6 +119,12 @@ public:
/// 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::SetVector<std::string> ModulesIgnoreMacros;
@@ -123,6 +132,9 @@ public:
/// \brief The set of user-provided module-map-files.
llvm::SetVector<std::string> ModuleMapFiles;
+ /// \brief The set of user-provided virtual filesystem overlay files.
+ std::vector<std::string> VFSOverlayFiles;
+
/// Include the compiler builtin includes.
unsigned UseBuiltinIncludes : 1;
@@ -138,14 +150,25 @@ public:
/// 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;
+
public:
HeaderSearchOptions(StringRef _Sysroot = "/")
: Sysroot(_Sysroot), DisableModuleHash(0), ModuleMaps(0),
ModuleCachePruneInterval(7*24*60*60),
ModuleCachePruneAfter(31*24*60*60),
+ BuildSessionTimestamp(0),
UseBuiltinIncludes(true),
UseStandardSystemIncludes(true), UseStandardCXXIncludes(true),
- UseLibcxx(false), Verbose(false) {}
+ UseLibcxx(false), Verbose(false),
+ ModulesValidateOncePerBuildSession(false),
+ ModulesValidateSystemHeaders(false) {}
/// AddPath - Add the \p Path path to the specified \p Group list.
void AddPath(StringRef Path, frontend::IncludeDirGroup Group,
@@ -159,6 +182,10 @@ public:
void AddSystemHeaderPrefix(StringRef Prefix, bool IsSystemHeader) {
SystemHeaderPrefixes.push_back(SystemHeaderPrefix(Prefix, IsSystemHeader));
}
+
+ void AddVFSOverlayFile(StringRef Name) {
+ VFSOverlayFiles.push_back(Name);
+ }
};
} // end namespace clang
diff --git a/include/clang/Lex/Lexer.h b/include/clang/Lex/Lexer.h
index f456fa9cd51c..edcf883eced3 100644
--- a/include/clang/Lex/Lexer.h
+++ b/include/clang/Lex/Lexer.h
@@ -44,7 +44,7 @@ enum ConflictMarkerKind {
/// 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 {
- virtual void anchor();
+ void anchor() override;
//===--------------------------------------------------------------------===//
// Constant configuration values for this lexer.
@@ -145,7 +145,7 @@ public:
private:
/// IndirectLex - An indirect call to 'Lex' that can be invoked via
/// the PreprocessorLexer interface.
- void IndirectLex(Token &Result) { Lex(Result); }
+ void IndirectLex(Token &Result) override { Lex(Result); }
public:
/// LexFromRawLexer - Lex a token from a designated raw lexer (one with no
@@ -205,7 +205,7 @@ public:
/// 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 = 0);
+ void ReadToEndOfLine(SmallVectorImpl<char> *Result = nullptr);
/// Diag - Forwarding function for diagnostics. This translate a source
@@ -218,7 +218,9 @@ public:
/// getSourceLocation - Return a source location for the next character in
/// the current file.
- SourceLocation getSourceLocation() { return getSourceLocation(BufferPtr); }
+ SourceLocation getSourceLocation() override {
+ return getSourceLocation(BufferPtr);
+ }
/// \brief Return the current location in the buffer.
const char *getBufferLocation() const { return BufferPtr; }
@@ -246,7 +248,7 @@ public:
static unsigned getSpelling(const Token &Tok, const char *&Buffer,
const SourceManager &SourceMgr,
const LangOptions &LangOpts,
- bool *Invalid = 0);
+ 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
@@ -256,7 +258,7 @@ public:
static std::string getSpelling(const Token &Tok,
const SourceManager &SourceMgr,
const LangOptions &LangOpts,
- bool *Invalid = 0);
+ 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
@@ -270,7 +272,7 @@ public:
SmallVectorImpl<char> &buffer,
const SourceManager &SourceMgr,
const LangOptions &LangOpts,
- bool *invalid = 0);
+ 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.
@@ -329,7 +331,7 @@ public:
static bool isAtStartOfMacroExpansion(SourceLocation loc,
const SourceManager &SM,
const LangOptions &LangOpts,
- SourceLocation *MacroBegin = 0);
+ SourceLocation *MacroBegin = nullptr);
/// \brief Returns true if the given MacroID location points at the last
/// token of the macro expansion.
@@ -339,7 +341,7 @@ public:
static bool isAtEndOfMacroExpansion(SourceLocation loc,
const SourceManager &SM,
const LangOptions &LangOpts,
- SourceLocation *MacroEnd = 0);
+ SourceLocation *MacroEnd = nullptr);
/// \brief Accepts a range and returns a character range with file locations.
///
@@ -375,7 +377,7 @@ public:
static StringRef getSourceText(CharSourceRange Range,
const SourceManager &SM,
const LangOptions &LangOpts,
- bool *Invalid = 0);
+ bool *Invalid = nullptr);
/// \brief Retrieve the name of the immediate macro expansion.
///
@@ -546,7 +548,8 @@ private:
/// getCharAndSizeSlow - Handle the slow/uncommon case of the getCharAndSize
/// method.
- char getCharAndSizeSlow(const char *Ptr, unsigned &Size, Token *Tok = 0);
+ 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
@@ -614,8 +617,28 @@ private:
/// \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
diff --git a/include/clang/Lex/LiteralSupport.h b/include/clang/Lex/LiteralSupport.h
index 64d5aa2d5928..b7fcc5d34de6 100644
--- a/include/clang/Lex/LiteralSupport.h
+++ b/include/clang/Lex/LiteralSupport.h
@@ -33,6 +33,9 @@ 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.
@@ -48,6 +51,8 @@ class NumericLiteralParser {
bool saw_exponent, saw_period, saw_ud_suffix;
+ SmallString<32> UDSuffixBuf;
+
public:
NumericLiteralParser(StringRef TokSpelling,
SourceLocation TokLoc,
@@ -58,7 +63,7 @@ public:
bool isLongLong;
bool isFloat; // 1.0f
bool isImaginary; // 1.0i
- bool isMicrosoftInteger; // Microsoft suffix extension i8, i16, i32, or i64.
+ uint8_t MicrosoftInteger; // Microsoft suffix extension i8, i16, i32, or i64.
bool isIntegerLiteral() const {
return !saw_period && !saw_exponent;
@@ -72,7 +77,7 @@ public:
}
StringRef getUDSuffix() const {
assert(saw_ud_suffix);
- return StringRef(SuffixBegin, ThisTokEnd - SuffixBegin);
+ return UDSuffixBuf;
}
unsigned getUDSuffixOffset() const {
assert(saw_ud_suffix);
@@ -191,15 +196,16 @@ class StringLiteralParser {
unsigned UDSuffixToken;
unsigned UDSuffixOffset;
public:
- StringLiteralParser(const Token *StringToks, unsigned NumStringToks,
+ StringLiteralParser(ArrayRef<Token> StringToks,
Preprocessor &PP, bool Complain = true);
- StringLiteralParser(const Token *StringToks, unsigned NumStringToks,
+ StringLiteralParser(ArrayRef<Token> StringToks,
const SourceManager &sm, const LangOptions &features,
- const TargetInfo &target, DiagnosticsEngine *diags = 0)
+ 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, NumStringToks);
+ init(StringToks);
}
@@ -243,7 +249,7 @@ public:
}
private:
- void init(const Token *StringToks, unsigned NumStringToks);
+ void init(ArrayRef<Token> StringToks);
bool CopyStringFragment(const Token &Tok, const char *TokBegin,
StringRef Fragment);
void DiagnoseLexingError(SourceLocation Loc);
diff --git a/include/clang/Lex/MacroArgs.h b/include/clang/Lex/MacroArgs.h
index 1fd295ebfa9e..4c0120c77f04 100644
--- a/include/clang/Lex/MacroArgs.h
+++ b/include/clang/Lex/MacroArgs.h
@@ -52,9 +52,10 @@ class MacroArgs {
/// ArgCache - This is a linked list of MacroArgs objects that the
/// Preprocessor owns which we use to avoid thrashing malloc/free.
MacroArgs *ArgCache;
-
+
MacroArgs(unsigned NumToks, bool varargsElided)
- : NumUnexpArgTokens(NumToks), VarargsElided(varargsElided), ArgCache(0) {}
+ : NumUnexpArgTokens(NumToks), VarargsElided(varargsElided),
+ ArgCache(nullptr) {}
~MacroArgs() {}
public:
/// MacroArgs ctor function - Create a new MacroArgs object with the specified
diff --git a/include/clang/Lex/MacroInfo.h b/include/clang/Lex/MacroInfo.h
index 8cb370e6f833..e9a66e857dbc 100644
--- a/include/clang/Lex/MacroInfo.h
+++ b/include/clang/Lex/MacroInfo.h
@@ -21,7 +21,7 @@
#include <cassert>
namespace clang {
- class Preprocessor;
+class Preprocessor;
/// \brief Encapsulates the data about a macro definition (e.g. its tokens).
///
@@ -104,8 +104,11 @@ private:
/// \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;
+
~MacroInfo() {
- assert(ArgumentList == 0 && "Didn't call destroy before dtor!");
+ assert(!ArgumentList && "Didn't call destroy before dtor!");
}
public:
@@ -116,7 +119,7 @@ public:
/// This restores this MacroInfo to a state where it can be reused for other
/// devious purposes.
void FreeArgumentList() {
- ArgumentList = 0;
+ ArgumentList = nullptr;
NumArguments = 0;
}
@@ -176,7 +179,7 @@ public:
/// this macro.
void setArgumentList(IdentifierInfo* const *List, unsigned NumArgs,
llvm::BumpPtrAllocator &PPAllocator) {
- assert(ArgumentList == 0 && NumArguments == 0 &&
+ assert(ArgumentList == nullptr && NumArguments == 0 &&
"Argument list already set!");
if (NumArgs == 0) return;
@@ -282,6 +285,11 @@ public:
/// 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 {
@@ -291,6 +299,8 @@ public:
return 0;
}
+ void dump() const;
+
private:
unsigned getDefinitionLengthSlow(SourceManager &SM) const;
@@ -338,12 +348,6 @@ protected:
/// \brief True if the macro directive was loaded from a PCH file.
bool IsFromPCH : 1;
- /// \brief Whether the macro directive is currently "hidden".
- ///
- /// Note that this is transient state that is never serialized to the AST
- /// file.
- bool IsHidden : 1;
-
// Used by DefMacroDirective -----------------------------------------------//
/// \brief True if this macro was imported from a module.
@@ -360,10 +364,10 @@ protected:
bool IsPublic : 1;
MacroDirective(Kind K, SourceLocation Loc)
- : Previous(0), Loc(Loc), MDKind(K), IsFromPCH(false), IsHidden(false),
+ : Previous(nullptr), Loc(Loc), MDKind(K), IsFromPCH(false),
IsImported(false), IsAmbiguous(false),
IsPublic(true) {
- }
+ }
public:
Kind getKind() const { return Kind(MDKind); }
@@ -386,19 +390,13 @@ public:
void setIsFromPCH() { IsFromPCH = true; }
- /// \brief Determine whether this macro directive is hidden.
- bool isHidden() const { return IsHidden; }
-
- /// \brief Set whether this macro directive is hidden.
- void setHidden(bool Val) { IsHidden = Val; }
-
class DefInfo {
DefMacroDirective *DefDirective;
SourceLocation UndefLoc;
bool IsPublic;
public:
- DefInfo() : DefDirective(0) { }
+ DefInfo() : DefDirective(nullptr) { }
DefInfo(DefMacroDirective *DefDirective, SourceLocation UndefLoc,
bool isPublic)
@@ -418,42 +416,44 @@ public:
bool isPublic() const { return IsPublic; }
- bool isValid() const { return DefDirective != 0; }
+ bool isValid() const { return DefDirective != nullptr; }
bool isInvalid() const { return !isValid(); }
LLVM_EXPLICIT operator bool() const { return isValid(); }
- inline DefInfo getPreviousDefinition(bool AllowHidden = false);
- const DefInfo getPreviousDefinition(bool AllowHidden = false) const {
- return const_cast<DefInfo*>(this)->getPreviousDefinition(AllowHidden);
+ 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(bool AllowHidden = false);
- const DefInfo getDefinition(bool AllowHidden = false) const {
- return const_cast<MacroDirective*>(this)->getDefinition(AllowHidden);
+ DefInfo getDefinition();
+ const DefInfo getDefinition() const {
+ return const_cast<MacroDirective*>(this)->getDefinition();
}
- bool isDefined(bool AllowHidden = false) const {
- if (const DefInfo Def = getDefinition(AllowHidden))
+ bool isDefined() const {
+ if (const DefInfo Def = getDefinition())
return !Def.isUndefined();
return false;
}
- const MacroInfo *getMacroInfo(bool AllowHidden = false) const {
- return getDefinition(AllowHidden).getMacroInfo();
+ const MacroInfo *getMacroInfo() const {
+ return getDefinition().getMacroInfo();
}
- MacroInfo *getMacroInfo(bool AllowHidden = false) {
- return getDefinition(AllowHidden).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; }
};
@@ -533,15 +533,15 @@ inline SourceLocation MacroDirective::DefInfo::getLocation() const {
inline MacroInfo *MacroDirective::DefInfo::getMacroInfo() {
if (isInvalid())
- return 0;
+ return nullptr;
return DefDirective->getInfo();
}
inline MacroDirective::DefInfo
-MacroDirective::DefInfo::getPreviousDefinition(bool AllowHidden) {
- if (isInvalid() || DefDirective->getPrevious() == 0)
+MacroDirective::DefInfo::getPreviousDefinition() {
+ if (isInvalid() || DefDirective->getPrevious() == nullptr)
return DefInfo();
- return DefDirective->getPrevious()->getDefinition(AllowHidden);
+ return DefDirective->getPrevious()->getDefinition();
}
} // end namespace clang
diff --git a/include/clang/Lex/Makefile b/include/clang/Lex/Makefile
deleted file mode 100644
index 762b9a258758..000000000000
--- a/include/clang/Lex/Makefile
+++ /dev/null
@@ -1,13 +0,0 @@
-CLANG_LEVEL := ../../..
-TD_SRC_DIR = $(PROJ_SRC_DIR)/../Basic
-BUILT_SOURCES = AttrSpellings.inc
-
-TABLEGEN_INC_FILES_COMMON = 1
-
-include $(CLANG_LEVEL)/Makefile
-
-$(ObjDir)/AttrSpellings.inc.tmp : $(TD_SRC_DIR)/Attr.td $(CLANG_TBLGEN) \
- $(ObjDir)/.dir
- $(Echo) "Building Clang attribute spellings with tblgen"
- $(Verb) $(ClangTableGen) -gen-clang-attr-spelling-list -o $(call SYSPATH, $@) \
- -I $(PROJ_SRC_DIR)/../../ $<
diff --git a/include/clang/Lex/ModuleLoader.h b/include/clang/Lex/ModuleLoader.h
index 254ab36fe960..7869799c2c54 100644
--- a/include/clang/Lex/ModuleLoader.h
+++ b/include/clang/Lex/ModuleLoader.h
@@ -21,6 +21,7 @@
namespace clang {
+class GlobalModuleIndex;
class IdentifierInfo;
class Module;
@@ -53,11 +54,24 @@ public:
/// 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:
- ModuleLoader() : HadFatalFailure(false) {}
+ 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
@@ -88,6 +102,26 @@ public:
SourceLocation ImportLoc,
bool Complain) = 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;
};
diff --git a/include/clang/Lex/ModuleMap.h b/include/clang/Lex/ModuleMap.h
index 3a17157f94d5..a86a92749959 100644
--- a/include/clang/Lex/ModuleMap.h
+++ b/include/clang/Lex/ModuleMap.h
@@ -38,7 +38,7 @@ class ModuleMapParser;
class ModuleMap {
SourceManager &SourceMgr;
- IntrusiveRefCntPtr<DiagnosticsEngine> Diags;
+ DiagnosticsEngine &Diags;
const LangOptions &LangOpts;
const TargetInfo *Target;
HeaderSearch &HeaderInfo;
@@ -86,7 +86,7 @@ public:
llvm::PointerIntPair<Module *, 2, ModuleHeaderRole> Storage;
public:
- KnownHeader() : Storage(0, NormalHeader) { }
+ KnownHeader() : Storage(nullptr, NormalHeader) { }
KnownHeader(Module *M, ModuleHeaderRole Role) : Storage(M, Role) { }
/// \brief Retrieve the module the header is stored in.
@@ -102,7 +102,9 @@ public:
// \brief Whether this known header is valid (i.e., it has an
// associated module).
- LLVM_EXPLICIT operator bool() const { return Storage.getPointer() != 0; }
+ LLVM_EXPLICIT operator bool() const {
+ return Storage.getPointer() != nullptr;
+ }
};
private:
@@ -131,6 +133,10 @@ private:
/// \brief Whether the modules we infer are [system] modules.
unsigned InferSystemModules : 1;
+ /// \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;
@@ -175,6 +181,29 @@ private:
/// 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 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));
+ }
+
public:
/// \brief Construct a new module map.
///
@@ -182,13 +211,12 @@ public:
/// This source manager should be shared with the header-search mechanism,
/// since they will refer to the same headers.
///
- /// \param DC A diagnostic consumer that will be cloned for use in generating
- /// diagnostics.
+ /// \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, DiagnosticConsumer &DC,
+ ModuleMap(SourceManager &SourceMgr, DiagnosticsEngine &Diags,
const LangOptions &LangOpts, const TargetInfo *Target,
HeaderSearch &HeaderInfo);
@@ -217,12 +245,30 @@ public:
/// given header file. The KnownHeader is default constructed to indicate
/// that no module owns this header file.
KnownHeader findModuleForHeader(const FileEntry *File,
- Module *RequestingModule = NULL);
+ Module *RequestingModule = nullptr);
+
+ /// \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.
@@ -260,13 +306,17 @@ public:
/// \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 ModuleMap The module map that defines or allows the inference of
+ /// this 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,
+ std::pair<Module *, bool> findOrCreateModule(StringRef Name, Module *Parent,
+ const FileEntry *ModuleMap,
bool IsFramework,
bool IsExplicit);
diff --git a/include/clang/Lex/MultipleIncludeOpt.h b/include/clang/Lex/MultipleIncludeOpt.h
index b532bf82f049..e3c6de555b35 100644
--- a/include/clang/Lex/MultipleIncludeOpt.h
+++ b/include/clang/Lex/MultipleIncludeOpt.h
@@ -60,8 +60,8 @@ public:
ReadAnyTokens = false;
ImmediatelyAfterTopLevelIfndef = false;
DidMacroExpansion = false;
- TheMacro = 0;
- DefinedMacro = 0;
+ TheMacro = nullptr;
+ DefinedMacro = nullptr;
}
SourceLocation GetMacroLocation() const {
@@ -88,8 +88,8 @@ public:
// below can never "accept".
ReadAnyTokens = true;
ImmediatelyAfterTopLevelIfndef = false;
- DefinedMacro = 0;
- TheMacro = 0;
+ DefinedMacro = nullptr;
+ TheMacro = nullptr;
}
/// getHasReadAnyTokensVal - This is used for the \#ifndef hande-shake at the
@@ -166,7 +166,7 @@ public:
// macro if it's valid (if it isn't, it will be null).
if (!ReadAnyTokens)
return TheMacro;
- return 0;
+ return nullptr;
}
/// \brief If the ControllingMacro is followed by a macro definition, return
diff --git a/include/clang/Lex/PPCallbacks.h b/include/clang/Lex/PPCallbacks.h
index 0e112182794d..7f1ea34a460e 100644
--- a/include/clang/Lex/PPCallbacks.h
+++ b/include/clang/Lex/PPCallbacks.h
@@ -214,8 +214,7 @@ public:
/// \brief Callback invoked when a \#pragma gcc dianostic directive is read.
virtual void PragmaDiagnostic(SourceLocation Loc, StringRef Namespace,
- diag::Mapping mapping, StringRef Str) {
- }
+ diag::Severity mapping, StringRef Str) {}
/// \brief Called when an OpenCL extension is either disabled or
/// enabled with a pragma.
@@ -267,6 +266,10 @@ public:
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.
@@ -274,7 +277,7 @@ public:
///
// FIXME: better to pass in a list (or tree!) of Tokens.
virtual void If(SourceLocation Loc, SourceRange ConditionRange,
- bool ConditionValue) {
+ ConditionValueKind ConditionValue) {
}
/// \brief Hook called whenever an \#elif is seen.
@@ -284,7 +287,7 @@ public:
/// \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,
- bool ConditionValue, SourceLocation IfLoc) {
+ ConditionValueKind ConditionValue, SourceLocation IfLoc) {
}
/// \brief Hook called whenever an \#ifdef is seen.
@@ -329,35 +332,31 @@ public:
delete First;
}
- virtual void FileChanged(SourceLocation Loc, FileChangeReason Reason,
- SrcMgr::CharacteristicKind FileType,
- FileID PrevFID) {
+ void FileChanged(SourceLocation Loc, FileChangeReason Reason,
+ SrcMgr::CharacteristicKind FileType,
+ FileID PrevFID) override {
First->FileChanged(Loc, Reason, FileType, PrevFID);
Second->FileChanged(Loc, Reason, FileType, PrevFID);
}
- virtual void FileSkipped(const FileEntry &ParentFile,
- const Token &FilenameTok,
- SrcMgr::CharacteristicKind FileType) {
+ void FileSkipped(const FileEntry &ParentFile,
+ const Token &FilenameTok,
+ SrcMgr::CharacteristicKind FileType) override {
First->FileSkipped(ParentFile, FilenameTok, FileType);
Second->FileSkipped(ParentFile, FilenameTok, FileType);
}
- virtual bool FileNotFound(StringRef FileName,
- SmallVectorImpl<char> &RecoveryPath) {
+ bool FileNotFound(StringRef FileName,
+ SmallVectorImpl<char> &RecoveryPath) override {
return First->FileNotFound(FileName, RecoveryPath) ||
Second->FileNotFound(FileName, RecoveryPath);
}
- virtual void InclusionDirective(SourceLocation HashLoc,
- const Token &IncludeTok,
- StringRef FileName,
- bool IsAngled,
- CharSourceRange FilenameRange,
- const FileEntry *File,
- StringRef SearchPath,
- StringRef RelativePath,
- const Module *Imported) {
+ 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);
@@ -366,147 +365,142 @@ public:
Imported);
}
- virtual void moduleImport(SourceLocation ImportLoc,
- ModuleIdPath Path,
- const Module *Imported) {
+ void moduleImport(SourceLocation ImportLoc, ModuleIdPath Path,
+ const Module *Imported) override {
First->moduleImport(ImportLoc, Path, Imported);
Second->moduleImport(ImportLoc, Path, Imported);
}
- virtual void EndOfMainFile() {
+ void EndOfMainFile() override {
First->EndOfMainFile();
Second->EndOfMainFile();
}
- virtual void Ident(SourceLocation Loc, const std::string &str) {
+ void Ident(SourceLocation Loc, const std::string &str) override {
First->Ident(Loc, str);
Second->Ident(Loc, str);
}
- virtual void PragmaComment(SourceLocation Loc, const IdentifierInfo *Kind,
- const std::string &Str) {
+ void PragmaComment(SourceLocation Loc, const IdentifierInfo *Kind,
+ const std::string &Str) override {
First->PragmaComment(Loc, Kind, Str);
Second->PragmaComment(Loc, Kind, Str);
}
- virtual void PragmaDetectMismatch(SourceLocation Loc,
- const std::string &Name,
- const std::string &Value) {
+ void PragmaDetectMismatch(SourceLocation Loc, const std::string &Name,
+ const std::string &Value) override {
First->PragmaDetectMismatch(Loc, Name, Value);
Second->PragmaDetectMismatch(Loc, Name, Value);
}
- virtual void PragmaMessage(SourceLocation Loc, StringRef Namespace,
- PragmaMessageKind Kind, StringRef Str) {
+ void PragmaMessage(SourceLocation Loc, StringRef Namespace,
+ PragmaMessageKind Kind, StringRef Str) override {
First->PragmaMessage(Loc, Namespace, Kind, Str);
Second->PragmaMessage(Loc, Namespace, Kind, Str);
}
- virtual void PragmaDiagnosticPush(SourceLocation Loc,
- StringRef Namespace) {
+ void PragmaDiagnosticPush(SourceLocation Loc, StringRef Namespace) override {
First->PragmaDiagnosticPush(Loc, Namespace);
Second->PragmaDiagnosticPush(Loc, Namespace);
}
- virtual void PragmaDiagnosticPop(SourceLocation Loc,
- StringRef Namespace) {
+ void PragmaDiagnosticPop(SourceLocation Loc, StringRef Namespace) override {
First->PragmaDiagnosticPop(Loc, Namespace);
Second->PragmaDiagnosticPop(Loc, Namespace);
}
- virtual void PragmaDiagnostic(SourceLocation Loc, StringRef Namespace,
- diag::Mapping mapping, StringRef Str) {
+ void PragmaDiagnostic(SourceLocation Loc, StringRef Namespace,
+ diag::Severity mapping, StringRef Str) override {
First->PragmaDiagnostic(Loc, Namespace, mapping, Str);
Second->PragmaDiagnostic(Loc, Namespace, mapping, Str);
}
- virtual void PragmaOpenCLExtension(SourceLocation NameLoc,
- const IdentifierInfo *Name,
- SourceLocation StateLoc, unsigned State) {
+ void PragmaOpenCLExtension(SourceLocation NameLoc, const IdentifierInfo *Name,
+ SourceLocation StateLoc, unsigned State) override {
First->PragmaOpenCLExtension(NameLoc, Name, StateLoc, State);
Second->PragmaOpenCLExtension(NameLoc, Name, StateLoc, State);
}
- virtual void PragmaWarning(SourceLocation Loc, StringRef WarningSpec,
- ArrayRef<int> Ids) {
+ void PragmaWarning(SourceLocation Loc, StringRef WarningSpec,
+ ArrayRef<int> Ids) override {
First->PragmaWarning(Loc, WarningSpec, Ids);
Second->PragmaWarning(Loc, WarningSpec, Ids);
}
- virtual void PragmaWarningPush(SourceLocation Loc, int Level) {
+ void PragmaWarningPush(SourceLocation Loc, int Level) override {
First->PragmaWarningPush(Loc, Level);
Second->PragmaWarningPush(Loc, Level);
}
- virtual void PragmaWarningPop(SourceLocation Loc) {
+ void PragmaWarningPop(SourceLocation Loc) override {
First->PragmaWarningPop(Loc);
Second->PragmaWarningPop(Loc);
}
- virtual void MacroExpands(const Token &MacroNameTok, const MacroDirective *MD,
- SourceRange Range, const MacroArgs *Args) {
+ void MacroExpands(const Token &MacroNameTok, const MacroDirective *MD,
+ SourceRange Range, const MacroArgs *Args) override {
First->MacroExpands(MacroNameTok, MD, Range, Args);
Second->MacroExpands(MacroNameTok, MD, Range, Args);
}
- virtual void MacroDefined(const Token &MacroNameTok, const MacroDirective *MD) {
+ void MacroDefined(const Token &MacroNameTok, const MacroDirective *MD) override {
First->MacroDefined(MacroNameTok, MD);
Second->MacroDefined(MacroNameTok, MD);
}
- virtual void MacroUndefined(const Token &MacroNameTok,
- const MacroDirective *MD) {
+ void MacroUndefined(const Token &MacroNameTok,
+ const MacroDirective *MD) override {
First->MacroUndefined(MacroNameTok, MD);
Second->MacroUndefined(MacroNameTok, MD);
}
- virtual void Defined(const Token &MacroNameTok, const MacroDirective *MD,
- SourceRange Range) {
+ void Defined(const Token &MacroNameTok, const MacroDirective *MD,
+ SourceRange Range) override {
First->Defined(MacroNameTok, MD, Range);
Second->Defined(MacroNameTok, MD, Range);
}
- virtual void SourceRangeSkipped(SourceRange Range) {
+ void SourceRangeSkipped(SourceRange Range) override {
First->SourceRangeSkipped(Range);
Second->SourceRangeSkipped(Range);
}
/// \brief Hook called whenever an \#if is seen.
- virtual void If(SourceLocation Loc, SourceRange ConditionRange,
- bool ConditionValue) {
+ 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.
- virtual void Elif(SourceLocation Loc, SourceRange ConditionRange,
- bool ConditionValue, SourceLocation IfLoc) {
+ 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.
- virtual void Ifdef(SourceLocation Loc, const Token &MacroNameTok,
- const MacroDirective *MD) {
+ void Ifdef(SourceLocation Loc, const Token &MacroNameTok,
+ const MacroDirective *MD) override {
First->Ifdef(Loc, MacroNameTok, MD);
Second->Ifdef(Loc, MacroNameTok, MD);
}
/// \brief Hook called whenever an \#ifndef is seen.
- virtual void Ifndef(SourceLocation Loc, const Token &MacroNameTok,
- const MacroDirective *MD) {
+ void Ifndef(SourceLocation Loc, const Token &MacroNameTok,
+ const MacroDirective *MD) override {
First->Ifndef(Loc, MacroNameTok, MD);
Second->Ifndef(Loc, MacroNameTok, MD);
}
/// \brief Hook called whenever an \#else is seen.
- virtual void Else(SourceLocation Loc, SourceLocation IfLoc) {
+ void Else(SourceLocation Loc, SourceLocation IfLoc) override {
First->Else(Loc, IfLoc);
Second->Else(Loc, IfLoc);
}
/// \brief Hook called whenever an \#endif is seen.
- virtual void Endif(SourceLocation Loc, SourceLocation IfLoc) {
+ void Endif(SourceLocation Loc, SourceLocation IfLoc) override {
First->Endif(Loc, IfLoc);
Second->Endif(Loc, IfLoc);
}
diff --git a/include/clang/Lex/PPConditionalDirectiveRecord.h b/include/clang/Lex/PPConditionalDirectiveRecord.h
index 54a132d586d1..00d2d5797359 100644
--- a/include/clang/Lex/PPConditionalDirectiveRecord.h
+++ b/include/clang/Lex/PPConditionalDirectiveRecord.h
@@ -86,16 +86,16 @@ public:
SourceLocation findConditionalDirectiveRegionLoc(SourceLocation Loc) const;
private:
- virtual void If(SourceLocation Loc, SourceRange ConditionRange,
- bool ConditionValue);
- virtual void Elif(SourceLocation Loc, SourceRange ConditionRange,
- bool ConditionValue, SourceLocation IfLoc);
- virtual void Ifdef(SourceLocation Loc, const Token &MacroNameTok,
- const MacroDirective *MD);
- virtual void Ifndef(SourceLocation Loc, const Token &MacroNameTok,
- const MacroDirective *MD);
- virtual void Else(SourceLocation Loc, SourceLocation IfLoc);
- virtual void Endif(SourceLocation Loc, SourceLocation IfLoc);
+ 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 MacroDirective *MD) override;
+ void Ifndef(SourceLocation Loc, const Token &MacroNameTok,
+ const MacroDirective *MD) override;
+ void Else(SourceLocation Loc, SourceLocation IfLoc) override;
+ void Endif(SourceLocation Loc, SourceLocation IfLoc) override;
};
} // end namespace clang
diff --git a/include/clang/Lex/PTHLexer.h b/include/clang/Lex/PTHLexer.h
index d748bc1f7dff..2352ccea1853 100644
--- a/include/clang/Lex/PTHLexer.h
+++ b/include/clang/Lex/PTHLexer.h
@@ -90,11 +90,11 @@ public:
/// IndirectLex - An indirect call to 'Lex' that can be invoked via
/// the PreprocessorLexer interface.
- void IndirectLex(Token &Result) { Lex(Result); }
+ void IndirectLex(Token &Result) override { Lex(Result); }
/// getSourceLocation - Return a source location for the token in
/// the current file.
- SourceLocation getSourceLocation();
+ SourceLocation getSourceLocation() override;
/// SkipBlock - Used by Preprocessor to skip the current conditional block.
bool SkipBlock();
diff --git a/include/clang/Lex/PTHManager.h b/include/clang/Lex/PTHManager.h
index fad0806ca347..11b5ceaad1de 100644
--- a/include/clang/Lex/PTHManager.h
+++ b/include/clang/Lex/PTHManager.h
@@ -114,7 +114,7 @@ public:
/// 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);
+ 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.
diff --git a/include/clang/Lex/Pragma.h b/include/clang/Lex/Pragma.h
index 087448fbc5ff..4a695a0e901c 100644
--- a/include/clang/Lex/Pragma.h
+++ b/include/clang/Lex/Pragma.h
@@ -69,7 +69,7 @@ public:
/// getIfNamespace - If this is a namespace, return it. This is equivalent to
/// using a dynamic_cast, but doesn't require RTTI.
- virtual PragmaNamespace *getIfNamespace() { return 0; }
+ virtual PragmaNamespace *getIfNamespace() { return nullptr; }
};
/// EmptyPragmaHandler - A pragma handler which takes no action, which can be
@@ -78,8 +78,8 @@ class EmptyPragmaHandler : public PragmaHandler {
public:
EmptyPragmaHandler();
- virtual void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
- Token &FirstToken);
+ void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
+ Token &FirstToken) override;
};
/// PragmaNamespace - This PragmaHandler subdivides the namespace of pragmas,
@@ -114,10 +114,10 @@ public:
return Handlers.empty();
}
- virtual void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
- Token &FirstToken);
+ void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
+ Token &FirstToken) override;
- virtual PragmaNamespace *getIfNamespace() { return this; }
+ PragmaNamespace *getIfNamespace() override { return this; }
};
diff --git a/include/clang/Lex/PreprocessingRecord.h b/include/clang/Lex/PreprocessingRecord.h
index 2584340f6ec7..4609fe3c68f8 100644
--- a/include/clang/Lex/PreprocessingRecord.h
+++ b/include/clang/Lex/PreprocessingRecord.h
@@ -304,6 +304,9 @@ namespace clang {
/// 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
@@ -400,7 +403,7 @@ namespace clang {
typedef std::random_access_iterator_tag iterator_category;
typedef int difference_type;
- iterator() : Self(0), Position(0) { }
+ iterator() : Self(nullptr), Position(0) { }
iterator(PreprocessingRecord *Self, int Position)
: Self(Self), Position(Position) { }
@@ -556,28 +559,32 @@ namespace clang {
/// \brief Retrieve the macro definition that corresponds to the given
/// \c MacroInfo.
MacroDefinition *findMacroDefinition(const MacroInfo *MI);
+
+ /// \brief Retrieve all ranges that got skipped while preprocessing.
+ const std::vector<SourceRange> &getSkippedRanges() const {
+ return SkippedRanges;
+ }
private:
- virtual void MacroExpands(const Token &Id, const MacroDirective *MD,
- SourceRange Range, const MacroArgs *Args);
- virtual void MacroDefined(const Token &Id, const MacroDirective *MD);
- virtual void MacroUndefined(const Token &Id, const MacroDirective *MD);
- virtual void InclusionDirective(SourceLocation HashLoc,
- const Token &IncludeTok,
- StringRef FileName,
- bool IsAngled,
- CharSourceRange FilenameRange,
- const FileEntry *File,
- StringRef SearchPath,
- StringRef RelativePath,
- const Module *Imported);
- virtual void Ifdef(SourceLocation Loc, const Token &MacroNameTok,
- const MacroDirective *MD);
- virtual void Ifndef(SourceLocation Loc, const Token &MacroNameTok,
- const MacroDirective *MD);
+ void MacroExpands(const Token &Id, const MacroDirective *MD,
+ SourceRange Range, const MacroArgs *Args) override;
+ void MacroDefined(const Token &Id, const MacroDirective *MD) override;
+ void MacroUndefined(const Token &Id, const MacroDirective *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 MacroDirective *MD) override;
+ void Ifndef(SourceLocation Loc, const Token &MacroNameTok,
+ const MacroDirective *MD) override;
/// \brief Hook called whenever the 'defined' operator is seen.
- virtual void Defined(const Token &MacroNameTok, const MacroDirective *MD,
- SourceRange Range);
+ void Defined(const Token &MacroNameTok, const MacroDirective *MD,
+ SourceRange Range) override;
+
+ void SourceRangeSkipped(SourceRange Range) override;
void addMacroExpansion(const Token &Id, const MacroInfo *MI,
SourceRange Range);
diff --git a/include/clang/Lex/Preprocessor.h b/include/clang/Lex/Preprocessor.h
index 223fd470eca1..d4b4ba246961 100644
--- a/include/clang/Lex/Preprocessor.h
+++ b/include/clang/Lex/Preprocessor.h
@@ -6,9 +6,10 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
-//
-// This file defines the Preprocessor interface.
-//
+///
+/// \file
+/// \brief Defines the clang::Preprocessor interface.
+///
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_LEX_PREPROCESSOR_H
@@ -28,10 +29,10 @@
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/IntrusiveRefCntPtr.h"
-#include "llvm/ADT/OwningPtr.h"
#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/Support/Allocator.h"
+#include <memory>
#include <vector>
namespace llvm {
@@ -64,7 +65,7 @@ class TokenValue {
IdentifierInfo *II;
public:
- TokenValue(tok::TokenKind Kind) : Kind(Kind), II(0) {
+ 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 *)");
@@ -78,11 +79,12 @@ public:
}
};
-/// Preprocessor - This object engages in a tight little dance with the lexer to
-/// efficiently preprocess tokens. Lexers know only about tokens within a
-/// single source file, and don't know anything about preprocessor-level issues
-/// like the \#include stack, token expansion, etc.
+/// \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;
@@ -98,12 +100,12 @@ class Preprocessor : public RefCountedBase<Preprocessor> {
ExternalPreprocessorSource *ExternalSource;
- /// PTH - An optional PTHManager object used for getting tokens from
- /// a token cache rather than lexing the original source file.
- OwningPtr<PTHManager> PTH;
+ /// An optional PTHManager object used for getting tokens from
+ /// a token cache rather than lexing the original source file.
+ std::unique_ptr<PTHManager> PTH;
- /// BP - A BumpPtrAllocator object used to quickly allocate and release
- /// objects internal to the Preprocessor.
+ /// A BumpPtrAllocator object used to quickly allocate and release
+ /// objects internal to the Preprocessor.
llvm::BumpPtrAllocator BP;
/// Identifiers for builtin macros and other builtins.
@@ -114,6 +116,7 @@ class Preprocessor : public RefCountedBase<Preprocessor> {
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
@@ -122,6 +125,7 @@ class Preprocessor : public RefCountedBase<Preprocessor> {
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__
@@ -129,7 +133,7 @@ class Preprocessor : public RefCountedBase<Preprocessor> {
unsigned CounterValue; // Next __COUNTER__ value.
enum {
- /// MaxIncludeStackDepth - Maximum depth of \#includes.
+ /// \brief Maximum depth of \#includes.
MaxAllowedIncludeStackDepth = 200
};
@@ -144,12 +148,11 @@ class Preprocessor : public RefCountedBase<Preprocessor> {
/// Whether the preprocessor owns the header search object.
bool OwnsHeaderSearch : 1;
- /// DisableMacroExpansion - True if macro expansion is disabled.
+ /// True if macro expansion is disabled.
bool DisableMacroExpansion : 1;
- /// MacroExpansionInDirectivesOverride - Temporarily disables
- /// DisableMacroExpansion (i.e. enables expansion) when parsing preprocessor
- /// directives.
+ /// Temporarily disables DisableMacroExpansion (i.e. enables expansion)
+ /// when parsing preprocessor directives.
bool MacroExpansionInDirectivesOverride : 1;
class ResetMacroExpansionHelper;
@@ -169,23 +172,25 @@ class Preprocessor : public RefCountedBase<Preprocessor> {
/// \brief True if we are pre-expanding macro arguments.
bool InMacroArgPreExpansion;
- /// Identifiers - This is mapping/lookup information for all identifiers in
+ /// \brief Mapping/lookup information for all identifiers in
/// the program, including program keywords.
mutable IdentifierTable Identifiers;
- /// Selectors - This table contains all the selectors in the program. Unlike
- /// IdentifierTable above, this table *isn't* populated by the preprocessor.
- /// It is declared/expanded here because it's role/lifetime is
- /// conceptually similar the IdentifierTable. In addition, the current control
- /// flow (in clang::ParseAST()), make it convenient to put here.
+ /// \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;
- /// BuiltinInfo - Information about builtins.
+ /// \brief Information about builtins.
Builtin::Context BuiltinInfo;
- /// PragmaHandlers - This tracks all of the pragmas that the client registered
+ /// \brief Tracks all of the pragmas that the client registered
/// with this preprocessor.
PragmaNamespace *PragmaHandlers;
@@ -197,6 +202,9 @@ class Preprocessor : public RefCountedBase<Preprocessor> {
/// 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;
@@ -216,7 +224,7 @@ class Preprocessor : public RefCountedBase<Preprocessor> {
/// for preprocessing.
SourceLocation CodeCompletionFileLoc;
- /// \brief The source location of the 'import' contextual keyword we just
+ /// \brief The source location of the \c import contextual keyword we just
/// lexed, if any.
SourceLocation ModuleImportLoc;
@@ -226,46 +234,53 @@ class Preprocessor : public RefCountedBase<Preprocessor> {
/// \brief Whether the last token we lexed was an '@'.
bool LastTokenWasAt;
- /// \brief Whether the module import expectes an identifier next. Otherwise,
+ /// \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.
+ /// \#pragma clang arc_cf_code_audited begin.
SourceLocation PragmaARCCFCodeAuditedLoc;
/// \brief True if we hit the code-completion point.
bool CodeCompletionReached;
/// \brief The number of bytes that we will initially skip when entering the
- /// main file, which is used when loading a precompiled preamble, along
- /// with a flag that indicates whether skipping this number of bytes will
- /// place the lexer at the start of a line.
+ /// 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<unsigned, bool> SkipMainFilePreamble;
- /// CurLexer - This is the current top of the stack that we're lexing from if
+ /// \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.
- OwningPtr<Lexer> CurLexer;
+ ///
+ /// Only one of CurLexer, CurPTHLexer, or CurTokenLexer will be non-null.
+ std::unique_ptr<Lexer> CurLexer;
- /// CurPTHLexer - This is the current top of stack that we're lexing from if
- /// not expanding from a macro and we are lexing from a PTH cache.
- /// Only one of CurLexer, CurPTHLexer, or CurTokenLexer will be non-null.
- OwningPtr<PTHLexer> CurPTHLexer;
+ /// \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;
- /// CurPPLexer - This is the current top of the stack what we're lexing from
- /// if not expanding a macro. This is an alias for either CurLexer or
- /// CurPTHLexer.
+ /// \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;
- /// CurLookup - The DirectoryLookup structure used to find the current
- /// FileEntry, if CurLexer is non-null and if applicable. This allows us to
- /// implement \#include_next and find directory-specific properties.
+ /// \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;
- /// CurTokenLexer - This is the current macro we are expanding, if we are
- /// expanding a macro. One of CurLexer and CurTokenLexer must be null.
- OwningPtr<TokenLexer> CurTokenLexer;
+ /// \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 {
@@ -276,26 +291,48 @@ class Preprocessor : public RefCountedBase<Preprocessor> {
CLK_LexAfterModuleImport
} CurLexerKind;
- /// IncludeMacroStack - This keeps track of the stack of files currently
+ /// \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;
- Lexer *TheLexer;
- PTHLexer *ThePTHLexer;
- PreprocessorLexer *ThePPLexer;
- TokenLexer *TheTokenLexer;
- const DirectoryLookup *TheDirLookup;
-
- IncludeStackInfo(enum CurLexerKind K, Lexer *L, PTHLexer* P,
- PreprocessorLexer* PPL,
- TokenLexer* TL, const DirectoryLookup *D)
- : CurLexerKind(K), TheLexer(L), ThePTHLexer(P), ThePPLexer(PPL),
- TheTokenLexer(TL), TheDirLookup(D) {}
+ 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;
- /// Callbacks - These are actions invoked when some preprocessor activity is
+ /// \brief Actions invoked when some preprocessor activity is
/// encountered (e.g. a file is \#included, etc).
PPCallbacks *Callbacks;
@@ -308,14 +345,16 @@ class Preprocessor : public RefCountedBase<Preprocessor> {
};
SmallVector<MacroExpandsInfo, 2> DelayedMacroExpandsCallbacks;
- /// Macros - For each IdentifierInfo that was associated with a macro, we
+ /// 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).
llvm::DenseMap<const IdentifierInfo*, MacroDirective*> Macros;
friend class ASTReader;
/// \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 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
@@ -324,35 +363,36 @@ class Preprocessor : public RefCountedBase<Preprocessor> {
typedef llvm::SmallPtrSet<SourceLocation, 32> WarnUnusedMacroLocsTy;
WarnUnusedMacroLocsTy WarnUnusedMacroLocs;
- /// MacroArgCache - This is a "freelist" of MacroArg objects that can be
+ /// \brief A "freelist" of MacroArg objects that can be
/// reused for quick allocation.
MacroArgs *MacroArgCache;
friend class MacroArgs;
- /// PragmaPushMacroInfo - For each IdentifierInfo used in a #pragma
- /// push_macro directive, we keep a MacroInfo stack used to restore
- /// previous macro value.
+ /// 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, NumIncluded, NumDefined, NumUndefined, NumPragma;
+ unsigned NumDirectives, NumDefined, NumUndefined, NumPragma;
unsigned NumIf, NumElse, NumEndif;
unsigned NumEnteredSourceFiles, MaxIncludeStackDepth;
unsigned NumMacroExpanded, NumFnMacroExpanded, NumBuiltinMacroExpanded;
unsigned NumFastMacroExpanded, NumTokenPaste, NumFastTokenPaste;
unsigned NumSkipped;
- /// Predefines - This string is the predefined macros that preprocessor
- /// should use from the command line etc.
+ /// \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;
- /// TokenLexerCache - Cache macro expanders to reduce malloc traffic.
+ /// \{
+ /// \brief Cache of macro expanders to reduce malloc traffic.
enum { TokenLexerCacheSize = 8 };
unsigned NumCachedTokenLexers;
TokenLexer *TokenLexerCache[TokenLexerCacheSize];
+ /// \}
/// \brief Keeps macro expanded tokens for TokenLexers.
//
@@ -372,17 +412,20 @@ class Preprocessor : public RefCountedBase<Preprocessor> {
private: // Cached tokens state.
typedef SmallVector<Token, 1> CachedTokensTy;
- /// CachedTokens - Cached tokens are stored here when we do backtracking or
+ /// \brief Cached tokens are stored here when we do backtracking or
/// lookahead. They are "lexed" by the CachingLex() method.
CachedTokensTy CachedTokens;
- /// CachedLexPos - The position of the cached token that CachingLex() should
- /// "lex" next. If it points beyond the CachedTokens vector, it means that
- /// a normal Lex() should be invoked.
+ /// \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;
- /// BacktrackPositions - Stack of backtrack positions, allowing nested
- /// backtracks. The EnableBacktrackAtThisPos() method pushes a position to
+ /// \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;
@@ -397,7 +440,7 @@ private: // Cached tokens state.
/// of that list.
MacroInfoChain *MIChainHead;
- /// MICache - A "freelist" of MacroInfo objects that can be reused for quick
+ /// A "freelist" of MacroInfo objects that can be reused for quick
/// allocation.
MacroInfoChain *MICache;
@@ -412,20 +455,18 @@ private: // Cached tokens state.
public:
Preprocessor(IntrusiveRefCntPtr<PreprocessorOptions> PPOpts,
DiagnosticsEngine &diags, LangOptions &opts,
- const TargetInfo *target,
SourceManager &SM, HeaderSearch &Headers,
ModuleLoader &TheModuleLoader,
- IdentifierInfoLookup *IILookup = 0,
+ IdentifierInfoLookup *IILookup = nullptr,
bool OwnsHeaderSearch = false,
- bool DelayInitialization = false,
- bool IncrProcessing = false);
+ TranslationUnitKind TUKind = TU_Complete);
~Preprocessor();
- /// \brief Initialize the preprocessor, if the constructor did not already
- /// perform the initialization.
+ /// \brief Initialize the preprocessor using information about the target.
///
- /// \param Target Information about the target.
+ /// \param Target is owned by the caller and must remain valid for the
+ /// lifetime of the preprocessor.
void Initialize(const TargetInfo &Target);
/// \brief Retrieve the preprocessor options used to initialize this
@@ -470,8 +511,7 @@ public:
return ParsingIfOrElifDirective;
}
- /// SetCommentRetentionState - Control whether or not the preprocessor retains
- /// comments in output.
+ /// \brief Control whether the preprocessor retains comments in output.
void SetCommentRetentionState(bool KeepComments, bool KeepMacroComments) {
this->KeepComments = KeepComments | KeepMacroComments;
this->KeepMacroComments = KeepMacroComments;
@@ -500,26 +540,29 @@ public:
/// false if it is producing tokens to be consumed by Parse and Sema.
bool isPreprocessedOutput() const { return PreprocessedOutput; }
- /// isCurrentLexer - Return true if we are lexing directly from the specified
- /// lexer.
+ /// \brief Return true if we are lexing directly from the specified lexer.
bool isCurrentLexer(const PreprocessorLexer *L) const {
return CurPPLexer == L;
}
- /// getCurrentLexer - Return the current lexer being lexed from. Note
- /// that this ignores any potentially active macro expansions and _Pragma
+ /// \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; }
- /// getCurrentFileLexer - Return the current file lexer being lexed from.
+ /// \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 Returns the file ID for the preprocessor predefines.
+ /// \brief Returns the FileID for the preprocessor predefines.
FileID getPredefinesFileID() const { return PredefinesFileID; }
- /// getPPCallbacks/addPPCallbacks - Accessors for preprocessor callbacks.
+ /// \{
+ /// \brief Accessors for preprocessor callbacks.
+ ///
/// Note that this class takes ownership of any PPCallbacks object given to
/// it.
PPCallbacks *getPPCallbacks() const { return Callbacks; }
@@ -528,12 +571,13 @@ public:
C = new PPChainedCallbacks(C, Callbacks);
Callbacks = C;
}
+ /// \}
/// \brief Given an identifier, return its latest MacroDirective if it is
- // \#defined or null if it isn't \#define'd.
+ /// \#defined or null if it isn't \#define'd.
MacroDirective *getMacroDirective(IdentifierInfo *II) const {
if (!II->hasMacroDefinition())
- return 0;
+ return nullptr;
MacroDirective *MD = getMacroDirectiveHistory(II);
assert(MD->isDefined() && "Macro is undefined!");
@@ -547,13 +591,14 @@ public:
MacroInfo *getMacroInfo(IdentifierInfo *II) {
if (MacroDirective *MD = getMacroDirective(II))
return MD->getMacroInfo();
- return 0;
+ return nullptr;
}
/// \brief Given an identifier, return the (probably #undef'd) MacroInfo
- /// representing the most recent macro definition. One can iterate over all
- /// previous macro definitions from it. This method should only be called for
- /// identifiers that hadMacroDefinition().
+ /// representing the most recent macro definition.
+ ///
+ /// One can iterate over all previous macro definitions from the most recent
+ /// one. This should only be called for identifiers that hadMacroDefinition().
MacroDirective *getMacroDirectiveHistory(const IdentifierInfo *II) const;
/// \brief Add a directive to the macro directive history for this identifier.
@@ -571,14 +616,15 @@ public:
/// \brief Set a MacroDirective that was loaded from a PCH file.
void setLoadedMacroDirective(IdentifierInfo *II, MacroDirective *MD);
- /// macro_iterator/macro_begin/macro_end - This allows you to walk the macro
- /// history table. Currently defined macros have
+ /// \{
+ /// 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 llvm::DenseMap<const IdentifierInfo *,
MacroDirective*>::const_iterator macro_iterator;
macro_iterator macro_begin(bool IncludeExternalMacros = true) const;
macro_iterator macro_end(bool IncludeExternalMacros = true) const;
+ /// \}
/// \brief Return the name of the macro defined before \p Loc that has
/// spelling \p Tokens. If there are multiple macros with same spelling,
@@ -587,8 +633,9 @@ public:
ArrayRef<TokenValue> Tokens) const;
const std::string &getPredefines() const { return Predefines; }
- /// setPredefines - Set the predefines for this Preprocessor. These
- /// predefines are automatically injected when parsing the main file.
+ /// \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(const std::string &P) { Predefines = P; }
@@ -598,23 +645,28 @@ public:
return &Identifiers.get(Name);
}
- /// AddPragmaHandler - Add the specified pragma handler to the preprocessor.
- /// If 'Namespace' is non-null, then it is a token required to exist on the
+ /// \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);
}
- /// RemovePragmaHandler - Remove the specific pragma handler from
- /// the 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.
+ /// \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);
@@ -635,7 +687,7 @@ public:
/// \brief Clear out the code completion handler.
void clearCodeCompletionHandler() {
- CodeComplete = 0;
+ CodeComplete = nullptr;
}
/// \brief Hook used by the lexer to invoke the "natural language" code
@@ -650,51 +702,51 @@ public:
/// all macro expansions, macro definitions, etc.
void createPreprocessingRecord();
- /// EnterMainSourceFile - Enter the specified FileID as the main source file,
+ /// \brief Enter the specified FileID as the main source file,
/// which implicitly adds the builtin defines etc.
void EnterMainSourceFile();
- /// EndSourceFile - Inform the preprocessor callbacks that processing is
- /// complete.
+ /// \brief Inform the preprocessor callbacks that processing is complete.
void EndSourceFile();
- /// EnterSourceFile - Add a source file to the top of the include stack and
- /// start lexing tokens from it instead of the current buffer. Emit an error
- /// and don't enter the file on error.
- void EnterSourceFile(FileID CurFileID, const DirectoryLookup *Dir,
+ /// \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);
- /// EnterMacro - Add a Macro to the top of the include stack and start lexing
- /// tokens from it instead of the current buffer. Args specifies the
- /// tokens input to a function-like macro.
+ /// \brief Add a Macro to the top of the include stack and start lexing
+ /// tokens from it instead of the current buffer.
///
- /// ILEnd specifies the location of the ')' for a function-like macro or the
- /// identifier for an object-like macro.
+ /// \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);
- /// EnterTokenStream - Add a "macro" context to the top of the include stack,
+ /// \brief Add a "macro" context to the top of the include stack,
/// which will cause the lexer to start returning the specified tokens.
///
- /// If DisableMacroExpansion is true, tokens lexed from the token stream will
- /// not be subject to further macro expansion. Otherwise, these tokens will
- /// be re-macro-expanded when/if expansion is enabled.
- ///
- /// If OwnsTokens is false, this method assumes that the specified stream of
- /// tokens has a permanent owner somewhere, so they do not need to be copied.
- /// If it is true, it assumes the array of tokens is allocated with new[] and
- /// must be freed.
+ /// 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);
- /// RemoveTopOfLexerStack - Pop the current lexer/macro exp off the top of the
- /// lexer stack. This should only be used in situations where the current
- /// state of the top-of-stack lexer is known.
+ /// \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();
- /// EnableBacktrackAtThisPos - From the point that this method is called, and
- /// until CommitBacktrackedTokens() or Backtrack() is called, the Preprocessor
+ /// 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.
///
@@ -708,18 +760,18 @@ public:
///
void EnableBacktrackAtThisPos();
- /// CommitBacktrackedTokens - Disable the last EnableBacktrackAtThisPos call.
+ /// \brief Disable the last EnableBacktrackAtThisPos call.
void CommitBacktrackedTokens();
- /// Backtrack - Make Preprocessor re-lex the tokens that were lexed since
+ /// \brief Make Preprocessor re-lex the tokens that were lexed since
/// EnableBacktrackAtThisPos() was previously called.
void Backtrack();
- /// isBacktrackEnabled - True if EnableBacktrackAtThisPos() was called and
+ /// \brief True if EnableBacktrackAtThisPos() was called and
/// caching of tokens is on.
bool isBacktrackEnabled() const { return !BacktrackPositions.empty(); }
- /// Lex - Lex the next token for this preprocessor.
+ /// \brief Lex the next token for this preprocessor.
void Lex(Token &Result);
void LexAfterModuleImport(Token &Result);
@@ -743,17 +795,18 @@ public:
const char *DiagnosticTag,
bool AllowMacroExpansion);
- /// LexNonComment - Lex a token. If it's a comment, keep lexing until we get
- /// something not a comment. This is useful in -E -C mode where comments
- /// would foul up preprocessor directive handling.
+ /// \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);
}
- /// LexUnexpandedToken - This is just like Lex, but this disables macro
- /// expansion of identifier tokens.
+ /// \brief Just like Lex, but disables macro expansion of identifier tokens.
void LexUnexpandedToken(Token &Result) {
// Disable macro expansion.
bool OldVal = DisableMacroExpansion;
@@ -765,24 +818,31 @@ public:
DisableMacroExpansion = OldVal;
}
- /// LexUnexpandedNonComment - Like LexNonComment, but this disables macro
- /// expansion of identifier tokens.
+ /// \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;
}
- /// LookAhead - This peeks ahead N tokens and returns that token without
- /// consuming any tokens. LookAhead(0) returns the next token that would be
- /// returned by Lex(), LookAhead(1) returns the token after it, etc. This
- /// returns normal tokens after phase 5. As such, it is equivalent to using
+ /// \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())
@@ -791,8 +851,9 @@ public:
return PeekAhead(N+1);
}
- /// RevertCachedTokens - When backtracking is enabled and tokens are cached,
+ /// \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) {
@@ -805,20 +866,21 @@ public:
CachedLexPos -= N;
}
- /// EnterToken - Enters a token in the token stream to be lexed next. If
- /// BackTrack() is called afterwards, the token will remain at the insertion
- /// point.
+ /// \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);
}
- /// AnnotateCachedTokens - We notify the Preprocessor that if it is caching
- /// tokens (because backtrack is enabled) it should replace the most recent
- /// cached tokens with the given annotation token. This function has no effect
- /// if backtracking is not enabled.
+ /// 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
+ /// 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) {
@@ -848,7 +910,7 @@ public:
CachedTokens[CachedLexPos-1] = Tok;
}
- /// TypoCorrectToken - Update the current token to represent the provided
+ /// 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");
@@ -886,14 +948,16 @@ public:
unsigned Line, unsigned Column);
/// \brief Determine if we are performing code completion.
- bool isCodeCompletionEnabled() const { return CodeCompletionFile != 0; }
+ 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 {
@@ -913,8 +977,9 @@ public:
}
/// \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.
+ /// arc_cf_code_audited begin.
+ ///
+ /// Returns an invalid location if there is no such pragma active.
SourceLocation getPragmaARCCFCodeAuditedLoc() const {
return PragmaARCCFCodeAuditedLoc;
}
@@ -936,7 +1001,7 @@ public:
SkipMainFilePreamble.second = StartOfLine;
}
- /// Diag - Forwarding function for diagnostics. This emits a diagnostic at
+ /// 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 {
@@ -947,7 +1012,7 @@ public:
return Diags->Report(Tok.getLocation(), DiagID);
}
- /// getSpelling() - Return the 'spelling' of the token at the given
+ /// Return the 'spelling' of the token at the given
/// location; does not go up to the spelling location or down to the
/// expansion location.
///
@@ -956,25 +1021,28 @@ public:
/// \param invalid If non-null, will be set \c true if an error occurs.
StringRef getSpelling(SourceLocation loc,
SmallVectorImpl<char> &buffer,
- bool *invalid = 0) const {
+ bool *invalid = nullptr) const {
return Lexer::getSpelling(loc, buffer, SourceMgr, LangOpts, invalid);
}
- /// 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.
+ /// \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 = 0) const {
+ std::string getSpelling(const Token &Tok, bool *Invalid = nullptr) const {
return Lexer::getSpelling(Tok, SourceMgr, LangOpts, Invalid);
}
- /// getSpelling - This method is used to get the spelling of a token into a
- /// preallocated buffer, instead of as an std::string. The caller is required
- /// to allocate enough space for the token, which is guaranteed to be at least
- /// Tok.getLength() bytes long. The length of the actual result is returned.
+ /// \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*
@@ -982,16 +1050,17 @@ public:
/// copy). The caller is not allowed to modify the returned buffer pointer
/// if an internal buffer is returned.
unsigned getSpelling(const Token &Tok, const char *&Buffer,
- bool *Invalid = 0) const {
+ bool *Invalid = nullptr) const {
return Lexer::getSpelling(Tok, Buffer, SourceMgr, LangOpts, Invalid);
}
- /// getSpelling - This method is used to get the spelling of a token into a
- /// SmallVector. Note that the returned StringRef may not point to the
+ /// \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 = 0) const;
+ bool *Invalid = nullptr) const;
/// \brief Relex the token at the specified location.
/// \returns true if there was a failure, false on success.
@@ -1000,10 +1069,11 @@ public:
return Lexer::getRawToken(Loc, Result, SourceMgr, LangOpts, IgnoreWhiteSpace);
}
- /// getSpellingOfSingleCharacterNumericConstant - Tok is a numeric constant
- /// with length 1, return the character.
- char getSpellingOfSingleCharacterNumericConstant(const Token &Tok,
- bool *Invalid = 0) const {
+ /// \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");
@@ -1019,18 +1089,21 @@ public:
/// \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 the SourceManager.
+ /// 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());
}
- /// CreateString - Plop the specified string into a scratch buffer and set the
- /// specified token's location and length to it. If specified, the source
- /// location provides a location of the expansion point of the token.
+ /// \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());
@@ -1060,7 +1133,7 @@ public:
/// \param MacroBegin If non-null and function returns true, it is set to
/// begin location of the macro.
bool isAtStartOfMacroExpansion(SourceLocation loc,
- SourceLocation *MacroBegin = 0) const {
+ SourceLocation *MacroBegin = nullptr) const {
return Lexer::isAtStartOfMacroExpansion(loc, SourceMgr, LangOpts,
MacroBegin);
}
@@ -1071,27 +1144,26 @@ public:
/// \param MacroEnd If non-null and function returns true, it is set to
/// end location of the macro.
bool isAtEndOfMacroExpansion(SourceLocation loc,
- SourceLocation *MacroEnd = 0) const {
+ SourceLocation *MacroEnd = nullptr) const {
return Lexer::isAtEndOfMacroExpansion(loc, SourceMgr, LangOpts, MacroEnd);
}
- /// DumpToken - Print the token to stderr, used for debugging.
- ///
+ /// \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;
- /// AdvanceToTokenCharacter - Given a location that specifies the start of a
+ /// \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);
}
- /// IncrementPasteCounter - Increment the counters for the number of token
- /// paste operations performed. If fast was specified, this is a 'fast paste'
- /// case we handled.
+ /// \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;
@@ -1103,16 +1175,16 @@ public:
size_t getTotalMemory() const;
- /// HandleMicrosoftCommentPaste - When the macro expander pastes together a
- /// comment (/##/) in microsoft mode, this method handles updating the current
- /// state, returning the token on the next source line.
+ /// When the macro expander pastes together a comment (/##/) in Microsoft
+ /// mode, this method handles updating the current state, returning the
+ /// token on the next source line.
void HandleMicrosoftCommentPaste(Token &Tok);
//===--------------------------------------------------------------------===//
// Preprocessor callback methods. These are invoked by a lexer as various
// directives and events are found.
- /// LookUpIdentifierInfo - Given a tok::raw_identifier token, look up the
+ /// 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;
@@ -1122,14 +1194,13 @@ private:
public:
- // SetPoisonReason - Call this function to indicate 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.
+ /// \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);
- // HandlePoisonedIdentifier - Display reason for poisoned
- // identifier.
+ /// \brief Display reason for poisoned identifier.
void HandlePoisonedIdentifier(Token & Tok);
void MaybeHandlePoisonedIdentifier(Token & Identifier) {
@@ -1155,45 +1226,53 @@ private:
IdentifierInfo *Ident__abnormal_termination,
*Ident___abnormal_termination,
*Ident_AbnormalTermination;
+
+ const char *getCurLexerEndPos();
+
public:
void PoisonSEHIdentifiers(bool Poison = true); // Borland
- /// HandleIdentifier - This callback is invoked when the lexer reads an
- /// identifier and has filled in the tokens IdentifierInfo member. This
- /// callback potentially macro expands it or turns it into a named token (like
- /// 'for').
+ /// \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);
- /// HandleEndOfFile - This callback is invoked when the lexer hits the end of
- /// the current file. This either returns the EOF token and returns true, or
+ /// \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);
- /// HandleEndOfTokenLexer - This callback is invoked when the current
- /// TokenLexer hits the end of its token stream.
+ /// \brief Callback invoked when the current TokenLexer hits the end of its
+ /// token stream.
bool HandleEndOfTokenLexer(Token &Result);
- /// HandleDirective - This callback is invoked when the lexer sees a # token
- /// at the start of a line. This consumes the directive, modifies the
- /// lexer/preprocessor state, and advances the lexer(s) so that the next token
- /// read is the correct one.
+ /// \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);
- /// CheckEndOfDirective - Ensure that the next token is a tok::eod token. If
- /// not, emit a diagnostic and consume up until the eod. If EnableMacros is
- /// true, then we consider macros that expand to zero tokens as being ok.
+ /// \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);
- /// DiscardUntilEndOfDirective - Read and discard all tokens remaining on the
- /// current line until the tok::eod token is found.
+ /// \brief Read and discard all tokens remaining on the current line until
+ /// the tok::eod token is found.
void DiscardUntilEndOfDirective();
- /// SawDateOrTime - This returns true if the preprocessor has seen a use of
+ /// \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();
@@ -1234,17 +1313,20 @@ public:
ModuleMap::KnownHeader *SuggestedModule,
bool SkipCache = false);
- /// GetCurLookup - The DirectoryLookup structure used to find the current
- /// FileEntry, if CurLexer is non-null and if applicable. This allows us to
- /// implement \#include_next and find directory-specific properties.
+ /// \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;
- /// ConcatenateIncludeName - Handle cases where the \#include name is expanded
- /// from a macro as multiple tokens, which need to be glued together. This
- /// occurs for code like:
+ /// \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
@@ -1257,28 +1339,28 @@ public:
bool ConcatenateIncludeName(SmallString<128> &FilenameBuffer,
SourceLocation &End);
- /// LexOnOffSwitch - Lex an on-off-switch (C99 6.10.6p2) and verify that it is
+ /// \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, char isDefineUndef);
+
private:
void PushIncludeMacroStack() {
- IncludeMacroStack.push_back(IncludeStackInfo(CurLexerKind,
- CurLexer.take(),
- CurPTHLexer.take(),
- CurPPLexer,
- CurTokenLexer.take(),
- CurDirLookup));
- CurPPLexer = 0;
+ IncludeMacroStack.push_back(IncludeStackInfo(
+ CurLexerKind, CurSubmodule, std::move(CurLexer), std::move(CurPTHLexer),
+ CurPPLexer, std::move(CurTokenLexer), CurDirLookup));
+ CurPPLexer = nullptr;
}
void PopIncludeMacroStack() {
- CurLexer.reset(IncludeMacroStack.back().TheLexer);
- CurPTHLexer.reset(IncludeMacroStack.back().ThePTHLexer);
+ CurLexer = std::move(IncludeMacroStack.back().TheLexer);
+ CurPTHLexer = std::move(IncludeMacroStack.back().ThePTHLexer);
CurPPLexer = IncludeMacroStack.back().ThePPLexer;
- CurTokenLexer.reset(IncludeMacroStack.back().TheTokenLexer);
+ CurTokenLexer = std::move(IncludeMacroStack.back().TheTokenLexer);
CurDirLookup = IncludeMacroStack.back().TheDirLookup;
+ CurSubmodule = IncludeMacroStack.back().TheSubmodule;
CurLexerKind = IncludeMacroStack.back().CurLexerKind;
IncludeMacroStack.pop_back();
}
@@ -1300,15 +1382,16 @@ private:
/// This memory will be reused for allocating new MacroInfo objects.
void ReleaseMacroInfo(MacroInfo* MI);
- /// ReadMacroName - Lex and validate a macro name, which occurs after a
- /// \#define or \#undef. This emits a diagnostic, sets the token kind to eod,
+ /// \brief Lex and validate a macro name, which occurs after a
+ /// \#define or \#undef.
+ ///
+ /// 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, char isDefineUndef = 0);
- /// ReadMacroDefinitionArgList - The ( starting an argument list of a macro
- /// definition has just been read. Lex the rest of the arguments and the
- /// closing ), updating MI with what we learn and saving in LastTok the
- /// last token read.
+ /// 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);
@@ -1327,21 +1410,22 @@ private:
/// \brief A fast PTH version of SkipExcludedConditionalBlock.
void PTHSkipExcludedConditionalBlock();
- /// EvaluateDirectiveExpression - Evaluate an integer constant expression that
- /// may occur after a #if or #elif directive and return it as a bool. If the
- /// expression is equivalent to "!defined(X)" return X in IfNDefMacro.
+ /// \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);
- /// RegisterBuiltinPragmas - Install the standard preprocessor pragmas:
+ /// \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();
- /// HandleMacroExpandedIdentifier - If an identifier token is read that is to
- /// be expanded as a macro, handle it and return the next token as 'Tok'. If
- /// we lexed a token, return true; otherwise the caller should lex again.
+ /// 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, MacroDirective *MD);
/// \brief Cache macro expanded tokens for TokenLexers.
@@ -1354,52 +1438,51 @@ private:
void removeCachedMacroExpandedTokensOfLastLexer();
friend void TokenLexer::ExpandFunctionArguments();
- /// isNextPPTokenLParen - Determine whether the next preprocessor token to be
+ /// Determine whether the next preprocessor token to be
/// lexed is a '('. If so, consume the token and return true, if not, this
/// method should have no observable side-effect on the lexed tokens.
bool isNextPPTokenLParen();
- /// ReadFunctionLikeMacroArgs - After reading "MACRO(", this method is
- /// invoked to read all of the formal arguments specified for the macro
- /// invocation. This returns null on error.
+ /// 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);
- /// ExpandBuiltinMacro - If an identifier token is read that is to be expanded
+ /// \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);
- /// Handle_Pragma - Read a _Pragma directive, slice it up, process it, then
- /// return the first token after the directive. The _Pragma token has just
- /// been read into 'Tok'.
+ /// \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);
- /// HandleMicrosoft__pragma - Like Handle_Pragma except the pragma text
- /// is not enclosed within a string literal.
+ /// \brief Like Handle_Pragma except the pragma text is not enclosed within
+ /// a string literal.
void HandleMicrosoft__pragma(Token &Tok);
- /// EnterSourceFileWithLexer - Add a lexer to the top of the include stack and
+ /// \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);
- /// EnterSourceFileWithPTH - Add a lexer to the top of the include stack and
+ /// \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 file ID for the preprocessor predefines.
+ /// \brief Set the FileID for the preprocessor predefines.
void setPredefinesFileID(FileID FID) {
assert(PredefinesFileID.isInvalid() && "PredefinesFileID already set!");
PredefinesFileID = FID;
}
- /// IsFileLexer - Returns true if we are lexing from a file and not a
- /// pragma or a macro.
+ /// \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 != 0;
+ return L ? !L->isPragmaLexer() : P != nullptr;
}
static bool IsFileLexer(const IncludeStackInfo& I) {
- return IsFileLexer(I.TheLexer, I.ThePPLexer);
+ return IsFileLexer(I.TheLexer.get(), I.ThePPLexer);
}
bool IsFileLexer() const {
@@ -1437,7 +1520,7 @@ private:
// File inclusion.
void HandleIncludeDirective(SourceLocation HashLoc,
Token &Tok,
- const DirectoryLookup *LookupFrom = 0,
+ const DirectoryLookup *LookupFrom = nullptr,
bool isImport = false);
void HandleIncludeNextDirective(SourceLocation HashLoc, Token &Tok);
void HandleIncludeMacrosDirective(SourceLocation HashLoc, Token &Tok);
@@ -1449,25 +1532,6 @@ private:
/// points to.
Module *getModuleForLocation(SourceLocation FilenameLoc);
- /// \brief Verify that a private header is included only from within its
- /// module.
- bool violatesPrivateInclude(Module *RequestingModule,
- const FileEntry *IncFileEnt,
- ModuleMap::ModuleHeaderRole Role,
- Module *RequestedModule);
-
- /// \brief Verify that a module includes headers only from modules that it
- /// has declared that it uses.
- bool violatesUseDeclarations(Module *RequestingModule,
- Module *RequestedModule);
-
- /// \brief Verify that it is legal for the source file that \p FilenameLoc
- /// points to to include the file \p Filename.
- ///
- /// Tries to reuse \p IncFileEnt.
- void verifyModuleInclude(SourceLocation FilenameLoc, StringRef Filename,
- const FileEntry *IncFileEnt);
-
// Macro handling.
void HandleDefineDirective(Token &Tok, bool ImmediatelyAfterTopLevelIfndef);
void HandleUndefDirective(Token &Tok);
diff --git a/include/clang/Lex/PreprocessorLexer.h b/include/clang/Lex/PreprocessorLexer.h
index 27a8df43a274..ed226ae9a3f6 100644
--- a/include/clang/Lex/PreprocessorLexer.h
+++ b/include/clang/Lex/PreprocessorLexer.h
@@ -76,7 +76,7 @@ protected:
PreprocessorLexer(Preprocessor *pp, FileID fid);
PreprocessorLexer()
- : PP(0), InitialNumSLocEntries(0),
+ : PP(nullptr), InitialNumSLocEntries(0),
ParsingPreprocessorDirective(false),
ParsingFilename(false),
LexingRawMode(false) {}
diff --git a/include/clang/Lex/PreprocessorOptions.h b/include/clang/Lex/PreprocessorOptions.h
index eba2a13342f5..135c87fa837b 100644
--- a/include/clang/Lex/PreprocessorOptions.h
+++ b/include/clang/Lex/PreprocessorOptions.h
@@ -97,14 +97,13 @@ public:
/// 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;
+ std::vector<std::pair<std::string, std::string>> RemappedFiles;
/// \brief The set of file-to-buffer remappings, which take existing files
/// on the system (the first part of each pair) and gives them the contents
/// of the specified memory buffer (the second part of each pair).
- std::vector<std::pair<std::string, const llvm::MemoryBuffer *> >
- RemappedFileBuffers;
-
+ 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.
///
@@ -140,40 +139,6 @@ public:
/// build it again.
IntrusiveRefCntPtr<FailedModulesSet> FailedModules;
- typedef std::vector<std::pair<std::string, std::string> >::iterator
- remapped_file_iterator;
- typedef std::vector<std::pair<std::string, std::string> >::const_iterator
- const_remapped_file_iterator;
- remapped_file_iterator remapped_file_begin() {
- return RemappedFiles.begin();
- }
- const_remapped_file_iterator remapped_file_begin() const {
- return RemappedFiles.begin();
- }
- remapped_file_iterator remapped_file_end() {
- return RemappedFiles.end();
- }
- const_remapped_file_iterator remapped_file_end() const {
- return RemappedFiles.end();
- }
-
- typedef std::vector<std::pair<std::string, const llvm::MemoryBuffer *> >::
- iterator remapped_file_buffer_iterator;
- typedef std::vector<std::pair<std::string, const llvm::MemoryBuffer *> >::
- const_iterator const_remapped_file_buffer_iterator;
- remapped_file_buffer_iterator remapped_file_buffer_begin() {
- return RemappedFileBuffers.begin();
- }
- const_remapped_file_buffer_iterator remapped_file_buffer_begin() const {
- return RemappedFileBuffers.begin();
- }
- remapped_file_buffer_iterator remapped_file_buffer_end() {
- return RemappedFileBuffers.end();
- }
- const_remapped_file_buffer_iterator remapped_file_buffer_end() const {
- return RemappedFileBuffers.end();
- }
-
public:
PreprocessorOptions() : UsePredefines(true), DetailedRecord(false),
DisablePCHValidation(false),
@@ -193,20 +158,11 @@ public:
void addRemappedFile(StringRef From, StringRef To) {
RemappedFiles.push_back(std::make_pair(From, To));
}
-
- remapped_file_iterator eraseRemappedFile(remapped_file_iterator Remapped) {
- return RemappedFiles.erase(Remapped);
- }
-
- void addRemappedFile(StringRef From, const llvm::MemoryBuffer * To) {
+
+ void addRemappedFile(StringRef From, llvm::MemoryBuffer *To) {
RemappedFileBuffers.push_back(std::make_pair(From, To));
}
-
- remapped_file_buffer_iterator
- eraseRemappedFile(remapped_file_buffer_iterator Remapped) {
- return RemappedFileBuffers.erase(Remapped);
- }
-
+
void clearRemappedFiles() {
RemappedFiles.clear();
RemappedFileBuffers.clear();
diff --git a/include/clang/Lex/Token.h b/include/clang/Lex/Token.h
index 4f6391d6502d..c8b77d11747e 100644
--- a/include/clang/Lex/Token.h
+++ b/include/clang/Lex/Token.h
@@ -18,6 +18,7 @@
#include "clang/Basic/SourceLocation.h"
#include "clang/Basic/TemplateKinds.h"
#include "clang/Basic/TokenKinds.h"
+#include "llvm/ADT/StringRef.h"
#include <cstdlib>
namespace clang {
@@ -62,8 +63,7 @@ class Token {
void *PtrData;
/// Kind - The actual flavor of token this is.
- ///
- unsigned short Kind;
+ tok::TokenKind Kind;
/// Flags - Bits we track about this token, members of the TokenFlags enum.
unsigned char Flags;
@@ -83,13 +83,13 @@ public:
IgnoredComma = 0x80 // This comma is not a macro argument separator (MS).
};
- tok::TokenKind getKind() const { return (tok::TokenKind)Kind; }
+ 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 == (unsigned) K; }
- bool isNot(tok::TokenKind K) const { return Kind != (unsigned) K; }
+ bool is(tok::TokenKind K) const { return Kind == K; }
+ bool isNot(tok::TokenKind K) const { return Kind != K; }
/// \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).
@@ -145,15 +145,13 @@ public:
setAnnotationEndLoc(R.getEnd());
}
- const char *getName() const {
- return tok::getTokenName( (tok::TokenKind) Kind);
- }
+ const char *getName() const { return tok::getTokenName(Kind); }
/// \brief Reset all flags to cleared.
void startToken() {
Kind = tok::unknown;
Flags = 0;
- PtrData = 0;
+ PtrData = nullptr;
UintData = 0;
Loc = SourceLocation();
}
@@ -163,19 +161,19 @@ public:
"getIdentifierInfo() on a tok::raw_identifier token!");
assert(!isAnnotation() &&
"getIdentifierInfo() on an annotation token!");
- if (isLiteral()) return 0;
+ if (isLiteral()) return nullptr;
return (IdentifierInfo*) PtrData;
}
void setIdentifierInfo(IdentifierInfo *II) {
PtrData = (void*) II;
}
- /// getRawIdentifierData - For a raw identifier token (i.e., an identifier
- /// lexed in raw mode), returns a pointer to the start of it in the text
- /// buffer if known, null otherwise.
- const char *getRawIdentifierData() const {
+ /// 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 reinterpret_cast<const char*>(PtrData);
+ return StringRef(reinterpret_cast<const char *>(PtrData), getLength());
}
void setRawIdentifierData(const char *Ptr) {
assert(is(tok::raw_identifier));
diff --git a/include/clang/Lex/TokenLexer.h b/include/clang/Lex/TokenLexer.h
index 7c8cfd028a28..a873a2e27508 100644
--- a/include/clang/Lex/TokenLexer.h
+++ b/include/clang/Lex/TokenLexer.h
@@ -81,6 +81,14 @@ class TokenLexer {
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
@@ -100,7 +108,7 @@ public:
/// identifier for an object-like macro.
TokenLexer(Token &Tok, SourceLocation ILEnd, MacroInfo *MI,
MacroArgs *ActualArgs, Preprocessor &pp)
- : Macro(0), ActualArgs(0), PP(pp), OwnsTokens(false) {
+ : Macro(nullptr), ActualArgs(nullptr), PP(pp), OwnsTokens(false) {
Init(Tok, ILEnd, MI, ActualArgs);
}
@@ -116,7 +124,7 @@ public:
/// the token lexer is empty.
TokenLexer(const Token *TokArray, unsigned NumToks, bool DisableExpansion,
bool ownsTokens, Preprocessor &pp)
- : Macro(0), ActualArgs(0), PP(pp), OwnsTokens(false) {
+ : Macro(nullptr), ActualArgs(nullptr), PP(pp), OwnsTokens(false) {
Init(TokArray, NumToks, DisableExpansion, ownsTokens);
}
@@ -182,6 +190,13 @@ private:
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);
};
diff --git a/include/clang/Makefile b/include/clang/Makefile
index 5f2077d2f041..5ba2dd2991b8 100644
--- a/include/clang/Makefile
+++ b/include/clang/Makefile
@@ -1,5 +1,5 @@
CLANG_LEVEL := ../..
-DIRS := AST Basic Driver Lex Parse Sema Serialization
+DIRS := AST Basic Driver Parse Sema Serialization
include $(CLANG_LEVEL)/Makefile
diff --git a/include/clang/Parse/CMakeLists.txt b/include/clang/Parse/CMakeLists.txt
index ed80c1889c7d..ec75f7b96b14 100644
--- a/include/clang/Parse/CMakeLists.txt
+++ b/include/clang/Parse/CMakeLists.txt
@@ -1,14 +1,4 @@
-clang_tablegen(AttrIdentifierArg.inc -gen-clang-attr-identifier-arg-list
+clang_tablegen(AttrParserStringSwitches.inc -gen-clang-attr-parser-string-switches
-I ${CMAKE_CURRENT_SOURCE_DIR}/../../
SOURCE ../Basic/Attr.td
- TARGET ClangAttrIdentifierArg)
-
-clang_tablegen(AttrTypeArg.inc -gen-clang-attr-type-arg-list
- -I ${CMAKE_CURRENT_SOURCE_DIR}/../../
- SOURCE ../Basic/Attr.td
- TARGET ClangAttrTypeArg)
-
-clang_tablegen(AttrLateParsed.inc -gen-clang-attr-late-parsed-list
- -I ${CMAKE_CURRENT_SOURCE_DIR}/../../
- SOURCE ../Basic/Attr.td
- TARGET ClangAttrLateParsed)
+ TARGET ClangAttrParserStringSwitches)
diff --git a/include/clang/Parse/Makefile b/include/clang/Parse/Makefile
index 00d41fafddeb..c4770190562d 100644
--- a/include/clang/Parse/Makefile
+++ b/include/clang/Parse/Makefile
@@ -1,25 +1,13 @@
CLANG_LEVEL := ../../..
TD_SRC_DIR = $(PROJ_SRC_DIR)/../Basic
-BUILT_SOURCES = AttrIdentifierArg.inc AttrLateParsed.inc AttrTypeArg.inc
+BUILT_SOURCES = AttrParserStringSwitches.inc
TABLEGEN_INC_FILES_COMMON = 1
include $(CLANG_LEVEL)/Makefile
-$(ObjDir)/AttrIdentifierArg.inc.tmp : $(TD_SRC_DIR)/Attr.td $(CLANG_TBLGEN) \
+$(ObjDir)/AttrParserStringSwitches.inc.tmp : $(TD_SRC_DIR)/Attr.td $(CLANG_TBLGEN) \
$(ObjDir)/.dir
- $(Echo) "Building Clang attribute identifier argument table with tblgen"
- $(Verb) $(ClangTableGen) -gen-clang-attr-identifier-arg-list -o $(call SYSPATH, $@) \
- -I $(PROJ_SRC_DIR)/../../ $<
-
-$(ObjDir)/AttrTypeArg.inc.tmp : $(TD_SRC_DIR)/Attr.td $(CLANG_TBLGEN) \
- $(ObjDir)/.dir
- $(Echo) "Building Clang attribute type argument table with tblgen"
- $(Verb) $(ClangTableGen) -gen-clang-attr-type-arg-list -o $(call SYSPATH, $@) \
- -I $(PROJ_SRC_DIR)/../../ $<
-
-$(ObjDir)/AttrLateParsed.inc.tmp : $(TD_SRC_DIR)/Attr.td $(CLANG_TBLGEN) \
- $(ObjDir)/.dir
- $(Echo) "Building Clang attribute late-parsed table with tblgen"
- $(Verb) $(ClangTableGen) -gen-clang-attr-late-parsed-list -o $(call SYSPATH, $@) \
+ $(Echo) "Building Clang parser-related attribute string switches"
+ $(Verb) $(ClangTableGen) -gen-clang-attr-parser-string-switches -o $(call SYSPATH, $@) \
-I $(PROJ_SRC_DIR)/../../ $<
diff --git a/include/clang/Parse/ParseAST.h b/include/clang/Parse/ParseAST.h
index 2405a0ccd653..21f9701c3ed8 100644
--- a/include/clang/Parse/ParseAST.h
+++ b/include/clang/Parse/ParseAST.h
@@ -36,7 +36,7 @@ namespace clang {
void ParseAST(Preprocessor &pp, ASTConsumer *C,
ASTContext &Ctx, bool PrintStats = false,
TranslationUnitKind TUKind = TU_Complete,
- CodeCompleteConsumer *CompletionConsumer = 0,
+ CodeCompleteConsumer *CompletionConsumer = nullptr,
bool SkipFunctionBodies = false);
/// \brief Parse the main file known to the preprocessor, producing an
diff --git a/include/clang/Parse/Parser.h b/include/clang/Parse/Parser.h
index bd49988c5b00..c58c41a44c58 100644
--- a/include/clang/Parse/Parser.h
+++ b/include/clang/Parse/Parser.h
@@ -20,12 +20,13 @@
#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/OwningPtr.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 {
@@ -40,7 +41,6 @@ namespace clang {
class ParsingDeclSpec;
class ParsingDeclarator;
class ParsingFieldDeclarator;
- class PragmaUnusedHandler;
class ColonProtectionRAIIObject;
class InMessageExpressionRAIIObject;
class PoisonSEHIdentifiersRAIIObject;
@@ -52,7 +52,6 @@ namespace clang {
/// been read.
///
class Parser : public CodeCompletionHandler {
- friend class PragmaUnusedHandler;
friend class ColonProtectionRAIIObject;
friend class InMessageExpressionRAIIObject;
friend class PoisonSEHIdentifiersRAIIObject;
@@ -73,7 +72,7 @@ class Parser : public CodeCompletionHandler {
SourceLocation PrevTokLocation;
unsigned short ParenCount, BracketCount, BraceCount;
-
+
/// Actions - These are the callbacks we invoke as we parse various constructs
/// in the file.
Sema &Actions;
@@ -136,24 +135,37 @@ class Parser : public CodeCompletionHandler {
mutable IdentifierInfo *Ident_final;
mutable IdentifierInfo *Ident_override;
- // C++ type trait keywords that have can be reverted to identifiers and
- // still used as type traits.
- llvm::SmallDenseMap<IdentifierInfo *, tok::TokenKind> RevertableTypeTraits;
-
- OwningPtr<PragmaHandler> AlignHandler;
- OwningPtr<PragmaHandler> GCCVisibilityHandler;
- OwningPtr<PragmaHandler> OptionsHandler;
- OwningPtr<PragmaHandler> PackHandler;
- OwningPtr<PragmaHandler> MSStructHandler;
- OwningPtr<PragmaHandler> UnusedHandler;
- OwningPtr<PragmaHandler> WeakHandler;
- OwningPtr<PragmaHandler> RedefineExtnameHandler;
- OwningPtr<PragmaHandler> FPContractHandler;
- OwningPtr<PragmaHandler> OpenCLExtensionHandler;
- OwningPtr<CommentHandler> CommentSemaHandler;
- OwningPtr<PragmaHandler> OpenMPHandler;
- OwningPtr<PragmaHandler> MSCommentHandler;
- OwningPtr<PragmaHandler> MSDetectMismatchHandler;
+ // Some token kinds such as C++ type traits can be reverted to identifiers and
+ // still get used as keywords depending on context.
+ llvm::SmallDenseMap<const IdentifierInfo *, tok::TokenKind>
+ ContextualKeywords;
+
+ 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> OptimizeHandler;
+ std::unique_ptr<PragmaHandler> LoopHintHandler;
+ std::unique_ptr<PragmaHandler> UnrollHintHandler;
+
+ 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++
@@ -167,7 +179,7 @@ class Parser : public CodeCompletionHandler {
/// ColonProtectionRAIIObject RAII object.
bool ColonIsSacred;
- /// \brief When true, we are directly inside an Objective-C messsage
+ /// \brief When true, we are directly inside an Objective-C message
/// send expression.
///
/// This is managed by the \c InMessageExpressionRAIIObject class, and
@@ -193,6 +205,10 @@ class Parser : public CodeCompletionHandler {
++Depth;
++AddedLevels;
}
+ void addDepth(unsigned D) {
+ Depth += D;
+ AddedLevels += D;
+ }
unsigned getDepth() const { return Depth; }
};
@@ -229,6 +245,9 @@ public:
const Token &getCurToken() const { return Tok; }
Scope *getCurScope() const { return Actions.getCurScope(); }
+ void incrementMSLocalManglingNumber() const {
+ return Actions.incrementMSLocalManglingNumber();
+ }
Decl *getObjCDeclContext() const { return Actions.getObjCDeclContext(); }
@@ -246,7 +265,7 @@ public:
typedef clang::TypeResult TypeResult;
typedef Expr *ExprArg;
- typedef llvm::MutableArrayRef<Stmt*> MultiStmtArg;
+ typedef MutableArrayRef<Stmt*> MultiStmtArg;
typedef Sema::FullExprArg FullExprArg;
ExprResult ExprError() { return ExprResult(true); }
@@ -266,24 +285,40 @@ public:
/// 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 all kinds of tokens: strings and specific other
- /// tokens must be consumed with custom methods below. This returns the
- /// location of the consumed token.
- SourceLocation ConsumeToken(bool ConsumeCodeCompletionTok = false) {
- assert(!isTokenStringLiteral() && !isTokenParen() && !isTokenBracket() &&
- !isTokenBrace() &&
+ /// 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");
-
- if (!ConsumeCodeCompletionTok && Tok.is(tok::code_completion))
- return handleUnexpectedCodeCompletionToken();
-
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;
+ }
+
private:
//===--------------------------------------------------------------------===//
// Low-Level token peeking and consumption methods.
@@ -301,12 +336,15 @@ private:
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 '='
@@ -318,14 +356,16 @@ private:
SourceLocation ConsumeAnyToken(bool ConsumeCodeCompletionTok = false) {
if (isTokenParen())
return ConsumeParen();
- else if (isTokenBracket())
+ if (isTokenBracket())
return ConsumeBracket();
- else if (isTokenBrace())
+ if (isTokenBrace())
return ConsumeBrace();
- else if (isTokenStringLiteral())
+ if (isTokenStringLiteral())
return ConsumeStringToken();
- else
- return ConsumeToken(ConsumeCodeCompletionTok);
+ if (Tok.is(tok::code_completion))
+ return ConsumeCodeCompletionTok ? ConsumeCodeCompletionToken()
+ : handleUnexpectedCodeCompletionToken();
+ return ConsumeToken();
}
/// ConsumeParen - This consume method keeps the paren count up-to-date.
@@ -383,8 +423,9 @@ private:
/// \brief Consume the current code-completion token.
///
- /// This routine should be called to consume the code-completion token once
- /// a code-completion action has already been invoked.
+ /// 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();
@@ -408,6 +449,20 @@ private:
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();
@@ -427,6 +482,18 @@ private:
/// #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();
@@ -455,6 +522,10 @@ private:
/// #pragma clang __debug captured
StmtResult HandlePragmaCaptured();
+ /// \brief Handle the annotation token produced for
+ /// #pragma clang loop and #pragma unroll.
+ LoopHint HandlePragmaLoopHint();
+
/// 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.
@@ -521,7 +592,7 @@ private:
ANK_Success
};
AnnotatedNameKind TryAnnotateName(bool IsAddressOfOperand,
- CorrectionCandidateCallback *CCC = 0);
+ CorrectionCandidateCallback *CCC = nullptr);
/// Push a tok::annot_cxxscope token onto the token stream.
void AnnotateScopeToken(CXXScopeSpec &SS, bool IsNewAnnotation);
@@ -562,6 +633,12 @@ private:
/// otherwise emits a diagnostic and returns true.
bool TryKeywordIdentFallback(bool DisableKeyword);
+ /// TryIdentKeywordUpgrade - Convert the current identifier token back to
+ /// its original kind and return true if it was disabled by
+ /// TryKeywordIdentFallback(), otherwise return false. Use this to
+ /// contextually enable keywords.
+ bool TryIdentKeywordUpgrade();
+
/// \brief Get the TemplateIdAnnotation from the token.
TemplateIdAnnotation *takeTemplateIdAnnotation(const Token &tok);
@@ -628,7 +705,7 @@ private:
public:
explicit ObjCDeclContextSwitch(Parser &p)
: P(p), DC(p.getObjCDeclContext()),
- WithinObjCContainer(P.ParsingInObjCContainer, DC != 0) {
+ WithinObjCContainer(P.ParsingInObjCContainer, DC != nullptr) {
if (DC)
P.Actions.ActOnObjCTemporaryExitContainerContext(cast<DeclContext>(DC));
}
@@ -641,12 +718,14 @@ private:
/// ExpectAndConsume - The parser expects that 'ExpectedTok' is next in the
/// input. If so, it is consumed and false is returned.
///
- /// If the input is malformed, this emits the specified diagnostic. Next, if
- /// SkipToTok is specified, it calls SkipUntil(SkipToTok). Finally, true is
+ /// 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,
- const char *DiagMsg = "",
- tok::TokenKind SkipToTok = tok::unknown);
+ bool ExpectAndConsume(tok::TokenKind ExpectedTok,
+ unsigned Diag = diag::err_expected,
+ StringRef DiagMsg = "");
/// \brief The parser expects a semicolon and, if present, will consume it.
///
@@ -684,14 +763,18 @@ public:
public:
// ParseScope - Construct a new object to manage a scope in the
// parser Self where the new Scope is created with the flags
- // ScopeFlags, but only when ManageScope is true (the default). If
- // ManageScope is false, this object does nothing.
- ParseScope(Parser *Self, unsigned ScopeFlags, bool ManageScope = true)
+ // 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 (ManageScope)
+ if (EnteredScope && !BeforeCompoundStmt)
Self->EnterScope(ScopeFlags);
- else
- this->Self = 0;
+ else {
+ if (BeforeCompoundStmt)
+ Self->incrementMSLocalManglingNumber();
+
+ this->Self = nullptr;
+ }
}
// Exit - Exit the scope associated with this object now, rather
@@ -699,7 +782,7 @@ public:
void Exit() {
if (Self) {
Self->ExitScope();
- Self = 0;
+ Self = nullptr;
}
}
@@ -818,10 +901,10 @@ private:
LateParsedClass(Parser *P, ParsingClass *C);
virtual ~LateParsedClass();
- virtual void ParseLexedMethodDeclarations();
- virtual void ParseLexedMemberInitializers();
- virtual void ParseLexedMethodDefs();
- virtual void ParseLexedAttributes();
+ void ParseLexedMethodDeclarations() override;
+ void ParseLexedMemberInitializers() override;
+ void ParseLexedMethodDefs() override;
+ void ParseLexedAttributes() override;
private:
Parser *Self;
@@ -845,7 +928,7 @@ private:
SourceLocation Loc)
: Self(P), AttrName(Name), AttrNameLoc(Loc) {}
- virtual void ParseLexedAttributes();
+ void ParseLexedAttributes() override;
void addDecl(Decl *D) { Decls.push_back(D); }
};
@@ -877,7 +960,7 @@ private:
explicit LexedMethod(Parser* P, Decl *MD)
: Self(P), D(MD), TemplateScope(false) {}
- virtual void ParseLexedMethodDefs();
+ void ParseLexedMethodDefs() override;
};
/// LateParsedDefaultArgument - Keeps track of a parameter that may
@@ -886,7 +969,7 @@ private:
/// (C++ [class.mem]p2).
struct LateParsedDefaultArgument {
explicit LateParsedDefaultArgument(Decl *P,
- CachedTokens *Toks = 0)
+ CachedTokens *Toks = nullptr)
: Param(P), Toks(Toks) { }
/// Param - The parameter declaration for this parameter.
@@ -905,9 +988,10 @@ private:
/// argument (C++ [class.mem]p2).
struct LateParsedMethodDeclaration : public LateParsedDeclaration {
explicit LateParsedMethodDeclaration(Parser *P, Decl *M)
- : Self(P), Method(M), TemplateScope(false), ExceptionSpecTokens(0) { }
+ : Self(P), Method(M), TemplateScope(false),
+ ExceptionSpecTokens(nullptr) {}
- virtual void ParseLexedMethodDeclarations();
+ void ParseLexedMethodDeclarations() override;
Parser* Self;
@@ -938,7 +1022,7 @@ private:
LateParsedMemberInitializer(Parser *P, Decl *FD)
: Self(P), Field(FD) { }
- virtual void ParseLexedMemberInitializers();
+ void ParseLexedMemberInitializers() override;
Parser *Self;
@@ -1028,7 +1112,7 @@ private:
/// specifiers.
struct ParsedTemplateInfo {
ParsedTemplateInfo()
- : Kind(NonTemplate), TemplateParams(0), TemplateLoc() { }
+ : Kind(NonTemplate), TemplateParams(nullptr), TemplateLoc() { }
ParsedTemplateInfo(TemplateParameterLists *TemplateParams,
bool isSpecialization,
@@ -1039,7 +1123,7 @@ private:
explicit ParsedTemplateInfo(SourceLocation ExternLoc,
SourceLocation TemplateLoc)
- : Kind(ExplicitInstantiation), TemplateParams(0),
+ : Kind(ExplicitInstantiation), TemplateParams(nullptr),
ExternLoc(ExternLoc), TemplateLoc(TemplateLoc),
LastParameterListWasEmpty(false){ }
@@ -1132,12 +1216,12 @@ private:
};
DeclGroupPtrTy ParseExternalDeclaration(ParsedAttributesWithRange &attrs,
- ParsingDeclSpec *DS = 0);
+ ParsingDeclSpec *DS = nullptr);
bool isDeclarationAfterDeclarator();
bool isStartOfFunctionDefinition(const ParsingDeclarator &Declarator);
DeclGroupPtrTy ParseDeclarationOrFunctionDefinition(
ParsedAttributesWithRange &attrs,
- ParsingDeclSpec *DS = 0,
+ ParsingDeclSpec *DS = nullptr,
AccessSpecifier AS = AS_none);
DeclGroupPtrTy ParseDeclOrFunctionDefInternal(ParsedAttributesWithRange &attrs,
ParsingDeclSpec &DS,
@@ -1145,11 +1229,11 @@ private:
Decl *ParseFunctionDefinition(ParsingDeclarator &D,
const ParsedTemplateInfo &TemplateInfo = ParsedTemplateInfo(),
- LateParsedAttrList *LateParsedAttrs = 0);
+ 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 = 0);
+ ExprResult ParseSimpleAsm(SourceLocation *EndLoc = nullptr);
ExprResult ParseAsmStringLiteral();
// Objective-C External Declarations
@@ -1289,12 +1373,12 @@ private:
typedef SmallVector<SourceLocation, 20> CommaLocsTy;
/// ParseExpressionList - Used for C/C++ (argument-)expression-list.
- bool ParseExpressionList(SmallVectorImpl<Expr*> &Exprs,
- SmallVectorImpl<SourceLocation> &CommaLocs,
- void (Sema::*Completer)(Scope *S,
- Expr *Data,
- ArrayRef<Expr *> Args) = 0,
- Expr *Data = 0);
+ bool
+ ParseExpressionList(SmallVectorImpl<Expr *> &Exprs,
+ SmallVectorImpl<SourceLocation> &CommaLocs,
+ void (Sema::*Completer)(Scope *S, Expr *Data,
+ ArrayRef<Expr *> Args) = nullptr,
+ Expr *Data = nullptr);
/// ParseSimpleExpressionList - A simple comma-separated list of expressions,
/// used for misc language extensions.
@@ -1315,9 +1399,9 @@ private:
ParsedType &CastTy,
SourceLocation &RParenLoc);
- ExprResult ParseCXXAmbiguousParenExpression(ParenParseOption &ExprType,
- ParsedType &CastTy,
- BalancedDelimiterTracker &Tracker);
+ ExprResult ParseCXXAmbiguousParenExpression(
+ ParenParseOption &ExprType, ParsedType &CastTy,
+ BalancedDelimiterTracker &Tracker, ColonProtectionRAIIObject &ColonProt);
ExprResult ParseCompoundLiteralExpression(ParsedType Ty,
SourceLocation LParenLoc,
SourceLocation RParenLoc);
@@ -1341,9 +1425,9 @@ private:
bool ParseOptionalCXXScopeSpecifier(CXXScopeSpec &SS,
ParsedType ObjectType,
bool EnteringContext,
- bool *MayBePseudoDestructor = 0,
+ bool *MayBePseudoDestructor = nullptr,
bool IsTypename = false,
- IdentifierInfo **LastII = 0);
+ IdentifierInfo **LastII = nullptr);
void CheckForLParenAfterColonColon();
@@ -1354,7 +1438,7 @@ private:
ExprResult ParseLambdaExpression();
ExprResult TryParseLambdaExpression();
Optional<unsigned> ParseLambdaIntroducer(LambdaIntroducer &Intro,
- bool *SkippedInits = 0);
+ bool *SkippedInits = nullptr);
bool TryParseLambdaIntroducer(LambdaIntroducer &Intro);
ExprResult ParseLambdaExpressionAfterIntroducer(
LambdaIntroducer &Intro);
@@ -1490,10 +1574,10 @@ private:
/// A SmallVector of types.
typedef SmallVector<ParsedType, 12> TypeVector;
- StmtResult ParseStatement(SourceLocation *TrailingElseLoc = 0);
- StmtResult ParseStatementOrDeclaration(StmtVector &Stmts,
- bool OnlyStatement,
- SourceLocation *TrailingElseLoc = 0);
+ StmtResult ParseStatement(SourceLocation *TrailingElseLoc = nullptr);
+ StmtResult
+ ParseStatementOrDeclaration(StmtVector &Stmts, bool OnlyStatement,
+ SourceLocation *TrailingElseLoc = nullptr);
StmtResult ParseStatementOrDeclarationAfterAttributes(
StmtVector &Stmts,
bool OnlyStatement,
@@ -1524,6 +1608,9 @@ private:
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.
@@ -1582,6 +1669,7 @@ private:
StmtResult ParseSEHTryBlockCommon(SourceLocation Loc);
StmtResult ParseSEHExceptBlock(SourceLocation Loc);
StmtResult ParseSEHFinallyBlock(SourceLocation Loc);
+ StmtResult ParseSEHLeaveStatement();
//===--------------------------------------------------------------------===//
// Objective-C Statements
@@ -1604,9 +1692,29 @@ private:
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_top_level // top-level/namespace declaration context
+ 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
};
+ /// 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:
+ 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 {
@@ -1624,17 +1732,19 @@ private:
SourceLocation &DeclEnd,
ParsedAttributesWithRange &attrs,
bool RequireSemi,
- ForRangeInit *FRI = 0);
+ ForRangeInit *FRI = nullptr);
bool MightBeDeclarator(unsigned Context);
DeclGroupPtrTy ParseDeclGroup(ParsingDeclSpec &DS, unsigned Context,
bool AllowFunctionDefinitions,
- SourceLocation *DeclEnd = 0,
- ForRangeInit *FRI = 0);
+ 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());
+ Decl *ParseDeclarationAfterDeclaratorAndAttributes(
+ Declarator &D,
+ const ParsedTemplateInfo &TemplateInfo = ParsedTemplateInfo(),
+ ForRangeInit *FRI = nullptr);
Decl *ParseFunctionStatementBody(Decl *Decl, ParseScope &BodyScope);
Decl *ParseFunctionTryBlock(Decl *Decl, ParseScope &BodyScope);
@@ -1653,10 +1763,10 @@ private:
const ParsedTemplateInfo &TemplateInfo = ParsedTemplateInfo(),
AccessSpecifier AS = AS_none,
DeclSpecContext DSC = DSC_normal,
- LateParsedAttrList *LateAttrs = 0);
+ LateParsedAttrList *LateAttrs = nullptr);
bool DiagnoseMissingSemiAfterTagDefinition(DeclSpec &DS, AccessSpecifier AS,
- DeclSpecContext DSContext,
- LateParsedAttrList *LateAttrs = 0);
+ DeclSpecContext DSContext,
+ LateParsedAttrList *LateAttrs = nullptr);
void ParseSpecifierQualifierList(DeclSpec &DS, AccessSpecifier AS = AS_none,
DeclSpecContext DSC = DSC_normal);
@@ -1696,7 +1806,7 @@ private:
/// 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 isCXXDeclarationSpecifier() == TPResult::True;
return isDeclarationSpecifier(true);
}
@@ -1719,6 +1829,9 @@ private:
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();
@@ -1726,12 +1839,13 @@ private:
/// \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 isConstructorDeclarator(bool Unqualified);
/// \brief Specifies the context in which type-id/expression
/// disambiguation will occur.
enum TentativeCXXTypeIdContext {
TypeIdInParens,
+ TypeIdUnambiguous,
TypeIdAsTemplateArgument
};
@@ -1750,6 +1864,16 @@ private:
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.
@@ -1769,7 +1893,7 @@ private:
/// 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 = 0);
+ bool isCXXFunctionDeclarator(bool *IsAmbiguous = nullptr);
/// isCXXConditionDeclaration - Disambiguates between a declaration or an
/// expression for a condition of a if/switch/while/for statement.
@@ -1785,25 +1909,8 @@ private:
/// TPResult - Used as the result value for functions whose purpose is to
/// disambiguate C++ constructs by "tentatively parsing" them.
- /// This is a class instead of a simple enum because the implicit enum-to-bool
- /// conversions may cause subtle bugs.
- class TPResult {
- enum Result {
- TPR_true,
- TPR_false,
- TPR_ambiguous,
- TPR_error
- };
- Result Res;
- TPResult(Result result) : Res(result) {}
- public:
- static TPResult True() { return TPR_true; }
- static TPResult False() { return TPR_false; }
- static TPResult Ambiguous() { return TPR_ambiguous; }
- static TPResult Error() { return TPR_error; }
-
- bool operator==(const TPResult &RHS) const { return Res == RHS.Res; }
- bool operator!=(const TPResult &RHS) const { return Res != RHS.Res; }
+ enum class TPResult {
+ True, False, Ambiguous, Error
};
/// \brief Based only on the given token kind, determine whether we know that
@@ -1818,16 +1925,16 @@ private:
/// 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
+ /// 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 = 0);
+ 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
@@ -1840,9 +1947,9 @@ private:
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
+ // 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.
@@ -1853,19 +1960,20 @@ private:
TPResult TryParseOperatorId();
TPResult TryParseInitDeclaratorList();
TPResult TryParseDeclarator(bool mayBeAbstract, bool mayHaveIdentifier=true);
- TPResult TryParseParameterDeclarationClause(bool *InvalidAsDeclaration = 0,
- bool VersusTemplateArg = false);
+ TPResult
+ TryParseParameterDeclarationClause(bool *InvalidAsDeclaration = nullptr,
+ bool VersusTemplateArg = false);
TPResult TryParseFunctionDeclarator();
TPResult TryParseBracketDeclarator();
TPResult TryConsumeDeclarationSpecifier();
public:
- TypeResult ParseTypeName(SourceRange *Range = 0,
+ TypeResult ParseTypeName(SourceRange *Range = nullptr,
Declarator::TheContext Context
= Declarator::TypeNameContext,
AccessSpecifier AS = AS_none,
- Decl **OwnedType = 0,
- ParsedAttributes *Attrs = 0);
+ Decl **OwnedType = nullptr,
+ ParsedAttributes *Attrs = nullptr);
private:
void ParseBlockId(SourceLocation CaretLoc);
@@ -1903,35 +2011,51 @@ private:
// 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 = 0) {
+ LateParsedAttrList *LateAttrs = nullptr) {
if (Tok.is(tok::kw___attribute)) {
ParsedAttributes attrs(AttrFactory);
SourceLocation endLoc;
- ParseGNUAttributes(attrs, &endLoc, LateAttrs);
+ ParseGNUAttributes(attrs, &endLoc, LateAttrs, &D);
D.takeAttributes(attrs, endLoc);
}
}
void MaybeParseGNUAttributes(ParsedAttributes &attrs,
- SourceLocation *endLoc = 0,
- LateParsedAttrList *LateAttrs = 0) {
+ SourceLocation *endLoc = nullptr,
+ LateParsedAttrList *LateAttrs = nullptr) {
if (Tok.is(tok::kw___attribute))
ParseGNUAttributes(attrs, endLoc, LateAttrs);
}
void ParseGNUAttributes(ParsedAttributes &attrs,
- SourceLocation *endLoc = 0,
- LateParsedAttrList *LateAttrs = 0);
+ 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);
+ AttributeList::Syntax Syntax,
+ Declarator *D);
IdentifierLoc *ParseIdentifierLoc();
void MaybeParseCXX11Attributes(Declarator &D) {
@@ -1943,7 +2067,7 @@ private:
}
}
void MaybeParseCXX11Attributes(ParsedAttributes &attrs,
- SourceLocation *endLoc = 0) {
+ SourceLocation *endLoc = nullptr) {
if (getLangOpts().CPlusPlus11 && isCXX11AttributeSpecifier()) {
ParsedAttributesWithRange attrsWithRange(AttrFactory);
ParseCXX11Attributes(attrsWithRange, endLoc);
@@ -1951,7 +2075,7 @@ private:
}
}
void MaybeParseCXX11Attributes(ParsedAttributesWithRange &attrs,
- SourceLocation *endLoc = 0,
+ SourceLocation *endLoc = nullptr,
bool OuterMightBeMessageSend = false) {
if (getLangOpts().CPlusPlus11 &&
isCXX11AttributeSpecifier(false, OuterMightBeMessageSend))
@@ -1959,54 +2083,68 @@ private:
}
void ParseCXX11AttributeSpecifier(ParsedAttributes &attrs,
- SourceLocation *EndLoc = 0);
+ SourceLocation *EndLoc = nullptr);
void ParseCXX11Attributes(ParsedAttributesWithRange &attrs,
- SourceLocation *EndLoc = 0);
+ 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 = 0) {
+ SourceLocation *endLoc = nullptr) {
if (getLangOpts().MicrosoftExt && Tok.is(tok::l_square))
ParseMicrosoftAttributes(attrs, endLoc);
}
void ParseMicrosoftAttributes(ParsedAttributes &attrs,
- SourceLocation *endLoc = 0);
+ SourceLocation *endLoc = nullptr);
void ParseMicrosoftDeclSpec(ParsedAttributes &Attrs);
- bool IsSimpleMicrosoftDeclSpec(IdentifierInfo *Ident);
- void ParseComplexMicrosoftDeclSpec(IdentifierInfo *Ident,
- SourceLocation Loc,
- ParsedAttributes &Attrs);
- void ParseMicrosoftDeclSpecWithSingleArg(IdentifierInfo *AttrName,
- SourceLocation AttrNameLoc,
- ParsedAttributes &Attrs);
+ bool ParseMicrosoftDeclSpecArgs(IdentifierInfo *AttrName,
+ SourceLocation AttrNameLoc,
+ ParsedAttributes &Attrs);
void ParseMicrosoftTypeAttributes(ParsedAttributes &attrs);
void ParseMicrosoftInheritanceClassAttributes(ParsedAttributes &attrs);
void ParseBorlandTypeAttributes(ParsedAttributes &attrs);
void ParseOpenCLAttributes(ParsedAttributes &attrs);
- void ParseOpenCLQualifiers(DeclSpec &DS);
+ void ParseOpenCLQualifiers(ParsedAttributes &Attrs);
VersionTuple ParseVersionTuple(SourceRange &Range);
void ParseAvailabilityAttribute(IdentifierInfo &Availability,
SourceLocation AvailabilityLoc,
ParsedAttributes &attrs,
- SourceLocation *endLoc);
-
- bool IsThreadSafetyAttribute(StringRef AttrName);
- void ParseThreadSafetyAttribute(IdentifierInfo &AttrName,
- SourceLocation AttrNameLoc,
- ParsedAttributes &Attrs,
- SourceLocation *EndLoc);
+ 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);
+ SourceLocation *EndLoc,
+ IdentifierInfo *ScopeName,
+ SourceLocation ScopeLoc,
+ AttributeList::Syntax Syntax);
void ParseAttributeWithTypeArg(IdentifierInfo &AttrName,
SourceLocation AttrNameLoc,
ParsedAttributes &Attrs,
- SourceLocation *EndLoc);
+ SourceLocation *EndLoc,
+ IdentifierInfo *ScopeName,
+ SourceLocation ScopeLoc,
+ AttributeList::Syntax Syntax);
void ParseTypeofSpecifier(DeclSpec &DS);
SourceLocation ParseDecltypeSpecifier(DeclSpec &DS);
@@ -2019,7 +2157,7 @@ private:
ExprResult ParseAlignArgument(SourceLocation Start,
SourceLocation &EllipsisLoc);
void ParseAlignmentSpecifier(ParsedAttributes &Attrs,
- SourceLocation *endLoc = 0);
+ SourceLocation *endLoc = nullptr);
VirtSpecifiers::Specifier isCXX11VirtSpecifier(const Token &Tok) const;
VirtSpecifiers::Specifier isCXX11VirtSpecifier() const {
@@ -2090,6 +2228,7 @@ private:
SmallVectorImpl<DeclaratorChunk::ParamInfo> &ParamInfo,
SourceLocation &EllipsisLoc);
void ParseBracketDeclarator(Declarator &D);
+ void ParseMisplacedBracketDeclarator(Declarator &D);
//===--------------------------------------------------------------------===//
// C++ 7: Declarations [dcl.dcl]
@@ -2123,7 +2262,7 @@ private:
const ParsedTemplateInfo &TemplateInfo,
SourceLocation &DeclEnd,
ParsedAttributesWithRange &attrs,
- Decl **OwnedType = 0);
+ Decl **OwnedType = nullptr);
Decl *ParseUsingDirective(unsigned Context,
SourceLocation UsingLoc,
SourceLocation &DeclEnd,
@@ -2133,7 +2272,7 @@ private:
SourceLocation UsingLoc,
SourceLocation &DeclEnd,
AccessSpecifier AS = AS_none,
- Decl **OwnedType = 0);
+ Decl **OwnedType = nullptr);
Decl *ParseStaticAssertDeclaration(SourceLocation &DeclEnd);
Decl *ParseNamespaceAlias(SourceLocation NamespaceLoc,
SourceLocation AliasLoc, IdentifierInfo *Alias,
@@ -2154,9 +2293,13 @@ private:
Decl *TagDecl);
ExprResult ParseCXXMemberInitializer(Decl *D, bool IsFunction,
SourceLocation &EqualLoc);
+ void ParseCXXMemberDeclaratorBeforeInitializer(Declarator &DeclaratorInfo,
+ VirtSpecifiers &VS,
+ ExprResult &BitfieldSize,
+ LateParsedAttrList &LateAttrs);
void ParseCXXClassMemberDeclaration(AccessSpecifier AS, AttributeList *Attr,
- const ParsedTemplateInfo &TemplateInfo = ParsedTemplateInfo(),
- ParsingDeclRAIIObject *DiagsFromTParams = 0);
+ const ParsedTemplateInfo &TemplateInfo = ParsedTemplateInfo(),
+ ParsingDeclRAIIObject *DiagsFromTParams = nullptr);
void ParseConstructorInitializer(Decl *ConstructorDecl);
MemInitResult ParseMemInitializer(Decl *ConstructorDecl);
void HandleMemberFunctionDeclDelays(Declarator& DeclaratorInfo,
@@ -2197,7 +2340,12 @@ private:
SmallVectorImpl<Expr *> &VarList,
bool AllowScopeSpecifier);
/// \brief Parses declarative or executable directive.
- StmtResult ParseOpenMPDeclarativeOrExecutableDirective();
+ ///
+ /// \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.
@@ -2217,6 +2365,17 @@ private:
/// \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.
@@ -2236,9 +2395,9 @@ private:
// C++ 14.1: Template Parameters [temp.param]
Decl *ParseDeclarationStartingWithTemplate(unsigned Context,
- SourceLocation &DeclEnd,
- AccessSpecifier AS = AS_none,
- AttributeList *AccessAttrs = 0);
+ SourceLocation &DeclEnd,
+ AccessSpecifier AS = AS_none,
+ AttributeList *AccessAttrs = nullptr);
Decl *ParseTemplateDeclarationOrSpecialization(unsigned Context,
SourceLocation &DeclEnd,
AccessSpecifier AS,
@@ -2249,7 +2408,7 @@ private:
ParsingDeclRAIIObject &DiagsFromParams,
SourceLocation &DeclEnd,
AccessSpecifier AS=AS_none,
- AttributeList *AccessAttrs = 0);
+ AttributeList *AccessAttrs = nullptr);
bool ParseTemplateParameters(unsigned Depth,
SmallVectorImpl<Decl*> &TemplateParams,
SourceLocation &LAngleLoc,
@@ -2261,6 +2420,12 @@ private:
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;
@@ -2295,9 +2460,7 @@ private:
DeclGroupPtrTy ParseModuleImport(SourceLocation AtLoc);
//===--------------------------------------------------------------------===//
- // GNU G++: Type Traits [Type-Traits.html in the GCC manual]
- ExprResult ParseUnaryTypeTrait();
- ExprResult ParseBinaryTypeTrait();
+ // C++11/G++: Type Traits [Type-Traits.html in the GCC manual]
ExprResult ParseTypeTrait();
//===--------------------------------------------------------------------===//
@@ -2307,14 +2470,13 @@ private:
//===--------------------------------------------------------------------===//
// Preprocessor code-completion pass-through
- virtual void CodeCompleteDirective(bool InConditional);
- virtual void CodeCompleteInConditionalExclusion();
- virtual void CodeCompleteMacroName(bool IsDefinition);
- virtual void CodeCompletePreprocessorExpression();
- virtual void CodeCompleteMacroArgument(IdentifierInfo *Macro,
- MacroInfo *MacroInfo,
- unsigned ArgumentIndex);
- virtual void CodeCompleteNaturalLanguage();
+ 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
diff --git a/include/clang/Rewrite/Core/HTMLRewrite.h b/include/clang/Rewrite/Core/HTMLRewrite.h
index 3cd04615d826..ec061dc7dba8 100644
--- a/include/clang/Rewrite/Core/HTMLRewrite.h
+++ b/include/clang/Rewrite/Core/HTMLRewrite.h
@@ -63,7 +63,7 @@ namespace html {
void AddLineNumbers(Rewriter& R, FileID FID);
void AddHeaderFooterInternalBuiltinCSS(Rewriter& R, FileID FID,
- const char *title = NULL);
+ const char *title = nullptr);
/// SyntaxHighlight - Relex the specified FileID and annotate the HTML with
/// information about keywords, comments, etc.
diff --git a/include/clang/Rewrite/Core/RewriteRope.h b/include/clang/Rewrite/Core/RewriteRope.h
index a5192ef1ea1c..f312aedc082a 100644
--- a/include/clang/Rewrite/Core/RewriteRope.h
+++ b/include/clang/Rewrite/Core/RewriteRope.h
@@ -14,6 +14,7 @@
#ifndef LLVM_CLANG_REWRITEROPE_H
#define LLVM_CLANG_REWRITEROPE_H
+#include "llvm/ADT/StringRef.h"
#include "llvm/Support/Compiler.h"
#include <cassert>
#include <cstddef>
@@ -60,7 +61,7 @@ namespace clang {
unsigned StartOffs;
unsigned EndOffs;
- RopePiece() : StrData(0), StartOffs(0), EndOffs(0) {}
+ RopePiece() : StrData(nullptr), StartOffs(0), EndOffs(0) {}
RopePiece(RopeRefCountString *Str, unsigned Start, unsigned End)
: StrData(Str), StartOffs(Start), EndOffs(End) {
@@ -121,7 +122,8 @@ namespace clang {
// begin iterator.
RopePieceBTreeIterator(const void /*RopePieceBTreeNode*/ *N);
// end iterator
- RopePieceBTreeIterator() : CurNode(0), CurPiece(0), CurChar(0) {}
+ RopePieceBTreeIterator()
+ : CurNode(nullptr), CurPiece(nullptr), CurChar(0) {}
char operator*() const {
return (*CurPiece)[CurChar];
@@ -144,7 +146,11 @@ namespace clang {
inline RopePieceBTreeIterator operator++(int) { // Postincrement
RopePieceBTreeIterator tmp = *this; ++*this; return tmp;
}
- private:
+
+ llvm::StringRef piece() const {
+ return llvm::StringRef(&(*CurPiece)[0], CurPiece->size());
+ }
+
void MoveToNextPiece();
};
@@ -190,9 +196,9 @@ class RewriteRope {
enum { AllocChunkSize = 4080 };
public:
- RewriteRope() : AllocBuffer(0), AllocOffs(AllocChunkSize) {}
+ RewriteRope() : AllocBuffer(nullptr), AllocOffs(AllocChunkSize) {}
RewriteRope(const RewriteRope &RHS)
- : Chunks(RHS.Chunks), AllocBuffer(0), AllocOffs(AllocChunkSize) {
+ : Chunks(RHS.Chunks), AllocBuffer(nullptr), AllocOffs(AllocChunkSize) {
}
~RewriteRope() {
diff --git a/include/clang/Rewrite/Core/Rewriter.h b/include/clang/Rewrite/Core/Rewriter.h
index 2d2917b910b9..7b22fb49bc2c 100644
--- a/include/clang/Rewrite/Core/Rewriter.h
+++ b/include/clang/Rewrite/Core/Rewriter.h
@@ -151,7 +151,7 @@ public:
explicit Rewriter(SourceManager &SM, const LangOptions &LO)
: SourceMgr(&SM), LangOpts(&LO) {}
- explicit Rewriter() : SourceMgr(0), LangOpts(0) {}
+ explicit Rewriter() : SourceMgr(nullptr), LangOpts(nullptr) {}
void setSourceMgr(SourceManager &SM, const LangOptions &LO) {
SourceMgr = &SM;
@@ -275,7 +275,7 @@ public:
const RewriteBuffer *getRewriteBufferFor(FileID FID) const {
std::map<FileID, RewriteBuffer>::const_iterator I =
RewriteBuffers.find(FID);
- return I == RewriteBuffers.end() ? 0 : &I->second;
+ return I == RewriteBuffers.end() ? nullptr : &I->second;
}
// Iterators over rewrite buffers.
diff --git a/include/clang/Rewrite/Core/TokenRewriter.h b/include/clang/Rewrite/Core/TokenRewriter.h
index ec0bb5ba0827..c313b453d984 100644
--- a/include/clang/Rewrite/Core/TokenRewriter.h
+++ b/include/clang/Rewrite/Core/TokenRewriter.h
@@ -17,9 +17,9 @@
#include "clang/Basic/SourceLocation.h"
#include "clang/Lex/Token.h"
-#include "llvm/ADT/OwningPtr.h"
#include <list>
#include <map>
+#include <memory>
namespace clang {
class LangOptions;
@@ -41,7 +41,7 @@ namespace clang {
/// ScratchBuf - This is the buffer that we create scratch tokens from.
///
- OwningPtr<ScratchBuffer> ScratchBuf;
+ std::unique_ptr<ScratchBuffer> ScratchBuf;
TokenRewriter(const TokenRewriter &) LLVM_DELETED_FUNCTION;
void operator=(const TokenRewriter &) LLVM_DELETED_FUNCTION;
diff --git a/include/clang/Rewrite/Frontend/FixItRewriter.h b/include/clang/Rewrite/Frontend/FixItRewriter.h
index 423f0667cde0..3ad8f408af6e 100644
--- a/include/clang/Rewrite/Frontend/FixItRewriter.h
+++ b/include/clang/Rewrite/Frontend/FixItRewriter.h
@@ -90,7 +90,7 @@ public:
/// \brief Check whether there are modifications for a given file.
bool IsModified(FileID ID) const {
- return Rewrite.getRewriteBufferFor(ID) != NULL;
+ return Rewrite.getRewriteBufferFor(ID) != nullptr;
}
// Iteration over files with changes.
@@ -106,18 +106,18 @@ public:
///
/// \returns true if there was an error, false otherwise.
bool WriteFixedFiles(
- std::vector<std::pair<std::string, std::string> > *RewrittenFiles = 0);
+ 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.
- virtual bool IncludeInDiagnosticCounts() const;
+ bool IncludeInDiagnosticCounts() const override;
/// HandleDiagnostic - Handle this diagnostic, reporting it to the user or
/// capturing it to a log as needed.
- virtual void HandleDiagnostic(DiagnosticsEngine::Level DiagLevel,
- const Diagnostic &Info);
+ void HandleDiagnostic(DiagnosticsEngine::Level DiagLevel,
+ const Diagnostic &Info) override;
/// \brief Emit a diagnostic via the adapted diagnostic client.
void Diag(SourceLocation Loc, unsigned DiagID);
diff --git a/include/clang/Rewrite/Frontend/FrontendActions.h b/include/clang/Rewrite/Frontend/FrontendActions.h
index ea876d9980f6..fc792707487d 100644
--- a/include/clang/Rewrite/Frontend/FrontendActions.h
+++ b/include/clang/Rewrite/Frontend/FrontendActions.h
@@ -22,24 +22,24 @@ class FixItOptions;
class HTMLPrintAction : public ASTFrontendAction {
protected:
- virtual ASTConsumer *CreateASTConsumer(CompilerInstance &CI,
- StringRef InFile);
+ ASTConsumer *CreateASTConsumer(CompilerInstance &CI,
+ StringRef InFile) override;
};
class FixItAction : public ASTFrontendAction {
protected:
- OwningPtr<FixItRewriter> Rewriter;
- OwningPtr<FixItOptions> FixItOpts;
+ std::unique_ptr<FixItRewriter> Rewriter;
+ std::unique_ptr<FixItOptions> FixItOpts;
- virtual ASTConsumer *CreateASTConsumer(CompilerInstance &CI,
- StringRef InFile);
+ ASTConsumer *CreateASTConsumer(CompilerInstance &CI,
+ StringRef InFile) override;
- virtual bool BeginSourceFileAction(CompilerInstance &CI,
- StringRef Filename);
+ bool BeginSourceFileAction(CompilerInstance &CI,
+ StringRef Filename) override;
- virtual void EndSourceFileAction();
+ void EndSourceFileAction() override;
- virtual bool hasASTFileSupport() const { return false; }
+ bool hasASTFileSupport() const override { return false; }
public:
FixItAction();
@@ -54,28 +54,28 @@ public:
: WrapperFrontendAction(WrappedAction) {}
protected:
- virtual bool BeginInvocation(CompilerInstance &CI);
+ bool BeginInvocation(CompilerInstance &CI) override;
};
class RewriteObjCAction : public ASTFrontendAction {
protected:
- virtual ASTConsumer *CreateASTConsumer(CompilerInstance &CI,
- StringRef InFile);
+ ASTConsumer *CreateASTConsumer(CompilerInstance &CI,
+ StringRef InFile) override;
};
class RewriteMacrosAction : public PreprocessorFrontendAction {
protected:
- void ExecuteAction();
+ void ExecuteAction() override;
};
class RewriteTestAction : public PreprocessorFrontendAction {
protected:
- void ExecuteAction();
+ void ExecuteAction() override;
};
class RewriteIncludesAction : public PreprocessorFrontendAction {
protected:
- void ExecuteAction();
+ void ExecuteAction() override;
};
} // end namespace clang
diff --git a/include/clang/Sema/AttributeList.h b/include/clang/Sema/AttributeList.h
index 508064def2ca..c21c19fd55c9 100644
--- a/include/clang/Sema/AttributeList.h
+++ b/include/clang/Sema/AttributeList.h
@@ -18,8 +18,9 @@
#include "clang/Basic/SourceLocation.h"
#include "clang/Basic/VersionTuple.h"
#include "clang/Sema/Ownership.h"
-#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/PointerUnion.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/Triple.h"
#include "llvm/Support/Allocator.h"
#include <cassert>
@@ -79,7 +80,9 @@ public:
/// __declspec(...)
AS_Declspec,
/// __ptr16, alignas(...), etc.
- AS_Keyword
+ AS_Keyword,
+ /// #pragma ...
+ AS_Pragma
};
private:
@@ -217,7 +220,7 @@ private:
ScopeLoc(scopeLoc), EllipsisLoc(ellipsisLoc), NumArgs(numArgs),
SyntaxUsed(syntaxUsed), Invalid(false), UsedAsTypeAttr(false),
IsAvailability(false), IsTypeTagForDatatype(false), IsProperty(false),
- HasParsedType(false), NextInPosition(0), NextInPool(0) {
+ HasParsedType(false), NextInPosition(nullptr), NextInPool(nullptr) {
if (numArgs) memcpy(getArgsBuffer(), args, numArgs * sizeof(ArgsUnion));
AttrKind = getKind(getName(), getScopeName(), syntaxUsed);
}
@@ -236,7 +239,7 @@ private:
Invalid(false), UsedAsTypeAttr(false), IsAvailability(true),
IsTypeTagForDatatype(false), IsProperty(false), HasParsedType(false),
UnavailableLoc(unavailable), MessageExpr(messageExpr),
- NextInPosition(0), NextInPool(0) {
+ NextInPosition(nullptr), NextInPool(nullptr) {
ArgsUnion PVal(Parm);
memcpy(getArgsBuffer(), &PVal, sizeof(ArgsUnion));
new (&getAvailabilitySlot(IntroducedSlot)) AvailabilityChange(introduced);
@@ -245,6 +248,26 @@ private:
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,
@@ -254,7 +277,7 @@ private:
ScopeLoc(scopeLoc), EllipsisLoc(), NumArgs(1), SyntaxUsed(syntaxUsed),
Invalid(false), UsedAsTypeAttr(false), IsAvailability(false),
IsTypeTagForDatatype(true), IsProperty(false), HasParsedType(false),
- NextInPosition(NULL), NextInPool(NULL) {
+ NextInPosition(nullptr), NextInPool(nullptr) {
ArgsUnion PVal(ArgKind);
memcpy(getArgsBuffer(), &PVal, sizeof(ArgsUnion));
TypeTagForDatatypeData &ExtraData = getTypeTagForDatatypeDataSlot();
@@ -272,7 +295,7 @@ private:
ScopeLoc(scopeLoc), EllipsisLoc(), NumArgs(0), SyntaxUsed(syntaxUsed),
Invalid(false), UsedAsTypeAttr(false), IsAvailability(false),
IsTypeTagForDatatype(false), IsProperty(false), HasParsedType(true),
- NextInPosition(0), NextInPool(0) {
+ NextInPosition(nullptr), NextInPool(nullptr) {
new (&getTypeBuffer()) ParsedType(typeArg);
AttrKind = getKind(getName(), getScopeName(), syntaxUsed);
}
@@ -286,7 +309,7 @@ private:
ScopeLoc(scopeLoc), EllipsisLoc(), NumArgs(0), SyntaxUsed(syntaxUsed),
Invalid(false), UsedAsTypeAttr(false), IsAvailability(false),
IsTypeTagForDatatype(false), IsProperty(true), HasParsedType(false),
- NextInPosition(0), NextInPool(0) {
+ NextInPosition(nullptr), NextInPool(nullptr) {
new (&getPropertyDataBuffer()) PropertyData(getterId, setterId);
AttrKind = getKind(getName(), getScopeName(), syntaxUsed);
}
@@ -368,44 +391,6 @@ public:
return getArg(Arg).get<IdentifierLoc*>();
}
- class arg_iterator {
- ArgsUnion const *X;
- unsigned Idx;
- public:
- arg_iterator(ArgsUnion const *x, unsigned idx) : X(x), Idx(idx) {}
-
- arg_iterator& operator++() {
- ++Idx;
- return *this;
- }
-
- bool operator==(const arg_iterator& I) const {
- assert (X == I.X &&
- "compared arg_iterators are for different argument lists");
- return Idx == I.Idx;
- }
-
- bool operator!=(const arg_iterator& I) const {
- return !operator==(I);
- }
-
- ArgsUnion operator*() const {
- return X[Idx];
- }
-
- unsigned getArgNum() const {
- return Idx+1;
- }
- };
-
- arg_iterator arg_begin() const {
- return arg_iterator(getArgsBuffer(), 0);
- }
-
- arg_iterator arg_end() const {
- return arg_iterator(getArgsBuffer(), NumArgs);
- }
-
const AvailabilityChange &getAvailabilityIntroduced() const {
assert(getKind() == AT_Availability && "Not an availability attribute");
return getAvailabilitySlot(IntroducedSlot);
@@ -464,9 +449,23 @@ public:
/// to pretty print itself.
unsigned getAttributeSpellingListIndex() const;
+ bool isTargetSpecificAttr() const;
+ bool isTypeAttr() const;
+
bool hasCustomParsing() const;
unsigned getMinArgs() const;
unsigned getMaxArgs() const;
+ bool diagnoseAppertainsTo(class Sema &S, const Decl *D) const;
+ bool diagnoseLangOpts(class Sema &S) const;
+ bool existsInTarget(const llvm::Triple &T) 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
@@ -549,11 +548,11 @@ class AttributePool {
public:
/// Create a new pool for a factory.
- AttributePool(AttributeFactory &factory) : Factory(factory), Head(0) {}
+ AttributePool(AttributeFactory &factory) : Factory(factory), Head(nullptr) {}
/// Move the given pool's allocations to this pool.
AttributePool(AttributePool &pool) : Factory(pool.Factory), Head(pool.Head) {
- pool.Head = 0;
+ pool.Head = nullptr;
}
AttributeFactory &getFactory() const { return Factory; }
@@ -561,7 +560,7 @@ public:
void clear() {
if (Head) {
Factory.reclaimPool(Head);
- Head = 0;
+ Head = nullptr;
}
}
@@ -569,7 +568,7 @@ public:
void takeAllFrom(AttributePool &pool) {
if (pool.Head) {
takePool(pool.Head);
- pool.Head = 0;
+ pool.Head = nullptr;
}
}
@@ -607,8 +606,19 @@ public:
syntax));
}
- AttributeList *createIntegerAttribute(ASTContext &C, IdentifierInfo *Name,
- SourceLocation TokLoc, int Arg);
+ 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,
@@ -647,40 +657,6 @@ public:
}
};
-/// addAttributeLists - Add two AttributeLists together
-/// The right-hand list is appended to the left-hand list, if any
-/// A pointer to the joined list is returned.
-/// Note: the lists are not left unmodified.
-inline AttributeList *addAttributeLists(AttributeList *Left,
- AttributeList *Right) {
- if (!Left)
- return Right;
-
- AttributeList *next = Left, *prev;
- do {
- prev = next;
- next = next->getNext();
- } while (next);
- prev->setNext(Right);
- return Left;
-}
-
-/// CXX11AttributeList - A wrapper around a C++11 attribute list.
-/// Stores, in addition to the list proper, whether or not an actual list was
-/// (as opposed to an empty list, which may be ill-formed in some places) and
-/// the source range of the list.
-struct CXX11AttributeList {
- AttributeList *AttrList;
- SourceRange Range;
- bool HasAttr;
- CXX11AttributeList (AttributeList *attrList, SourceRange range, bool hasAttr)
- : AttrList(attrList), Range(range), HasAttr (hasAttr) {
- }
- CXX11AttributeList ()
- : AttrList(0), Range(), HasAttr(false) {
- }
-};
-
/// ParsedAttributes - A collection of parsed attributes. Currently
/// we don't differentiate between the various attribute syntaxes,
/// which is basically silly.
@@ -690,21 +666,18 @@ struct CXX11AttributeList {
class ParsedAttributes {
public:
ParsedAttributes(AttributeFactory &factory)
- : pool(factory), list(0) {
+ : pool(factory), list(nullptr) {
}
- ParsedAttributes(ParsedAttributes &attrs)
- : pool(attrs.pool), list(attrs.list) {
- attrs.list = 0;
- }
+ ParsedAttributes(const ParsedAttributes &) LLVM_DELETED_FUNCTION;
AttributePool &getPool() const { return pool; }
- bool empty() const { return list == 0; }
+ bool empty() const { return list == nullptr; }
void add(AttributeList *newAttr) {
assert(newAttr);
- assert(newAttr->getNext() == 0);
+ assert(newAttr->getNext() == nullptr);
newAttr->setNext(list);
list = newAttr;
}
@@ -726,11 +699,11 @@ public:
void takeAllFrom(ParsedAttributes &attrs) {
addAll(attrs.list);
- attrs.list = 0;
+ attrs.list = nullptr;
pool.takeAllFrom(attrs.pool);
}
- void clear() { list = 0; pool.clear(); }
+ void clear() { list = nullptr; pool.clear(); }
AttributeList *getList() const { return list; }
/// Returns a reference to the attribute list. Try not to introduce
@@ -767,6 +740,20 @@ public:
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,
@@ -808,15 +795,6 @@ public:
return attr;
}
- AttributeList *addNewInteger(ASTContext &C, IdentifierInfo *name,
- SourceLocation loc, int arg) {
- AttributeList *attr =
- pool.createIntegerAttribute(C, name, loc, arg);
- add(attr);
- return attr;
- }
-
-
private:
mutable AttributePool pool;
AttributeList *list;
@@ -831,6 +809,42 @@ enum AttributeArgumentNType {
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,
+ ExpectedVariable,
+ ExpectedMethod,
+ ExpectedVariableFunctionOrLabel,
+ ExpectedFieldOrGlobalVar,
+ ExpectedStruct,
+ ExpectedVariableFunctionOrTag,
+ ExpectedTLSVar,
+ ExpectedVariableOrField,
+ ExpectedVariableFieldOrTag,
+ ExpectedTypeOrNamespace,
+ ExpectedObjectiveCInterface,
+ ExpectedMethodOrProperty,
+ ExpectedStructOrUnion,
+ ExpectedStructOrUnionOrClass,
+ ExpectedType,
+ ExpectedObjCInstanceMethod,
+ ExpectedObjCInterfaceDeclInitMethod,
+ ExpectedFunctionVariableOrClass,
+ ExpectedObjectiveCProtocol,
+ ExpectedFunctionGlobalVarMethodOrProperty,
+ ExpectedStructOrTypedef,
+ ExpectedObjectiveCInterfaceOrProtocol
+};
+
} // end namespace clang
#endif
diff --git a/include/clang/Sema/CodeCompleteConsumer.h b/include/clang/Sema/CodeCompleteConsumer.h
index 64de82c6b05f..92a4e9a42f15 100644
--- a/include/clang/Sema/CodeCompleteConsumer.h
+++ b/include/clang/Sema/CodeCompleteConsumer.h
@@ -397,7 +397,7 @@ public:
CodeCompletionString *Optional;
};
- Chunk() : Kind(CK_Text), Text(0) { }
+ Chunk() : Kind(CK_Text), Text(nullptr) { }
explicit Chunk(ChunkKind Kind, const char *Text = "");
@@ -575,14 +575,14 @@ public:
CodeCompletionTUInfo &CCTUInfo)
: Allocator(Allocator), CCTUInfo(CCTUInfo),
Priority(0), Availability(CXAvailability_Available),
- BriefComment(NULL) { }
+ BriefComment(nullptr) { }
CodeCompletionBuilder(CodeCompletionAllocator &Allocator,
CodeCompletionTUInfo &CCTUInfo,
unsigned Priority, CXAvailabilityKind Availability)
: Allocator(Allocator), CCTUInfo(CCTUInfo),
Priority(Priority), Availability(Availability),
- BriefComment(NULL) { }
+ BriefComment(nullptr) { }
/// \brief Retrieve the allocator into which the code completion
/// strings should be allocated.
@@ -700,7 +700,7 @@ public:
/// \brief Build a result that refers to a declaration.
CodeCompletionResult(const NamedDecl *Declaration,
unsigned Priority,
- NestedNameSpecifier *Qualifier = 0,
+ NestedNameSpecifier *Qualifier = nullptr,
bool QualifierIsInformative = false,
bool Accessible = true)
: Declaration(Declaration), Priority(Priority),
@@ -714,36 +714,34 @@ public:
/// \brief Build a result that refers to a keyword or symbol.
CodeCompletionResult(const char *Keyword, unsigned Priority = CCP_Keyword)
- : Declaration(0), Keyword(Keyword), Priority(Priority), StartParameter(0),
- Kind(RK_Keyword), CursorKind(CXCursor_NotImplemented),
+ : 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(0)
- {
- }
+ AllParametersAreInformative(false), DeclaringEntity(false),
+ Qualifier(nullptr) {}
/// \brief Build a result that refers to a macro.
CodeCompletionResult(const IdentifierInfo *Macro,
unsigned Priority = CCP_Macro)
- : Declaration(0), Macro(Macro), Priority(Priority), StartParameter(0),
+ : 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(0)
- {
- }
+ 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 = 0)
+ 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(0)
+ DeclaringEntity(false), Qualifier(nullptr)
{
}
@@ -754,7 +752,8 @@ public:
: 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(0) {
+ AllParametersAreInformative(false), DeclaringEntity(false),
+ Qualifier(nullptr) {
computeCursorKindAndAvailability();
}
@@ -966,20 +965,19 @@ public:
CCTUInfo(new GlobalCodeCompletionAllocator) {}
/// \brief Prints the finalized code-completion results.
- virtual void ProcessCodeCompleteResults(Sema &S,
- CodeCompletionContext Context,
- CodeCompletionResult *Results,
- unsigned NumResults);
+ void ProcessCodeCompleteResults(Sema &S, CodeCompletionContext Context,
+ CodeCompletionResult *Results,
+ unsigned NumResults) override;
- virtual void ProcessOverloadCandidates(Sema &S, unsigned CurrentArg,
- OverloadCandidate *Candidates,
- unsigned NumCandidates);
+ void ProcessOverloadCandidates(Sema &S, unsigned CurrentArg,
+ OverloadCandidate *Candidates,
+ unsigned NumCandidates) override;
- virtual CodeCompletionAllocator &getAllocator() {
+ CodeCompletionAllocator &getAllocator() override {
return CCTUInfo.getAllocator();
}
- virtual CodeCompletionTUInfo &getCodeCompletionTUInfo() { return CCTUInfo; }
+ CodeCompletionTUInfo &getCodeCompletionTUInfo() override { return CCTUInfo; }
};
} // end namespace clang
diff --git a/include/clang/Sema/DeclSpec.h b/include/clang/Sema/DeclSpec.h
index 8f6bd186a7dc..8364dfc4b0bb 100644
--- a/include/clang/Sema/DeclSpec.h
+++ b/include/clang/Sema/DeclSpec.h
@@ -178,9 +178,9 @@ public:
bool isNotEmpty() const { return !isEmpty(); }
/// An error occurred during parsing of the scope specifier.
- bool isInvalid() const { return isNotEmpty() && getScopeRep() == 0; }
+ 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() != 0; }
+ bool isValid() const { return isNotEmpty() && getScopeRep() != nullptr; }
/// \brief Indicate that this nested-name-specifier is invalid.
void SetInvalid(SourceRange R) {
@@ -193,7 +193,7 @@ public:
/// Deprecated. Some call sites intend isNotEmpty() while others intend
/// isValid().
- bool isSet() const { return getScopeRep() != 0; }
+ bool isSet() const { return getScopeRep() != nullptr; }
void clear() {
Range = SourceRange();
@@ -285,14 +285,6 @@ public:
static const TST TST_auto = clang::TST_auto;
static const TST TST_unknown_anytype = clang::TST_unknown_anytype;
static const TST TST_atomic = clang::TST_atomic;
- static const TST TST_image1d_t = clang::TST_image1d_t;
- static const TST TST_image1d_array_t = clang::TST_image1d_array_t;
- static const TST TST_image1d_buffer_t = clang::TST_image1d_buffer_t;
- static const TST TST_image2d_t = clang::TST_image2d_t;
- static const TST TST_image2d_array_t = clang::TST_image2d_array_t;
- static const TST TST_image3d_t = clang::TST_image3d_t;
- static const TST TST_sampler_t = clang::TST_sampler_t;
- static const TST TST_event_t = clang::TST_event_t;
static const TST TST_error = clang::TST_error;
// type-qualifiers
@@ -428,11 +420,11 @@ public:
Friend_specified(false),
Constexpr_specified(false),
Attrs(attrFactory),
- ProtocolQualifiers(0),
+ ProtocolQualifiers(nullptr),
NumProtocolQualifiers(0),
- ProtocolLocs(0),
+ ProtocolLocs(nullptr),
writtenBS(),
- ObjCQualifiers(0) {
+ ObjCQualifiers(nullptr) {
}
~DeclSpec() {
delete [] ProtocolQualifiers;
@@ -516,7 +508,8 @@ public:
bool hasTagDefinition() const;
/// \brief Turn a type-specifier-type into a string like "_Bool" or "union".
- static const char *getSpecifierName(DeclSpec::TST T);
+ 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);
@@ -604,36 +597,45 @@ public:
/// 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 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);
+ 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);
+ unsigned &DiagID, const PrintingPolicy &Policy);
bool SetTypeSpecType(TST T, SourceLocation Loc, const char *&PrevSpec,
- unsigned &DiagID, ParsedType Rep);
+ unsigned &DiagID, ParsedType Rep,
+ const PrintingPolicy &Policy);
bool SetTypeSpecType(TST T, SourceLocation Loc, const char *&PrevSpec,
- unsigned &DiagID, Decl *Rep, bool Owned);
+ unsigned &DiagID, Decl *Rep, bool Owned,
+ const PrintingPolicy &Policy);
bool SetTypeSpecType(TST T, SourceLocation TagKwLoc,
SourceLocation TagNameLoc, const char *&PrevSpec,
- unsigned &DiagID, ParsedType Rep);
+ unsigned &DiagID, ParsedType Rep,
+ const PrintingPolicy &Policy);
bool SetTypeSpecType(TST T, SourceLocation TagKwLoc,
SourceLocation TagNameLoc, const char *&PrevSpec,
- unsigned &DiagID, Decl *Rep, bool Owned);
+ unsigned &DiagID, Decl *Rep, bool Owned,
+ const PrintingPolicy &Policy);
bool SetTypeSpecType(TST T, SourceLocation Loc, const char *&PrevSpec,
- unsigned &DiagID, Expr *Rep);
+ unsigned &DiagID, Expr *Rep,
+ const PrintingPolicy &policy);
bool SetTypeAltiVecVector(bool isAltiVecVector, SourceLocation Loc,
- const char *&PrevSpec, unsigned &DiagID);
+ const char *&PrevSpec, unsigned &DiagID,
+ const PrintingPolicy &Policy);
bool SetTypeAltiVecPixel(bool isAltiVecPixel, SourceLocation Loc,
- const char *&PrevSpec, unsigned &DiagID);
+ const char *&PrevSpec, unsigned &DiagID,
+ const PrintingPolicy &Policy);
bool SetTypeAltiVecBool(bool isAltiVecBool, SourceLocation Loc,
- const char *&PrevSpec, unsigned &DiagID);
+ const char *&PrevSpec, unsigned &DiagID,
+ const PrintingPolicy &Policy);
bool SetTypeSpecError();
void UpdateDeclRep(Decl *Rep) {
assert(isDeclRep((TST) TypeSpecType));
@@ -707,22 +709,12 @@ public:
void addAttributes(AttributeList *AL) {
Attrs.addAll(AL);
}
- void setAttributes(AttributeList *AL) {
- Attrs.set(AL);
- }
bool hasAttributes() const { return !Attrs.empty(); }
ParsedAttributes &getAttributes() { return Attrs; }
const ParsedAttributes &getAttributes() const { return Attrs; }
- /// \brief Return the current attribute list and remove them from
- /// the DeclSpec so that it doesn't own them.
- ParsedAttributes takeAttributes() {
- // The non-const "copy" constructor clears the operand automatically.
- return Attrs;
- }
-
void takeAttributesFrom(ParsedAttributes &attrs) {
Attrs.takeAllFrom(attrs);
}
@@ -743,7 +735,8 @@ public:
/// 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(DiagnosticsEngine &D, Preprocessor &PP);
+ void Finish(DiagnosticsEngine &D, Preprocessor &PP,
+ const PrintingPolicy &Policy);
const WrittenBuiltinSpecs& getWrittenBuiltinSpecs() const {
return writtenBS;
@@ -798,7 +791,7 @@ public:
ObjCDeclSpec()
: objcDeclQualifier(DQ_None), PropertyAttributes(DQ_PR_noattr),
- GetterName(0), SetterName(0) { }
+ GetterName(nullptr), SetterName(nullptr) { }
ObjCDeclQualifier getObjCDeclQualifier() const { return objcDeclQualifier; }
void setObjCDeclQualifier(ObjCDeclQualifier DQVal) {
objcDeclQualifier = (ObjCDeclQualifier) (objcDeclQualifier | DQVal);
@@ -821,15 +814,15 @@ public:
void setSetterName(IdentifierInfo *name) { SetterName = name; }
private:
- // FIXME: These two are unrelated and mutially exclusive. So perhaps
- // we can put them in a union to reflect their mutual exclusiveness
+ // 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 : 6;
// NOTE: VC++ treats enums as signed, avoid using ObjCPropertyAttributeKind
unsigned PropertyAttributes : 12;
- IdentifierInfo *GetterName; // getter name of NULL if no getter
- IdentifierInfo *SetterName; // setter name of NULL if no setter
+ 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.
@@ -912,13 +905,13 @@ public:
/// \brief The location of the last token that describes this unqualified-id.
SourceLocation EndLocation;
- UnqualifiedId() : Kind(IK_Identifier), Identifier(0) { }
+ UnqualifiedId() : Kind(IK_Identifier), Identifier(nullptr) { }
/// \brief Clear out this unqualified-id, setting it to default (invalid)
/// state.
void clear() {
Kind = IK_Identifier;
- Identifier = 0;
+ Identifier = nullptr;
StartLocation = SourceLocation();
EndLocation = SourceLocation();
}
@@ -1112,7 +1105,8 @@ struct DeclaratorChunk {
};
/// ParamInfo - An array of paraminfo objects is allocated whenever a function
- /// declarator is parsed. There are two interesting styles of arguments here:
+ /// 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
@@ -1132,7 +1126,7 @@ struct DeclaratorChunk {
ParamInfo() {}
ParamInfo(IdentifierInfo *ident, SourceLocation iloc,
Decl *param,
- CachedTokens *DefArgTokens = 0)
+ CachedTokens *DefArgTokens = nullptr)
: Ident(ident), IdentLoc(iloc), Param(param),
DefaultArgTokens(DefArgTokens) {}
};
@@ -1144,7 +1138,7 @@ struct DeclaratorChunk {
struct FunctionTypeInfo : TypeInfoCommon {
/// hasPrototype - This is true if the function had at least one typed
- /// argument. If the function is () or (a,b,c), then it has no prototype,
+ /// 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;
@@ -1167,8 +1161,8 @@ struct DeclaratorChunk {
/// ExceptionSpecType - An ExceptionSpecificationType value.
unsigned ExceptionSpecType : 3;
- /// DeleteArgInfo - If this is true, we need to delete[] ArgInfo.
- unsigned DeleteArgInfo : 1;
+ /// DeleteParams - If this is true, we need to delete[] Params.
+ unsigned DeleteParams : 1;
/// HasTrailingReturnType - If this is true, a trailing return type was
/// specified.
@@ -1183,9 +1177,9 @@ struct DeclaratorChunk {
/// The location of the right parenthesis in the source.
unsigned RParenLoc;
- /// NumArgs - This is the number of formal arguments provided for the
+ /// NumParams - This is the number of formal parameters specified by the
/// declarator.
- unsigned NumArgs;
+ unsigned NumParams;
/// NumExceptions - This is the number of types in the dynamic-exception-
/// decl, if the function has one.
@@ -1213,10 +1207,10 @@ struct DeclaratorChunk {
/// \brief The location of the keyword introducing the spec, if any.
unsigned ExceptionSpecLoc;
- /// ArgInfo - This is a pointer to a new[]'d array of ParamInfo objects that
- /// describe the arguments for this function declarator. This is null if
- /// there are no arguments specified.
- ParamInfo *ArgInfo;
+ /// 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
@@ -1233,30 +1227,32 @@ struct DeclaratorChunk {
/// type specified.
UnionParsedType TrailingReturnType;
- /// \brief Reset the argument list to having zero arguments.
+ /// \brief Reset the parameter list to having zero parameters.
///
/// This is used in various places for error recovery.
- void freeArgs() {
- if (DeleteArgInfo) {
- delete[] ArgInfo;
- DeleteArgInfo = false;
+ void freeParams() {
+ for (unsigned I = 0; I < NumParams; ++I) {
+ delete Params[I].DefaultArgTokens;
+ Params[I].DefaultArgTokens = nullptr;
+ }
+ if (DeleteParams) {
+ delete[] Params;
+ DeleteParams = false;
}
- NumArgs = 0;
+ NumParams = 0;
}
void destroy() {
- if (DeleteArgInfo)
- delete[] ArgInfo;
+ if (DeleteParams)
+ delete[] Params;
if (getExceptionSpecType() == EST_Dynamic)
delete[] Exceptions;
}
/// isKNRPrototype - Return true if this is a K&R style identifier list,
/// like "void foo(a,b,c)". In a function definition, this will be followed
- /// by the argument type definitions.
- bool isKNRPrototype() const {
- return !hasPrototype && NumArgs != 0;
- }
+ /// by the parameter type definitions.
+ bool isKNRPrototype() const { return !hasPrototype && NumParams != 0; }
SourceLocation getLParenLoc() const {
return SourceLocation::getFromRawEncoding(LParenLoc);
@@ -1388,7 +1384,7 @@ struct DeclaratorChunk {
I.Ptr.ConstQualLoc = ConstQualLoc.getRawEncoding();
I.Ptr.VolatileQualLoc = VolatileQualLoc.getRawEncoding();
I.Ptr.RestrictQualLoc = RestrictQualLoc.getRawEncoding();
- I.Ptr.AttrList = 0;
+ I.Ptr.AttrList = nullptr;
return I;
}
@@ -1400,7 +1396,7 @@ struct DeclaratorChunk {
I.Loc = Loc;
I.Ref.HasRestrict = (TypeQuals & DeclSpec::TQ_restrict) != 0;
I.Ref.LValueRef = lvalue;
- I.Ref.AttrList = 0;
+ I.Ref.AttrList = nullptr;
return I;
}
@@ -1412,7 +1408,7 @@ struct DeclaratorChunk {
I.Kind = Array;
I.Loc = LBLoc;
I.EndLoc = RBLoc;
- I.Arr.AttrList = 0;
+ I.Arr.AttrList = nullptr;
I.Arr.TypeQuals = TypeQuals;
I.Arr.hasStatic = isStatic;
I.Arr.isStar = isStar;
@@ -1422,10 +1418,10 @@ struct DeclaratorChunk {
/// 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,
+ static DeclaratorChunk getFunction(bool HasProto,
+ bool IsAmbiguous,
SourceLocation LParenLoc,
- ParamInfo *ArgInfo, unsigned NumArgs,
+ ParamInfo *Params, unsigned NumParams,
SourceLocation EllipsisLoc,
SourceLocation RParenLoc,
unsigned TypeQuals,
@@ -1453,7 +1449,7 @@ struct DeclaratorChunk {
I.Kind = BlockPointer;
I.Loc = Loc;
I.Cls.TypeQuals = TypeQuals;
- I.Cls.AttrList = 0;
+ I.Cls.AttrList = nullptr;
return I;
}
@@ -1464,7 +1460,7 @@ struct DeclaratorChunk {
I.Kind = MemberPointer;
I.Loc = Loc;
I.Mem.TypeQuals = TypeQuals;
- I.Mem.AttrList = 0;
+ I.Mem.AttrList = nullptr;
new (I.Mem.ScopeMem.Mem) CXXScopeSpec(SS);
return I;
}
@@ -1476,7 +1472,7 @@ struct DeclaratorChunk {
I.Kind = Paren;
I.Loc = LParenLoc;
I.EndLoc = RParenLoc;
- I.Common.AttrList = 0;
+ I.Common.AttrList = nullptr;
return I;
}
@@ -1594,7 +1590,7 @@ public:
InvalidType(DS.getTypeSpecType() == DeclSpec::TST_error),
GroupingParens(false), FunctionDefinition(FDK_Declaration),
Redeclaration(false),
- Attrs(ds.getAttributePool().getFactory()), AsmLabel(0),
+ Attrs(ds.getAttributePool().getFactory()), AsmLabel(nullptr),
InlineParamsUsed(false), Extension(false) {
}
@@ -1671,7 +1667,7 @@ public:
DeclTypeInfo[i].destroy();
DeclTypeInfo.clear();
Attrs.clear();
- AsmLabel = 0;
+ AsmLabel = nullptr;
InlineParamsUsed = false;
CommaLoc = SourceLocation();
EllipsisLoc = SourceLocation();
@@ -1844,7 +1840,7 @@ public:
if (Name.getKind() == UnqualifiedId::IK_Identifier)
return Name.Identifier;
- return 0;
+ return nullptr;
}
SourceLocation getIdentifierLoc() const { return Name.StartLocation; }
@@ -1899,7 +1895,7 @@ public:
if (!DeclTypeInfo[i].isParen())
return &DeclTypeInfo[i];
}
- return 0;
+ return nullptr;
}
/// Return the outermost (furthest from the declarator) chunk of
@@ -1910,7 +1906,7 @@ public:
if (!DeclTypeInfo[i-1].isParen())
return &DeclTypeInfo[i-1];
}
- return 0;
+ return nullptr;
}
/// isArrayOfUnknownBound - This method returns true if the declarator
@@ -2121,7 +2117,7 @@ struct FieldDeclarator {
Declarator D;
Expr *BitfieldSize;
explicit FieldDeclarator(const DeclSpec &DS)
- : D(DS, Declarator::MemberContext), BitfieldSize(0) { }
+ : D(DS, Declarator::MemberContext), BitfieldSize(nullptr) { }
};
/// \brief Represents a C++11 virt-specifier-seq.
@@ -2139,6 +2135,8 @@ public:
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; }
@@ -2159,25 +2157,23 @@ private:
SourceLocation LastLocation;
};
-/// \brief An individual capture in a lambda introducer.
-struct LambdaCapture {
- LambdaCaptureKind Kind;
- SourceLocation Loc;
- IdentifierInfo *Id;
- SourceLocation EllipsisLoc;
- ExprResult Init;
- ParsedType InitCaptureType;
- LambdaCapture(LambdaCaptureKind Kind, SourceLocation Loc,
- IdentifierInfo* Id,
- SourceLocation EllipsisLoc,
- ExprResult Init, ParsedType InitCaptureType)
- : Kind(Kind), Loc(Loc), Id(Id), EllipsisLoc(EllipsisLoc), Init(Init),
- InitCaptureType(InitCaptureType)
- {}
-};
-
/// \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;
+ ExprResult Init;
+ ParsedType InitCaptureType;
+ LambdaCapture(LambdaCaptureKind Kind, SourceLocation Loc,
+ IdentifierInfo *Id, SourceLocation EllipsisLoc,
+ ExprResult Init, ParsedType InitCaptureType)
+ : Kind(Kind), Loc(Loc), Id(Id), EllipsisLoc(EllipsisLoc), Init(Init),
+ InitCaptureType(InitCaptureType) {}
+ };
+
SourceRange Range;
SourceLocation DefaultLoc;
LambdaCaptureDefault Default;
diff --git a/include/clang/Sema/DelayedDiagnostic.h b/include/clang/Sema/DelayedDiagnostic.h
index 4f4a87fe11f2..85551f8db036 100644
--- a/include/clang/Sema/DelayedDiagnostic.h
+++ b/include/clang/Sema/DelayedDiagnostic.h
@@ -113,7 +113,7 @@ private:
/// the complete parsing of the current declaration.
class DelayedDiagnostic {
public:
- enum DDKind { Deprecation, Access, ForbiddenType };
+ enum DDKind { Deprecation, Unavailable, Access, ForbiddenType };
unsigned char Kind; // actually a DDKind
bool Triggered;
@@ -122,11 +122,14 @@ public:
void Destroy();
- static DelayedDiagnostic makeDeprecation(SourceLocation Loc,
- const NamedDecl *D,
- const ObjCInterfaceDecl *UnknownObjCClass,
- const ObjCPropertyDecl *ObjCProperty,
- StringRef Msg);
+ 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) {
@@ -162,12 +165,14 @@ public:
}
const NamedDecl *getDeprecationDecl() const {
- assert(Kind == Deprecation && "Not a deprecation diagnostic.");
+ assert((Kind == Deprecation || Kind == Unavailable) &&
+ "Not a deprecation diagnostic.");
return DeprecationData.Decl;
}
StringRef getDeprecationMessage() const {
- assert(Kind == Deprecation && "Not a deprecation diagnostic.");
+ assert((Kind == Deprecation || Kind == Unavailable) &&
+ "Not a deprecation diagnostic.");
return StringRef(DeprecationData.Message,
DeprecationData.MessageLen);
}
@@ -198,6 +203,10 @@ public:
const ObjCPropertyDecl *getObjCProperty() const {
return DeprecationData.ObjCProperty;
}
+
+ bool getObjCPropertyAccess() const {
+ return DeprecationData.ObjCPropertyAccess;
+ }
private:
@@ -207,6 +216,7 @@ private:
const ObjCPropertyDecl *ObjCProperty;
const char *Message;
size_t MessageLen;
+ bool ObjCPropertyAccess;
};
struct FTD {
@@ -244,7 +254,7 @@ public:
/// Does this pool, or any of its ancestors, contain any diagnostics?
bool empty() const {
- return (Diagnostics.empty() && (Parent == NULL || Parent->empty()));
+ return (Diagnostics.empty() && (!Parent || Parent->empty()));
}
/// Add a diagnostic to this pool.
@@ -257,7 +267,7 @@ public:
if (pool.Diagnostics.empty()) return;
if (Diagnostics.empty()) {
- Diagnostics = llvm_move(pool.Diagnostics);
+ Diagnostics = std::move(pool.Diagnostics);
} else {
Diagnostics.append(pool.pool_begin(), pool.pool_end());
}
diff --git a/include/clang/Sema/IdentifierResolver.h b/include/clang/Sema/IdentifierResolver.h
index 99d94a1fed85..b2404bc14b93 100644
--- a/include/clang/Sema/IdentifierResolver.h
+++ b/include/clang/Sema/IdentifierResolver.h
@@ -150,11 +150,14 @@ public:
/// if 'D' is in Scope 'S', otherwise 'S' is ignored and isDeclInScope returns
/// true if 'D' belongs to the given declaration context.
///
- /// \param ExplicitInstantiationOrSpecialization When true, we are checking
- /// whether the declaration is in scope for the purposes of explicit template
- /// instantiation or specialization. The default is false.
- bool isDeclInScope(Decl *D, DeclContext *Ctx, Scope *S = 0,
- bool ExplicitInstantiationOrSpecialization = false) const;
+ /// \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);
diff --git a/include/clang/Sema/Initialization.h b/include/clang/Sema/Initialization.h
index 83fb2be5f15f..9f342b2407aa 100644
--- a/include/clang/Sema/Initialization.h
+++ b/include/clang/Sema/Initialization.h
@@ -103,6 +103,9 @@ private:
/// \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,
@@ -155,19 +158,19 @@ private:
struct C Capture;
};
- InitializedEntity() { }
+ InitializedEntity() : ManglingNumber(0) {}
/// \brief Create the initialization entity for a variable.
InitializedEntity(VarDecl *Var)
- : Kind(EK_Variable), Parent(0), Type(Var->getType()),
- VariableOrMember(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(0), Type(Type)
+ : Kind(Kind), Parent(nullptr), Type(Type), ManglingNumber(0)
{
LocAndNRVO.Location = Loc.getRawEncoding();
LocAndNRVO.NRVO = NRVO;
@@ -176,7 +179,7 @@ private:
/// \brief Create the initialization entity for a member subobject.
InitializedEntity(FieldDecl *Member, const InitializedEntity *Parent)
: Kind(EK_Member), Parent(Parent), Type(Member->getType()),
- VariableOrMember(Member) { }
+ ManglingNumber(0), VariableOrMember(Member) { }
/// \brief Create the initialization entity for an array element.
InitializedEntity(ASTContext &Context, unsigned Index,
@@ -184,7 +187,8 @@ private:
/// \brief Create the initialization entity for a lambda capture.
InitializedEntity(IdentifierInfo *VarID, QualType FieldType, SourceLocation Loc)
- : Kind(EK_LambdaCapture), Parent(0), Type(FieldType)
+ : Kind(EK_LambdaCapture), Parent(nullptr), Type(FieldType),
+ ManglingNumber(0)
{
Capture.VarID = VarID;
Capture.Location = Loc.getRawEncoding();
@@ -214,7 +218,7 @@ public:
Entity.Kind = EK_Parameter;
Entity.Type =
Context.getVariableArrayDecayedType(Type.getUnqualifiedType());
- Entity.Parent = 0;
+ Entity.Parent = nullptr;
Entity.Parameter
= (static_cast<uintptr_t>(Consumed) | reinterpret_cast<uintptr_t>(Parm));
return Entity;
@@ -228,7 +232,7 @@ public:
InitializedEntity Entity;
Entity.Kind = EK_Parameter;
Entity.Type = Context.getVariableArrayDecayedType(Type);
- Entity.Parent = 0;
+ Entity.Parent = nullptr;
Entity.Parameter = (Consumed);
return Entity;
}
@@ -258,7 +262,7 @@ public:
/// \brief Create the initialization entity for a temporary.
static InitializedEntity InitializeTemporary(QualType Type) {
InitializedEntity Result(EK_Temporary, SourceLocation(), Type);
- Result.TypeInfo = 0;
+ Result.TypeInfo = nullptr;
return Result;
}
@@ -290,14 +294,16 @@ public:
}
/// \brief Create the initialization entity for a member subobject.
- static InitializedEntity InitializeMember(FieldDecl *Member,
- const InitializedEntity *Parent = 0) {
+ 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 = 0) {
+ static InitializedEntity
+ InitializeMember(IndirectFieldDecl *Member,
+ const InitializedEntity *Parent = nullptr) {
return InitializedEntity(Member->getAnonField(), Parent);
}
@@ -341,7 +347,7 @@ public:
if (Kind == EK_Temporary || Kind == EK_CompoundLiteralInit)
return TypeInfo;
- return 0;
+ return nullptr;
}
/// \brief Retrieve the name of the entity being initialized.
@@ -395,6 +401,13 @@ public:
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) {
@@ -418,6 +431,8 @@ public:
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;
@@ -648,22 +663,25 @@ public:
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
+ /// \brief Perform list-initialization without a constructor.
SK_ListInitialization,
- /// \brief Perform list-initialization with a constructor.
- SK_ListConstructorCall,
/// \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
@@ -687,6 +705,9 @@ public:
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.
@@ -843,17 +864,17 @@ public:
///
/// \param Args the argument(s) provided for initialization.
///
- /// \param InInitList true if we are initializing from an expression within
- /// an initializer list. This disallows narrowing conversions in C++11
- /// onwards.
+ /// \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 InInitList = false);
+ bool TopLevelOfInitList = false);
void InitializeFrom(Sema &S, const InitializedEntity &Entity,
const InitializationKind &Kind, MultiExprArg Args,
- bool InInitList);
+ bool TopLevelOfInitList);
~InitializationSequence();
@@ -882,7 +903,7 @@ public:
const InitializedEntity &Entity,
const InitializationKind &Kind,
MultiExprArg Args,
- QualType *ResultType = 0);
+ QualType *ResultType = nullptr);
/// \brief Diagnose an potentially-invalid initialization sequence.
///
@@ -980,7 +1001,11 @@ public:
/// 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
diff --git a/include/clang/Sema/Lookup.h b/include/clang/Sema/Lookup.h
index 105c8791e222..00cc164d964c 100644
--- a/include/clang/Sema/Lookup.h
+++ b/include/clang/Sema/Lookup.h
@@ -130,8 +130,8 @@ public:
Sema::LookupNameKind LookupKind,
Sema::RedeclarationKind Redecl = Sema::NotForRedeclaration)
: ResultKind(NotFound),
- Paths(0),
- NamingClass(0),
+ Paths(nullptr),
+ NamingClass(nullptr),
SemaRef(SemaRef),
NameInfo(NameInfo),
LookupKind(LookupKind),
@@ -152,8 +152,8 @@ public:
SourceLocation NameLoc, Sema::LookupNameKind LookupKind,
Sema::RedeclarationKind Redecl = Sema::NotForRedeclaration)
: ResultKind(NotFound),
- Paths(0),
- NamingClass(0),
+ Paths(nullptr),
+ NamingClass(nullptr),
SemaRef(SemaRef),
NameInfo(Name, NameLoc),
LookupKind(LookupKind),
@@ -172,8 +172,8 @@ public:
/// disabled.
LookupResult(TemporaryToken _, const LookupResult &Other)
: ResultKind(NotFound),
- Paths(0),
- NamingClass(0),
+ Paths(nullptr),
+ NamingClass(nullptr),
SemaRef(Other.SemaRef),
NameInfo(Other.NameInfo),
LookupKind(Other.LookupKind),
@@ -259,7 +259,7 @@ public:
}
LookupResultKind getResultKind() const {
- sanity();
+ assert(sanity());
return ResultKind;
}
@@ -303,7 +303,7 @@ public:
/// if there is one.
NamedDecl *getAcceptableDecl(NamedDecl *D) const {
if (!D->isInIdentifierNamespace(IDNS))
- return 0;
+ return nullptr;
if (isHiddenDeclarationVisible() || isVisible(SemaRef, D))
return D;
@@ -324,7 +324,7 @@ public:
/// \brief Returns whether these results arose from performing a
/// lookup into a class.
bool isClassLookup() const {
- return NamingClass != 0;
+ return NamingClass != nullptr;
}
/// \brief Returns the 'naming class' for this lookup, i.e. the
@@ -421,7 +421,7 @@ public:
if (Paths) {
deletePaths(Paths);
- Paths = 0;
+ Paths = nullptr;
}
} else {
AmbiguityKind SavedAK = Ambiguity;
@@ -434,14 +434,14 @@ public:
Ambiguity = SavedAK;
} else if (Paths) {
deletePaths(Paths);
- Paths = 0;
+ Paths = nullptr;
}
}
}
template <class DeclClass>
DeclClass *getAsSingle() const {
- if (getResultKind() != Found) return 0;
+ if (getResultKind() != Found) return nullptr;
return dyn_cast<DeclClass>(getFoundDecl());
}
@@ -491,8 +491,8 @@ public:
ResultKind = NotFound;
Decls.clear();
if (Paths) deletePaths(Paths);
- Paths = NULL;
- NamingClass = 0;
+ Paths = nullptr;
+ NamingClass = nullptr;
Shadowed = false;
}
@@ -637,13 +637,7 @@ private:
void configure();
// Sanity checks.
- void sanityImpl() const;
-
- void sanity() const {
-#ifndef NDEBUG
- sanityImpl();
-#endif
- }
+ bool sanity() const;
bool sanityCheckUnresolved() const {
for (iterator I = begin(), E = end(); I != E; ++I)
diff --git a/include/clang/Sema/LoopHint.h b/include/clang/Sema/LoopHint.h
new file mode 100644
index 000000000000..d4b985df544c
--- /dev/null
+++ b/include/clang/Sema/LoopHint.h
@@ -0,0 +1,40 @@
+//===--- 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" case, this is identical to PragmaNameLoc.
+ IdentifierLoc *OptionLoc;
+ // Identifier for the hint argument. If null, then the hint has no argument
+ // such as for "#pragma unroll".
+ IdentifierLoc *ValueLoc;
+ // Expression for the hint argument if it exists, null otherwise.
+ Expr *ValueExpr;
+};
+
+} // end namespace clang
+
+#endif // LLVM_CLANG_SEMA_LOOPHINT_H
diff --git a/include/clang/Sema/MultiplexExternalSemaSource.h b/include/clang/Sema/MultiplexExternalSemaSource.h
index e9ba479d1255..7860b6da06a0 100644
--- a/include/clang/Sema/MultiplexExternalSemaSource.h
+++ b/include/clang/Sema/MultiplexExternalSemaSource.h
@@ -65,31 +65,35 @@ public:
/// \brief Resolve a declaration ID into a declaration, potentially
/// building a new declaration.
- virtual Decl *GetExternalDecl(uint32_t ID);
+ 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.
- virtual Selector GetExternalSelector(uint32_t ID);
+ Selector GetExternalSelector(uint32_t ID) override;
/// \brief Returns the number of selectors known to the external AST
/// source.
- virtual uint32_t GetNumExternalSelectors();
+ uint32_t GetNumExternalSelectors() override;
/// \brief Resolve the offset of a statement in the decl stream into
/// a statement.
- virtual Stmt *GetExternalDeclStmt(uint64_t Offset);
+ 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.
- virtual CXXBaseSpecifier *GetExternalCXXBaseSpecifiers(uint64_t Offset);
+ CXXBaseSpecifier *GetExternalCXXBaseSpecifiers(uint64_t Offset) override;
/// \brief Find all declarations with the given name in the
/// given context.
- virtual bool
- FindExternalVisibleDeclsByName(const DeclContext *DC, DeclarationName Name);
+ bool
+ FindExternalVisibleDeclsByName(const DeclContext *DC, DeclarationName Name) override;
/// \brief Ensures that the table of all visible declarations inside this
/// context is up to date.
- virtual void completeVisibleDeclsMap(const DeclContext *DC);
+ void completeVisibleDeclsMap(const DeclContext *DC) override;
/// \brief Finds all declarations lexically contained within the given
/// DeclContext, after applying an optional filter predicate.
@@ -99,9 +103,9 @@ public:
/// are returned.
///
/// \return an indication of whether the load succeeded or failed.
- virtual ExternalLoadResult FindExternalLexicalDecls(const DeclContext *DC,
- bool (*isKindWeWant)(Decl::Kind),
- SmallVectorImpl<Decl*> &Result);
+ ExternalLoadResult FindExternalLexicalDecls(const DeclContext *DC,
+ bool (*isKindWeWant)(Decl::Kind),
+ SmallVectorImpl<Decl*> &Result) override;
/// \brief Finds all declarations lexically contained within the given
/// DeclContext.
@@ -109,7 +113,7 @@ public:
/// \return true if an error occurred
ExternalLoadResult FindExternalLexicalDecls(const DeclContext *DC,
SmallVectorImpl<Decl*> &Result) {
- return FindExternalLexicalDecls(DC, 0, Result);
+ return FindExternalLexicalDecls(DC, nullptr, Result);
}
template <typename DeclTy>
@@ -121,12 +125,12 @@ public:
/// \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);
+ 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.
- virtual void CompleteType(TagDecl *Tag);
+ void CompleteType(TagDecl *Tag) override;
/// \brief Gives the external AST source an opportunity to complete an
/// incomplete Objective-C class.
@@ -134,27 +138,27 @@ public:
/// 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);
+ void CompleteType(ObjCInterfaceDecl *Class) override;
/// \brief Loads comment ranges.
- virtual void ReadComments();
+ 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.
- virtual void StartedDeserializing();
+ void StartedDeserializing() override;
/// \brief Notify ExternalASTSource that we finished the deserialization of
/// a decl or type. Must be paired with StartedDeserializing.
- virtual void FinishedDeserializing();
+ void FinishedDeserializing() override;
/// \brief Function that will be invoked when we begin parsing a new
/// translation unit involving this external AST source.
- virtual void StartTranslationUnit(ASTConsumer *Consumer);
+ void StartTranslationUnit(ASTConsumer *Consumer) override;
/// \brief Print any statistics that have been gathered regarding
/// the external AST source.
- virtual void PrintStats();
+ void PrintStats() override;
/// \brief Perform layout on the given record.
@@ -184,16 +188,17 @@ public:
/// be laid out according to the ABI.
///
/// \returns true if the record layout was provided, false otherwise.
- virtual bool
+ 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);
+ 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.
- virtual void getMemoryBufferSizes(MemoryBufferSizes &sizes) const;
+ void getMemoryBufferSizes(MemoryBufferSizes &sizes) const override;
//===--------------------------------------------------------------------===//
// ExternalSemaSource.
@@ -202,24 +207,25 @@ public:
/// \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);
+ void InitializeSema(Sema &S) override;
/// \brief Inform the semantic consumer that Sema is no longer available.
- virtual void ForgetSema();
+ void ForgetSema() override;
/// \brief Load the contents of the global method pool for a given
/// selector.
- virtual void ReadMethodPool(Selector Sel);
+ 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.
- virtual void ReadKnownNamespaces(SmallVectorImpl<NamespaceDecl*> &Namespaces);
+ 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.
- virtual void ReadUndefinedButUsed(
- llvm::DenseMap<NamedDecl*, SourceLocation> &Undefined);
-
+ void ReadUndefinedButUsed(
+ llvm::DenseMap<NamedDecl*, SourceLocation> &Undefined) override;
+
/// \brief Do last resort, unqualified lookup on a LookupResult that
/// Sema cannot find.
///
@@ -228,7 +234,7 @@ public:
/// \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);
+ bool LookupUnqualified(LookupResult &R, Scope *S) override;
/// \brief Read the set of tentative definitions known to the external Sema
/// source.
@@ -237,8 +243,8 @@ public:
/// 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*> &Defs);
-
+ void ReadTentativeDefinitions(SmallVectorImpl<VarDecl*> &Defs) override;
+
/// \brief Read the set of unused file-scope declarations known to the
/// external Sema source.
///
@@ -246,9 +252,9 @@ public:
/// 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);
-
+ void ReadUnusedFileScopedDecls(
+ SmallVectorImpl<const DeclaratorDecl*> &Decls) override;
+
/// \brief Read the set of delegating constructors known to the
/// external Sema source.
///
@@ -256,8 +262,8 @@ public:
/// 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);
+ void ReadDelegatingConstructors(
+ SmallVectorImpl<CXXConstructorDecl*> &Decls) override;
/// \brief Read the set of ext_vector type declarations known to the
/// external Sema source.
@@ -266,7 +272,7 @@ public:
/// 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);
+ void ReadExtVectorDecls(SmallVectorImpl<TypedefNameDecl*> &Decls) override;
/// \brief Read the set of dynamic classes known to the external Sema source.
///
@@ -274,7 +280,7 @@ public:
/// 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 ReadDynamicClasses(SmallVectorImpl<CXXRecordDecl*> &Decls);
+ void ReadDynamicClasses(SmallVectorImpl<CXXRecordDecl*> &Decls) override;
/// \brief Read the set of locally-scoped extern "C" declarations known to the
/// external Sema source.
@@ -283,7 +289,8 @@ public:
/// 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 ReadLocallyScopedExternCDecls(SmallVectorImpl<NamedDecl*>&Decls);
+ void ReadLocallyScopedExternCDecls(
+ SmallVectorImpl<NamedDecl*> &Decls) override;
/// \brief Read the set of referenced selectors known to the
/// external Sema source.
@@ -292,8 +299,8 @@ public:
/// 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);
+ void ReadReferencedSelectors(SmallVectorImpl<std::pair<Selector,
+ SourceLocation> > &Sels) override;
/// \brief Read the set of weak, undeclared identifiers known to the
/// external Sema source.
@@ -302,15 +309,15 @@ public:
/// 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);
+ 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.
- virtual void ReadUsedVTables(SmallVectorImpl<ExternalVTableUse> &VTables);
+ void ReadUsedVTables(SmallVectorImpl<ExternalVTableUse> &VTables) override;
/// \brief Read the set of pending instantiations known to the external
/// Sema source.
@@ -319,8 +326,8 @@ public:
/// 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);
+ void ReadPendingInstantiations(
+ SmallVectorImpl<std::pair<ValueDecl*, SourceLocation> >& Pending) override;
/// \brief Read the set of late parsed template functions for this source.
///
@@ -328,17 +335,18 @@ public:
/// 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::DenseMap<const FunctionDecl *, LateParsedTemplate *> &LPTMap);
+ void ReadLateParsedTemplates(
+ llvm::DenseMap<const FunctionDecl *,
+ LateParsedTemplate *> &LPTMap) override;
/// \copydoc ExternalSemaSource::CorrectTypo
/// \note Returns the first nonempty correction.
- virtual TypoCorrection CorrectTypo(const DeclarationNameInfo &Typo,
- int LookupKind, Scope *S, CXXScopeSpec *SS,
- CorrectionCandidateCallback &CCC,
- DeclContext *MemberContext,
- bool EnteringContext,
- const ObjCObjectPointerType *OPT);
+ 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
@@ -350,7 +358,8 @@ public:
/// \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);
+ bool MaybeDiagnoseMissingCompleteType(SourceLocation Loc,
+ QualType T) override;
// isa/cast/dyn_cast support
static bool classof(const MultiplexExternalSemaSource*) { return true; }
diff --git a/include/clang/Sema/ObjCMethodList.h b/include/clang/Sema/ObjCMethodList.h
index 94e380721de2..20033567dff9 100644
--- a/include/clang/Sema/ObjCMethodList.h
+++ b/include/clang/Sema/ObjCMethodList.h
@@ -26,7 +26,7 @@ struct ObjCMethodList {
/// \brief The next list object and 2 bits for extra info.
llvm::PointerIntPair<ObjCMethodList *, 2> NextAndExtraBits;
- ObjCMethodList() : Method(0) { }
+ ObjCMethodList() : Method(nullptr) { }
ObjCMethodList(ObjCMethodDecl *M, ObjCMethodList *C)
: Method(M), NextAndExtraBits(C, 0) { }
diff --git a/include/clang/Sema/Overload.h b/include/clang/Sema/Overload.h
index b8bd14aa1cd5..7c221a2336ce 100644
--- a/include/clang/Sema/Overload.h
+++ b/include/clang/Sema/Overload.h
@@ -262,7 +262,7 @@ namespace clang {
StandardConversionSequence Before;
/// EllipsisConversion - When this is true, it means user-defined
- /// conversion sequence starts with a ... (elipsis) conversion, instead of
+ /// 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
@@ -339,7 +339,6 @@ namespace clang {
enum FailureKind {
no_conversion,
unrelated_class,
- suppressed_user,
bad_qualifiers,
lvalue_ref_to_rvalue,
rvalue_ref_to_lvalue
@@ -364,7 +363,7 @@ namespace clang {
}
void init(FailureKind K, QualType From, QualType To) {
Kind = K;
- FromExpr = 0;
+ FromExpr = nullptr;
setFromType(From);
setToType(To);
}
@@ -579,7 +578,11 @@ namespace clang {
/// (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
+ 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).
@@ -675,11 +678,35 @@ namespace clang {
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;
@@ -688,6 +715,7 @@ namespace clang {
llvm::BumpPtrAllocator ConversionSequenceAllocator;
SourceLocation Loc;
+ CandidateSetKind Kind;
unsigned NumInlineSequences;
char InlineSpace[16 * sizeof(ImplicitConversionSequence)];
@@ -698,10 +726,12 @@ namespace clang {
void destroyCandidates();
public:
- OverloadCandidateSet(SourceLocation Loc) : Loc(Loc), NumInlineSequences(0){}
+ 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.
diff --git a/include/clang/Sema/Ownership.h b/include/clang/Sema/Ownership.h
index b7d7710eb121..8031562e0ec4 100644
--- a/include/clang/Sema/Ownership.h
+++ b/include/clang/Sema/Ownership.h
@@ -49,7 +49,7 @@ namespace clang {
typedef llvm::PointerLikeTypeTraits<PtrTy> Traits;
public:
- OpaquePtr() : Ptr(0) {}
+ OpaquePtr() : Ptr(nullptr) {}
static OpaquePtr make(PtrTy P) { OpaquePtr OP; OP.set(P); return OP; }
@@ -79,7 +79,7 @@ namespace clang {
Ptr = Traits::getAsVoidPointer(P);
}
- LLVM_EXPLICIT operator bool() const { return Ptr != 0; }
+ LLVM_EXPLICIT operator bool() const { return Ptr != nullptr; }
void *getAsOpaquePtr() const { return Ptr; }
static OpaquePtr getFromOpaquePtr(void *P) { return OpaquePtr(P); }
@@ -158,12 +158,10 @@ namespace clang {
bool isInvalid() const { return Invalid; }
bool isUsable() const { return !Invalid && Val; }
+ bool isUnset() const { return !Invalid && !Val; }
PtrTy get() const { return Val; }
- // FIXME: Replace with get.
- PtrTy release() const { return Val; }
- PtrTy take() const { return Val; }
- template <typename T> T *takeAs() { return static_cast<T*>(get()); }
+ template <typename T> T *getAs() { return static_cast<T*>(get()); }
void set(PtrTy V) { Val = V; }
@@ -199,15 +197,13 @@ namespace clang {
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);
}
- // FIXME: Replace with get.
- PtrTy take() const { return get(); }
- PtrTy release() const { return get(); }
- template <typename T> T *takeAs() { return static_cast<T*>(get()); }
+ template <typename T> T *getAs() { return static_cast<T*>(get()); }
void set(PtrTy V) {
void *VP = PtrTraits::getAsVoidPointer(V);
@@ -262,11 +258,11 @@ namespace clang {
typedef ActionResult<Decl*> DeclResult;
typedef OpaquePtr<TemplateName> ParsedTemplateTy;
- typedef llvm::MutableArrayRef<Expr*> MultiExprArg;
- typedef llvm::MutableArrayRef<Stmt*> MultiStmtArg;
- typedef llvm::MutableArrayRef<ParsedTemplateArgument> ASTTemplateArgsPtr;
- typedef llvm::MutableArrayRef<ParsedType> MultiTypeArg;
- typedef llvm::MutableArrayRef<TemplateParameterList*> MultiTemplateParamsArg;
+ 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); }
diff --git a/include/clang/Sema/ParsedTemplate.h b/include/clang/Sema/ParsedTemplate.h
index 94db454a8543..b36425f1be83 100644
--- a/include/clang/Sema/ParsedTemplate.h
+++ b/include/clang/Sema/ParsedTemplate.h
@@ -35,7 +35,7 @@ namespace clang {
/// \brief Build an empty template argument.
///
/// This template argument is invalid.
- ParsedTemplateArgument() : Kind(Type), Arg(0) { }
+ ParsedTemplateArgument() : Kind(Type), Arg(nullptr) { }
/// \brief Create a template type argument or non-type template argument.
///
@@ -61,7 +61,7 @@ namespace clang {
SS(SS), Loc(TemplateLoc), EllipsisLoc() { }
/// \brief Determine whether the given template argument is invalid.
- bool isInvalid() const { return Arg == 0; }
+ bool isInvalid() const { return Arg == nullptr; }
/// \brief Determine what kind of template argument we have.
KindType getKind() const { return Kind; }
diff --git a/include/clang/Sema/PrettyDeclStackTrace.h b/include/clang/Sema/PrettyDeclStackTrace.h
index aa5570526332..c0c772dc5983 100644
--- a/include/clang/Sema/PrettyDeclStackTrace.h
+++ b/include/clang/Sema/PrettyDeclStackTrace.h
@@ -39,7 +39,7 @@ public:
const char *Msg)
: S(S), TheDecl(D), Loc(Loc), Message(Msg) {}
- virtual void print(raw_ostream &OS) const;
+ void print(raw_ostream &OS) const override;
};
}
diff --git a/include/clang/Sema/Scope.h b/include/clang/Sema/Scope.h
index 249a4c74311b..8e4e2ef4be21 100644
--- a/include/clang/Sema/Scope.h
+++ b/include/clang/Sema/Scope.h
@@ -15,13 +15,21 @@
#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
@@ -93,21 +101,47 @@ public:
/// \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 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 a SEH try.
+ SEHTryScope = 0x80000,
};
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;
- /// Flags - This contains a set of ScopeFlags, which indicates how the scope
- /// interrelates with other control flow statements.
- unsigned short Flags;
+ /// \brief Declarations with static linkage are mangled with the number of
+ /// scopes seen as a component.
+ unsigned short MSLocalManglingNumber;
+
+ /// \brief SEH __try blocks get uniquely numbered within a function. This
+ /// variable holds the index for an SEH try block.
+ short SEHTryIndex;
+
+ /// \brief SEH __try blocks get uniquely numbered within a function. This
+ /// variable holds the next free index at a function's scope.
+ short SEHTryIndexPool;
/// PrototypeDepth - This is the number of function prototype scopes
/// enclosing this scope, including this scope.
@@ -120,6 +154,8 @@ private:
/// 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 *MSLocalManglingParent;
+ Scope *SEHTryParent;
/// BreakParent/ContinueParent - This is a direct link to the innermost
/// BreakScope/ContinueScope which contains the contents of this scope
@@ -156,7 +192,11 @@ private:
/// \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) {
@@ -181,6 +221,11 @@ public:
const Scope *getFnParent() const { return FnParent; }
Scope *getFnParent() { return FnParent; }
+ const Scope *getMSLocalManglingParent() const {
+ return MSLocalManglingParent;
+ }
+ Scope *getMSLocalManglingParent() { return MSLocalManglingParent; }
+
/// getContinueParent - Return the closest scope that a continue statement
/// would be affected by.
Scope *getContinueParent() {
@@ -219,10 +264,11 @@ public:
return PrototypeIndex++;
}
- typedef DeclSetTy::iterator decl_iterator;
- decl_iterator decl_begin() const { return DeclsInScope.begin(); }
- decl_iterator decl_end() const { return DeclsInScope.end(); }
- bool decl_empty() const { return DeclsInScope.empty(); }
+ 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);
@@ -232,6 +278,30 @@ public:
DeclsInScope.erase(D);
}
+ void incrementMSLocalManglingNumber() {
+ if (Scope *MSLMP = getMSLocalManglingParent())
+ MSLMP->MSLocalManglingNumber += 1;
+ }
+
+ void decrementMSLocalManglingNumber() {
+ if (Scope *MSLMP = getMSLocalManglingParent())
+ MSLMP->MSLocalManglingNumber -= 1;
+ }
+
+ unsigned getMSLocalManglingNumber() const {
+ if (const Scope *MSLMP = getMSLocalManglingParent())
+ return MSLMP->MSLocalManglingNumber;
+ return 1;
+ }
+
+ int getSEHTryIndex() {
+ return SEHTryIndex;
+ }
+
+ int getSEHTryParentIndex() const {
+ return SEHTryParent ? SEHTryParent->SEHTryIndex : -1;
+ }
+
/// isDeclScope - Return true if this is the scope that the specified decl is
/// declared in.
bool isDeclScope(Decl *D) {
@@ -273,6 +343,18 @@ public:
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 {
@@ -309,39 +391,81 @@ public:
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; }
+
/// containedInPrototypeScope - Return true if this or a parent scope
/// is a FunctionPrototypeScope.
bool containedInPrototypeScope() const;
- typedef UsingDirectivesTy::iterator udir_iterator;
- typedef UsingDirectivesTy::const_iterator const_udir_iterator;
-
void PushUsingDirective(UsingDirectiveDecl *UDir) {
UsingDirectives.push_back(UDir);
}
- udir_iterator using_directives_begin() {
- return UsingDirectives.begin();
- }
+ typedef llvm::iterator_range<UsingDirectivesTy::iterator>
+ using_directives_range;
- udir_iterator using_directives_end() {
- return UsingDirectives.end();
+ using_directives_range using_directives() {
+ return using_directives_range(UsingDirectives.begin(),
+ UsingDirectives.end());
}
- const_udir_iterator using_directives_begin() const {
- return UsingDirectives.begin();
+ void addNRVOCandidate(VarDecl *VD) {
+ if (NRVO.getInt())
+ return;
+ if (NRVO.getPointer() == nullptr) {
+ NRVO.setPointer(VD);
+ return;
+ }
+ if (NRVO.getPointer() != VD)
+ setNoNRVO();
}
- const_udir_iterator using_directives_end() const {
- return UsingDirectives.end();
+ 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
diff --git a/include/clang/Sema/ScopeInfo.h b/include/clang/Sema/ScopeInfo.h
index 06afe1a8ae9d..63427aaa4a75 100644
--- a/include/clang/Sema/ScopeInfo.h
+++ b/include/clang/Sema/ScopeInfo.h
@@ -110,6 +110,21 @@ public:
/// with \c __attribute__((objc_requires_super)).
bool ObjCShouldCallSuper;
+ /// True when this is a method marked as a designated initializer.
+ bool ObjCIsDesignatedInit;
+ /// 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;
+
+ /// 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;
+ /// 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;
+
/// \brief Used to determine if errors occurred in this function or block.
DiagnosticErrorTrap ErrorTrap;
@@ -318,6 +333,10 @@ public:
HasIndirectGoto(false),
HasDroppedStmt(false),
ObjCShouldCallSuper(false),
+ ObjCIsDesignatedInit(false),
+ ObjCWarnForNoDesignatedInitChain(false),
+ ObjCIsSecondaryInit(false),
+ ObjCWarnForNoInitDelegation(false),
ErrorTrap(Diag) { }
virtual ~FunctionScopeInfo();
@@ -386,7 +405,7 @@ public:
enum IsThisCapture { ThisCapture };
Capture(IsThisCapture, bool IsNested, SourceLocation Loc,
QualType CaptureType, Expr *Cpy)
- : VarAndNested(0, IsNested),
+ : VarAndNested(nullptr, IsNested),
InitExprAndCaptureKind(Cpy, Cap_This),
Loc(Loc), EllipsisLoc(), CaptureType(CaptureType) {}
@@ -644,10 +663,10 @@ public:
SourceLocation PotentialThisCaptureLocation;
LambdaScopeInfo(DiagnosticsEngine &Diag)
- : CapturingScopeInfo(Diag, ImpCap_None), Lambda(0),
- CallOperator(0), NumExplicitCaptures(0), Mutable(false),
+ : CapturingScopeInfo(Diag, ImpCap_None), Lambda(nullptr),
+ CallOperator(nullptr), NumExplicitCaptures(0), Mutable(false),
ExprNeedsCleanups(false), ContainsUnexpandedParameterPack(false),
- AutoTemplateParameterDepth(0), GLTemplateParameterList(0)
+ AutoTemplateParameterDepth(0), GLTemplateParameterList(nullptr)
{
Kind = SK_Lambda;
}
@@ -708,10 +727,10 @@ public:
/// 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;
+ ///
+ /// 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
@@ -725,12 +744,12 @@ public:
/// 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
+ /// "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) {
@@ -738,7 +757,7 @@ public:
|| isa<MemberExpr>(CapturingVarExpr));
NonODRUsedCapturingExprs.insert(CapturingVarExpr);
}
- bool isVariableExprMarkedAsNonODRUsed(Expr *CapturingVarExpr) {
+ bool isVariableExprMarkedAsNonODRUsed(Expr *CapturingVarExpr) const {
assert(isa<DeclRefExpr>(CapturingVarExpr)
|| isa<MemberExpr>(CapturingVarExpr));
return NonODRUsedCapturingExprs.count(CapturingVarExpr);
@@ -761,16 +780,14 @@ public:
return getNumPotentialVariableCaptures() ||
PotentialThisCaptureLocation.isValid();
}
-
- // When passed the index, returns the VarDecl and Expr associated
+
+ // When passed the index, returns the VarDecl and Expr associated
// with the index.
- void getPotentialVariableCapture(unsigned Idx, VarDecl *&VD, Expr *&E);
-
+ void getPotentialVariableCapture(unsigned Idx, VarDecl *&VD, Expr *&E) const;
};
-
FunctionScopeInfo::WeakObjectProfileTy::WeakObjectProfileTy()
- : Base(0, false), Property(0) {}
+ : Base(nullptr, false), Property(nullptr) {}
FunctionScopeInfo::WeakObjectProfileTy
FunctionScopeInfo::WeakObjectProfileTy::getSentinel() {
diff --git a/include/clang/Sema/Sema.h b/include/clang/Sema/Sema.h
index 48794d6f02fd..e254afdbadaa 100644
--- a/include/clang/Sema/Sema.h
+++ b/include/clang/Sema/Sema.h
@@ -26,11 +26,11 @@
#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/Lex/ModuleLoader.h"
#include "clang/Sema/AnalysisBasedWarnings.h"
#include "clang/Sema/DeclSpec.h"
#include "clang/Sema/ExternalSemaSource.h"
@@ -38,17 +38,18 @@
#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/OwningPtr.h"
#include "llvm/ADT/SetVector.h"
#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/ADT/SmallVector.h"
-#include "llvm/MC/MCParser/MCAsmParser.h"
+#include "llvm/ADT/TinyPtrVector.h"
#include <deque>
+#include <memory>
#include <string>
#include <vector>
@@ -57,6 +58,7 @@ namespace llvm {
template <typename ValueT> struct DenseMapInfo;
template <typename ValueT, typename ValueInfoT> class DenseSet;
class SmallBitVector;
+ class InlineAsmIdentifierInfo;
}
namespace clang {
@@ -101,6 +103,7 @@ namespace clang {
class DependentDiagnostic;
class DesignatedInitExpr;
class Designation;
+ class EnableIfAttr;
class EnumConstantDecl;
class Expr;
class ExtVectorType;
@@ -122,6 +125,8 @@ namespace clang {
class LocalInstantiationScope;
class LookupResult;
class MacroInfo;
+ typedef ArrayRef<std::pair<IdentifierInfo *, SourceLocation>> ModuleIdPath;
+ class ModuleLoader;
class MultiLevelTemplateArgumentList;
class NamedDecl;
class NonNullAttr;
@@ -152,7 +157,6 @@ namespace clang {
class Stmt;
class StringLiteral;
class SwitchStmt;
- class TargetAttributesSema;
class TemplateArgument;
class TemplateArgumentList;
class TemplateArgumentLoc;
@@ -204,7 +208,6 @@ typedef std::pair<llvm::PointerUnion<const TemplateTypeParmType*, NamedDecl*>,
class Sema {
Sema(const Sema &) LLVM_DELETED_FUNCTION;
void operator=(const Sema &) LLVM_DELETED_FUNCTION;
- mutable const TargetAttributesSema* TheTargetAttributesSema;
///\brief Source of additional semantic information.
ExternalSemaSource *ExternalSource;
@@ -263,9 +266,82 @@ public:
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;
+
+ /// \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;
+
+ /// 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
@@ -307,7 +383,7 @@ public:
ExtVectorDeclsType ExtVectorDecls;
/// FieldCollector - Collects CXXFieldDecls during parsing of C++ classes.
- OwningPtr<CXXFieldCollector> FieldCollector;
+ std::unique_ptr<CXXFieldCollector> FieldCollector;
typedef llvm::SmallSetVector<const NamedDecl*, 16> NamedDeclSetType;
@@ -319,7 +395,7 @@ public:
/// 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.
- OwningPtr<RecordDeclSetTy> PureVirtualClassDiagSet;
+ std::unique_ptr<RecordDeclSetTy> PureVirtualClassDiagSet;
/// ParsingInitForAutoVars - a set of declarations with auto types for which
/// we are currently parsing the initializer.
@@ -426,13 +502,13 @@ public:
sema::DelayedDiagnosticPool *CurPool;
public:
- DelayedDiagnostics() : CurPool(0) {}
+ 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 != 0; }
+ bool shouldDelayDiagnostics() { return CurPool != nullptr; }
/// Returns the current delayed-diagnostics pool.
sema::DelayedDiagnosticPool *getCurrentPool() const {
@@ -460,13 +536,13 @@ public:
DelayedDiagnosticsState pushUndelayed() {
DelayedDiagnosticsState state;
state.SavedPool = CurPool;
- CurPool = 0;
+ CurPool = nullptr;
return state;
}
/// Undo a previous pushUndelayed().
void popUndelayed(DelayedDiagnosticsState state) {
- assert(CurPool == NULL);
+ assert(CurPool == nullptr);
CurPool = state.SavedPool;
}
} DelayedDiagnostics;
@@ -480,13 +556,15 @@ public:
QualType SavedCXXThisTypeOverride;
public:
- ContextRAII(Sema &S, DeclContext *ContextToPush)
+ 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() {
@@ -494,7 +572,7 @@ public:
S.CurContext = SavedContext;
S.DelayedDiagnostics.popUndelayed(SavedContextState);
S.CXXThisTypeOverride = SavedCXXThisTypeOverride;
- SavedContext = 0;
+ SavedContext = nullptr;
}
~ContextRAII() {
@@ -569,7 +647,7 @@ public:
RecordDecl *MSVCGuidDecl;
/// \brief Caches identifiers/selectors for NSFoundation APIs.
- OwningPtr<NSAPI> NSAPIObj;
+ std::unique_ptr<NSAPI> NSAPIObj;
/// \brief The declaration of the Objective-C NSNumber class.
ObjCInterfaceDecl *NSNumberDecl;
@@ -772,7 +850,7 @@ public:
/// \brief The number of SFINAE diagnostics that have been trapped.
unsigned NumSFINAEErrors;
- typedef llvm::DenseMap<ParmVarDecl *, SmallVector<ParmVarDecl *, 1> >
+ typedef llvm::DenseMap<ParmVarDecl *, llvm::TinyPtrVector<ParmVarDecl *>>
UnparsedDefaultArgInstantiationsMap;
/// \brief A mapping from parameters with unparsed default arguments to the
@@ -833,6 +911,7 @@ public:
/// 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
@@ -853,13 +932,12 @@ public:
bool OldFPContractState : 1;
};
- typedef llvm::MCAsmParserSemaCallback::InlineAsmIdentifierInfo
- InlineAsmIdentifierInfo;
+ void addImplicitTypedef(StringRef Name, QualType T);
public:
Sema(Preprocessor &pp, ASTContext &ctxt, ASTConsumer &consumer,
TranslationUnitKind TUKind = TU_Complete,
- CodeCompleteConsumer *CompletionConsumer = 0);
+ CodeCompleteConsumer *CompletionConsumer = nullptr);
~Sema();
/// \brief Perform initialization that occurs after the parser has been
@@ -872,7 +950,6 @@ public:
DiagnosticsEngine &getDiagnostics() const { return Diags; }
SourceManager &getSourceManager() const { return SourceMgr; }
- const TargetAttributesSema &getTargetAttributesSema() const;
Preprocessor &getPreprocessor() const { return PP; }
ASTContext &getASTContext() const { return Context; }
ASTConsumer &getASTConsumer() const { return Consumer; }
@@ -954,9 +1031,11 @@ public:
getFixItZeroInitializerForType(QualType T, SourceLocation Loc) const;
std::string getFixItZeroLiteralForType(QualType T, SourceLocation Loc) const;
- ExprResult Owned(Expr* E) { return E; }
- ExprResult Owned(ExprResult R) { return R; }
- StmtResult Owned(Stmt* S) { return S; }
+ /// \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 ActOnEndOfTranslationUnit();
@@ -967,7 +1046,7 @@ public:
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.
@@ -976,13 +1055,27 @@ public:
void PushCapturedRegionScope(Scope *RegionScope, CapturedDecl *CD,
RecordDecl *RD,
CapturedRegionKind K);
- void PopFunctionScopeInfo(const sema::AnalysisBasedWarnings::Policy *WP =0,
- const Decl *D = 0, const BlockExpr *blkExpr = 0);
+ 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())
@@ -1018,9 +1111,9 @@ public:
//
QualType BuildQualifiedType(QualType T, SourceLocation Loc, Qualifiers Qs,
- const DeclSpec *DS = 0);
+ const DeclSpec *DS = nullptr);
QualType BuildQualifiedType(QualType T, SourceLocation Loc, unsigned CVRA,
- const DeclSpec *DS = 0);
+ const DeclSpec *DS = nullptr);
QualType BuildPointerType(QualType T,
SourceLocation Loc, DeclarationName Entity);
QualType BuildReferenceType(QualType T, bool LValueRef,
@@ -1061,7 +1154,7 @@ public:
/// unqualified type will always be a FunctionProtoType.
/// Otherwise, returns a NULL type.
QualType BuildFunctionType(QualType T,
- llvm::MutableArrayRef<QualType> ParamTypes,
+ MutableArrayRef<QualType> ParamTypes,
SourceLocation Loc, DeclarationName Entity,
const FunctionProtoType::ExtProtoInfo &EPI);
@@ -1082,10 +1175,13 @@ public:
ParsedType CreateParsedType(QualType T, TypeSourceInfo *TInfo);
DeclarationNameInfo GetNameForDeclarator(Declarator &D);
DeclarationNameInfo GetNameFromUnqualifiedId(const UnqualifiedId &Name);
- static QualType GetTypeFromParser(ParsedType Ty, TypeSourceInfo **TInfo = 0);
+ 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::ExtProtoInfo &EPI);
bool CheckSpecifiedExceptionType(QualType &T, const SourceRange &Range);
bool CheckDistantExceptionSpec(QualType T);
bool CheckEquivalentExceptionSpec(FunctionDecl *Old, FunctionDecl *New);
@@ -1096,8 +1192,8 @@ public:
const PartialDiagnostic &DiagID, const PartialDiagnostic & NoteID,
const FunctionProtoType *Old, SourceLocation OldLoc,
const FunctionProtoType *New, SourceLocation NewLoc,
- bool *MissingExceptionSpecification = 0,
- bool *MissingEmptyExceptionSpecification = 0,
+ bool *MissingExceptionSpecification = nullptr,
+ bool *MissingEmptyExceptionSpecification = nullptr,
bool AllowNoexceptAllMatchWithNoSpec = false,
bool IsOperatorNew = false);
bool CheckExceptionSpecSubset(
@@ -1148,7 +1244,7 @@ public:
public:
BoundTypeDiagnoser1(unsigned DiagID, const T1 &Arg1)
: TypeDiagnoser(DiagID == 0), DiagID(DiagID), Arg1(Arg1) { }
- virtual void diagnose(Sema &S, SourceLocation Loc, QualType T) {
+ void diagnose(Sema &S, SourceLocation Loc, QualType T) override {
if (Suppressed) return;
S.Diag(Loc, DiagID) << getPrintable(Arg1) << T;
}
@@ -1168,7 +1264,7 @@ public:
: TypeDiagnoser(DiagID == 0), DiagID(DiagID), Arg1(Arg1),
Arg2(Arg2) { }
- virtual void diagnose(Sema &S, SourceLocation Loc, QualType T) {
+ void diagnose(Sema &S, SourceLocation Loc, QualType T) override {
if (Suppressed) return;
S.Diag(Loc, DiagID) << getPrintable(Arg1) << getPrintable(Arg2) << T;
}
@@ -1189,7 +1285,7 @@ public:
: TypeDiagnoser(DiagID == 0), DiagID(DiagID), Arg1(Arg1),
Arg2(Arg2), Arg3(Arg3) { }
- virtual void diagnose(Sema &S, SourceLocation Loc, QualType T) {
+ void diagnose(Sema &S, SourceLocation Loc, QualType T) override {
if (Suppressed) return;
S.Diag(Loc, DiagID)
<< getPrintable(Arg1) << getPrintable(Arg2) << getPrintable(Arg3) << T;
@@ -1299,33 +1395,36 @@ public:
/// function to pin them on. ActOnFunctionDeclarator reads this list and patches
/// them into the FunctionDecl.
std::vector<NamedDecl*> DeclsInPrototypeScope;
- /// Nonzero if we are currently parsing a function declarator. This is a counter
- /// as opposed to a boolean so we can deal with nested function declarators
- /// such as:
- /// void f(void (*g)(), ...)
- unsigned InFunctionDeclarator;
- DeclGroupPtrTy ConvertDeclToDeclGroup(Decl *Ptr, Decl *OwnedType = 0);
+ 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 = 0,
+ Scope *S, CXXScopeSpec *SS = nullptr,
bool isClassName = false,
bool HasTrailingDot = false,
ParsedType ObjectType = ParsedType(),
bool IsCtorOrDtorName = false,
bool WantNontrivialTypeSourceInfo = false,
- IdentifierInfo **CorrectedII = 0);
+ IdentifierInfo **CorrectedII = nullptr);
TypeSpecifierType isTagName(IdentifierInfo &II, Scope *S);
bool isMicrosoftMissingTypename(const CXXScopeSpec *SS, Scope *S);
- bool DiagnoseUnknownTypeName(IdentifierInfo *&II,
+ void DiagnoseUnknownTypeName(IdentifierInfo *&II,
SourceLocation IILoc,
Scope *S,
CXXScopeSpec *SS,
- ParsedType &SuggestedType);
+ 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().
@@ -1450,7 +1549,7 @@ public:
SourceLocation NameLoc,
const Token &NextToken,
bool IsAddressOfOperand,
- CorrectionCandidateCallback *CCC = 0);
+ CorrectionCandidateCallback *CCC = nullptr);
Decl *ActOnDeclarator(Scope *S, Declarator &D);
@@ -1461,6 +1560,14 @@ public:
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);
@@ -1482,8 +1589,6 @@ public:
void CheckVariableDeclarationType(VarDecl *NewVD);
void CheckCompleteVariableDeclaration(VarDecl *var);
void MaybeSuggestAddingStaticToDecl(const FunctionDecl *D);
- void ActOnStartFunctionDeclarator();
- void ActOnEndFunctionDeclarator();
NamedDecl* ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC,
TypeSourceInfo *TInfo,
@@ -1491,7 +1596,6 @@ public:
MultiTemplateParamsArg TemplateParamLists,
bool &AddToScope);
bool AddOverriddenMethods(CXXRecordDecl *DC, CXXMethodDecl *MD);
- void checkVoidParamDecl(ParmVarDecl *Param);
bool CheckConstexprFunctionDecl(const FunctionDecl *FD);
bool CheckConstexprFunctionBody(const FunctionDecl *FD, Stmt *Body);
@@ -1521,7 +1625,7 @@ public:
void ActOnParamUnparsedDefaultArgument(Decl *param,
SourceLocation EqualLoc,
SourceLocation ArgLoc);
- void ActOnParamDefaultArgumentError(Decl *param);
+ void ActOnParamDefaultArgumentError(Decl *param, SourceLocation EqualLoc);
bool SetParamDefaultArgument(ParmVarDecl *Param, Expr *DefaultArg,
SourceLocation EqualLoc);
@@ -1530,12 +1634,16 @@ public:
void ActOnUninitializedDecl(Decl *dcl, bool TypeMayContainAuto);
void ActOnInitializerError(Decl *Dcl);
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(llvm::MutableArrayRef<Decl *> Group,
+ DeclGroupPtrTy BuildDeclaratorGroup(MutableArrayRef<Decl *> Group,
bool TypeMayContainAuto = true);
/// Should be called on all declarations that might have attached
@@ -1547,7 +1655,7 @@ public:
SourceLocation LocAfterDecls);
void CheckForFunctionRedefinition(FunctionDecl *FD,
const FunctionDecl *EffectiveDefinition =
- 0);
+ nullptr);
Decl *ActOnStartOfFunctionDef(Scope *S, Declarator &D);
Decl *ActOnStartOfFunctionDef(Scope *S, Decl *D);
void ActOnStartOfObjCMethodDef(Scope *S, Decl *D);
@@ -1555,6 +1663,16 @@ public:
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.
@@ -1568,6 +1686,7 @@ public:
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.
@@ -1611,12 +1730,13 @@ public:
void ActOnModuleInclude(SourceLocation DirectiveLoc, Module *Mod);
/// \brief Create an implicit import of the given module at the given
- /// source location.
+ /// source location, for error recovery, if possible.
///
- /// This routine is typically used for error recovery, when the entity found
- /// by name lookup is actually hidden within a module that we know about but
- /// the user has forgotten to import.
- void createImplicitModuleImport(SourceLocation Loc, Module *Mod);
+ /// 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);
/// \brief Retrieve a suitable printing policy.
PrintingPolicy getPrintingPolicy() const {
@@ -1640,7 +1760,8 @@ public:
Decl *BuildAnonymousStructOrUnion(Scope *S, DeclSpec &DS,
AccessSpecifier AS,
- RecordDecl *Record);
+ RecordDecl *Record,
+ const PrintingPolicy &Policy);
Decl *BuildMicrosoftCAnonymousStruct(Scope *S, DeclSpec &DS,
RecordDecl *Record);
@@ -1665,7 +1786,8 @@ public:
MultiTemplateParamsArg TemplateParameterLists,
bool &OwnedDecl, bool &IsDependent,
SourceLocation ScopedEnumKWLoc,
- bool ScopedEnumUsesClassTag, TypeResult UnderlyingType);
+ bool ScopedEnumUsesClassTag, TypeResult UnderlyingType,
+ bool IsTypeSpecifier);
Decl *ActOnTemplatedFriendTag(Scope *S, SourceLocation FriendLoc,
unsigned TagSpec, SourceLocation TagLoc,
@@ -1706,7 +1828,7 @@ public:
InClassInitStyle InitStyle,
SourceLocation TSSL,
AccessSpecifier AS, NamedDecl *PrevDecl,
- Declarator *D = 0);
+ Declarator *D = nullptr);
bool CheckNontrivialField(FieldDecl *FD);
void DiagnoseNontrivial(const CXXRecordDecl *Record, CXXSpecialMember CSM);
@@ -1823,11 +1945,11 @@ public:
/// if 'D' is in Scope 'S', otherwise 'S' is ignored and isDeclInScope returns
/// true if 'D' belongs to the given declaration context.
///
- /// \param ExplicitInstantiationOrSpecialization When true, we are checking
- /// whether the declaration is in scope for the purposes of explicit template
- /// instantiation or specialization. The default is false.
- bool isDeclInScope(NamedDecl *D, DeclContext *Ctx, Scope *S = 0,
- bool ExplicitInstantiationOrSpecialization = false);
+ /// \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.
@@ -1858,6 +1980,10 @@ public:
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);
@@ -1880,7 +2006,7 @@ public:
void mergeDeclAttributes(NamedDecl *New, Decl *Old,
AvailabilityMergeKind AMK = AMK_Redeclaration);
void MergeTypedefNameDecl(TypedefNameDecl *New, LookupResult &OldDecls);
- bool MergeFunctionDecl(FunctionDecl *New, Decl *Old, Scope *S,
+ bool MergeFunctionDecl(FunctionDecl *New, NamedDecl *&Old, Scope *S,
bool MergeTypeWithOld);
bool MergeCompatibleFunctionDecls(FunctionDecl *New, FunctionDecl *Old,
Scope *S, bool MergeTypeWithOld);
@@ -1951,9 +2077,9 @@ public:
QualType &ConvertedType);
bool IsBlockPointerConversion(QualType FromType, QualType ToType,
QualType& ConvertedType);
- bool FunctionArgTypesAreEqual(const FunctionProtoType *OldType,
- const FunctionProtoType *NewType,
- unsigned *ArgPos = 0);
+ bool FunctionParamTypesAreEqual(const FunctionProtoType *OldType,
+ const FunctionProtoType *NewType,
+ unsigned *ArgPos = nullptr);
void HandleFunctionTypeMismatch(PartialDiagnostic &PDiag,
QualType FromType, QualType ToType);
@@ -2067,10 +2193,10 @@ public:
AllowScopedEnumerations(AllowScopedEnumerations) {}
/// Match an integral or (possibly scoped) enumeration type.
- bool match(QualType T);
+ bool match(QualType T) override;
SemaDiagnosticBuilder
- diagnoseNoMatch(Sema &S, SourceLocation Loc, QualType T) {
+ diagnoseNoMatch(Sema &S, SourceLocation Loc, QualType T) override {
return diagnoseNotInt(S, Loc, T);
}
@@ -2123,10 +2249,10 @@ public:
bool PartialOverloading = false,
bool AllowExplicit = false);
void AddFunctionCandidates(const UnresolvedSetImpl &Functions,
- ArrayRef<Expr *> Args,
- OverloadCandidateSet& CandidateSet,
- bool SuppressUserConversions = false,
- TemplateArgumentListInfo *ExplicitTemplateArgs = 0);
+ ArrayRef<Expr *> Args,
+ OverloadCandidateSet &CandidateSet,
+ bool SuppressUserConversions = false,
+ TemplateArgumentListInfo *ExplicitTemplateArgs = nullptr);
void AddMethodCandidate(DeclAccessPair FoundDecl,
QualType ObjectType,
Expr::Classification ObjectClassification,
@@ -2160,13 +2286,13 @@ public:
CXXRecordDecl *ActingContext,
Expr *From, QualType ToType,
OverloadCandidateSet& CandidateSet,
- bool AllowObjCConversionOnExplicit = false);
+ bool AllowObjCConversionOnExplicit);
void AddTemplateConversionCandidate(FunctionTemplateDecl *FunctionTemplate,
DeclAccessPair FoundDecl,
CXXRecordDecl *ActingContext,
Expr *From, QualType ToType,
OverloadCandidateSet &CandidateSet,
- bool AllowObjCConversionOnExplicit = false);
+ bool AllowObjCConversionOnExplicit);
void AddSurrogateCandidate(CXXConversionDecl *Conversion,
DeclAccessPair FoundDecl,
CXXRecordDecl *ActingContext,
@@ -2186,7 +2312,7 @@ public:
SourceLocation OpLoc, ArrayRef<Expr *> Args,
OverloadCandidateSet& CandidateSet);
void AddArgumentDependentLookupCandidates(DeclarationName Name,
- bool Operator, SourceLocation Loc,
+ SourceLocation Loc,
ArrayRef<Expr *> Args,
TemplateArgumentListInfo *ExplicitTemplateArgs,
OverloadCandidateSet& CandidateSet,
@@ -2199,6 +2325,11 @@ public:
// identified by the expression Expr
void NoteAllOverloadCandidates(Expr* E, QualType DestType = QualType());
+ /// 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);
+
// [PossiblyAFunctionType] --> [Return]
// NonFunctionType --> NonFunctionType
// R (A) --> R(A)
@@ -2212,11 +2343,12 @@ public:
QualType TargetType,
bool Complain,
DeclAccessPair &Found,
- bool *pHadMultipleCandidates = 0);
+ bool *pHadMultipleCandidates = nullptr);
- FunctionDecl *ResolveSingleFunctionTemplateSpecialization(OverloadExpr *ovl,
- bool Complain = false,
- DeclAccessPair* Found = 0);
+ FunctionDecl *
+ ResolveSingleFunctionTemplateSpecialization(OverloadExpr *ovl,
+ bool Complain = false,
+ DeclAccessPair *Found = nullptr);
bool ResolveAndFixSingleFunctionTemplateSpecialization(
ExprResult &SrcExpr,
@@ -2302,7 +2434,7 @@ public:
ExprResult BuildOverloadedArrowExpr(Scope *S, Expr *Base,
SourceLocation OpLoc,
- bool *NoArrowOperatorFound = 0);
+ 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
@@ -2468,6 +2600,9 @@ public:
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());
@@ -2484,6 +2619,7 @@ public:
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,
@@ -2491,10 +2627,8 @@ public:
bool AllowStringTemplate);
bool isKnownName(StringRef name);
- void ArgumentDependentLookup(DeclarationName Name, bool Operator,
- SourceLocation Loc,
- ArrayRef<Expr *> Args,
- ADLResult &Functions);
+ void ArgumentDependentLookup(DeclarationName Name, SourceLocation Loc,
+ ArrayRef<Expr *> Args, ADLResult &Functions);
void LookupVisibleDecls(Scope *S, LookupNameKind Kind,
VisibleDeclConsumer &Consumer,
@@ -2503,13 +2637,19 @@ public:
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,
CorrectionCandidateCallback &CCC,
- DeclContext *MemberContext = 0,
+ CorrectTypoKind Mode,
+ DeclContext *MemberContext = nullptr,
bool EnteringContext = false,
- const ObjCObjectPointerType *OPT = 0,
+ const ObjCObjectPointerType *OPT = nullptr,
bool RecordFailure = true);
void diagnoseTypo(const TypoCorrection &Correction,
@@ -2527,8 +2667,7 @@ public:
AssociatedClassSet &AssociatedClasses);
void FilterLookupForScope(LookupResult &R, DeclContext *Ctx, Scope *S,
- bool ConsiderLinkage,
- bool ExplicitInstantiationOrSpecialization);
+ bool ConsiderLinkage, bool AllowInlineNamespace);
void DiagnoseAmbiguousLookup(LookupResult &Result);
//@}
@@ -2557,11 +2696,14 @@ public:
bool CheckRegparmAttr(const AttributeList &attr, unsigned &value);
bool CheckCallingConvAttr(const AttributeList &attr, CallingConv &CC,
- const FunctionDecl *FD = 0);
+ const FunctionDecl *FD = nullptr);
bool CheckNoReturnAttr(const AttributeList &attr);
bool checkStringLiteralArgumentAttr(const AttributeList &Attr,
unsigned ArgNum, StringRef &Str,
- SourceLocation *ArgLocation = 0);
+ SourceLocation *ArgLocation = nullptr);
+ bool checkMSInheritanceAttrOnDefinition(
+ CXXRecordDecl *RD, SourceRange Range, bool BestCase,
+ MSInheritanceAttr::Spelling SemanticSpelling);
void CheckAlignasUnderalignment(Decl *D);
@@ -2570,6 +2712,11 @@ public:
/// function type typedefs and typename template arguments.
void adjustMemberFunctionCC(QualType &T, bool IsStatic);
+ // 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;
@@ -2578,8 +2725,6 @@ public:
StmtResult ProcessStmtAttributes(Stmt *Stmt, AttributeList *Attrs,
SourceRange Range);
- void WarnUndefinedMethod(SourceLocation ImpLoc, ObjCMethodDecl *method,
- bool &IncompleteImpl, unsigned DiagID);
void WarnConflictingTypedMethods(ObjCMethodDecl *Method,
ObjCMethodDecl *MethodDecl,
bool IsProtocolMethodDecl);
@@ -2597,15 +2742,6 @@ public:
typedef llvm::SmallPtrSet<Selector, 8> SelectorSet;
typedef llvm::DenseMap<Selector, ObjCMethodDecl*> ProtocolsMethodsMap;
- /// CheckProtocolMethodDefs - This routine checks unimplemented
- /// methods declared in protocol, and those referenced by it.
- void CheckProtocolMethodDefs(SourceLocation ImpLoc,
- ObjCProtocolDecl *PDecl,
- bool& IncompleteImpl,
- const SelectorSet &InsMap,
- const SelectorSet &ClsMap,
- ObjCContainerDecl *CDecl);
-
/// CheckImplementationIvars - This routine checks if the instance variables
/// listed in the implelementation match those listed in the interface.
void CheckImplementationIvars(ObjCImplementationDecl *ImpDecl,
@@ -2621,7 +2757,8 @@ public:
/// DiagnoseUnimplementedProperties - This routine warns on those properties
/// which must be implemented by this implementation.
void DiagnoseUnimplementedProperties(Scope *S, ObjCImplDecl* IMPDecl,
- ObjCContainerDecl *CDecl);
+ ObjCContainerDecl *CDecl,
+ bool SynthesizeProperties);
/// DefaultSynthesizeProperties - This routine default synthesizes all
/// properties which must be synthesized in the class's \@implementation.
@@ -2629,12 +2766,6 @@ public:
ObjCInterfaceDecl *IDecl);
void DefaultSynthesizeProperties(Scope *S, Decl *D);
- /// CollectImmediateProperties - This routine collects all properties in
- /// the class and its conforming protocols; but not those it its super class.
- void CollectImmediateProperties(ObjCContainerDecl *CDecl,
- llvm::DenseMap<IdentifierInfo *, ObjCPropertyDecl*>& PropMap,
- llvm::DenseMap<IdentifierInfo *, ObjCPropertyDecl*>& SuperPropMap);
-
/// IvarBacksCurrentMethodAccessor - This routine returns 'true' if 'IV' is
/// an ivar synthesized for 'Method' and 'Method' is a property accessor
/// declared in class 'IFace'.
@@ -2643,7 +2774,8 @@ public:
/// DiagnoseUnusedBackingIvarInAccessor - Issue an 'unused' warning if ivar which
/// backs the property is not used in the property's accessor.
- void DiagnoseUnusedBackingIvarInAccessor(Scope *S);
+ 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.
@@ -2682,7 +2814,7 @@ public:
const unsigned AttributesAsWritten,
TypeSourceInfo *T,
tok::ObjCKeywordKind MethodImplKind,
- DeclContext *lexicalDC = 0);
+ DeclContext *lexicalDC = nullptr);
/// AtomicPropertySetterGetterRules - This routine enforces the rule (via
/// warning) when atomic property has one but not the other user-declared
@@ -2692,6 +2824,10 @@ public:
void DiagnoseOwningPropertyGetterSynthesis(const ObjCImplementationDecl *D);
+ void DiagnoseMissingDesignatedInitOverrides(
+ const ObjCImplementationDecl *ImplD,
+ const ObjCInterfaceDecl *IFD);
+
void DiagnoseDuplicateIvars(ObjCInterfaceDecl *ID, ObjCInterfaceDecl *SID);
enum MethodMatchStrategy {
@@ -2785,12 +2921,6 @@ public:
const ObjCMethodDecl *SelectorsForTypoCorrection(Selector Sel,
QualType ObjectType=QualType());
-
- /// DiagnoseMismatchedMethodsInGlobalPool - This routine goes through list of
- /// methods in global pool and issues diagnostic on identical selectors which
- /// have mismathched types.
- void DiagnoseMismatchedMethodsInGlobalPool();
-
/// LookupImplementedMethodInGlobalPool - Returns the method which has an
/// implementation.
ObjCMethodDecl *LookupImplementedMethodInGlobalPool(Selector Sel);
@@ -2805,7 +2935,7 @@ public:
public:
class FullExprArg {
public:
- FullExprArg(Sema &actions) : E(0) { }
+ FullExprArg(Sema &actions) : E(nullptr) { }
// FIXME: The const_cast here is ugly. RValue references would make this
// much nicer (or we could duplicate a bunch of the move semantics
@@ -2836,13 +2966,13 @@ public:
return MakeFullExpr(Arg, Arg ? Arg->getExprLoc() : SourceLocation());
}
FullExprArg MakeFullExpr(Expr *Arg, SourceLocation CC) {
- return FullExprArg(ActOnFinishFullExpr(Arg, CC).release());
+ return FullExprArg(ActOnFinishFullExpr(Arg, CC).get());
}
FullExprArg MakeFullDiscardedValueExpr(Expr *Arg) {
ExprResult FE =
ActOnFinishFullExpr(Arg, Arg ? Arg->getExprLoc() : SourceLocation(),
/*DiscardedValue*/ true);
- return FullExprArg(FE.release());
+ return FullExprArg(FE.get());
}
StmtResult ActOnExprStmt(ExprResult Arg);
@@ -2957,15 +3087,23 @@ public:
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);
- const VarDecl *getCopyElisionCandidate(QualType ReturnType, Expr *E,
- bool AllowFunctionParameters);
-
- StmtResult ActOnReturnStmt(SourceLocation ReturnLoc, Expr *RetValExp);
+ 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,
@@ -2978,7 +3116,7 @@ public:
ExprResult LookupInlineAsmIdentifier(CXXScopeSpec &SS,
SourceLocation TemplateKWLoc,
UnqualifiedId &Id,
- InlineAsmIdentifierInfo &Info,
+ llvm::InlineAsmIdentifierInfo &Info,
bool IsUnevaluatedContext);
bool LookupInlineAsmField(StringRef Base, StringRef Member,
unsigned &Offset, SourceLocation AsmLoc);
@@ -3031,14 +3169,12 @@ public:
StmtResult ActOnSEHTryBlock(bool IsCXXTry, // try (true) or __try (false) ?
SourceLocation TryLoc, Stmt *TryBlock,
- Stmt *Handler);
-
- StmtResult ActOnSEHExceptBlock(SourceLocation Loc,
- Expr *FilterExpr,
+ Stmt *Handler, int HandlerIndex,
+ int HandlerParentIndex);
+ StmtResult ActOnSEHExceptBlock(SourceLocation Loc, Expr *FilterExpr,
Stmt *Block);
-
- StmtResult ActOnSEHFinallyBlock(SourceLocation Loc,
- Stmt *Block);
+ StmtResult ActOnSEHFinallyBlock(SourceLocation Loc, Stmt *Block);
+ StmtResult ActOnSEHLeaveStmt(SourceLocation Loc, Scope *CurScope);
void DiagnoseReturnInConstructorExceptionHandler(CXXTryStmt *TryBlock);
@@ -3083,12 +3219,16 @@ public:
void redelayDiagnostics(sema::DelayedDiagnosticPool &pool);
- void EmitDeprecationWarning(NamedDecl *D, StringRef Message,
- SourceLocation Loc,
- const ObjCInterfaceDecl *UnknownObjCClass,
- const ObjCPropertyDecl *ObjCProperty);
+ enum AvailabilityDiagnostic { AD_Deprecation, AD_Unavailable };
+
+ void EmitAvailabilityWarning(AvailabilityDiagnostic AD,
+ NamedDecl *D, StringRef Message,
+ SourceLocation Loc,
+ const ObjCInterfaceDecl *UnknownObjCClass,
+ const ObjCPropertyDecl *ObjCProperty,
+ bool ObjCPropertyAccess);
- void HandleDelayedDeprecationCheck(sema::DelayedDiagnostic &DD, Decl *Ctx);
+ void HandleDelayedAvailabilityCheck(sema::DelayedDiagnostic &DD, Decl *Ctx);
bool makeUnavailableInSystemHeader(SourceLocation loc,
StringRef message);
@@ -3098,7 +3238,8 @@ public:
bool CanUseDecl(NamedDecl *D);
bool DiagnoseUseOfDecl(NamedDecl *D, SourceLocation Loc,
- const ObjCInterfaceDecl *UnknownObjCClass=0);
+ const ObjCInterfaceDecl *UnknownObjCClass=nullptr,
+ bool ObjCPropertyAccess=false);
void NoteDeletedFunction(FunctionDecl *FD);
std::string getDeletedOrUnavailableSuffix(const FunctionDecl *FD);
bool DiagnosePropertyAccessorMismatch(ObjCPropertyDecl *PD,
@@ -3108,7 +3249,7 @@ public:
ArrayRef<Expr *> Args);
void PushExpressionEvaluationContext(ExpressionEvaluationContext NewContext,
- Decl *LambdaContextDecl = 0,
+ Decl *LambdaContextDecl = nullptr,
bool IsDecltype = false);
enum ReuseLambdaContextDecl_t { ReuseLambdaContextDecl };
void PushExpressionEvaluationContext(ExpressionEvaluationContext NewContext,
@@ -3199,7 +3340,7 @@ public:
/// emitted; this may also leave the ExprResult invalid.
bool tryToRecoverWithCall(ExprResult &E, const PartialDiagnostic &PD,
bool ForceComplain = false,
- bool (*IsPlausibleResult)(QualType) = 0);
+ bool (*IsPlausibleResult)(QualType) = nullptr);
/// \brief Figure out if an expression could be turned into a call.
bool tryExprAsCall(Expr &E, QualType &ZeroArgCallReturnTy,
@@ -3222,7 +3363,7 @@ public:
SourceLocation TemplateKWLoc,
UnqualifiedId &Id,
bool HasTrailingLParen, bool IsAddressOfOperand,
- CorrectionCandidateCallback *CCC = 0,
+ CorrectionCandidateCallback *CCC = nullptr,
bool IsInlineAsmIdentifier = false);
void DecomposeUnqualifiedId(const UnqualifiedId &Id,
@@ -3230,10 +3371,11 @@ public:
DeclarationNameInfo &NameInfo,
const TemplateArgumentListInfo *&TemplateArgs);
- bool DiagnoseEmptyLookup(Scope *S, CXXScopeSpec &SS, LookupResult &R,
- CorrectionCandidateCallback &CCC,
- TemplateArgumentListInfo *ExplicitTemplateArgs = 0,
- ArrayRef<Expr *> Args = None);
+ bool
+ DiagnoseEmptyLookup(Scope *S, CXXScopeSpec &SS, LookupResult &R,
+ CorrectionCandidateCallback &CCC,
+ TemplateArgumentListInfo *ExplicitTemplateArgs = nullptr,
+ ArrayRef<Expr *> Args = None);
ExprResult LookupInObjCMethod(LookupResult &LookUp, Scope *S,
IdentifierInfo *II,
@@ -3248,18 +3390,20 @@ public:
ExprResult BuildDeclRefExpr(ValueDecl *D, QualType Ty,
ExprValueKind VK,
SourceLocation Loc,
- const CXXScopeSpec *SS = 0);
- ExprResult BuildDeclRefExpr(ValueDecl *D, QualType Ty, ExprValueKind VK,
- const DeclarationNameInfo &NameInfo,
- const CXXScopeSpec *SS = 0, NamedDecl *FoundD = 0,
- const TemplateArgumentListInfo *TemplateArgs = 0);
+ 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(0, AS_none),
- Expr *baseObjectExpr = 0,
+ DeclAccessPair FoundDecl = DeclAccessPair::make(nullptr, AS_none),
+ Expr *baseObjectExpr = nullptr,
SourceLocation opLoc = SourceLocation());
ExprResult BuildPossibleImplicitMemberExpr(const CXXScopeSpec &SS,
@@ -3275,9 +3419,10 @@ public:
const LookupResult &R,
bool HasTrailingLParen);
- ExprResult BuildQualifiedDeclarationNameExpr(CXXScopeSpec &SS,
- const DeclarationNameInfo &NameInfo,
- bool IsAddressOfOperand);
+ ExprResult BuildQualifiedDeclarationNameExpr(
+ CXXScopeSpec &SS, const DeclarationNameInfo &NameInfo,
+ bool IsAddressOfOperand, TypeSourceInfo **RecoveryTSI = nullptr);
+
ExprResult BuildDependentDeclRefExpr(const CXXScopeSpec &SS,
SourceLocation TemplateKWLoc,
const DeclarationNameInfo &NameInfo,
@@ -3288,20 +3433,22 @@ public:
bool NeedsADL);
ExprResult BuildDeclarationNameExpr(
const CXXScopeSpec &SS, const DeclarationNameInfo &NameInfo, NamedDecl *D,
- NamedDecl *FoundD = 0, const TemplateArgumentListInfo *TemplateArgs = 0);
+ NamedDecl *FoundD = nullptr,
+ const TemplateArgumentListInfo *TemplateArgs = nullptr);
ExprResult BuildLiteralOperatorCall(LookupResult &R,
- DeclarationNameInfo &SuffixInfo,
- ArrayRef<Expr*> Args,
- SourceLocation LitEndLoc,
- TemplateArgumentListInfo *ExplicitTemplateArgs = 0);
+ 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);
- ExprResult ActOnNumericConstant(const Token &Tok, Scope *UDLScope = 0);
- ExprResult ActOnCharacterConstant(const Token &Tok, Scope *UDLScope = 0);
+ 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,
@@ -3309,8 +3456,8 @@ public:
/// ActOnStringLiteral - The specified tokens were lexed as pasted string
/// fragments (e.g. "foo" "bar" L"baz").
- ExprResult ActOnStringLiteral(const Token *StringToks, unsigned NumStringToks,
- Scope *UDLScope = 0);
+ ExprResult ActOnStringLiteral(ArrayRef<Token> StringToks,
+ Scope *UDLScope = nullptr);
ExprResult ActOnGenericSelectionExpr(SourceLocation KeyLoc,
SourceLocation DefaultLoc,
@@ -3367,14 +3514,6 @@ public:
ExprResult CreateBuiltinArraySubscriptExpr(Expr *Base, SourceLocation LLoc,
Expr *Idx, SourceLocation RLoc);
- ExprResult BuildMemberReferenceExpr(Expr *Base, QualType BaseType,
- SourceLocation OpLoc, bool IsArrow,
- CXXScopeSpec &SS,
- SourceLocation TemplateKWLoc,
- NamedDecl *FirstQualifierInScope,
- const DeclarationNameInfo &NameInfo,
- const TemplateArgumentListInfo *TemplateArgs);
-
// 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
@@ -3387,22 +3526,23 @@ public:
bool HasTrailingLParen;
};
- ExprResult BuildMemberReferenceExpr(Expr *Base, QualType BaseType,
- SourceLocation OpLoc, bool IsArrow,
- const CXXScopeSpec &SS,
- SourceLocation TemplateKWLoc,
- NamedDecl *FirstQualifierInScope,
- LookupResult &R,
- const TemplateArgumentListInfo *TemplateArgs,
- bool SuppressQualifierCheck = false,
- ActOnMemberAccessExtraArgs *ExtraArgs = 0);
+ ExprResult BuildMemberReferenceExpr(
+ Expr *Base, QualType BaseType, SourceLocation OpLoc, bool IsArrow,
+ CXXScopeSpec &SS, SourceLocation TemplateKWLoc,
+ NamedDecl *FirstQualifierInScope, const DeclarationNameInfo &NameInfo,
+ const TemplateArgumentListInfo *TemplateArgs,
+ 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,
+ bool SuppressQualifierCheck = false,
+ ActOnMemberAccessExtraArgs *ExtraArgs = nullptr);
ExprResult PerformMemberExprBaseConversion(Expr *Base, bool IsArrow);
- ExprResult LookupMemberExpr(LookupResult &R, ExprResult &Base,
- bool &IsArrow, SourceLocation OpLoc,
- CXXScopeSpec &SS,
- Decl *ObjCImpDecl,
- bool HasTemplateArgs);
bool CheckQualifiedMemberReference(Expr *BaseExpr, QualType BaseType,
const CXXScopeSpec &SS,
@@ -3441,12 +3581,13 @@ public:
/// locations.
ExprResult ActOnCallExpr(Scope *S, Expr *Fn, SourceLocation LParenLoc,
MultiExprArg ArgExprs, SourceLocation RParenLoc,
- Expr *ExecConfig = 0, bool IsExecConfig = false);
+ Expr *ExecConfig = nullptr,
+ bool IsExecConfig = false);
ExprResult BuildResolvedCallExpr(Expr *Fn, NamedDecl *NDecl,
SourceLocation LParenLoc,
ArrayRef<Expr *> Arg,
SourceLocation RParenLoc,
- Expr *Config = 0,
+ Expr *Config = nullptr,
bool IsExecConfig = false);
ExprResult ActOnCUDAExecConfigExpr(Scope *S, SourceLocation LLLLoc,
@@ -3682,12 +3823,13 @@ public:
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,
- const DeclarationNameInfo &NameInfo,
+ DeclarationNameInfo NameInfo,
AttributeList *AttrList,
bool IsInstantiation,
bool HasTypenameKeyword,
@@ -3720,16 +3862,18 @@ public:
BuildCXXConstructExpr(SourceLocation ConstructLoc, QualType DeclInitType,
CXXConstructorDecl *Constructor, MultiExprArg Exprs,
bool HadMultipleCandidates, bool IsListInitialization,
+ bool IsStdInitListInitialization,
bool RequiresZeroInit, unsigned ConstructKind,
SourceRange ParenRange);
- // FIXME: Can re remove this and have the above BuildCXXConstructExpr check if
+ // 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 RequiresZeroInit,
+ bool IsListInitialization,
+ bool IsStdInitListInitialization, bool RequiresZeroInit,
unsigned ConstructKind, SourceRange ParenRange);
/// BuildCXXDefaultArgExpr - Creates a CXXDefaultArgExpr, instantiating
@@ -3801,7 +3945,7 @@ public:
/// potential exceptions of the special member function contains "any"
EPI.ExceptionSpecType = EST_ComputedNoexcept;
EPI.NoexceptExpr = Self->ActOnCXXBoolLiteral(SourceLocation(),
- tok::kw_false).take();
+ tok::kw_false).get();
}
}
FunctionProtoType::ExtProtoInfo getEPI() const {
@@ -4111,7 +4255,7 @@ public:
/// \return returns 'true' if failed, 'false' if success.
bool CheckCXXThisCapture(SourceLocation Loc, bool Explicit = false,
bool BuildAndDiagnose = true,
- const unsigned *const FunctionScopeIndexToStopAt = 0);
+ 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
@@ -4208,32 +4352,6 @@ public:
ExprResult BuildCXXNoexceptExpr(SourceLocation KeyLoc, Expr *Operand,
SourceLocation RParen);
- /// ActOnUnaryTypeTrait - Parsed one of the unary type trait support
- /// pseudo-functions.
- ExprResult ActOnUnaryTypeTrait(UnaryTypeTrait OTT,
- SourceLocation KWLoc,
- ParsedType Ty,
- SourceLocation RParen);
-
- ExprResult BuildUnaryTypeTrait(UnaryTypeTrait OTT,
- SourceLocation KWLoc,
- TypeSourceInfo *T,
- SourceLocation RParen);
-
- /// ActOnBinaryTypeTrait - Parsed one of the bianry type trait support
- /// pseudo-functions.
- ExprResult ActOnBinaryTypeTrait(BinaryTypeTrait OTT,
- SourceLocation KWLoc,
- ParsedType LhsTy,
- ParsedType RhsTy,
- SourceLocation RParen);
-
- ExprResult BuildBinaryTypeTrait(BinaryTypeTrait BTT,
- SourceLocation KWLoc,
- TypeSourceInfo *LhsT,
- TypeSourceInfo *RhsT,
- SourceLocation RParen);
-
/// \brief Parsed one of the type trait support pseudo-functions.
ExprResult ActOnTypeTrait(TypeTrait Kind, SourceLocation KWLoc,
ArrayRef<ParsedType> Args,
@@ -4359,7 +4477,8 @@ public:
bool EnteringContext,
CXXScopeSpec &SS,
NamedDecl *ScopeLookupResult,
- bool ErrorRecoveryLookup);
+ bool ErrorRecoveryLookup,
+ bool *IsCorrectedToColon = nullptr);
/// \brief The parser has parsed a nested-name-specifier 'identifier::'.
///
@@ -4382,6 +4501,13 @@ public:
/// 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,
@@ -4389,7 +4515,9 @@ public:
SourceLocation CCLoc,
ParsedType ObjectType,
bool EnteringContext,
- CXXScopeSpec &SS);
+ CXXScopeSpec &SS,
+ bool ErrorRecoveryLookup = false,
+ bool *IsCorrectedToColon = nullptr);
ExprResult ActOnDecltypeExpression(Expr *E);
@@ -4632,7 +4760,8 @@ public:
SourceLocation AtLoc,
SourceLocation SelLoc,
SourceLocation LParenLoc,
- SourceLocation RParenLoc);
+ SourceLocation RParenLoc,
+ bool WarnMultipleSelectors);
/// ParseObjCProtocolExpression - Build protocol expression for \@protocol
ExprResult ParseObjCProtocolExpression(IdentifierInfo * ProtocolName,
@@ -4647,8 +4776,7 @@ public:
//
Decl *ActOnStartLinkageSpecification(Scope *S,
SourceLocation ExternLoc,
- SourceLocation LangLoc,
- StringRef Lang,
+ Expr *LangStr,
SourceLocation LBraceLoc);
Decl *ActOnFinishLinkageSpecification(Scope *S,
Decl *LinkageSpec,
@@ -4659,21 +4787,24 @@ public:
// C++ Classes
//
bool isCurrentClassName(const IdentifierInfo &II, Scope *S,
- const CXXScopeSpec *SS = 0);
+ const CXXScopeSpec *SS = nullptr);
bool isCurrentClassNameTypo(IdentifierInfo *&II, const CXXScopeSpec *SS);
bool ActOnAccessSpecifier(AccessSpecifier Access,
SourceLocation ASLoc,
SourceLocation ColonLoc,
- AttributeList *Attrs = 0);
+ AttributeList *Attrs = nullptr);
NamedDecl *ActOnCXXMemberDeclarator(Scope *S, AccessSpecifier AS,
Declarator &D,
MultiTemplateParamsArg TemplateParameterLists,
Expr *BitfieldWidth, const VirtSpecifiers &VS,
InClassInitStyle InitStyle);
- void ActOnCXXInClassMemberInitializer(Decl *VarDecl, SourceLocation EqualLoc,
- Expr *Init);
+
+ void ActOnStartCXXInClassMemberInitializer();
+ void ActOnFinishCXXInClassMemberInitializer(Decl *VarDecl,
+ SourceLocation EqualLoc,
+ Expr *Init);
MemInitResult ActOnMemInitializer(Decl *ConstructorD,
Scope *S,
@@ -4799,8 +4930,8 @@ public:
AttributeList *AttrList);
void ActOnFinishCXXMemberDecls();
- void ActOnReenterTemplateScope(Scope *S, Decl *Template);
- void ActOnReenterDeclaratorTemplateScope(Scope *S, DeclaratorDecl *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);
@@ -4879,7 +5010,7 @@ public:
bool CheckDerivedToBaseConversion(QualType Derived, QualType Base,
SourceLocation Loc, SourceRange Range,
- CXXCastPath *BasePath = 0,
+ CXXCastPath *BasePath = nullptr,
bool IgnoreAccess = false);
bool CheckDerivedToBaseConversion(QualType Derived, QualType Base,
unsigned InaccessibleBaseID,
@@ -5067,7 +5198,7 @@ public:
void DiagnoseTemplateParameterShadow(SourceLocation Loc, Decl *PrevDecl);
TemplateDecl *AdjustDeclIfTemplate(Decl *&Decl);
- Decl *ActOnTypeParameter(Scope *S, bool Typename, bool Ellipsis,
+ Decl *ActOnTypeParameter(Scope *S, bool Typename,
SourceLocation EllipsisLoc,
SourceLocation KeyLoc,
IdentifierInfo *ParamName,
@@ -5118,7 +5249,8 @@ public:
TemplateParamListContext TPC);
TemplateParameterList *MatchTemplateParametersToScopeSpecifier(
SourceLocation DeclStartLoc, SourceLocation DeclLoc,
- const CXXScopeSpec &SS, ArrayRef<TemplateParameterList *> ParamLists,
+ const CXXScopeSpec &SS, TemplateIdAnnotation *TemplateId,
+ ArrayRef<TemplateParameterList *> ParamLists,
bool IsFriend, bool &IsExplicitSpecialization, bool &Invalid);
DeclResult CheckClassTemplate(Scope *S, unsigned TagSpec, TagUseKind TUK,
@@ -5128,6 +5260,7 @@ public:
TemplateParameterList *TemplateParams,
AccessSpecifier AS,
SourceLocation ModulePrivateLoc,
+ SourceLocation FriendLoc,
unsigned NumOuterTemplateParamLists,
TemplateParameterList **OuterTemplateParamLists);
@@ -5162,7 +5295,7 @@ public:
SourceLocation RAngleLoc);
DeclResult ActOnVarTemplateSpecialization(
- Scope *S, VarTemplateDecl *VarTemplate, Declarator &D, TypeSourceInfo *DI,
+ Scope *S, Declarator &D, TypeSourceInfo *DI,
SourceLocation TemplateKWLoc, TemplateParameterList *TemplateParams,
StorageClass SC, bool IsPartialSpecialization);
@@ -5200,12 +5333,7 @@ public:
ActOnClassTemplateSpecialization(Scope *S, unsigned TagSpec, TagUseKind TUK,
SourceLocation KWLoc,
SourceLocation ModulePrivateLoc,
- CXXScopeSpec &SS,
- TemplateTy Template,
- SourceLocation TemplateNameLoc,
- SourceLocation LAngleLoc,
- ASTTemplateArgsPtr TemplateArgs,
- SourceLocation RAngleLoc,
+ TemplateIdAnnotation &TemplateId,
AttributeList *Attr,
MultiTemplateParamsArg TemplateParameterLists);
@@ -5290,7 +5418,7 @@ public:
};
bool CheckTemplateArgument(NamedDecl *Param,
- const TemplateArgumentLoc &Arg,
+ TemplateArgumentLoc &Arg,
NamedDecl *Template,
SourceLocation TemplateLoc,
SourceLocation RAngleLoc,
@@ -5318,21 +5446,15 @@ public:
/// \param Converted Will receive the converted, canonicalized template
/// arguments.
///
- ///
- /// \param ExpansionIntoFixedList If non-NULL, will be set true to indicate
- /// when the template arguments contain a pack expansion that is being
- /// expanded into a fixed parameter list.
- ///
- /// \returns True if an error occurred, false otherwise.
+ /// \returns true if an error occurred, false otherwise.
bool CheckTemplateArgumentList(TemplateDecl *Template,
SourceLocation TemplateLoc,
TemplateArgumentListInfo &TemplateArgs,
bool PartialTemplateArgs,
- SmallVectorImpl<TemplateArgument> &Converted,
- bool *ExpansionIntoFixedList = 0);
+ SmallVectorImpl<TemplateArgument> &Converted);
bool CheckTemplateTypeArgument(TemplateTypeParmDecl *Param,
- const TemplateArgumentLoc &Arg,
+ TemplateArgumentLoc &Arg,
SmallVectorImpl<TemplateArgument> &Converted);
bool CheckTemplateArgument(TemplateTypeParmDecl *Param,
@@ -5342,7 +5464,7 @@ public:
TemplateArgument &Converted,
CheckTemplateArgumentKind CTAK = CTAK_Specified);
bool CheckTemplateArgument(TemplateTemplateParmDecl *Param,
- const TemplateArgumentLoc &Arg,
+ TemplateArgumentLoc &Arg,
unsigned ArgumentPackIndex);
ExprResult
@@ -5880,7 +6002,7 @@ public:
unsigned NumExplicitlySpecified,
FunctionDecl *&Specialization,
sema::TemplateDeductionInfo &Info,
- SmallVectorImpl<OriginalCallArg> const *OriginalCallArgs = 0);
+ SmallVectorImpl<OriginalCallArg> const *OriginalCallArgs = nullptr);
TemplateDeductionResult
DeduceTemplateArguments(FunctionTemplateDecl *FunctionTemplate,
@@ -5977,10 +6099,11 @@ public:
// C++ Template Instantiation
//
- MultiLevelTemplateArgumentList getTemplateInstantiationArgs(NamedDecl *D,
- const TemplateArgumentList *Innermost = 0,
- bool RelativeToPrimary = false,
- const FunctionDecl *Pattern = 0);
+ 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 {
@@ -6055,8 +6178,8 @@ public:
SourceRange InstantiationRange;
ActiveTemplateInstantiation()
- : Kind(TemplateInstantiation), Template(0), Entity(0), TemplateArgs(0),
- NumTemplateArgs(0), DeductionInfo(0) {}
+ : 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.
@@ -6249,13 +6372,15 @@ public:
SourceRange InstantiationRange = SourceRange());
/// \brief Note that we are substituting prior template arguments into a
- /// non-type or template template parameter.
+ /// 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,
@@ -6287,6 +6412,15 @@ public:
bool CheckInstantiationDepth(SourceLocation PointOfInstantiation,
SourceRange InstantiationRange);
+ // FIXME: Replace this with a constructor once we can use delegating
+ // constructors in llvm.
+ void Initialize(
+ ActiveTemplateInstantiation::InstantiationKind Kind,
+ SourceLocation PointOfInstantiation, SourceRange InstantiationRange,
+ Decl *Entity, NamedDecl *Template = nullptr,
+ ArrayRef<TemplateArgument> TemplateArgs = ArrayRef<TemplateArgument>(),
+ sema::TemplateDeductionInfo *DeductionInfo = nullptr);
+
InstantiatingTemplate(const InstantiatingTemplate&) LLVM_DELETED_FUNCTION;
InstantiatingTemplate&
@@ -6472,7 +6606,7 @@ public:
ParmVarDecl **Params, unsigned NumParams,
const MultiLevelTemplateArgumentList &TemplateArgs,
SmallVectorImpl<QualType> &ParamTypes,
- SmallVectorImpl<ParmVarDecl *> *OutParams = 0);
+ SmallVectorImpl<ParmVarDecl *> *OutParams = nullptr);
ExprResult SubstExpr(Expr *E,
const MultiLevelTemplateArgumentList &TemplateArgs);
@@ -6536,8 +6670,8 @@ public:
void InstantiateAttrs(const MultiLevelTemplateArgumentList &TemplateArgs,
const Decl *Pattern, Decl *Inst,
- LateInstantiatedAttrVec *LateAttrs = 0,
- LocalInstantiationScope *OuterMostScope = 0);
+ LateInstantiatedAttrVec *LateAttrs = nullptr,
+ LocalInstantiationScope *OuterMostScope = nullptr);
bool
InstantiateClassTemplateSpecialization(SourceLocation PointOfInstantiation,
@@ -6582,8 +6716,8 @@ public:
const TemplateArgumentListInfo &TemplateArgsInfo,
SmallVectorImpl<TemplateArgument> &Converted,
SourceLocation PointOfInstantiation, void *InsertPos,
- LateInstantiatedAttrVec *LateAttrs = 0,
- LocalInstantiationScope *StartingScope = 0);
+ LateInstantiatedAttrVec *LateAttrs = nullptr,
+ LocalInstantiationScope *StartingScope = nullptr);
VarTemplateSpecializationDecl *CompleteVarTemplateSpecializationDecl(
VarTemplateSpecializationDecl *VarSpec, VarDecl *PatternDecl,
const MultiLevelTemplateArgumentList &TemplateArgs);
@@ -6717,8 +6851,8 @@ public:
/// \param lexicalDC Container for redeclaredProperty.
void ProcessPropertyDecl(ObjCPropertyDecl *property,
ObjCContainerDecl *CD,
- ObjCPropertyDecl *redeclaredProperty = 0,
- ObjCContainerDecl *lexicalDC = 0);
+ ObjCPropertyDecl *redeclaredProperty = nullptr,
+ ObjCContainerDecl *lexicalDC = nullptr);
void DiagnosePropertyMismatch(ObjCPropertyDecl *Property,
@@ -6739,7 +6873,7 @@ public:
Selector GetterSel, Selector SetterSel,
bool *OverridingProperty,
tok::ObjCKeywordKind MethodImplKind,
- DeclContext *lexicalDC = 0);
+ DeclContext *lexicalDC = nullptr);
Decl *ActOnPropertyImplDecl(Scope *S,
SourceLocation AtLoc,
@@ -6902,6 +7036,27 @@ public:
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
@@ -6969,6 +7124,69 @@ public:
/// \#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,
+ };
+
+ 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;
+ bool UnifySection(const StringRef &SectionName,
+ int SectionFlags,
+ DeclaratorDecl *TheDecl);
+ bool UnifySection(const 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);
@@ -7040,6 +7258,25 @@ public:
/// 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);
@@ -7052,11 +7289,15 @@ private:
/// \brief Initialization of data-sharing attributes stack.
void InitDataSharingAttributesStack();
void DestroyDataSharingAttributesStack();
+ ExprResult VerifyPositiveIntegerConstantInClause(Expr *Op,
+ OpenMPClauseKind CKind);
public:
+ 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);
+ const DeclarationNameInfo &DirName, Scope *CurScope,
+ SourceLocation Loc);
/// \brief Called on end of data sharing attribute block.
void EndOpenMPDSABlock(Stmt *CurDirective);
@@ -7070,12 +7311,15 @@ public:
DeclGroupPtrTy ActOnOpenMPThreadprivateDirective(
SourceLocation Loc,
ArrayRef<Expr *> VarList);
- // \brief Builds a new OpenMPThreadPrivateDecl and checks its correctness.
+ /// \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);
StmtResult ActOnOpenMPExecutableDirective(OpenMPDirectiveKind Kind,
+ const DeclarationNameInfo &DirName,
ArrayRef<OMPClause *> Clauses,
Stmt *AStmt,
SourceLocation StartLoc,
@@ -7086,6 +7330,100 @@ public:
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 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,
+ 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 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 flush'.
+ StmtResult ActOnOpenMPFlushDirective(ArrayRef<OMPClause *> Clauses,
+ SourceLocation StartLoc,
+ SourceLocation EndLoc);
+
+ OMPClause *ActOnOpenMPSingleExprClause(OpenMPClauseKind Kind,
+ Expr *Expr,
+ SourceLocation StartLoc,
+ SourceLocation LParenLoc,
+ SourceLocation EndLoc);
+ /// \brief Called on well-formed 'if' clause.
+ OMPClause *ActOnOpenMPIfClause(Expr *Condition, SourceLocation StartLoc,
+ SourceLocation LParenLoc,
+ 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 'collapse' clause.
+ OMPClause *ActOnOpenMPCollapseClause(Expr *NumForLoops,
+ SourceLocation StartLoc,
+ SourceLocation LParenLoc,
+ SourceLocation EndLoc);
OMPClause *ActOnOpenMPSimpleClause(OpenMPClauseKind Kind,
unsigned Argument,
@@ -7099,12 +7437,50 @@ public:
SourceLocation StartLoc,
SourceLocation LParenLoc,
SourceLocation EndLoc);
-
- OMPClause *ActOnOpenMPVarListClause(OpenMPClauseKind Kind,
- ArrayRef<Expr *> Vars,
- SourceLocation StartLoc,
- SourceLocation LParenLoc,
+ /// \brief Called on well-formed 'proc_bind' clause.
+ OMPClause *ActOnOpenMPProcBindClause(OpenMPProcBindClauseKind Kind,
+ SourceLocation KindLoc,
+ SourceLocation StartLoc,
+ SourceLocation LParenLoc,
+ SourceLocation EndLoc);
+
+ OMPClause *ActOnOpenMPSingleExprWithArgClause(OpenMPClauseKind Kind,
+ unsigned Argument, Expr *Expr,
+ SourceLocation StartLoc,
+ SourceLocation LParenLoc,
+ SourceLocation ArgumentLoc,
+ SourceLocation CommaLoc,
+ SourceLocation EndLoc);
+ /// \brief Called on well-formed 'schedule' clause.
+ OMPClause *ActOnOpenMPScheduleClause(OpenMPScheduleClauseKind Kind,
+ Expr *ChunkSize, SourceLocation StartLoc,
+ SourceLocation LParenLoc,
+ SourceLocation KindLoc,
+ SourceLocation CommaLoc,
+ SourceLocation EndLoc);
+
+ OMPClause *ActOnOpenMPClause(OpenMPClauseKind Kind, SourceLocation StartLoc,
+ SourceLocation EndLoc);
+ /// \brief Called on well-formed 'ordered' clause.
+ OMPClause *ActOnOpenMPOrderedClause(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);
+
+ OMPClause *
+ ActOnOpenMPVarListClause(OpenMPClauseKind Kind, ArrayRef<Expr *> Vars,
+ Expr *TailExpr, SourceLocation StartLoc,
+ SourceLocation LParenLoc, SourceLocation ColonLoc,
+ SourceLocation EndLoc,
+ CXXScopeSpec &ReductionIdScopeSpec,
+ const DeclarationNameInfo &ReductionId);
/// \brief Called on well-formed 'private' clause.
OMPClause *ActOnOpenMPPrivateClause(ArrayRef<Expr *> VarList,
SourceLocation StartLoc,
@@ -7115,11 +7491,52 @@ public:
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,
+ 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 The kind of conversion being performed.
enum CheckedConversionKind {
@@ -7138,7 +7555,7 @@ public:
/// 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 = 0,
+ const CXXCastPath *BasePath = nullptr,
CheckedConversionKind CCK
= CCK_ImplicitConversion);
@@ -7155,6 +7572,10 @@ public:
// 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);
@@ -7204,13 +7625,14 @@ public:
/// 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,
+ bool GatherArgumentsForCall(SourceLocation CallLoc, FunctionDecl *FDecl,
const FunctionProtoType *Proto,
- unsigned FirstProtoArg,
- ArrayRef<Expr *> Args,
+ unsigned FirstParam, ArrayRef<Expr *> Args,
SmallVectorImpl<Expr *> &AllArgs,
VariadicCallType CallType = VariadicDoesNotApply,
bool AllowExplicit = false,
@@ -7308,7 +7730,7 @@ public:
SourceLocation Loc,
QualType DstType, QualType SrcType,
Expr *SrcExpr, AssignmentAction Action,
- bool *Complained = 0);
+ bool *Complained = nullptr);
/// DiagnoseAssignmentEnum - Warn if assignment to enum is a constant
/// integer not in the range of enum values.
@@ -7379,10 +7801,10 @@ public:
bool IsCompAssign = false);
QualType CheckAdditionOperands( // C99 6.5.6
ExprResult &LHS, ExprResult &RHS, SourceLocation Loc, unsigned Opc,
- QualType* CompLHSTy = 0);
+ QualType* CompLHSTy = nullptr);
QualType CheckSubtractionOperands( // C99 6.5.6
ExprResult &LHS, ExprResult &RHS, SourceLocation Loc,
- QualType* CompLHSTy = 0);
+ QualType* CompLHSTy = nullptr);
QualType CheckShiftOperands( // C99 6.5.7
ExprResult &LHS, ExprResult &RHS, SourceLocation Loc, unsigned Opc,
bool IsCompAssign = false);
@@ -7415,15 +7837,15 @@ public:
ExprResult &cond, ExprResult &lhs, ExprResult &rhs,
ExprValueKind &VK, ExprObjectKind &OK, SourceLocation questionLoc);
QualType FindCompositePointerType(SourceLocation Loc, Expr *&E1, Expr *&E2,
- bool *NonStandardCompositeType = 0);
+ bool *NonStandardCompositeType = nullptr);
QualType FindCompositePointerType(SourceLocation Loc,
ExprResult &E1, ExprResult &E2,
- bool *NonStandardCompositeType = 0) {
- Expr *E1Tmp = E1.take(), *E2Tmp = E2.take();
+ bool *NonStandardCompositeType = nullptr) {
+ Expr *E1Tmp = E1.get(), *E2Tmp = E2.get();
QualType Composite = FindCompositePointerType(Loc, E1Tmp, E2Tmp,
NonStandardCompositeType);
- E1 = Owned(E1Tmp);
- E2 = Owned(E2Tmp);
+ E1 = E1Tmp;
+ E2 = E2Tmp;
return Composite;
}
@@ -7433,6 +7855,10 @@ public:
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);
@@ -7442,6 +7868,8 @@ public:
QualType CheckVectorLogicalOperands(ExprResult &LHS, ExprResult &RHS,
SourceLocation Loc);
+ bool isLaxVectorConversion(QualType srcType, QualType destType);
+
/// type checking declaration initializers (C99 6.7.8)
bool CheckForConstantInitializer(Expr *e, QualType t);
@@ -7514,7 +7942,9 @@ public:
ARCConversionResult CheckObjCARCConversion(SourceRange castRange,
QualType castType, Expr *&op,
CheckedConversionKind CCK,
- bool DiagnoseCFAudited = false);
+ bool DiagnoseCFAudited = false,
+ BinaryOperatorKind Opc = BO_PtrMemD
+ );
Expr *stripARCUnbridgedCast(Expr *e);
void diagnoseARCUnbridgedCast(Expr *e);
@@ -7622,7 +8052,8 @@ public:
ExprResult VerifyIntegerConstantExpression(Expr *E, llvm::APSInt *Result,
unsigned DiagID,
bool AllowFold = true);
- ExprResult VerifyIntegerConstantExpression(Expr *E, llvm::APSInt *Result=0);
+ 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.
@@ -7630,7 +8061,7 @@ public:
/// 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 = 0);
+ Expr *BitWidth, bool *ZeroWidth = nullptr);
enum CUDAFunctionTarget {
CFT_Device,
@@ -7754,7 +8185,7 @@ public:
void CodeCompleteObjCInstanceMessage(Scope *S, Expr *Receiver,
ArrayRef<IdentifierInfo *> SelIdents,
bool AtArgumentExpression,
- ObjCInterfaceDecl *Super = 0);
+ ObjCInterfaceDecl *Super = nullptr);
void CodeCompleteObjCForCollection(Scope *S,
DeclGroupPtrTy IterationVar);
void CodeCompleteObjCSelector(Scope *S,
@@ -7807,7 +8238,7 @@ public:
private:
void CheckArrayAccess(const Expr *BaseExpr, const Expr *IndexExpr,
- const ArraySubscriptExpr *ASE=0,
+ 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
@@ -7833,21 +8264,24 @@ private:
SourceLocation Loc);
void checkCall(NamedDecl *FDecl, ArrayRef<const Expr *> Args,
- unsigned NumProtoArgs, bool IsMemberFunction,
- SourceLocation Loc, SourceRange Range,
- VariadicCallType CallType);
-
+ unsigned NumParams, bool IsMemberFunction, SourceLocation Loc,
+ SourceRange Range, VariadicCallType CallType);
bool CheckObjCString(Expr *Arg);
ExprResult CheckBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall);
- bool CheckARMBuiltinExclusiveCall(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 CheckX86BuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall);
bool SemaBuiltinVAStart(CallExpr *TheCall);
+ bool SemaBuiltinVAStartARM(CallExpr *Call);
bool SemaBuiltinUnorderedCompare(CallExpr *TheCall);
bool SemaBuiltinFPClassification(CallExpr *TheCall, unsigned NumArgs);
@@ -7860,13 +8294,15 @@ public:
private:
bool SemaBuiltinPrefetch(CallExpr *TheCall);
- bool SemaBuiltinObjectSize(CallExpr *TheCall);
+ bool SemaBuiltinAssume(CallExpr *TheCall);
bool SemaBuiltinLongjmp(CallExpr *TheCall);
ExprResult SemaBuiltinAtomicOverloaded(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);
public:
enum FormatStringType {
@@ -7901,9 +8337,9 @@ private:
SourceLocation Loc, SourceRange range,
llvm::SmallBitVector &CheckedVarArgs);
- void CheckNonNullArguments(const NonNullAttr *NonNull,
- const Expr * const *ExprArgs,
- SourceLocation CallSiteLoc);
+ void CheckAbsoluteValueFunction(const CallExpr *Call,
+ const FunctionDecl *FDecl,
+ IdentifierInfo *FnInfo);
void CheckMemaccessArguments(const CallExpr *Call,
unsigned BId,
@@ -7915,8 +8351,12 @@ private:
void CheckStrncatArguments(const CallExpr *Call,
IdentifierInfo *FnName);
- void CheckReturnStackAddr(Expr *RetValExp, QualType lhsType,
- SourceLocation ReturnLoc);
+ 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 CheckForIntOverflow(Expr *E);
@@ -7930,6 +8370,10 @@ private:
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);
+
public:
/// \brief Register a magic integral constant to be used as a type tag.
void RegisterTypeTagForDatatype(const IdentifierInfo *ArgumentKind,
@@ -7958,7 +8402,7 @@ public:
private:
/// \brief A map from magic value to type information.
- OwningPtr<llvm::DenseMap<TypeTagMagicValue, TypeTagData> >
+ std::unique_ptr<llvm::DenseMap<TypeTagMagicValue, TypeTagData>>
TypeTagForDatatypeMagicValues;
/// \brief Peform checks on a call of a function with argument_with_type_tag
@@ -7991,6 +8435,10 @@ public:
/// template substitution or instantiation.
Scope *getCurScope() const { return CurScope; }
+ void incrementMSLocalManglingNumber() const {
+ return CurScope->incrementMSLocalManglingNumber();
+ }
+
IdentifierInfo *getSuperIdentifier() const;
IdentifierInfo *getFloat128Identifier() const;
@@ -8018,7 +8466,7 @@ class EnterExpressionEvaluationContext {
public:
EnterExpressionEvaluationContext(Sema &Actions,
Sema::ExpressionEvaluationContext NewContext,
- Decl *LambdaContextDecl = 0,
+ Decl *LambdaContextDecl = nullptr,
bool IsDecltype = false)
: Actions(Actions) {
Actions.PushExpressionEvaluationContext(NewContext, LambdaContextDecl,
diff --git a/include/clang/Sema/SemaInternal.h b/include/clang/Sema/SemaInternal.h
index 01d4cc9679ef..9199b0fba2a5 100644
--- a/include/clang/Sema/SemaInternal.h
+++ b/include/clang/Sema/SemaInternal.h
@@ -24,44 +24,68 @@ namespace clang {
inline PartialDiagnostic Sema::PDiag(unsigned DiagID) {
return PartialDiagnostic(DiagID, Context.getDiagAllocator());
}
-
-
-// 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 = 0;
- return !isa<ParmVarDecl>(Var) &&
- Var->isUsableInConstantExpressions(Context) &&
- Var->getAnyInitializer(DefVD) && DefVD->checkInitIsICE();
-}
-
-// 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);
+
+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();
+}
+
+// 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;
+}
+
}
#endif
diff --git a/include/clang/Sema/SemaLambda.h b/include/clang/Sema/SemaLambda.h
index cf9fff1f1a2a..f6367505f866 100644
--- a/include/clang/Sema/SemaLambda.h
+++ b/include/clang/Sema/SemaLambda.h
@@ -1,39 +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_LAMBDA_H
-#define LLVM_CLANG_SEMA_LAMBDA_H
-#include "clang/AST/ASTLambda.h"
-#include "clang/Sema/ScopeInfo.h"
-namespace clang {
-
-// Given a lambda's call operator and a variable (or null for 'this'),
-// compute the nearest enclosing lambda that is capture-ready (i.e
-// the enclosing context is not dependent, and all intervening lambdas can
-// either implicitly or explicitly capture Var)
-//
-// Return the CallOperator of the capturable lambda and set function scope
-// index to the correct index within the function scope stack to correspond
-// to the capturable lambda.
-// If VarDecl *VD is null, we check for 'this' capture.
-CXXMethodDecl*
-GetInnermostEnclosingCapturableLambda(
- ArrayRef<sema::FunctionScopeInfo*> FunctionScopes,
- unsigned &FunctionScopeIndex,
- DeclContext *const CurContext, VarDecl *VD, Sema &S);
-
-} // clang
-
-#endif // LLVM_CLANG_SEMA_LAMBDA_H
+//===--- 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_LAMBDA_H
+#define LLVM_CLANG_SEMA_LAMBDA_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 // LLVM_CLANG_SEMA_LAMBDA_H
diff --git a/include/clang/Sema/Template.h b/include/clang/Sema/Template.h
index 1af61d5abd61..c08a5df00b36 100644
--- a/include/clang/Sema/Template.h
+++ b/include/clang/Sema/Template.h
@@ -246,7 +246,7 @@ namespace clang {
LocalInstantiationScope(Sema &SemaRef, bool CombineWithOuterScope = false)
: SemaRef(SemaRef), Outer(SemaRef.CurrentInstantiationScope),
Exited(false), CombineWithOuterScope(CombineWithOuterScope),
- PartiallySubstitutedPack(0)
+ PartiallySubstitutedPack(nullptr)
{
SemaRef.CurrentInstantiationScope = this;
}
@@ -276,7 +276,7 @@ namespace clang {
LocalInstantiationScope *newScope =
new LocalInstantiationScope(SemaRef, CombineWithOuterScope);
- newScope->Outer = 0;
+ newScope->Outer = nullptr;
if (Outer)
newScope->Outer = Outer->cloneScopes(Outermost);
@@ -319,7 +319,7 @@ namespace clang {
/// \param D The declaration whose instantiation we are searching for.
///
/// \returns A pointer to the declaration or argument pack of declarations
- /// to which the declaration \c D is instantiataed, if found. Otherwise,
+ /// to which the declaration \c D is instantiated, if found. Otherwise,
/// returns NULL.
llvm::PointerUnion<Decl *, DeclArgumentPack *> *
findInstantiationOf(const Decl *D);
@@ -348,17 +348,17 @@ namespace clang {
/// interest.
void ResetPartiallySubstitutedPack() {
assert(PartiallySubstitutedPack && "No partially-substituted pack");
- PartiallySubstitutedPack = 0;
- ArgsInPartiallySubstitutedPack = 0;
+ 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 = 0,
- unsigned *NumExplicitArgs = 0) const;
+ NamedDecl *
+ getPartiallySubstitutedPack(const TemplateArgument **ExplicitArgs = nullptr,
+ unsigned *NumExplicitArgs = nullptr) const;
};
class TemplateDeclInstantiator
@@ -391,8 +391,8 @@ namespace clang {
const MultiLevelTemplateArgumentList &TemplateArgs)
: SemaRef(SemaRef),
SubstIndex(SemaRef, SemaRef.ArgumentPackSubstitutionIndex),
- Owner(Owner), TemplateArgs(TemplateArgs), LateAttrs(0), StartingScope(0)
- { }
+ Owner(Owner), TemplateArgs(TemplateArgs), LateAttrs(nullptr),
+ StartingScope(nullptr) {}
// Define all the decl visitors using DeclNodes.inc
#define DECL(DERIVED, BASE) \
@@ -436,8 +436,8 @@ namespace clang {
// Disable late instantiation of attributes.
void disableLateAttributeInstantiation() {
- LateAttrs = 0;
- StartingScope = 0;
+ LateAttrs = nullptr;
+ StartingScope = nullptr;
}
LocalInstantiationScope *getStartingScope() const { return StartingScope; }
@@ -493,7 +493,7 @@ namespace clang {
Decl *VisitVarTemplateSpecializationDecl(
VarTemplateDecl *VarTemplate, VarDecl *FromVar, void *InsertPos,
const TemplateArgumentListInfo &TemplateArgsInfo,
- llvm::ArrayRef<TemplateArgument> Converted);
+ ArrayRef<TemplateArgument> Converted);
Decl *InstantiateTypedefNameDecl(TypedefNameDecl *D, bool IsTypeAlias);
ClassTemplatePartialSpecializationDecl *
diff --git a/include/clang/Sema/TemplateDeduction.h b/include/clang/Sema/TemplateDeduction.h
index 1daa6891ed12..2c2c36d30be3 100644
--- a/include/clang/Sema/TemplateDeduction.h
+++ b/include/clang/Sema/TemplateDeduction.h
@@ -19,6 +19,7 @@
namespace clang {
+struct DeducedPack;
class TemplateArgumentList;
class Sema;
@@ -48,7 +49,8 @@ class TemplateDeductionInfo {
public:
TemplateDeductionInfo(SourceLocation Loc)
- : Deduced(0), Loc(Loc), HasSFINAEDiagnostic(false), Expression(0) { }
+ : Deduced(nullptr), Loc(Loc), HasSFINAEDiagnostic(false),
+ Expression(nullptr) {}
/// \brief Returns the location at which template argument is
/// occurring.
@@ -59,7 +61,7 @@ public:
/// \brief Take ownership of the deduced template argument list.
TemplateArgumentList *take() {
TemplateArgumentList *Result = Deduced;
- Deduced = 0;
+ Deduced = nullptr;
return Result;
}
@@ -161,6 +163,11 @@ public:
/// an overloaded function which could not be resolved to a specific
/// function.
Expr *Expression;
+
+ /// \brief Information on packs that we're currently expanding.
+ ///
+ /// FIXME: This should be kept internal to SemaTemplateDeduction.
+ SmallVector<DeducedPack *, 8> PendingDeducedPacks;
};
} // end namespace sema
diff --git a/include/clang/Sema/TypoCorrection.h b/include/clang/Sema/TypoCorrection.h
index f0b772649847..6cab59c93efc 100644
--- a/include/clang/Sema/TypoCorrection.h
+++ b/include/clang/Sema/TypoCorrection.h
@@ -39,7 +39,7 @@ public:
static const unsigned CallbackDistanceWeight = 150U;
TypoCorrection(const DeclarationName &Name, NamedDecl *NameDecl,
- NestedNameSpecifier *NNS = 0, unsigned CharDistance = 0,
+ NestedNameSpecifier *NNS = nullptr, unsigned CharDistance = 0,
unsigned QualifierDistance = 0)
: CorrectionName(Name), CorrectionNameSpec(NNS),
CharDistance(CharDistance), QualifierDistance(QualifierDistance),
@@ -49,7 +49,7 @@ public:
CorrectionDecls.push_back(NameDecl);
}
- TypoCorrection(NamedDecl *Name, NestedNameSpecifier *NNS = 0,
+ TypoCorrection(NamedDecl *Name, NestedNameSpecifier *NNS = nullptr,
unsigned CharDistance = 0)
: CorrectionName(Name->getDeclName()), CorrectionNameSpec(NNS),
CharDistance(CharDistance), QualifierDistance(0), CallbackDistance(0),
@@ -58,14 +58,14 @@ public:
CorrectionDecls.push_back(Name);
}
- TypoCorrection(DeclarationName Name, NestedNameSpecifier *NNS = 0,
+ 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(0), CharDistance(0), QualifierDistance(0),
+ : CorrectionNameSpec(nullptr), CharDistance(0), QualifierDistance(0),
CallbackDistance(0), ForceSpecifierReplacement(false),
RequiresImport(false) {}
@@ -81,7 +81,7 @@ public:
}
void setCorrectionSpecifier(NestedNameSpecifier* NNS) {
CorrectionNameSpec = NNS;
- ForceSpecifierReplacement = (NNS != 0);
+ ForceSpecifierReplacement = (NNS != nullptr);
}
void WillReplaceSpecifier(bool ForceReplacement) {
@@ -130,7 +130,7 @@ public:
/// \brief Gets the pointer to the declaration of the typo correction
NamedDecl *getCorrectionDecl() const {
- return hasCorrectionDecl() ? *(CorrectionDecls.begin()) : 0;
+ return hasCorrectionDecl() ? *(CorrectionDecls.begin()) : nullptr;
}
template <class DeclClass>
DeclClass *getCorrectionDeclAs() const {
@@ -172,7 +172,7 @@ public:
/// as the only element in the list to mark this TypoCorrection as a keyword.
void makeKeyword() {
CorrectionDecls.clear();
- CorrectionDecls.push_back(0);
+ CorrectionDecls.push_back(nullptr);
ForceSpecifierReplacement = true;
}
@@ -180,7 +180,7 @@ public:
// item in CorrectionDecls is NULL.
bool isKeyword() const {
return !CorrectionDecls.empty() &&
- CorrectionDecls.front() == 0;
+ CorrectionDecls.front() == nullptr;
}
// Check if this TypoCorrection is the given keyword.
@@ -250,8 +250,8 @@ public:
CorrectionCandidateCallback()
: WantTypeSpecifiers(true), WantExpressionKeywords(true),
WantCXXNamedCasts(true), WantRemainingKeywords(true),
- WantObjCSuper(false),
- IsObjCIvarLookup(false) {}
+ WantObjCSuper(false), IsObjCIvarLookup(false),
+ IsAddressOfOperand(false) {}
virtual ~CorrectionCandidateCallback() {}
@@ -287,6 +287,7 @@ public:
// Temporary hack for the one case where a CorrectTypoContext enum is used
// when looking up results.
bool IsObjCIvarLookup;
+ bool IsAddressOfOperand;
};
/// @brief Simple template class for restricting typo correction candidates
@@ -294,7 +295,7 @@ public:
template <class C>
class DeclFilterCCC : public CorrectionCandidateCallback {
public:
- virtual bool ValidateCandidate(const TypoCorrection &candidate) {
+ bool ValidateCandidate(const TypoCorrection &candidate) override {
return candidate.getCorrectionDeclAs<C>();
}
};
@@ -305,13 +306,16 @@ public:
class FunctionCallFilterCCC : public CorrectionCandidateCallback {
public:
FunctionCallFilterCCC(Sema &SemaRef, unsigned NumArgs,
- bool HasExplicitTemplateArgs);
+ bool HasExplicitTemplateArgs,
+ MemberExpr *ME = nullptr);
- virtual bool ValidateCandidate(const TypoCorrection &candidate);
+ bool ValidateCandidate(const TypoCorrection &candidate) override;
private:
unsigned NumArgs;
bool HasExplicitTemplateArgs;
+ DeclContext *CurContext;
+ MemberExpr *MemberFn;
};
// @brief Callback class that effectively disabled typo correction
@@ -324,7 +328,7 @@ public:
WantRemainingKeywords = false;
}
- virtual bool ValidateCandidate(const TypoCorrection &candidate) {
+ bool ValidateCandidate(const TypoCorrection &candidate) override {
return false;
}
};
diff --git a/include/clang/Sema/Weak.h b/include/clang/Sema/Weak.h
index 6d1b64bd3016..9c7212e0c8ee 100644
--- a/include/clang/Sema/Weak.h
+++ b/include/clang/Sema/Weak.h
@@ -28,7 +28,7 @@ class WeakInfo {
bool used; // identifier later declared?
public:
WeakInfo()
- : alias(0), loc(SourceLocation()), used(false) {}
+ : alias(nullptr), loc(SourceLocation()), used(false) {}
WeakInfo(IdentifierInfo *Alias, SourceLocation Loc)
: alias(Alias), loc(Loc), used(false) {}
inline IdentifierInfo * getAlias() const { return alias; }
diff --git a/include/clang/Serialization/ASTBitCodes.h b/include/clang/Serialization/ASTBitCodes.h
index 03d905054aea..7ae1977d3e71 100644
--- a/include/clang/Serialization/ASTBitCodes.h
+++ b/include/clang/Serialization/ASTBitCodes.h
@@ -213,9 +213,6 @@ namespace clang {
/// types and decls used within the AST file.
DECLTYPES_BLOCK_ID,
- /// \brief The block containing DECL_UPDATES records.
- DECL_UPDATES_BLOCK_ID,
-
/// \brief The block containing the detailed preprocessing record.
PREPROCESSOR_DETAIL_BLOCK_ID,
@@ -284,7 +281,14 @@ namespace clang {
HEADER_SEARCH_OPTIONS = 11,
/// \brief Record code for the preprocessor options table.
- PREPROCESSOR_OPTIONS = 12
+ PREPROCESSOR_OPTIONS = 12,
+
+ /// \brief Record code for the module name.
+ MODULE_NAME = 13,
+
+ /// \brief Record code for the module map file that was used to build this
+ /// AST file.
+ MODULE_MAP_FILE = 14
};
/// \brief Record types that occur within the input-files block
@@ -349,15 +353,15 @@ namespace clang {
/// IDs).
IDENTIFIER_TABLE = 5,
- /// \brief Record code for the array of external definitions.
+ /// \brief Record code for the array of eagerly deserialized decls.
///
- /// The AST file contains a list of all of the unnamed external
- /// definitions present within the parsed headers, stored as an
- /// array of declaration IDs. These external definitions will be
+ /// 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).
- EXTERNAL_DEFINITIONS = 6,
+ EAGERLY_DESERIALIZED_DECLS = 6,
/// \brief Record code for the set of non-builtin, special
/// types.
@@ -538,7 +542,10 @@ namespace clang {
UNDEFINED_BUT_USED = 49,
/// \brief Record code for late parsed template functions.
- LATE_PARSED_TEMPLATE = 50
+ LATE_PARSED_TEMPLATE = 50,
+
+ /// \brief Record code for \#pragma optimize options.
+ OPTIMIZE_PRAGMA_OPTIONS = 51
};
/// \brief Record types used within a source manager block.
@@ -841,7 +848,9 @@ namespace clang {
/// \brief An AtomicType record.
TYPE_ATOMIC = 40,
/// \brief A DecayedType record.
- TYPE_DECAYED = 41
+ TYPE_DECAYED = 41,
+ /// \brief An AdjustedType record.
+ TYPE_ADJUSTED = 42
};
/// \brief The type IDs for special types constructed by semantic
@@ -1300,13 +1309,11 @@ namespace clang {
EXPR_CXX_UNRESOLVED_MEMBER, // UnresolvedMemberExpr
EXPR_CXX_UNRESOLVED_LOOKUP, // UnresolvedLookupExpr
- EXPR_CXX_UNARY_TYPE_TRAIT, // UnaryTypeTraitExpr
EXPR_CXX_EXPRESSION_TRAIT, // ExpressionTraitExpr
EXPR_CXX_NOEXCEPT, // CXXNoexceptExpr
EXPR_OPAQUE_VALUE, // OpaqueValueExpr
EXPR_BINARY_CONDITIONAL_OPERATOR, // BinaryConditionalOperator
- EXPR_BINARY_TYPE_TRAIT, // BinaryTypeTraitExpr
EXPR_TYPE_TRAIT, // TypeTraitExpr
EXPR_ARRAY_TYPE_TRAIT, // ArrayTypeTraitIntExpr
@@ -1327,12 +1334,27 @@ namespace clang {
EXPR_CXX_PROPERTY_REF_EXPR, // MSPropertyRefExpr
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 drectives
STMT_OMP_PARALLEL_DIRECTIVE,
+ STMT_OMP_SIMD_DIRECTIVE,
+ STMT_OMP_FOR_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_SECTIONS_DIRECTIVE,
+ STMT_OMP_TASK_DIRECTIVE,
+ STMT_OMP_TASKYIELD_DIRECTIVE,
+ STMT_OMP_BARRIER_DIRECTIVE,
+ STMT_OMP_TASKWAIT_DIRECTIVE,
+ STMT_OMP_FLUSH_DIRECTIVE,
// ARC
EXPR_OBJC_BRIDGED_CAST, // ObjCBridgedCastExpr
diff --git a/include/clang/Serialization/ASTDeserializationListener.h b/include/clang/Serialization/ASTDeserializationListener.h
index 0218129fb625..180f554dafea 100644
--- a/include/clang/Serialization/ASTDeserializationListener.h
+++ b/include/clang/Serialization/ASTDeserializationListener.h
@@ -15,6 +15,7 @@
#ifndef LLVM_CLANG_FRONTEND_AST_DESERIALIZATION_LISTENER_H
#define LLVM_CLANG_FRONTEND_AST_DESERIALIZATION_LISTENER_H
+#include "clang/Basic/IdentifierTable.h"
#include "clang/Serialization/ASTBitCodes.h"
namespace clang {
@@ -27,10 +28,8 @@ class MacroInfo;
class Module;
class ASTDeserializationListener {
-protected:
- virtual ~ASTDeserializationListener();
-
public:
+ virtual ~ASTDeserializationListener();
/// \brief The ASTReader was initialized.
virtual void ReaderInitialized(ASTReader *Reader) { }
diff --git a/include/clang/Serialization/ASTReader.h b/include/clang/Serialization/ASTReader.h
index d3cca1a84948..3f44440d4b9a 100644
--- a/include/clang/Serialization/ASTReader.h
+++ b/include/clang/Serialization/ASTReader.h
@@ -34,21 +34,20 @@
#include "llvm/ADT/APFloat.h"
#include "llvm/ADT/APInt.h"
#include "llvm/ADT/APSInt.h"
-#include "llvm/ADT/DenseSet.h"
#include "llvm/ADT/MapVector.h"
-#include "llvm/ADT/OwningPtr.h"
#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/ADT/SmallSet.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringRef.h"
+#include "llvm/ADT/TinyPtrVector.h"
#include "llvm/Bitcode/BitstreamReader.h"
#include "llvm/Support/DataTypes.h"
#include <deque>
#include <map>
+#include <memory>
#include <string>
#include <utility>
#include <vector>
-#include <sys/stat.h>
namespace llvm {
class MemoryBuffer;
@@ -64,6 +63,7 @@ class ASTUnit; // FIXME: Layering violation and egregious hack.
class Attr;
class Decl;
class DeclContext;
+class DefMacroDirective;
class DiagnosticOptions;
class NestedNameSpecifier;
class CXXBaseSpecifier;
@@ -108,6 +108,9 @@ public:
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.
@@ -129,8 +132,9 @@ public:
///
/// \returns true to indicate the diagnostic options are invalid, or false
/// otherwise.
- virtual bool ReadDiagnosticOptions(const DiagnosticOptions &DiagOpts,
- bool Complain) {
+ virtual bool
+ ReadDiagnosticOptions(IntrusiveRefCntPtr<DiagnosticOptions> DiagOpts,
+ bool Complain) {
return false;
}
@@ -170,15 +174,60 @@ public:
virtual void ReadCounter(const serialization::ModuleFile &M,
unsigned Value) {}
+ /// This is called for each AST file loaded.
+ virtual void visitModuleFile(StringRef Filename) {}
+
/// \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 if \c needsInputFileVisitation returns true, this is called for each
- /// input file of the AST file.
+ /// \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) { return true;}
+ virtual bool visitInputFile(StringRef Filename, bool isSystem,
+ bool isOverridden) {
+ return true;
+ }
+};
+
+/// \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(ASTReaderListener *First, ASTReaderListener *Second)
+ : First(First), Second(Second) { }
+
+ bool ReadFullVersionInformation(StringRef FullVersion) override;
+ void ReadModuleName(StringRef ModuleName) override;
+ void ReadModuleMapFile(StringRef ModuleMapPath) override;
+ bool ReadLanguageOptions(const LangOptions &LangOpts, bool Complain) override;
+ bool ReadTargetOptions(const TargetOptions &TargetOpts,
+ bool Complain) override;
+ bool ReadDiagnosticOptions(IntrusiveRefCntPtr<DiagnosticOptions> DiagOpts,
+ bool Complain) override;
+ bool ReadFileSystemOptions(const FileSystemOptions &FSOpts,
+ bool Complain) override;
+
+ bool ReadHeaderSearchOptions(const HeaderSearchOptions &HSOpts,
+ 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) override;
+ bool visitInputFile(StringRef Filename, bool isSystem,
+ bool isOverridden) override;
};
/// \brief ASTReaderListener implementation to validate the information of
@@ -191,14 +240,15 @@ public:
PCHValidator(Preprocessor &PP, ASTReader &Reader)
: PP(PP), Reader(Reader) {}
- virtual bool ReadLanguageOptions(const LangOptions &LangOpts,
- bool Complain);
- virtual bool ReadTargetOptions(const TargetOptions &TargetOpts,
- bool Complain);
- virtual bool ReadPreprocessorOptions(const PreprocessorOptions &PPOpts,
- bool Complain,
- std::string &SuggestedPredefines);
- virtual void ReadCounter(const serialization::ModuleFile &M, unsigned Value);
+ bool ReadLanguageOptions(const LangOptions &LangOpts,
+ bool Complain) override;
+ bool ReadTargetOptions(const TargetOptions &TargetOpts,
+ bool Complain) override;
+ bool ReadDiagnosticOptions(IntrusiveRefCntPtr<DiagnosticOptions> DiagOpts,
+ bool Complain) override;
+ bool ReadPreprocessorOptions(const PreprocessorOptions &PPOpts, bool Complain,
+ std::string &SuggestedPredefines) override;
+ void ReadCounter(const serialization::ModuleFile &M, unsigned Value) override;
private:
void Error(const char *Msg);
@@ -211,7 +261,7 @@ class ReadMethodPoolVisitor;
namespace reader {
class ASTIdentifierLookupTrait;
/// \brief The on-disk hash table used for the DeclContext's Name lookup table.
- typedef OnDiskChainedHashTable<ASTDeclContextNameLookupTrait>
+ typedef llvm::OnDiskIterableChainedHashTable<ASTDeclContextNameLookupTrait>
ASTDeclContextNameLookupTable;
}
@@ -285,10 +335,11 @@ public:
private:
/// \brief The receiver of some callbacks invoked by ASTReader.
- OwningPtr<ASTReaderListener> Listener;
+ std::unique_ptr<ASTReaderListener> Listener;
/// \brief The receiver of deserialization events.
ASTDeserializationListener *DeserializationListener;
+ bool OwnsDeserializationListener;
SourceManager &SourceMgr;
FileManager &FileMgr;
@@ -315,7 +366,7 @@ private:
SourceLocation CurrentImportLoc;
/// \brief The global module index, if loaded.
- llvm::OwningPtr<GlobalModuleIndex> GlobalIndex;
+ std::unique_ptr<GlobalModuleIndex> GlobalIndex;
/// \brief A map of global bit offsets to the module that stores entities
/// at those bit offsets.
@@ -366,12 +417,17 @@ private:
/// 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;
+
struct ReplacedDeclInfo {
ModuleFile *Mod;
uint64_t Offset;
unsigned RawLoc;
- ReplacedDeclInfo() : Mod(0), Offset(0), RawLoc(0) {}
+ ReplacedDeclInfo() : Mod(nullptr), Offset(0), RawLoc(0) {}
ReplacedDeclInfo(ModuleFile *Mod, uint64_t Offset, unsigned RawLoc)
: Mod(Mod), Offset(Offset), RawLoc(RawLoc) {}
};
@@ -385,7 +441,7 @@ private:
ModuleFile *Mod;
ArrayRef<serialization::LocalDeclID> Decls;
- FileDeclsInfo() : Mod(0) {}
+ FileDeclsInfo() : Mod(nullptr) {}
FileDeclsInfo(ModuleFile *Mod, ArrayRef<serialization::LocalDeclID> Decls)
: Mod(Mod), Decls(Decls) {}
};
@@ -471,18 +527,22 @@ private:
/// global submodule ID to produce a local ID.
GlobalSubmoduleMapType GlobalSubmoduleMap;
+ /// \brief Information on a macro definition or undefinition that is visible
+ /// at the end of a submodule.
+ struct ModuleMacroInfo;
+
/// \brief An entity that has been hidden.
class HiddenName {
public:
enum NameKind {
Declaration,
- MacroVisibility
+ Macro
} Kind;
private:
union {
Decl *D;
- MacroDirective *MD;
+ ModuleMacroInfo *MMI;
};
IdentifierInfo *Id;
@@ -490,8 +550,8 @@ private:
public:
HiddenName(Decl *D) : Kind(Declaration), D(D), Id() { }
- HiddenName(IdentifierInfo *II, MacroDirective *MD)
- : Kind(MacroVisibility), MD(MD), Id(II) { }
+ HiddenName(IdentifierInfo *II, ModuleMacroInfo *MMI)
+ : Kind(Macro), MMI(MMI), Id(II) { }
NameKind getKind() const { return Kind; }
@@ -500,15 +560,21 @@ private:
return D;
}
- std::pair<IdentifierInfo *, MacroDirective *> getMacro() const {
- assert(getKind() == MacroVisibility && "Hidden name is not a macro!");
- return std::make_pair(Id, MD);
+ std::pair<IdentifierInfo *, ModuleMacroInfo *> getMacro() const {
+ assert(getKind() == Macro && "Hidden name is not a macro!");
+ return std::make_pair(Id, MMI);
}
-};
+ };
+
+ typedef llvm::SmallDenseMap<IdentifierInfo*,
+ ModuleMacroInfo*> HiddenMacrosMap;
/// \brief A set of hidden declarations.
- typedef SmallVector<HiddenName, 2> HiddenNames;
-
+ struct HiddenNames {
+ SmallVector<Decl*, 2> HiddenDecls;
+ HiddenMacrosMap HiddenMacros;
+ };
+
typedef llvm::DenseMap<Module *, HiddenNames> HiddenNamesMapType;
/// \brief A mapping from each of the hidden submodules to the deserialized
@@ -564,8 +630,8 @@ private:
ModuleFile *M;
struct ModuleMacroDataTy {
- serialization::GlobalMacroID GMacID;
- unsigned ImportLoc;
+ uint32_t MacID;
+ serialization::SubmoduleID *Overrides;
};
struct PCHMacroDataTy {
uint64_t MacroDirectivesOffset;
@@ -577,10 +643,10 @@ private:
};
PendingMacroInfo(ModuleFile *M,
- serialization::GlobalMacroID GMacID,
- SourceLocation ImportLoc) : M(M) {
- ModuleMacroData.GMacID = GMacID;
- ModuleMacroData.ImportLoc = ImportLoc.getRawEncoding();
+ uint32_t MacID,
+ serialization::SubmoduleID *Overrides) : M(M) {
+ ModuleMacroData.MacID = MacID;
+ ModuleMacroData.Overrides = Overrides;
}
PendingMacroInfo(ModuleFile *M, uint64_t MacroDirectivesOffset) : M(M) {
@@ -610,10 +676,10 @@ private:
/// \brief The IDs of all declarations that fulfill the criteria of
/// "interesting" decls.
///
- /// This contains the data loaded from all EXTERNAL_DEFINITIONS blocks in the
- /// chain. The referenced declarations are deserialized and passed to the
- /// consumer eagerly.
- SmallVector<uint64_t, 16> ExternalDefinitions;
+ /// 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.
///
@@ -701,6 +767,9 @@ private:
/// \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;
@@ -714,9 +783,17 @@ private:
// \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<serialization::SubmoduleID, 2> ImportedModules;
+ SmallVector<ImportedSubmodule, 2> ImportedModules;
//@}
/// \brief The directory that the PCH we are reading is stored in.
@@ -733,16 +810,19 @@ private:
/// \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;
- /// \brief The current "generation" of the module file import stack, which
- /// indicates how many separate module file load operations have occurred.
- unsigned CurrentGeneration;
-
typedef llvm::DenseMap<unsigned, SwitchCase *> SwitchCaseMapTy;
/// \brief Mapping from switch-case IDs in the chain to switch-case statements
///
@@ -860,6 +940,10 @@ private:
/// \brief Keeps track of the elements added to PendingDeclChains.
llvm::SmallSet<serialization::DeclID, 16> PendingDeclChainsKnown;
+ /// \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 {
@@ -883,6 +967,13 @@ private:
/// 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;
@@ -891,7 +982,14 @@ private:
/// loaded, for which we will need to check for categories whenever a new
/// module is loaded.
SmallVector<ObjCInterfaceDecl *, 16> ObjCClassesLoaded;
-
+
+ /// \brief A mapping from a primary context for a declaration chain to the
+ /// other declarations of that entity that also have name lookup tables.
+ /// Used when we merge together two class definitions that have different
+ /// sets of declared special member functions.
+ llvm::DenseMap<const DeclContext*, SmallVector<const DeclContext*, 2>>
+ MergedLookups;
+
typedef llvm::DenseMap<Decl *, SmallVector<serialization::DeclID, 2> >
MergedDeclsMap;
@@ -970,6 +1068,18 @@ private:
/// \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;
+ };
+
+ /// \brief Reads the stored information about an input file.
+ InputFileInfo readInputFileInfo(ModuleFile &F, unsigned ID);
+ /// \brief A convenience method to read the filename from an input file.
+ std::string getInputFileName(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,
@@ -999,13 +1109,15 @@ private:
unsigned ClientLoadCapabilities);
ASTReadResult ReadControlBlock(ModuleFile &F,
SmallVectorImpl<ImportedModule> &Loaded,
+ const ModuleFile *ImportedBy,
unsigned ClientLoadCapabilities);
- bool ReadASTBlock(ModuleFile &F);
+ ASTReadResult ReadASTBlock(ModuleFile &F, unsigned ClientLoadCapabilities);
bool ParseLineTable(ModuleFile &F, SmallVectorImpl<uint64_t> &Record);
bool ReadSourceManagerBlock(ModuleFile &F);
llvm::BitstreamCursor &SLocCursorForID(int ID);
SourceLocation getImportLocation(ModuleFile *F);
- bool ReadSubmoduleBlock(ModuleFile &F);
+ ASTReadResult ReadSubmoduleBlock(ModuleFile &F,
+ unsigned ClientLoadCapabilities);
static bool ParseLanguageOptions(const RecordData &Record, bool Complain,
ASTReaderListener &Listener);
static bool ParseTargetOptions(const RecordData &Record, bool Complain,
@@ -1028,9 +1140,14 @@ private:
};
QualType readTypeRecord(unsigned Index);
+ void readExceptionSpec(ModuleFile &ModuleFile,
+ SmallVectorImpl<QualType> &ExceptionStorage,
+ FunctionProtoType::ExtProtoInfo &EPI,
+ const RecordData &Record, unsigned &Index);
RecordLocation TypeCursorForIndex(unsigned Index);
void LoadedDecl(unsigned Index, Decl *D);
Decl *ReadDeclRecord(serialization::DeclID ID);
+ void markIncompleteDeclChain(Decl *Canon);
RecordLocation DeclCursorForID(serialization::DeclID ID,
unsigned &RawLocation);
void loadDeclUpdateRecords(serialization::DeclID ID, Decl *D);
@@ -1041,13 +1158,10 @@ private:
RecordLocation getLocalBitOffset(uint64_t GlobalOffset);
uint64_t getGlobalBitOffset(ModuleFile &M, uint32_t LocalOffset);
- /// \brief Returns the first preprocessed entity ID that ends after BLoc.
+ /// \brief Returns the first preprocessed entity ID that begins or ends after
+ /// \arg Loc.
serialization::PreprocessedEntityID
- findBeginPreprocessedEntity(SourceLocation BLoc) const;
-
- /// \brief Returns the first preprocessed entity ID that begins after ELoc.
- serialization::PreprocessedEntityID
- findEndPreprocessedEntity(SourceLocation ELoc) const;
+ findPreprocessedEntity(SourceLocation Loc, bool EndsAfter) const;
/// \brief Find the next module that contains entities and return the ID
/// of the first entry.
@@ -1079,7 +1193,7 @@ private:
typedef value_type& reference;
typedef value_type* pointer;
- ModuleDeclIterator() : Reader(0), Mod(0), Pos(0) { }
+ ModuleDeclIterator() : Reader(nullptr), Mod(nullptr), Pos(nullptr) { }
ModuleDeclIterator(ASTReader *Reader, ModuleFile *Mod,
const serialization::LocalDeclID *Pos)
@@ -1174,11 +1288,20 @@ public:
/// 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.
ASTReader(Preprocessor &PP, ASTContext &Context, StringRef isysroot = "",
bool DisableValidation = false,
bool AllowASTWithCompilerErrors = false,
+ bool AllowConfigurationMismatch = false,
+ bool ValidateSystemInputs = false,
bool UseGlobalIndex = true);
~ASTReader();
@@ -1237,24 +1360,41 @@ public:
/// \param ImportLoc The location at which the import occurs.
///
/// \param Complain Whether to complain about conflicting module imports.
- void makeModuleVisible(Module *Mod,
+ void makeModuleVisible(Module *Mod,
Module::NameVisibilityKind NameVisibility,
SourceLocation ImportLoc,
bool Complain);
-
+
/// \brief Make the names within this set of hidden names visible.
- void makeNamesVisible(const HiddenNames &Names, Module *Owner);
-
+ void makeNamesVisible(const HiddenNames &Names, Module *Owner,
+ bool FromFinalization);
+
/// \brief Set the AST callbacks listener.
void setListener(ASTReaderListener *listener) {
Listener.reset(listener);
}
+ /// \brief Add an AST callbak listener.
+ ///
+ /// Takes ownership of \p L.
+ void addListener(ASTReaderListener *L) {
+ if (Listener)
+ L = new ChainedASTReaderListener(L, Listener.release());
+ Listener.reset(L);
+ }
+
/// \brief Set the AST deserialization listener.
- void setDeserializationListener(ASTDeserializationListener *Listener);
+ void setDeserializationListener(ASTDeserializationListener *Listener,
+ bool TakeOwnership = false);
/// \brief Determine whether this AST reader has a global index.
- bool hasGlobalIndex() const { return GlobalIndex.isValid(); }
+ 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.
///
@@ -1325,20 +1465,20 @@ public:
///
/// \returns null if an error occurred that prevented the preprocessed
/// entity from being loaded.
- virtual PreprocessedEntity *ReadPreprocessedEntity(unsigned Index);
+ PreprocessedEntity *ReadPreprocessedEntity(unsigned Index) override;
/// \brief Returns a pair of [Begin, End) indices of preallocated
/// preprocessed entities that \p Range encompasses.
- virtual std::pair<unsigned, unsigned>
- findPreprocessedEntitiesInRange(SourceRange Range);
+ 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.
- virtual Optional<bool> isPreprocessedEntityInFileID(unsigned Index,
- FileID FID);
+ Optional<bool> isPreprocessedEntityInFileID(unsigned Index,
+ FileID FID) override;
/// \brief Read the header file information for the given file entry.
- virtual HeaderFileInfo GetHeaderFileInfo(const FileEntry *FE);
+ HeaderFileInfo GetHeaderFileInfo(const FileEntry *FE) override;
void ReadPragmaDiagnosticMappings(DiagnosticsEngine &Diag);
@@ -1443,14 +1583,22 @@ public:
/// \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);
- virtual Decl *GetExternalDecl(uint32_t 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) {
@@ -1497,19 +1645,24 @@ public:
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);
- virtual CXXBaseSpecifier *GetExternalCXXBaseSpecifiers(uint64_t Offset);
+ 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).
- virtual Stmt *GetExternalDeclStmt(uint64_t Offset);
+ 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
@@ -1519,9 +1672,8 @@ public:
/// \brief Finds all the visible declarations with a given name.
/// The current implementation of this method just loads the entire
/// lookup table as unmaterialized references.
- virtual bool
- FindExternalVisibleDeclsByName(const DeclContext *DC,
- DeclarationName Name);
+ bool FindExternalVisibleDeclsByName(const DeclContext *DC,
+ DeclarationName Name) override;
/// \brief Read all of the declarations lexically stored in a
/// declaration context.
@@ -1536,49 +1688,49 @@ public:
///
/// \returns true if there was an error while reading the
/// declarations for this declaration context.
- virtual ExternalLoadResult FindExternalLexicalDecls(const DeclContext *DC,
- bool (*isKindWeWant)(Decl::Kind),
- SmallVectorImpl<Decl*> &Decls);
+ ExternalLoadResult FindExternalLexicalDecls(const DeclContext *DC,
+ bool (*isKindWeWant)(Decl::Kind),
+ 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.
- virtual void FindFileRegionDecls(FileID File, unsigned Offset,unsigned Length,
- SmallVectorImpl<Decl *> &Decls);
+ 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.
- virtual void StartedDeserializing() { ++NumCurrentElementsDeserializing; }
+ void StartedDeserializing() override { ++NumCurrentElementsDeserializing; }
/// \brief Notify ASTReader that we finished the deserialization of
/// a decl or type. Must be paired with StartedDeserializing.
- virtual void FinishedDeserializing();
+ 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.
- virtual void StartTranslationUnit(ASTConsumer *Consumer);
+ void StartTranslationUnit(ASTConsumer *Consumer) override;
/// \brief Print some statistics about AST usage.
- virtual void PrintStats();
+ 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.
- virtual void getMemoryBufferSizes(MemoryBufferSizes &sizes) const;
+ 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.
- virtual void InitializeSema(Sema &S);
+ void InitializeSema(Sema &S) override;
/// \brief Inform the semantic consumer that Sema is no longer available.
- virtual void ForgetSema() { SemaObj = 0; }
+ void ForgetSema() override { SemaObj = nullptr; }
/// \brief Retrieve the IdentifierInfo for the named identifier.
///
@@ -1587,56 +1739,57 @@ public:
/// declarations will be deserialized and introduced into the declaration
/// chain of the identifier.
virtual IdentifierInfo *get(const char *NameStart, const char *NameEnd);
- IdentifierInfo *get(StringRef Name) {
+ IdentifierInfo *get(StringRef Name) override {
return get(Name.begin(), Name.end());
}
/// \brief Retrieve an iterator into the set of all identifiers
/// in all loaded AST files.
- virtual IdentifierIterator *getIdentifiers();
+ IdentifierIterator *getIdentifiers() override;
/// \brief Load the contents of the global method pool for a given
/// selector.
- virtual void ReadMethodPool(Selector Sel);
+ 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.
- virtual void ReadKnownNamespaces(
- SmallVectorImpl<NamespaceDecl *> &Namespaces);
+ void ReadKnownNamespaces(
+ SmallVectorImpl<NamespaceDecl *> &Namespaces) override;
- virtual void ReadUndefinedButUsed(
- llvm::DenseMap<NamedDecl *, SourceLocation> &Undefined);
+ void ReadUndefinedButUsed(
+ llvm::DenseMap<NamedDecl *, SourceLocation> &Undefined) override;
- virtual void ReadTentativeDefinitions(
- SmallVectorImpl<VarDecl *> &TentativeDefs);
+ void ReadTentativeDefinitions(
+ SmallVectorImpl<VarDecl *> &TentativeDefs) override;
- virtual void ReadUnusedFileScopedDecls(
- SmallVectorImpl<const DeclaratorDecl *> &Decls);
+ void ReadUnusedFileScopedDecls(
+ SmallVectorImpl<const DeclaratorDecl *> &Decls) override;
- virtual void ReadDelegatingConstructors(
- SmallVectorImpl<CXXConstructorDecl *> &Decls);
+ void ReadDelegatingConstructors(
+ SmallVectorImpl<CXXConstructorDecl *> &Decls) override;
- virtual void ReadExtVectorDecls(SmallVectorImpl<TypedefNameDecl *> &Decls);
+ void ReadExtVectorDecls(SmallVectorImpl<TypedefNameDecl *> &Decls) override;
- virtual void ReadDynamicClasses(SmallVectorImpl<CXXRecordDecl *> &Decls);
+ void ReadDynamicClasses(SmallVectorImpl<CXXRecordDecl *> &Decls) override;
- virtual void ReadLocallyScopedExternCDecls(
- SmallVectorImpl<NamedDecl *> &Decls);
+ void ReadLocallyScopedExternCDecls(
+ SmallVectorImpl<NamedDecl *> &Decls) override;
- virtual void ReadReferencedSelectors(
- SmallVectorImpl<std::pair<Selector, SourceLocation> > &Sels);
+ void ReadReferencedSelectors(
+ SmallVectorImpl<std::pair<Selector, SourceLocation> > &Sels) override;
- virtual void ReadWeakUndeclaredIdentifiers(
- SmallVectorImpl<std::pair<IdentifierInfo *, WeakInfo> > &WI);
+ void ReadWeakUndeclaredIdentifiers(
+ SmallVectorImpl<std::pair<IdentifierInfo *, WeakInfo> > &WI) override;
- virtual void ReadUsedVTables(SmallVectorImpl<ExternalVTableUse> &VTables);
+ void ReadUsedVTables(SmallVectorImpl<ExternalVTableUse> &VTables) override;
- virtual void ReadPendingInstantiations(
+ void ReadPendingInstantiations(
SmallVectorImpl<std::pair<ValueDecl *,
- SourceLocation> > &Pending);
+ SourceLocation> > &Pending) override;
- virtual void ReadLateParsedTemplates(
- llvm::DenseMap<const FunctionDecl *, LateParsedTemplate *> &LPTMap);
+ void ReadLateParsedTemplates(
+ llvm::DenseMap<const FunctionDecl *,
+ LateParsedTemplate *> &LPTMap) override;
/// \brief Load a selector from disk, registering its ID if it exists.
void LoadSelector(Selector Sel);
@@ -1644,7 +1797,7 @@ public:
void SetIdentifierInfo(unsigned ID, IdentifierInfo *II);
void SetGloballyVisibleDecls(IdentifierInfo *II,
const SmallVectorImpl<uint32_t> &DeclIDs,
- SmallVectorImpl<Decl *> *Decls = 0);
+ SmallVectorImpl<Decl *> *Decls = nullptr);
/// \brief Report a diagnostic.
DiagnosticBuilder Diag(unsigned DiagID);
@@ -1659,7 +1812,7 @@ public:
return DecodeIdentifierInfo(getGlobalIdentifierID(M, Record[Idx++]));
}
- virtual IdentifierInfo *GetIdentifier(serialization::IdentifierID ID) {
+ IdentifierInfo *GetIdentifier(serialization::IdentifierID ID) override {
// Note that we are loading an identifier.
Deserializing AnIdentifier(this);
@@ -1671,13 +1824,26 @@ public:
serialization::IdentifierID getGlobalIdentifierID(ModuleFile &M,
unsigned LocalID);
+ ModuleMacroInfo *getModuleMacro(const PendingMacroInfo &PMInfo);
+
void resolvePendingMacro(IdentifierInfo *II, const PendingMacroInfo &PMInfo);
void installPCHMacroDirectives(IdentifierInfo *II,
ModuleFile &M, uint64_t Offset);
- void installImportedMacro(IdentifierInfo *II, MacroDirective *MD,
- Module *Owner);
+ void installImportedMacro(IdentifierInfo *II, ModuleMacroInfo *MMI,
+ Module *Owner, bool FromFinalization);
+
+ typedef llvm::TinyPtrVector<DefMacroDirective *> AmbiguousMacros;
+ llvm::DenseMap<IdentifierInfo*, AmbiguousMacros> AmbiguousMacroDefs;
+
+ void
+ removeOverriddenMacros(IdentifierInfo *II, AmbiguousMacros &Ambig,
+ ArrayRef<serialization::SubmoduleID> Overrides);
+
+ AmbiguousMacros *
+ removeOverriddenMacros(IdentifierInfo *II,
+ ArrayRef<serialization::SubmoduleID> Overrides);
/// \brief Retrieve the macro with the given ID.
MacroInfo *getMacro(serialization::MacroID ID);
@@ -1687,11 +1853,11 @@ public:
serialization::MacroID getGlobalMacroID(ModuleFile &M, unsigned LocalID);
/// \brief Read the source location entry with index ID.
- virtual bool ReadSLocEntry(int ID);
+ bool ReadSLocEntry(int ID) override;
/// \brief Retrieve the module import location and module name for the
/// given source manager entry ID.
- virtual std::pair<SourceLocation, StringRef> getModuleImportLoc(int ID);
+ std::pair<SourceLocation, StringRef> getModuleImportLoc(int ID) override;
/// \brief Retrieve the global submodule ID given a module and its local ID
/// number.
@@ -1705,7 +1871,7 @@ public:
/// \brief Retrieve the module that corresponds to the given module ID.
///
/// Note: overrides method in ExternalASTSource
- virtual Module *getModule(unsigned ID);
+ Module *getModule(unsigned ID) override;
/// \brief Retrieve a selector from the given module with its local ID
/// number.
@@ -1713,8 +1879,8 @@ public:
Selector DecodeSelector(serialization::SelectorID Idx);
- virtual Selector GetExternalSelector(serialization::SelectorID ID);
- uint32_t GetNumExternalSelectors();
+ Selector GetExternalSelector(serialization::SelectorID ID) override;
+ uint32_t GetNumExternalSelectors() override;
Selector ReadSelector(ModuleFile &M, const RecordData &Record, unsigned &Idx) {
return getLocalSelector(M, Record[Idx++]);
@@ -1832,7 +1998,7 @@ public:
"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!");
+ assert(!StmtStack.empty() && "Read too many sub-statements!");
return StmtStack.pop_back_val();
}
@@ -1855,11 +2021,10 @@ public:
/// \param II The name of the macro.
/// \param M The module file.
/// \param GMacID The global macro ID that is associated with this identifier.
- /// \param ImportLoc The location where the module is imported.
void addPendingMacroFromModule(IdentifierInfo *II,
ModuleFile *M,
serialization::GlobalMacroID GMacID,
- SourceLocation ImportLoc);
+ ArrayRef<serialization::SubmoduleID>);
/// \brief Add a macro to deserialize its macro directive history from a PCH.
///
@@ -1871,16 +2036,16 @@ public:
ModuleFile *M, uint64_t MacroDirectivesOffset);
/// \brief Read the set of macros defined by this external macro source.
- virtual void ReadDefinedMacros();
+ void ReadDefinedMacros() override;
/// \brief Update an out-of-date identifier.
- virtual void updateOutOfDateIdentifier(IdentifierInfo &II);
+ 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);
+ void completeVisibleDeclsMap(const DeclContext *DC) override;
/// \brief Retrieve the AST context that this AST reader supplements.
ASTContext &getContext() { return Context; }
@@ -1911,8 +2076,8 @@ public:
SmallVector<std::pair<llvm::BitstreamCursor,
serialization::ModuleFile *>, 8> CommentsCursors;
- /// \brief Loads comments ranges.
- void ReadComments();
+ //RIDErief Loads comments ranges.
+ void ReadComments() override;
};
/// \brief Helper class that saves the current stream position and
diff --git a/include/clang/Serialization/ASTWriter.h b/include/clang/Serialization/ASTWriter.h
index 07fdd062ace7..ad6ecdd3519b 100644
--- a/include/clang/Serialization/ASTWriter.h
+++ b/include/clang/Serialization/ASTWriter.h
@@ -246,10 +246,10 @@ private:
/// @name FlushStmt Caches
/// @{
- /// \brief Set of parent Stmts for the currently serializing sub stmt.
+ /// \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
+ /// \brief Offsets of sub-stmts already serialized. The offset points
/// just after the stmt record.
llvm::DenseMap<Stmt *, uint64_t> SubStmtEntries;
@@ -283,7 +283,37 @@ private:
llvm::DenseMap<const MacroDefinition *, serialization::PreprocessedEntityID>
MacroDefinitions;
- typedef SmallVector<uint64_t, 2> UpdateRecord;
+ /// An update to a Decl.
+ class DeclUpdate {
+ /// A DeclUpdateKind.
+ unsigned Kind;
+ union {
+ const Decl *Dcl;
+ void *Type;
+ unsigned Loc;
+ unsigned Val;
+ };
+
+ 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) {}
+
+ 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; }
+ };
+
+ typedef SmallVector<DeclUpdate, 1> UpdateRecord;
typedef llvm::DenseMap<const Decl *, UpdateRecord> DeclUpdateMap;
/// \brief Mapping from declarations that came from a chained PCH to the
/// record containing modifications to them.
@@ -297,16 +327,15 @@ private:
/// \brief Declarations encountered that might be external
/// definitions.
///
- /// We keep track of external definitions (as well as tentative
- /// definitions) as we are emitting declarations to the AST
- /// file. The AST file contains a separate record for these external
- /// definitions, which are provided to the AST consumer by the AST
- /// reader. This is behavior is required to properly cope with,
+ /// 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 EXTERNAL_DEFINITIONS
+ /// IDs, since they will be written out to an EAGERLY_DESERIALIZED_DECLS
/// record.
- SmallVector<uint64_t, 16> ExternalDefinitions;
+ SmallVector<uint64_t, 16> EagerlyDeserializedDecls;
/// \brief DeclContexts that have received extensions since their serialized
/// form.
@@ -438,6 +467,8 @@ private:
bool isModule);
void WriteCXXBaseSpecifiersOffsets();
void WriteType(QualType T);
+ uint32_t GenerateNameLookupTable(const DeclContext *DC,
+ llvm::SmallVectorImpl<char> &LookupTable);
uint64_t WriteDeclContextLexicalBlock(ASTContext &Context, DeclContext *DC);
uint64_t WriteDeclContextVisibleBlock(ASTContext &Context, DeclContext *DC);
void WriteTypeDeclOffsets();
@@ -448,8 +479,7 @@ private:
void WriteIdentifierTable(Preprocessor &PP, IdentifierResolver &IdResolver,
bool IsModule);
void WriteAttributes(ArrayRef<const Attr*> Attrs, RecordDataImpl &Record);
- void ResolveDeclUpdatesBlocks();
- void WriteDeclUpdatesBlocks();
+ void WriteDeclUpdatesBlocks(RecordDataImpl &OffsetsRecord);
void WriteDeclReplacementsBlock();
void WriteDeclContextVisibleUpdate(const DeclContext *DC);
void WriteFPPragmaOptions(const FPOptions &Opts);
@@ -458,6 +488,7 @@ private:
void WriteRedeclarations();
void WriteMergedDecls();
void WriteLateParsedTemplates(Sema &SemaRef);
+ void WriteOptimizePragmaOptions(Sema &SemaRef);
unsigned DeclParmVarAbbrev;
unsigned DeclContextLexicalAbbrev;
@@ -475,6 +506,7 @@ private:
void WriteDeclsBlockAbbrevs();
void WriteDecl(ASTContext &Context, Decl *D);
+ void AddFunctionDefinition(const FunctionDecl *FD, RecordData &Record);
void WriteASTCore(Sema &SemaRef,
StringRef isysroot, const std::string &OutputFile,
@@ -645,9 +677,7 @@ public:
void AddVersionTuple(const VersionTuple &Version, RecordDataImpl &Record);
/// \brief Mark a declaration context as needing an update.
- void AddUpdatedDeclContext(const DeclContext *DC) {
- UpdatedDeclContexts.insert(DC);
- }
+ void AddUpdatedDeclContext(const DeclContext *DC);
void RewriteDecl(const Decl *D) {
DeclsToRewrite.insert(D);
@@ -715,35 +745,36 @@ public:
bool hasChain() const { return Chain; }
// ASTDeserializationListener implementation
- void ReaderInitialized(ASTReader *Reader);
- void IdentifierRead(serialization::IdentID ID, IdentifierInfo *II);
- void MacroRead(serialization::MacroID ID, MacroInfo *MI);
- void TypeRead(serialization::TypeIdx Idx, QualType T);
- void SelectorRead(serialization::SelectorID ID, Selector Sel);
+ 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,
- MacroDefinition *MD);
- void ModuleRead(serialization::SubmoduleID ID, Module *Mod);
+ MacroDefinition *MD) override;
+ void ModuleRead(serialization::SubmoduleID ID, Module *Mod) override;
// ASTMutationListener implementation.
- virtual void CompletedTagDefinition(const TagDecl *D);
- virtual void AddedVisibleDecl(const DeclContext *DC, const Decl *D);
- virtual void AddedCXXImplicitMember(const CXXRecordDecl *RD, const Decl *D);
- virtual void AddedCXXTemplateSpecialization(const ClassTemplateDecl *TD,
- const ClassTemplateSpecializationDecl *D);
- virtual void
- AddedCXXTemplateSpecialization(const VarTemplateDecl *TD,
- const VarTemplateSpecializationDecl *D);
- virtual void AddedCXXTemplateSpecialization(const FunctionTemplateDecl *TD,
- const FunctionDecl *D);
- virtual void DeducedReturnType(const FunctionDecl *FD, QualType ReturnType);
- virtual void CompletedImplicitDefinition(const FunctionDecl *D);
- virtual void StaticDataMemberInstantiated(const VarDecl *D);
- virtual void AddedObjCCategoryToInterface(const ObjCCategoryDecl *CatD,
- const ObjCInterfaceDecl *IFD);
- virtual void AddedObjCPropertyInClassExtension(const ObjCPropertyDecl *Prop,
- const ObjCPropertyDecl *OrigProp,
- const ObjCCategoryDecl *ClassExt);
- void DeclarationMarkedUsed(const Decl *D) LLVM_OVERRIDE;
+ 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 AddedCXXTemplateSpecialization(const ClassTemplateDecl *TD,
+ const ClassTemplateSpecializationDecl *D) override;
+ void AddedCXXTemplateSpecialization(const VarTemplateDecl *TD,
+ const VarTemplateSpecializationDecl *D) override;
+ void AddedCXXTemplateSpecialization(const FunctionTemplateDecl *TD,
+ const FunctionDecl *D) override;
+ void ResolvedExceptionSpec(const FunctionDecl *FD) override;
+ void DeducedReturnType(const FunctionDecl *FD, QualType ReturnType) 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 AddedObjCPropertyInClassExtension(const ObjCPropertyDecl *Prop,
+ const ObjCPropertyDecl *OrigProp,
+ const ObjCCategoryDecl *ClassExt) override;
+ void DeclarationMarkedUsed(const Decl *D) override;
};
/// \brief AST and semantic-analysis consumer that generates a
@@ -771,10 +802,10 @@ public:
StringRef isysroot, raw_ostream *Out,
bool AllowASTWithErrors = false);
~PCHGenerator();
- virtual void InitializeSema(Sema &S) { SemaPtr = &S; }
- virtual void HandleTranslationUnit(ASTContext &Ctx);
- virtual ASTMutationListener *GetASTMutationListener();
- virtual ASTDeserializationListener *GetASTDeserializationListener();
+ void InitializeSema(Sema &S) override { SemaPtr = &S; }
+ void HandleTranslationUnit(ASTContext &Ctx) override;
+ ASTMutationListener *GetASTMutationListener() override;
+ ASTDeserializationListener *GetASTDeserializationListener() override;
bool hasEmittedPCH() const { return HasEmittedPCH; }
};
diff --git a/include/clang/Serialization/GlobalModuleIndex.h b/include/clang/Serialization/GlobalModuleIndex.h
index 76414ba634cc..1f0d7523ec29 100644
--- a/include/clang/Serialization/GlobalModuleIndex.h
+++ b/include/clang/Serialization/GlobalModuleIndex.h
@@ -17,11 +17,11 @@
#define LLVM_CLANG_SERIALIZATION_GLOBAL_MODULE_INDEX_H
#include "llvm/ADT/DenseMap.h"
-#include "llvm/ADT/OwningPtr.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 {
@@ -59,7 +59,7 @@ using serialization::ModuleFile;
class GlobalModuleIndex {
/// \brief Buffer containing the index file, which is lazily accessed so long
/// as the global module index is live.
- llvm::OwningPtr<llvm::MemoryBuffer> Buffer;
+ std::unique_ptr<llvm::MemoryBuffer> Buffer;
/// \brief The hash table.
///
@@ -186,6 +186,9 @@ public:
/// \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.
diff --git a/include/clang/Serialization/Module.h b/include/clang/Serialization/Module.h
index 89c604f393ed..49520390559b 100644
--- a/include/clang/Serialization/Module.h
+++ b/include/clang/Serialization/Module.h
@@ -18,17 +18,21 @@
#include "clang/Basic/SourceLocation.h"
#include "clang/Serialization/ASTBitCodes.h"
#include "clang/Serialization/ContinuousRangeMap.h"
-#include "llvm/ADT/OwningPtr.h"
#include "llvm/ADT/SetVector.h"
#include "llvm/Bitcode/BitstreamReader.h"
+#include <memory>
#include <string>
+namespace llvm {
+template <typename Info> class OnDiskChainedHashTable;
+template <typename Info> class OnDiskIterableChainedHashTable;
+}
+
namespace clang {
class FileEntry;
class DeclContext;
class Module;
-template<typename Info> class OnDiskChainedHashTable;
namespace serialization {
@@ -49,7 +53,7 @@ struct DeclContextInfo {
DeclContextInfo()
: NameLookupTableData(), LexicalDecls(), NumLexicalDecls() {}
- OnDiskChainedHashTable<reader::ASTDeclContextNameLookupTrait>
+ llvm::OnDiskIterableChainedHashTable<reader::ASTDeclContextNameLookupTrait>
*NameLookupTableData; // an ASTDeclContextNameLookupTable.
const KindDeclIDPair *LexicalDecls;
unsigned NumLexicalDecls;
@@ -57,11 +61,12 @@ struct DeclContextInfo {
/// \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.
+/// out-of-date or not-found.
class InputFile {
enum {
Overridden = 1,
- OutOfDate = 2
+ OutOfDate = 2,
+ NotFound = 3
};
llvm::PointerIntPair<const FileEntry *, 2, unsigned> Val;
@@ -79,9 +84,16 @@ public:
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; }
};
/// \brief Information about a module that has been loaded by the ASTReader.
@@ -107,6 +119,13 @@ public:
/// \brief The file name of the module file.
std::string FileName;
+ /// \brief The name of the module.
+ std::string ModuleName;
+
+ 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.
@@ -124,6 +143,8 @@ public:
/// 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;
@@ -139,7 +160,7 @@ public:
/// \brief The memory buffer that stores the data associated with
/// this AST file.
- OwningPtr<llvm::MemoryBuffer> Buffer;
+ std::unique_ptr<llvm::MemoryBuffer> Buffer;
/// \brief The size of this file, in bits.
uint64_t SizeInBits;
@@ -159,6 +180,9 @@ public:
/// 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.
@@ -177,6 +201,12 @@ public:
/// \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.
diff --git a/include/clang/Serialization/ModuleManager.h b/include/clang/Serialization/ModuleManager.h
index ca643ba45f2e..3259902222d8 100644
--- a/include/clang/Serialization/ModuleManager.h
+++ b/include/clang/Serialization/ModuleManager.h
@@ -18,6 +18,7 @@
#include "clang/Basic/FileManager.h"
#include "clang/Serialization/Module.h"
#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/SmallPtrSet.h"
namespace clang {
@@ -65,7 +66,7 @@ class ModuleManager {
/// calls to visit().
struct VisitState {
explicit VisitState(unsigned N)
- : VisitNumber(N, 0), NextVisitNumber(1), NextState(0)
+ : VisitNumber(N, 0), NextVisitNumber(1), NextState(nullptr)
{
Stack.reserve(N);
}
@@ -194,6 +195,7 @@ public:
/// \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
@@ -230,7 +232,7 @@ public:
/// 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(bool (*Visitor)(ModuleFile &M, void *UserData), void *UserData,
- llvm::SmallPtrSet<ModuleFile *, 4> *ModuleFilesHit = 0);
+ llvm::SmallPtrSet<ModuleFile *, 4> *ModuleFilesHit = nullptr);
/// \brief Visit each of the modules with a depth-first traversal.
///
diff --git a/include/clang/StaticAnalyzer/Checkers/ObjCRetainCount.h b/include/clang/StaticAnalyzer/Checkers/ObjCRetainCount.h
index 5978299701cf..26335bf68dd9 100644
--- a/include/clang/StaticAnalyzer/Checkers/ObjCRetainCount.h
+++ b/include/clang/StaticAnalyzer/Checkers/ObjCRetainCount.h
@@ -114,8 +114,6 @@ public:
/// Indicates that the object is not owned and controlled by the
/// Garbage collector.
GCNotOwnedSymbol,
- /// Indicates that the object is not owned and controlled by ARC.
- ARCNotOwnedSymbol,
/// Indicates that the return value is an owned object when the
/// receiver is also a tracked object.
OwnedWhenTrackedReceiver,
@@ -154,7 +152,7 @@ public:
}
bool notOwned() const {
- return K == NotOwnedSymbol || K == ARCNotOwnedSymbol;
+ return K == NotOwnedSymbol;
}
bool operator==(const RetEffect &Other) const {
@@ -174,9 +172,6 @@ public:
static RetEffect MakeGCNotOwned() {
return RetEffect(GCNotOwnedSymbol, ObjC);
}
- static RetEffect MakeARCNotOwned() {
- return RetEffect(ARCNotOwnedSymbol, ObjC);
- }
static RetEffect MakeNoRet() {
return RetEffect(NoRet);
}
@@ -202,7 +197,7 @@ class CallEffects {
public:
/// Returns the argument effects for a call.
- llvm::ArrayRef<ArgEffect> getArgs() const { return Args; }
+ ArrayRef<ArgEffect> getArgs() const { return Args; }
/// Returns the effects on the receiver.
ArgEffect getReceiver() const { return Receiver; }
diff --git a/include/clang/StaticAnalyzer/Core/AnalyzerOptions.h b/include/clang/StaticAnalyzer/Core/AnalyzerOptions.h
index 618782e5d78c..978c3e20ab20 100644
--- a/include/clang/StaticAnalyzer/Core/AnalyzerOptions.h
+++ b/include/clang/StaticAnalyzer/Core/AnalyzerOptions.h
@@ -54,6 +54,7 @@ NumConstraints
enum AnalysisDiagClients {
#define ANALYSIS_DIAGNOSTICS(NAME, CMDFLAG, DESC, CREATFN) PD_##NAME,
#include "clang/StaticAnalyzer/Core/Analyses.def"
+PD_NONE,
NUM_ANALYSIS_DIAG_CLIENTS
};
@@ -140,7 +141,7 @@ public:
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.
///
@@ -198,8 +199,11 @@ private:
/// \sa mayInlineTemplateFunctions
Optional<bool> InlineTemplateFunctions;
- /// \sa mayInlineCXXContainerCtorsAndDtors
- Optional<bool> InlineCXXContainerCtorsAndDtors;
+ /// \sa mayInlineCXXAllocator
+ Optional<bool> InlineCXXAllocator;
+
+ /// \sa mayInlineCXXContainerMethods
+ Optional<bool> InlineCXXContainerMethods;
/// \sa mayInlineCXXSharedPtrDtor
Optional<bool> InlineCXXSharedPtrDtor;
@@ -229,6 +233,9 @@ private:
/// \sa reportIssuesInMainSourceFile
Optional<bool> ReportIssuesInMainSourceFile;
+ /// \sa StableReportFilename
+ Optional<bool> StableReportFilename;
+
/// \sa getGraphTrimInterval
Optional<unsigned> GraphTrimInterval;
@@ -290,12 +297,18 @@ public:
/// accepts the values "true" and "false".
bool mayInlineTemplateFunctions();
- /// Returns whether or not constructors and destructors of C++ container
- /// objects may be considered for inlining.
+ /// 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 mayInlineCXXContainerCtorsAndDtors();
+ bool mayInlineCXXContainerMethods();
/// Returns whether or not the destructor of C++ 'shared_ptr' may be
/// considered for inlining.
@@ -349,6 +362,12 @@ public:
/// 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.
///
diff --git a/include/clang/StaticAnalyzer/Core/BugReporter/BugReporter.h b/include/clang/StaticAnalyzer/Core/BugReporter/BugReporter.h
index 9584b8baf4f1..53712319253c 100644
--- a/include/clang/StaticAnalyzer/Core/BugReporter/BugReporter.h
+++ b/include/clang/StaticAnalyzer/Core/BugReporter/BugReporter.h
@@ -19,6 +19,7 @@
#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"
@@ -143,19 +144,18 @@ private:
public:
BugReport(BugType& bt, StringRef desc, const ExplodedNode *errornode)
- : BT(bt), DeclWithIssue(0), Description(desc), ErrorNode(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(0), ShortDescription(shortDesc), Description(desc),
- ErrorNode(errornode), ConfigurationChangeToken(0),
+ : BT(bt), DeclWithIssue(nullptr), ShortDescription(shortDesc),
+ Description(desc), ErrorNode(errornode), ConfigurationChangeToken(0),
DoNotPrunePath(false) {}
- BugReport(BugType& bt, StringRef desc, PathDiagnosticLocation l)
- : BT(bt), DeclWithIssue(0), Description(desc), Location(l), ErrorNode(0),
- 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.
///
@@ -166,7 +166,7 @@ public:
/// 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(0), Description(desc),
+ : BT(bt), DeclWithIssue(nullptr), Description(desc),
UniqueingLocation(LocationToUnique),
UniqueingDecl(DeclToUnique),
ErrorNode(errornode), ConfigurationChangeToken(0),
@@ -463,7 +463,12 @@ public:
/// reports.
void emitReport(BugReport *R);
- void EmitBasicReport(const Decl *DeclWithIssue,
+ 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);
@@ -473,7 +478,8 @@ private:
/// \brief Returns a BugType that is associated with the given name and
/// category.
- BugType *getBugTypeForName(StringRef name, StringRef category);
+ BugType *getBugTypeForName(CheckName CheckName, StringRef name,
+ StringRef category);
};
// FIXME: Get rid of GRBugReporter. It's the wrong abstraction.
@@ -505,9 +511,8 @@ public:
///
/// \return True if the report was valid and a path was generated,
/// false if the reports should be considered invalid.
- virtual bool generatePathDiagnostic(PathDiagnostic &PD,
- PathDiagnosticConsumer &PC,
- ArrayRef<BugReport*> &bugReports);
+ bool generatePathDiagnostic(PathDiagnostic &PD, PathDiagnosticConsumer &PC,
+ ArrayRef<BugReport*> &bugReports) override;
/// classof - Used by isa<>, cast<>, and dyn_cast<>.
static bool classof(const BugReporter* R) {
diff --git a/include/clang/StaticAnalyzer/Core/BugReporter/BugReporterVisitor.h b/include/clang/StaticAnalyzer/Core/BugReporter/BugReporterVisitor.h
index 2e67180beace..f352f806eb9c 100644
--- a/include/clang/StaticAnalyzer/Core/BugReporter/BugReporterVisitor.h
+++ b/include/clang/StaticAnalyzer/Core/BugReporter/BugReporterVisitor.h
@@ -89,7 +89,7 @@ public:
/// will have to provide your own implementation.)
template <class DERIVED>
class BugReporterVisitorImpl : public BugReporterVisitor {
- virtual BugReporterVisitor *clone() const {
+ BugReporterVisitor *clone() const override {
return new DERIVED(*static_cast<const DERIVED *>(this));
}
};
@@ -118,12 +118,12 @@ public:
Satisfied(false),
EnableNullFPSuppression(InEnableNullFPSuppression) {}
- void Profile(llvm::FoldingSetNodeID &ID) const;
+ void Profile(llvm::FoldingSetNodeID &ID) const override;
PathDiagnosticPiece *VisitNode(const ExplodedNode *N,
const ExplodedNode *PrevN,
BugReporterContext &BRC,
- BugReport &BR);
+ BugReport &BR) override;
};
class TrackConstraintBRVisitor
@@ -144,7 +144,7 @@ public:
IsZeroCheck(!Assumption && Constraint.getAs<Loc>()),
IsTrackingTurnedOn(false) {}
- void Profile(llvm::FoldingSetNodeID &ID) const;
+ 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.
@@ -153,7 +153,7 @@ public:
PathDiagnosticPiece *VisitNode(const ExplodedNode *N,
const ExplodedNode *PrevN,
BugReporterContext &BRC,
- BugReport &BR);
+ BugReport &BR) override;
private:
/// Checks if the constraint is valid in the current state.
@@ -166,8 +166,8 @@ private:
class NilReceiverBRVisitor
: public BugReporterVisitorImpl<NilReceiverBRVisitor> {
public:
-
- void Profile(llvm::FoldingSetNodeID &ID) const {
+
+ void Profile(llvm::FoldingSetNodeID &ID) const override {
static int x = 0;
ID.AddPointer(&x);
}
@@ -175,7 +175,7 @@ public:
PathDiagnosticPiece *VisitNode(const ExplodedNode *N,
const ExplodedNode *PrevN,
BugReporterContext &BRC,
- BugReport &BR);
+ BugReport &BR) override;
/// If the statement is a message send expression with nil receiver, returns
/// the receiver expression. Returns NULL otherwise.
@@ -185,7 +185,7 @@ public:
/// Visitor that tries to report interesting diagnostics from conditions.
class ConditionBRVisitor : public BugReporterVisitorImpl<ConditionBRVisitor> {
public:
- void Profile(llvm::FoldingSetNodeID &ID) const {
+ void Profile(llvm::FoldingSetNodeID &ID) const override {
static int x = 0;
ID.AddPointer(&x);
}
@@ -193,11 +193,11 @@ public:
/// Return the tag associated with this visitor. This tag will be used
/// to make all PathDiagnosticPieces created by this visitor.
static const char *getTag();
-
- virtual PathDiagnosticPiece *VisitNode(const ExplodedNode *N,
- const ExplodedNode *Prev,
- BugReporterContext &BRC,
- BugReport &BR);
+
+ PathDiagnosticPiece *VisitNode(const ExplodedNode *N,
+ const ExplodedNode *Prev,
+ BugReporterContext &BRC,
+ BugReport &BR) override;
PathDiagnosticPiece *VisitNodeImpl(const ExplodedNode *N,
const ExplodedNode *Prev,
@@ -257,20 +257,20 @@ public:
return static_cast<void *>(&Tag);
}
- void Profile(llvm::FoldingSetNodeID &ID) const {
+ void Profile(llvm::FoldingSetNodeID &ID) const override {
ID.AddPointer(getTag());
}
- virtual PathDiagnosticPiece *VisitNode(const ExplodedNode *N,
- const ExplodedNode *Prev,
- BugReporterContext &BRC,
- BugReport &BR) {
- return 0;
+ PathDiagnosticPiece *VisitNode(const ExplodedNode *N,
+ const ExplodedNode *Prev,
+ BugReporterContext &BRC,
+ BugReport &BR) override {
+ return nullptr;
}
- virtual PathDiagnosticPiece *getEndPath(BugReporterContext &BRC,
- const ExplodedNode *N,
- BugReport &BR);
+ PathDiagnosticPiece *getEndPath(BugReporterContext &BRC,
+ const ExplodedNode *N,
+ BugReport &BR) override;
};
/// \brief When a region containing undefined value or '0' value is passed
@@ -287,7 +287,7 @@ class UndefOrNullArgVisitor
public:
UndefOrNullArgVisitor(const MemRegion *InR) : R(InR) {}
- virtual void Profile(llvm::FoldingSetNodeID &ID) const {
+ void Profile(llvm::FoldingSetNodeID &ID) const override {
static int Tag = 0;
ID.AddPointer(&Tag);
ID.AddPointer(R);
@@ -296,7 +296,7 @@ public:
PathDiagnosticPiece *VisitNode(const ExplodedNode *N,
const ExplodedNode *PrevN,
BugReporterContext &BRC,
- BugReport &BR);
+ BugReport &BR) override;
};
class SuppressInlineDefensiveChecksVisitor
@@ -319,7 +319,7 @@ class SuppressInlineDefensiveChecksVisitor
public:
SuppressInlineDefensiveChecksVisitor(DefinedSVal Val, const ExplodedNode *N);
- void Profile(llvm::FoldingSetNodeID &ID) const;
+ 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.
@@ -328,7 +328,7 @@ public:
PathDiagnosticPiece *VisitNode(const ExplodedNode *Succ,
const ExplodedNode *Pred,
BugReporterContext &BRC,
- BugReport &BR);
+ BugReport &BR) override;
};
namespace bugreporter {
diff --git a/include/clang/StaticAnalyzer/Core/BugReporter/BugType.h b/include/clang/StaticAnalyzer/Core/BugReporter/BugType.h
index 49f9c83ba950..24c778552ee4 100644
--- a/include/clang/StaticAnalyzer/Core/BugReporter/BugType.h
+++ b/include/clang/StaticAnalyzer/Core/BugReporter/BugType.h
@@ -14,8 +14,9 @@
#ifndef LLVM_CLANG_ANALYSIS_BUGTYPE
#define LLVM_CLANG_ANALYSIS_BUGTYPE
-#include "clang/StaticAnalyzer/Core/BugReporter/CommonBugCategories.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>
@@ -29,20 +30,25 @@ class ExprEngine;
class BugType {
private:
+ const CheckName Check;
const std::string Name;
const std::string Category;
bool SuppressonSink;
virtual void anchor();
public:
- BugType(StringRef name, StringRef cat)
- : Name(name), Category(cat), SuppressonSink(false) {}
+ 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.
@@ -54,14 +60,18 @@ public:
class BuiltinBug : public BugType {
const std::string desc;
- virtual void anchor();
+ void anchor() override;
public:
- BuiltinBug(const char *name, const char *description)
- : BugType(name, categories::LogicError), desc(description) {}
-
- BuiltinBug(const char *name)
- : BugType(name, categories::LogicError), desc(name) {}
-
+ 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; }
};
diff --git a/include/clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h b/include/clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h
index b0670dad240d..5a578d015e39 100644
--- a/include/clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h
+++ b/include/clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h
@@ -21,13 +21,13 @@
#include "llvm/ADT/Optional.h"
#include "llvm/ADT/PointerUnion.h"
#include <deque>
-#include <list>
#include <iterator>
+#include <list>
#include <string>
#include <vector>
namespace clang {
-
+class ConditionalOperator;
class AnalysisDeclContext;
class BinaryOperator;
class CompoundStmt;
@@ -72,7 +72,9 @@ public:
struct FilesMade : public llvm::FoldingSet<PDFileEntry> {
llvm::BumpPtrAllocator Alloc;
-
+
+ ~FilesMade();
+
void addDiagnostic(const PathDiagnostic &PD,
StringRef ConsumerName,
StringRef fileName);
@@ -136,29 +138,29 @@ private:
PathDiagnosticLocation(SourceLocation L, const SourceManager &sm,
Kind kind)
- : K(kind), S(0), D(0), SM(&sm),
+ : K(kind), S(nullptr), D(nullptr), SM(&sm),
Loc(genLocation(L)), Range(genRange()) {
}
- FullSourceLoc
- genLocation(SourceLocation L = SourceLocation(),
- LocationOrAnalysisDeclContext LAC = (AnalysisDeclContext*)0) const;
+ FullSourceLoc genLocation(
+ SourceLocation L = SourceLocation(),
+ LocationOrAnalysisDeclContext LAC = (AnalysisDeclContext *)nullptr) const;
- PathDiagnosticRange
- genRange(LocationOrAnalysisDeclContext LAC = (AnalysisDeclContext*)0) const;
+ PathDiagnosticRange genRange(
+ LocationOrAnalysisDeclContext LAC = (AnalysisDeclContext *)nullptr) const;
public:
/// Create an invalid location.
PathDiagnosticLocation()
- : K(SingleLocK), S(0), D(0), SM(0) {}
+ : 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 : 0),
- D(0), SM(&sm),
+ S(K == StmtK ? s : nullptr),
+ D(nullptr), SM(&sm),
Loc(genLocation(SourceLocation(), lac)),
Range(genRange(lac)) {
assert(K == SingleLocK || S);
@@ -168,7 +170,7 @@ public:
/// Create a location corresponding to the given declaration.
PathDiagnosticLocation(const Decl *d, const SourceManager &sm)
- : K(DeclK), S(0), D(d), SM(&sm),
+ : K(DeclK), S(nullptr), D(d), SM(&sm),
Loc(genLocation()), Range(genRange()) {
assert(D);
assert(Loc.isValid());
@@ -179,7 +181,8 @@ public:
///
/// This should only be used if there are no more appropriate constructors.
PathDiagnosticLocation(SourceLocation loc, const SourceManager &sm)
- : K(SingleLocK), S(0), D(0), SM(&sm), Loc(loc, sm), Range(genRange()) {
+ : K(SingleLocK), S(nullptr), D(nullptr), SM(&sm), Loc(loc, sm),
+ Range(genRange()) {
assert(Loc.isValid());
assert(Range.isValid());
}
@@ -211,6 +214,9 @@ public:
/// 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.
@@ -259,7 +265,7 @@ public:
}
bool isValid() const {
- return SM != 0;
+ return SM != nullptr;
}
FullSourceLoc asLocation() const {
@@ -420,7 +426,7 @@ public:
return Result;
}
- LLVM_ATTRIBUTE_USED void dump() const;
+ void dump() const;
};
class PathDiagnosticSpotPiece : public PathDiagnosticPiece {
@@ -437,10 +443,10 @@ public:
if (addPosRange && Pos.hasRange()) addRange(Pos.asRange());
}
- PathDiagnosticLocation getLocation() const { return Pos; }
- virtual void flattenLocations() { Pos.flatten(); }
+ PathDiagnosticLocation getLocation() const override { return Pos; }
+ void flattenLocations() override { Pos.flatten(); }
- virtual void Profile(llvm::FoldingSetNodeID &ID) const;
+ void Profile(llvm::FoldingSetNodeID &ID) const override;
static bool classof(const PathDiagnosticPiece *P) {
return P->getKind() == Event || P->getKind() == Macro;
@@ -476,7 +482,7 @@ public:
/// \brief Search the call expression for the symbol Sym and dispatch the
/// 'getMessageForX()' methods to construct a specific message.
- virtual std::string getMessage(const ExplodedNode *N);
+ std::string getMessage(const ExplodedNode *N) override;
/// Produces the message of the following form:
/// 'Msg via Nth parameter'
@@ -496,12 +502,12 @@ class PathDiagnosticEventPiece : public PathDiagnosticSpotPiece {
/// 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.
- OwningPtr<StackHintGenerator> CallStackHint;
+ std::unique_ptr<StackHintGenerator> CallStackHint;
public:
PathDiagnosticEventPiece(const PathDiagnosticLocation &pos,
StringRef s, bool addPosRange = true,
- StackHintGenerator *stackHint = 0)
+ StackHintGenerator *stackHint = nullptr)
: PathDiagnosticSpotPiece(pos, s, Event, addPosRange),
CallStackHint(stackHint) {}
@@ -520,10 +526,8 @@ public:
bool isPrunable() const {
return IsPrunable.hasValue() ? IsPrunable.getValue() : false;
}
-
- bool hasCallStackHint() {
- return CallStackHint.isValid();
- }
+
+ 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.
@@ -533,7 +537,7 @@ public:
return "";
}
- virtual void dump() const;
+ void dump() const override;
static inline bool classof(const PathDiagnosticPiece *P) {
return P->getKind() == Event;
@@ -543,11 +547,11 @@ public:
class PathDiagnosticCallPiece : public PathDiagnosticPiece {
PathDiagnosticCallPiece(const Decl *callerD,
const PathDiagnosticLocation &callReturnPos)
- : PathDiagnosticPiece(Call), Caller(callerD), Callee(0),
+ : PathDiagnosticPiece(Call), Caller(callerD), Callee(nullptr),
NoExit(false), callReturn(callReturnPos) {}
PathDiagnosticCallPiece(PathPieces &oldPath, const Decl *caller)
- : PathDiagnosticPiece(Call), Caller(caller), Callee(0),
+ : PathDiagnosticPiece(Call), Caller(caller), Callee(nullptr),
NoExit(true), path(oldPath) {}
const Decl *Caller;
@@ -579,7 +583,7 @@ public:
CallStackMessage = st;
}
- virtual PathDiagnosticLocation getLocation() const {
+ PathDiagnosticLocation getLocation() const override {
return callEnter;
}
@@ -588,7 +592,7 @@ public:
getCallEnterWithinCallerEvent() const;
IntrusiveRefCntPtr<PathDiagnosticEventPiece> getCallExitEvent() const;
- virtual void flattenLocations() {
+ void flattenLocations() override {
callEnter.flatten();
callReturn.flatten();
for (PathPieces::iterator I = path.begin(),
@@ -601,10 +605,10 @@ public:
static PathDiagnosticCallPiece *construct(PathPieces &pieces,
const Decl *caller);
-
- virtual void dump() const;
- virtual void Profile(llvm::FoldingSetNodeID &ID) const;
+ void dump() const override;
+
+ void Profile(llvm::FoldingSetNodeID &ID) const override;
static inline bool classof(const PathDiagnosticPiece *P) {
return P->getKind() == Call;
@@ -651,7 +655,7 @@ public:
void push_back(const PathDiagnosticLocationPair &X) { LPairs.push_back(X); }
- virtual PathDiagnosticLocation getLocation() const {
+ PathDiagnosticLocation getLocation() const override {
return getStartLocation();
}
@@ -659,7 +663,7 @@ public:
iterator begin() { return LPairs.begin(); }
iterator end() { return LPairs.end(); }
- virtual void flattenLocations() {
+ void flattenLocations() override {
for (iterator I=begin(), E=end(); I!=E; ++I) I->flatten();
}
@@ -672,9 +676,9 @@ public:
return P->getKind() == ControlFlow;
}
- virtual void dump() const;
+ void dump() const override;
- virtual void Profile(llvm::FoldingSetNodeID &ID) const;
+ void Profile(llvm::FoldingSetNodeID &ID) const override;
};
class PathDiagnosticMacroPiece : public PathDiagnosticSpotPiece {
@@ -688,7 +692,7 @@ public:
bool containsEvent() const;
- virtual void flattenLocations() {
+ void flattenLocations() override {
PathDiagnosticSpotPiece::flattenLocations();
for (PathPieces::iterator I = subPieces.begin(),
E = subPieces.end(); I != E; ++I) (*I)->flattenLocations();
@@ -698,15 +702,16 @@ public:
return P->getKind() == Macro;
}
- virtual void dump() const;
+ void dump() const override;
- virtual void Profile(llvm::FoldingSetNodeID &ID) const;
+ 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;
@@ -727,8 +732,8 @@ class PathDiagnostic : public llvm::FoldingSetNode {
PathDiagnostic() LLVM_DELETED_FUNCTION;
public:
- PathDiagnostic(const Decl *DeclWithIssue, StringRef bugtype,
- StringRef verboseDesc, StringRef shortDesc,
+ PathDiagnostic(StringRef CheckName, const Decl *DeclWithIssue,
+ StringRef bugtype, StringRef verboseDesc, StringRef shortDesc,
StringRef category, PathDiagnosticLocation LocationToUnique,
const Decl *DeclToUnique);
@@ -785,6 +790,7 @@ public:
StringRef getShortDescription() const {
return ShortDesc.empty() ? VerboseDesc : ShortDesc;
}
+ StringRef getCheckName() const { return CheckName; }
StringRef getBugType() const { return BugType; }
StringRef getCategory() const { return Category; }
diff --git a/include/clang/StaticAnalyzer/Core/Checker.h b/include/clang/StaticAnalyzer/Core/Checker.h
index cf7cf051d225..b9a5b8a27fa9 100644
--- a/include/clang/StaticAnalyzer/Core/Checker.h
+++ b/include/clang/StaticAnalyzer/Core/Checker.h
@@ -453,14 +453,29 @@ public:
} // end eval namespace
class CheckerBase : public ProgramPointTag {
+ CheckName Name;
+ friend class ::clang::ento::CheckerManager;
+
public:
- StringRef getTagDescription() const;
+ 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 CHECK2=check::_VoidCheck,
typename CHECK3=check::_VoidCheck, typename CHECK4=check::_VoidCheck,
typename CHECK5=check::_VoidCheck, typename CHECK6=check::_VoidCheck,
@@ -511,7 +526,7 @@ template <typename EVENT>
class EventDispatcher {
CheckerManager *Mgr;
public:
- EventDispatcher() : Mgr(0) { }
+ EventDispatcher() : Mgr(nullptr) { }
template <typename CHECKER>
static void _register(CHECKER *checker, CheckerManager &mgr) {
diff --git a/include/clang/StaticAnalyzer/Core/CheckerManager.h b/include/clang/StaticAnalyzer/Core/CheckerManager.h
index 8ad67c118f01..b364115c99b6 100644
--- a/include/clang/StaticAnalyzer/Core/CheckerManager.h
+++ b/include/clang/StaticAnalyzer/Core/CheckerManager.h
@@ -16,8 +16,8 @@
#include "clang/Analysis/ProgramPoint.h"
#include "clang/Basic/LangOptions.h"
-#include "clang/StaticAnalyzer/Core/PathSensitive/Store.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>
@@ -29,11 +29,11 @@ namespace clang {
namespace ento {
class CheckerBase;
+ class CheckerRegistry;
class ExprEngine;
class AnalysisManager;
class BugReporter;
class CheckerContext;
- class SimpleCall;
class ObjCMethodCall;
class SVal;
class ExplodedNode;
@@ -132,9 +132,26 @@ enum PointerEscapeKind {
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() {}
+ CheckName(const CheckName &Other) : Name(Other.Name) {}
+ StringRef getName() const { return Name; }
+};
+
class CheckerManager {
const LangOptions LangOpts;
AnalyzerOptionsRef AOptions;
+ CheckName CurrentCheckName;
+
public:
CheckerManager(const LangOptions &langOpts,
AnalyzerOptionsRef AOptions)
@@ -143,6 +160,9 @@ public:
~CheckerManager();
+ void setCurrentCheckName(CheckName name) { CurrentCheckName = name; }
+ CheckName getCurrentCheckName() const { return CurrentCheckName; }
+
bool hasPathSensitiveCheckers() const;
void finishedCheckerRegistration();
@@ -169,6 +189,7 @@ public:
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;
@@ -183,6 +204,7 @@ public:
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;
diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/APSIntType.h b/include/clang/StaticAnalyzer/Core/PathSensitive/APSIntType.h
index 9502900f7e35..37be69aaba84 100644
--- a/include/clang/StaticAnalyzer/Core/PathSensitive/APSIntType.h
+++ b/include/clang/StaticAnalyzer/Core/PathSensitive/APSIntType.h
@@ -11,6 +11,7 @@
#define LLVM_CLANG_SA_CORE_APSINTTYPE_H
#include "llvm/ADT/APSInt.h"
+#include <tuple>
namespace clang {
namespace ento {
@@ -97,13 +98,8 @@ public:
/// Unsigned integers are considered to be better conversion types than
/// signed integers of the same width.
bool operator<(const APSIntType &Other) const {
- if (BitWidth < Other.BitWidth)
- return true;
- if (BitWidth > Other.BitWidth)
- return false;
- if (!IsUnsigned && Other.IsUnsigned)
- return true;
- return false;
+ return std::tie(BitWidth, IsUnsigned) <
+ std::tie(Other.BitWidth, Other.IsUnsigned);
}
};
diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h b/include/clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h
index d7d83ce8b17d..1a398b86484d 100644
--- a/include/clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h
+++ b/include/clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h
@@ -65,8 +65,8 @@ public:
StoreManagerCreator getStoreManagerCreator() {
return CreateStoreMgr;
}
-
- AnalyzerOptions& getAnalyzerOptions() {
+
+ AnalyzerOptions& getAnalyzerOptions() override {
return options;
}
@@ -76,15 +76,15 @@ public:
CheckerManager *getCheckerManager() const { return CheckerMgr; }
- virtual ASTContext &getASTContext() {
+ ASTContext &getASTContext() override {
return Ctx;
}
- virtual SourceManager &getSourceManager() {
+ SourceManager &getSourceManager() override {
return getASTContext().getSourceManager();
}
- virtual DiagnosticsEngine &getDiagnostic() {
+ DiagnosticsEngine &getDiagnostic() override {
return Diags;
}
@@ -92,7 +92,7 @@ public:
return LangOpts;
}
- ArrayRef<PathDiagnosticConsumer*> getPathDiagnosticConsumers() {
+ ArrayRef<PathDiagnosticConsumer*> getPathDiagnosticConsumers() override {
return PathConsumers;
}
diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/BasicValueFactory.h b/include/clang/StaticAnalyzer/Core/PathSensitive/BasicValueFactory.h
index 2c799c0db44e..08905fdf0783 100644
--- a/include/clang/StaticAnalyzer/Core/PathSensitive/BasicValueFactory.h
+++ b/include/clang/StaticAnalyzer/Core/PathSensitive/BasicValueFactory.h
@@ -79,9 +79,9 @@ class BasicValueFactory {
const llvm::APSInt& getValue(uint64_t X, unsigned BitWidth, bool isUnsigned);
public:
- BasicValueFactory(ASTContext &ctx, llvm::BumpPtrAllocator& Alloc)
- : Ctx(ctx), BPAlloc(Alloc), PersistentSVals(0), PersistentSValPairs(0),
- SValListFactory(Alloc) {}
+ BasicValueFactory(ASTContext &ctx, llvm::BumpPtrAllocator &Alloc)
+ : Ctx(ctx), BPAlloc(Alloc), PersistentSVals(nullptr),
+ PersistentSValPairs(nullptr), SValListFactory(Alloc) {}
~BasicValueFactory();
diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/BlockCounter.h b/include/clang/StaticAnalyzer/Core/PathSensitive/BlockCounter.h
index 2483a79455b2..0408070e493f 100644
--- a/include/clang/StaticAnalyzer/Core/PathSensitive/BlockCounter.h
+++ b/include/clang/StaticAnalyzer/Core/PathSensitive/BlockCounter.h
@@ -16,9 +16,7 @@
#ifndef LLVM_CLANG_GR_BLOCKCOUNTER
#define LLVM_CLANG_GR_BLOCKCOUNTER
-namespace llvm {
- class BumpPtrAllocator;
-}
+#include "llvm/Support/Allocator.h"
namespace clang {
@@ -35,7 +33,7 @@ class BlockCounter {
BlockCounter(void *D) : Data(D) {}
public:
- BlockCounter() : Data(0) {}
+ BlockCounter() : Data(nullptr) {}
unsigned getNumVisited(const StackFrameContext *CallSite,
unsigned BlockID) const;
diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h b/include/clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h
index cfaf085b5f34..4a5426b2747d 100644
--- a/include/clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h
+++ b/include/clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h
@@ -33,9 +33,6 @@ namespace ento {
enum CallEventKind {
CE_Function,
- CE_Block,
- CE_BEG_SIMPLE_CALLS = CE_Function,
- CE_END_SIMPLE_CALLS = CE_Block,
CE_CXXMember,
CE_CXXMemberOperator,
CE_CXXDestructor,
@@ -45,6 +42,7 @@ enum CallEventKind {
CE_CXXAllocator,
CE_BEG_FUNCTION_CALLS = CE_Function,
CE_END_FUNCTION_CALLS = CE_CXXAllocator,
+ CE_Block,
CE_ObjCMessage
};
@@ -58,14 +56,14 @@ public:
CallEventRef(const CallEventRef &Orig) : IntrusiveRefCntPtr<const T>(Orig) {}
CallEventRef<T> cloneWithState(ProgramStateRef State) const {
- return this->getPtr()->template cloneWithState<T>(State);
+ 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->getPtr();
+ return this->get();
}
};
@@ -88,15 +86,15 @@ class RuntimeDefinition {
const MemRegion *R;
public:
- RuntimeDefinition(): D(0), R(0) {}
- RuntimeDefinition(const Decl *InD): D(InD), R(0) {}
+ 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 != 0; }
+ bool mayHaveOtherDefinitions() { return R != nullptr; }
/// When other definitions are possible, returns the region whose runtime type
/// determines the method definition.
@@ -239,7 +237,7 @@ public:
/// \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 0; }
+ virtual const Expr *getArgExpr(unsigned Index) const { return nullptr; }
/// \brief Returns the source range for errors associated with this argument.
///
@@ -295,20 +293,20 @@ public:
const IdentifierInfo *getCalleeIdentifier() const {
const NamedDecl *ND = dyn_cast_or_null<NamedDecl>(getDecl());
if (!ND)
- return 0;
+ return nullptr;
return ND->getIdentifier();
}
/// \brief Returns an appropriate ProgramPoint for this call.
ProgramPoint getProgramPoint(bool IsPreVisit = false,
- const ProgramPointTag *Tag = 0) const;
+ 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 = 0) const;
+ ProgramStateRef Orig = nullptr) const;
typedef std::pair<Loc, SVal> FrameBindingTy;
typedef SmallVectorImpl<FrameBindingTy> BindingsTy;
@@ -344,23 +342,16 @@ public:
// Iterator access to formal parameters and their types.
private:
typedef std::const_mem_fun_t<QualType, ParmVarDecl> get_type_fun;
-
-public:
- typedef const ParmVarDecl * const *param_iterator;
- /// Returns an iterator over the call's formal parameters.
+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).
- ///
- /// If the call has no accessible declaration, \c param_begin() will be equal
- /// to \c param_end().
- virtual param_iterator param_begin() const = 0;
- /// \sa param_begin()
- virtual param_iterator param_end() const = 0;
+ virtual ArrayRef<ParmVarDecl*> parameters() const = 0;
- typedef llvm::mapped_iterator<param_iterator, get_type_fun>
+ 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.
@@ -369,17 +360,18 @@ public:
/// definition because it represents a public interface, and probably has
/// more annotations.
param_type_iterator param_type_begin() const {
- return llvm::map_iterator(param_begin(),
+ 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(param_end(), get_type_fun(&ParmVarDecl::getType));
+ return llvm::map_iterator(parameters().end(),
+ get_type_fun(&ParmVarDecl::getType));
}
// For debugging purposes only
void dump(raw_ostream &Out) const;
- LLVM_ATTRIBUTE_USED void dump() const;
+ void dump() const;
};
@@ -398,11 +390,11 @@ protected:
public:
// This function is overridden by subclasses, but they must return
// a FunctionDecl.
- virtual const FunctionDecl *getDecl() const {
+ const FunctionDecl *getDecl() const override {
return cast<FunctionDecl>(CallEvent::getDecl());
}
- virtual RuntimeDefinition getRuntimeDefinition() const {
+ RuntimeDefinition getRuntimeDefinition() const override {
const FunctionDecl *FD = getDecl();
// Note that the AnalysisDeclContext will have the FunctionDecl with
// the definition (if one exists).
@@ -417,13 +409,12 @@ public:
return RuntimeDefinition();
}
- virtual bool argumentsMayEscape() const;
+ bool argumentsMayEscape() const override;
- virtual void getInitialStackFrameContents(const StackFrameContext *CalleeCtx,
- BindingsTy &Bindings) const;
+ void getInitialStackFrameContents(const StackFrameContext *CalleeCtx,
+ BindingsTy &Bindings) const override;
- virtual param_iterator param_begin() const;
- virtual param_iterator param_end() const;
+ ArrayRef<ParmVarDecl *> parameters() const override;
static bool classof(const CallEvent *CA) {
return CA->getKind() >= CE_BEG_FUNCTION_CALLS &&
@@ -431,49 +422,36 @@ public:
}
};
-/// \brief Represents a call to a non-C++ function, written as a CallExpr.
-class SimpleCall : public AnyFunctionCall {
+/// \brief Represents a C function or static C++ member function call.
+///
+/// Example: \c fun()
+class SimpleFunctionCall : public AnyFunctionCall {
+ friend class CallEventManager;
+
protected:
- SimpleCall(const CallExpr *CE, ProgramStateRef St,
- const LocationContext *LCtx)
+ SimpleFunctionCall(const CallExpr *CE, ProgramStateRef St,
+ const LocationContext *LCtx)
: AnyFunctionCall(CE, St, LCtx) {}
- SimpleCall(const SimpleCall &Other) : AnyFunctionCall(Other) {}
+ 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());
}
- virtual const FunctionDecl *getDecl() const;
+ const FunctionDecl *getDecl() const override;
- virtual unsigned getNumArgs() const { return getOriginExpr()->getNumArgs(); }
+ unsigned getNumArgs() const override { return getOriginExpr()->getNumArgs(); }
- virtual const Expr *getArgExpr(unsigned Index) const {
+ const Expr *getArgExpr(unsigned Index) const override {
return getOriginExpr()->getArg(Index);
}
- static bool classof(const CallEvent *CA) {
- return CA->getKind() >= CE_BEG_SIMPLE_CALLS &&
- CA->getKind() <= CE_END_SIMPLE_CALLS;
- }
-};
-
-/// \brief Represents a C function or static C++ member function call.
-///
-/// Example: \c fun()
-class FunctionCall : public SimpleCall {
- friend class CallEventManager;
-
-protected:
- FunctionCall(const CallExpr *CE, ProgramStateRef St,
- const LocationContext *LCtx)
- : SimpleCall(CE, St, LCtx) {}
-
- FunctionCall(const FunctionCall &Other) : SimpleCall(Other) {}
- virtual void cloneTo(void *Dest) const { new (Dest) FunctionCall(*this); }
-
-public:
- virtual Kind getKind() const { return CE_Function; }
+ Kind getKind() const override { return CE_Function; }
static bool classof(const CallEvent *CA) {
return CA->getKind() == CE_Function;
@@ -483,47 +461,56 @@ public:
/// \brief Represents a call to a block.
///
/// Example: <tt>^{ /* ... */ }()</tt>
-class BlockCall : public SimpleCall {
+class BlockCall : public CallEvent {
friend class CallEventManager;
protected:
BlockCall(const CallExpr *CE, ProgramStateRef St,
const LocationContext *LCtx)
- : SimpleCall(CE, St, LCtx) {}
+ : CallEvent(CE, St, LCtx) {}
- BlockCall(const BlockCall &Other) : SimpleCall(Other) {}
- virtual void cloneTo(void *Dest) const { new (Dest) BlockCall(*this); }
+ BlockCall(const BlockCall &Other) : CallEvent(Other) {}
+ void cloneTo(void *Dest) const override { new (Dest) BlockCall(*this); }
- virtual void getExtraInvalidatedValues(ValueList &Values) const;
+ void getExtraInvalidatedValues(ValueList &Values) 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;
- /// \brief Gets the declaration of the block.
- ///
- /// This is not an override of getDecl() because AnyFunctionCall has already
- /// assumed that it's a FunctionDecl.
- const BlockDecl *getBlockDecl() const {
+ const BlockDecl *getDecl() const override {
const BlockDataRegion *BR = getBlockRegion();
if (!BR)
- return 0;
+ return nullptr;
return BR->getDecl();
}
- virtual RuntimeDefinition getRuntimeDefinition() const {
- return RuntimeDefinition(getBlockDecl());
+ RuntimeDefinition getRuntimeDefinition() const override {
+ return RuntimeDefinition(getDecl());
}
- virtual void getInitialStackFrameContents(const StackFrameContext *CalleeCtx,
- BindingsTy &Bindings) const;
+ bool argumentsMayEscape() const override {
+ return true;
+ }
- virtual param_iterator param_begin() const;
- virtual param_iterator param_end() const;
+ void getInitialStackFrameContents(const StackFrameContext *CalleeCtx,
+ BindingsTy &Bindings) const override;
- virtual Kind getKind() const { return CE_Block; }
+ ArrayRef<ParmVarDecl*> parameters() const override;
+
+ Kind getKind() const override { return CE_Block; }
static bool classof(const CallEvent *CA) {
return CA->getKind() == CE_Block;
@@ -534,7 +521,7 @@ public:
/// it is written.
class CXXInstanceCall : public AnyFunctionCall {
protected:
- virtual void getExtraInvalidatedValues(ValueList &Values) const;
+ void getExtraInvalidatedValues(ValueList &Values) const override;
CXXInstanceCall(const CallExpr *CE, ProgramStateRef St,
const LocationContext *LCtx)
@@ -548,17 +535,17 @@ protected:
public:
/// \brief Returns the expression representing the implicit 'this' object.
- virtual const Expr *getCXXThisExpr() const { return 0; }
+ virtual const Expr *getCXXThisExpr() const { return nullptr; }
/// \brief Returns the value of the implicit 'this' object.
virtual SVal getCXXThisVal() const;
- virtual const FunctionDecl *getDecl() const;
+ const FunctionDecl *getDecl() const override;
- virtual RuntimeDefinition getRuntimeDefinition() const;
+ RuntimeDefinition getRuntimeDefinition() const override;
- virtual void getInitialStackFrameContents(const StackFrameContext *CalleeCtx,
- BindingsTy &Bindings) const;
+ void getInitialStackFrameContents(const StackFrameContext *CalleeCtx,
+ BindingsTy &Bindings) const override;
static bool classof(const CallEvent *CA) {
return CA->getKind() >= CE_BEG_CXX_INSTANCE_CALLS &&
@@ -578,28 +565,28 @@ protected:
: CXXInstanceCall(CE, St, LCtx) {}
CXXMemberCall(const CXXMemberCall &Other) : CXXInstanceCall(Other) {}
- virtual void cloneTo(void *Dest) const { new (Dest) CXXMemberCall(*this); }
+ void cloneTo(void *Dest) const override { new (Dest) CXXMemberCall(*this); }
public:
virtual const CXXMemberCallExpr *getOriginExpr() const {
return cast<CXXMemberCallExpr>(CXXInstanceCall::getOriginExpr());
}
- virtual unsigned getNumArgs() const {
+ unsigned getNumArgs() const override {
if (const CallExpr *CE = getOriginExpr())
return CE->getNumArgs();
return 0;
}
- virtual const Expr *getArgExpr(unsigned Index) const {
+ const Expr *getArgExpr(unsigned Index) const override {
return getOriginExpr()->getArg(Index);
}
- virtual const Expr *getCXXThisExpr() const;
-
- virtual RuntimeDefinition getRuntimeDefinition() const;
+ const Expr *getCXXThisExpr() const override;
- virtual Kind getKind() const { return CE_CXXMember; }
+ RuntimeDefinition getRuntimeDefinition() const override;
+
+ Kind getKind() const override { return CE_CXXMember; }
static bool classof(const CallEvent *CA) {
return CA->getKind() == CE_CXXMember;
@@ -620,7 +607,7 @@ protected:
CXXMemberOperatorCall(const CXXMemberOperatorCall &Other)
: CXXInstanceCall(Other) {}
- virtual void cloneTo(void *Dest) const {
+ void cloneTo(void *Dest) const override {
new (Dest) CXXMemberOperatorCall(*this);
}
@@ -629,16 +616,16 @@ public:
return cast<CXXOperatorCallExpr>(CXXInstanceCall::getOriginExpr());
}
- virtual unsigned getNumArgs() const {
+ unsigned getNumArgs() const override {
return getOriginExpr()->getNumArgs() - 1;
}
- virtual const Expr *getArgExpr(unsigned Index) const {
+ const Expr *getArgExpr(unsigned Index) const override {
return getOriginExpr()->getArg(Index + 1);
}
- virtual const Expr *getCXXThisExpr() const;
+ const Expr *getCXXThisExpr() const override;
- virtual Kind getKind() const { return CE_CXXMemberOperator; }
+ Kind getKind() const override { return CE_CXXMemberOperator; }
static bool classof(const CallEvent *CA) {
return CA->getKind() == CE_CXXMemberOperator;
@@ -671,23 +658,23 @@ protected:
}
CXXDestructorCall(const CXXDestructorCall &Other) : CXXInstanceCall(Other) {}
- virtual void cloneTo(void *Dest) const { new (Dest) CXXDestructorCall(*this); }
+ void cloneTo(void *Dest) const override {new (Dest) CXXDestructorCall(*this);}
public:
- virtual SourceRange getSourceRange() const { return Location; }
- virtual unsigned getNumArgs() const { return 0; }
+ SourceRange getSourceRange() const override { return Location; }
+ unsigned getNumArgs() const override { return 0; }
- virtual RuntimeDefinition getRuntimeDefinition() const;
+ RuntimeDefinition getRuntimeDefinition() const override;
/// \brief Returns the value of the implicit 'this' object.
- virtual SVal getCXXThisVal() const;
+ SVal getCXXThisVal() const override;
/// Returns true if this is a call to a base class destructor.
bool isBaseDestructor() const {
return DtorDataTy::getFromOpaqueValue(Data).getInt();
}
- virtual Kind getKind() const { return CE_CXXDestructor; }
+ Kind getKind() const override { return CE_CXXDestructor; }
static bool classof(const CallEvent *CA) {
return CA->getKind() == CE_CXXDestructor;
@@ -715,32 +702,32 @@ protected:
}
CXXConstructorCall(const CXXConstructorCall &Other) : AnyFunctionCall(Other){}
- virtual void cloneTo(void *Dest) const { new (Dest) CXXConstructorCall(*this); }
+ void cloneTo(void *Dest) const override { new (Dest) CXXConstructorCall(*this); }
- virtual void getExtraInvalidatedValues(ValueList &Values) const;
+ void getExtraInvalidatedValues(ValueList &Values) const override;
public:
virtual const CXXConstructExpr *getOriginExpr() const {
return cast<CXXConstructExpr>(AnyFunctionCall::getOriginExpr());
}
- virtual const CXXConstructorDecl *getDecl() const {
+ const CXXConstructorDecl *getDecl() const override {
return getOriginExpr()->getConstructor();
}
- virtual unsigned getNumArgs() const { return getOriginExpr()->getNumArgs(); }
+ unsigned getNumArgs() const override { return getOriginExpr()->getNumArgs(); }
- virtual const Expr *getArgExpr(unsigned Index) const {
+ const Expr *getArgExpr(unsigned Index) const override {
return getOriginExpr()->getArg(Index);
}
/// \brief Returns the value of the implicit 'this' object.
SVal getCXXThisVal() const;
- virtual void getInitialStackFrameContents(const StackFrameContext *CalleeCtx,
- BindingsTy &Bindings) const;
+ void getInitialStackFrameContents(const StackFrameContext *CalleeCtx,
+ BindingsTy &Bindings) const override;
- virtual Kind getKind() const { return CE_CXXConstructor; }
+ Kind getKind() const override { return CE_CXXConstructor; }
static bool classof(const CallEvent *CA) {
return CA->getKind() == CE_CXXConstructor;
@@ -759,29 +746,29 @@ protected:
: AnyFunctionCall(E, St, LCtx) {}
CXXAllocatorCall(const CXXAllocatorCall &Other) : AnyFunctionCall(Other) {}
- virtual void cloneTo(void *Dest) const { new (Dest) CXXAllocatorCall(*this); }
+ void cloneTo(void *Dest) const override { new (Dest) CXXAllocatorCall(*this); }
public:
virtual const CXXNewExpr *getOriginExpr() const {
return cast<CXXNewExpr>(AnyFunctionCall::getOriginExpr());
}
- virtual const FunctionDecl *getDecl() const {
+ const FunctionDecl *getDecl() const override {
return getOriginExpr()->getOperatorNew();
}
- virtual unsigned getNumArgs() const {
+ unsigned getNumArgs() const override {
return getOriginExpr()->getNumPlacementArgs() + 1;
}
- virtual const Expr *getArgExpr(unsigned Index) const {
+ const Expr *getArgExpr(unsigned Index) const override {
// The first argument of an allocator call is the size of the allocation.
if (Index == 0)
- return 0;
+ return nullptr;
return getOriginExpr()->getPlacementArg(Index - 1);
}
- virtual Kind getKind() const { return CE_CXXAllocator; }
+ Kind getKind() const override { return CE_CXXAllocator; }
static bool classof(const CallEvent *CE) {
return CE->getKind() == CE_CXXAllocator;
@@ -810,13 +797,13 @@ protected:
ObjCMethodCall(const ObjCMessageExpr *Msg, ProgramStateRef St,
const LocationContext *LCtx)
: CallEvent(Msg, St, LCtx) {
- Data = 0;
+ Data = nullptr;
}
ObjCMethodCall(const ObjCMethodCall &Other) : CallEvent(Other) {}
- virtual void cloneTo(void *Dest) const { new (Dest) ObjCMethodCall(*this); }
+ void cloneTo(void *Dest) const override { new (Dest) ObjCMethodCall(*this); }
- virtual void getExtraInvalidatedValues(ValueList &Values) const;
+ void getExtraInvalidatedValues(ValueList &Values) const override;
/// Check if the selector may have multiple definitions (may have overrides).
virtual bool canBeOverridenInSubclass(ObjCInterfaceDecl *IDecl,
@@ -826,13 +813,13 @@ public:
virtual const ObjCMessageExpr *getOriginExpr() const {
return cast<ObjCMessageExpr>(CallEvent::getOriginExpr());
}
- virtual const ObjCMethodDecl *getDecl() const {
+ const ObjCMethodDecl *getDecl() const override {
return getOriginExpr()->getMethodDecl();
}
- virtual unsigned getNumArgs() const {
+ unsigned getNumArgs() const override {
return getOriginExpr()->getNumArgs();
}
- virtual const Expr *getArgExpr(unsigned Index) const {
+ const Expr *getArgExpr(unsigned Index) const override {
return getOriginExpr()->getArg(Index);
}
@@ -846,7 +833,7 @@ public:
return getOriginExpr()->getSelector();
}
- virtual SourceRange getSourceRange() const;
+ SourceRange getSourceRange() const override;
/// \brief Returns the value of the receiver at the time of this call.
SVal getReceiverSVal() const;
@@ -883,15 +870,16 @@ public:
llvm_unreachable("Unknown message kind");
}
- virtual RuntimeDefinition getRuntimeDefinition() const;
+ RuntimeDefinition getRuntimeDefinition() const override;
- virtual void getInitialStackFrameContents(const StackFrameContext *CalleeCtx,
- BindingsTy &Bindings) const;
+ bool argumentsMayEscape() const override;
+
+ void getInitialStackFrameContents(const StackFrameContext *CalleeCtx,
+ BindingsTy &Bindings) const override;
- virtual param_iterator param_begin() const;
- virtual param_iterator param_end() const;
+ ArrayRef<ParmVarDecl*> parameters() const override;
- virtual Kind getKind() const { return CE_ObjCMessage; }
+ Kind getKind() const override { return CE_ObjCMessage; }
static bool classof(const CallEvent *CA) {
return CA->getKind() == CE_ObjCMessage;
@@ -911,6 +899,7 @@ class CallEventManager {
llvm::BumpPtrAllocator &Alloc;
SmallVector<void *, 8> Cache;
+ typedef SimpleFunctionCall CallEventTemplateTy;
void reclaim(const void *Memory) {
Cache.push_back(const_cast<void *>(Memory));
@@ -919,24 +908,30 @@ class CallEventManager {
/// Returns memory that can be initialized as a CallEvent.
void *allocate() {
if (Cache.empty())
- return Alloc.Allocate<FunctionCall>();
+ 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);
}
@@ -944,6 +939,8 @@ class CallEventManager {
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);
}
@@ -989,7 +986,8 @@ public:
template <typename T>
CallEventRef<T> CallEvent::cloneWithState(ProgramStateRef NewState) const {
assert(isa<T>(*this) && "Cloning to unrelated type");
- assert(sizeof(T) == sizeof(CallEvent) && "Subclasses may not add fields");
+ static_assert(sizeof(T) == sizeof(CallEvent),
+ "Subclasses may not add fields");
if (NewState == State)
return cast<T>(this);
@@ -1026,7 +1024,7 @@ namespace llvm {
static SimpleType
getSimplifiedValue(clang::ento::CallEventRef<T> Val) {
- return Val.getPtr();
+ return Val.get();
}
};
}
diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h b/include/clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h
index 0b9762ac42e7..5a33bdf01b3c 100644
--- a/include/clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h
+++ b/include/clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h
@@ -174,8 +174,13 @@ public:
return Pred->getLocationContext()->getAnalysisDeclContext();
}
- /// \brief If the given node corresponds to a PostStore program point, retrieve
- /// the location region as it was uttered in the code.
+ /// \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.
@@ -183,7 +188,7 @@ public:
ProgramPoint L = N->getLocation();
if (Optional<PostStore> PSL = L.getAs<PostStore>())
return reinterpret_cast<const MemRegion*>(PSL->getLocationValue());
- return 0;
+ return nullptr;
}
/// \brief Get the value of arbitrary expressions at this point in the path.
@@ -200,9 +205,9 @@ public:
/// 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 = 0,
- const ProgramPointTag *Tag = 0) {
- return addTransitionImpl(State ? State : getState(), false, 0, Tag);
+ 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.
@@ -214,15 +219,15 @@ public:
/// @param Tag The tag to uniquely identify the creation site.
ExplodedNode *addTransition(ProgramStateRef State,
ExplodedNode *Pred,
- const ProgramPointTag *Tag = 0) {
+ const ProgramPointTag *Tag = nullptr) {
return addTransitionImpl(State, false, Pred, Tag);
}
/// \brief Generate a sink node. Generating a sink stops exploration of the
/// given path.
- ExplodedNode *generateSink(ProgramStateRef State = 0,
- ExplodedNode *Pred = 0,
- const ProgramPointTag *Tag = 0) {
+ ExplodedNode *generateSink(ProgramStateRef State = nullptr,
+ ExplodedNode *Pred = nullptr,
+ const ProgramPointTag *Tag = nullptr) {
return addTransitionImpl(State ? State : getState(), true, Pred, Tag);
}
@@ -244,7 +249,7 @@ public:
if (FunDecl)
return FunDecl->getIdentifier();
else
- return 0;
+ return nullptr;
}
/// \brief Get the name of the called function (path-sensitive).
@@ -280,8 +285,8 @@ public:
private:
ExplodedNode *addTransitionImpl(ProgramStateRef State,
bool MarkAsSink,
- ExplodedNode *P = 0,
- const ProgramPointTag *Tag = 0) {
+ ExplodedNode *P = nullptr,
+ const ProgramPointTag *Tag = nullptr) {
if (!State || (State == Pred->getState() && !Tag && !MarkAsSink))
return Pred;
diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/ConstraintManager.h b/include/clang/StaticAnalyzer/Core/PathSensitive/ConstraintManager.h
index 1e76ea6ed647..51bb89b9e1f9 100644
--- a/include/clang/StaticAnalyzer/Core/PathSensitive/ConstraintManager.h
+++ b/include/clang/StaticAnalyzer/Core/PathSensitive/ConstraintManager.h
@@ -85,7 +85,7 @@ public:
// does not. Is there a good equivalent there?
assert(assume(State, Cond, false) && "System is over constrained.");
#endif
- return ProgramStatePair((ProgramStateRef)NULL, State);
+ return ProgramStatePair((ProgramStateRef)nullptr, State);
}
ProgramStateRef StFalse = assume(State, Cond, false);
@@ -93,7 +93,7 @@ public:
// 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)NULL);
+ return ProgramStatePair(State, (ProgramStateRef)nullptr);
}
return ProgramStatePair(StTrue, StFalse);
@@ -106,7 +106,7 @@ public:
/// value for a symbol, even if it is perfectly constrained.
virtual const llvm::APSInt* getSymVal(ProgramStateRef state,
SymbolRef sym) const {
- return 0;
+ return nullptr;
}
virtual ProgramStateRef removeDeadBindings(ProgramStateRef state,
diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/CoreEngine.h b/include/clang/StaticAnalyzer/Core/PathSensitive/CoreEngine.h
index a2e211edea8b..76ace6d7cc2a 100644
--- a/include/clang/StaticAnalyzer/Core/PathSensitive/CoreEngine.h
+++ b/include/clang/StaticAnalyzer/Core/PathSensitive/CoreEngine.h
@@ -21,7 +21,7 @@
#include "clang/StaticAnalyzer/Core/PathSensitive/ExplodedGraph.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/FunctionSummary.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/WorkList.h"
-#include "llvm/ADT/OwningPtr.h"
+#include <memory>
namespace clang {
@@ -60,12 +60,12 @@ private:
SubEngine& SubEng;
/// G - The simulation graph. Each node is a (location,state) pair.
- OwningPtr<ExplodedGraph> G;
+ std::unique_ptr<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.
- OwningPtr<WorkList> WList;
+ 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
@@ -120,7 +120,7 @@ public:
/// takeGraph - Returns the exploded graph. Ownership of the graph is
/// transferred to the caller.
- ExplodedGraph* takeGraph() { return G.take(); }
+ ExplodedGraph *takeGraph() { return G.release(); }
/// ExecuteWorkList - Run the worklist algorithm for a maximum number of
/// steps. Returns true if there is still simulation state on the worklist.
@@ -312,7 +312,7 @@ public:
/// \class NodeBuilderWithSinks
/// \brief This node builder keeps track of the generated sink nodes.
class NodeBuilderWithSinks: public NodeBuilder {
- virtual void anchor();
+ void anchor() override;
protected:
SmallVector<ExplodedNode*, 2> sinksGenerated;
ProgramPoint &Location;
@@ -324,13 +324,13 @@ public:
ExplodedNode *generateNode(ProgramStateRef State,
ExplodedNode *Pred,
- const ProgramPointTag *Tag = 0) {
+ 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 = 0) {
+ const ProgramPointTag *Tag = nullptr) {
const ProgramPoint &LocalLoc = (Tag ? Location.withTag(Tag) : Location);
ExplodedNode *N = NodeBuilder::generateSink(LocalLoc, State, Pred);
if (N && N->isSink())
@@ -355,14 +355,16 @@ public:
/// 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 = 0)
+ 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 = 0)
+ const NodeBuilderContext &Ctx,
+ NodeBuilder *Enclosing = nullptr)
: NodeBuilder(SrcSet, DstSet, Ctx), EnclosingBldr(Enclosing) {
if (EnclosingBldr)
for (ExplodedNodeSet::iterator I = SrcSet.begin(),
@@ -378,7 +380,7 @@ public:
ExplodedNode *generateNode(const Stmt *S,
ExplodedNode *Pred,
ProgramStateRef St,
- const ProgramPointTag *tag = 0,
+ const ProgramPointTag *tag = nullptr,
ProgramPoint::Kind K = ProgramPoint::PostStmtKind){
const ProgramPoint &L = ProgramPoint::getProgramPoint(S, K,
Pred->getLocationContext(), tag);
@@ -388,7 +390,7 @@ public:
ExplodedNode *generateSink(const Stmt *S,
ExplodedNode *Pred,
ProgramStateRef St,
- const ProgramPointTag *tag = 0,
+ const ProgramPointTag *tag = nullptr,
ProgramPoint::Kind K = ProgramPoint::PostStmtKind){
const ProgramPoint &L = ProgramPoint::getProgramPoint(S, K,
Pred->getLocationContext(), tag);
@@ -399,7 +401,7 @@ public:
/// \brief BranchNodeBuilder is responsible for constructing the nodes
/// corresponding to the two branches of the if statement - true and false.
class BranchNodeBuilder: public NodeBuilder {
- virtual void anchor();
+ void anchor() override;
const CFGBlock *DstT;
const CFGBlock *DstF;
diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/ExplodedGraph.h b/include/clang/StaticAnalyzer/Core/PathSensitive/ExplodedGraph.h
index bf17cd807d65..98092ef00db7 100644
--- a/include/clang/StaticAnalyzer/Core/PathSensitive/ExplodedGraph.h
+++ b/include/clang/StaticAnalyzer/Core/PathSensitive/ExplodedGraph.h
@@ -27,11 +27,11 @@
#include "llvm/ADT/DepthFirstIterator.h"
#include "llvm/ADT/FoldingSet.h"
#include "llvm/ADT/GraphTraits.h"
-#include "llvm/ADT/OwningPtr.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 {
@@ -164,7 +164,7 @@ public:
const ProgramStateRef &state,
bool IsSink) {
ID.Add(Loc);
- ID.AddPointer(state.getPtr());
+ ID.AddPointer(state.get());
ID.AddBoolean(IsSink);
}
@@ -189,7 +189,7 @@ public:
}
ExplodedNode *getFirstPred() {
- return pred_empty() ? NULL : *(pred_begin());
+ return pred_empty() ? nullptr : *(pred_begin());
}
const ExplodedNode *getFirstPred() const {
@@ -197,7 +197,7 @@ public:
}
const ExplodedNode *getFirstSucc() const {
- return succ_empty() ? NULL : *(succ_begin());
+ return succ_empty() ? nullptr : *(succ_begin());
}
// Iterators over successor and predecessor vertices.
@@ -295,7 +295,7 @@ public:
/// the node was freshly created.
ExplodedNode *getNode(const ProgramPoint &L, ProgramStateRef State,
bool IsSink = false,
- bool* IsNew = 0);
+ bool* IsNew = nullptr);
ExplodedGraph* MakeEmptyGraph() const {
return new ExplodedGraph();
@@ -373,8 +373,8 @@ public:
/// nodes in this graph.
/// \returns The trimmed graph
ExplodedGraph *trim(ArrayRef<const NodeTy *> Nodes,
- InterExplodedGraphMap *ForwardMap = 0,
- InterExplodedGraphMap *InverseMap = 0) const;
+ InterExplodedGraphMap *ForwardMap = nullptr,
+ InterExplodedGraphMap *InverseMap = nullptr) const;
/// Enable tracking of recently allocated nodes for potential reclamation
/// when calling reclaimRecentlyAllocatedNodes().
diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h b/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h
index d89dffe63b0a..0fb4a245916f 100644
--- a/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h
+++ b/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h
@@ -43,7 +43,6 @@ namespace ento {
class AnalysisManager;
class CallEvent;
-class SimpleCall;
class CXXConstructorCall;
class ExprEngine : public SubEngine {
@@ -107,7 +106,7 @@ public:
/// Returns true if there is still simulation state on the worklist.
bool ExecuteWorkList(const LocationContext *L, unsigned Steps = 150000) {
- return Engine.ExecuteWorkList(L, Steps, 0);
+ return Engine.ExecuteWorkList(L, Steps, nullptr);
}
/// Execute the work list with an initial state. Nodes that reaches the exit
@@ -123,7 +122,7 @@ public:
/// getContext - Return the ASTContext associated with this analysis.
ASTContext &getContext() const { return AMgr.getASTContext(); }
- virtual AnalysisManager &getAnalysisManager() { return AMgr; }
+ AnalysisManager &getAnalysisManager() override { return AMgr; }
CheckerManager &getCheckerManager() const {
return *AMgr.getCheckerManager();
@@ -155,7 +154,7 @@ public:
/// getInitialState - Return the initial state used for the root vertex
/// in the ExplodedGraph.
- ProgramStateRef getInitialState(const LocationContext *InitLoc);
+ ProgramStateRef getInitialState(const LocationContext *InitLoc) override;
ExplodedGraph& getGraph() { return G; }
const ExplodedGraph& getGraph() const { return G; }
@@ -187,13 +186,13 @@ public:
/// and \p ReferenceStmt must be valid (non-null).
void removeDead(ExplodedNode *Node, ExplodedNodeSet &Out,
const Stmt *ReferenceStmt, const LocationContext *LC,
- const Stmt *DiagnosticStmt = 0,
+ 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);
+ unsigned StmtIdx, NodeBuilderContext *Ctx) override;
void ProcessStmt(const CFGStmt S, ExplodedNode *Pred);
@@ -201,7 +200,9 @@ public:
void ProcessImplicitDtor(const CFGImplicitDtor D, ExplodedNode *Pred);
- void ProcessAutomaticObjDtor(const CFGAutomaticObjDtor D,
+ 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);
@@ -213,10 +214,10 @@ public:
ExplodedNode *Pred, ExplodedNodeSet &Dst);
/// Called by CoreEngine when processing the entrance of a CFGBlock.
- virtual void processCFGBlockEntrance(const BlockEdge &L,
- NodeBuilderWithSinks &nodeBuilder,
- ExplodedNode *Pred);
-
+ 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,
@@ -224,7 +225,7 @@ public:
ExplodedNode *Pred,
ExplodedNodeSet &Dst,
const CFGBlock *DstT,
- const CFGBlock *DstF);
+ const CFGBlock *DstF) override;
/// Called by CoreEngine. Used to processing branching behavior
/// at static initalizers.
@@ -233,20 +234,20 @@ public:
ExplodedNode *Pred,
ExplodedNodeSet &Dst,
const CFGBlock *DstT,
- const CFGBlock *DstF);
+ 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);
+ 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);
+ 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);
+ ExplodedNode *Pred) override;
/// Remove dead bindings/symbols before exiting a function.
void removeDeadOnEndOfFunction(NodeBuilderContext& BC,
@@ -254,22 +255,23 @@ public:
ExplodedNodeSet &Dst);
/// Generate the entry node of the callee.
- void processCallEnter(CallEnter CE, ExplodedNode *Pred);
+ 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);
+ void processCallExit(ExplodedNode *Pred) override;
/// Called by CoreEngine when the analysis worklist has terminated.
- void processEndWorklist(bool hasWorkRemaining);
+ 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);
+ 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);
+ 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.
@@ -278,13 +280,13 @@ public:
const InvalidatedSymbols *invalidated,
ArrayRef<const MemRegion *> ExplicitRegions,
ArrayRef<const MemRegion *> Regions,
- const CallEvent *Call);
+ 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);
+ const char *NL, const char *Sep) override;
- virtual ProgramStateManager& getStateManager() { return StateMgr; }
+ ProgramStateManager& getStateManager() override { return StateMgr; }
StoreManager& getStoreManager() { return StateMgr.getStoreManager(); }
@@ -420,6 +422,10 @@ public:
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);
@@ -471,21 +477,21 @@ protected:
/// 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 = 0);
+ const ProgramPoint *PP = nullptr);
/// Call PointerEscape callback when a value escapes as a result of bind.
ProgramStateRef processPointerEscapedOnBind(ProgramStateRef State,
- SVal Loc, SVal Val);
+ 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);
+ 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
@@ -500,14 +506,14 @@ public:
ExplodedNode *Pred,
ProgramStateRef St,
SVal location,
- const ProgramPointTag *tag = 0,
+ 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 = 0);
+ const ProgramPointTag *tag = nullptr);
/// \brief Create a new state in which the call return value is binded to the
/// call origin expression.
@@ -580,7 +586,7 @@ private:
ProgramStateRef createTemporaryRegionIfNeeded(ProgramStateRef State,
const LocationContext *LC,
const Expr *E,
- const Expr *ResultE = 0);
+ const Expr *ResultE = nullptr);
};
/// Traits for storing the call processing policy inside GDM.
diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h b/include/clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h
index cc790c1b6b39..92b082d5215c 100644
--- a/include/clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h
+++ b/include/clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h
@@ -23,13 +23,10 @@
#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 llvm {
-class BumpPtrAllocator;
-}
-
namespace clang {
class LocationContext;
@@ -57,7 +54,7 @@ public:
// Visual Studio will only create enumerations of size int, not long long.
static const int64_t Symbolic = INT64_MAX;
- RegionOffset() : R(0) {}
+ RegionOffset() : R(nullptr) {}
RegionOffset(const MemRegion *r, int64_t off) : R(r), Offset(off) {}
const MemRegion *getRegion() const { return R; }
@@ -204,12 +201,12 @@ protected:
assert(classof(this));
}
- MemRegionManager* getMemRegionManager() const { return Mgr; }
+ MemRegionManager* getMemRegionManager() const override { return Mgr; }
public:
- bool isBoundable() const { return false; }
-
- void Profile(llvm::FoldingSetNodeID &ID) const;
+ bool isBoundable() const override { return false; }
+
+ void Profile(llvm::FoldingSetNodeID &ID) const override;
static bool classof(const MemRegion *R) {
Kind k = R->getKind();
@@ -243,9 +240,9 @@ class StaticGlobalSpaceRegion : public GlobalsSpaceRegion {
: GlobalsSpaceRegion(mgr, StaticGlobalSpaceRegionKind), CR(cr) {}
public:
- void Profile(llvm::FoldingSetNodeID &ID) const;
-
- void dumpToStream(raw_ostream &os) const;
+ void Profile(llvm::FoldingSetNodeID &ID) const override;
+
+ void dumpToStream(raw_ostream &os) const override;
const CodeTextRegion *getCodeRegion() const { return CR; }
@@ -286,7 +283,7 @@ class GlobalSystemSpaceRegion : public NonStaticGlobalSpaceRegion {
public:
- void dumpToStream(raw_ostream &os) const;
+ void dumpToStream(raw_ostream &os) const override;
static bool classof(const MemRegion *R) {
return R->getKind() == GlobalSystemSpaceRegionKind;
@@ -306,7 +303,7 @@ class GlobalImmutableSpaceRegion : public NonStaticGlobalSpaceRegion {
public:
- void dumpToStream(raw_ostream &os) const;
+ void dumpToStream(raw_ostream &os) const override;
static bool classof(const MemRegion *R) {
return R->getKind() == GlobalImmutableSpaceRegionKind;
@@ -324,7 +321,7 @@ class GlobalInternalSpaceRegion : public NonStaticGlobalSpaceRegion {
public:
- void dumpToStream(raw_ostream &os) const;
+ void dumpToStream(raw_ostream &os) const override;
static bool classof(const MemRegion *R) {
return R->getKind() == GlobalInternalSpaceRegionKind;
@@ -339,7 +336,7 @@ class HeapSpaceRegion : public MemSpaceRegion {
: MemSpaceRegion(mgr, HeapSpaceRegionKind) {}
public:
- void dumpToStream(raw_ostream &os) const;
+ void dumpToStream(raw_ostream &os) const override;
static bool classof(const MemRegion *R) {
return R->getKind() == HeapSpaceRegionKind;
@@ -353,7 +350,7 @@ class UnknownSpaceRegion : public MemSpaceRegion {
: MemSpaceRegion(mgr, UnknownSpaceRegionKind) {}
public:
- void dumpToStream(raw_ostream &os) const;
+ void dumpToStream(raw_ostream &os) const override;
static bool classof(const MemRegion *R) {
return R->getKind() == UnknownSpaceRegionKind;
@@ -373,7 +370,7 @@ protected:
public:
const StackFrameContext *getStackFrame() const { return SFC; }
- void Profile(llvm::FoldingSetNodeID &ID) const;
+ void Profile(llvm::FoldingSetNodeID &ID) const override;
static bool classof(const MemRegion *R) {
Kind k = R->getKind();
@@ -389,7 +386,7 @@ class StackLocalsSpaceRegion : public StackSpaceRegion {
: StackSpaceRegion(mgr, StackLocalsSpaceRegionKind, sfc) {}
public:
- void dumpToStream(raw_ostream &os) const;
+ void dumpToStream(raw_ostream &os) const override;
static bool classof(const MemRegion *R) {
return R->getKind() == StackLocalsSpaceRegionKind;
@@ -404,7 +401,7 @@ private:
: StackSpaceRegion(mgr, StackArgumentsSpaceRegionKind, sfc) {}
public:
- void dumpToStream(raw_ostream &os) const;
+ void dumpToStream(raw_ostream &os) const override;
static bool classof(const MemRegion *R) {
return R->getKind() == StackArgumentsSpaceRegionKind;
@@ -430,9 +427,9 @@ public:
return UnknownVal();
}
- MemRegionManager* getMemRegionManager() const;
+ MemRegionManager* getMemRegionManager() const override;
- virtual bool isSubRegionOf(const MemRegion* R) const;
+ bool isSubRegionOf(const MemRegion* R) const override;
static bool classof(const MemRegion* R) {
return R->getKind() > END_MEMSPACES;
@@ -459,16 +456,16 @@ public:
const Expr *getExpr() const { return Ex; }
- bool isBoundable() const { return true; }
+ bool isBoundable() const override { return true; }
- DefinedOrUnknownSVal getExtent(SValBuilder &svalBuilder) const;
+ DefinedOrUnknownSVal getExtent(SValBuilder &svalBuilder) const override;
- void Profile(llvm::FoldingSetNodeID& ID) const;
+ 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;
+ void dumpToStream(raw_ostream &os) const override;
static bool classof(const MemRegion* R) {
return R->getKind() == AllocaRegionKind;
@@ -478,7 +475,7 @@ public:
/// TypedRegion - An abstract class representing regions that are typed.
class TypedRegion : public SubRegion {
public:
- virtual void anchor();
+ void anchor() override;
protected:
TypedRegion(const MemRegion* sReg, Kind k) : SubRegion(sReg, k) {}
@@ -489,7 +486,7 @@ public:
return getLocationType().getDesugaredType(Context);
}
- bool isBoundable() const { return true; }
+ bool isBoundable() const override { return true; }
static bool classof(const MemRegion* R) {
unsigned k = R->getKind();
@@ -500,14 +497,14 @@ public:
/// TypedValueRegion - An abstract class representing regions having a typed value.
class TypedValueRegion : public TypedRegion {
public:
- virtual void anchor();
+ void anchor() override;
protected:
TypedValueRegion(const MemRegion* sReg, Kind k) : TypedRegion(sReg, k) {}
public:
virtual QualType getValueType() const = 0;
- virtual QualType getLocationType() const {
+ QualType getLocationType() const override {
// FIXME: We can possibly optimize this later to cache this value.
QualType T = getValueType();
ASTContext &ctx = getContext();
@@ -521,7 +518,7 @@ public:
return T.getTypePtrOrNull() ? T.getDesugaredType(Context) : T;
}
- DefinedOrUnknownSVal getExtent(SValBuilder &svalBuilder) const;
+ DefinedOrUnknownSVal getExtent(SValBuilder &svalBuilder) const override;
static bool classof(const MemRegion* R) {
unsigned k = R->getKind();
@@ -532,12 +529,12 @@ public:
class CodeTextRegion : public TypedRegion {
public:
- virtual void anchor();
+ void anchor() override;
protected:
CodeTextRegion(const MemRegion *sreg, Kind k) : TypedRegion(sreg, k) {}
public:
- bool isBoundable() const { return false; }
-
+ bool isBoundable() const override { return false; }
+
static bool classof(const MemRegion* R) {
Kind k = R->getKind();
return k >= FunctionTextRegionKind && k <= BlockTextRegionKind;
@@ -552,8 +549,8 @@ public:
: CodeTextRegion(sreg, FunctionTextRegionKind), FD(fd) {
assert(isa<ObjCMethodDecl>(fd) || isa<FunctionDecl>(fd));
}
-
- QualType getLocationType() const {
+
+ QualType getLocationType() const override {
const ASTContext &Ctx = getContext();
if (const FunctionDecl *D = dyn_cast<FunctionDecl>(FD)) {
return Ctx.getPointerType(D->getType());
@@ -570,11 +567,11 @@ public:
const NamedDecl *getDecl() const {
return FD;
}
-
- virtual void dumpToStream(raw_ostream &os) const;
-
- void Profile(llvm::FoldingSetNodeID& ID) const;
-
+
+ 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*);
@@ -602,7 +599,7 @@ class BlockTextRegion : public CodeTextRegion {
: CodeTextRegion(sreg, BlockTextRegionKind), BD(bd), AC(ac), locTy(lTy) {}
public:
- QualType getLocationType() const {
+ QualType getLocationType() const override {
return locTy;
}
@@ -611,11 +608,11 @@ public:
}
AnalysisDeclContext *getAnalysisDeclContext() const { return AC; }
-
- virtual void dumpToStream(raw_ostream &os) const;
-
- void Profile(llvm::FoldingSetNodeID& ID) const;
-
+
+ virtual 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*);
@@ -643,15 +640,15 @@ class BlockDataRegion : public TypedRegion {
unsigned count, const MemRegion *sreg)
: TypedRegion(sreg, BlockDataRegionKind), BC(bc), LC(lc),
BlockCount(count),
- ReferencedVars(0), OriginalVars(0) {}
+ ReferencedVars(nullptr), OriginalVars(nullptr) {}
public:
const BlockTextRegion *getCodeRegion() const { return BC; }
const BlockDecl *getDecl() const { return BC->getDecl(); }
- QualType getLocationType() const { return BC->getLocationType(); }
-
+ QualType getLocationType() const override { return BC->getLocationType(); }
+
class referenced_vars_iterator {
const MemRegion * const *R;
const MemRegion * const *OriginalR;
@@ -668,11 +665,11 @@ public:
}
bool operator==(const referenced_vars_iterator &I) const {
- assert((R == 0) == (I.R == 0));
+ assert((R == nullptr) == (I.R == nullptr));
return I.R == R;
}
bool operator!=(const referenced_vars_iterator &I) const {
- assert((R == 0) == (I.R == 0));
+ assert((R == nullptr) == (I.R == nullptr));
return I.R != R;
}
referenced_vars_iterator &operator++() {
@@ -688,11 +685,11 @@ public:
referenced_vars_iterator referenced_vars_begin() const;
referenced_vars_iterator referenced_vars_end() const;
-
- virtual void dumpToStream(raw_ostream &os) const;
-
- void Profile(llvm::FoldingSetNodeID& ID) 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 *);
@@ -723,17 +720,17 @@ public:
return sym;
}
- bool isBoundable() const { return true; }
+ bool isBoundable() const override { return true; }
- DefinedOrUnknownSVal getExtent(SValBuilder &svalBuilder) const;
+ DefinedOrUnknownSVal getExtent(SValBuilder &svalBuilder) const override;
- void Profile(llvm::FoldingSetNodeID& ID) const;
+ void Profile(llvm::FoldingSetNodeID& ID) const override;
static void ProfileRegion(llvm::FoldingSetNodeID& ID,
SymbolRef sym,
const MemRegion* superRegion);
- void dumpToStream(raw_ostream &os) const;
+ void dumpToStream(raw_ostream &os) const override;
static bool classof(const MemRegion* R) {
return R->getKind() == SymbolicRegionKind;
@@ -757,19 +754,19 @@ public:
const StringLiteral* getStringLiteral() const { return Str; }
- QualType getValueType() const {
+ QualType getValueType() const override {
return Str->getType();
}
- DefinedOrUnknownSVal getExtent(SValBuilder &svalBuilder) const;
+ DefinedOrUnknownSVal getExtent(SValBuilder &svalBuilder) const override;
- bool isBoundable() const { return false; }
+ bool isBoundable() const override { return false; }
- void Profile(llvm::FoldingSetNodeID& ID) const {
+ void Profile(llvm::FoldingSetNodeID& ID) const override {
ProfileRegion(ID, Str, superRegion);
}
- void dumpToStream(raw_ostream &os) const;
+ void dumpToStream(raw_ostream &os) const override;
static bool classof(const MemRegion* R) {
return R->getKind() == StringRegionKind;
@@ -792,19 +789,19 @@ protected:
public:
const ObjCStringLiteral* getObjCStringLiteral() const { return Str; }
-
- QualType getValueType() const {
+
+ QualType getValueType() const override {
return Str->getType();
}
-
- bool isBoundable() const { return false; }
-
- void Profile(llvm::FoldingSetNodeID& ID) const {
+
+ bool isBoundable() const override { return false; }
+
+ void Profile(llvm::FoldingSetNodeID& ID) const override {
ProfileRegion(ID, Str, superRegion);
}
-
- void dumpToStream(raw_ostream &os) const;
-
+
+ void dumpToStream(raw_ostream &os) const override;
+
static bool classof(const MemRegion* R) {
return R->getKind() == ObjCStringRegionKind;
}
@@ -825,15 +822,15 @@ private:
const CompoundLiteralExpr *CL,
const MemRegion* superRegion);
public:
- QualType getValueType() const {
+ QualType getValueType() const override {
return CL->getType();
}
- bool isBoundable() const { return !CL->isFileScope(); }
+ bool isBoundable() const override { return !CL->isFileScope(); }
- void Profile(llvm::FoldingSetNodeID& ID) const;
+ void Profile(llvm::FoldingSetNodeID& ID) const override;
- void dumpToStream(raw_ostream &os) const;
+ void dumpToStream(raw_ostream &os) const override;
const CompoundLiteralExpr *getLiteralExpr() const { return CL; }
@@ -854,7 +851,7 @@ protected:
public:
const Decl *getDecl() const { return D; }
- void Profile(llvm::FoldingSetNodeID& ID) const;
+ void Profile(llvm::FoldingSetNodeID& ID) const override;
static bool classof(const MemRegion* R) {
unsigned k = R->getKind();
@@ -874,27 +871,27 @@ class VarRegion : public DeclRegion {
DeclRegion::ProfileRegion(ID, VD, superRegion, VarRegionKind);
}
- void Profile(llvm::FoldingSetNodeID& ID) const;
+ void Profile(llvm::FoldingSetNodeID& ID) const override;
public:
const VarDecl *getDecl() const { return cast<VarDecl>(D); }
const StackFrameContext *getStackFrame() const;
-
- QualType getValueType() const {
+
+ QualType getValueType() const override {
// FIXME: We can cache this if needed.
return getDecl()->getType();
}
- void dumpToStream(raw_ostream &os) const;
+ void dumpToStream(raw_ostream &os) const override;
static bool classof(const MemRegion* R) {
return R->getKind() == VarRegionKind;
}
- bool canPrintPrettyAsExpr() const;
+ bool canPrintPrettyAsExpr() const override;
- void printPrettyAsExpr(raw_ostream &os) const;
+ void printPrettyAsExpr(raw_ostream &os) const override;
};
/// CXXThisRegion - Represents the region for the implicit 'this' parameter
@@ -910,15 +907,15 @@ class CXXThisRegion : public TypedValueRegion {
const PointerType *PT,
const MemRegion *sReg);
- void Profile(llvm::FoldingSetNodeID &ID) const;
+ void Profile(llvm::FoldingSetNodeID &ID) const override;
-public:
- QualType getValueType() const {
+public:
+ QualType getValueType() const override {
return QualType(ThisPointerTy, 0);
}
- void dumpToStream(raw_ostream &os) const;
-
+ void dumpToStream(raw_ostream &os) const override;
+
static bool classof(const MemRegion* R) {
return R->getKind() == CXXThisRegionKind;
}
@@ -936,12 +933,12 @@ class FieldRegion : public DeclRegion {
public:
const FieldDecl *getDecl() const { return cast<FieldDecl>(D); }
- QualType getValueType() const {
+ QualType getValueType() const override {
// FIXME: We can cache this if needed.
return getDecl()->getType();
}
- DefinedOrUnknownSVal getExtent(SValBuilder &svalBuilder) const;
+ DefinedOrUnknownSVal getExtent(SValBuilder &svalBuilder) const override;
static void ProfileRegion(llvm::FoldingSetNodeID& ID, const FieldDecl *FD,
const MemRegion* superRegion) {
@@ -952,12 +949,12 @@ public:
return R->getKind() == FieldRegionKind;
}
- void dumpToStream(raw_ostream &os) const;
+ void dumpToStream(raw_ostream &os) const override;
- bool canPrintPretty() const;
- void printPretty(raw_ostream &os) const;
- bool canPrintPrettyAsExpr() const;
- void printPrettyAsExpr(raw_ostream &os) const;
+ 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 {
@@ -971,12 +968,12 @@ class ObjCIvarRegion : public DeclRegion {
public:
const ObjCIvarDecl *getDecl() const;
- QualType getValueType() const;
+ QualType getValueType() const override;
- bool canPrintPrettyAsExpr() const;
- void printPrettyAsExpr(raw_ostream &os) const;
+ bool canPrintPrettyAsExpr() const override;
+ void printPrettyAsExpr(raw_ostream &os) const override;
- void dumpToStream(raw_ostream &os) const;
+ void dumpToStream(raw_ostream &os) const override;
static bool classof(const MemRegion* R) {
return R->getKind() == ObjCIvarRegionKind;
@@ -1029,7 +1026,7 @@ public:
NonLoc getIndex() const { return Index; }
- QualType getValueType() const {
+ QualType getValueType() const override {
return ElementType;
}
@@ -1039,9 +1036,9 @@ public:
/// Compute the offset within the array. The array might also be a subobject.
RegionRawOffset getAsArrayOffset() const;
- void dumpToStream(raw_ostream &os) const;
+ void dumpToStream(raw_ostream &os) const override;
- void Profile(llvm::FoldingSetNodeID& ID) const;
+ void Profile(llvm::FoldingSetNodeID& ID) const override;
static bool classof(const MemRegion* R) {
return R->getKind() == ElementRegionKind;
@@ -1063,13 +1060,13 @@ class CXXTempObjectRegion : public TypedValueRegion {
public:
const Expr *getExpr() const { return Ex; }
- QualType getValueType() const {
+ QualType getValueType() const override {
return Ex->getType();
}
- void dumpToStream(raw_ostream &os) const;
+ void dumpToStream(raw_ostream &os) const override;
- void Profile(llvm::FoldingSetNodeID &ID) const;
+ void Profile(llvm::FoldingSetNodeID &ID) const override;
static bool classof(const MemRegion* R) {
return R->getKind() == CXXTempObjectRegionKind;
@@ -1094,19 +1091,19 @@ public:
const CXXRecordDecl *getDecl() const { return Data.getPointer(); }
bool isVirtual() const { return Data.getInt(); }
- QualType getValueType() const;
+ QualType getValueType() const override;
- void dumpToStream(raw_ostream &os) const;
+ void dumpToStream(raw_ostream &os) const override;
- void Profile(llvm::FoldingSetNodeID &ID) const;
+ void Profile(llvm::FoldingSetNodeID &ID) const override;
static bool classof(const MemRegion *region) {
return region->getKind() == CXXBaseObjectRegionKind;
}
- bool canPrintPrettyAsExpr() const;
-
- void printPrettyAsExpr(raw_ostream &os) const;
+ bool canPrintPrettyAsExpr() const override;
+
+ void printPrettyAsExpr(raw_ostream &os) const override;
};
template<typename RegionTy>
@@ -1114,7 +1111,7 @@ const RegionTy* MemRegion::getAs() const {
if (const RegionTy* RT = dyn_cast<RegionTy>(this))
return RT;
- return NULL;
+ return nullptr;
}
//===----------------------------------------------------------------------===//
@@ -1143,9 +1140,10 @@ class MemRegionManager {
MemSpaceRegion *code;
public:
- MemRegionManager(ASTContext &c, llvm::BumpPtrAllocator& a)
- : C(c), A(a), InternalGlobals(0), SystemGlobals(0), ImmutableGlobals(0),
- heap(0), unknown(0), code(0) {}
+ MemRegionManager(ASTContext &c, llvm::BumpPtrAllocator &a)
+ : C(c), A(a), InternalGlobals(nullptr), SystemGlobals(nullptr),
+ ImmutableGlobals(nullptr), heap(nullptr), unknown(nullptr),
+ code(nullptr) {}
~MemRegionManager();
@@ -1167,7 +1165,7 @@ public:
/// global variables.
const GlobalsSpaceRegion *getGlobalsRegion(
MemRegion::Kind K = MemRegion::GlobalInternalSpaceRegionKind,
- const CodeTextRegion *R = 0);
+ const CodeTextRegion *R = nullptr);
/// getHeapRegion - Retrieve the memory region associated with the
/// generic "heap".
diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h b/include/clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h
index 03739ed9284d..4902ef50c7fe 100644
--- a/include/clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h
+++ b/include/clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h
@@ -25,10 +25,10 @@
#include "llvm/ADT/FoldingSet.h"
#include "llvm/ADT/ImmutableMap.h"
#include "llvm/ADT/PointerIntPair.h"
+#include "llvm/Support/Allocator.h"
namespace llvm {
class APSInt;
-class BumpPtrAllocator;
}
namespace clang {
@@ -237,16 +237,16 @@ public:
ProgramStateRef
invalidateRegions(ArrayRef<const MemRegion *> Regions, const Expr *E,
unsigned BlockCount, const LocationContext *LCtx,
- bool CausesPointerEscape, InvalidatedSymbols *IS = 0,
- const CallEvent *Call = 0,
- RegionAndSymbolInvalidationTraits *ITraits = 0) const;
+ 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 = 0,
- const CallEvent *Call = 0,
- RegionAndSymbolInvalidationTraits *ITraits = 0) const;
+ 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.
@@ -441,8 +441,8 @@ private:
SubEngine *Eng; /* Can be null. */
EnvironmentManager EnvMgr;
- OwningPtr<StoreManager> StoreMgr;
- OwningPtr<ConstraintManager> ConstraintMgr;
+ std::unique_ptr<StoreManager> StoreMgr;
+ std::unique_ptr<ConstraintManager> ConstraintMgr;
ProgramState::GenericDataMap::Factory GDMFactory;
@@ -454,10 +454,10 @@ private:
llvm::FoldingSet<ProgramState> StateSet;
/// Object that manages the data for all created SVals.
- OwningPtr<SValBuilder> svalBuilder;
+ std::unique_ptr<SValBuilder> svalBuilder;
/// Manages memory for created CallEvents.
- OwningPtr<CallEventManager> CallEventMgr;
+ std::unique_ptr<CallEventManager> CallEventMgr;
/// A BumpPtrAllocator to allocate states.
llvm::BumpPtrAllocator &Alloc;
@@ -676,10 +676,8 @@ inline SVal ProgramState::getLValue(const FieldDecl *D, SVal Base) const {
inline SVal ProgramState::getLValue(const IndirectFieldDecl *D,
SVal Base) const {
StoreManager &SM = *getStateManager().StoreMgr;
- for (IndirectFieldDecl::chain_iterator I = D->chain_begin(),
- E = D->chain_end();
- I != E; ++I) {
- Base = SM.getLValueField(cast<FieldDecl>(*I), Base);
+ for (const auto *I : D->chain()) {
+ Base = SM.getLValueField(cast<FieldDecl>(I), Base);
}
return Base;
diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/ProgramStateTrait.h b/include/clang/StaticAnalyzer/Core/PathSensitive/ProgramStateTrait.h
index eb52ae47bdf2..823bde798e55 100644
--- a/include/clang/StaticAnalyzer/Core/PathSensitive/ProgramStateTrait.h
+++ b/include/clang/StaticAnalyzer/Core/PathSensitive/ProgramStateTrait.h
@@ -18,10 +18,10 @@
#ifndef LLVM_CLANG_GR_PROGRAMSTATETRAIT_H
#define LLVM_CLANG_GR_PROGRAMSTATETRAIT_H
+#include "llvm/Support/Allocator.h"
#include "llvm/Support/DataTypes.h"
namespace llvm {
- class BumpPtrAllocator;
template <typename K, typename D, typename I> class ImmutableMap;
template <typename K, typename I> class ImmutableSet;
template <typename T> class ImmutableList;
@@ -64,7 +64,8 @@ namespace ento {
typedef const value_type* lookup_type;
static inline data_type MakeData(void *const* p) {
- return p ? data_type((typename data_type::TreeTy*) *p) : data_type(0);
+ return p ? data_type((typename data_type::TreeTy*) *p)
+ : data_type(nullptr);
}
static inline void *MakeVoidPtr(data_type B) {
return B.getRoot();
@@ -112,7 +113,8 @@ namespace ento {
typedef Key key_type;
static inline data_type MakeData(void *const* p) {
- return p ? data_type((typename data_type::TreeTy*) *p) : data_type(0);
+ return p ? data_type((typename data_type::TreeTy*) *p)
+ : data_type(nullptr);
}
static inline void *MakeVoidPtr(data_type B) {
@@ -163,7 +165,7 @@ namespace ento {
static inline data_type MakeData(void *const* p) {
return p ? data_type((const llvm::ImmutableListImpl<T>*) *p)
- : data_type(0);
+ : data_type(nullptr);
}
static inline void *MakeVoidPtr(data_type D) {
diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/SValBuilder.h b/include/clang/StaticAnalyzer/Core/PathSensitive/SValBuilder.h
index c5d0a92cabdd..29fb413d1ce7 100644
--- a/include/clang/StaticAnalyzer/Core/PathSensitive/SValBuilder.h
+++ b/include/clang/StaticAnalyzer/Core/PathSensitive/SValBuilder.h
@@ -88,7 +88,7 @@ public:
virtual SVal evalComplement(NonLoc val) = 0;
- /// Create a new value which represents a binary expression with two non
+ /// 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;
@@ -99,7 +99,7 @@ public:
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
+ /// 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;
@@ -146,14 +146,14 @@ public:
const LocationContext *LCtx,
QualType type,
unsigned visitCount,
- const void *symbolTag = 0) {
+ 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 = 0) {
+ const void *symbolTag = nullptr) {
return SymMgr.conjureSymbol(expr, LCtx, visitCount, symbolTag);
}
diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/SVals.h b/include/clang/StaticAnalyzer/Core/PathSensitive/SVals.h
index 5a426ef00197..d50c3be4bf5d 100644
--- a/include/clang/StaticAnalyzer/Core/PathSensitive/SVals.h
+++ b/include/clang/StaticAnalyzer/Core/PathSensitive/SVals.h
@@ -63,11 +63,11 @@ protected:
explicit SVal(const void *d, bool isLoc, unsigned ValKind)
: Data(d), Kind((isLoc ? LocKind : NonLocKind) | (ValKind << BaseBits)) {}
- explicit SVal(BaseKind k, const void *D = NULL)
+ explicit SVal(BaseKind k, const void *D = nullptr)
: Data(D), Kind(k) {}
public:
- explicit SVal() : Data(0), Kind(0) {}
+ explicit SVal() : Data(nullptr), Kind(0) {}
/// \brief Convert to the specified SVal type, asserting that this SVal is of
/// the desired type.
@@ -211,7 +211,7 @@ protected:
explicit DefinedOrUnknownSVal(const void *d, bool isLoc, unsigned ValKind)
: SVal(d, isLoc, ValKind) {}
- explicit DefinedOrUnknownSVal(BaseKind k, void *D = NULL)
+ explicit DefinedOrUnknownSVal(BaseKind k, void *D = nullptr)
: SVal(k, D) {}
private:
diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/Store.h b/include/clang/StaticAnalyzer/Core/PathSensitive/Store.h
index 530dae59892a..84c31661212f 100644
--- a/include/clang/StaticAnalyzer/Core/PathSensitive/Store.h
+++ b/include/clang/StaticAnalyzer/Core/PathSensitive/Store.h
@@ -220,10 +220,11 @@ public:
bool First;
public:
- FindUniqueBinding(SymbolRef sym) : Sym(sym), Binding(0), First(true) {}
+ FindUniqueBinding(SymbolRef sym)
+ : Sym(sym), Binding(nullptr), First(true) {}
bool HandleBinding(StoreManager& SMgr, Store store, const MemRegion* R,
- SVal val);
+ SVal val) override;
LLVM_EXPLICIT operator bool() { return First && Binding; }
const MemRegion *getRegion() { return Binding; }
};
diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/SubEngine.h b/include/clang/StaticAnalyzer/Core/PathSensitive/SubEngine.h
index f653c70a30f3..3482e8d27dbb 100644
--- a/include/clang/StaticAnalyzer/Core/PathSensitive/SubEngine.h
+++ b/include/clang/StaticAnalyzer/Core/PathSensitive/SubEngine.h
@@ -122,7 +122,7 @@ public:
inline ProgramStateRef
processRegionChange(ProgramStateRef state,
const MemRegion* MR) {
- return processRegionChanges(state, 0, MR, MR, 0);
+ return processRegionChanges(state, nullptr, MR, MR, nullptr);
}
virtual ProgramStateRef
diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.h b/include/clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.h
index 914b2bea2d16..2b5cc18c9a29 100644
--- a/include/clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.h
+++ b/include/clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.h
@@ -23,12 +23,9 @@
#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 llvm {
-class BumpPtrAllocator;
-}
-
namespace clang {
class ASTContext;
class StackFrameContext;
@@ -105,7 +102,7 @@ typedef unsigned SymbolID;
/// \brief A symbol representing data which can be stored in a memory location
/// (region).
class SymbolData : public SymExpr {
- virtual void anchor();
+ void anchor() override;
const SymbolID Sym;
protected:
@@ -138,13 +135,13 @@ public:
profile.AddPointer(R);
}
- virtual void Profile(llvm::FoldingSetNodeID& profile) {
+ void Profile(llvm::FoldingSetNodeID& profile) override {
Profile(profile, R);
}
- virtual void dumpToStream(raw_ostream &os) const;
+ void dumpToStream(raw_ostream &os) const override;
- QualType getType() const;
+ QualType getType() const override;
// Implement isa<T> support.
static inline bool classof(const SymExpr *SE) {
@@ -173,9 +170,9 @@ public:
unsigned getCount() const { return Count; }
const void *getTag() const { return SymbolTag; }
- QualType getType() const;
+ QualType getType() const override;
- virtual void dumpToStream(raw_ostream &os) const;
+ void dumpToStream(raw_ostream &os) const override;
static void Profile(llvm::FoldingSetNodeID& profile, const Stmt *S,
QualType T, unsigned Count, const LocationContext *LCtx,
@@ -188,7 +185,7 @@ public:
profile.AddPointer(SymbolTag);
}
- virtual void Profile(llvm::FoldingSetNodeID& profile) {
+ void Profile(llvm::FoldingSetNodeID& profile) override {
Profile(profile, S, T, Count, LCtx, SymbolTag);
}
@@ -211,9 +208,9 @@ public:
SymbolRef getParentSymbol() const { return parentSymbol; }
const TypedValueRegion *getRegion() const { return R; }
- QualType getType() const;
+ QualType getType() const override;
- virtual void dumpToStream(raw_ostream &os) const;
+ void dumpToStream(raw_ostream &os) const override;
static void Profile(llvm::FoldingSetNodeID& profile, SymbolRef parent,
const TypedValueRegion *r) {
@@ -222,7 +219,7 @@ public:
profile.AddPointer(parent);
}
- virtual void Profile(llvm::FoldingSetNodeID& profile) {
+ void Profile(llvm::FoldingSetNodeID& profile) override {
Profile(profile, parentSymbol, R);
}
@@ -244,16 +241,16 @@ public:
const SubRegion *getRegion() const { return R; }
- QualType getType() const;
+ QualType getType() const override;
- virtual void dumpToStream(raw_ostream &os) const;
+ void dumpToStream(raw_ostream &os) const override;
static void Profile(llvm::FoldingSetNodeID& profile, const SubRegion *R) {
profile.AddInteger((unsigned) ExtentKind);
profile.AddPointer(R);
}
- virtual void Profile(llvm::FoldingSetNodeID& profile) {
+ void Profile(llvm::FoldingSetNodeID& profile) override {
Profile(profile, R);
}
@@ -283,9 +280,9 @@ public:
unsigned getCount() const { return Count; }
const void *getTag() const { return Tag; }
- QualType getType() const;
+ QualType getType() const override;
- virtual void dumpToStream(raw_ostream &os) const;
+ void dumpToStream(raw_ostream &os) const override;
static void Profile(llvm::FoldingSetNodeID& profile, const MemRegion *R,
const Stmt *S, QualType T, unsigned Count,
@@ -298,7 +295,7 @@ public:
profile.AddPointer(Tag);
}
- virtual void Profile(llvm::FoldingSetNodeID& profile) {
+ void Profile(llvm::FoldingSetNodeID& profile) override {
Profile(profile, R, S, T, Count, Tag);
}
@@ -320,11 +317,11 @@ public:
SymbolCast(const SymExpr *In, QualType From, QualType To) :
SymExpr(CastSymbolKind), Operand(In), FromTy(From), ToTy(To) { }
- QualType getType() const { return ToTy; }
+ QualType getType() const override { return ToTy; }
const SymExpr *getOperand() const { return Operand; }
- virtual void dumpToStream(raw_ostream &os) const;
+ void dumpToStream(raw_ostream &os) const override;
static void Profile(llvm::FoldingSetNodeID& ID,
const SymExpr *In, QualType From, QualType To) {
@@ -334,7 +331,7 @@ public:
ID.Add(To);
}
- void Profile(llvm::FoldingSetNodeID& ID) {
+ void Profile(llvm::FoldingSetNodeID& ID) override {
Profile(ID, Operand, FromTy, ToTy);
}
@@ -356,7 +353,7 @@ protected:
public:
// FIXME: We probably need to make this out-of-line to avoid redundant
// generation of virtual functions.
- QualType getType() const { return T; }
+ QualType getType() const override { return T; }
BinaryOperator::Opcode getOpcode() const { return Op; }
@@ -377,7 +374,7 @@ public:
const llvm::APSInt& rhs, QualType t)
: BinarySymExpr(SymIntKind, op, t), LHS(lhs), RHS(rhs) {}
- virtual void dumpToStream(raw_ostream &os) const;
+ void dumpToStream(raw_ostream &os) const override;
const SymExpr *getLHS() const { return LHS; }
const llvm::APSInt &getRHS() const { return RHS; }
@@ -392,7 +389,7 @@ public:
ID.Add(t);
}
- void Profile(llvm::FoldingSetNodeID& ID) {
+ void Profile(llvm::FoldingSetNodeID& ID) override {
Profile(ID, LHS, getOpcode(), RHS, getType());
}
@@ -412,7 +409,7 @@ public:
const SymExpr *rhs, QualType t)
: BinarySymExpr(IntSymKind, op, t), LHS(lhs), RHS(rhs) {}
- virtual void dumpToStream(raw_ostream &os) const;
+ void dumpToStream(raw_ostream &os) const override;
const SymExpr *getRHS() const { return RHS; }
const llvm::APSInt &getLHS() const { return LHS; }
@@ -427,7 +424,7 @@ public:
ID.Add(t);
}
- void Profile(llvm::FoldingSetNodeID& ID) {
+ void Profile(llvm::FoldingSetNodeID& ID) override {
Profile(ID, LHS, getOpcode(), RHS, getType());
}
@@ -450,7 +447,7 @@ public:
const SymExpr *getLHS() const { return LHS; }
const SymExpr *getRHS() const { return RHS; }
- virtual void dumpToStream(raw_ostream &os) const;
+ void dumpToStream(raw_ostream &os) const override;
static void Profile(llvm::FoldingSetNodeID& ID, const SymExpr *lhs,
BinaryOperator::Opcode op, const SymExpr *rhs, QualType t) {
@@ -461,7 +458,7 @@ public:
ID.Add(t);
}
- void Profile(llvm::FoldingSetNodeID& ID) {
+ void Profile(llvm::FoldingSetNodeID& ID) override {
Profile(ID, LHS, getOpcode(), RHS, getType());
}
@@ -501,12 +498,12 @@ public:
const LocationContext *LCtx,
QualType T,
unsigned VisitCount,
- const void *SymbolTag = 0);
+ const void *SymbolTag = nullptr);
const SymbolConjured* conjureSymbol(const Expr *E,
const LocationContext *LCtx,
unsigned VisitCount,
- const void *SymbolTag = 0) {
+ const void *SymbolTag = nullptr) {
return conjureSymbol(E, LCtx, E->getType(), VisitCount, SymbolTag);
}
@@ -519,9 +516,9 @@ public:
///
/// 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,
+ const SymbolMetadata *getMetadataSymbol(const MemRegion *R, const Stmt *S,
QualType T, unsigned VisitCount,
- const void *SymbolTag = 0);
+ const void *SymbolTag = nullptr);
const SymbolCast* getCastSymbol(const SymExpr *Operand,
QualType From, QualType To);
@@ -590,7 +587,7 @@ public:
SymbolReaper(const StackFrameContext *Ctx, const Stmt *s, SymbolManager& symmgr,
StoreManager &storeMgr)
: LCtx(Ctx), Loc(s), SymMgr(symmgr),
- reapedStore(0, storeMgr) {}
+ reapedStore(nullptr, storeMgr) {}
~SymbolReaper() {}
diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/WorkList.h b/include/clang/StaticAnalyzer/Core/PathSensitive/WorkList.h
index d12a1514898f..3ed145dbd2b6 100644
--- a/include/clang/StaticAnalyzer/Core/PathSensitive/WorkList.h
+++ b/include/clang/StaticAnalyzer/Core/PathSensitive/WorkList.h
@@ -42,7 +42,7 @@ public:
explicit WorkListUnit(ExplodedNode *N, BlockCounter C)
: node(N),
counter(C),
- block(NULL),
+ block(nullptr),
blockIdx(0) {}
/// Returns the node associated with the worklist unit.
diff --git a/include/clang/StaticAnalyzer/Frontend/AnalysisConsumer.h b/include/clang/StaticAnalyzer/Frontend/AnalysisConsumer.h
new file mode 100644
index 000000000000..30e5d3dd9a2b
--- /dev/null
+++ b/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_GR_ANALYSISCONSUMER_H
+#define LLVM_CLANG_GR_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;
+
+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.)
+AnalysisASTConsumer *CreateAnalysisConsumer(const Preprocessor &pp,
+ const std::string &output,
+ AnalyzerOptionsRef opts,
+ ArrayRef<std::string> plugins);
+
+} // end GR namespace
+
+} // end clang namespace
+
+#endif
diff --git a/include/clang/StaticAnalyzer/Frontend/FrontendActions.h b/include/clang/StaticAnalyzer/Frontend/FrontendActions.h
index 838ac925533f..21ecfc234fbe 100644
--- a/include/clang/StaticAnalyzer/Frontend/FrontendActions.h
+++ b/include/clang/StaticAnalyzer/Frontend/FrontendActions.h
@@ -22,8 +22,8 @@ namespace ento {
class AnalysisAction : public ASTFrontendAction {
protected:
- virtual ASTConsumer *CreateASTConsumer(CompilerInstance &CI,
- StringRef InFile);
+ ASTConsumer *CreateASTConsumer(CompilerInstance &CI,
+ StringRef InFile) override;
};
void printCheckerHelp(raw_ostream &OS, ArrayRef<std::string> plugins);
diff --git a/include/clang/Tooling/ArgumentsAdjusters.h b/include/clang/Tooling/ArgumentsAdjusters.h
index 71acef8650fe..765e7d2e051d 100644
--- a/include/clang/Tooling/ArgumentsAdjusters.h
+++ b/include/clang/Tooling/ArgumentsAdjusters.h
@@ -49,13 +49,13 @@ public:
/// This class implements ArgumentsAdjuster interface and converts input
/// command line arguments to the "syntax check only" variant.
class ClangSyntaxOnlyAdjuster : public ArgumentsAdjuster {
- virtual CommandLineArguments Adjust(const CommandLineArguments &Args);
+ CommandLineArguments Adjust(const CommandLineArguments &Args) override;
};
/// \brief An argument adjuster which removes output-related command line
/// arguments.
class ClangStripOutputAdjuster : public ArgumentsAdjuster {
- virtual CommandLineArguments Adjust(const CommandLineArguments &Args);
+ CommandLineArguments Adjust(const CommandLineArguments &Args) override;
};
} // end namespace tooling
diff --git a/include/clang/Tooling/CommonOptionsParser.h b/include/clang/Tooling/CommonOptionsParser.h
index eaffe4363515..815ede80c233 100644
--- a/include/clang/Tooling/CommonOptionsParser.h
+++ b/include/clang/Tooling/CommonOptionsParser.h
@@ -28,6 +28,7 @@
#define LLVM_TOOLS_CLANG_INCLUDE_CLANG_TOOLING_COMMONOPTIONSPARSER_H
#include "clang/Tooling/CompilationDatabase.h"
+#include "llvm/Support/CommandLine.h"
namespace clang {
namespace tooling {
@@ -46,13 +47,14 @@ namespace tooling {
/// 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(...);
+/// static cl::opt<bool> YourOwnOption(...);
/// ...
///
/// int main(int argc, const char **argv) {
-/// CommonOptionsParser OptionsParser(argc, argv);
+/// CommonOptionsParser OptionsParser(argc, argv, MyToolCategory);
/// ClangTool Tool(OptionsParser.getCompilations(),
/// OptionsParser.getSourcePathListi());
/// return Tool.run(newFrontendActionFactory<clang::SyntaxOnlyAction>());
@@ -61,10 +63,16 @@ namespace tooling {
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, const char *Overview = 0);
+ CommonOptionsParser(int &argc, const char **argv,
+ llvm::cl::OptionCategory &Category,
+ const char *Overview = nullptr);
/// Returns a reference to the loaded compilations database.
CompilationDatabase &getCompilations() {
@@ -79,7 +87,7 @@ public:
static const char *const HelpMessage;
private:
- OwningPtr<CompilationDatabase> Compilations;
+ std::unique_ptr<CompilationDatabase> Compilations;
std::vector<std::string> SourcePathList;
};
diff --git a/include/clang/Tooling/CompilationDatabase.h b/include/clang/Tooling/CompilationDatabase.h
index 8cca3296f94d..d1e729a88b27 100644
--- a/include/clang/Tooling/CompilationDatabase.h
+++ b/include/clang/Tooling/CompilationDatabase.h
@@ -30,9 +30,9 @@
#include "clang/Basic/LLVM.h"
#include "llvm/ADT/ArrayRef.h"
-#include "llvm/ADT/OwningPtr.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/Twine.h"
+#include <memory>
#include <string>
#include <vector>
@@ -42,8 +42,8 @@ namespace tooling {
/// \brief Specifies the working directory and command of a compilation.
struct CompileCommand {
CompileCommand() {}
- CompileCommand(Twine Directory, ArrayRef<std::string> CommandLine)
- : Directory(Directory.str()), CommandLine(CommandLine) {}
+ CompileCommand(Twine Directory, std::vector<std::string> CommandLine)
+ : Directory(Directory.str()), CommandLine(std::move(CommandLine)) {}
/// \brief The working directory the command was executed from.
std::string Directory;
@@ -166,7 +166,7 @@ public:
/// The argument list is meant to be compatible with normal llvm command line
/// parsing in main methods.
/// int main(int argc, char **argv) {
- /// OwningPtr<FixedCompilationDatabase> Compilations(
+ /// std::unique_ptr<FixedCompilationDatabase> Compilations(
/// FixedCompilationDatabase::loadFromCommandLine(argc, argv));
/// cl::ParseCommandLineOptions(argc, argv);
/// ...
@@ -190,19 +190,19 @@ public:
/// 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.
- virtual std::vector<CompileCommand> getCompileCommands(
- StringRef FilePath) const;
+ 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.
- virtual std::vector<std::string> getAllFiles() const;
+ 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.
- virtual std::vector<CompileCommand> getAllCompileCommands() const;
+ std::vector<CompileCommand> getAllCompileCommands() const override;
private:
/// This is built up to contain a single entry vector to be returned from
diff --git a/include/clang/Tooling/FileMatchTrie.h b/include/clang/Tooling/FileMatchTrie.h
index e531854cca49..be37baff2ffc 100644
--- a/include/clang/Tooling/FileMatchTrie.h
+++ b/include/clang/Tooling/FileMatchTrie.h
@@ -16,8 +16,8 @@
#define LLVM_CLANG_TOOLING_FILE_MATCH_TRIE_H
#include "clang/Basic/LLVM.h"
-#include "llvm/ADT/OwningPtr.h"
#include "llvm/ADT/StringRef.h"
+#include <memory>
#include <string>
#include <vector>
@@ -79,7 +79,7 @@ public:
raw_ostream &Error) const;
private:
FileMatchTrieNode *Root;
- OwningPtr<PathComparator> Comparator;
+ std::unique_ptr<PathComparator> Comparator;
};
diff --git a/include/clang/Tooling/JSONCompilationDatabase.h b/include/clang/Tooling/JSONCompilationDatabase.h
index e3f149bebc86..1b3335968594 100644
--- a/include/clang/Tooling/JSONCompilationDatabase.h
+++ b/include/clang/Tooling/JSONCompilationDatabase.h
@@ -18,12 +18,12 @@
#include "clang/Basic/LLVM.h"
#include "clang/Tooling/CompilationDatabase.h"
#include "clang/Tooling/FileMatchTrie.h"
-#include "llvm/ADT/OwningPtr.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>
@@ -67,17 +67,17 @@ public:
///
/// FIXME: Currently FilePath must be an absolute path inside the
/// source directory which does not have symlinks resolved.
- virtual std::vector<CompileCommand> getCompileCommands(
- StringRef FilePath) const;
+ 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.
- virtual std::vector<std::string> getAllFiles() const;
+ std::vector<std::string> getAllFiles() const override;
/// \brief Returns all compile commands for all the files in the compilation
/// database.
- virtual std::vector<CompileCommand> getAllCompileCommands() const;
+ std::vector<CompileCommand> getAllCompileCommands() const override;
private:
/// \brief Constructs a JSON compilation database on a memory buffer.
@@ -104,7 +104,7 @@ private:
FileMatchTrie MatchTrie;
- OwningPtr<llvm::MemoryBuffer> Database;
+ std::unique_ptr<llvm::MemoryBuffer> Database;
llvm::SourceMgr SM;
llvm::yaml::Stream YAMLStream;
};
diff --git a/include/clang/Tooling/Refactoring.h b/include/clang/Tooling/Refactoring.h
index 43ec9acdb3bf..cd2fb9f6c563 100644
--- a/include/clang/Tooling/Refactoring.h
+++ b/include/clang/Tooling/Refactoring.h
@@ -83,16 +83,16 @@ public:
/// \brief Creates a Replacement of the range [Start, Start+Length) with
/// ReplacementText.
- Replacement(SourceManager &Sources, SourceLocation Start, unsigned Length,
+ Replacement(const SourceManager &Sources, SourceLocation Start, unsigned Length,
StringRef ReplacementText);
/// \brief Creates a Replacement of the given range with ReplacementText.
- Replacement(SourceManager &Sources, const CharSourceRange &Range,
+ Replacement(const SourceManager &Sources, const CharSourceRange &Range,
StringRef ReplacementText);
/// \brief Creates a Replacement of the node with ReplacementText.
template <typename Node>
- Replacement(SourceManager &Sources, const Node &NodeToReplace,
+ Replacement(const SourceManager &Sources, const Node &NodeToReplace,
StringRef ReplacementText);
/// \brief Returns whether this replacement can be applied to a file.
@@ -115,9 +115,10 @@ public:
std::string toString() const;
private:
- void setFromSourceLocation(SourceManager &Sources, SourceLocation Start,
+ void setFromSourceLocation(const SourceManager &Sources, SourceLocation Start,
unsigned Length, StringRef ReplacementText);
- void setFromSourceRange(SourceManager &Sources, const CharSourceRange &Range,
+ void setFromSourceRange(const SourceManager &Sources,
+ const CharSourceRange &Range,
StringRef ReplacementText);
std::string FilePath;
@@ -230,8 +231,8 @@ private:
};
template <typename Node>
-Replacement::Replacement(SourceManager &Sources, const Node &NodeToReplace,
- StringRef ReplacementText) {
+Replacement::Replacement(const SourceManager &Sources,
+ const Node &NodeToReplace, StringRef ReplacementText) {
const CharSourceRange Range =
CharSourceRange::getTokenRange(NodeToReplace->getSourceRange());
setFromSourceRange(Sources, Range, ReplacementText);
diff --git a/include/clang/Tooling/RefactoringCallbacks.h b/include/clang/Tooling/RefactoringCallbacks.h
index c500f356a4d2..19f277431a3e 100644
--- a/include/clang/Tooling/RefactoringCallbacks.h
+++ b/include/clang/Tooling/RefactoringCallbacks.h
@@ -52,7 +52,7 @@ protected:
class ReplaceStmtWithText : public RefactoringCallback {
public:
ReplaceStmtWithText(StringRef FromId, StringRef ToText);
- virtual void run(const ast_matchers::MatchFinder::MatchResult &Result);
+ void run(const ast_matchers::MatchFinder::MatchResult &Result) override;
private:
std::string FromId;
@@ -64,7 +64,7 @@ private:
class ReplaceStmtWithStmt : public RefactoringCallback {
public:
ReplaceStmtWithStmt(StringRef FromId, StringRef ToId);
- virtual void run(const ast_matchers::MatchFinder::MatchResult &Result);
+ void run(const ast_matchers::MatchFinder::MatchResult &Result) override;
private:
std::string FromId;
@@ -77,7 +77,7 @@ private:
class ReplaceIfStmtWithItsBody : public RefactoringCallback {
public:
ReplaceIfStmtWithItsBody(StringRef Id, bool PickTrueBranch);
- virtual void run(const ast_matchers::MatchFinder::MatchResult &Result);
+ void run(const ast_matchers::MatchFinder::MatchResult &Result) override;
private:
std::string Id;
diff --git a/include/clang/Tooling/ReplacementsYaml.h b/include/clang/Tooling/ReplacementsYaml.h
index 18d3259d7058..ac9f46908ffe 100644
--- a/include/clang/Tooling/ReplacementsYaml.h
+++ b/include/clang/Tooling/ReplacementsYaml.h
@@ -18,26 +18,14 @@
#include "clang/Tooling/Refactoring.h"
#include "llvm/Support/YAMLTraits.h"
-#include <vector>
#include <string>
+#include <vector>
LLVM_YAML_IS_SEQUENCE_VECTOR(clang::tooling::Replacement)
namespace llvm {
namespace yaml {
-/// \brief ScalarTraits to read/write std::string objects.
-template <> struct ScalarTraits<std::string> {
- static void output(const std::string &Val, void *, llvm::raw_ostream &Out) {
- Out << Val;
- }
-
- static StringRef input(StringRef Scalar, void *, std::string &Val) {
- Val = Scalar;
- return StringRef();
- }
-};
-
/// \brief Specialized MappingTraits to describe how a Replacement is
/// (de)serialized.
template <> struct MappingTraits<clang::tooling::Replacement> {
diff --git a/include/clang/Tooling/Tooling.h b/include/clang/Tooling/Tooling.h
index de507a7a8b25..769acd325367 100644
--- a/include/clang/Tooling/Tooling.h
+++ b/include/clang/Tooling/Tooling.h
@@ -39,6 +39,7 @@
#include "clang/Tooling/CompilationDatabase.h"
#include "llvm/ADT/StringMap.h"
#include "llvm/ADT/Twine.h"
+#include <memory>
#include <string>
#include <vector>
@@ -80,7 +81,7 @@ public:
/// \brief Invokes the compiler with a FrontendAction created by create().
bool runInvocation(clang::CompilerInvocation *Invocation, FileManager *Files,
- DiagnosticConsumer *DiagConsumer);
+ DiagnosticConsumer *DiagConsumer) override;
/// \brief Returns a new clang::FrontendAction.
///
@@ -96,7 +97,7 @@ public:
/// FrontendActionFactory *Factory =
/// newFrontendActionFactory<clang::SyntaxOnlyAction>();
template <typename T>
-FrontendActionFactory *newFrontendActionFactory();
+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
@@ -125,11 +126,11 @@ public:
/// struct ProvidesASTConsumers {
/// clang::ASTConsumer *newASTConsumer();
/// } Factory;
-/// FrontendActionFactory *FactoryAdapter =
-/// newFrontendActionFactory(&Factory);
+/// std::unique_ptr<FrontendActionFactory> FactoryAdapter(
+/// newFrontendActionFactory(&Factory));
template <typename FactoryT>
-inline FrontendActionFactory *newFrontendActionFactory(
- FactoryT *ConsumerFactory, SourceFileCallbacks *Callbacks = NULL);
+inline std::unique_ptr<FrontendActionFactory> newFrontendActionFactory(
+ FactoryT *ConsumerFactory, SourceFileCallbacks *Callbacks = nullptr);
/// \brief Runs (and deletes) the tool on 'Code' with the -fsyntax-only flag.
///
@@ -160,8 +161,8 @@ bool runToolOnCodeWithArgs(clang::FrontendAction *ToolAction, const Twine &Code,
/// \param FileName The file name which 'Code' will be mapped as.
///
/// \return The resulting AST or null if an error occurred.
-ASTUnit *buildASTFromCode(const Twine &Code,
- const Twine &FileName = "input.cc");
+std::unique_ptr<ASTUnit> buildASTFromCode(const Twine &Code,
+ const Twine &FileName = "input.cc");
/// \brief Builds an AST for 'Code' with additional flags.
///
@@ -170,9 +171,10 @@ ASTUnit *buildASTFromCode(const Twine &Code,
/// \param FileName The file name which 'Code' will be mapped as.
///
/// \return The resulting AST or null if an error occurred.
-ASTUnit *buildASTFromCodeWithArgs(const Twine &Code,
- const std::vector<std::string> &Args,
- const Twine &FileName = "input.cc");
+std::unique_ptr<ASTUnit>
+buildASTFromCodeWithArgs(const Twine &Code,
+ const std::vector<std::string> &Args,
+ const Twine &FileName = "input.cc");
/// \brief Utility to run a FrontendAction in a single clang invocation.
class ToolInvocation {
@@ -186,7 +188,7 @@ class ToolInvocation {
/// \param FAction The action to be executed. Class takes ownership.
/// \param Files The FileManager used for the execution. Class does not take
/// ownership.
- ToolInvocation(ArrayRef<std::string> CommandLine, FrontendAction *FAction,
+ ToolInvocation(std::vector<std::string> CommandLine, FrontendAction *FAction,
FileManager *Files);
/// \brief Create a tool invocation.
@@ -194,7 +196,7 @@ class ToolInvocation {
/// \param CommandLine The command line arguments to clang.
/// \param Action The action to be executed.
/// \param Files The FileManager used for the execution.
- ToolInvocation(ArrayRef<std::string> CommandLine, ToolAction *Action,
+ ToolInvocation(std::vector<std::string> CommandLine, ToolAction *Action,
FileManager *Files);
~ToolInvocation();
@@ -282,7 +284,7 @@ class ClangTool {
/// \brief Create an AST for each file specified in the command line and
/// append them to ASTs.
- int buildASTs(std::vector<ASTUnit *> &ASTs);
+ int buildASTs(std::vector<std::unique_ptr<ASTUnit>> &ASTs);
/// \brief Returns the file manager used in the tool.
///
@@ -303,17 +305,18 @@ class ClangTool {
};
template <typename T>
-FrontendActionFactory *newFrontendActionFactory() {
+std::unique_ptr<FrontendActionFactory> newFrontendActionFactory() {
class SimpleFrontendActionFactory : public FrontendActionFactory {
public:
- virtual clang::FrontendAction *create() { return new T; }
+ clang::FrontendAction *create() override { return new T; }
};
- return new SimpleFrontendActionFactory;
+ return std::unique_ptr<FrontendActionFactory>(
+ new SimpleFrontendActionFactory);
}
template <typename FactoryT>
-inline FrontendActionFactory *newFrontendActionFactory(
+inline std::unique_ptr<FrontendActionFactory> newFrontendActionFactory(
FactoryT *ConsumerFactory, SourceFileCallbacks *Callbacks) {
class FrontendActionFactoryAdapter : public FrontendActionFactory {
public:
@@ -321,7 +324,7 @@ inline FrontendActionFactory *newFrontendActionFactory(
SourceFileCallbacks *Callbacks)
: ConsumerFactory(ConsumerFactory), Callbacks(Callbacks) {}
- virtual clang::FrontendAction *create() {
+ clang::FrontendAction *create() override {
return new ConsumerFactoryAdaptor(ConsumerFactory, Callbacks);
}
@@ -333,21 +336,21 @@ inline FrontendActionFactory *newFrontendActionFactory(
: ConsumerFactory(ConsumerFactory), Callbacks(Callbacks) {}
clang::ASTConsumer *CreateASTConsumer(clang::CompilerInstance &,
- StringRef) {
+ StringRef) override {
return ConsumerFactory->newASTConsumer();
}
protected:
- virtual bool BeginSourceFileAction(CompilerInstance &CI,
- StringRef Filename) LLVM_OVERRIDE {
+ bool BeginSourceFileAction(CompilerInstance &CI,
+ StringRef Filename) override {
if (!clang::ASTFrontendAction::BeginSourceFileAction(CI, Filename))
return false;
- if (Callbacks != NULL)
+ if (Callbacks)
return Callbacks->handleBeginSource(CI, Filename);
return true;
}
- virtual void EndSourceFileAction() LLVM_OVERRIDE {
- if (Callbacks != NULL)
+ void EndSourceFileAction() override {
+ if (Callbacks)
Callbacks->handleEndSource();
clang::ASTFrontendAction::EndSourceFileAction();
}
@@ -360,7 +363,8 @@ inline FrontendActionFactory *newFrontendActionFactory(
SourceFileCallbacks *Callbacks;
};
- return new FrontendActionFactoryAdapter(ConsumerFactory, Callbacks);
+ return std::unique_ptr<FrontendActionFactory>(
+ new FrontendActionFactoryAdapter(ConsumerFactory, Callbacks));
}
/// \brief Returns the absolute path of \c File, by prepending it with
diff --git a/include/clang/module.modulemap b/include/clang/module.modulemap
new file mode 100644
index 000000000000..03806016cc48
--- /dev/null
+++ b/include/clang/module.modulemap
@@ -0,0 +1,110 @@
+module Clang_Analysis {
+ requires cplusplus
+ umbrella "Analysis"
+
+ // This file is intended for repeated textual inclusion.
+ exclude header "Analysis/Analyses/ThreadSafetyOps.def"
+
+ module * { export * }
+}
+
+module Clang_AST {
+ requires cplusplus
+ umbrella "AST"
+
+ // These files are intended for repeated textual inclusion.
+ exclude header "AST/BuiltinTypes.def"
+ exclude header "AST/TypeLocNodes.def"
+ exclude header "AST/TypeNodes.def"
+
+ module * { export * }
+}
+
+module Clang_ASTMatchers { requires cplusplus umbrella "ASTMatchers" module * { export * } }
+
+module Clang_Basic {
+ requires cplusplus
+ umbrella "Basic"
+
+ // These files are intended for repeated textual inclusion.
+ exclude header "Basic/BuiltinsAArch64.def"
+ exclude header "Basic/BuiltinsARM64.def"
+ exclude header "Basic/BuiltinsARM.def"
+ exclude header "Basic/Builtins.def"
+ exclude header "Basic/BuiltinsHexagon.def"
+ exclude header "Basic/BuiltinsMips.def"
+ exclude header "Basic/BuiltinsNEON.def"
+ exclude header "Basic/BuiltinsNVPTX.def"
+ exclude header "Basic/BuiltinsPPC.def"
+ exclude header "Basic/BuiltinsR600.def"
+ exclude header "Basic/BuiltinsX86.def"
+ exclude header "Basic/BuiltinsXCore.def"
+ exclude header "Basic/DiagnosticOptions.def"
+ exclude header "Basic/LangOptions.def"
+ exclude header "Basic/OpenCLExtensions.def"
+ exclude header "Basic/OpenMPKinds.def"
+ exclude header "Basic/OperatorKinds.def"
+ exclude header "Basic/Sanitizers.def"
+ exclude header "Basic/TokenKinds.def"
+
+ // This file is one big layering violation.
+ exclude header "Basic/AllDiagnostics.h"
+
+ // This file includes a header from Lex.
+ exclude header "Basic/PlistSupport.h"
+
+ // FIXME: This is logically a part of Basic, but has been put in the wrong place.
+ header "StaticAnalyzer/Core/AnalyzerOptions.h"
+
+ module * { export * }
+}
+
+module Clang_CodeGen { requires cplusplus umbrella "CodeGen" module * { export * } }
+module Clang_Config { requires cplusplus umbrella "Config" module * { export * } }
+
+module Clang_Driver {
+ requires cplusplus
+ umbrella "Driver"
+
+ // This file is intended for repeated textual inclusion.
+ exclude 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"
+
+ // These files are intended for repeated textual inclusion.
+ exclude header "Frontend/CodeGenOptions.def"
+ exclude header "Frontend/LangStandards.def"
+
+ module * { export * }
+}
+
+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 {
+ requires cplusplus
+ umbrella "StaticAnalyzer"
+
+ // This file is intended for repeated textual inclusion.
+ exclude header "StaticAnalyzer/Core/Analyses.def"
+
+ // FIXME: This is logically a part of Basic, but has been put in the wrong place.
+ exclude header "StaticAnalyzer/Core/AnalyzerOptions.h"
+
+ module * { export * }
+}
+
+module Clang_Tooling { requires cplusplus umbrella "Tooling" module * { export * } }